From 1a567d39c3ad0c80970f7d173a13bdf6ff5367cb Mon Sep 17 00:00:00 2001 From: David Kleingeld Date: Sat, 18 May 2019 01:58:15 +0200 Subject: [PATCH 001/687] adds infrastructure for setting alarms via web api --- src/controller/mod.rs | 20 ++++--- src/errors.rs | 35 ++++++++++++ src/input/alarms.rs | 128 ++++++++++++++++++++++++++---------------- src/main.rs | 32 ++++++++--- 4 files changed, 151 insertions(+), 64 deletions(-) create mode 100644 src/errors.rs diff --git a/src/controller/mod.rs b/src/controller/mod.rs index c6a7bece..7c15ab26 100644 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -67,15 +67,19 @@ pub fn start(rx: mpsc::Receiver) -> Result<(),()>{ let mut state = ActiveState::Normal(states::Normal::enter(&mut mods, &mut system)); //initial state loop { - //wait for next update or an incoming event - let start_recv = Instant::now(); let time_till_update = saturating_duration_till(system.next_update); - let event = if let Ok(event) = rx.recv_timeout(time_till_update){ - event - } else { - system.next_update = Instant::now()+system.update_period; - Event::Update + dbg!(("waiting!")); + let event = match rx.recv_timeout(time_till_update){ + Ok(event) => event, + Err(error) => match error { + mpsc::RecvTimeoutError::Timeout => { + dbg!(("timeout!")); + system.next_update = Instant::now()+system.update_period; + Event::Update + }, + mpsc::RecvTimeoutError::Disconnected => return (()), + } }; state = match (event, state) { @@ -88,7 +92,7 @@ pub fn start(rx: mpsc::Receiver) -> Result<(),()>{ (Event::Alarm, state) => {dbg!("ALARM ALARM"); state}, (Event::Test, state) => {dbg!("a test happend"); state}, - (Event::Stop, _) => break, + (Event::Stop, _) => return (()), }; } }); diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 00000000..bb2acb0f --- /dev/null +++ b/src/errors.rs @@ -0,0 +1,35 @@ +//https://doc.rust-lang.org/std/convert/trait.From.html +use std::fmt; + +pub enum Error { + IO(std::io::Error), + GPIO(sysfs_gpio::Error), + YamlParsing(serde_yaml::Error), +} + +impl From for Error { + fn from(error: serde_yaml::Error) -> Self { + Error::YamlParsing(error) + } +} +impl From for Error { + fn from(error: std::io::Error) -> Self { + Error::IO(error) + } +} + +impl From for Error { + fn from(error: sysfs_gpio::Error) -> Self { + Error::GPIO(error) + } +} + +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Error::IO(error) => error.fmt(f), + Error::GPIO(error) => error.fmt(f), + Error::YamlParsing(error) => error.fmt(f), + } + } +} \ No newline at end of file diff --git a/src/input/alarms.rs b/src/input/alarms.rs index 7435e4e4..916049f2 100644 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -14,56 +14,53 @@ use crate::errors::Error; //TODO, move alarms to input? then backup waker/trigger/speaker/alarm moves to arduino -struct AlarmList { +#[derive(Debug)] +struct RawList { memory: BTreeSet>, - file: File, + file: File, } -enum WakerMessage { - RemoveAlarm(DateTime), - AddAlarm(DateTime), +#[derive(Debug, Clone)] +struct AlarmList { + rawlist: Arc>, } -#[derive(Debug)] -struct Alarms { - waker_tx: mpsc::Sender, - waker_thread: thread::JoinHandle<()>, +#[derive(Debug, Clone)] +pub struct Alarms { + waker_tx: mpsc::Sender<()>, + alarm_list: AlarmList, } -fn waker(mut alarm_list: AlarmList, event_tx: mpsc::Sender, waker_rx: mpsc::Receiver) { +fn waker(mut alarm_list: AlarmList, event_tx: mpsc::Sender, waker_rx: mpsc::Receiver<()>) { loop { if let Some(current_alarm) = alarm_list.get_next_alarm() { - loop { //we have an alarm time, keep waiting until is should go off, handle instructions in the mean time - let now = Utc::now(); - let timeout = (now - current_alarm).to_std().unwrap(); + let now = Utc::now(); + let timeout = (now - current_alarm).to_std().unwrap(); + + //do we sound the an alarm or should we add or remove one? + match waker_rx.recv_timeout(timeout) { + //do not set off alarm + Ok(_) => (),//should recheck if "current alarm" is still the right one as we removed one + - //do we sound the an alarm or should we add or remove one? - match waker_rx.recv_timeout(timeout) { - Ok(message) => match message {//the alarm should not go off - WakerMessage::RemoveAlarm(at_time) => alarm_list.remove_alarm(&at_time), - WakerMessage::AddAlarm(at_time) => alarm_list.add_alarm(at_time), - }, - Err(error) => match error {//should the alarm go off or should we stop? - mpsc::RecvTimeoutError::Timeout => { - event_tx.send(Event::Alarm); //set - alarm_list.remove_alarm(¤t_alarm); - break; //get next alarm - } - //we should stop, end the thread by returning - mpsc::RecvTimeoutError::Disconnected => return, + Err(error) => match error {//should the alarm go off or should we stop? + mpsc::RecvTimeoutError::Timeout => { + event_tx.send(Event::Alarm); //set + //remove alarm from memory and file + alarm_list.remove_alarm(¤t_alarm); + break; //get next alarm } + //we should stop, end the thread by returning + mpsc::RecvTimeoutError::Disconnected => return, } } } else { - //we have no alarm to wait on, wait for instructions + //no alarm to wait on, wait for instructions loop { + //A message through the mpsc signals an alarm has been added match waker_rx.recv() { - Ok(message) => match message { - WakerMessage::RemoveAlarm(at_time) => alarm_list.remove_alarm(&at_time), - //should not only add the alarm but go back and start waiting on it - WakerMessage::AddAlarm(at_time) => { alarm_list.add_alarm(at_time); break }, - } + Ok(_) => (), //alarms were added or remove, go back and start waiting on it Err(_) => return //cant have timed out thus program should exit } } @@ -74,25 +71,54 @@ fn waker(mut alarm_list: AlarmList, event_tx: mpsc::Sender, waker_rx: mps impl Alarms { - fn setup_alarms(event_tx: mpsc::Sender) -> Result { + pub fn setup(event_tx: mpsc::Sender) -> Result<(Self, thread::JoinHandle<()>), Error> { + dbg!(("hoi")); let mut alarm_list = AlarmList::load()?; - let (waker_tx, waker_rx) = mpsc::channel(); - let waker_thread = thread::spawn(move || { waker(alarm_list, event_tx, waker_rx)}); + let mut alarm_list_for_waker = alarm_list.clone(); + let waker_thread = thread::spawn(move || { waker(alarm_list_for_waker, event_tx, waker_rx)}); - Ok(Self {waker_tx, waker_thread}) + Ok((Self {alarm_list, waker_tx}, waker_thread)) } - fn add_alarm(&mut self, at_time: DateTime){ - self.waker_tx.send(WakerMessage::AddAlarm(at_time)); + pub fn add_alarm(&self, at_time: DateTime) -> Result<(), Error> { + self.alarm_list.remove_alarm(&at_time)?; + self.waker_tx.send(()); + Ok(()) } - fn remove_alarm(&mut self, at_time: DateTime){ - self.waker_tx.send(WakerMessage::RemoveAlarm(at_time)); + pub fn remove_alarm(&self, at_time: DateTime) -> Result<(), Error> { + self.alarm_list.remove_alarm(&at_time)?; + self.waker_tx.send(()); + Ok(()) } } impl AlarmList { + fn load() -> Result { + let list = RawList::load()?; + Ok(Self {rawlist: Arc::new(Mutex::new(list)) }) + } + + fn add_alarm(&self, at_time: DateTime) -> Result<(), Error> { + let mut list = self.rawlist.lock().unwrap(); + list.add_alarm(at_time) + } + fn remove_alarm(&self, at_time: &DateTime) -> Result<(), Error> { + let mut list = self.rawlist.lock().unwrap(); + list.remove_alarm(at_time) + } + + /// calculate time to the earliest alarm, remove it from the list if the current time is later + /// then the alarm + fn get_next_alarm(&mut self) -> Option> { + let mut list = self.rawlist.lock().unwrap(); + list.get_next_alarm() + } +} + +impl RawList { + fn load() -> Result { let path = Path::new("alarms.yaml"); @@ -100,23 +126,27 @@ impl AlarmList { let memory; if path.exists() { file = File::open(path)?; - memory = serde_yaml::from_reader(&mut file)? + memory = serde_yaml::from_reader(&mut file)?; } else { file = File::create(path)?; memory = BTreeSet::new(); + serde_yaml::to_writer(&file, &memory)?; } - Ok(Self {memory, file }) + + Ok(Self {memory, file}) } - fn add_alarm(&mut self, at_time: DateTime) { + fn add_alarm(&mut self, at_time: DateTime) -> Result<(), Error>{ self.memory.insert(at_time); - self.file.set_len(0); //truncate file - serde_yaml::to_writer(&mut self.file, &self.memory); + self.file.set_len(0)?; //truncate file + serde_yaml::to_writer(&mut self.file, &self.memory)?; + Ok(()) } - fn remove_alarm(&mut self, at_time: &DateTime) { + fn remove_alarm(&mut self, at_time: &DateTime) -> Result<(), Error>{ self.memory.remove(at_time); - self.file.set_len(0); //truncate file - serde_yaml::to_writer(&mut self.file, &self.memory); + self.file.set_len(0)?; //truncate file + serde_yaml::to_writer(&mut self.file, &self.memory)?; + Ok(()) } /// calculate time to the earliest alarm, remove it from the list if the current time is later diff --git a/src/main.rs b/src/main.rs index 8e34d4bb..46a52000 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,11 +2,14 @@ extern crate dataserver; extern crate actix_web; #[macro_use] extern crate log; +extern crate chrono; use crate::actix_web::actix::Arbiter; use crate::actix_web::{server,App,http::Method}; use crate::actix_web::middleware::identity::{CookieIdentityPolicy, IdentityService}; +use crate::chrono::Duration; + use std::sync::mpsc; use std::sync::atomic::{AtomicUsize}; use std::thread; @@ -27,8 +30,11 @@ use controller::Event; mod input; use input::web_api; +mod errors; + pub struct ServerState { controller_addr: mpsc::Sender, + alarms: input::alarms::Alarms, dataserver_state: DataServerState, } @@ -44,7 +50,8 @@ pub fn start(signed_cert: &str, private_key: &str, data: Arc>, passw_db: Arc>, sessions: Arc>>, - controller_tx: mpsc::Sender) -> (DataRouterHandle, ServerHandle) { + controller_tx: mpsc::Sender, + alarms: input::alarms::Alarms) -> (DataRouterHandle, ServerHandle) { let tls_config = httpserver::make_tls_config(signed_cert, private_key); let cookie_key = httpserver::make_random_cookie_key(); @@ -71,6 +78,7 @@ pub fn start(signed_cert: &str, private_key: &str, }; let state = ServerState { controller_addr: controller_tx.clone(), + alarms: alarms.clone(), dataserver_state, }; @@ -80,6 +88,7 @@ pub fn start(signed_cert: &str, private_key: &str, .domain("deviousd.duckdns.org") .name("auth-cookie") .path("/") + .max_age(Duration::weeks(1)) .secure(true), )) .middleware(CheckLogin{ @@ -93,6 +102,10 @@ pub fn start(signed_cert: &str, private_key: &str, .resource(r"/commands/lamps/day", |r| r.method(Method::GET).f(web_api::normal)) .resource(r"/commands/lamps/dimmest", |r| r.method(Method::GET).f(web_api::dimmest)) .resource(r"/commands/lamps/dim", |r| r.method(Method::GET).f(web_api::dim)) + + .resource(r"/commands/lightLoop", |r| r.method(Method::GET).f(web_api::lightloop)) + + .resource(r"/commands/set/wakeup_alarm", |r| r.method(Method::POST).with(web_api::set_alarm)) // websocket route // note some browsers need already existing http connection to // this server for the upgrade to wss to work @@ -112,8 +125,8 @@ pub fn start(signed_cert: &str, private_key: &str, //for all other urls we try to resolve to static files in the "web" dir .resource(r"/{tail:.*}", |r| r.f(serve_file)) }) - .bind_rustls("0.0.0.0:8080", tls_config).unwrap() - //.bind("0.0.0.0:8080").unwrap() //without tcp use with debugging (note: https -> http, wss -> ws) + //.bind_rustls("0.0.0.0:8080", tls_config).unwrap() + .bind("0.0.0.0:8080").unwrap() //without tcp use with debugging (note: https -> http, wss -> ws) .shutdown_timeout(5) // shut down 5 seconds after getting the signal to shut down .start(); @@ -147,21 +160,26 @@ fn main() { let sessions = Arc::new(RwLock::new(HashMap::new())); let (controller_tx, controller_rx) = mpsc::channel(); + controller::start(controller_rx).unwrap(); + input::attached_sensors::check_local_sensing_dataset(&dataset_handle).unwrap(); + let (Alarms, waker_thread) = input::alarms::Alarms::setup(controller_tx.clone()).unwrap(); + let (data_router_handle, web_handle) = //starts webserver - start("keys/cert.key", "keys/cert.cert", dataset_handle.clone(), passw_db.clone(), sessions.clone(), controller_tx.clone()); + start("keys/cert.key", "keys/cert.cert", dataset_handle.clone(), passw_db.clone(), sessions.clone(), controller_tx.clone(), Alarms.clone()); - controller::start(controller_rx).unwrap(); + #[cfg(feature = "sensors_connected")] input::attached_sensors::start_monitoring(controller_tx.clone(), data_router_handle, dataset_handle.clone()); - println!("press: t to send test data, n: to add a new user, q to quit, a to add new dataset"); + println!("press: t to send test data, n: to add a new user, q to quit, a to add new dataset, u to add fields to a user"); loop { let mut input = String::new(); stdin().read_line(&mut input).unwrap(); match input.as_str() { - "t\n" => helper::send_test_data(dataset_handle.clone()), + "t\n" => helper::send_test_data_over_http(dataset_handle.clone(), 8080), //"x\n" => httpserver::signal_newdata(data_handle.clone(),0), "n\n" => helper::add_user(& passw_db), "a\n" => helper::add_dataset(&passw_db, &dataset_handle), + "u\n" => helper::add_fields_to_user(&passw_db), "q\n" => break, _ => println!("unhandled"), }; From eb3027457c8482c0f82035514e7590317b2f18bb Mon Sep 17 00:00:00 2001 From: David Kleingeld Date: Sat, 18 May 2019 23:34:01 +0200 Subject: [PATCH 002/687] fixes button numbers and mpsc panic --- Cargo.lock | 1241 ++++++++++++------------- Cargo.toml | 16 +- src/controller/commands.rs | 17 +- src/controller/mod.rs | 15 +- src/controller/states/lightloop.rs | 6 +- src/errors.rs | 17 +- src/input/alarms.rs | 32 +- src/input/attached_sensors/bme280.rs | 1 - src/input/attached_sensors/buttons.rs | 47 +- src/input/attached_sensors/mod.rs | 16 +- src/input/web_api/mod.rs | 61 ++ src/main.rs | 25 +- web/plot.js | 171 ++-- web/set_alarm.html | 97 ++ 14 files changed, 1002 insertions(+), 760 deletions(-) create mode 100644 web/set_alarm.html diff --git a/Cargo.lock b/Cargo.lock index 5f4b5d6c..158bf681 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,51 +1,46 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "HomeAutomation" version = "0.1.0" dependencies = [ "actix 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)", "actix-web-httpauth 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "bme280 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "dataserver 0.1.0 (git+https://github.com/dskleingeld/dataserver?branch=as_lib)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "dataserver 0.1.0 (git+https://github.com/dskleingeld/dataserver)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "linux-embedded-hal 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "philipshue 0.3.2 (git+https://github.com/dskleingeld/philipshue)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "sysfs_gpio 0.5.3 (git+https://github.com/rust-embedded/rust-sysfs-gpio)", - "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "MacTypes-sys" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "acme-client" version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/janderholm/acme-client#18009de3316c0c0bc62db5fb5aee642bcda2c79b" dependencies = [ "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.18 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.41 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.22 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.16 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -55,26 +50,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "actix_derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-proto 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -83,19 +78,19 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "actix 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-rustls 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -107,7 +102,7 @@ dependencies = [ [[package]] name = "actix-web" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "actix 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -116,15 +111,15 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -138,24 +133,24 @@ dependencies = [ "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-rustls 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "v_htmlescape 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "v_htmlescape 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -166,9 +161,9 @@ name = "actix-web-httpauth" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "actix-web 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -176,9 +171,9 @@ name = "actix_derive" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -194,22 +189,30 @@ dependencies = [ "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "aho-corasick" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "antidote" -version = "1.0.0" +name = "approx" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "arc-swap" -version = "0.3.7" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -225,9 +228,9 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -237,15 +240,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -253,8 +256,8 @@ name = "backtrace-sys" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -276,12 +279,12 @@ dependencies = [ [[package]] name = "bincode" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -294,11 +297,6 @@ name = "bitflags" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "bitflags" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bitflags" version = "1.0.4" @@ -309,7 +307,7 @@ name = "bme280" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "embedded-hal 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -317,8 +315,8 @@ name = "brotli-sys" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -327,7 +325,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -342,7 +340,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytes" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -356,13 +354,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cc" -version = "1.0.29" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cgmath" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "chrono" @@ -371,20 +379,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "clap" -version = "2.32.0" +version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -399,15 +407,16 @@ dependencies = [ [[package]] name = "colored" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winconsole 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cookie" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -417,38 +426,37 @@ dependencies = [ ] [[package]] -name = "core-foundation" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "core-foundation" +name = "cookie_store" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "core-foundation-sys" -version = "0.2.3" +name = "core-foundation" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "core-foundation-sys" -version = "0.5.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "crc" @@ -460,25 +468,10 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -492,7 +485,7 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.6.3" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -505,49 +498,57 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-queue" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-utils" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "dataserver" version = "0.1.0" -source = "git+https://github.com/dskleingeld/dataserver?branch=as_lib#1f73c853f9f0698fe1b7b90ac9ab91a7768d0588" +source = "git+https://github.com/dskleingeld/dataserver#8e2e4452f03cc4c758b16f4a0d2e6bbae3681eab" dependencies = [ - "acme-client 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "acme-client 0.5.3 (git+https://github.com/janderholm/acme-client)", "actix 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "actix-net 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)", - "bincode 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)", + "bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "fern 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "fern 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "minimal_timeseries 0.1.1 (git+https://github.com/dskleingeld/minimal_timeseries?branch=multithraeded_file_read)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.16 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "text_io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -558,20 +559,20 @@ dependencies = [ [[package]] name = "dtoa" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "either" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "embedded-hal" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -637,7 +638,7 @@ name = "encoding_rs" version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -654,7 +655,7 @@ name = "error-chain" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -662,15 +663,16 @@ name = "error-chain" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "error-chain" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -678,7 +680,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -687,28 +689,28 @@ name = "failure_derive" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "fern" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "colored 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "flate2" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -752,7 +754,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures" -version = "0.1.25" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -760,7 +762,7 @@ name = "futures-cpupool" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -779,19 +781,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "h2" -version = "0.1.16" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -799,18 +801,18 @@ name = "hostname" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "http" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -820,7 +822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hyper" -version = "0.10.15" +version = "0.10.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -838,46 +840,37 @@ dependencies = [ [[package]] name = "hyper" -version = "0.12.24" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "hyper-native-tls" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "hyper-rustls" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -885,14 +878,14 @@ dependencies = [ [[package]] name = "hyper-tls" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.24 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -902,7 +895,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -926,7 +919,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -936,9 +929,9 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -947,12 +940,12 @@ name = "itertools" version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "itoa" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -969,11 +962,6 @@ name = "language-tags" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "lazy_static" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "lazy_static" version = "1.3.0" @@ -986,27 +974,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.49" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libflate" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "linked-hash-map" -version = "0.4.2" +version = "0.2.54" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "linked-hash-map" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1015,7 +988,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "embedded-hal 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "i2cdev 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "spidev 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "sysfs_gpio 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1043,15 +1016,15 @@ name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "lru-cache" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1090,7 +1063,7 @@ name = "mime" version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1107,11 +1080,11 @@ dependencies = [ [[package]] name = "minimal_timeseries" version = "0.1.1" -source = "git+https://github.com/dskleingeld/minimal_timeseries?branch=multithraeded_file_read#69a69ef9ed8c79beceecd1f2113fc98b035df2ac" +source = "git+https://github.com/dskleingeld/minimal_timeseries?branch=multithraeded_file_read#a0cc62277dbb13feb39a926e5da33b64c1b2342d" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fern 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", + "fern 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "ndarray 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1123,8 +1096,8 @@ name = "miniz-sys" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1140,9 +1113,9 @@ name = "miniz_oxide_c_api" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1156,7 +1129,7 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1170,7 +1143,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1187,38 +1160,24 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "native-tls" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.18 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.22 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.41 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "nb" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1237,9 +1196,9 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1248,8 +1207,8 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1261,10 +1220,10 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1274,9 +1233,9 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1287,7 +1246,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "nom" -version = "4.2.0" +version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1351,6 +1310,14 @@ dependencies = [ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-traits" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-traits" version = "0.2.6" @@ -1361,32 +1328,25 @@ name = "num_cpus" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "openssl" -version = "0.9.24" +name = "numtoa" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.41 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "openssl" -version = "0.10.18" +version = "0.10.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.41 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1396,11 +1356,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.41" +version = "0.9.46" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1427,11 +1388,11 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1480,11 +1441,11 @@ version = "0.3.2" source = "git+https://github.com/dskleingeld/philipshue#7005847cd8dca572d411634d20c02264d6262081" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1494,12 +1455,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.4.27" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "publicsuffix" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quick-error" version = "1.2.2" @@ -1507,10 +1480,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1519,10 +1492,10 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1532,9 +1505,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1543,16 +1516,16 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1595,25 +1568,25 @@ dependencies = [ [[package]] name = "rand_jitter" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_os" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1648,7 +1621,7 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.51" +version = "0.1.54" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1656,7 +1629,7 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1673,12 +1646,12 @@ dependencies = [ [[package]] name = "regex" -version = "1.1.0" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1693,7 +1666,7 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1704,51 +1677,39 @@ name = "remove_dir_all" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "reqwest" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libflate 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "reqwest" -version = "0.9.10" +version = "0.9.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie_store 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.24 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libflate 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1760,20 +1721,25 @@ dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rgb" +version = "0.8.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ring" version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1820,7 +1786,7 @@ dependencies = [ [[package]] name = "ryu" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1842,7 +1808,7 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1861,43 +1827,21 @@ dependencies = [ [[package]] name = "security-framework" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "security-framework" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "security-framework-sys" -version = "0.1.16" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "security-framework-sys" -version = "0.2.3" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1920,49 +1864,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.88" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "serde_derive" -version = "1.0.88" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.38" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_urlencoded" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_yaml" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "yaml-rust 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1972,11 +1919,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "signal-hook" -version = "0.1.8" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "signal-hook-registry 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "signal-hook-registry" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arc-swap 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "arc-swap 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1996,13 +1952,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "socket2" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2011,7 +1967,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2027,16 +1983,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "strsim" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.26" +version = "0.15.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2045,9 +2001,9 @@ name = "synstructure" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2056,10 +2012,10 @@ name = "sysfs_gpio" version = "0.5.3" source = "git+https://github.com/rust-embedded/rust-sysfs-gpio#409bab143fbf4004613009aef204df7fc0c0ae8f" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2070,35 +2026,27 @@ dependencies = [ "nix 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "tempdir" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "tempfile" version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "termion" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2109,7 +2057,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "textwrap" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2128,30 +2076,31 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio" -version = "0.1.15" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2161,64 +2110,65 @@ name = "tokio-codec" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-current-thread" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-fs" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-io" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-reactor" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2226,9 +2176,9 @@ name = "tokio-rustls" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2237,23 +2187,24 @@ name = "tokio-signal" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "signal-hook 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "signal-hook 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-sync" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2261,29 +2212,28 @@ name = "tokio-tcp" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2292,9 +2242,17 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-trace-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2302,13 +2260,13 @@ name = "tokio-udp" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2316,16 +2274,16 @@ name = "tokio-uds" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2333,7 +2291,7 @@ name = "tower-service" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2348,16 +2306,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2371,16 +2329,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2392,16 +2350,16 @@ name = "trust-dns-resolver" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2410,6 +2368,14 @@ name = "try-lock" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "try_from" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "typeable" version = "0.1.2" @@ -2430,7 +2396,7 @@ dependencies = [ [[package]] name = "unicase" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2485,7 +2451,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "uuid" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2493,32 +2459,31 @@ dependencies = [ [[package]] name = "v_escape" -version = "0.3.2" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "v_escape_derive 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "v_escape_derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "v_escape_derive" -version = "0.2.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "v_htmlescape" -version = "0.3.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "v_escape 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "v_escape 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2547,7 +2512,7 @@ version = "2.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2556,7 +2521,7 @@ name = "want" version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2591,7 +2556,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2613,7 +2578,7 @@ name = "winapi-util" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2621,12 +2586,23 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winconsole" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cgmath 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rgb 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winreg" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2634,7 +2610,7 @@ name = "winutil" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2648,66 +2624,65 @@ dependencies = [ [[package]] name = "yaml-rust" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] -"checksum MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eaf9f0d0b1cc33a4d2aee14fb4b2eac03462ef4db29c8ac4057327d8a71ad86f" -"checksum acme-client 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "72202dd6b4bd5d6541d21aac8aae4fea0f3b0205c850fc60e85acd52af9e4395" +"checksum acme-client 0.5.3 (git+https://github.com/janderholm/acme-client)" = "" "checksum actix 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c616db5fa4b0c40702fb75201c2af7f8aa8f3a2e2c1dda3b0655772aa949666" "checksum actix-net 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8bebfbe6629e0131730746718c9e032b58f02c6ce06ed7c982b9fef6c8545acd" -"checksum actix-web 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)" = "e9f33c941e5e69a58a6bfef33853228042ed3799fc4b5a4923a36a85776fb690" +"checksum actix-web 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b0ac60f86c65a50b140139f499f4f7c6e49e4b5d88fbfba08e4e3975991f7bf4" "checksum actix-web-httpauth 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "843c8b2e6b9d02d2511c0b26e5e7b59834ea870d266056e474707ba8c80ff3a7" "checksum actix_derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4300e9431455322ae393d43a2ba1ef96b8080573c0fc23b196219efedfb6ba69" "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" +"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" -"checksum arc-swap 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1025aeae2b664ca0ea726a89d574fe8f4e77dd712d443236ad1de00379450cf6" +"checksum approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08abcc3b4e9339e33a3d0a5ed15d84a687350c05689d825e0f6655eef9e76a94" +"checksum arc-swap 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "bc4662175ead9cd84451d5c35070517777949a2ed84551764129cedb88384841" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" +"checksum backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f106c02a3604afcdc0df5d36cc47b44b55917dbaf3d808f71c163a0ddba64637" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -"checksum bincode 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3efe0b4c8eaeed8600549c29f538a6a11bf422858d0ed435b1d70ec4ab101190" +"checksum bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "959c8e54c1ad412ffeeb95f05a9cade02d2d40a7b3c2f852d3353148f4beff35" "checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" -"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum bme280 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d168c341491c9ba4e2c73d59470c108a5961377c67061dc1796a193fa945b452" "checksum brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" "checksum brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" -"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" +"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" -"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a0c56216487bb80eec9c4516337b2588a4f2a2290d72a1416d930e4dcdb0c90d" +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" +"checksum cgmath 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64a4b57c8f4e3a2e9ac07e0f6abc9c24b6fc9e1b54c3478cfb598f3d0023e51c" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" -"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum colored 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e9a455e156a4271e12fd0246238c380b1e223e3736663c7a18ed8b6362028a9" -"checksum cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1465f8134efa296b4c19db34d909637cb2bf0f7aaf21299e23e18fa29ac557cf" -"checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67" -"checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" -"checksum core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d" -"checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" +"checksum colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cdb90b60f2927f8d76139c72dbde7e10c3a2bc47c8594c9c7a66529f2687c03" +"checksum cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "99be24cfcf40d56ed37fd11c2123be833959bbc5bddecb46e1c2e442e15fa3e0" +"checksum cookie_store 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b0d2f2ecb21dce00e2453268370312978af9b8024020c7a37ae2cc6dbbe64685" +"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" +"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" -"checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192" -"checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" +"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" -"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" +"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" "checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" +"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" -"checksum dataserver 0.1.0 (git+https://github.com/dskleingeld/dataserver?branch=as_lib)" = "" -"checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" -"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" -"checksum embedded-hal 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9880e55238830314d41d88f1ac7a819d495799c3cc3bc392cc172bab26428c33" +"checksum dataserver 0.1.0 (git+https://github.com/dskleingeld/dataserver)" = "" +"checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" +"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" +"checksum embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ee4908a155094da7723c2d60d617b820061e3b4efcc3d9e293d206a5a76c170b" "checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" "checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" "checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" @@ -2718,52 +2693,48 @@ dependencies = [ "checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" -"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" +"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" -"checksum fern 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b48af88aaf938b11baef948a5599e66e709cf92854aa2b87c71f1bcf20f80a01" -"checksum flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2291c165c8e703ee54ef3055ad6188e3d51108e2ded18e9f2476e774fc5ad3d4" +"checksum fern 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "29d26fa0f4d433d1956746e66ec10d6bf4d6c8b93cd39965cceea7f7cc78c7dd" +"checksum flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f87e68aa82b2de08a6e037f1385455759df6e445a8df5e005b4297191dbf18aa" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" +"checksum futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)" = "a2037ec1c6c1c4f79557762eab1f7eae1f64f6cb418ace90fae88f0942b60139" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" -"checksum h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb2b25a33e231484694267af28fec74ac63b5ccf51ee2065a5e313b834d836e" +"checksum h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "85ab6286db06040ddefb71641b50017c06874614001a134b423783e2db2920bd" "checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" -"checksum http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fe67e3678f2827030e89cc4b9e7ecd16d52f132c0b940ab5005f88e821500f6a" +"checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" -"checksum hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "df0caae6b71d266b91b4a83111a61d2b94ed2e2bea024c532b933dcff867e58c" -"checksum hyper 0.12.24 (registry+https://github.com/rust-lang/crates.io-index)" = "fdfa9b401ef6c4229745bb6e9b2529192d07b920eed624cdee2a82348cd550af" -"checksum hyper-native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72332e4a35d3059583623b50e98e491b78f8b96c5521fcb3f428167955aa56e8" +"checksum hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" +"checksum hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)" = "e8e4606fed1c162e3a63d408c07584429f49a4f34c7176cb6cbee60e78f2372c" "checksum hyper-rustls 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "71f7b2e5858ab9e19771dc361159f09ee5031734a6f7471fe0947db0238d92b7" -"checksum hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cd73f14ad370d3b4d4b7dce08f69b81536c82e39fcc89731930fe5788cd661" +"checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum i2cdev 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3dabb8dd1c6c973b20fa6342069a2703a11f062768d613cc57a5db29a3fe325c" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "08f7eadeaf4b52700de180d147c4805f199854600b36faa963d91114827b2ffc" "checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" -"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "413f3dfc802c5dc91dc570b05125b6cda9855edfaa9825c9849807876376e70e" -"checksum libflate 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "54d1ddf9c52870243c5689d7638d888331c1116aa5b398f3ba1acfa7d8758ca1" -"checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" -"checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e" +"checksum libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c6785aa7dd976f5fbf3b71cfd9cd49d7f783c1ff565a858d71031c6c313aa5c6" +"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum linux-embedded-hal 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "795096c0eecb0622afb591c3e1a97b1ba046688a7689957b70b8eee9cac8fb84" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" -"checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21" +"checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum matrixmultiply 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "dcad67dcec2d58ff56f6292582377e6921afdf3bfbd533e26fb8900ae575e002" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" @@ -2778,28 +2749,28 @@ dependencies = [ "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f74dbadc8b43df7864539cedb7bc91345e532fdd913cfdc23ad94f4d2d40fbc0" -"checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2" -"checksum nb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "69f380b5fe9fab8c0d7a6a99cda23e2cc0463bedb2cbc3aada0813b98496ecdc" +"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" +"checksum nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b1411551beb3c11dedfb0a90a0fa256b47d28b9ec2cdff34c25a2fa59e45dbdc" "checksum ndarray 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7cf380a8af901ad627594013a3bbac903ae0a6f94e176e47e46b5bbc1877b928" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nix 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b7fd5681d13fda646462cfbd4e5f2051279a89a544d50eb98c365b507246839f" "checksum nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37e713a259ff641624b6cb20e3b12b2952313ba36b6823c0f16e6cfd9e5de17" "checksum nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a7bb1da2be7da3cbffda73fc681d509ffd9e665af478d2bee1907cee0bc64b2" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b30adc557058ce00c9d0d7cb3c6e0b5bc6f36e2e2eabe74b0ba726d194abd588" +"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" "checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" "checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718" "checksum num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "107b9be86cd2481930688277b675b0114578227f034674726605b8a482d8baf8" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" "checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10" +"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" -"checksum openssl 0.10.18 (registry+https://github.com/rust-lang/crates.io-index)" = "b90119d71b0a3596588da04bf7c2c42f2978cfa1217a94119d8ec9e963c7729c" -"checksum openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a3605c298474a3aa69de92d21139fb5e2a81688d308262359d85cdd0d12a7985" +"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" +"checksum openssl 0.10.22 (registry+https://github.com/rust-lang/crates.io-index)" = "a51f452b82d622fc8dd973d7266e9055ac64af25b957d9ced3989142dc61cb6b" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.41 (registry+https://github.com/rust-lang/crates.io-index)" = "e4c77cdd67d31759b22aa72cfda3c65c12348f9e6c5420946b403c022fd0311a" +"checksum openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)" = "05636e06b4f8762d4b81d24a351f3966f38bd25ccbcfd235606c91fdb82cc60f" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" @@ -2810,9 +2781,10 @@ dependencies = [ "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" "checksum philipshue 0.3.2 (git+https://github.com/dskleingeld/philipshue)" = "" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" -"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5afecba86dcf1e4fd610246f89899d1924fe12e1e89f555eb7c7f710f3c5ad1d" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" "checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" @@ -2821,80 +2793,79 @@ dependencies = [ "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" -"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" +"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rawpointer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebac11a9d2e11f2af219b8b8d833b76b1ea0e054aa0e8d8e9e4cbde353bdf019" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" -"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" +"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" -"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" +"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum reqwest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1d56dbe269dbe19d716b76ec8c3efce8ef84e974f5b7e5527463e8c0507d4e17" -"checksum reqwest 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f205a95638627fc0d21c53901671b06f439dc2830311ff11ecdff34ae2d839a8" +"checksum reqwest 0.9.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddcfd2c13c6af0f9c45a1086be3b9c68af79e4430b42790759e2d34cce2a6c60" "checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" +"checksum rgb 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)" = "4f089652ca87f5a82a62935ec6172a534066c7b97be003cc8f702ee9a7a59c92" "checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a" -"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" +"checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "942b71057b31981152970d57399c25f72e27a6ee0d207a669d8304cabf44705b" "checksum rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b7891791343c75b73ed9a18cadcafd8c8563d11a88ebe2d87f5b8a3182654d9" -"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" +"checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f" "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum sct 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb8f61f9e6eadd062a71c380043d28036304a4706b3c4dd001ff3387ed00745a" -"checksum security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "dfa44ee9c54ce5eecc9de7d5acbad112ee58755239381f687e564004ba4a2332" -"checksum security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfab8dda0e7a327c696d893df9ffa19cadc4bd195797997f5223cf5831beaf05" -"checksum security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5421621e836278a0b139268f36eee0dc7e389b784dc3f79d8f11aabadf41bead" -"checksum security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d6696852716b589dff9e886ff83778bb635150168e83afa8ac6b8a78cb82abc" +"checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" +"checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850" -"checksum serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "beed18e6f5175aef3ba670e57c60ef3b1b74d250d962a26604bff4c80e970dd4" -"checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" -"checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2" -"checksum serde_yaml 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0887a8e097a69559b56aa2526bf7aff7c3048cf627dff781f0b56a6001534593" +"checksum serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "a72e9b96fa45ce22a4bc23da3858dfccfd60acd28a25bcd328a98fdd6bea43fd" +"checksum serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "101b495b109a3e3ca8c4cbe44cf62391527cdfb6ba15821c5ce80bcd5ea23f9f" +"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" +"checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" +"checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" -"checksum signal-hook 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "97a47ae722318beceb0294e6f3d601205a1e6abaa4437d9d33e3a212233e3021" +"checksum signal-hook 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "72ab58f1fda436857e6337dcb6a5aaa34f16c5ddc87b3a8b6ef7a212f90b9c5a" +"checksum signal-hook-registry 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cded4ffa32146722ec54ab1f16320568465aa922aa9ab4708129599740da85d7" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" -"checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" +"checksum socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "4e626972d3593207547f14bf5fc9efa4d0e7283deb73fef1dff313dae9ab8878" "checksum spidev 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ba01d3ef92a37e898fecac76cd3e1b33c999395e2d70787608d9678c4293e04" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" -"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum sysfs_gpio 0.5.3 (git+https://github.com/rust-embedded/rust-sysfs-gpio)" = "" "checksum sysfs_gpio 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d68f2cae3c7d39f54ce8a858cc31ffb01974744ee65e5b4999b6037cd691e3f" -"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" -"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" +"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea" "checksum text_io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9658b61ebd1d2a40c276ba2335890b9eb6550b67458a6fbce2022e58c3350a50" -"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "e0500b88064f08bebddd0c0bed39e19f5c567a5f30975bee52b0c0d3e2eeb38c" +"checksum tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "cec6c34409089be085de9403ba2010b80e36938c9ca992c4f67f407bb13db0b1" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" -"checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" -"checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" -"checksum tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9cbbc8a3698b7ab652340f46633364f9eaa928ddaaee79d8b8f356dd79a09d" -"checksum tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b53aeb9d3f5ccf2ebb29e19788f96987fa1355f8fe45ea193928eaaaf3ae820f" -"checksum tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f" +"checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" +"checksum tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "83ea44c6c0773cc034771693711c35c677b4b5a4b21b9e7071704c54de7d555e" +"checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" +"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" +"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" "checksum tokio-rustls 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04a5c8de3797c207c574495724eb77ded1a150160a2db0936c751bf49003c84e" "checksum tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "dd6dc5276ea05ce379a16de90083ec80836440d5ef8a6a39545a3207373b8296" -"checksum tokio-sync 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c73850a5ad497d73ccfcfc0ffb494a4502d93f35cb475cfeef4fcf2916d26040" +"checksum tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2f843ffdf8d6e1f90bddd48da43f99ab071660cd92b7ec560ef3cdfd7a409a" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c3fd86cb15547d02daa2b21aadaf4e37dee3368df38a526178a5afa3c034d2fb" +"checksum tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72558af20be886ea124595ea0f806dd5703b8958e4705429dd58b3d8231f72f2" "checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" +"checksum tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "350c9edade9830dc185ae48ba45667a445ab59f6167ef6d0254ec9d2430d9dd3" "checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" "checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" "checksum tower-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b32f72af77f1bfe3d3d4da8516a238ebe7039b51dd8637a09841ac7f16d2c987" @@ -2903,10 +2874,11 @@ dependencies = [ "checksum trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "09144f0992b0870fa8d2972cc069cbf1e3c0fda64d1f3d45c4d68d0e0b52ad4e" "checksum trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a9f877f7a1ad821ab350505e1f1b146a4960402991787191d6d8cab2ce2de2c" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" +"checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -"checksum unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d3218ea14b4edcaccfa0df0a64a3792a2c32cc706f1b336e48867f9d3147f90" +"checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" @@ -2914,10 +2886,10 @@ dependencies = [ "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" -"checksum uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0238db0c5b605dd1cf51de0f21766f97fba2645897024461d6a00c036819a768" -"checksum v_escape 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c8b50688edb86f4c092a1a9fe8bda004b0faa3197100897653809e97e09a2814" -"checksum v_escape_derive 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7cd994c63b487fef7aad31e5394ec04b9e24de7b32ea5251c9fb499cd2cbf44c" -"checksum v_htmlescape 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "020cae817dc82693aa523f01087b291b1c7a9ac8cea5c12297963f21769fb27f" +"checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" +"checksum v_escape 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8865501b78eef9193c1b45486acf18ba889e5662eba98854d6fc59d8ecf3542d" +"checksum v_escape_derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "306896ff4b75998501263a1dc000456de442e21d68fe8c8bdf75c66a33a58e23" +"checksum v_htmlescape 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7fbbe0fa88dd36f9c8cf61a218d4b953ba669de4d0785832f33cc72bd081e1be" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" @@ -2928,12 +2900,13 @@ dependencies = [ "checksum webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85d1f408918fd590908a70d36b7ac388db2edc221470333e4d6e5b598e44cabf" "checksum widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum winconsole 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef84b96d10db72dd980056666d7f1e7663ce93d82fa33b63e71c966f4cf5032" "checksum winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a27a759395c1195c4cc5cda607ef6f8f6498f64e78f7900f5de0a127a424704a" "checksum winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum yaml-rust 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "95acf0db5515d07da9965ec0e0ba6cc2d825e2caeb7303b66ca441729801254e" +"checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" diff --git a/Cargo.toml b/Cargo.toml index 6de71b02..196919b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,11 +4,19 @@ version = "0.1.0" authors = ["David Kleingeld "] edition = "2018" +[features] +default = ["sensors_connected"] + +# Enable code that expects sensor hardware to be present. Will stop execution +# if hardware is not present, +# on by default for testing use cargo flag: --no-default-features +sensors_connected = [] + [dependencies] actix-web = { version = "0.7.15", features = ["rust-tls"] } actix-web-httpauth = "0.1.0" actix = "0.7.5" -serde = "1.0" +serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.8" log = "0.4" @@ -20,7 +28,7 @@ futures = { version = "0.1"} #dont forget to run cargo update when these change philipshue = { git = "https://github.com/dskleingeld/philipshue", branch = "master" } -dataserver = { git = "https://github.com/dskleingeld/dataserver", branch = "as_lib" } +dataserver = { git = "https://github.com/dskleingeld/dataserver", branch = "master" } #for local dev purpose we use below targets #dataserver = { path = "../dataserver"} @@ -31,4 +39,6 @@ bme280 = "0.1.1" smallvec = "0.6.6" chrono = { version = "0.4.6", features = ["serde"] } -bytes = "0.4.11" \ No newline at end of file +bytes = "0.4.11" + +crossbeam-channel = "0.3" \ No newline at end of file diff --git a/src/controller/commands.rs b/src/controller/commands.rs index f8aa2111..a0b2dcf7 100644 --- a/src/controller/commands.rs +++ b/src/controller/commands.rs @@ -16,8 +16,12 @@ pub enum Command { LampsEvening, LampsNight, LampsDay, - LampsOff, - LampsOn, + + PauseMpd, + GoToLinux, + GoToWindows, + + Test, //prints a test message ChangeState(TargetState), } @@ -36,8 +40,13 @@ pub fn handle_cmd(cmd: Command, state: ActiveState, mods: &mut Modifications, sy Command::LampsEvening => {sys.lights.set_all_to(254,320).unwrap(); mods.lighting = true}, Command::LampsNight => {sys.lights.set_all_to(220,500).unwrap(); mods.lighting = true}, Command::LampsDay => {sys.lights.set_all_to(254,240).unwrap(); mods.lighting = true}, - Command::LampsOff => {unimplemented!(); mods.lighting = true}, - Command::LampsOn => {unimplemented!(); mods.lighting = true}, + + Command::GoToLinux => println!("should go to linux"), + Command::GoToWindows => println!("should go to windows"), + + Command::PauseMpd => println!("should pause mpd"), + + Command::Test => { warn!("The Test command was just send")}, } state } diff --git a/src/controller/mod.rs b/src/controller/mod.rs index 7c15ab26..bfd49c3c 100644 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -1,4 +1,3 @@ -use std::sync::mpsc; use std::time::{Duration, Instant}; use std::thread; @@ -50,7 +49,7 @@ fn saturating_duration_till(target: std::time::Instant) -> std::time::Duration{ } } -pub fn start(rx: mpsc::Receiver) -> Result<(),()>{ +pub fn start(rx: crossbeam_channel::Receiver) -> Result,()>{ let mut system = System { update_period: Duration::from_secs(5), @@ -60,7 +59,7 @@ pub fn start(rx: mpsc::Receiver) -> Result<(),()>{ //mpd init? }; - thread::spawn(move || { + let handle = thread::spawn(move || { let mut mods = Modifications::default(); // TODO guess best init state from statefile or lamps+mpd+time @@ -69,16 +68,14 @@ pub fn start(rx: mpsc::Receiver) -> Result<(),()>{ loop { //wait for next update or an incoming event let time_till_update = saturating_duration_till(system.next_update); - dbg!(("waiting!")); let event = match rx.recv_timeout(time_till_update){ Ok(event) => event, Err(error) => match error { - mpsc::RecvTimeoutError::Timeout => { - dbg!(("timeout!")); + crossbeam_channel::RecvTimeoutError::Timeout => { system.next_update = Instant::now()+system.update_period; Event::Update }, - mpsc::RecvTimeoutError::Disconnected => return (()), + crossbeam_channel::RecvTimeoutError::Disconnected => return (), } }; @@ -92,10 +89,10 @@ pub fn start(rx: mpsc::Receiver) -> Result<(),()>{ (Event::Alarm, state) => {dbg!("ALARM ALARM"); state}, (Event::Test, state) => {dbg!("a test happend"); state}, - (Event::Stop, _) => return (()), + (Event::Stop, _) => return (), }; } }); - Ok(()) + Ok(handle) } diff --git a/src/controller/states/lightloop.rs b/src/controller/states/lightloop.rs index 51ef0c8f..f588bf9c 100644 --- a/src/controller/states/lightloop.rs +++ b/src/controller/states/lightloop.rs @@ -12,11 +12,11 @@ pub struct LightLoop { impl RoomState for LightLoop { fn update(mut self, mods: &mut Modifications, sys: &mut System) -> ActiveState { dbg!("updating lightloop state"); - if (self.counter == 0){ + if self.counter == 0 { ActiveState::Normal(normal::Normal::enter(mods, sys)) } else { dbg!(self.counter); - sys.lights.set_all_to(self.counter, 200); + sys.lights.set_all_to(self.counter, 200).unwrap(); self.counter -= 1; ActiveState::LightLoop(self) } @@ -24,7 +24,7 @@ impl RoomState for LightLoop { fn enter(mods: &mut Modifications, sys: &mut System) -> Self { dbg!("making everything rdy for the lightloop state"); - sys.lights.set_all_to(0, 200); + sys.lights.set_all_to(0, 200).unwrap(); mods.lighting = false; sys.update_period = Duration::from_millis(500); diff --git a/src/errors.rs b/src/errors.rs index bb2acb0f..e1c92846 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,10 +1,11 @@ -//https://doc.rust-lang.org/std/convert/trait.From.html -use std::fmt; +//use std::fmt; +#[derive(Debug)] pub enum Error { IO(std::io::Error), GPIO(sysfs_gpio::Error), YamlParsing(serde_yaml::Error), + Channel(crossbeam_channel::SendError<()>), } impl From for Error { @@ -24,12 +25,20 @@ impl From for Error { } } -impl fmt::Debug for Error { +impl From> for Error { + fn from(error: crossbeam_channel::SendError<()>) -> Self { + Error::Channel(error) + } +} + + +/*impl fmt::Debug for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + dbg!(("heee")); match self { Error::IO(error) => error.fmt(f), Error::GPIO(error) => error.fmt(f), Error::YamlParsing(error) => error.fmt(f), } } -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/input/alarms.rs b/src/input/alarms.rs index 916049f2..0a773e10 100644 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -1,11 +1,11 @@ use std::collections::BTreeSet; use std::path::Path; -use std::sync::{Arc, Mutex, mpsc}; +use crossbeam_channel; +use std::sync::{Arc, Mutex}; use std::thread; use chrono::{DateTime, Utc}; -use serde::{Serialize, Deserialize}; use std::fs::File; use serde_yaml; @@ -27,11 +27,11 @@ struct AlarmList { #[derive(Debug, Clone)] pub struct Alarms { - waker_tx: mpsc::Sender<()>, + waker_tx: crossbeam_channel::Sender<()>, alarm_list: AlarmList, } -fn waker(mut alarm_list: AlarmList, event_tx: mpsc::Sender, waker_rx: mpsc::Receiver<()>) { +fn waker(mut alarm_list: AlarmList, event_tx: crossbeam_channel::Sender, waker_rx: crossbeam_channel::Receiver<()>) { loop { if let Some(current_alarm) = alarm_list.get_next_alarm() { @@ -45,14 +45,18 @@ fn waker(mut alarm_list: AlarmList, event_tx: mpsc::Sender, waker_rx: mps Err(error) => match error {//should the alarm go off or should we stop? - mpsc::RecvTimeoutError::Timeout => { - event_tx.send(Event::Alarm); //set + crossbeam_channel::RecvTimeoutError::Timeout => { + if let Err(error) = event_tx.send(Event::Alarm){ + error!("could not set off alarm: {:?}", error); + }; //set //remove alarm from memory and file - alarm_list.remove_alarm(¤t_alarm); + if let Err(error) = alarm_list.remove_alarm(¤t_alarm){ + error!("could not remove alarm after its trigger time: {:?}", error); + }; break; //get next alarm } //we should stop, end the thread by returning - mpsc::RecvTimeoutError::Disconnected => return, + crossbeam_channel::RecvTimeoutError::Disconnected => return, } } } else { @@ -71,10 +75,10 @@ fn waker(mut alarm_list: AlarmList, event_tx: mpsc::Sender, waker_rx: mps impl Alarms { - pub fn setup(event_tx: mpsc::Sender) -> Result<(Self, thread::JoinHandle<()>), Error> { + pub fn setup(event_tx: crossbeam_channel::Sender) -> Result<(Self, thread::JoinHandle<()>), Error> { dbg!(("hoi")); let mut alarm_list = AlarmList::load()?; - let (waker_tx, waker_rx) = mpsc::channel(); + let (waker_tx, waker_rx) = crossbeam_channel::unbounded(); let mut alarm_list_for_waker = alarm_list.clone(); let waker_thread = thread::spawn(move || { waker(alarm_list_for_waker, event_tx, waker_rx)}); @@ -83,12 +87,12 @@ impl Alarms { pub fn add_alarm(&self, at_time: DateTime) -> Result<(), Error> { self.alarm_list.remove_alarm(&at_time)?; - self.waker_tx.send(()); + self.waker_tx.send(())?; Ok(()) } pub fn remove_alarm(&self, at_time: DateTime) -> Result<(), Error> { self.alarm_list.remove_alarm(&at_time)?; - self.waker_tx.send(()); + self.waker_tx.send(())?; Ok(()) } } @@ -160,7 +164,9 @@ impl RawList { if alarm > now { return Some(alarm.clone()); } else { - self.remove_alarm(&alarm); + if self.remove_alarm(&alarm).is_err() { + error!("could not remove alarm after it fired!"); + } } } else { return None; diff --git a/src/input/attached_sensors/bme280.rs b/src/input/attached_sensors/bme280.rs index ca3744b8..1a52f18b 100644 --- a/src/input/attached_sensors/bme280.rs +++ b/src/input/attached_sensors/bme280.rs @@ -16,7 +16,6 @@ pub fn init() -> BME280 { pub fn measure_and_record(bme: &mut BME280 ) -> (f32, f32, f32) { // measure temperature, pressure, and humidity - dbg!(""); let measurements = bme.measure().unwrap(); (measurements.humidity, measurements.temperature, measurements.pressure) diff --git a/src/input/attached_sensors/buttons.rs b/src/input/attached_sensors/buttons.rs index 83dd2ad9..06e504a3 100644 --- a/src/input/attached_sensors/buttons.rs +++ b/src/input/attached_sensors/buttons.rs @@ -4,9 +4,9 @@ extern crate tokio; use futures::{Future, lazy, Stream}; use sysfs_gpio::{Direction, Edge, Pin}; -use std::sync::mpsc::Sender; use std::thread; use std::time::{Duration, Instant}; +use crossbeam_channel; use crate::controller::{Command, Event}; @@ -14,7 +14,7 @@ use crate::controller::{Command, Event}; // 23 works perfectly // 24 also works perfectly -fn stream(mut pin_numb_command_pairs: Vec<(u64, Command)>, tx: Sender) -> sysfs_gpio::Result<()> { +fn stream(mut pin_numb_command_pairs: Vec<(u64, Command)>, tx: crossbeam_channel::Sender) -> sysfs_gpio::Result<()> { // NOTE: this currently runs forever and as such if // the app is stopped (Ctrl-C), no cleanup will happen // and the GPIO will be left exported. Not much @@ -24,13 +24,13 @@ fn stream(mut pin_numb_command_pairs: Vec<(u64, Command)>, tx: Sender) -> for (pin_numb, command) in pin_numb_command_pairs.drain(..) { let mut last_press = Instant::now(); let pin = Pin::new(pin_numb); - pin.export().unwrap(); - pin.set_direction(Direction::In).unwrap(); - pin.set_edge(Edge::RisingEdge).unwrap(); + pin.export().expect("could not export pin"); + pin.set_direction(Direction::In).expect("could not set direction for pin"); + pin.set_edge(Edge::RisingEdge).expect("could not set interrupt to rising edge for pin"); let tx = tx.clone(); tokio::spawn(pin.get_value_stream().unwrap() .for_each(move |val| { //TODO refactor - if val == 1 { + if val == 1 { if last_press.elapsed() > Duration::from_millis(50) { last_press = Instant::now(); dbg!(pin_numb); @@ -48,11 +48,38 @@ fn stream(mut pin_numb_command_pairs: Vec<(u64, Command)>, tx: Sender) -> Ok(()) } -pub fn start(tx: Sender) { +pub fn start(tx: crossbeam_channel::Sender) { thread::spawn(move || { - let pin_numb_command_pairs = vec!((22, Command::LampsDim), - (23, Command::LampsDimmest), - (24, Command::LampsToggle)); //BCM pin number + let pin_numb_command_pairs = vec!((16, Command::LampsDim), + (12, Command::LampsDimmest), + (13, Command::LampsToggle), + + (27, Command::LampsToggle), //left 3, left + (22, Command::LampsToggle), //left 3, middle + (18, Command::LampsToggle), //left 3, right + + (23, Command::LampsNight), //right 4, left most + (24, Command::LampsEvening), //right 4, left + (26, Command::LampsDay), //right 4, right + (17, Command::LampsToggle), //right 4, right most + ); //BCM pin number + + /*let pin_numb_command_pairs = vec!((4, Command::Test), //pin 4 is broken and will give sporadic highs if connected + (17, Command::Test), + (27, Command::Test), + + (22, Command::Test), + (5, Command::Test), + (6, Command::Test), + (13, Command::Test), + (26, Command::Test), + (18, Command::Test), + (23, Command::Test), + (24, Command::Test), + (25, Command::Test), + (12, Command::Test), + (16, Command::Test), + ); //BCM pin number */ stream(pin_numb_command_pairs, tx).unwrap(); }); } diff --git a/src/input/attached_sensors/mod.rs b/src/input/attached_sensors/mod.rs index 0e67cdc8..4c23894d 100644 --- a/src/input/attached_sensors/mod.rs +++ b/src/input/attached_sensors/mod.rs @@ -3,11 +3,12 @@ extern crate chrono; extern crate smallvec; extern crate bytes; -use bytes::Bytes; -use dataserver::{httpserver, httpserver::timeseries_interface, httpserver::DataRouterHandle}; +use dataserver::{httpserver::timeseries_interface, httpserver::DataRouterHandle}; use timeseries_interface::specifications::{MetaDataSpec, FieldSpec, FieldLength, FieldResolution}; use self::chrono::{Utc}; +use crossbeam_channel; + mod buttons; mod bme280; @@ -15,12 +16,11 @@ use std::thread; use std::time::{Duration}; use std::sync::{RwLock, Arc}; -use std::sync::mpsc::Sender; -use crate::controller::{Command, Event}; +use crate::controller::{Event}; const LOCAL_SENSING_ID: timeseries_interface::DatasetId = 0; //TODO mechanisme for shutdown -pub fn start_monitoring(tx: Sender, data_router_handle: DataRouterHandle, dataset_handle: Arc>) { +pub fn start_monitoring(tx: crossbeam_channel::Sender, data_router_handle: DataRouterHandle, dataset_handle: Arc>) { buttons::start(tx.clone()); @@ -50,10 +50,6 @@ pub fn start_monitoring(tx: Sender, data_router_handle: DataRouterHandle, //dbg!(fields); let mut line: Vec = vec!(0;64); - dbg!(&humidity); - dbg!(&temperature); - dbg!(&pressure); - fields[0].encode::(humidity, &mut line); fields[1].encode::(temperature, &mut line); fields[2].encode::(pressure, &mut line); @@ -112,7 +108,7 @@ pub fn check_local_sensing_dataset(data: &Arc } else { //TODO write specification that we can use let spec = make_local_sensing_spec(); - data.add_specific_set(spec); + data.add_specific_set(spec).expect("could not create the dataset for the given spec"); info!("created home automation dataset"); Ok(()) } diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index fc88b242..7b975c5d 100644 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -1,10 +1,15 @@ extern crate actix_web_httpauth; + +use actix_web::Form; use actix_web::FromRequest; use actix_web_httpauth::extractors::basic::{BasicAuth, Config}; use actix_web_httpauth::headers::www_authenticate::basic::Basic; use actix_web_httpauth::headers::www_authenticate::{WWWAuthenticate}; use actix_web::http::StatusCode; +use chrono::{DateTime, NaiveDateTime, Utc}; +use serde::Deserialize; + use crate::ServerState; use crate::actix_web::{HttpResponse, HttpRequest}; use crate::controller::{Command, TargetState, Event}; @@ -34,6 +39,11 @@ fn make_auth_error(req: &HttpRequest) -> HttpResponse { .finish() } +fn make_error(req: &HttpRequest, header: StatusCode) -> HttpResponse { + req.build_response(StatusCode::INTERNAL_SERVER_ERROR) + .finish() +} + ///////////////////// lamp commands /////////////////////////////// pub fn toggle(req: &HttpRequest) -> HttpResponse { @@ -99,4 +109,55 @@ pub fn lightloop(req: &HttpRequest) -> HttpResponse { } else { make_auth_error(req) } +} + +//////////////////////// control alarms commands ///////////////////////////////// + +#[derive(Deserialize, Debug)] +pub struct AlarmDataMinFrom { + min_till_alarm: String, +} + +pub fn set_alarm_minutes_from_now((req, params): (HttpRequest, Form)) -> HttpResponse { + if authenticated(&req) { + //Code to parse alarm time + dbg!(¶ms); + + if let Ok(minutes) = params.min_till_alarm.parse(){ + let time = Utc::now() + chrono::Duration::minutes(minutes); + + req.state().alarms.add_alarm(time).unwrap(); + HttpResponse::Ok().finish() + } else { + make_error(&req, StatusCode::INTERNAL_SERVER_ERROR) + } + } else { + make_auth_error(&req) + } +} + +#[derive(Deserialize, Debug)] +pub struct AlarmDataUnixTS { + timestamp: String, +} + +pub fn set_alarm_unix_timestamp((req, params): (HttpRequest, Form)) -> HttpResponse { + if authenticated(&req) { + //Code to parse alarm time + dbg!(¶ms); + + if let Ok(ts) = params.timestamp.parse(){ + let time = DateTime::::from_utc(NaiveDateTime::from_timestamp(ts, 0), Utc); + if time>Utc::now() { + req.state().alarms.add_alarm(time).unwrap(); + HttpResponse::Ok().finish() + } else { + make_error(&req, StatusCode::UNPROCESSABLE_ENTITY) + } + } else { + make_error(&req, StatusCode::INTERNAL_SERVER_ERROR) + } + } else { + make_auth_error(&req) + } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 46a52000..8a89ac38 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,6 @@ use crate::actix_web::middleware::identity::{CookieIdentityPolicy, IdentityServi use crate::chrono::Duration; -use std::sync::mpsc; use std::sync::atomic::{AtomicUsize}; use std::thread; @@ -33,7 +32,7 @@ use input::web_api; mod errors; pub struct ServerState { - controller_addr: mpsc::Sender, + controller_addr: crossbeam_channel::Sender, alarms: input::alarms::Alarms, dataserver_state: DataServerState, } @@ -50,7 +49,7 @@ pub fn start(signed_cert: &str, private_key: &str, data: Arc>, passw_db: Arc>, sessions: Arc>>, - controller_tx: mpsc::Sender, + controller_tx: crossbeam_channel::Sender, alarms: input::alarms::Alarms) -> (DataRouterHandle, ServerHandle) { let tls_config = httpserver::make_tls_config(signed_cert, private_key); @@ -59,7 +58,7 @@ pub fn start(signed_cert: &str, private_key: &str, let free_session_ids = Arc::new(AtomicUsize::new(0)); let free_ws_session_ids = Arc::new(AtomicUsize::new(0)); - let (tx, rx) = mpsc::channel(); + let (tx, rx) = crossbeam_channel::unbounded(); thread::spawn(move || { // Start data server actor in separate thread let sys = actix::System::new("http-server"); @@ -105,7 +104,7 @@ pub fn start(signed_cert: &str, private_key: &str, .resource(r"/commands/lightLoop", |r| r.method(Method::GET).f(web_api::lightloop)) - .resource(r"/commands/set/wakeup_alarm", |r| r.method(Method::POST).with(web_api::set_alarm)) + .resource(r"/commands/set/wakeup_alarm", |r| r.method(Method::POST).with(web_api::set_alarm_minutes_from_now)) // websocket route // note some browsers need already existing http connection to // this server for the upgrade to wss to work @@ -116,6 +115,8 @@ pub fn start(signed_cert: &str, private_key: &str, .resource("/plot", |r| r.f(plot_data)) .resource(r"/list_data.html", |r| r.method(Method::GET).f(list_data)) + .resource(r"/set_alarm", |r| r.method(Method::POST).with(web_api::set_alarm_unix_timestamp)) + //login route, every uri starting "/login" will be forwarded to the adress //after "/login" once the client has been authenticated .resource(r"/login/{tail:.*}", |r| { @@ -125,8 +126,8 @@ pub fn start(signed_cert: &str, private_key: &str, //for all other urls we try to resolve to static files in the "web" dir .resource(r"/{tail:.*}", |r| r.f(serve_file)) }) - //.bind_rustls("0.0.0.0:8080", tls_config).unwrap() - .bind("0.0.0.0:8080").unwrap() //without tcp use with debugging (note: https -> http, wss -> ws) + .bind_rustls("0.0.0.0:8070", tls_config).unwrap() + //.bind("0.0.0.0:8070").unwrap() //without tcp use with debugging (note: https -> http, wss -> ws) .shutdown_timeout(5) // shut down 5 seconds after getting the signal to shut down .start(); @@ -158,14 +159,14 @@ fn main() { let passw_db = Arc::new(RwLock::new(PasswordDatabase::load("").unwrap())); let dataset_handle = Arc::new(RwLock::new(timeseries_interface::init("data").unwrap())); let sessions = Arc::new(RwLock::new(HashMap::new())); - let (controller_tx, controller_rx) = mpsc::channel(); + let (controller_tx, controller_rx) = crossbeam_channel::unbounded(); - controller::start(controller_rx).unwrap(); + let _controller_thread = controller::start(controller_rx).unwrap(); input::attached_sensors::check_local_sensing_dataset(&dataset_handle).unwrap(); - let (Alarms, waker_thread) = input::alarms::Alarms::setup(controller_tx.clone()).unwrap(); + let (alarms, _waker_thread) = input::alarms::Alarms::setup(controller_tx.clone()).unwrap(); let (data_router_handle, web_handle) = //starts webserver - start("keys/cert.key", "keys/cert.cert", dataset_handle.clone(), passw_db.clone(), sessions.clone(), controller_tx.clone(), Alarms.clone()); + start("keys/cert.key", "keys/cert.cert", dataset_handle.clone(), passw_db.clone(), sessions.clone(), controller_tx.clone(), alarms.clone()); #[cfg(feature = "sensors_connected")] input::attached_sensors::start_monitoring(controller_tx.clone(), data_router_handle, dataset_handle.clone()); @@ -186,5 +187,5 @@ fn main() { } println!("shutting down"); httpserver::stop(web_handle); - controller_tx.send(Event::Stop); + controller_tx.send(Event::Stop).unwrap(); } diff --git a/web/plot.js b/web/plot.js index 05a79920..0b5f149f 100644 --- a/web/plot.js +++ b/web/plot.js @@ -22,6 +22,28 @@ var layout = { //TODO extend id_map to keep track of position is typedArray +Date.prototype.toDateInputValue = (function() { + var local = new Date(this); + local.setMinutes(this.getMinutes() - this.getTimezoneOffset()); + return local.toJSON().slice(0,10); +}); + +// ensure that after conversion to GMT the date will still be correct +Date.prototype.toTimeInputValue = (function() { + var local = new Date(this); + local.setUTCHours(this.getHours(), this.getMinutes(), this.getSeconds(),0); + return local; +}); + +function onLoad(){ + var d = new Date(); + var timeControl = document.getElementById("stop-time"); + timeControl.valueAsDate = d.toTimeInputValue(); + var dateControl = document.getElementById("stop-date"); + dateControl.value = d.toDateInputValue(); +} +window.addEventListener("load", onLoad, false); + function init(){ output = document.getElementById("output"); @@ -32,13 +54,15 @@ function init(){ websocket.onerror = function(evt) { onError(evt) }; } + + function onOpen(evt){ writeToScreen("CONNECTED"); //parse the form //TODO change plot button to "update" var selected = document.forms["choose lines"]; - for (var i = 0; i < selected.length; i++) { + for (var i = 0; i < selected.length; i++) {//TODO selected.for ... of ... (look up) if (selected[i].checked === true) { var input = selected[i].value; let [set_id_str, field_id] = input.split(","); @@ -52,13 +76,25 @@ function onOpen(evt){ } } - var start_timestamp = 0;//placeholder - var stop_timestamp = 0; + //var dateOffset = (24*60*60*1000);//TODO fix this + //var stop_timestamp = new Date( Date.now() ); + + //var start_timestamp = new Date(); + //console.log(stop_timestamp.getTime()); + //start_timestamp.setTime(stop_timestamp.getTime() - dateOffset); + + //TODO improve + //var start_timestamp = document.getElementById('start-date').valueAsDate; + //var stop_timestamp = document.getElementById('stop-date').valueAsDate; + + var start_timestamp = new Date(1553731200000); + var stop_timestamp = new Date(1554508800000); + //generate and send subscribe string for (const [set,fields] of subbed.entries()){ var s = "/select_uncompressed " - +start_timestamp+" " - +stop_timestamp+" " + +start_timestamp.getTime()+" " + +stop_timestamp.getTime()+" " +set+" "; for (var i = 0; i < fields.length; i++ ) { @@ -68,7 +104,7 @@ function onOpen(evt){ } websocket.onmessage = function(evt) { gotMeta(evt) }; - doSend("/meta"); + doSend("/meta 1000"); //1000 is max numb of lines, paramater is optional } function gotMeta(evt){ @@ -76,39 +112,48 @@ function gotMeta(evt){ var id_info; var sets_meta = JSON.parse(evt.data);//add package info (total data size, package size) - console.log(sets_meta); + //console.log(sets_meta); //for every dataset - for (var set_idx=0; set_idx < sets_meta.length; set_idx+=1){ - ({field_ids, traces_meta, numb_of_lines, set_id} = sets_meta[set_idx]); + for (var i=0; i < sets_meta.length; i+=1){ + ({field_ids, traces_meta, n_lines, dataset_id} = sets_meta[i]); + + //console.log("sets_meta"); + //console.log(sets_meta[i]); + var old_len = lines.length; var field_list = []; //append all the metadata to the lines - console.log("lines before"); - console.log(lines); - console.log("traces_meta"); - console.log(traces_meta); + //console.log("lines before"); + //console.log(lines); + //console.log("traces_meta"); + //console.log(traces_meta); lines = lines.concat(traces_meta); - console.log("lines"); - console.log(lines); + //console.log("lines"); + //console.log(lines); //create an x-array for all a dataset - var shared_x = new Float64Array(numb_of_lines); - var len = lines.length; + var shared_x = new Float64Array(n_lines); for (var i= 0; i x*1000); //from seconds to milliseconds //no need to set for all x-axises as they are linked //memcpy equivalent of memcpy(trace+pos, timestamps, len(timestamps)); trace_numb = fields_to_lines[0].trace_numb; - console.log("fields to lines[0]"); - console.log(fields_to_lines[0]); - console.log("fields to lines"); - console.log(fields_to_lines); - console.log("lines"); - console.log(lines); + //console.log("fields to lines[0]"); console.log(fields_to_lines[0]); + //console.log("fields to lines"); console.log(fields_to_lines); + //console.log("lines"); console.log(lines); + //console.log("trace_numb"); console.log(trace_numb); // Copy the new timestamps into the array starting at index pos - //console.log(lines); - lines[trace_numb].x = lines[trace_numb].x.set(timestamps, pos); - //console.log("timestamps"); - //console.log(timestamps); + //console.log("timestamps"); console.log(timestamps); + lines[trace_numb].x.set(timestamps, pos); + //console.log("lines"); console.log(lines); } function setData(data, numb_of_elements, fields_to_lines, pos){ var nTraces_in_set = fields_to_lines.length; var data = new Float32Array(data, 8+numb_of_elements*8, numb_of_elements); + //console.log("data:"); console.log(data); + //console.log("pos"); console.log(pos); + for (var i=0; i < numb_of_elements; i+=1){ for (var j=0; j < nTraces_in_set; j++){ var trace_numb = fields_to_lines[j].trace_numb; lines[trace_numb].y[pos+i] = data[i+j]; + //console.log("trace_numb"); console.log(trace_numb); + //console.log("pos+i"); console.log(pos+i); } } } //allocate data for all chunks function gotDataChunk(evt){ //FIXME only works for one dataset - console.log("evt"); - console.log(evt); + //console.log("evt"); + //console.log(evt); var data = new DataView(evt.data); //check for server signal that all data has been recieved, or an error has //occured - if (data.getInt16(3, true) == 1) { + var chunknumb = data.getInt16(0, true); + console.log("chunknumb: "); console.log(chunknumb); + console.log("data: "); console.log(data); + console.log("lines: "); console.log(lines); + if (chunknumb == 0) { //check if this was the last package (package numb=0) //console.log("got last data chunk, creating plot"); + console.log("lines"); console.log(lines); Plotly.newPlot("plot", lines, layout, {responsive: true}); websocket.onmessage = function(evt) { gotUpdate(evt) }; doSend("/sub"); return; }; - var chunknumb = data.getInt16(0, true); var setid = data.getInt16(2, true); - var fields_to_lines = id_map.get(setid); + var [fields_to_lines, pos] = id_map.get(setid); + //console.log("fields_to_lines:"); console.log(fields_to_lines); + //console.log("id_map:"); console.log(id_map); + //console.log("setid:"); console.log(setid); + var numb_of_elements = (evt.data.byteLength-8)/(4*(fields_to_lines.length)+8); - console.log("numb_of_elements"); - console.log(numb_of_elements); - console.log(evt.data.byteLength); - console.log("evt.data"); - console.log(evt.data); - console.log(fields_to_lines.length); + //console.log("numb_of_elements"); console.log(numb_of_elements); + //console.log("evt.data"); console.log(evt.data); + //console.log(fields_to_lines.length); //FIXME NEEDS TO MOVE TO META DATA, NO TIME TO PRE ALLOC CURRENTLY //next package arrives and is handled before this is done @@ -181,13 +234,16 @@ function gotDataChunk(evt){ //FIXME only works for one dataset //--determine pos not from last (vector/write style) but chunknumber and known chunk sizes //--add check if allocation is finished before continueing (use global bool flag for this) - var pos = chunknumb*package_size; - //console.log("numb of elements"); - //console.log(numb_of_elements); + //console.log("numb_of_elements"); console.log(numb_of_elements); + //console.log("package_size"); console.log(package_size); + + console.log("pos"); console.log(pos); setTimestamps(evt.data, numb_of_elements, fields_to_lines, pos); - debugger; setData(evt.data, numb_of_elements, fields_to_lines, pos); - debugger; + pos += numb_of_elements; + + id_map.set(setid, [fields_to_lines, pos]); + //console.log("lines"); console.log(lines); } function gotUpdate(evt){ @@ -197,7 +253,7 @@ function gotUpdate(evt){ //console.log(setid); //console.log(id_map); - var fields_to_lines = id_map.get(setid); + var fields_to_lines = id_map.get(setid)[0]; //TODO rethink metadata ordening (use nested list) var x_update = []; @@ -206,12 +262,15 @@ function gotUpdate(evt){ //console.log(setid); //console.log(id_map); var len = fields_to_lines.length; - for (var i=0; i < len; i++) { + for (var i=0; i < len; i++) {// for all traces make an update var trace_numb = fields_to_lines[i].trace_numb; updated_traces.push(trace_numb); - x_update.push([new Date(timestamp*1000)]); - y_update.push([data.getFloat32(4*i+10, true)]); + x_update.push(new Float64Array([timestamp*1000])); + y_update.push(new Float32Array([data.getFloat32(4*i+10, true)])); } + console.log(x_update); + console.log(y_update); + console.log(lines); Plotly.extendTraces("plot", {x: x_update, y: y_update}, updated_traces); writeToScreen("Got Update"); @@ -243,5 +302,3 @@ function writeToScreen(message){ pre.innerHTML = message; output.appendChild(pre); } - -//window.addEventListener("load", init, false); diff --git a/web/set_alarm.html b/web/set_alarm.html new file mode 100644 index 00000000..2d88754c --- /dev/null +++ b/web/set_alarm.html @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + \ No newline at end of file From 4f423aa6a007b2848b9dddc3f8a319e57e465c5b Mon Sep 17 00:00:00 2001 From: David Kleingeld Date: Sun, 19 May 2019 01:37:57 +0200 Subject: [PATCH 003/687] fixes parsing error in set alarm javascript --- web/set_alarm.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/set_alarm.html b/web/set_alarm.html index 2d88754c..0e717b22 100644 --- a/web/set_alarm.html +++ b/web/set_alarm.html @@ -84,7 +84,7 @@ var shouldBeAsync = true; request.open("POST", "/set_alarm", shouldBeAsync); request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - request.send("timestamp","12"); + request.send("timestamp=12"); } From 033029704cf6308aeae825380308c2a51cbb5066 Mon Sep 17 00:00:00 2001 From: David Kleingeld Date: Sun, 19 May 2019 02:29:29 +0200 Subject: [PATCH 004/687] further refinements to alarm system --- src/controller/commands.rs | 15 +-------------- src/controller/mod.rs | 10 ++++++---- src/controller/states/mod.rs | 22 ++++++++++++++++++++-- src/input/alarms.rs | 20 ++++++++++++++++---- src/input/web_api/mod.rs | 34 +++++++++++++++++++++++----------- src/main.rs | 1 + web/set_alarm.html | 5 ++--- 7 files changed, 69 insertions(+), 38 deletions(-) diff --git a/src/controller/commands.rs b/src/controller/commands.rs index a0b2dcf7..4cd02c3c 100644 --- a/src/controller/commands.rs +++ b/src/controller/commands.rs @@ -2,12 +2,6 @@ use super::{ActiveState, Modifications, System}; use crate::controller::states::*; use crate::controller::states::RoomState; -#[derive(Copy, Clone)] -pub enum TargetState { - Normal, - LightLoop, -} - #[derive(Copy, Clone)] pub enum Command { LampsToggle, @@ -30,7 +24,7 @@ pub fn handle_cmd(cmd: Command, state: ActiveState, mods: &mut Modifications, sy println!("handled a command"); match cmd { Command::ChangeState(target_state) => { - return handle_changestate_cmd(target_state, mods, sys) + return change_state(target_state, mods, sys) } //Command::PauseMpd => {unimplemented!(); state}, @@ -50,10 +44,3 @@ pub fn handle_cmd(cmd: Command, state: ActiveState, mods: &mut Modifications, sy } state } - -fn handle_changestate_cmd(target_state: TargetState, mods: &mut Modifications, sys: &mut System) -> ActiveState { - match target_state { - TargetState::Normal => ActiveState::Normal(Normal::enter(mods, sys)), - TargetState::LightLoop => ActiveState::LightLoop(LightLoop::enter(mods, sys)), - } -} diff --git a/src/controller/mod.rs b/src/controller/mod.rs index bfd49c3c..add83f7b 100644 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -5,10 +5,12 @@ mod system; use system::lamps::Lighting; mod states; -use states::{ActiveState, RoomState}; +use states::{ActiveState, RoomState, change_state}; mod commands; use commands::{handle_cmd}; -pub use commands::{Command, TargetState}; + +pub use commands::Command; +pub use states::TargetState; pub enum Event { Update, @@ -86,8 +88,8 @@ pub fn start(rx: crossbeam_channel::Receiver) -> Result {handle_cmd(cmd, state, &mut mods, &mut system)}, (Event::Update, state) => {state.update(&mut mods, &mut system)}, - (Event::Alarm, state) => {dbg!("ALARM ALARM"); state}, - (Event::Test, state) => {dbg!("a test happend"); state}, + (Event::Alarm, state) => {dbg!("ALARM ALARM"); info!("Alarm went off"); state}, + (Event::Test, state) => {dbg!("a test happend"); change_state(TargetState::WakeUp, &mut mods, &mut system)}, (Event::Stop, _) => return (), }; diff --git a/src/controller/states/mod.rs b/src/controller/states/mod.rs index 80c4aab1..4b23d0e6 100644 --- a/src/controller/states/mod.rs +++ b/src/controller/states/mod.rs @@ -2,15 +2,24 @@ use super::{System, Modifications}; mod normal; mod lightloop; +mod wakeup; pub use normal::Normal; pub use lightloop::LightLoop; - +pub use wakeup::WakeUp; #[derive(Copy, Clone)] pub enum ActiveState { Normal(normal::Normal), - LightLoop(lightloop::LightLoop) + LightLoop(lightloop::LightLoop), + WakeUp(wakeup::WakeUp), +} + +#[derive(Copy, Clone)] +pub enum TargetState { + Normal, + LightLoop, + WakeUp, } impl ActiveState { @@ -18,10 +27,19 @@ impl ActiveState { match self { ActiveState::Normal(state) => state.update(mods, system), ActiveState::LightLoop(state) => state.update(mods, system), + ActiveState::WakeUp(state) => state.update(mods, system), } } } +pub fn change_state(target_state: TargetState, mods: &mut Modifications, sys: &mut System) -> ActiveState { + match target_state { + TargetState::Normal => ActiveState::Normal(Normal::enter(mods, sys)), + TargetState::LightLoop => ActiveState::LightLoop(LightLoop::enter(mods, sys)), + TargetState::WakeUp => ActiveState::WakeUp(WakeUp::enter(mods, sys)), + } +} + pub trait RoomState { fn enter(mods: &mut Modifications, system: &mut System) -> Self; fn update(self, mods: &mut Modifications, system: &mut System) -> ActiveState; diff --git a/src/input/alarms.rs b/src/input/alarms.rs index 0a773e10..46c26cf4 100644 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -6,7 +6,7 @@ use std::sync::{Arc, Mutex}; use std::thread; use chrono::{DateTime, Utc}; -use std::fs::File; +use std::fs::{File, OpenOptions}; use serde_yaml; use crate::controller::Event; @@ -76,7 +76,6 @@ fn waker(mut alarm_list: AlarmList, event_tx: crossbeam_channel::Sender, impl Alarms { pub fn setup(event_tx: crossbeam_channel::Sender) -> Result<(Self, thread::JoinHandle<()>), Error> { - dbg!(("hoi")); let mut alarm_list = AlarmList::load()?; let (waker_tx, waker_rx) = crossbeam_channel::unbounded(); let mut alarm_list_for_waker = alarm_list.clone(); @@ -86,7 +85,7 @@ impl Alarms { } pub fn add_alarm(&self, at_time: DateTime) -> Result<(), Error> { - self.alarm_list.remove_alarm(&at_time)?; + self.alarm_list.add_alarm(at_time)?; self.waker_tx.send(())?; Ok(()) } @@ -95,6 +94,10 @@ impl Alarms { self.waker_tx.send(())?; Ok(()) } + + pub fn list(&self) -> Vec> { + self.alarm_list.list() + } } impl AlarmList { @@ -113,6 +116,11 @@ impl AlarmList { list.remove_alarm(at_time) } + fn list(&self) -> Vec> { + let mut list = self.rawlist.lock().unwrap(); + list.memory.iter().cloned().collect() + } + /// calculate time to the earliest alarm, remove it from the list if the current time is later /// then the alarm fn get_next_alarm(&mut self) -> Option> { @@ -129,12 +137,14 @@ impl RawList { let mut file; let memory; if path.exists() { - file = File::open(path)?; + file = OpenOptions::new().write(true).read(true).open(path)?; memory = serde_yaml::from_reader(&mut file)?; + info!("loaded alarms from file"); } else { file = File::create(path)?; memory = BTreeSet::new(); serde_yaml::to_writer(&file, &memory)?; + info!("alarm file did not exist, created new"); } Ok(Self {memory, file}) @@ -144,12 +154,14 @@ impl RawList { self.memory.insert(at_time); self.file.set_len(0)?; //truncate file serde_yaml::to_writer(&mut self.file, &self.memory)?; + self.file.sync_data()?; Ok(()) } fn remove_alarm(&mut self, at_time: &DateTime) -> Result<(), Error>{ self.memory.remove(at_time); self.file.set_len(0)?; //truncate file serde_yaml::to_writer(&mut self.file, &self.memory)?; + self.file.sync_data()?; Ok(()) } diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index 7b975c5d..62852ba8 100644 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -142,22 +142,34 @@ pub struct AlarmDataUnixTS { } pub fn set_alarm_unix_timestamp((req, params): (HttpRequest, Form)) -> HttpResponse { - if authenticated(&req) { - //Code to parse alarm time - dbg!(¶ms); - - if let Ok(ts) = params.timestamp.parse(){ - let time = DateTime::::from_utc(NaiveDateTime::from_timestamp(ts, 0), Utc); - if time>Utc::now() { - req.state().alarms.add_alarm(time).unwrap(); + //Code to parse alarm time + dbg!(¶ms); + + if let Ok(ts) = params.timestamp.parse(){ + let time = DateTime::::from_utc(NaiveDateTime::from_timestamp(ts, 0), Utc); + if time>Utc::now() { + if req.state().alarms.add_alarm(time).is_ok() { + dbg!(("done setting alarm")); HttpResponse::Ok().finish() } else { - make_error(&req, StatusCode::UNPROCESSABLE_ENTITY) + make_error(&req, StatusCode::INTERNAL_SERVER_ERROR) } } else { - make_error(&req, StatusCode::INTERNAL_SERVER_ERROR) + make_error(&req, StatusCode::UNPROCESSABLE_ENTITY) } } else { - make_auth_error(&req) + make_error(&req, StatusCode::INTERNAL_SERVER_ERROR) + } +} + +pub fn list_alarms(req: &HttpRequest) -> HttpResponse { + //Code to parse alarm time + + let alarms = req.state().alarms.list(); + let mut list = String::with_capacity(alarms.len()*30); + for alarm in alarms { + list.push_str(&alarm.to_rfc2822()); } + dbg!(&list); + HttpResponse::Ok().body(list) } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 8a89ac38..2199f754 100644 --- a/src/main.rs +++ b/src/main.rs @@ -116,6 +116,7 @@ pub fn start(signed_cert: &str, private_key: &str, .resource(r"/list_data.html", |r| r.method(Method::GET).f(list_data)) .resource(r"/set_alarm", |r| r.method(Method::POST).with(web_api::set_alarm_unix_timestamp)) + .resource(r"/list_alarms", |r| r.method(Method::GET).f(web_api::list_alarms)) //login route, every uri starting "/login" will be forwarded to the adress //after "/login" once the client has been authenticated diff --git a/web/set_alarm.html b/web/set_alarm.html index 0e717b22..4f93f9d9 100644 --- a/web/set_alarm.html +++ b/web/set_alarm.html @@ -4,7 +4,7 @@ - + @@ -84,8 +84,7 @@ var shouldBeAsync = true; request.open("POST", "/set_alarm", shouldBeAsync); request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - request.send("timestamp=12"); - + request.send("timestamp="+unix_time); } document.getElementById("alarm_date").valueAsDate = getDefaultAlarmDate(); From fc96ae92b15bd4024396b9f177cc1a632b8eb9c2 Mon Sep 17 00:00:00 2001 From: David Kleingeld Date: Sat, 25 May 2019 01:08:28 +0200 Subject: [PATCH 005/687] moves alarm system to use sled --- Cargo.lock | 129 ++++++++++++++++++++++++++++++++++++ Cargo.toml | 6 +- src/errors.rs | 12 ++++ src/input/alarms.rs | 158 ++++++++++++++++++-------------------------- src/main.rs | 11 ++- 5 files changed, 220 insertions(+), 96 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 158bf681..176f9f31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,7 @@ dependencies = [ "actix-web 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)", "actix-web-httpauth 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "bme280 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -15,9 +16,11 @@ dependencies = [ "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "linux-embedded-hal 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "philipshue 0.3.2 (git+https://github.com/dskleingeld/philipshue)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", + "sled 0.24.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "sysfs_gpio 0.5.3 (git+https://github.com/rust-embedded/rust-sysfs-gpio)", "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -483,6 +486,15 @@ dependencies = [ "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-deque" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-deque" version = "0.7.1" @@ -492,6 +504,20 @@ dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-epoch" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-epoch" version = "0.7.1" @@ -513,6 +539,14 @@ dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-utils" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-utils" version = "0.6.5" @@ -733,6 +767,15 @@ name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -796,6 +839,19 @@ dependencies = [ "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hashbrown" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "historian" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "hostname" version = "0.1.5" @@ -1374,6 +1430,27 @@ dependencies = [ "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pagecache" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "historian 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot" version = "0.7.1" @@ -1611,6 +1688,27 @@ name = "rawpointer" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rayon" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rdrand" version = "0.4.0" @@ -1870,6 +1968,14 @@ dependencies = [ "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde_bytes" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serde_derive" version = "1.0.91" @@ -1945,6 +2051,18 @@ name = "slab" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "sled" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "smallvec" version = "0.6.9" @@ -2675,9 +2793,12 @@ dependencies = [ "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" +"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" +"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" +"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum dataserver 0.1.0 (git+https://github.com/dskleingeld/dataserver)" = "" "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" @@ -2702,6 +2823,7 @@ dependencies = [ "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" @@ -2710,6 +2832,8 @@ dependencies = [ "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" "checksum h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "85ab6286db06040ddefb71641b50017c06874614001a134b423783e2db2920bd" +"checksum hashbrown 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "570178d5e4952010d138b0f1d581271ff3a02406d990f887d1e87e3d6e43b0ac" +"checksum historian 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f653416eb756b69642a1f1498817970fafe409998a849622c27cc5b1b7df989c" "checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" "checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" @@ -2772,6 +2896,7 @@ dependencies = [ "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)" = "05636e06b4f8762d4b81d24a351f3966f38bd25ccbcfd235606c91fdb82cc60f" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" +"checksum pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74a701d13e2f3ee32a50be43321da8f712cf1e6e9ff0e2be66ab7f5c6598a16a" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" @@ -2798,6 +2923,8 @@ dependencies = [ "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rawpointer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebac11a9d2e11f2af219b8b8d833b76b1ea0e054aa0e8d8e9e4cbde353bdf019" +"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" +"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" @@ -2827,6 +2954,7 @@ dependencies = [ "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "a72e9b96fa45ce22a4bc23da3858dfccfd60acd28a25bcd328a98fdd6bea43fd" +"checksum serde_bytes 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aaff47db6ef8771cca5d88febef2f22f47f645420e51226374049f68c6b08569" "checksum serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "101b495b109a3e3ca8c4cbe44cf62391527cdfb6ba15821c5ce80bcd5ea23f9f" "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" @@ -2836,6 +2964,7 @@ dependencies = [ "checksum signal-hook-registry 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cded4ffa32146722ec54ab1f16320568465aa922aa9ab4708129599740da85d7" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +"checksum sled 0.24.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a780266d241e270e52cab0010e11aecfc6d52e33aa98e52eb9792023abd23aa" "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "4e626972d3593207547f14bf5fc9efa4d0e7283deb73fef1dff313dae9ab8878" "checksum spidev 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ba01d3ef92a37e898fecac76cd3e1b33c999395e2d70787608d9678c4293e04" diff --git a/Cargo.toml b/Cargo.toml index 196919b7..356b46d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,5 +40,9 @@ bme280 = "0.1.1" smallvec = "0.6.6" chrono = { version = "0.4.6", features = ["serde"] } bytes = "0.4.11" +byteorder = "1.3.1" -crossbeam-channel = "0.3" \ No newline at end of file +crossbeam-channel = "0.3" + +sled = "0.24.1" +pagecache = "0.17.0" \ No newline at end of file diff --git a/src/errors.rs b/src/errors.rs index e1c92846..e2341ed9 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -6,6 +6,7 @@ pub enum Error { GPIO(sysfs_gpio::Error), YamlParsing(serde_yaml::Error), Channel(crossbeam_channel::SendError<()>), + DataBase(sled::Error), } impl From for Error { @@ -31,6 +32,17 @@ impl From> for Error { } } +//impl From for Error { +// fn from(error: crossbeam_channel::SendError<()>) -> Self { +// Error::Channel(error) +// } +//} + +impl From for Error { + fn from(error: sled::Error) -> Self { + Error::DataBase(error) + } +} /*impl fmt::Debug for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/input/alarms.rs b/src/input/alarms.rs index 46c26cf4..730545f7 100644 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -5,35 +5,36 @@ use crossbeam_channel; use std::sync::{Arc, Mutex}; use std::thread; -use chrono::{DateTime, Utc}; +use chrono::{DateTime, NaiveDateTime, Utc}; use std::fs::{File, OpenOptions}; -use serde_yaml; +use sled; +use byteorder::{ByteOrder, BigEndian}; use crate::controller::Event; use crate::errors::Error; -//TODO, move alarms to input? then backup waker/trigger/speaker/alarm moves to arduino +//TODO, what to do on multiple alarms at the same time? +// -add one a second later +// -store in millisec to lower collision chance? + -#[derive(Debug)] -struct RawList { - memory: BTreeSet>, - file: File, -} -#[derive(Debug, Clone)] -struct AlarmList { - rawlist: Arc>, -} -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct Alarms { waker_tx: crossbeam_channel::Sender<()>, - alarm_list: AlarmList, + alarm_db: AlarmList, +} + +#[derive(Clone)] +pub struct AlarmList { + db: Arc, } fn waker(mut alarm_list: AlarmList, event_tx: crossbeam_channel::Sender, waker_rx: crossbeam_channel::Receiver<()>) { loop { + //This can fail #TODO make sure an non waking error alarm is send to the user if let Some(current_alarm) = alarm_list.get_next_alarm() { let now = Utc::now(); let timeout = (now - current_alarm).to_std().unwrap(); @@ -50,7 +51,7 @@ fn waker(mut alarm_list: AlarmList, event_tx: crossbeam_channel::Sender, error!("could not set off alarm: {:?}", error); }; //set //remove alarm from memory and file - if let Err(error) = alarm_list.remove_alarm(¤t_alarm){ + if let Err(error) = alarm_list.remove_alarm(current_alarm){ error!("could not remove alarm after its trigger time: {:?}", error); }; break; //get next alarm @@ -75,93 +76,58 @@ fn waker(mut alarm_list: AlarmList, event_tx: crossbeam_channel::Sender, impl Alarms { - pub fn setup(event_tx: crossbeam_channel::Sender) -> Result<(Self, thread::JoinHandle<()>), Error> { - let mut alarm_list = AlarmList::load()?; + pub fn setup(event_tx: crossbeam_channel::Sender, db: sled::Db) -> Result<(Self, thread::JoinHandle<()>), Error> { + + let alarm_db = AlarmList { db: db.open_tree("alarms")? }; + let (waker_tx, waker_rx) = crossbeam_channel::unbounded(); - let mut alarm_list_for_waker = alarm_list.clone(); - let waker_thread = thread::spawn(move || { waker(alarm_list_for_waker, event_tx, waker_rx)}); + let waker_db_copy = alarm_db.clone(); + let waker_thread = thread::spawn(move || { waker(waker_db_copy, event_tx, waker_rx)}); - Ok((Self {alarm_list, waker_tx}, waker_thread)) + Ok((Self {alarm_db, waker_tx}, waker_thread)) } + // we decrease the time till the alarm until there is a place in the database + // as only one alarm can fire at the time, after an alarm gets a timeslot it is never changed pub fn add_alarm(&self, at_time: DateTime) -> Result<(), Error> { - self.alarm_list.add_alarm(at_time)?; + let mut timestamp = at_time.timestamp(); + + self.alarm_db.add_alarm(at_time); + //signal waker to update its next alarm self.waker_tx.send(())?; Ok(()) } pub fn remove_alarm(&self, at_time: DateTime) -> Result<(), Error> { - self.alarm_list.remove_alarm(&at_time)?; - self.waker_tx.send(())?; + self.alarm_db.remove_alarm(at_time)?; + self.waker_tx.send(())?; //signal waker to update its next alarm Ok(()) } pub fn list(&self) -> Vec> { - self.alarm_list.list() + //self.alarm_list.iter().keys().map(|k| DateTime::::from_utc(NaiveDateTime::from_timestamp(k, 0), Utc);) + Vec::new() //TODO placeholder } } impl AlarmList { - - fn load() -> Result { - let list = RawList::load()?; - Ok(Self {rawlist: Arc::new(Mutex::new(list)) }) - } - - fn add_alarm(&self, at_time: DateTime) -> Result<(), Error> { - let mut list = self.rawlist.lock().unwrap(); - list.add_alarm(at_time) - } - fn remove_alarm(&self, at_time: &DateTime) -> Result<(), Error> { - let mut list = self.rawlist.lock().unwrap(); - list.remove_alarm(at_time) - } - - fn list(&self) -> Vec> { - let mut list = self.rawlist.lock().unwrap(); - list.memory.iter().cloned().collect() - } - - /// calculate time to the earliest alarm, remove it from the list if the current time is later - /// then the alarm - fn get_next_alarm(&mut self) -> Option> { - let mut list = self.rawlist.lock().unwrap(); - list.get_next_alarm() - } -} - -impl RawList { - - fn load() -> Result { - let path = Path::new("alarms.yaml"); - - let mut file; - let memory; - if path.exists() { - file = OpenOptions::new().write(true).read(true).open(path)?; - memory = serde_yaml::from_reader(&mut file)?; - info!("loaded alarms from file"); - } else { - file = File::create(path)?; - memory = BTreeSet::new(); - serde_yaml::to_writer(&file, &memory)?; - info!("alarm file did not exist, created new"); + // we decrease the time till the alarm until there is a place in the database + // as only one alarm can fire at the time, after an alarm gets a timeslot it is never changed + pub fn add_alarm(&self, at_time: DateTime) -> Result<(), Error> { + let mut timestamp = at_time.timestamp() as u64; + let mut timestamp_array = timestamp.to_be_bytes(); + + //create alarm entry if there is no alarm at this timestamp yet + //if there is already an alarm schedualed, postpone this one until there is a spot free + //self.db.cas(&[1], None as Option<&[u8]>, Some(&[10]) + while let Err(old_event) = self.db.cas(×tamp_array, None as Option<&[u8]>, Some(&[0]))? {//cas unique creation + timestamp -= 1; + timestamp_array = timestamp.to_be_bytes(); } - - Ok(Self {memory, file}) - } - - fn add_alarm(&mut self, at_time: DateTime) -> Result<(), Error>{ - self.memory.insert(at_time); - self.file.set_len(0)?; //truncate file - serde_yaml::to_writer(&mut self.file, &self.memory)?; - self.file.sync_data()?; Ok(()) } - fn remove_alarm(&mut self, at_time: &DateTime) -> Result<(), Error>{ - self.memory.remove(at_time); - self.file.set_len(0)?; //truncate file - serde_yaml::to_writer(&mut self.file, &self.memory)?; - self.file.sync_data()?; + pub fn remove_alarm(&self, at_time: DateTime) -> Result<(), Error> { + let timestamp = at_time.timestamp() as u64; + self.db.del(timestamp.to_be_bytes())?; Ok(()) } @@ -170,19 +136,23 @@ impl RawList { fn get_next_alarm(&mut self) -> Option> { let now = Utc::now(); - loop { - let next_alarm = self.memory.iter().cloned().next(); - if let Some(alarm) = next_alarm { - if alarm > now { - return Some(alarm.clone()); - } else { - if self.remove_alarm(&alarm).is_err() { - error!("could not remove alarm after it fired!"); - } + //the greater then is applied to the integer representation + let timestamp = (now.timestamp()-10) as u64; + match self.db.get_gt(timestamp.to_be_bytes()) { + Ok(entry) => { + if let Some(entry) = entry { + let (timestamp, action) = entry; + let timestamp = BigEndian::read_u64(×tamp); + let alarm = DateTime::::from_utc(NaiveDateTime::from_timestamp(61, 0), Utc); + Some(alarm) + } else { + None } - } else { - return None; + }, + Err(error) => { + error!("Could not retrieve next alarm"); + None } - } + } } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 2199f754..813ad22d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,8 @@ use crate::actix_web::middleware::identity::{CookieIdentityPolicy, IdentityServi use crate::chrono::Duration; +use sled; + use std::sync::atomic::{AtomicUsize}; use std::thread; @@ -157,6 +159,13 @@ fn main() { helper::setup_logging(2).expect("could not set up debugging"); + let config = sled::ConfigBuilder::new() + .path("database".to_owned()) + .flush_every_ms(None) //do not flush to disk unless explicitly asked + .build(); + + let db = sled::Db::start(config).unwrap(); + let passw_db = Arc::new(RwLock::new(PasswordDatabase::load("").unwrap())); let dataset_handle = Arc::new(RwLock::new(timeseries_interface::init("data").unwrap())); let sessions = Arc::new(RwLock::new(HashMap::new())); @@ -164,7 +173,7 @@ fn main() { let _controller_thread = controller::start(controller_rx).unwrap(); input::attached_sensors::check_local_sensing_dataset(&dataset_handle).unwrap(); - let (alarms, _waker_thread) = input::alarms::Alarms::setup(controller_tx.clone()).unwrap(); + let (alarms, _waker_thread) = input::alarms::Alarms::setup(controller_tx.clone(), db.clone()).unwrap(); let (data_router_handle, web_handle) = //starts webserver start("keys/cert.key", "keys/cert.cert", dataset_handle.clone(), passw_db.clone(), sessions.clone(), controller_tx.clone(), alarms.clone()); From f34da32ea0c3f216632677aec054e94dfa1c990a Mon Sep 17 00:00:00 2001 From: David Kleingeld Date: Mon, 27 May 2019 01:00:38 +0200 Subject: [PATCH 006/687] switches web interface to datetime-local type --- web/set_alarm.html | 51 ++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/web/set_alarm.html b/web/set_alarm.html index 4f93f9d9..9d5ec2c1 100644 --- a/web/set_alarm.html +++ b/web/set_alarm.html @@ -4,9 +4,7 @@ - - - + From adf2ce8c11e01c1fa80e3cbfde560ff8cb8b8e87 Mon Sep 17 00:00:00 2001 From: David Kleingeld Date: Mon, 27 May 2019 01:01:30 +0200 Subject: [PATCH 007/687] fixes missing break in waker, adds debug calls to setalarm --- src/input/alarms.rs | 57 +++++++++++++++++++++++++++------------- src/input/web_api/mod.rs | 7 +++++ 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/input/alarms.rs b/src/input/alarms.rs index 730545f7..c6893394 100644 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -32,17 +32,18 @@ pub struct AlarmList { } fn waker(mut alarm_list: AlarmList, event_tx: crossbeam_channel::Sender, waker_rx: crossbeam_channel::Receiver<()>) { - + dbg!(); loop { //This can fail #TODO make sure an non waking error alarm is send to the user - if let Some(current_alarm) = alarm_list.get_next_alarm() { + if let Some(current_alarm) = alarm_list.get_next() { let now = Utc::now(); - let timeout = (now - current_alarm).to_std().unwrap(); - + let timeout = (current_alarm - now ).to_std().unwrap();//TODO handle alarm in past + info!("next alarm is in: {} seconds", timeout.as_secs()); + //do we sound the an alarm or should we add or remove one? match waker_rx.recv_timeout(timeout) { //do not set off alarm - Ok(_) => (),//should recheck if "current alarm" is still the right one as we removed one + Ok(_) => {dbg!(); ()},//should recheck if "current alarm" is still the right one as we removed one Err(error) => match error {//should the alarm go off or should we stop? @@ -62,11 +63,12 @@ fn waker(mut alarm_list: AlarmList, event_tx: crossbeam_channel::Sender, } } else { //no alarm to wait on, wait for instructions + info!("no alarm in the future"); loop { //A message through the mpsc signals an alarm has been added match waker_rx.recv() { - Ok(_) => (), //alarms were added or remove, go back and start waiting on it - Err(_) => return //cant have timed out thus program should exit + Ok(_) => break, //alarms were added or remove, go back and start waiting on it + Err(_) => return, //cant have timed out thus program should exit } } } @@ -78,7 +80,8 @@ impl Alarms { pub fn setup(event_tx: crossbeam_channel::Sender, db: sled::Db) -> Result<(Self, thread::JoinHandle<()>), Error> { - let alarm_db = AlarmList { db: db.open_tree("alarms")? }; + let mut alarm_db = AlarmList { db: db.open_tree("alarms")? }; + alarm_db.remove_old(); let (waker_tx, waker_rx) = crossbeam_channel::unbounded(); let waker_db_copy = alarm_db.clone(); @@ -89,10 +92,8 @@ impl Alarms { // we decrease the time till the alarm until there is a place in the database // as only one alarm can fire at the time, after an alarm gets a timeslot it is never changed - pub fn add_alarm(&self, at_time: DateTime) -> Result<(), Error> { - let mut timestamp = at_time.timestamp(); - - self.alarm_db.add_alarm(at_time); + pub fn add_alarm(&self, at_time: DateTime) -> Result<(), Error> { + self.alarm_db.add_alarm(at_time)?; //signal waker to update its next alarm self.waker_tx.send(())?; Ok(()) @@ -105,21 +106,30 @@ impl Alarms { pub fn list(&self) -> Vec> { //self.alarm_list.iter().keys().map(|k| DateTime::::from_utc(NaiveDateTime::from_timestamp(k, 0), Utc);) - Vec::new() //TODO placeholder + let start: &[u8] = &[0]; + let alarms = self.alarm_db.db.range(start..); + + let mut list = Vec::new(); //TODO placeholder + for (timestamp, _events) in alarms.filter_map(Result::ok) { + let timestamp = BigEndian::read_u64(×tamp) as i64; + let alarm = DateTime::::from_utc(NaiveDateTime::from_timestamp(timestamp, 0), Utc); + list.push(alarm); + } + list } } impl AlarmList { // we decrease the time till the alarm until there is a place in the database // as only one alarm can fire at the time, after an alarm gets a timeslot it is never changed - pub fn add_alarm(&self, at_time: DateTime) -> Result<(), Error> { + fn add_alarm(&self, at_time: DateTime) -> Result<(), Error> { let mut timestamp = at_time.timestamp() as u64; let mut timestamp_array = timestamp.to_be_bytes(); //create alarm entry if there is no alarm at this timestamp yet //if there is already an alarm schedualed, postpone this one until there is a spot free //self.db.cas(&[1], None as Option<&[u8]>, Some(&[10]) - while let Err(old_event) = self.db.cas(×tamp_array, None as Option<&[u8]>, Some(&[0]))? {//cas unique creation + while let Err(_old_event) = self.db.cas(×tamp_array, None as Option<&[u8]>, Some(&[0]))? {//cas unique creation timestamp -= 1; timestamp_array = timestamp.to_be_bytes(); } @@ -131,9 +141,20 @@ impl AlarmList { Ok(()) } + fn remove_old(&mut self) -> Result<(), Error> { + let now = Utc::now(); + let timestamp = now.timestamp() as u64; + let mut timestamp_array = timestamp.to_be_bytes(); + for old_alarm in self.db.range(..timestamp_array).keys() { + if let Ok(old_alarm) = old_alarm { + self.db.del(old_alarm)?; + } + } + Ok(()) + } /// calculate time to the earliest alarm, remove it from the list if the current time is later /// then the alarm - fn get_next_alarm(&mut self) -> Option> { + fn get_next(&mut self) -> Option> { let now = Utc::now(); //the greater then is applied to the integer representation @@ -142,8 +163,8 @@ impl AlarmList { Ok(entry) => { if let Some(entry) = entry { let (timestamp, action) = entry; - let timestamp = BigEndian::read_u64(×tamp); - let alarm = DateTime::::from_utc(NaiveDateTime::from_timestamp(61, 0), Utc); + let timestamp = BigEndian::read_u64(×tamp) as i64; + let alarm = DateTime::::from_utc(NaiveDateTime::from_timestamp(timestamp, 0), Utc); Some(alarm) } else { None diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index 62852ba8..2ecc982d 100644 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -147,17 +147,23 @@ pub fn set_alarm_unix_timestamp((req, params): (HttpRequest, Form::from_utc(NaiveDateTime::from_timestamp(ts, 0), Utc); + dbg!(time); + dbg!(Utc::now()); + if time>Utc::now() { if req.state().alarms.add_alarm(time).is_ok() { dbg!(("done setting alarm")); HttpResponse::Ok().finish() } else { + dbg!(); make_error(&req, StatusCode::INTERNAL_SERVER_ERROR) } } else { + dbg!(); make_error(&req, StatusCode::UNPROCESSABLE_ENTITY) } } else { + dbg!(); make_error(&req, StatusCode::INTERNAL_SERVER_ERROR) } } @@ -169,6 +175,7 @@ pub fn list_alarms(req: &HttpRequest) -> HttpResponse { let mut list = String::with_capacity(alarms.len()*30); for alarm in alarms { list.push_str(&alarm.to_rfc2822()); + list.push_str("\n"); } dbg!(&list); HttpResponse::Ok().body(list) From be21d291184461293d25ff33820c0e5724f223d0 Mon Sep 17 00:00:00 2001 From: David Kleingeld Date: Tue, 28 May 2019 01:20:13 +0200 Subject: [PATCH 008/687] finished wakeup state light control --- src/controller/commands.rs | 1 - src/controller/mod.rs | 10 +++---- src/controller/states/normal.rs | 4 +-- src/controller/states/wakeup.rs | 45 +++++++++++++++++++++++++++++++ src/controller/system/computer.rs | 5 ++++ src/input/alarms.rs | 12 +++------ src/input/web_api/mod.rs | 2 +- 7 files changed, 62 insertions(+), 17 deletions(-) create mode 100644 src/controller/states/wakeup.rs create mode 100644 src/controller/system/computer.rs diff --git a/src/controller/commands.rs b/src/controller/commands.rs index 4cd02c3c..8f040815 100644 --- a/src/controller/commands.rs +++ b/src/controller/commands.rs @@ -1,6 +1,5 @@ use super::{ActiveState, Modifications, System}; use crate::controller::states::*; -use crate::controller::states::RoomState; #[derive(Copy, Clone)] pub enum Command { diff --git a/src/controller/mod.rs b/src/controller/mod.rs index add83f7b..f299b45e 100644 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -82,16 +82,16 @@ pub fn start(rx: crossbeam_channel::Receiver) -> Result {dbg!("a test happend while in normal state"); ActiveState::Normal(state)}, - //general code that is the same for all functions, unless specific handlers exist above + //general code that is the same for all functions, unless specific handlers exist above (Event::Command(cmd), state) => {handle_cmd(cmd, state, &mut mods, &mut system)}, (Event::Update, state) => {state.update(&mut mods, &mut system)}, - (Event::Alarm, state) => {dbg!("ALARM ALARM"); info!("Alarm went off"); state}, - (Event::Test, state) => {dbg!("a test happend"); change_state(TargetState::WakeUp, &mut mods, &mut system)}, + (Event::Alarm, _) => {change_state(TargetState::WakeUp, &mut mods, &mut system)}, + (Event::Test, _) => {dbg!("a test happend"); change_state(TargetState::WakeUp, &mut mods, &mut system)}, - (Event::Stop, _) => return (), + (Event::Stop, _) => return (), }; } }); diff --git a/src/controller/states/normal.rs b/src/controller/states/normal.rs index cd2b75b6..6a55c368 100644 --- a/src/controller/states/normal.rs +++ b/src/controller/states/normal.rs @@ -7,11 +7,11 @@ use std::time::{Duration, Instant}; pub struct Normal {} impl RoomState for Normal { - fn update(self, mods: &mut Modifications, sys: &mut System) -> ActiveState { + fn update(self, _mods: &mut Modifications, _sys: &mut System) -> ActiveState { //dbg!("updating normal state"); ActiveState::Normal(self) } - fn enter(mods: &mut Modifications, sys: &mut System) -> Self { + fn enter(_mods: &mut Modifications, sys: &mut System) -> Self { dbg!("making everything rdy for the normal state"); sys.update_period = Duration::from_secs(5); sys.next_update = Instant::now()+sys.update_period; diff --git a/src/controller/states/wakeup.rs b/src/controller/states/wakeup.rs new file mode 100644 index 00000000..fc6ea648 --- /dev/null +++ b/src/controller/states/wakeup.rs @@ -0,0 +1,45 @@ +use super::super::{Modifications, System}; +use super::{RoomState, ActiveState}; +use super::Normal; + +use std::time::{Duration, Instant}; + +const WAKEUP_DURATION: u64 = 600; //in seconds +const BRI_PER_SECOND: f32 = 254./(WAKEUP_DURATION as f32); //in seconds + +const CT_BEGIN: u16 = 500; const CT_END: u16 = 280; +const CT_PER_SECOND: f32 = ((CT_BEGIN-CT_END) as f32)/(WAKEUP_DURATION as f32); +const UPDATE_PERIOD: u64 = 5; + +#[derive(Clone, Copy)] +pub struct WakeUp { + start: Instant, +} + +impl RoomState for WakeUp { + fn update(self, mods: &mut Modifications, sys: &mut System) -> ActiveState { + //dbg!("updating normal state"); + let elapsed = self.start.elapsed().as_secs(); + + if elapsed > WAKEUP_DURATION { + sys.lights.set_all_to(254, CT_END).unwrap(); + ActiveState::Normal(Normal::enter(mods, sys)) + } else { + let bri = (BRI_PER_SECOND*(elapsed as f32)) as u8; + let ct = CT_BEGIN-(CT_PER_SECOND*(elapsed as f32)) as u16; + + sys.lights.set_all_to(bri, ct).unwrap(); + + ActiveState::WakeUp(self) + } + } + + fn enter(_mods: &mut Modifications, sys: &mut System) -> Self { + dbg!("starting wakeup state"); + sys.update_period = Duration::from_secs(UPDATE_PERIOD); + sys.next_update = Instant::now()+sys.update_period; + + sys.lights.set_all_to(0, CT_BEGIN).unwrap(); + Self{start: Instant::now()} + } +} diff --git a/src/controller/system/computer.rs b/src/controller/system/computer.rs new file mode 100644 index 00000000..20df2e15 --- /dev/null +++ b/src/controller/system/computer.rs @@ -0,0 +1,5 @@ + +//thread that keeps an open conn to ssh server on pc? using ssh2 lib +//allows rbtw to execute on linux +//alows shutdown keyboard commands on windows via arduino keyboard +//allows boot pc via pc header pin pulse \ No newline at end of file diff --git a/src/input/alarms.rs b/src/input/alarms.rs index c6893394..a2c64beb 100644 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -1,12 +1,8 @@ -use std::collections::BTreeSet; -use std::path::Path; - use crossbeam_channel; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc}; use std::thread; use chrono::{DateTime, NaiveDateTime, Utc}; -use std::fs::{File, OpenOptions}; use sled; use byteorder::{ByteOrder, BigEndian}; @@ -144,7 +140,7 @@ impl AlarmList { fn remove_old(&mut self) -> Result<(), Error> { let now = Utc::now(); let timestamp = now.timestamp() as u64; - let mut timestamp_array = timestamp.to_be_bytes(); + let timestamp_array = timestamp.to_be_bytes(); for old_alarm in self.db.range(..timestamp_array).keys() { if let Ok(old_alarm) = old_alarm { self.db.del(old_alarm)?; @@ -162,7 +158,7 @@ impl AlarmList { match self.db.get_gt(timestamp.to_be_bytes()) { Ok(entry) => { if let Some(entry) = entry { - let (timestamp, action) = entry; + let (timestamp, _action) = entry; let timestamp = BigEndian::read_u64(×tamp) as i64; let alarm = DateTime::::from_utc(NaiveDateTime::from_timestamp(timestamp, 0), Utc); Some(alarm) @@ -171,7 +167,7 @@ impl AlarmList { } }, Err(error) => { - error!("Could not retrieve next alarm"); + error!("Could not retrieve next alarm: {:?}",error); None } } diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index 2ecc982d..28cdbaa2 100644 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -39,7 +39,7 @@ fn make_auth_error(req: &HttpRequest) -> HttpResponse { .finish() } -fn make_error(req: &HttpRequest, header: StatusCode) -> HttpResponse { +fn make_error(req: &HttpRequest, _header: StatusCode) -> HttpResponse { req.build_response(StatusCode::INTERNAL_SERVER_ERROR) .finish() } From 4aa9a31b09c69b2038b1add3bc90201bdb01cd66 Mon Sep 17 00:00:00 2001 From: David Kleingeld Date: Thu, 13 Jun 2019 00:27:32 +0200 Subject: [PATCH 009/687] moves youtube downloader to input --- src/input/youtube_downloader.rs | 70 +++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/input/youtube_downloader.rs diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs new file mode 100644 index 00000000..a9e611e1 --- /dev/null +++ b/src/input/youtube_downloader.rs @@ -0,0 +1,70 @@ +use std::process::Command; +use std::io::copy; +use std::fs; +use std::time::Duration; +use std::sync::{Arc, Mutex, Condvar} + +use std::path::Path; +use reqwest::{IntoUrl, get}; + +use crate::errors::Error; + +fn download_file(url: U, save_path: &Path) -> Result<(), Error> { + let mut response = reqwest::get(url)?; + let mut dest = fs::File::create(save_path)?; + copy(&mut response, &mut dest)?; + Ok(()) +} + +#[derive(Clone)] +pub struct YoutubeDownloader { + guard: Arc<(Mutex, Condvar)>, +} + +impl YoutubeDownloader { + pub fn init() -> Result{ + let dir_path = Path::new("temp"); + let full_path = Path::new("temp/youtube-dl"); + + if !full_path.exists() { + if !dir_path.exists() { + fs::create_dir(dir_path)?; + } + + download_file("https://yt-dl.org/downloads/latest/youtube-dl", full_path)?; + } + Ok(Self {guard: Arc::new(Mutex::new(false), Condvar::new()) }) + } + + fn download(url: &str) -> Result<(), Error> { + let full_path = Path::new("temp/youtube-dl"); + let output = Command::new(full_path) + .arg("-F") + .arg(url) + .output()?; + + dbg!(output); + Ok(()) + } + + fn download_song_timeout(&mut self, url: &str, timeout: Duration) -> Result<(), Error> { + + let (free, waker) = self.guard.lock(x); + if !free.lock.unwrap() { + waker.wait_timeout(free, timeout) + } + + + let full_path = Path::new("temp/youtube-dl"); + let output = Command::new(full_path) + .arg("-F") + .arg(url) + .output()?; + + dbg!(output); + + waker.notify_one(); + Ok(()) + } + +} \ No newline at end of file From e7d8df451aa18b9517946ff7796e24235929bbbb Mon Sep 17 00:00:00 2001 From: David Kleingeld Date: Thu, 13 Jun 2019 13:31:07 +0200 Subject: [PATCH 010/687] rewrites youtube download to be nonblocking --- src/input/youtube_downloader.rs | 93 +++++++++++++++++++++------------ src/main.rs | 32 +++++++++--- 2 files changed, 85 insertions(+), 40 deletions(-) diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index a9e611e1..2c37c26d 100644 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -1,8 +1,12 @@ use std::process::Command; use std::io::copy; + use std::fs; +use std::os::unix::fs::OpenOptionsExt; + use std::time::Duration; -use std::sync::{Arc, Mutex, Condvar} +use std::thread; +use crossbeam_channel::{unbounded, Receiver, Sender}; use std::path::Path; use reqwest::{IntoUrl, get}; @@ -10,19 +14,57 @@ use reqwest::{IntoUrl, get}; use crate::errors::Error; fn download_file(url: U, save_path: &Path) -> Result<(), Error> { - let mut response = reqwest::get(url)?; - let mut dest = fs::File::create(save_path)?; + + let mut dest = fs::OpenOptions::new() + .create(true) + .write(true) + .mode(0o770) + .open(save_path)?; + + let mut response = reqwest::get(url)?; copy(&mut response, &mut dest)?; + Ok(()) } #[derive(Clone)] pub struct YoutubeDownloader { - guard: Arc<(Mutex, Condvar)>, + url_tx: crossbeam_channel::Sender, +} + +fn download_song(url: &str) -> Result<(), Error> { + let full_path = Path::new("temp/youtube-dl"); + let output = Command::new(full_path) + .arg("--format") + .arg("bestaudio/best") + .arg("--extract-audio") + //.arg("--embed-thumbnail") + .arg(url) + .output()?; + + dbg!(output); + Ok(()) } +fn song_downloader(url_rx: crossbeam_channel::Receiver) { + loop { + match url_rx.recv() { + Ok(url) => { + dbg!(&url); + match download_song(&url) { + Ok(_) => dbg!(), + Err(error) => error!("error during song download: {:?}", error), + }; + }, + // return without url means YoutubeDownloader was dropped and we should stop + Err(_) => return, + } + } +} + + impl YoutubeDownloader { - pub fn init() -> Result{ + pub fn init() -> Result<(Self, thread::JoinHandle<()>), Error>{ let dir_path = Path::new("temp"); let full_path = Path::new("temp/youtube-dl"); @@ -30,41 +72,28 @@ impl YoutubeDownloader { if !dir_path.exists() { fs::create_dir(dir_path)?; } - download_file("https://yt-dl.org/downloads/latest/youtube-dl", full_path)?; } - Ok(Self {guard: Arc::new(Mutex::new(false), Condvar::new()) }) - } - fn download(url: &str) -> Result<(), Error> { - let full_path = Path::new("temp/youtube-dl"); - let output = Command::new(full_path) - .arg("-F") - .arg(url) - .output()?; + let (url_tx, url_rx) = crossbeam_channel::bounded(10); + let downloader_thread = thread::spawn(move || song_downloader(url_rx) ); - dbg!(output); - Ok(()) + Ok((Self {url_tx}, downloader_thread)) } - fn download_song_timeout(&mut self, url: &str, timeout: Duration) -> Result<(), Error> { + //TODO use youtube downloader to stream audio from youtube!!! + + /// checks if a song can be downloaded, if so sends the command to start download to + /// a seperate thread + pub fn add_song_to_queue(&self, url: String) -> Result<(), ()> { - let (free, waker) = self.guard.lock(x); - if !free.lock.unwrap() { - waker.wait_timeout(free, timeout) + if self.url_tx.try_send(url).is_err(){ + error!("could not add song to downlaod list"); + Err(()) + } else { + dbg!(); + Ok(()) } - - - let full_path = Path::new("temp/youtube-dl"); - let output = Command::new(full_path) - .arg("-F") - .arg(url) - .output()?; - - dbg!(output); - - waker.notify_one(); - Ok(()) } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 813ad22d..ee1dccc0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,6 +37,7 @@ pub struct ServerState { controller_addr: crossbeam_channel::Sender, alarms: input::alarms::Alarms, dataserver_state: DataServerState, + youtube_dl: input::YoutubeDownloader, } impl InnerState for ServerState { @@ -47,12 +48,14 @@ impl InnerState for ServerState { const FORCE_CERT_REGEN: bool = false; -pub fn start(signed_cert: &str, private_key: &str, +pub fn start_webserver(signed_cert: &str, private_key: &str, data: Arc>, passw_db: Arc>, sessions: Arc>>, controller_tx: crossbeam_channel::Sender, - alarms: input::alarms::Alarms) -> (DataRouterHandle, ServerHandle) { + alarms: input::alarms::Alarms, + youtube_dl: input::YoutubeDownloader, + ) -> (DataRouterHandle, ServerHandle) { let tls_config = httpserver::make_tls_config(signed_cert, private_key); let cookie_key = httpserver::make_random_cookie_key(); @@ -81,6 +84,7 @@ pub fn start(signed_cert: &str, private_key: &str, controller_addr: controller_tx.clone(), alarms: alarms.clone(), dataserver_state, + youtube_dl: youtube_dl.clone(), }; App::with_state(state) @@ -106,7 +110,9 @@ pub fn start(signed_cert: &str, private_key: &str, .resource(r"/commands/lightLoop", |r| r.method(Method::GET).f(web_api::lightloop)) - .resource(r"/commands/set/wakeup_alarm", |r| r.method(Method::POST).with(web_api::set_alarm_minutes_from_now)) + //currently not used + //.resource(r"/commands/set/wakeup_alarm", |r| r.method(Method::POST).with(web_api::set_alarm_minutes_from_now)) + // websocket route // note some browsers need already existing http connection to // this server for the upgrade to wss to work @@ -117,6 +123,7 @@ pub fn start(signed_cert: &str, private_key: &str, .resource("/plot", |r| r.f(plot_data)) .resource(r"/list_data.html", |r| r.method(Method::GET).f(list_data)) + .resource(r"/add_song", |r| r.method(Method::POST).with(web_api::add_song_from_url)) .resource(r"/set_alarm", |r| r.method(Method::POST).with(web_api::set_alarm_unix_timestamp)) .resource(r"/list_alarms", |r| r.method(Method::GET).f(web_api::list_alarms)) @@ -130,7 +137,7 @@ pub fn start(signed_cert: &str, private_key: &str, .resource(r"/{tail:.*}", |r| r.f(serve_file)) }) .bind_rustls("0.0.0.0:8070", tls_config).unwrap() - //.bind("0.0.0.0:8070").unwrap() //without tcp use with debugging (note: https -> http, wss -> ws) + //.bind("0.0.0.0:8080").unwrap() //without tcp use with debugging (note: https -> http, wss -> ws) .shutdown_timeout(5) // shut down 5 seconds after getting the signal to shut down .start(); @@ -172,12 +179,21 @@ fn main() { let (controller_tx, controller_rx) = crossbeam_channel::unbounded(); let _controller_thread = controller::start(controller_rx).unwrap(); - input::attached_sensors::check_local_sensing_dataset(&dataset_handle).unwrap(); let (alarms, _waker_thread) = input::alarms::Alarms::setup(controller_tx.clone(), db.clone()).unwrap(); + let (youtube_dl, _downloader_thread) = input::YoutubeDownloader::init().unwrap(); + + //verify dataset integrity + input::attached_sensors::check_local_sensing_dataset(&dataset_handle).unwrap(); + + //start the webserver + let (data_router_handle, web_handle) = start_webserver("keys/cert.key", "keys/cert.cert", + dataset_handle.clone(), passw_db.clone(), sessions.clone(), + controller_tx.clone(), alarms.clone(), youtube_dl.clone()); - let (data_router_handle, web_handle) = //starts webserver - start("keys/cert.key", "keys/cert.cert", dataset_handle.clone(), passw_db.clone(), sessions.clone(), controller_tx.clone(), alarms.clone()); + //TODO start the telegram server + //TODO + //start monitoring local sensors #[cfg(feature = "sensors_connected")] input::attached_sensors::start_monitoring(controller_tx.clone(), data_router_handle, dataset_handle.clone()); @@ -197,5 +213,5 @@ fn main() { } println!("shutting down"); httpserver::stop(web_handle); - controller_tx.send(Event::Stop).unwrap(); + controller_tx.send(Event::Stop).unwrap(); //TODO cant we do this by dropping the mpsc? } From 6ef2ceb99d848a90c053a596dd9d418fddc99e59 Mon Sep 17 00:00:00 2001 From: David Kleingeld Date: Thu, 13 Jun 2019 13:36:22 +0200 Subject: [PATCH 011/687] adds missing files --- Cargo.lock | 31 +++++++++++++------- Cargo.toml | 3 +- src/controller/mod.rs | 13 +++++---- src/controller/states/wakeup.rs | 2 +- src/controller/system/lamps/mod.rs | 33 ++++++++++----------- src/controller/system/mod.rs | 4 ++- src/errors.rs | 21 ++++++++++++++ src/input/alarms.rs | 1 + src/input/mod.rs | 5 +++- src/input/web_api/mod.rs | 20 +++++++++++++ web/add_song.html | 46 ++++++++++++++++++++++++++++++ 11 files changed, 143 insertions(+), 36 deletions(-) create mode 100644 web/add_song.html diff --git a/Cargo.lock b/Cargo.lock index 176f9f31..f45949f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,6 +18,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "philipshue 0.3.2 (git+https://github.com/dskleingeld/philipshue)", + "reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", "sled 0.24.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -40,7 +41,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.22 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.16 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", @@ -428,19 +429,26 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cookie" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cookie_store" -version = "0.5.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -576,7 +584,7 @@ dependencies = [ "minimal_timeseries 0.1.1 (git+https://github.com/dskleingeld/minimal_timeseries?branch=multithraeded_file_read)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.16 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1780,13 +1788,13 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.9.16" +version = "0.9.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie_store 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2787,7 +2795,8 @@ dependencies = [ "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cdb90b60f2927f8d76139c72dbde7e10c3a2bc47c8594c9c7a66529f2687c03" "checksum cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "99be24cfcf40d56ed37fd11c2123be833959bbc5bddecb46e1c2e442e15fa3e0" -"checksum cookie_store 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b0d2f2ecb21dce00e2453268370312978af9b8024020c7a37ae2cc6dbbe64685" +"checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" +"checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" @@ -2933,7 +2942,7 @@ dependencies = [ "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" "checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum reqwest 0.9.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddcfd2c13c6af0f9c45a1086be3b9c68af79e4430b42790759e2d34cce2a6c60" +"checksum reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "e57803405f8ea0eb041c1567dac36127e0c8caa1251c843cb03d43fd767b3d50" "checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" "checksum rgb 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)" = "4f089652ca87f5a82a62935ec6172a534066c7b97be003cc8f702ee9a7a59c92" "checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a" diff --git a/Cargo.toml b/Cargo.toml index 356b46d6..2b1b6427 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,4 +45,5 @@ byteorder = "1.3.1" crossbeam-channel = "0.3" sled = "0.24.1" -pagecache = "0.17.0" \ No newline at end of file +pagecache = "0.17.0" +reqwest = "0.9.17" \ No newline at end of file diff --git a/src/controller/mod.rs b/src/controller/mod.rs index f299b45e..17274efa 100644 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -2,7 +2,7 @@ use std::time::{Duration, Instant}; use std::thread; mod system; -use system::lamps::Lighting; +use system::{Lighting}; mod states; use states::{ActiveState, RoomState, change_state}; @@ -12,6 +12,8 @@ use commands::{handle_cmd}; pub use commands::Command; pub use states::TargetState; +use crate::errors::Error; + pub enum Event { Update, Alarm, @@ -39,6 +41,7 @@ pub struct System { lights: Lighting, //mpd + //etc } @@ -51,7 +54,7 @@ fn saturating_duration_till(target: std::time::Instant) -> std::time::Duration{ } } -pub fn start(rx: crossbeam_channel::Receiver) -> Result,()>{ +pub fn start(rx: crossbeam_channel::Receiver) -> Result, Error>{ let mut system = System { update_period: Duration::from_secs(5), @@ -83,11 +86,11 @@ pub fn start(rx: crossbeam_channel::Receiver) -> Result {dbg!("a test happend while in normal state"); ActiveState::Normal(state)}, + (Event::Test, ActiveState::Normal(state)) => {dbg!("a test happend while in normal state"); ActiveState::Normal(state)}, //general code that is the same for all functions, unless specific handlers exist above - (Event::Command(cmd), state) => {handle_cmd(cmd, state, &mut mods, &mut system)}, - (Event::Update, state) => {state.update(&mut mods, &mut system)}, + (Event::Command(cmd), state) => {handle_cmd(cmd, state, &mut mods, &mut system)}, + (Event::Update, state) => {state.update(&mut mods, &mut system)}, (Event::Alarm, _) => {change_state(TargetState::WakeUp, &mut mods, &mut system)}, (Event::Test, _) => {dbg!("a test happend"); change_state(TargetState::WakeUp, &mut mods, &mut system)}, diff --git a/src/controller/states/wakeup.rs b/src/controller/states/wakeup.rs index fc6ea648..73933b9f 100644 --- a/src/controller/states/wakeup.rs +++ b/src/controller/states/wakeup.rs @@ -4,7 +4,7 @@ use super::Normal; use std::time::{Duration, Instant}; -const WAKEUP_DURATION: u64 = 600; //in seconds +const WAKEUP_DURATION: u64 = 900; //in seconds const BRI_PER_SECOND: f32 = 254./(WAKEUP_DURATION as f32); //in seconds const CT_BEGIN: u16 = 500; const CT_END: u16 = 280; diff --git a/src/controller/system/lamps/mod.rs b/src/controller/system/lamps/mod.rs index 2ac7bb68..f6f8f841 100644 --- a/src/controller/system/lamps/mod.rs +++ b/src/controller/system/lamps/mod.rs @@ -11,6 +11,7 @@ use std::time::Duration; use std::fs::File; use std::path::Path; use std::collections::{HashMap, BTreeMap}; +use crate::errors::Error; fn register(ip: &str) -> Result{ for _ in 0..5 {//try 5 times to connect @@ -33,11 +34,11 @@ fn register(ip: &str) -> Result{ return Err(()); } -fn find_bridge_ip() -> Result { - let mut discovered = bridge::discover().unwrap(); +fn find_bridge_ip() -> Result { + let mut discovered = bridge::discover()?; if discovered.len() == 0 { error!("No bridge found!"); - return Err(()); + return Err(Error::Lamps(HueError::from_kind(HueErrorKind::Msg("no bridge found".into())))); } else if discovered.len() > 1 { error!("Found multiple hue bridges: {:?}, continueing with first one in list", discovered); } @@ -72,7 +73,7 @@ fn update_saved_bridge_info(bridge_ip: &str, login: &str) -> Result<(), ()> { Err(()) } -fn get_bridge_and_status() -> Result<(Bridge, BTreeMap),()> { +fn get_bridge_and_status() -> Result<(Bridge, BTreeMap), Error> { if let Ok((mut ip, mut login)) = saved_bridge_info(){ let mut update_ip_or_login = false; @@ -89,29 +90,29 @@ fn get_bridge_and_status() -> Result<(Bridge, BTreeMap { - ip = find_bridge_ip().map_err(|_| ())?; + ip = find_bridge_ip()?; update_ip_or_login = true; }, //cant register as button was not pressed in time Err(HueError(HueErrorKind::BridgeError{error: LinkButtonNotPressed, ..}, _)) => { - login = register(&ip).map_err(|_| ())?; + login = register(&ip)?; update_ip_or_login = true; }, Err(e) => { error!("Unexpected error occured: {:?}", e); - return Err(()); + return Err(e.into()); }, } } } else { - let ip = find_bridge_ip().map_err(|_| ())?; - let login = register(&ip).map_err(|_| ())?; + let ip = find_bridge_ip()?; + let login = register(&ip)?; if update_saved_bridge_info(&ip, &login).is_err() { error!("Could not save new bridge ip and login, next run will fail without user intervention") }; let bridge = Bridge::new(&ip, &login); - let lights_info = bridge.get_all_lights().map_err(|_| ())?; + let lights_info = bridge.get_all_lights()?; return Ok((bridge, lights_info)); } } @@ -150,7 +151,7 @@ impl From<&philipshue::hue::LightState> for Lamp{ impl Lighting { - pub fn init() -> Result { + pub fn init() -> Result { let (bridge, lights_info) = get_bridge_and_status()?; let lamps: HashMap = lights_info.iter().map(|(id,light)| (*id, Lamp::from(&light.state))).collect(); @@ -158,18 +159,18 @@ impl Lighting { } //how to deal with errors? - pub fn toggle(&mut self) -> Result<(),()>{ + pub fn toggle(&mut self) -> Result<(),Error>{ let numb_on: u8 = self.lamps.values().map(|lamp| lamp.on as u8).sum(); let numb_off = self.lamps.len() as u8 - numb_on; //group ID 0 is a special group containing all lights known to the bridge if numb_on > numb_off { let command = LightCommand::off(LightCommand::default() ); - self.bridge.set_group_state(0, &command).map_err(|_| ())?; + self.bridge.set_group_state(0, &command)?; self.lamps.values_mut().for_each(|lamp| lamp.on = false); } else { let command = LightCommand::on(LightCommand::default() ); - self.bridge.set_group_state(0, &command).map_err(|_| ())?; + self.bridge.set_group_state(0, &command)?; self.lamps.values_mut().for_each(|lamp| lamp.on = true); } @@ -177,12 +178,12 @@ impl Lighting { } //how to deal with errors? - pub fn set_all_to(&mut self, bri: u8, ct: u16) -> Result<(),()>{ + pub fn set_all_to(&mut self, bri: u8, ct: u16) -> Result<(),Error>{ let command = LightCommand::default(); let command = command.on(); let command = command.with_bri(bri); let command = command.with_ct(ct); - self.bridge.set_group_state(0, &command).map_err(|_| ())?; + self.bridge.set_group_state(0, &command)?; self.lamps.values_mut().for_each(|lamp| {lamp.bri =bri; lamp.ct =Some(ct); lamp.on =true}); Ok(()) diff --git a/src/controller/system/mod.rs b/src/controller/system/mod.rs index 14789e7e..cb016568 100644 --- a/src/controller/system/mod.rs +++ b/src/controller/system/mod.rs @@ -1 +1,3 @@ -pub mod lamps; \ No newline at end of file +mod lamps; + +pub use lamps::Lighting; \ No newline at end of file diff --git a/src/errors.rs b/src/errors.rs index e2341ed9..2ed047d5 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -7,6 +7,9 @@ pub enum Error { YamlParsing(serde_yaml::Error), Channel(crossbeam_channel::SendError<()>), DataBase(sled::Error), + Download(reqwest::Error), + Lamps(philipshue::errors::HueError), + UnTracked, } impl From for Error { @@ -32,6 +35,12 @@ impl From> for Error { } } +impl From for Error { + fn from(error: reqwest::Error) -> Self { + Error::Download(error) + } +} + //impl From for Error { // fn from(error: crossbeam_channel::SendError<()>) -> Self { // Error::Channel(error) @@ -44,6 +53,18 @@ impl From for Error { } } +impl From<()> for Error { + fn from(_error: ()) -> Self { + Error::UnTracked + } +} + +impl From for Error { + fn from(error: philipshue::errors::HueError) -> Self { + Error::Lamps(error) + } +} + /*impl fmt::Debug for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { dbg!(("heee")); diff --git a/src/input/alarms.rs b/src/input/alarms.rs index a2c64beb..8c1356d3 100644 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -125,6 +125,7 @@ impl AlarmList { //create alarm entry if there is no alarm at this timestamp yet //if there is already an alarm schedualed, postpone this one until there is a spot free //self.db.cas(&[1], None as Option<&[u8]>, Some(&[10]) + //TODO check how this works and expand sled documentation for fail cases while let Err(_old_event) = self.db.cas(×tamp_array, None as Option<&[u8]>, Some(&[0]))? {//cas unique creation timestamp -= 1; timestamp_array = timestamp.to_be_bytes(); diff --git a/src/input/mod.rs b/src/input/mod.rs index 17d7caff..1dad2432 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -1,3 +1,6 @@ pub mod web_api; pub mod attached_sensors; -pub mod alarms; \ No newline at end of file +pub mod alarms; +pub mod youtube_downloader; + +pub use youtube_downloader::YoutubeDownloader; \ No newline at end of file diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index 28cdbaa2..1000df69 100644 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -179,4 +179,24 @@ pub fn list_alarms(req: &HttpRequest) -> HttpResponse { } dbg!(&list); HttpResponse::Ok().body(list) +} + +//////////////////////// control mpd ///////////////////////////////// + +#[derive(Deserialize, Debug)] +pub struct SongUrl { + url: String, +} + + +pub fn add_song_from_url((req, params): (HttpRequest, Form)) -> HttpResponse { + let url = params.into_inner().url; + dbg!(); + + if req.state().youtube_dl.add_song_to_queue(url).is_ok(){ + dbg!(); + HttpResponse::Ok().finish() + } else { + make_error(&req, StatusCode::INTERNAL_SERVER_ERROR) + } } \ No newline at end of file diff --git a/web/add_song.html b/web/add_song.html new file mode 100644 index 00000000..d8010816 --- /dev/null +++ b/web/add_song.html @@ -0,0 +1,46 @@ + + + + + + + + + + + + \ No newline at end of file From 2b95e5c46badc139f5d9c2474c1b010f22a61489 Mon Sep 17 00:00:00 2001 From: David Kleingeld Date: Fri, 14 Jun 2019 23:18:22 +0200 Subject: [PATCH 012/687] adds mpdwatcher to startup, sets output dir for youtube_dl --- Cargo.lock | 91 +++++++++++++++++++++++++++++++++ Cargo.toml | 5 +- src/controller/mod.rs | 10 ++-- src/controller/system/mod.rs | 1 - src/errors.rs | 7 +++ src/input/mod.rs | 4 +- src/input/web_api/mod.rs | 2 +- src/input/youtube_downloader.rs | 17 +++++- src/main.rs | 8 +-- 9 files changed, 131 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f45949f1..2354107a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,11 @@ dependencies = [ "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "dataserver 0.1.0 (git+https://github.com/dskleingeld/dataserver)", + "dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "linux-embedded-hal 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mpd 0.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "philipshue 0.3.2 (git+https://github.com/dskleingeld/philipshue)", "reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -219,6 +221,15 @@ name = "arc-swap" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "argon2rs" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "arrayvec" version = "0.4.10" @@ -306,6 +317,15 @@ name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bme280" version = "0.1.1" @@ -332,6 +352,11 @@ dependencies = [ "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bufstream" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "build_const" version = "0.2.1" @@ -418,6 +443,11 @@ dependencies = [ "winconsole 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "constant_time_eq" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cookie" version = "0.11.1" @@ -599,6 +629,26 @@ dependencies = [ "webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dirs" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dirs-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "dtoa" version = "0.4.4" @@ -1222,6 +1272,16 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mpd" +version = "0.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "native-tls" version = "0.2.3" @@ -1738,6 +1798,17 @@ dependencies = [ "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "redox_users" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "regex" version = "0.2.11" @@ -1848,6 +1919,11 @@ name = "rustc-demangle" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc_version" version = "0.1.7" @@ -1917,6 +1993,11 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "scoped_threadpool" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "scopeguard" version = "0.3.3" @@ -2769,6 +2850,7 @@ dependencies = [ "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08abcc3b4e9339e33a3d0a5ed15d84a687350c05689d825e0f6655eef9e76a94" "checksum arc-swap 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "bc4662175ead9cd84451d5c35070517777949a2ed84551764129cedb88384841" +"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" @@ -2780,9 +2862,11 @@ dependencies = [ "checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "checksum bme280 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d168c341491c9ba4e2c73d59470c108a5961377c67061dc1796a193fa945b452" "checksum brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" "checksum brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" +"checksum bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" @@ -2794,6 +2878,7 @@ dependencies = [ "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cdb90b60f2927f8d76139c72dbde7e10c3a2bc47c8594c9c7a66529f2687c03" +"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "99be24cfcf40d56ed37fd11c2123be833959bbc5bddecb46e1c2e442e15fa3e0" "checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" "checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" @@ -2810,6 +2895,8 @@ dependencies = [ "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum dataserver 0.1.0 (git+https://github.com/dskleingeld/dataserver)" = "" +"checksum dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4ef5a8b902d393339e2a2c7fe573af92ce7e0ee5a3ff827b4c9ad7e07e4fa1" +"checksum dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "937756392ec77d1f2dd9dc3ac9d69867d109a2121479d72c364e42f4cab21e2d" "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" "checksum embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ee4908a155094da7723c2d60d617b820061e3b4efcc3d9e293d206a5a76c170b" @@ -2882,6 +2969,7 @@ dependencies = [ "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum mpd 0.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "57a20784da57fa01bf7910a5da686d9f39ff37feaa774856b71f050e4331bf82" "checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b1411551beb3c11dedfb0a90a0fa256b47d28b9ec2cdff34c25a2fa59e45dbdc" "checksum ndarray 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7cf380a8af901ad627594013a3bbac903ae0a6f94e176e47e46b5bbc1877b928" @@ -2937,6 +3025,7 @@ dependencies = [ "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" "checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" "checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" @@ -2947,6 +3036,7 @@ dependencies = [ "checksum rgb 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)" = "4f089652ca87f5a82a62935ec6172a534066c7b97be003cc8f702ee9a7a59c92" "checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a" "checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "942b71057b31981152970d57399c25f72e27a6ee0d207a669d8304cabf44705b" @@ -2955,6 +3045,7 @@ dependencies = [ "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" +"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum sct 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb8f61f9e6eadd062a71c380043d28036304a4706b3c4dd001ff3387ed00745a" "checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" diff --git a/Cargo.toml b/Cargo.toml index 2b1b6427..02face67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,4 +46,7 @@ crossbeam-channel = "0.3" sled = "0.24.1" pagecache = "0.17.0" -reqwest = "0.9.17" \ No newline at end of file +reqwest = "0.9.17" + +mpd = "0.0.12" +dirs = "2.0.1" \ No newline at end of file diff --git a/src/controller/mod.rs b/src/controller/mod.rs index 17274efa..98d17cd9 100644 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -12,6 +12,7 @@ use commands::{handle_cmd}; pub use commands::Command; pub use states::TargetState; +use crate::input; use crate::errors::Error; pub enum Event { @@ -19,7 +20,6 @@ pub enum Event { Alarm, Test, Command(Command), - Stop, } pub struct Modifications { //change name to: alteration, deviation, overrides or something else? @@ -73,7 +73,7 @@ pub fn start(rx: crossbeam_channel::Receiver) -> Result event, Err(error) => match error { crossbeam_channel::RecvTimeoutError::Timeout => { @@ -91,10 +91,8 @@ pub fn start(rx: crossbeam_channel::Receiver) -> Result {handle_cmd(cmd, state, &mut mods, &mut system)}, (Event::Update, state) => {state.update(&mut mods, &mut system)}, - (Event::Alarm, _) => {change_state(TargetState::WakeUp, &mut mods, &mut system)}, - (Event::Test, _) => {dbg!("a test happend"); change_state(TargetState::WakeUp, &mut mods, &mut system)}, - - (Event::Stop, _) => return (), + (Event::Alarm, _) => {change_state(TargetState::WakeUp, &mut mods, &mut system)}, + (Event::Test, _) => {dbg!("a test happend"); change_state(TargetState::WakeUp, &mut mods, &mut system)}, }; } }); diff --git a/src/controller/system/mod.rs b/src/controller/system/mod.rs index cb016568..11225707 100644 --- a/src/controller/system/mod.rs +++ b/src/controller/system/mod.rs @@ -1,3 +1,2 @@ mod lamps; - pub use lamps::Lighting; \ No newline at end of file diff --git a/src/errors.rs b/src/errors.rs index 2ed047d5..c0fe60bf 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -9,6 +9,7 @@ pub enum Error { DataBase(sled::Error), Download(reqwest::Error), Lamps(philipshue::errors::HueError), + Mpd(mpd::error::Error), UnTracked, } @@ -65,6 +66,12 @@ impl From for Error { } } +impl From for Error { + fn from(error: mpd::error::Error) -> Self { + Error::Mpd(error) + } +} + /*impl fmt::Debug for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { dbg!(("heee")); diff --git a/src/input/mod.rs b/src/input/mod.rs index 1dad2432..4a83b1e0 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -2,5 +2,7 @@ pub mod web_api; pub mod attached_sensors; pub mod alarms; pub mod youtube_downloader; +mod mpd_status; -pub use youtube_downloader::YoutubeDownloader; \ No newline at end of file +pub use youtube_downloader::YoutubeDownloader; +pub use mpd_status::MpdStatus; \ No newline at end of file diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index 1000df69..a8942d02 100644 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -188,13 +188,13 @@ pub struct SongUrl { url: String, } - pub fn add_song_from_url((req, params): (HttpRequest, Form)) -> HttpResponse { let url = params.into_inner().url; dbg!(); if req.state().youtube_dl.add_song_to_queue(url).is_ok(){ dbg!(); + HttpResponse::Ok().finish() } else { make_error(&req, StatusCode::INTERNAL_SERVER_ERROR) diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index 2c37c26d..2acde63b 100644 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -33,16 +33,31 @@ pub struct YoutubeDownloader { } fn download_song(url: &str) -> Result<(), Error> { + let mut music_dir = dirs::home_dir().unwrap(); + music_dir.push("Music"); + let mut output_arg = String::from(music_dir.to_str().unwrap()); + output_arg.push_str("/%(title)s.%(ext)s"); + let full_path = Path::new("temp/youtube-dl"); let output = Command::new(full_path) .arg("--format") .arg("bestaudio/best") .arg("--extract-audio") + .arg("--output") + .arg(&output_arg) //.arg("--embed-thumbnail") .arg(url) .output()?; - dbg!(output); + dbg!(&output); + if output.status.success() { + + //TODO move to mpd music location + //send rescan command to mpd + } else { + dbg!("HANDLE ERROR"); + } + Ok(()) } diff --git a/src/main.rs b/src/main.rs index ee1dccc0..e490816b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,7 +55,8 @@ pub fn start_webserver(signed_cert: &str, private_key: &str, controller_tx: crossbeam_channel::Sender, alarms: input::alarms::Alarms, youtube_dl: input::YoutubeDownloader, - ) -> (DataRouterHandle, ServerHandle) { + mpd_status: input::MpdStatus, + ) -> (DataRouterHandle, ServerHandle) { let tls_config = httpserver::make_tls_config(signed_cert, private_key); let cookie_key = httpserver::make_random_cookie_key(); @@ -181,6 +182,7 @@ fn main() { let _controller_thread = controller::start(controller_rx).unwrap(); let (alarms, _waker_thread) = input::alarms::Alarms::setup(controller_tx.clone(), db.clone()).unwrap(); let (youtube_dl, _downloader_thread) = input::YoutubeDownloader::init().unwrap(); + let (mpd_status, _mpd_watcher_thread, updater_tx) = input::MpdStatus::start_updating().unwrap(); //verify dataset integrity input::attached_sensors::check_local_sensing_dataset(&dataset_handle).unwrap(); @@ -188,7 +190,7 @@ fn main() { //start the webserver let (data_router_handle, web_handle) = start_webserver("keys/cert.key", "keys/cert.cert", dataset_handle.clone(), passw_db.clone(), sessions.clone(), - controller_tx.clone(), alarms.clone(), youtube_dl.clone()); + controller_tx.clone(), alarms.clone(), youtube_dl.clone(), mpd_status.clone()); //TODO start the telegram server //TODO @@ -213,5 +215,5 @@ fn main() { } println!("shutting down"); httpserver::stop(web_handle); - controller_tx.send(Event::Stop).unwrap(); //TODO cant we do this by dropping the mpsc? + input::MpdStatus::stop_updating(updater_tx); } From f3f9bb66e878930cf7d581b5b9543e8b195ed5f6 Mon Sep 17 00:00:00 2001 From: David Kleingeld Date: Sat, 15 Jun 2019 12:48:41 +0200 Subject: [PATCH 013/687] adds puts socket address behind conditional compilation feature --- Cargo.toml | 3 ++- src/input/youtube_downloader.rs | 7 ++++--- src/main.rs | 9 ++++++++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 02face67..69caa9b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,12 +5,13 @@ authors = ["David Kleingeld "] edition = "2018" [features] -default = ["sensors_connected"] +default = [] # Enable code that expects sensor hardware to be present. Will stop execution # if hardware is not present, # on by default for testing use cargo flag: --no-default-features sensors_connected = [] +live_server = [] [dependencies] actix-web = { version = "0.7.15", features = ["rust-tls"] } diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index 2acde63b..ac5eac8b 100644 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -33,8 +33,9 @@ pub struct YoutubeDownloader { } fn download_song(url: &str) -> Result<(), Error> { - let mut music_dir = dirs::home_dir().unwrap(); - music_dir.push("Music"); + //let mut music_dir = dirs::home_dir().unwrap(); + //music_dir.push("Music"); + let music_dir = std::path::PathBuf::from("/home/pi/Music"); let mut output_arg = String::from(music_dir.to_str().unwrap()); output_arg.push_str("/%(title)s.%(ext)s"); @@ -53,7 +54,7 @@ fn download_song(url: &str) -> Result<(), Error> { if output.status.success() { //TODO move to mpd music location - //send rescan command to mpd + mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| c.rescan()); } else { dbg!("HANDLE ERROR"); } diff --git a/src/main.rs b/src/main.rs index e490816b..592c406c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -48,6 +48,11 @@ impl InnerState for ServerState { const FORCE_CERT_REGEN: bool = false; +#[cfg(feature = "live_server")] +const socketaddr: &'static str = "0.0.0.0:8080"; +#[cfg(not(feature = "live_server"))] +const socketaddr: &'static str = "0.0.0.0:8070"; + pub fn start_webserver(signed_cert: &str, private_key: &str, data: Arc>, passw_db: Arc>, @@ -58,6 +63,8 @@ pub fn start_webserver(signed_cert: &str, private_key: &str, mpd_status: input::MpdStatus, ) -> (DataRouterHandle, ServerHandle) { + dbg!(&socketaddr); + let tls_config = httpserver::make_tls_config(signed_cert, private_key); let cookie_key = httpserver::make_random_cookie_key(); @@ -137,7 +144,7 @@ pub fn start_webserver(signed_cert: &str, private_key: &str, //for all other urls we try to resolve to static files in the "web" dir .resource(r"/{tail:.*}", |r| r.f(serve_file)) }) - .bind_rustls("0.0.0.0:8070", tls_config).unwrap() + .bind_rustls(socketaddr, tls_config).unwrap() //.bind("0.0.0.0:8080").unwrap() //without tcp use with debugging (note: https -> http, wss -> ws) .shutdown_timeout(5) // shut down 5 seconds after getting the signal to shut down .start(); From 243c0f759ae5ff2a82a38c5ca7630017ef0617a7 Mon Sep 17 00:00:00 2001 From: David Kleingeld Date: Sat, 15 Jun 2019 18:16:21 +0200 Subject: [PATCH 014/687] adds music to wakeup --- Cargo.lock | 11 ++++ Cargo.toml | 4 +- src/controller/mod.rs | 1 - src/controller/states/wakeup.rs | 72 ++++++++++++++++++++++----- src/controller/system/mod.rs | 1 + src/errors.rs | 18 +++++++ src/input/alarms.rs | 2 +- src/input/attached_sensors/buttons.rs | 2 +- src/input/attached_sensors/mod.rs | 6 ++- src/input/mod.rs | 4 +- src/input/youtube_downloader.rs | 2 +- src/main.rs | 8 ++- 12 files changed, 107 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2354107a..345aa8d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,7 +20,9 @@ dependencies = [ "mpd 0.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "philipshue 0.3.2 (git+https://github.com/dskleingeld/philipshue)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", + "retry 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", "sled 0.24.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1898,6 +1900,14 @@ dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "retry" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rgb" version = "0.8.13" @@ -3033,6 +3043,7 @@ dependencies = [ "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "e57803405f8ea0eb041c1567dac36127e0c8caa1251c843cb03d43fd767b3d50" "checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" +"checksum retry 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ac83b31b3831aa4b07608db4170f6555ab12942197037c38570dc4c5ba5028" "checksum rgb 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)" = "4f089652ca87f5a82a62935ec6172a534066c7b97be003cc8f702ee9a7a59c92" "checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a" "checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288" diff --git a/Cargo.toml b/Cargo.toml index 69caa9b6..70dbefe1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,4 +50,6 @@ pagecache = "0.17.0" reqwest = "0.9.17" mpd = "0.0.12" -dirs = "2.0.1" \ No newline at end of file +dirs = "2.0.1" +rand = "0.6" +retry = "0.5.1" diff --git a/src/controller/mod.rs b/src/controller/mod.rs index 98d17cd9..2271955e 100644 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -12,7 +12,6 @@ use commands::{handle_cmd}; pub use commands::Command; pub use states::TargetState; -use crate::input; use crate::errors::Error; pub enum Event { diff --git a/src/controller/states/wakeup.rs b/src/controller/states/wakeup.rs index 73933b9f..307ee6ce 100644 --- a/src/controller/states/wakeup.rs +++ b/src/controller/states/wakeup.rs @@ -1,19 +1,54 @@ use super::super::{Modifications, System}; use super::{RoomState, ActiveState}; use super::Normal; +use crate::controller::system; +use crate::errors::Error; +use retry::{retry, delay::Fixed}; use std::time::{Duration, Instant}; -const WAKEUP_DURATION: u64 = 900; //in seconds -const BRI_PER_SECOND: f32 = 254./(WAKEUP_DURATION as f32); //in seconds +const UPDATE_PERIOD: u64 = 5; +const WAKEUP_DURATION: u64 = 50*15; //in seconds const CT_BEGIN: u16 = 500; const CT_END: u16 = 280; const CT_PER_SECOND: f32 = ((CT_BEGIN-CT_END) as f32)/(WAKEUP_DURATION as f32); -const UPDATE_PERIOD: u64 = 5; +const BRI_PER_SECOND: f32 = 254./(WAKEUP_DURATION as f32); //in seconds + +const MUSIC_ON: u64 = 60*5; +const MAX_VOLUME: i8 = 40; +const MIN_VOLUME: i8 = 10; +const VOL_PER_SECOND: f32 = (MAX_VOLUME-MIN_VOLUME) as f32/(WAKEUP_DURATION-MUSIC_ON) as f32; #[derive(Clone, Copy)] pub struct WakeUp { start: Instant, + playing: bool, +} + +impl WakeUp { + + fn setup_playlist() -> Result<(), Error> { + let mpd = &mut mpd::Client::connect("127.0.0.1:6600")?; + let mpd = &mut retry(Fixed::from_millis(100), || mpd::Client::connect("127.0.0.1:6600"))?; + retry(Fixed::from_millis(100), || system::mpd_control::save_current_playlist(mpd))?; + retry(Fixed::from_millis(100), || + system::mpd_control::add_from_playlist(mpd, "calm", + chrono::Duration::seconds(3*60), + chrono::Duration::seconds(5*60)) + )?; + retry(Fixed::from_millis(100), || + system::mpd_control::add_from_playlist(mpd, "energetic", + chrono::Duration::seconds(10*60), + chrono::Duration::seconds(11*60)) + )?; + retry(Fixed::from_millis(100), || + system::mpd_control::add_from_playlist(mpd, "active", + chrono::Duration::seconds(30*60), + chrono::Duration::seconds(60*60)) + )?; + Ok(()) + } + } impl RoomState for WakeUp { @@ -23,15 +58,27 @@ impl RoomState for WakeUp { if elapsed > WAKEUP_DURATION { sys.lights.set_all_to(254, CT_END).unwrap(); - ActiveState::Normal(Normal::enter(mods, sys)) - } else { - let bri = (BRI_PER_SECOND*(elapsed as f32)) as u8; - let ct = CT_BEGIN-(CT_PER_SECOND*(elapsed as f32)) as u16; + return ActiveState::Normal(Normal::enter(mods, sys)) + } + + let bri = (BRI_PER_SECOND*(elapsed as f32)) as u8; + let ct = CT_BEGIN-(CT_PER_SECOND*(elapsed as f32)) as u16; - sys.lights.set_all_to(bri, ct).unwrap(); - - ActiveState::WakeUp(self) + sys.lights.set_all_to(bri, ct).unwrap(); + + if !self.playing { + if elapsed > MUSIC_ON { + mpd::Client::connect("127.0.0.1:6600") + .and_then(|ref mut c| c.volume(MIN_VOLUME) + .and_then(|_| c.play())); //only play if the volume was set correctly + } + } else { + mpd::Client::connect("127.0.0.1:6600") + .and_then(|mut c| c.volume((VOL_PER_SECOND*(elapsed-MUSIC_ON) as f32) as i8 )); } + + ActiveState::WakeUp(self) + } fn enter(_mods: &mut Modifications, sys: &mut System) -> Self { @@ -39,7 +86,8 @@ impl RoomState for WakeUp { sys.update_period = Duration::from_secs(UPDATE_PERIOD); sys.next_update = Instant::now()+sys.update_period; - sys.lights.set_all_to(0, CT_BEGIN).unwrap(); - Self{start: Instant::now()} + Self::setup_playlist(); + sys.lights.set_all_to(0, CT_BEGIN); + Self{start: Instant::now(), playing: false} } } diff --git a/src/controller/system/mod.rs b/src/controller/system/mod.rs index 11225707..a5e6158a 100644 --- a/src/controller/system/mod.rs +++ b/src/controller/system/mod.rs @@ -1,2 +1,3 @@ mod lamps; +pub mod mpd_control; pub use lamps::Lighting; \ No newline at end of file diff --git a/src/errors.rs b/src/errors.rs index c0fe60bf..d67b3e3e 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -10,6 +10,7 @@ pub enum Error { Download(reqwest::Error), Lamps(philipshue::errors::HueError), Mpd(mpd::error::Error), + RetryLogic(String), UnTracked, } @@ -42,6 +43,23 @@ impl From for Error { } } +impl From> for Error { + fn from(error: retry::Error) -> Self { + match error { + retry::Error::Operation{error, total_delay: _total_delay, tries: _tries} => error, + retry::Error::Internal(error_str) => Error::RetryLogic(error_str), + } + } +} + +impl From> for Error { + fn from(error: retry::Error) -> Self { + match error { + retry::Error::Operation{error, total_delay: _total_delay, tries: _tries} => Error::Mpd(error), + retry::Error::Internal(error_str) => Error::RetryLogic(error_str), + } + } +} //impl From for Error { // fn from(error: crossbeam_channel::SendError<()>) -> Self { // Error::Channel(error) diff --git a/src/input/alarms.rs b/src/input/alarms.rs index 8c1356d3..e277b4ca 100644 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -77,7 +77,7 @@ impl Alarms { pub fn setup(event_tx: crossbeam_channel::Sender, db: sled::Db) -> Result<(Self, thread::JoinHandle<()>), Error> { let mut alarm_db = AlarmList { db: db.open_tree("alarms")? }; - alarm_db.remove_old(); + alarm_db.remove_old()?; let (waker_tx, waker_rx) = crossbeam_channel::unbounded(); let waker_db_copy = alarm_db.clone(); diff --git a/src/input/attached_sensors/buttons.rs b/src/input/attached_sensors/buttons.rs index 06e504a3..6a450dae 100644 --- a/src/input/attached_sensors/buttons.rs +++ b/src/input/attached_sensors/buttons.rs @@ -35,7 +35,7 @@ fn stream(mut pin_numb_command_pairs: Vec<(u64, Command)>, tx: crossbeam_channel last_press = Instant::now(); dbg!(pin_numb); dbg!(val); - tx.send(Event::Command(command.clone())); + tx.send(Event::Command(command.clone())).unwrap(); } } Ok(()) diff --git a/src/input/attached_sensors/mod.rs b/src/input/attached_sensors/mod.rs index 4c23894d..58f8f50e 100644 --- a/src/input/attached_sensors/mod.rs +++ b/src/input/attached_sensors/mod.rs @@ -9,9 +9,12 @@ use self::chrono::{Utc}; use crossbeam_channel; +#[cfg(feature = "sensors_connected")] mod buttons; +#[cfg(feature = "sensors_connected")] mod bme280; + use std::thread; use std::time::{Duration}; use std::sync::{RwLock, Arc}; @@ -20,6 +23,7 @@ use crate::controller::{Event}; const LOCAL_SENSING_ID: timeseries_interface::DatasetId = 0; //TODO mechanisme for shutdown +#[cfg(feature = "sensors_connected")] pub fn start_monitoring(tx: crossbeam_channel::Sender, data_router_handle: DataRouterHandle, dataset_handle: Arc>) { buttons::start(tx.clone()); @@ -33,7 +37,7 @@ pub fn start_monitoring(tx: crossbeam_channel::Sender, data_router_handle //init all sensors let mut bme = bme280::init(); - thread::spawn(move || {//TODO figure out shutdown behaviour + thread::spawn(move || {//TODO figure out shutdown behaviour loop { //get all measurements diff --git a/src/input/mod.rs b/src/input/mod.rs index 4a83b1e0..b82f3c90 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -1,5 +1,7 @@ -pub mod web_api; + pub mod attached_sensors; + +pub mod web_api; pub mod alarms; pub mod youtube_downloader; mod mpd_status; diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index ac5eac8b..d26f7054 100644 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -54,7 +54,7 @@ fn download_song(url: &str) -> Result<(), Error> { if output.status.success() { //TODO move to mpd music location - mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| c.rescan()); + mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| c.rescan())?; } else { dbg!("HANDLE ERROR"); } diff --git a/src/main.rs b/src/main.rs index 592c406c..0d5985b8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -49,9 +49,9 @@ impl InnerState for ServerState { const FORCE_CERT_REGEN: bool = false; #[cfg(feature = "live_server")] -const socketaddr: &'static str = "0.0.0.0:8080"; +const SOCKETADDR: &'static str = "0.0.0.0:8080"; #[cfg(not(feature = "live_server"))] -const socketaddr: &'static str = "0.0.0.0:8070"; +const SOCKETADDR: &'static str = "0.0.0.0:8070"; pub fn start_webserver(signed_cert: &str, private_key: &str, data: Arc>, @@ -63,8 +63,6 @@ pub fn start_webserver(signed_cert: &str, private_key: &str, mpd_status: input::MpdStatus, ) -> (DataRouterHandle, ServerHandle) { - dbg!(&socketaddr); - let tls_config = httpserver::make_tls_config(signed_cert, private_key); let cookie_key = httpserver::make_random_cookie_key(); @@ -144,7 +142,7 @@ pub fn start_webserver(signed_cert: &str, private_key: &str, //for all other urls we try to resolve to static files in the "web" dir .resource(r"/{tail:.*}", |r| r.f(serve_file)) }) - .bind_rustls(socketaddr, tls_config).unwrap() + .bind_rustls(SOCKETADDR, tls_config).unwrap() //.bind("0.0.0.0:8080").unwrap() //without tcp use with debugging (note: https -> http, wss -> ws) .shutdown_timeout(5) // shut down 5 seconds after getting the signal to shut down .start(); From b7d98a90a0b709443334f8125524cc5eda703d5a Mon Sep 17 00:00:00 2001 From: David Kleingeld Date: Sat, 15 Jun 2019 18:17:24 +0200 Subject: [PATCH 015/687] adds mpd control and status files --- src/controller/system/mpd_control.rs | 27 +++++++++++++ src/input/mpd_status.rs | 59 ++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 src/controller/system/mpd_control.rs create mode 100644 src/input/mpd_status.rs diff --git a/src/controller/system/mpd_control.rs b/src/controller/system/mpd_control.rs new file mode 100644 index 00000000..2c64f038 --- /dev/null +++ b/src/controller/system/mpd_control.rs @@ -0,0 +1,27 @@ +use crate::errors::Error; +use chrono::Duration; +use rand::Rng; + +pub fn add_from_playlist(mpd: &mut mpd::Client, name: &str, minimal_play_time: Duration, maximal_play_time: Duration) -> Result<(),Error>{ + let mut rng = rand::thread_rng(); + + let mut songs = mpd.playlist(name)?; + let mut time = Duration::seconds(0); + //add random songs until the playtime is larger then the minimum + while time < minimal_play_time && songs.len()!=0 { + let idx = rng.gen_range(0, songs.len()-1); + let song = songs.remove(idx); + if time + song.duration.unwrap() < maximal_play_time { + time = time + song.duration.unwrap(); + mpd.push(song)?; + + } + } + Ok(()) +} + +pub fn save_current_playlist(mpd: &mut mpd::Client) -> Result<(),Error>{ + mpd.pl_clear("temp")?; + mpd.save("temp")?; + Ok(()) +} \ No newline at end of file diff --git a/src/input/mpd_status.rs b/src/input/mpd_status.rs new file mode 100644 index 00000000..a3d9efd0 --- /dev/null +++ b/src/input/mpd_status.rs @@ -0,0 +1,59 @@ +use mpd::{idle::Idle, idle::Subsystem, Client}; +use crate::errors::Error; +use std::thread; +use std::sync::{Arc, RwLock}; +use crossbeam_channel::{bounded, Receiver, Sender}; + +//mpd watcher, waits on mpd sys changes and stores in struct/sends updates to whomever needs to know +//mpd command sender (opens new connection for every command?) + +#[derive(Clone)] +pub struct MpdStatus { + inner: Arc>, +} + +fn mpd_watcher(mut client: Client, status: MpdStatus, rx: Receiver<()>) { + client.wait(&[Subsystem::Player, Subsystem::Mixer]).unwrap(); + loop { + //if we have a message that means we should shut down + if let Ok(_) = rx.try_recv(){ + return; + } + //this loop is stopped by sending a change to mpd server + if let Ok(_) = client.wait(&[Subsystem::Player, Subsystem::Mixer]){ + //update status + dbg!("updating mpd status"); + let new_status = client.status().unwrap(); + *(status.inner.write().unwrap()) = new_status; + } else { + return; + } + } +} + +impl MpdStatus { + pub fn stop_updating(tx: Sender<()>) { + let mut client = mpd::Client::connect("127.0.0.1:6600").unwrap(); + tx.send(()).unwrap(); //tell mpd watcher to shut down on next check + //make a small change to a subsys that is watched to force mpd_watcher to stop idle mode + let status = client.status().unwrap(); + client.volume(status.volume+1).unwrap(); + client.volume(status.volume).unwrap(); + } + + pub fn start_updating() -> Result<(Self, thread::JoinHandle<()>, Sender<()>), Error>{ + let mut client = mpd::Client::connect("127.0.0.1:6600")?; + let status = client.status()?; + dbg!(&status); + + let mpd_status = Self { inner: Arc::new(RwLock::new(status))}; + let mpd_status_cloned = mpd_status.clone(); + let (tx, rx) = crossbeam_channel::bounded(1); + + let mpd_watcher_thread = thread::spawn(move || { + mpd_watcher(client, mpd_status_cloned, rx); + }); + + Ok((mpd_status, mpd_watcher_thread, tx)) + } +} \ No newline at end of file From e246932e5f17e17861d1c3d0669fb474c479bf21 Mon Sep 17 00:00:00 2001 From: David Kleingeld Date: Sun, 22 Sep 2019 20:33:08 +0200 Subject: [PATCH 016/687] various changes to improve wakeup state --- src/controller/commands.rs | 12 +++--- src/controller/mod.rs | 21 ++++++----- src/controller/states/mod.rs | 10 ++--- src/controller/states/wakeup.rs | 56 ++++++++++++++++------------ src/controller/system/mpd_control.rs | 20 ++++++++-- src/input/youtube_downloader.rs | 2 +- src/main.rs | 2 +- 7 files changed, 74 insertions(+), 49 deletions(-) diff --git a/src/controller/commands.rs b/src/controller/commands.rs index 8f040815..e95afe03 100644 --- a/src/controller/commands.rs +++ b/src/controller/commands.rs @@ -27,12 +27,12 @@ pub fn handle_cmd(cmd: Command, state: ActiveState, mods: &mut Modifications, sy } //Command::PauseMpd => {unimplemented!(); state}, - Command::LampsToggle => {sys.lights.toggle().unwrap(); mods.lighting = true}, - Command::LampsDim => {sys.lights.set_all_to(50,500).unwrap(); mods.lighting = true}, - Command::LampsDimmest => {sys.lights.set_all_to(1,500).unwrap(); mods.lighting = true}, - Command::LampsEvening => {sys.lights.set_all_to(254,320).unwrap(); mods.lighting = true}, - Command::LampsNight => {sys.lights.set_all_to(220,500).unwrap(); mods.lighting = true}, - Command::LampsDay => {sys.lights.set_all_to(254,240).unwrap(); mods.lighting = true}, + Command::LampsToggle => {sys.lights.toggle().unwrap(); mods.lighting = true} + Command::LampsDim => {sys.lights.set_all_to(50,500).unwrap(); mods.lighting = true} + Command::LampsDimmest => {sys.lights.set_all_to(1,500).unwrap(); mods.lighting = true} + Command::LampsEvening => {sys.lights.set_all_to(254,320).unwrap(); mods.lighting = true} + Command::LampsNight => {sys.lights.set_all_to(220,500).unwrap(); mods.lighting = true} + Command::LampsDay => {sys.lights.set_all_to(254,240).unwrap(); mods.lighting = true} Command::GoToLinux => println!("should go to linux"), Command::GoToWindows => println!("should go to windows"), diff --git a/src/controller/mod.rs b/src/controller/mod.rs index 2271955e..835f25ae 100644 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -16,21 +16,21 @@ use crate::errors::Error; pub enum Event { Update, - Alarm, - Test, + Alarm, + Test, Command(Command), } pub struct Modifications { //change name to: alteration, deviation, overrides or something else? - lighting: bool - //Mpd, + lighting: bool, + mpd: bool, //Desk, //Alarm, } impl Default for Modifications { fn default() -> Self { - Modifications {lighting: false} + Modifications {lighting: false, mpd: false} } } @@ -83,15 +83,16 @@ pub fn start(rx: crossbeam_channel::Receiver) -> Result {dbg!("a test happend while in normal state"); ActiveState::Normal(state)}, + (Event::Test, ActiveState::Normal(state)) => {dbg!("a test happend while in normal state"); ActiveState::Normal(state)}, //general code that is the same for all functions, unless specific handlers exist above - (Event::Command(cmd), state) => {handle_cmd(cmd, state, &mut mods, &mut system)}, - (Event::Update, state) => {state.update(&mut mods, &mut system)}, - (Event::Alarm, _) => {change_state(TargetState::WakeUp, &mut mods, &mut system)}, - (Event::Test, _) => {dbg!("a test happend"); change_state(TargetState::WakeUp, &mut mods, &mut system)}, + (Event::Command(cmd), state) => {handle_cmd(cmd, state, &mut mods, &mut system)}, + (Event::Update, state) => {state.update(&mut mods, &mut system)}, + (Event::Alarm, _) => {change_state(TargetState::WakeUp, &mut mods, &mut system)}, + (Event::Test, _) => {dbg!("a test happend"); change_state(TargetState::WakeUp, &mut mods, &mut system)}, }; } }); diff --git a/src/controller/states/mod.rs b/src/controller/states/mod.rs index 4b23d0e6..d633378a 100644 --- a/src/controller/states/mod.rs +++ b/src/controller/states/mod.rs @@ -33,11 +33,11 @@ impl ActiveState { } pub fn change_state(target_state: TargetState, mods: &mut Modifications, sys: &mut System) -> ActiveState { - match target_state { - TargetState::Normal => ActiveState::Normal(Normal::enter(mods, sys)), - TargetState::LightLoop => ActiveState::LightLoop(LightLoop::enter(mods, sys)), - TargetState::WakeUp => ActiveState::WakeUp(WakeUp::enter(mods, sys)), - } + match target_state { + TargetState::Normal => ActiveState::Normal(Normal::enter(mods, sys)), + TargetState::LightLoop => ActiveState::LightLoop(LightLoop::enter(mods, sys)), + TargetState::WakeUp => ActiveState::WakeUp(WakeUp::enter(mods, sys)), + } } pub trait RoomState { diff --git a/src/controller/states/wakeup.rs b/src/controller/states/wakeup.rs index 307ee6ce..9f16ceda 100644 --- a/src/controller/states/wakeup.rs +++ b/src/controller/states/wakeup.rs @@ -8,7 +8,7 @@ use retry::{retry, delay::Fixed}; use std::time::{Duration, Instant}; const UPDATE_PERIOD: u64 = 5; -const WAKEUP_DURATION: u64 = 50*15; //in seconds +const WAKEUP_DURATION: u64 = 60*15; //in seconds const CT_BEGIN: u16 = 500; const CT_END: u16 = 280; const CT_PER_SECOND: f32 = ((CT_BEGIN-CT_END) as f32)/(WAKEUP_DURATION as f32); @@ -28,20 +28,22 @@ pub struct WakeUp { impl WakeUp { fn setup_playlist() -> Result<(), Error> { - let mpd = &mut mpd::Client::connect("127.0.0.1:6600")?; let mpd = &mut retry(Fixed::from_millis(100), || mpd::Client::connect("127.0.0.1:6600"))?; - retry(Fixed::from_millis(100), || system::mpd_control::save_current_playlist(mpd))?; - retry(Fixed::from_millis(100), || + dbg!(); + retry(Fixed::from_millis(100).take(3), || system::mpd_control::save_current_playlist(mpd))?; + dbg!(); + retry(Fixed::from_millis(100).take(3), || system::mpd_control::add_from_playlist(mpd, "calm", chrono::Duration::seconds(3*60), chrono::Duration::seconds(5*60)) )?; - retry(Fixed::from_millis(100), || + dbg!(); + retry(Fixed::from_millis(100).take(3), || system::mpd_control::add_from_playlist(mpd, "energetic", chrono::Duration::seconds(10*60), chrono::Duration::seconds(11*60)) )?; - retry(Fixed::from_millis(100), || + retry(Fixed::from_millis(100).take(3), || system::mpd_control::add_from_playlist(mpd, "active", chrono::Duration::seconds(30*60), chrono::Duration::seconds(60*60)) @@ -53,41 +55,49 @@ impl WakeUp { impl RoomState for WakeUp { fn update(self, mods: &mut Modifications, sys: &mut System) -> ActiveState { - //dbg!("updating normal state"); + dbg!("updating wakeup state"); let elapsed = self.start.elapsed().as_secs(); if elapsed > WAKEUP_DURATION { - sys.lights.set_all_to(254, CT_END).unwrap(); return ActiveState::Normal(Normal::enter(mods, sys)) } - let bri = (BRI_PER_SECOND*(elapsed as f32)) as u8; - let ct = CT_BEGIN-(CT_PER_SECOND*(elapsed as f32)) as u16; + if !mods.lighting { // if lighting controls have not been modified externally since start + let bri = (BRI_PER_SECOND*(elapsed as f32)) as u8; + let ct = CT_BEGIN-(CT_PER_SECOND*(elapsed as f32)) as u16; + sys.lights.set_all_to(bri, ct).expect("could not update lights in wakeup"); + } - sys.lights.set_all_to(bri, ct).unwrap(); - - if !self.playing { - if elapsed > MUSIC_ON { - mpd::Client::connect("127.0.0.1:6600") - .and_then(|ref mut c| c.volume(MIN_VOLUME) - .and_then(|_| c.play())); //only play if the volume was set correctly + if !mods.mpd { // if mpd controls have not been modified externally since start + if !self.playing { + if elapsed > MUSIC_ON { + mpd::Client::connect("127.0.0.1:6600") + .and_then(|ref mut c| c.volume(MIN_VOLUME) + .and_then(|_| c.play())); //only play if the volume was set correctly + } + } else { + mpd::Client::connect("127.0.0.1:6600") + .and_then(|mut c| c.volume((VOL_PER_SECOND*(elapsed-MUSIC_ON) as f32) as i8 )); } - } else { - mpd::Client::connect("127.0.0.1:6600") - .and_then(|mut c| c.volume((VOL_PER_SECOND*(elapsed-MUSIC_ON) as f32) as i8 )); } ActiveState::WakeUp(self) } - fn enter(_mods: &mut Modifications, sys: &mut System) -> Self { + fn enter(mods: &mut Modifications, sys: &mut System) -> Self { dbg!("starting wakeup state"); sys.update_period = Duration::from_secs(UPDATE_PERIOD); sys.next_update = Instant::now()+sys.update_period; - Self::setup_playlist(); - sys.lights.set_all_to(0, CT_BEGIN); + // reset modifications on entering state + mods.lighting = false; + mods.mpd = false; + + dbg!("setting up playlist"); + Self::setup_playlist().expect("error creating wakeup playlist"); + dbg!("done with setting up playlist"); + sys.lights.set_all_to(0, CT_BEGIN).expect("could not set lights on entering wakeup state"); Self{start: Instant::now(), playing: false} } } diff --git a/src/controller/system/mpd_control.rs b/src/controller/system/mpd_control.rs index 2c64f038..8a4da0e1 100644 --- a/src/controller/system/mpd_control.rs +++ b/src/controller/system/mpd_control.rs @@ -5,7 +5,18 @@ use rand::Rng; pub fn add_from_playlist(mpd: &mut mpd::Client, name: &str, minimal_play_time: Duration, maximal_play_time: Duration) -> Result<(),Error>{ let mut rng = rand::thread_rng(); - let mut songs = mpd.playlist(name)?; + let songs = mpd.playlist(name); + let mut songs = match songs{ //report all errors except non existing playlist + Ok(songs) => songs, + Err(error) => match error { + mpd::error::Error::Server(serv_error) => match serv_error.code { + mpd::error::ErrorCode::NoExist => {warn!("could not find playlist: {}", name); return Ok(())}, + _ => return Err(mpd::error::Error::Server(serv_error).into()), + }, + _ => return Err(error.into()), + }, + }; + let mut time = Duration::seconds(0); //add random songs until the playtime is larger then the minimum while time < minimal_play_time && songs.len()!=0 { @@ -14,14 +25,17 @@ pub fn add_from_playlist(mpd: &mut mpd::Client, name: &str, minimal_play_time: D if time + song.duration.unwrap() < maximal_play_time { time = time + song.duration.unwrap(); mpd.push(song)?; - } + dbg!(songs.len()); } Ok(()) } pub fn save_current_playlist(mpd: &mut mpd::Client) -> Result<(),Error>{ - mpd.pl_clear("temp")?; + dbg!(); + mpd.pl_remove("temp")?; + dbg!(); mpd.save("temp")?; + dbg!(); Ok(()) } \ No newline at end of file diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index d26f7054..21f3232a 100644 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -56,7 +56,7 @@ fn download_song(url: &str) -> Result<(), Error> { //TODO move to mpd music location mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| c.rescan())?; } else { - dbg!("HANDLE ERROR"); + dbg!("HANDLE ERROR"); //update youtube downloader on fail (once if not recenty updated (check file meta)) } Ok(()) diff --git a/src/main.rs b/src/main.rs index 0d5985b8..6a671a98 100644 --- a/src/main.rs +++ b/src/main.rs @@ -179,7 +179,7 @@ fn main() { let db = sled::Db::start(config).unwrap(); - let passw_db = Arc::new(RwLock::new(PasswordDatabase::load("").unwrap())); + let passw_db = Arc::new(RwLock::new(PasswordDatabase::load("").unwrap()));//replace with wrapper around db let dataset_handle = Arc::new(RwLock::new(timeseries_interface::init("data").unwrap())); let sessions = Arc::new(RwLock::new(HashMap::new())); let (controller_tx, controller_rx) = crossbeam_channel::unbounded(); From 5c197de55e04cfdb2b59f5942d5cb80e9918eded Mon Sep 17 00:00:00 2001 From: dskleingeld Date: Sat, 26 Oct 2019 19:14:16 +0200 Subject: [PATCH 017/687] Moves actix to version 1.0. Removes build in dataserver. Switches to actix scopes to seperate different authentication schemes Expands and reorders web_api homeautomation input. Large commit as commits in between where lost. Remember to push after a commit --- .gitignore | 0 Cargo.lock | 1505 ++++++++++------- Cargo.toml | 27 +- src/controller/commands.rs | 0 src/controller/environment/mod.rs | 12 + src/controller/mod.rs | 6 +- src/controller/states/lightloop.rs | 0 src/controller/states/mod.rs | 12 +- src/controller/states/normal.rs | 0 src/controller/states/wakeup.rs | 0 src/controller/system/computer.rs | 0 src/controller/system/lamps/mod.rs | 0 src/controller/system/mod.rs | 0 src/controller/system/mpd_control.rs | 0 src/errors.rs | 0 src/input/alarms.rs | 0 src/input/attached_sensors/buttons.rs | 85 - src/input/buttons.rs | 70 + src/input/mod.rs | 6 +- src/input/mpd_status.rs | 2 +- src/input/sensors/ble/mod.rs | 22 + src/input/sensors/ble/node_credentials.rs | 24 + .../bme280.rs => sensors/local.rs} | 0 .../{attached_sensors => sensors}/mod.rs | 47 +- src/input/web_api/command_logins.rs | 0 src/input/web_api/mod.rs | 139 +- src/input/web_api/server/database.rs | 137 ++ src/input/web_api/server/login.rs | 81 + src/input/web_api/server/login_redirect.rs | 91 + src/input/web_api/server/mod.rs | 54 + .../web_api/server/static_webpages/login.css | 57 + .../web_api/server/static_webpages/login.html | 12 + src/input/youtube_downloader.rs | 6 +- src/main.rs | 209 +-- web/add_song.html | 0 web/graph.html | 0 web/graphDebug.html | 0 web/login.css | 0 web/login.html | 0 web/plot.js | 0 web/plot_debug.js | 0 web/set_alarm.html | 0 web/test.html | 0 web/test_decode.html | 0 web/test_graph_updates.html | 0 web/test_ws_interface.html | 0 web/websocket.html | 0 web/websocket_getData.html | 0 web/websocket_getData2.html | 0 49 files changed, 1637 insertions(+), 967 deletions(-) mode change 100644 => 100755 .gitignore mode change 100644 => 100755 Cargo.lock mode change 100644 => 100755 Cargo.toml mode change 100644 => 100755 src/controller/commands.rs create mode 100755 src/controller/environment/mod.rs mode change 100644 => 100755 src/controller/mod.rs mode change 100644 => 100755 src/controller/states/lightloop.rs mode change 100644 => 100755 src/controller/states/mod.rs mode change 100644 => 100755 src/controller/states/normal.rs mode change 100644 => 100755 src/controller/states/wakeup.rs mode change 100644 => 100755 src/controller/system/computer.rs mode change 100644 => 100755 src/controller/system/lamps/mod.rs mode change 100644 => 100755 src/controller/system/mod.rs mode change 100644 => 100755 src/controller/system/mpd_control.rs mode change 100644 => 100755 src/errors.rs mode change 100644 => 100755 src/input/alarms.rs delete mode 100644 src/input/attached_sensors/buttons.rs create mode 100755 src/input/buttons.rs mode change 100644 => 100755 src/input/mod.rs mode change 100644 => 100755 src/input/mpd_status.rs create mode 100755 src/input/sensors/ble/mod.rs create mode 100755 src/input/sensors/ble/node_credentials.rs rename src/input/{attached_sensors/bme280.rs => sensors/local.rs} (100%) mode change 100644 => 100755 rename src/input/{attached_sensors => sensors}/mod.rs (71%) mode change 100644 => 100755 mode change 100644 => 100755 src/input/web_api/command_logins.rs mode change 100644 => 100755 src/input/web_api/mod.rs create mode 100755 src/input/web_api/server/database.rs create mode 100755 src/input/web_api/server/login.rs create mode 100755 src/input/web_api/server/login_redirect.rs create mode 100755 src/input/web_api/server/mod.rs create mode 100755 src/input/web_api/server/static_webpages/login.css create mode 100755 src/input/web_api/server/static_webpages/login.html mode change 100644 => 100755 src/input/youtube_downloader.rs mode change 100644 => 100755 src/main.rs mode change 100644 => 100755 web/add_song.html mode change 100644 => 100755 web/graph.html mode change 100644 => 100755 web/graphDebug.html mode change 100644 => 100755 web/login.css mode change 100644 => 100755 web/login.html mode change 100644 => 100755 web/plot.js mode change 100644 => 100755 web/plot_debug.js mode change 100644 => 100755 web/set_alarm.html mode change 100644 => 100755 web/test.html mode change 100644 => 100755 web/test_decode.html mode change 100644 => 100755 web/test_graph_updates.html mode change 100644 => 100755 web/test_ws_interface.html mode change 100644 => 100755 web/websocket.html mode change 100644 => 100755 web/websocket_getData.html mode change 100644 => 100755 web/websocket_getData2.html diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/Cargo.lock b/Cargo.lock old mode 100644 new mode 100755 index 345aa8d9..2a9f4535 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,25 +4,32 @@ name = "HomeAutomation" version = "0.1.0" dependencies = [ - "actix 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web-httpauth 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-files 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-identity 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-net 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-rt 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web-httpauth 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "bme280 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "dataserver 0.1.0 (git+https://github.com/dskleingeld/dataserver)", "dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "linux-embedded-hal 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mpd 0.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", - "philipshue 0.3.2 (git+https://github.com/dskleingeld/philipshue)", + "philipshue 0.3.2", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", "retry 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "secure-ble 0.1.0", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", "sled 0.24.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -31,26 +38,6 @@ dependencies = [ "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "acme-client" -version = "0.5.3" -source = "git+https://github.com/janderholm/acme-client#18009de3316c0c0bc62db5fb5aee642bcda2c79b" -dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.22 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "actix" version = "0.7.9" @@ -63,7 +50,7 @@ dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -81,97 +68,300 @@ dependencies = [ ] [[package]] -name = "actix-net" -version = "0.2.6" +name = "actix-codec" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "actix 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-rustls 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "actix-connect" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-rt 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-utils 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tower-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-resolver 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "actix-web" -version = "0.7.19" +name = "actix-files" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "actix 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-net 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-http 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "v_htmlescape 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "actix-http" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-connect 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-server-config 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-threadpool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-utils 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-resolver 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "actix-identity" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "actix-net" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "actix 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-rustls 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "v_htmlescape 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tower-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "actix-router" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "actix-rt" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "actix-threadpool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "actix-server" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "actix-rt 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-server-config 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "actix-server-config" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "actix-service" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "actix-threadpool" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "actix-utils" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "actix-web" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-http 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-router 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-rt 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-server 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-server-config 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-threadpool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-utils 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web-codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "awc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "actix-web-codegen" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "actix-web-httpauth" -version = "0.1.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "actix-web 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)", - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-locks 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -190,33 +380,41 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "aho-corasick" -version = "0.6.10" +name = "aes" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "aho-corasick" -version = "0.7.3" +name = "aes-soft" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "ansi_term" -version = "0.11.0" +name = "aesni" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "approx" -version = "0.1.1" +name = "aho-corasick" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "arc-swap" @@ -241,29 +439,42 @@ dependencies = [ ] [[package]] -name = "atty" -version = "0.2.11" +name = "autocfg" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "autocfg" -version = "0.1.2" +name = "awc" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-http 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "backtrace" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -274,16 +485,7 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "base64" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -291,7 +493,7 @@ name = "base64" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -299,8 +501,8 @@ name = "bincode" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -328,6 +530,33 @@ dependencies = [ "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-cipher-trait" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-padding" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bme280" version = "0.1.1" @@ -342,7 +571,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -351,7 +580,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -364,9 +593,14 @@ name = "build_const" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -374,10 +608,19 @@ name = "bytes" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "c2-chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cast" version = "0.2.2" @@ -393,16 +636,6 @@ name = "cfg-if" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "cgmath" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "chrono" version = "0.4.6" @@ -411,38 +644,15 @@ dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "clap" -version = "2.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "colored" -version = "1.8.0" +name = "cloudabi" +version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winconsole 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -450,17 +660,6 @@ name = "constant_time_eq" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "cookie" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "cookie" version = "0.12.0" @@ -487,13 +686,18 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "copyless" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "core-foundation" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -597,38 +801,41 @@ dependencies = [ ] [[package]] -name = "dataserver" -version = "0.1.0" -source = "git+https://github.com/dskleingeld/dataserver#8e2e4452f03cc4c758b16f4a0d2e6bbae3681eab" +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "acme-client 0.5.3 (git+https://github.com/janderholm/acme-client)", - "actix 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-net 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)", - "bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "fern 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "minimal_timeseries 0.1.1 (git+https://github.com/dskleingeld/minimal_timeseries?branch=multithraeded_file_read)", - "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "text_io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ct-logs" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "sct 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "derive_more" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -646,7 +853,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -671,77 +878,29 @@ dependencies = [ ] [[package]] -name = "encoding" -version = "0.2.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding-index-japanese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding-index-korean" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding-index-simpchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding-index-singlebyte" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding-index-tradchinese" -version = "1.20141219.5" +name = "encoding_rs" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "encoding_index_tests" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "encoding_rs" -version = "0.8.17" +name = "enum-as-inner" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "env_logger" -version = "0.4.3" +name = "enum_primitive" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -790,13 +949,9 @@ dependencies = [ ] [[package]] -name = "fern" -version = "0.5.8" +name = "fake-simd" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "flate2" @@ -804,7 +959,7 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -832,7 +987,7 @@ name = "fs2" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -869,12 +1024,22 @@ dependencies = [ "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "futures-locks" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fxhash" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -882,12 +1047,30 @@ name = "gcc" version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "getrandom" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "h2" version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -907,17 +1090,31 @@ dependencies = [ "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hashbrown" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "historian" version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "hmac" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hostname" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -936,24 +1133,6 @@ name = "httparse" version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "hyper" -version = "0.10.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "hyper" version = "0.12.28" @@ -983,13 +1162,18 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.6.2" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "ct-logs 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1010,8 +1194,8 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1025,6 +1209,16 @@ dependencies = [ "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "idna" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "indexmap" version = "1.0.2" @@ -1035,7 +1229,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1052,11 +1246,14 @@ dependencies = [ ] [[package]] -name = "itertools" -version = "0.7.11" +name = "ipconfig" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1083,14 +1280,9 @@ name = "lazy_static" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "lazycell" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "libc" -version = "0.2.54" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1119,6 +1311,14 @@ dependencies = [ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lock_api" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "log" version = "0.3.9" @@ -1148,14 +1348,6 @@ name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "matrixmultiply" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rawpointer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "memchr" version = "2.2.0" @@ -1166,14 +1358,6 @@ name = "memoffset" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "mime" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "mime" version = "0.3.13" @@ -1193,27 +1377,13 @@ dependencies = [ "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "minimal_timeseries" -version = "0.1.1" -source = "git+https://github.com/dskleingeld/minimal_timeseries?branch=multithraeded_file_read#a0cc62277dbb13feb39a926e5da33b64c1b2342d" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fern 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", - "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ndarray 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "miniz-sys" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1231,21 +1401,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mio" -version = "0.6.16" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1259,8 +1428,8 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1290,7 +1459,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.22 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1306,24 +1475,13 @@ name = "nb" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "ndarray" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", - "matrixmultiply 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1334,7 +1492,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1349,7 +1507,7 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1361,7 +1519,19 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nix" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1381,32 +1551,35 @@ dependencies = [ [[package]] name = "num" -version = "0.2.0" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", + "num-complex 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-bigint" -version = "0.2.2" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-complex" -version = "0.2.1" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1419,21 +1592,23 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.37" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-rational" -version = "0.2.1" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1454,12 +1629,12 @@ name = "num_cpus" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "numtoa" -version = "0.1.0" +name = "opaque-debug" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1471,7 +1646,7 @@ dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1485,9 +1660,9 @@ name = "openssl-sys" version = "0.9.46" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1515,7 +1690,7 @@ dependencies = [ "hashbrown 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "historian 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1530,13 +1705,37 @@ dependencies = [ "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot_core" -version = "0.4.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1547,6 +1746,11 @@ name = "percent-encoding" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "phf" version = "0.7.24" @@ -1585,11 +1789,9 @@ dependencies = [ [[package]] name = "philipshue" version = "0.3.2" -source = "git+https://github.com/dskleingeld/philipshue#7005847cd8dca572d411634d20c02264d6262081" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-rustls 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1600,6 +1802,11 @@ name = "pkg-config" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ppv-lite86" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "proc-macro2" version = "0.4.30" @@ -1639,7 +1846,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1652,7 +1859,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1662,8 +1869,8 @@ name = "rand" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1675,15 +1882,36 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_chacha" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_core" version = "0.3.1" @@ -1697,6 +1925,14 @@ name = "rand_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_hc" version = "0.1.0" @@ -1705,6 +1941,14 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_isaac" version = "0.1.1" @@ -1718,7 +1962,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1730,7 +1974,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1741,7 +1985,7 @@ name = "rand_pcg" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1753,11 +1997,6 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rawpointer" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "rayon" version = "1.0.3" @@ -1775,7 +2014,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1792,14 +2031,6 @@ name = "redox_syscall" version = "0.1.54" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "redox_termios" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "redox_users" version = "0.3.0" @@ -1811,18 +2042,6 @@ dependencies = [ "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "regex" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "regex" version = "1.1.6" @@ -1835,14 +2054,6 @@ dependencies = [ "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "regex-syntax" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "regex-syntax" version = "0.6.6" @@ -1873,11 +2084,13 @@ dependencies = [ "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-rustls 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1885,10 +2098,12 @@ dependencies = [ "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1908,20 +2123,35 @@ dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rgb" -version = "0.8.13" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "ring" -version = "0.13.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rumble" +version = "0.3.0" +source = "git+https://github.com/Josh-Thompson/rumble#3117372692ccfd371909eb4751b3d994a0d59386" +dependencies = [ + "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1952,28 +2182,15 @@ dependencies = [ [[package]] name = "rustls" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sct 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustls" -version = "0.14.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sct 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sct 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1981,19 +2198,6 @@ name = "ryu" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "safemem" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "same-file" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "schannel" version = "0.1.15" @@ -2013,15 +2217,33 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "scopeguard" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "sct" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "secure-ble" +version = "0.1.0" +dependencies = [ + "aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rumble 0.3.0 (git+https://github.com/Josh-Thompson/rumble)", + "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "security-framework" version = "0.3.1" @@ -2029,7 +2251,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2106,6 +2328,17 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde_urlencoded" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serde_yaml" version = "0.8.9" @@ -2117,6 +2350,17 @@ dependencies = [ "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sha-1" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sha1" version = "0.6.0" @@ -2127,7 +2371,7 @@ name = "signal-hook" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "signal-hook-registry 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2137,7 +2381,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arc-swap 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2173,7 +2417,7 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2184,10 +2428,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "stable_deref_trait" version = "1.1.1" @@ -2199,8 +2448,16 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "strsim" -version = "0.8.0" +name = "string" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "subtle" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2230,7 +2487,7 @@ version = "0.5.3" source = "git+https://github.com/rust-embedded/rust-sysfs-gpio#409bab143fbf4004613009aef204df7fc0c0ae8f" dependencies = [ "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2249,7 +2506,7 @@ version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2257,35 +2514,19 @@ dependencies = [ ] [[package]] -name = "termion" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "text_io" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "textwrap" -version = "0.11.0" +name = "thread_local" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "thread_local" -version = "0.3.6" +name = "threadpool" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2293,7 +2534,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2305,7 +2546,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2379,7 +2620,7 @@ dependencies = [ "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2390,13 +2631,13 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.8.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2405,8 +2646,8 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "signal-hook 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2432,7 +2673,7 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2480,7 +2721,7 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2494,9 +2735,9 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2511,17 +2752,12 @@ dependencies = [ "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "traitobject" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "trust-dns-proto" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2544,7 +2780,7 @@ name = "trust-dns-proto" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2562,6 +2798,30 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "trust-dns-proto" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "enum-as-inner 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "trust-dns-resolver" version = "0.10.3" @@ -2580,6 +2840,24 @@ dependencies = [ "trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "trust-dns-resolver" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-proto 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "try-lock" version = "0.2.2" @@ -2594,8 +2872,8 @@ dependencies = [ ] [[package]] -name = "typeable" -version = "0.1.2" +name = "typenum" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2635,11 +2913,6 @@ dependencies = [ "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "unicode-width" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "unicode-xid" version = "0.1.0" @@ -2655,12 +2928,21 @@ name = "url" version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "url" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "utf8-ranges" version = "1.0.2" @@ -2708,11 +2990,6 @@ name = "vcpkg" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "vec_map" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "version_check" version = "0.1.5" @@ -2723,16 +3000,6 @@ name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "walkdir" -version = "2.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "want" version = "0.0.6" @@ -2743,22 +3010,27 @@ dependencies = [ "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "wasi" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "webpki" -version = "0.18.1" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "webpki-roots" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2766,6 +3038,11 @@ name = "widestring" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "widestring" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.2.8" @@ -2790,33 +3067,22 @@ name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "winapi-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "winconsole" -version = "0.10.0" +name = "winreg" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cgmath 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rgb 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "winreg" -version = "0.5.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2848,50 +3114,63 @@ dependencies = [ ] [metadata] -"checksum acme-client 0.5.3 (git+https://github.com/janderholm/acme-client)" = "" "checksum actix 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c616db5fa4b0c40702fb75201c2af7f8aa8f3a2e2c1dda3b0655772aa949666" +"checksum actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9f2c11af4b06dc935d8e1b1491dad56bfb32febc49096a91e773f8535c176453" +"checksum actix-connect 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fade9bd4bb46bacde89f1e726c7a3dd230536092712f5d94d77ca57c087fca0" +"checksum actix-files 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e4640b28cd96059541c932f6f350c63c76688e43d68305cdb88e0004da12b5" +"checksum actix-http 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf758ebbc4abfecbdc1ce7408601b2d7e0cd7e4766ef61183cd8ce16c194d64" +"checksum actix-identity 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "84d972c0f80dc8beeceaff6f47b961a106b9f582c0b12ee6737cad30ed228edd" "checksum actix-net 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8bebfbe6629e0131730746718c9e032b58f02c6ce06ed7c982b9fef6c8545acd" -"checksum actix-web 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b0ac60f86c65a50b140139f499f4f7c6e49e4b5d88fbfba08e4e3975991f7bf4" -"checksum actix-web-httpauth 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "843c8b2e6b9d02d2511c0b26e5e7b59834ea870d266056e474707ba8c80ff3a7" +"checksum actix-router 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "23224bb527e204261d0291102cb9b52713084def67d94f7874923baefe04ccf7" +"checksum actix-rt 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "168620aaf00fcd2a16e621790abaf180ef7377c2f8355b4ca5775d6afc778ed8" +"checksum actix-server 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb3038e9e457e0a498ea682723e0f4e6cc2c4f362a1868d749808355275ad959" +"checksum actix-server-config 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "483a34989c682d93142bacad6300375bb6ad8002d2e0bb249dbad86128b9ff30" +"checksum actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bca5b48e928841ff7e7dce1fdb5b0d4582f6b1b976e08f4bac3f640643e0773f" +"checksum actix-threadpool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b5ae85d13da7e6fb86b1b7bc83185e0e3bd4cc5f421c887e1803796c034d35d" +"checksum actix-utils 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6ea501068a0173533704be321f149853f702d9e3c3ce9d57e7a96d94b1ab5aca" +"checksum actix-web 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8ced216f53d465f9d6478454b2b994d1fe91ec203ac9d056837cbe07e823cb83" +"checksum actix-web-codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe9e3cdec1e645b675f354766e0688c5705021c85ab3cf739be1c8999b91c76" +"checksum actix-web-httpauth 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7005033d05a151c86016468cca1d38febb84a894bbb7a332118479f4ed7398" "checksum actix_derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4300e9431455322ae393d43a2ba1ef96b8080573c0fc23b196219efedfb6ba69" "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" -"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" +"checksum aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "54eb1d8fe354e5fc611daf4f2ea97dd45a765f4f1e4512306ec183ae2e8f20c9" +"checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" +"checksum aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" "checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c" -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08abcc3b4e9339e33a3d0a5ed15d84a687350c05689d825e0f6655eef9e76a94" "checksum arc-swap 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "bc4662175ead9cd84451d5c35070517777949a2ed84551764129cedb88384841" "checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" -"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" +"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" +"checksum awc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "78c9c1e32d6084343b3857eacb1f43aaefb93a816e15aae4685bc3c0a9052964" "checksum backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f106c02a3604afcdc0df5d36cc47b44b55917dbaf3d808f71c163a0ddba64637" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "959c8e54c1ad412ffeeb95f05a9cade02d2d40a7b3c2f852d3353148f4beff35" "checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +"checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" +"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" "checksum bme280 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d168c341491c9ba4e2c73d59470c108a5961377c67061dc1796a193fa945b452" "checksum brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" "checksum brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" "checksum bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" -"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" "checksum cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a0c56216487bb80eec9c4516337b2588a4f2a2290d72a1416d930e4dcdb0c90d" "checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" -"checksum cgmath 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64a4b57c8f4e3a2e9ac07e0f6abc9c24b6fc9e1b54c3478cfb598f3d0023e51c" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" -"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cdb90b60f2927f8d76139c72dbde7e10c3a2bc47c8594c9c7a66529f2687c03" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" -"checksum cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "99be24cfcf40d56ed37fd11c2123be833959bbc5bddecb46e1c2e442e15fa3e0" "checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" "checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" +"checksum copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ff9c56c9fb2a49c05ef0e431485a22400af20d33226dc0764d891d09e724127" "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" @@ -2904,27 +3183,24 @@ dependencies = [ "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" -"checksum dataserver 0.1.0 (git+https://github.com/dskleingeld/dataserver)" = "" +"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +"checksum ct-logs 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b4660f8b07a560a88c02d76286edb9f0d5d64e495d2b0f233186155aa51be1f" +"checksum derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a141330240c921ec6d074a3e188a7c7ef95668bb95e7d44fa0e5778ec2a7afe" +"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" "checksum dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4ef5a8b902d393339e2a2c7fe573af92ce7e0ee5a3ff827b4c9ad7e07e4fa1" "checksum dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "937756392ec77d1f2dd9dc3ac9d69867d109a2121479d72c364e42f4cab21e2d" "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" "checksum embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ee4908a155094da7723c2d60d617b820061e3b4efcc3d9e293d206a5a76c170b" -"checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" -"checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" -"checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" -"checksum encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" -"checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" -"checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" -"checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" "checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" -"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" +"checksum enum-as-inner 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d58266c97445680766be408285e798d3401c6d4c378ec5552e78737e681e37d" +"checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" -"checksum fern 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "29d26fa0f4d433d1956746e66ec10d6bf4d6c8b93cd39965cceea7f7cc78c7dd" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f87e68aa82b2de08a6e037f1385455759df6e445a8df5e005b4297191dbf18aa" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" @@ -2935,84 +3211,89 @@ dependencies = [ "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)" = "a2037ec1c6c1c4f79557762eab1f7eae1f64f6cb418ace90fae88f0942b60139" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +"checksum futures-locks 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5658075ca5ae3918993c5bc95b43fcf22f927227660556a947da598f9f8981" "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" "checksum h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "85ab6286db06040ddefb71641b50017c06874614001a134b423783e2db2920bd" "checksum hashbrown 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "570178d5e4952010d138b0f1d581271ff3a02406d990f887d1e87e3d6e43b0ac" +"checksum hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353" "checksum historian 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f653416eb756b69642a1f1498817970fafe409998a849622c27cc5b1b7df989c" +"checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" "checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" "checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" -"checksum hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" "checksum hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)" = "e8e4606fed1c162e3a63d408c07584429f49a4f34c7176cb6cbee60e78f2372c" -"checksum hyper-rustls 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "71f7b2e5858ab9e19771dc361159f09ee5031734a6f7471fe0947db0238d92b7" +"checksum hyper-rustls 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "15b66d1bd4864ef036adf2363409caa3acd63ebb4725957b66e621c8a36631a3" "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum i2cdev 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3dabb8dd1c6c973b20fa6342069a2703a11f062768d613cc57a5db29a3fe325c" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "08f7eadeaf4b52700de180d147c4805f199854600b36faa963d91114827b2ffc" -"checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" +"checksum ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa79fa216fbe60834a9c0737d7fcd30425b32d1c58854663e24d4c4b328ed83f" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c6785aa7dd976f5fbf3b71cfd9cd49d7f783c1ff565a858d71031c6c313aa5c6" +"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum linux-embedded-hal 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "795096c0eecb0622afb591c3e1a97b1ba046688a7689957b70b8eee9cac8fb84" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum matrixmultiply 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "dcad67dcec2d58ff56f6292582377e6921afdf3bfbd533e26fb8900ae575e002" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" "checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" -"checksum minimal_timeseries 0.1.1 (git+https://github.com/dskleingeld/minimal_timeseries?branch=multithraeded_file_read)" = "" "checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649" "checksum miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c468f2369f07d651a5d0bb2c9079f8488a66d5466efe42d0c5c6466edcb7f71e" "checksum miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7fe927a42e3807ef71defb191dc87d4e24479b221e67015fe38ae2b7b447bab" -"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" +"checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum mpd 0.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "57a20784da57fa01bf7910a5da686d9f39ff37feaa774856b71f050e4331bf82" "checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b1411551beb3c11dedfb0a90a0fa256b47d28b9ec2cdff34c25a2fa59e45dbdc" -"checksum ndarray 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7cf380a8af901ad627594013a3bbac903ae0a6f94e176e47e46b5bbc1877b928" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nix 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b7fd5681d13fda646462cfbd4e5f2051279a89a544d50eb98c365b507246839f" "checksum nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37e713a259ff641624b6cb20e3b12b2952313ba36b6823c0f16e6cfd9e5de17" +"checksum nix 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "319fffb13b63c0f4ff5a4e1c97566e7e741561ff5d03bf8bbf11653454bbd70b" "checksum nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a7bb1da2be7da3cbffda73fc681d509ffd9e665af478d2bee1907cee0bc64b2" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" -"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" -"checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718" -"checksum num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "107b9be86cd2481930688277b675b0114578227f034674726605b8a482d8baf8" +"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" +"checksum num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" +"checksum num-complex 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "b288631d7878aaf59442cffd36910ea604ecd7745c36054328595114001c9656" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" -"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" -"checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10" +"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" +"checksum num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e" "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" -"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" +"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" "checksum openssl 0.10.22 (registry+https://github.com/rust-lang/crates.io-index)" = "a51f452b82d622fc8dd973d7266e9055ac64af25b957d9ced3989142dc61cb6b" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)" = "05636e06b4f8762d4b81d24a351f3966f38bd25ccbcfd235606c91fdb82cc60f" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74a701d13e2f3ee32a50be43321da8f712cf1e6e9ff0e2be66ab7f5c6598a16a" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" "checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" "checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" -"checksum philipshue 0.3.2 (git+https://github.com/dskleingeld/philipshue)" = "" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" +"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5afecba86dcf1e4fd610246f89899d1924fe12e1e89f555eb7c7f710f3c5ad1d" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" @@ -3020,45 +3301,43 @@ dependencies = [ "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" "checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rawpointer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebac11a9d2e11f2af219b8b8d833b76b1ea0e054aa0e8d8e9e4cbde353bdf019" "checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" "checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" -"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" -"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" "checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" -"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" "checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "e57803405f8ea0eb041c1567dac36127e0c8caa1251c843cb03d43fd767b3d50" "checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" "checksum retry 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ac83b31b3831aa4b07608db4170f6555ab12942197037c38570dc4c5ba5028" -"checksum rgb 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)" = "4f089652ca87f5a82a62935ec6172a534066c7b97be003cc8f702ee9a7a59c92" -"checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a" +"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c" +"checksum rumble 0.3.0 (git+https://github.com/Josh-Thompson/rumble)" = "" "checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "942b71057b31981152970d57399c25f72e27a6ee0d207a669d8304cabf44705b" -"checksum rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b7891791343c75b73ed9a18cadcafd8c8563d11a88ebe2d87f5b8a3182654d9" +"checksum rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f271e3552cd835fa28c541c34a7e8fdd8cdff09d77fe4eb8f6c42e87a11b096e" "checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f" -"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" -"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum sct 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb8f61f9e6eadd062a71c380043d28036304a4706b3c4dd001ff3387ed00745a" +"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +"checksum sct 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f5adf8fbd58e1b1b52699dc8bed2630faecb6d8c7bee77d009d6bbe4af569b9" "checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" "checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" @@ -3069,7 +3348,9 @@ dependencies = [ "checksum serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "101b495b109a3e3ca8c4cbe44cf62391527cdfb6ba15821c5ce80bcd5ea23f9f" "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" +"checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" "checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582" +"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum signal-hook 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "72ab58f1fda436857e6337dcb6a5aaa34f16c5ddc87b3a8b6ef7a212f90b9c5a" "checksum signal-hook-registry 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cded4ffa32146722ec54ab1f16320568465aa922aa9ab4708129599740da85d7" @@ -3079,18 +3360,18 @@ dependencies = [ "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "4e626972d3593207547f14bf5fc9efa4d0e7283deb73fef1dff313dae9ab8878" "checksum spidev 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ba01d3ef92a37e898fecac76cd3e1b33c999395e2d70787608d9678c4293e04" +"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" -"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" +"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" "checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum sysfs_gpio 0.5.3 (git+https://github.com/rust-embedded/rust-sysfs-gpio)" = "" "checksum sysfs_gpio 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d68f2cae3c7d39f54ce8a858cc31ffb01974744ee65e5b4999b6037cd691e3f" "checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" -"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea" -"checksum text_io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9658b61ebd1d2a40c276ba2335890b9eb6550b67458a6fbce2022e58c3350a50" -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "cec6c34409089be085de9403ba2010b80e36938c9ca992c4f67f407bb13db0b1" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" @@ -3099,7 +3380,7 @@ dependencies = [ "checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" "checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" -"checksum tokio-rustls 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04a5c8de3797c207c574495724eb77ded1a150160a2db0936c751bf49003c84e" +"checksum tokio-rustls 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1600e90b2602df28ff54ae842519b408fbb25378c3c5aee1b795593e9263dc80" "checksum tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "dd6dc5276ea05ce379a16de90083ec80836440d5ef8a6a39545a3207373b8296" "checksum tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2f843ffdf8d6e1f90bddd48da43f99ab071660cd92b7ec560ef3cdfd7a409a" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" @@ -3109,44 +3390,44 @@ dependencies = [ "checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" "checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" "checksum tower-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b32f72af77f1bfe3d3d4da8516a238ebe7039b51dd8637a09841ac7f16d2c987" -"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum trust-dns-proto 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0838272e89f1c693b4df38dc353412e389cf548ceed6f9fd1af5a8d6e0e7cf74" "checksum trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "09144f0992b0870fa8d2972cc069cbf1e3c0fda64d1f3d45c4d68d0e0b52ad4e" +"checksum trust-dns-proto 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5559ebdf6c2368ddd11e20b11d6bbaf9e46deb803acd7815e93f5a7b4a6d2901" "checksum trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a9f877f7a1ad821ab350505e1f1b146a4960402991787191d6d8cab2ce2de2c" +"checksum trust-dns-resolver 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c9992e58dba365798803c0b91018ff6c8d3fc77e06977c4539af2a6bfe0a039" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" -"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" +"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" -"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" "checksum v_escape 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8865501b78eef9193c1b45486acf18ba889e5662eba98854d6fc59d8ecf3542d" "checksum v_escape_derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "306896ff4b75998501263a1dc000456de442e21d68fe8c8bdf75c66a33a58e23" "checksum v_htmlescape 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7fbbe0fa88dd36f9c8cf61a218d4b953ba669de4d0785832f33cc72bd081e1be" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" -"checksum webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "17d7967316d8411ca3b01821ee6c332bde138ba4363becdb492f12e514daa17f" -"checksum webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85d1f408918fd590908a70d36b7ac388db2edc221470333e4d6e5b598e44cabf" +"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" +"checksum webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4f7e1cd7900a3a6b65a3e8780c51a3e6b59c0e2c55c6dc69578c288d69f7d082" +"checksum webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c10fa4212003ba19a564f25cd8ab572c6791f99a03cc219c13ed35ccab00de0e" "checksum widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" +"checksum widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum winconsole 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef84b96d10db72dd980056666d7f1e7663ce93d82fa33b63e71c966f4cf5032" "checksum winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a27a759395c1195c4cc5cda607ef6f8f6498f64e78f7900f5de0a127a424704a" +"checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" "checksum winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" diff --git a/Cargo.toml b/Cargo.toml old mode 100644 new mode 100755 index 70dbefe1..65b0527a --- a/Cargo.toml +++ b/Cargo.toml @@ -14,9 +14,20 @@ sensors_connected = [] live_server = [] [dependencies] -actix-web = { version = "0.7.15", features = ["rust-tls"] } -actix-web-httpauth = "0.1.0" -actix = "0.7.5" +actix-web = { version = "1.0.3", features = ["rust-tls"] } +actix-net = "0.2.4" +actix-identity = "0.1.0" +actix-files = "0.1.3" +actix-rt = "0.2.4" +actix-service = "0.4.1" +actix-web-httpauth = "0.3.2" +rustls = "0.15.2" + +#philipshue = { git = "https://github.com/dskleingeld/philipshue", branch = "master" } +#for local dev purpose we use below targets +philipshue = { path = "../philipshue"} +secure-ble = { path = "../home_sensors/ble/central"} + serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.8" log = "0.4" @@ -26,14 +37,8 @@ sysfs_gpio = { git = "https://github.com/rust-embedded/rust-sysfs-gpio", branch tokio = "0.1.15" futures = { version = "0.1"} - -#dont forget to run cargo update when these change -philipshue = { git = "https://github.com/dskleingeld/philipshue", branch = "master" } -dataserver = { git = "https://github.com/dskleingeld/dataserver", branch = "master" } - -#for local dev purpose we use below targets -#dataserver = { path = "../dataserver"} -#philipshue = { path = "../philipshue"} +bincode = "1.0.1" +ring = "0.14.6" linux-embedded-hal = "0.2.2" bme280 = "0.1.1" diff --git a/src/controller/commands.rs b/src/controller/commands.rs old mode 100644 new mode 100755 diff --git a/src/controller/environment/mod.rs b/src/controller/environment/mod.rs new file mode 100755 index 00000000..d6c5ec09 --- /dev/null +++ b/src/controller/environment/mod.rs @@ -0,0 +1,12 @@ + +pub struct Environment { + light: [f32; 100], +} + +impl std::default::Default for Environment { + fn default() -> Self { + Environment { + light: [0f32; 100], + } + } +} \ No newline at end of file diff --git a/src/controller/mod.rs b/src/controller/mod.rs old mode 100644 new mode 100755 index 835f25ae..b407c3b3 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -4,6 +4,9 @@ use std::thread; mod system; use system::{Lighting}; +mod environment; +use environment::Environment; + mod states; use states::{ActiveState, RoomState, change_state}; mod commands; @@ -65,6 +68,7 @@ pub fn start(rx: crossbeam_channel::Receiver) -> Result) -> Result {handle_cmd(cmd, state, &mut mods, &mut system)}, - (Event::Update, state) => {state.update(&mut mods, &mut system)}, + (Event::Update, state) => {state.update(&mut mods, &mut system, &mut env)}, (Event::Alarm, _) => {change_state(TargetState::WakeUp, &mut mods, &mut system)}, (Event::Test, _) => {dbg!("a test happend"); change_state(TargetState::WakeUp, &mut mods, &mut system)}, }; diff --git a/src/controller/states/lightloop.rs b/src/controller/states/lightloop.rs old mode 100644 new mode 100755 diff --git a/src/controller/states/mod.rs b/src/controller/states/mod.rs old mode 100644 new mode 100755 index d633378a..78fc8a57 --- a/src/controller/states/mod.rs +++ b/src/controller/states/mod.rs @@ -1,4 +1,4 @@ -use super::{System, Modifications}; +use super::{System, Modifications, Environment}; mod normal; mod lightloop; @@ -23,11 +23,11 @@ pub enum TargetState { } impl ActiveState { - pub fn update(self, mods: &mut Modifications, system: &mut System) -> ActiveState { + pub fn update(self, mods: &mut Modifications, system: &mut System, env: &mut Environment) -> ActiveState { match self { - ActiveState::Normal(state) => state.update(mods, system), - ActiveState::LightLoop(state) => state.update(mods, system), - ActiveState::WakeUp(state) => state.update(mods, system), + ActiveState::Normal(state) => state.update(mods, system, env), + ActiveState::LightLoop(state) => state.update(mods, system, env), + ActiveState::WakeUp(state) => state.update(mods, system, env), } } } @@ -42,5 +42,5 @@ pub fn change_state(target_state: TargetState, mods: &mut Modifications, sys: &m pub trait RoomState { fn enter(mods: &mut Modifications, system: &mut System) -> Self; - fn update(self, mods: &mut Modifications, system: &mut System) -> ActiveState; + fn update(self, mods: &mut Modifications, system: &mut System, env: &mut Environment) -> ActiveState; } \ No newline at end of file diff --git a/src/controller/states/normal.rs b/src/controller/states/normal.rs old mode 100644 new mode 100755 diff --git a/src/controller/states/wakeup.rs b/src/controller/states/wakeup.rs old mode 100644 new mode 100755 diff --git a/src/controller/system/computer.rs b/src/controller/system/computer.rs old mode 100644 new mode 100755 diff --git a/src/controller/system/lamps/mod.rs b/src/controller/system/lamps/mod.rs old mode 100644 new mode 100755 diff --git a/src/controller/system/mod.rs b/src/controller/system/mod.rs old mode 100644 new mode 100755 diff --git a/src/controller/system/mpd_control.rs b/src/controller/system/mpd_control.rs old mode 100644 new mode 100755 diff --git a/src/errors.rs b/src/errors.rs old mode 100644 new mode 100755 diff --git a/src/input/alarms.rs b/src/input/alarms.rs old mode 100644 new mode 100755 diff --git a/src/input/attached_sensors/buttons.rs b/src/input/attached_sensors/buttons.rs deleted file mode 100644 index 6a450dae..00000000 --- a/src/input/attached_sensors/buttons.rs +++ /dev/null @@ -1,85 +0,0 @@ -extern crate sysfs_gpio; -extern crate futures; -extern crate tokio; - -use futures::{Future, lazy, Stream}; -use sysfs_gpio::{Direction, Edge, Pin}; -use std::thread; -use std::time::{Duration, Instant}; -use crossbeam_channel; - -use crate::controller::{Command, Event}; - -// when pressing 22, 24 is often activated -// 23 works perfectly -// 24 also works perfectly - -fn stream(mut pin_numb_command_pairs: Vec<(u64, Command)>, tx: crossbeam_channel::Sender) -> sysfs_gpio::Result<()> { - // NOTE: this currently runs forever and as such if - // the app is stopped (Ctrl-C), no cleanup will happen - // and the GPIO will be left exported. Not much - // can be done about this as Rust signal handling isn't - // really present at the moment. Revisit later. - let task = lazy(move || { - for (pin_numb, command) in pin_numb_command_pairs.drain(..) { - let mut last_press = Instant::now(); - let pin = Pin::new(pin_numb); - pin.export().expect("could not export pin"); - pin.set_direction(Direction::In).expect("could not set direction for pin"); - pin.set_edge(Edge::RisingEdge).expect("could not set interrupt to rising edge for pin"); - let tx = tx.clone(); - tokio::spawn(pin.get_value_stream().unwrap() - .for_each(move |val| { //TODO refactor - if val == 1 { - if last_press.elapsed() > Duration::from_millis(50) { - last_press = Instant::now(); - dbg!(pin_numb); - dbg!(val); - tx.send(Event::Command(command.clone())).unwrap(); - } - } - Ok(()) - }) - .map_err(|_| ())); - } - Ok(()) - }); - tokio::run(task); - Ok(()) -} - -pub fn start(tx: crossbeam_channel::Sender) { - thread::spawn(move || { - let pin_numb_command_pairs = vec!((16, Command::LampsDim), - (12, Command::LampsDimmest), - (13, Command::LampsToggle), - - (27, Command::LampsToggle), //left 3, left - (22, Command::LampsToggle), //left 3, middle - (18, Command::LampsToggle), //left 3, right - - (23, Command::LampsNight), //right 4, left most - (24, Command::LampsEvening), //right 4, left - (26, Command::LampsDay), //right 4, right - (17, Command::LampsToggle), //right 4, right most - ); //BCM pin number - - /*let pin_numb_command_pairs = vec!((4, Command::Test), //pin 4 is broken and will give sporadic highs if connected - (17, Command::Test), - (27, Command::Test), - - (22, Command::Test), - (5, Command::Test), - (6, Command::Test), - (13, Command::Test), - (26, Command::Test), - (18, Command::Test), - (23, Command::Test), - (24, Command::Test), - (25, Command::Test), - (12, Command::Test), - (16, Command::Test), - ); //BCM pin number */ - stream(pin_numb_command_pairs, tx).unwrap(); - }); -} diff --git a/src/input/buttons.rs b/src/input/buttons.rs new file mode 100755 index 00000000..77ab6b29 --- /dev/null +++ b/src/input/buttons.rs @@ -0,0 +1,70 @@ +extern crate sysfs_gpio; +extern crate futures; +extern crate tokio; + +use futures::{Future, lazy, Stream}; +use sysfs_gpio::{Direction, Edge, Pin}; +use std::thread; +use std::time::{Duration, Instant}; +use crossbeam_channel; + +use crate::controller::{Command, Event}; + +// when pressing 22, 24 is often activated +// 23 works perfectly +// 24 also works perfectly + +fn stream(mut pin_numb_command_pairs: Vec<(u64, Command)>, tx: crossbeam_channel::Sender) -> sysfs_gpio::Result<()> { + // NOTE: this currently runs forever and as such if + // the app is stopped (Ctrl-C), no cleanup will happen + // and the GPIO will be left exported. Not much + // can be done about this as Rust signal handling isn't + // really present at the moment. Revisit later. + let task = lazy(move || { + for (pin_numb, command) in pin_numb_command_pairs.drain(..) { + let mut last_press = Instant::now(); + let pin = Pin::new(pin_numb); + pin.export().expect("could not export pin"); + pin.set_direction(Direction::In).expect("could not set direction for pin"); + pin.set_edge(Edge::RisingEdge).expect("could not set interrupt to rising edge for pin"); + let tx = tx.clone(); + tokio::spawn(pin.get_value_stream().unwrap() + .for_each(move |val| { //TODO refactor + if val == 1 { + if last_press.elapsed() > Duration::from_millis(50) { + last_press = Instant::now(); + dbg!(pin_numb); + dbg!(val); + tx.send(Event::Command(command.clone())).unwrap(); + } + } + Ok(()) + }) + .map_err(|_| ())); + } + Ok(()) + }); + tokio::run(task); + Ok(()) +} + +pub fn start_monitoring(tx: crossbeam_channel::Sender) { + thread::spawn(move || { + let pin_numb_command_pairs = vec!( + (16, Command::LampsDim), + (12, Command::LampsDimmest), + (13, Command::LampsToggle), + + (27, Command::LampsToggle), //left 3, left + (22, Command::LampsToggle), //left 3, middle + (18, Command::LampsToggle), //left 3, right + + (23, Command::LampsNight), //right 4, left most + (24, Command::LampsEvening), //right 4, left + (26, Command::LampsDay), //right 4, right + (17, Command::LampsToggle), //right 4, right most + ); //BCM pin number + + stream(pin_numb_command_pairs, tx).unwrap(); + }); +} diff --git a/src/input/mod.rs b/src/input/mod.rs old mode 100644 new mode 100755 index b82f3c90..da6e02af --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -1,5 +1,7 @@ - -pub mod attached_sensors; +#[cfg(feature = "sensors_connected")] +pub mod sensors; +#[cfg(feature = "sensors_connected")] +pub mod buttons; pub mod web_api; pub mod alarms; diff --git a/src/input/mpd_status.rs b/src/input/mpd_status.rs old mode 100644 new mode 100755 index a3d9efd0..e7413505 --- a/src/input/mpd_status.rs +++ b/src/input/mpd_status.rs @@ -2,7 +2,7 @@ use mpd::{idle::Idle, idle::Subsystem, Client}; use crate::errors::Error; use std::thread; use std::sync::{Arc, RwLock}; -use crossbeam_channel::{bounded, Receiver, Sender}; +use crossbeam_channel::{Receiver, Sender}; //mpd watcher, waits on mpd sys changes and stores in struct/sends updates to whomever needs to know //mpd command sender (opens new connection for every command?) diff --git a/src/input/sensors/ble/mod.rs b/src/input/sensors/ble/mod.rs new file mode 100755 index 00000000..145fbaf3 --- /dev/null +++ b/src/input/sensors/ble/mod.rs @@ -0,0 +1,22 @@ +use secure_ble::{connect_to_adapter, connect_to_node, +authenticate_node, StreamCipher, subscribe, printvalues}; + +mod node_credentials; +use node_credentials::*; + + +pub fn init(){ + let central = connect_to_adapter(); + + let mut bed_node = connect_to_node(central, node_bed::ADRESS, Duration::from_secs(100)).unwrap(); + authenticate_node(&mut node_bed, node::bed::HMAC_KEY); + let bed_decryptor = StreamCipher::from_node(&mut sensor_node, node_bed::KEY); + let bed_fast_rx = subscribe(sensor_node.clone(), node_bed::HMAC_KEY, SLOW_MEASURMENTS_UUID); + let bed_slow_rx = subscribe(sensor_node.clone(), node_bed::HMAC_KEY, FAST_MEASURMENTS_UUID); + + let mut bed_node = connect_to_node(central, node_bed::ADRESS, Duration::from_secs(100)).unwrap(); + authenticate_node(&mut node_bed, node::bed::HMAC_KEY); + let bed_decryptor = StreamCipher::from_node(&mut sensor_node, node_bed::KEY); + let bed_rx = subscribe(sensor_node, node_bed::HMAC_KEY); + +} \ No newline at end of file diff --git a/src/input/sensors/ble/node_credentials.rs b/src/input/sensors/ble/node_credentials.rs new file mode 100755 index 00000000..bfe5431b --- /dev/null +++ b/src/input/sensors/ble/node_credentials.rs @@ -0,0 +1,24 @@ +use secure_ble::UUID; + +//shared +pub const FAST_MEASURMENTS_UUID: UUID = UUID::B128([137, 20, 153, 220, 231, 245, 91, 152, 153, 21, 183, 27, 175, 191, 112, 147]); +pub const SLOW_MEASURMENTS_UUID: UUID = UUID::B128([137, 20, 153, 220, 231, 245, 91, 152, 153, 21, 183, 27, 175, 191, 112, 147]); + +//specific +pub mod node_bed { + pub const KEY: [u8;16] + = [66,72,79,15,11,8,27,55,83,75,91,63,21,32,84,87]; + pub const HMAC_KEY: [u8;16] + = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; + pub const ADRESS: &str + = "C6:46:56:AC:2C:4C"; //TODO change +} + +pub mod node_bathroom { + pub const KEY: [u8;16] + = [66,72,79,15,11,8,27,55,83,75,91,63,21,32,84,87]; + pub const HMAC_KEY: [u8;16] + = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; + pub const ADRESS: &str + = "C6:46:56:AC:2C:4C"; +} \ No newline at end of file diff --git a/src/input/attached_sensors/bme280.rs b/src/input/sensors/local.rs old mode 100644 new mode 100755 similarity index 100% rename from src/input/attached_sensors/bme280.rs rename to src/input/sensors/local.rs diff --git a/src/input/attached_sensors/mod.rs b/src/input/sensors/mod.rs old mode 100644 new mode 100755 similarity index 71% rename from src/input/attached_sensors/mod.rs rename to src/input/sensors/mod.rs index 58f8f50e..833cbe65 --- a/src/input/attached_sensors/mod.rs +++ b/src/input/sensors/mod.rs @@ -1,27 +1,11 @@ -extern crate dataserver; extern crate chrono; extern crate smallvec; extern crate bytes; -use dataserver::{httpserver::timeseries_interface, httpserver::DataRouterHandle}; -use timeseries_interface::specifications::{MetaDataSpec, FieldSpec, FieldLength, FieldResolution}; -use self::chrono::{Utc}; - -use crossbeam_channel; - -#[cfg(feature = "sensors_connected")] -mod buttons; #[cfg(feature = "sensors_connected")] -mod bme280; - - -use std::thread; -use std::time::{Duration}; -use std::sync::{RwLock, Arc}; - -use crate::controller::{Event}; +mod local; -const LOCAL_SENSING_ID: timeseries_interface::DatasetId = 0; +//const LOCAL_SENSING_ID: timeseries_interface::DatasetId = 0; //TODO mechanisme for shutdown #[cfg(feature = "sensors_connected")] pub fn start_monitoring(tx: crossbeam_channel::Sender, data_router_handle: DataRouterHandle, dataset_handle: Arc>) { @@ -34,44 +18,38 @@ pub fn start_monitoring(tx: crossbeam_channel::Sender, data_router_handle let fields = dataset.metadata.fields.clone(); drop(data); - //init all sensors - let mut bme = bme280::init(); + //init all local sensors + let mut local_sensors = local::init(); + //subscribe and init remote sensors + ble::init(); - thread::spawn(move || {//TODO figure out shutdown behaviour + + /*thread::spawn(move || {//TODO figure out shutdown behaviour loop { //get all measurements let (humidity, temperature, pressure) = bme280::measure_and_record(&mut bme); - - //init new slow measurements - //TODO let now = Utc::now(); - //process data into events and send off as event //TODO + //process data into events and send off as event //encode all data - //dbg!(fields); let mut line: Vec = vec!(0;64); fields[0].encode::(humidity, &mut line); fields[1].encode::(temperature, &mut line); fields[2].encode::(pressure, &mut line); - //store data and send to active web_clients - dataserver::httpserver::signal_newdata(&data_router_handle, LOCAL_SENSING_ID, line.clone(), now.timestamp() ); - let mut data = dataset_handle.write().unwrap(); - let set = data.sets.get_mut(&LOCAL_SENSING_ID).unwrap(); - set.timeseries.append(now, &line).unwrap(); - //dbg!(&line); + //send data to dataserver drop(data); //sleep until 5 seconds are completed thread::sleep(Duration::from_secs(5)); } - }); + });*/ } -fn make_local_sensing_spec() -> MetaDataSpec { +/*fn make_local_sensing_spec() -> MetaDataSpec { let humidity_desk = FieldSpec::BitLength( FieldLength { name: String::from("humidity below desk"), min_value: 0.0f32, @@ -117,3 +95,4 @@ pub fn check_local_sensing_dataset(data: &Arc Ok(()) } } +*/ diff --git a/src/input/web_api/command_logins.rs b/src/input/web_api/command_logins.rs old mode 100644 new mode 100755 diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs old mode 100644 new mode 100755 index a8942d02..fc1f36ab --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -1,113 +1,105 @@ -extern crate actix_web_httpauth; - -use actix_web::Form; -use actix_web::FromRequest; -use actix_web_httpauth::extractors::basic::{BasicAuth, Config}; +use actix_web::web::{Form, Data}; +use actix_web_httpauth::extractors::basic::{BasicAuth}; use actix_web_httpauth::headers::www_authenticate::basic::Basic; -use actix_web_httpauth::headers::www_authenticate::{WWWAuthenticate}; +use actix_web_httpauth::headers::www_authenticate::WwwAuthenticate; use actix_web::http::StatusCode; use chrono::{DateTime, NaiveDateTime, Utc}; use serde::Deserialize; -use crate::ServerState; -use crate::actix_web::{HttpResponse, HttpRequest}; +use actix_web::HttpResponse; use crate::controller::{Command, TargetState, Event}; - mod command_logins; +pub mod server; +use server::State; + +fn authenticated(auth: BasicAuth) -> bool { -fn authenticated(req: &HttpRequest) -> bool { - let mut config = Config::default(); - config.realm("Restricted area"); - - if let Ok(auth) = BasicAuth::from_request(&req, &config){ - let username = auth.username(); - if let Some(password) = auth.password(){ - command_logins::LIST.into_iter() - .filter(|x| x.username==username) - .filter(|x| x.password==password) - .next().is_some() - } else {false } + let username = auth.user_id(); + if let Some(password) = auth.password(){ + command_logins::LIST.into_iter() + .filter(|x| x.username==username) + .filter(|x| x.password==password) + .next().is_some() } else {false } } -fn make_auth_error(req: &HttpRequest) -> HttpResponse { - let challenge = Basic {realm: Some("Restricted area".to_string()),}; - req.build_response(StatusCode::UNAUTHORIZED) - .set(WWWAuthenticate(challenge)) +fn make_auth_error() -> HttpResponse { + let challenge = Basic::with_realm("Restricted area"); + HttpResponse::Unauthorized() + .set(WwwAuthenticate(challenge)) .finish() } -fn make_error(req: &HttpRequest, _header: StatusCode) -> HttpResponse { - req.build_response(StatusCode::INTERNAL_SERVER_ERROR) - .finish() +fn make_error(statuscode: StatusCode) -> HttpResponse { + HttpResponse::build(statuscode).finish() } ///////////////////// lamp commands /////////////////////////////// -pub fn toggle(req: &HttpRequest) -> HttpResponse { - if authenticated(req) { - req.state().controller_addr.send(Event::Command(Command::LampsToggle)).unwrap(); +pub fn toggle(state: Data, auth: BasicAuth) -> HttpResponse { + if authenticated(auth) { + state.controller_addr.send(Event::Command(Command::LampsToggle)).unwrap(); HttpResponse::Ok().finish() } else { - make_auth_error(req) + make_auth_error() } } -pub fn dim(req: &HttpRequest) -> HttpResponse { - if authenticated(req) { - req.state().controller_addr.send(Event::Command(Command::LampsDim)).unwrap(); +pub fn dim(state: Data, auth: BasicAuth) -> HttpResponse { + if authenticated(auth) { + state.controller_addr.send(Event::Command(Command::LampsDim)).unwrap(); HttpResponse::Ok().finish() } else { - make_auth_error(req) + make_auth_error() } } -pub fn dimmest(req: &HttpRequest) -> HttpResponse { - if authenticated(req) { - req.state().controller_addr.send(Event::Command(Command::LampsDimmest)).unwrap(); +pub fn dimmest(state: Data, auth: BasicAuth) -> HttpResponse { + if authenticated(auth) { + state.controller_addr.send(Event::Command(Command::LampsDimmest)).unwrap(); HttpResponse::Ok().finish() } else { - make_auth_error(req) + make_auth_error() } } -pub fn normal(req: &HttpRequest) -> HttpResponse { - if authenticated(req) { - req.state().controller_addr.send(Event::Command(Command::LampsDay)).unwrap(); +pub fn normal(state: Data, auth: BasicAuth) -> HttpResponse { + if authenticated(auth) { + state.controller_addr.send(Event::Command(Command::LampsDay)).unwrap(); HttpResponse::Ok().finish() } else { - make_auth_error(req) + make_auth_error() } } -pub fn evening(req: &HttpRequest) -> HttpResponse { - if authenticated(req) { - req.state().controller_addr.send(Event::Command(Command::LampsEvening)).unwrap(); +pub fn evening(state: Data, auth: BasicAuth) -> HttpResponse { + if authenticated(auth) { + state.controller_addr.send(Event::Command(Command::LampsEvening)).unwrap(); HttpResponse::Ok().finish() } else { - make_auth_error(req) + make_auth_error() } } -pub fn night(req: &HttpRequest) -> HttpResponse { - if authenticated(req) { - req.state().controller_addr.send(Event::Command(Command::LampsNight)).unwrap(); +pub fn night(state: Data, auth: BasicAuth) -> HttpResponse { + if authenticated(auth) { + state.controller_addr.send(Event::Command(Command::LampsNight)).unwrap(); HttpResponse::Ok().finish() } else { - make_auth_error(req) + make_auth_error() } } //////////////////////// go to state commands ///////////////////////////////// -pub fn lightloop(req: &HttpRequest) -> HttpResponse { - if authenticated(req) { - req.state().controller_addr.send(Event::Command(Command::ChangeState(TargetState::LightLoop))).unwrap(); +pub fn lightloop(state: Data, auth: BasicAuth) -> HttpResponse { + if authenticated(auth) { + state.controller_addr.send(Event::Command(Command::ChangeState(TargetState::LightLoop))).unwrap(); HttpResponse::Ok().finish() } else { - make_auth_error(req) + make_auth_error() } } @@ -118,30 +110,31 @@ pub struct AlarmDataMinFrom { min_till_alarm: String, } -pub fn set_alarm_minutes_from_now((req, params): (HttpRequest, Form)) -> HttpResponse { - if authenticated(&req) { +/*pub fn set_alarm_minutes_from_now(req: HttpRequest, params: Form, + state: Data, auth: BasicAuth) -> HttpResponse { + if authenticated(auth) { //Code to parse alarm time dbg!(¶ms); if let Ok(minutes) = params.min_till_alarm.parse(){ let time = Utc::now() + chrono::Duration::minutes(minutes); - req.state().alarms.add_alarm(time).unwrap(); + state.alarms.add_alarm(time).unwrap(); HttpResponse::Ok().finish() } else { - make_error(&req, StatusCode::INTERNAL_SERVER_ERROR) + make_error(StatusCode::INTERNAL_SERVER_ERROR) } } else { - make_auth_error(&req) + make_auth_error() } -} +}*/ #[derive(Deserialize, Debug)] pub struct AlarmDataUnixTS { timestamp: String, } -pub fn set_alarm_unix_timestamp((req, params): (HttpRequest, Form)) -> HttpResponse { +pub fn set_alarm_unix_timestamp(params: Form, state: Data) -> HttpResponse { //Code to parse alarm time dbg!(¶ms); @@ -151,27 +144,27 @@ pub fn set_alarm_unix_timestamp((req, params): (HttpRequest, FormUtc::now() { - if req.state().alarms.add_alarm(time).is_ok() { - dbg!(("done setting alarm")); + if state.alarms.add_alarm(time).is_ok() { + dbg!("done setting alarm"); HttpResponse::Ok().finish() } else { dbg!(); - make_error(&req, StatusCode::INTERNAL_SERVER_ERROR) + make_error( StatusCode::INTERNAL_SERVER_ERROR) } } else { dbg!(); - make_error(&req, StatusCode::UNPROCESSABLE_ENTITY) + make_error(StatusCode::UNPROCESSABLE_ENTITY) } } else { dbg!(); - make_error(&req, StatusCode::INTERNAL_SERVER_ERROR) + make_error(StatusCode::INTERNAL_SERVER_ERROR) } } -pub fn list_alarms(req: &HttpRequest) -> HttpResponse { +pub fn list_alarms(state: Data) -> HttpResponse { //Code to parse alarm time - let alarms = req.state().alarms.list(); + let alarms = state.alarms.list(); let mut list = String::with_capacity(alarms.len()*30); for alarm in alarms { list.push_str(&alarm.to_rfc2822()); @@ -188,15 +181,15 @@ pub struct SongUrl { url: String, } -pub fn add_song_from_url((req, params): (HttpRequest, Form)) -> HttpResponse { +pub fn add_song_from_url(params: Form, state: Data) -> HttpResponse { let url = params.into_inner().url; dbg!(); - if req.state().youtube_dl.add_song_to_queue(url).is_ok(){ + if state.youtube_dl.add_song_to_queue(url).is_ok(){ dbg!(); HttpResponse::Ok().finish() } else { - make_error(&req, StatusCode::INTERNAL_SERVER_ERROR) + make_error(StatusCode::INTERNAL_SERVER_ERROR) } } \ No newline at end of file diff --git a/src/input/web_api/server/database.rs b/src/input/web_api/server/database.rs new file mode 100755 index 00000000..32c8904d --- /dev/null +++ b/src/input/web_api/server/database.rs @@ -0,0 +1,137 @@ +use serde::{Deserialize,Serialize}; + +use sled::{Db,Tree}; +use bincode; + +use ring::{digest, pbkdf2}; + +use std::num::NonZeroU32; +use std::sync::Arc; + +use chrono::{DateTime, Utc}; + +static DIGEST_ALG: &'static digest::Algorithm = &digest::SHA256; +const CREDENTIAL_LEN: usize = digest::SHA256_OUTPUT_LEN; +const PBKDF2_ITERATIONS: NonZeroU32 = unsafe {NonZeroU32::new_unchecked(100_000)}; +const DB_SALT_COMPONENT: [u8; 16] = [ // This value was generated from a secure PRNG. //TODO check this + 0xd6, 0x26, 0x98, 0xda, 0xf4, 0xdc, 0x50, 0x52, + 0x24, 0xf2, 0x27, 0xd1, 0xfe, 0x39, 0x01, 0x8a]; + +pub enum PasswDbError { + WrongUsername, + WrongPassword, + Internal, +} + +#[derive(Debug, Clone)] +pub struct PasswordDatabase { + pub storage: Arc, +} + +impl PasswordDatabase { + pub fn from_db(db: &Db) -> Result { + Ok(Self { + storage: db.open_tree("passw_database")?, //created it not exist + }) + } + + pub fn set_password(&mut self, username: &[u8], password: &[u8]) + -> Result<(), sled::Error> { + let salt = self.salt(username); + let mut credential = [0u8; CREDENTIAL_LEN]; + pbkdf2::derive(DIGEST_ALG, PBKDF2_ITERATIONS, &salt, password, &mut credential); + + self.storage.set(username, &credential)?; + self.storage.flush()?; + Ok(()) + } + + pub fn verify_password(&self, username: &[u8], attempted_password: &[u8]) + -> Result<(), PasswDbError> { + if let Ok(db_entry) = self.storage.get(username) { + if let Some(credential) = db_entry { + let salted_attempt = self.salt(username); + pbkdf2::verify(DIGEST_ALG, PBKDF2_ITERATIONS, &salted_attempt, + attempted_password, + &credential) + .map_err(|_| PasswDbError::WrongPassword) + } else { Err(PasswDbError::WrongUsername) } + } else { Err(PasswDbError::Internal )} + } + + pub fn is_user_in_database(&self, username: &[u8]) -> Result { + self.storage.contains_key(username) + } + + // The salt should have a user-specific component so that an attacker + // cannot crack one password for multiple users in the database. It + // should have a database-unique component so that an attacker cannot + // crack the same user's password across databases in the unfortunate + // but common case that the user has used the same password for + // multiple systems. + pub fn salt(&self, username: &[u8]) -> Vec { + let mut salt = Vec::with_capacity(DB_SALT_COMPONENT.len() + username.len()); + salt.extend(DB_SALT_COMPONENT.as_ref()); + salt.extend(username); + salt + } +} + + + +#[derive(Debug, Clone)] +pub struct UserDatabase { + pub storage: Arc, +} + +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +pub struct UserInfo { + pub last_login: DateTime, + pub username: String, +} + +#[derive(Debug)] +pub enum UserDbError { + UserNotInDb, + DatabaseError(sled::Error), + SerializeError(bincode::Error), +} + +impl From for UserDbError { + fn from(error: sled::Error) -> Self { + UserDbError::DatabaseError(error) + } +} +impl From for UserDbError { + fn from(error: bincode::Error) -> Self { + UserDbError::SerializeError(error) + } +} + + +impl UserDatabase { + pub fn from_db(db: &Db) -> Result { + Ok(Self { + storage: db.open_tree("user_database")?, //created it not exist + }) + } + + pub fn get_userdata>(&self, username: T) -> Result { + let username = username.as_ref(); + if let Some(user_data) = self.storage.get(username)? { + let user_info = bincode::deserialize(&user_data)?; + Ok(user_info) + } else { + Err(UserDbError::UserNotInDb) + } + } + + pub fn set_userdata(&mut self, user_info: UserInfo) + -> Result <(),UserDbError> { + let username = user_info.username.as_str().as_bytes(); + let user_data = bincode::serialize(&user_info)?; + self.storage.set(username,user_data)?; + self.storage.flush()?; + Ok(()) + } +} diff --git a/src/input/web_api/server/login.rs b/src/input/web_api/server/login.rs new file mode 100755 index 00000000..621b9651 --- /dev/null +++ b/src/input/web_api/server/login.rs @@ -0,0 +1,81 @@ +use actix_identity::{Identity}; +use actix_web::Result as wResult; +use actix_web::{ + http, + HttpRequest, HttpResponse, +}; +use actix_web::web::{Data, Form}; +use rand::{Rng,FromEntropy}; +use serde::Deserialize; + +use std::sync::{Arc, Mutex, atomic::Ordering}; + +use super::{State, Session}; + +pub fn logout(id: Identity) -> HttpResponse { + id.forget(); + HttpResponse::Found().finish() +} + +pub fn login_page() -> HttpResponse { + let page = include_str!("static_webpages/login.html"); + HttpResponse::Ok().header(http::header::CONTENT_TYPE, "text/html; charset=utf-8").body(page) +} + +#[derive(Deserialize)] +pub struct Logindata { + u: String, + p: String, +} + +/// State and POST Params +pub fn login_get_and_check( + id: Identity, + state: Data, + req: HttpRequest, + params: Form) -> wResult { + + trace!("checking login"); + + //time function duration + let now = std::time::Instant::now(); + + //if login valid (check passwdb) load userinfo + if state.passw_db.verify_password(params.u.as_str().as_bytes(), params.p.as_str().as_bytes()).is_err(){ + warn!("incorrect password"); + return Ok(HttpResponse::build(http::StatusCode::UNAUTHORIZED) + .content_type("text/plain") + .body("incorrect password or username")); + } else { info!("user logged in");} + + //copy userinfo into new session + let _userinfo = state.user_db.get_userdata(¶ms.u).unwrap(); + //userinfo.last_login = Utc::now(); + //passw_db.set_userdata(params.u.as_str().as_bytes(), userinfo.clone()); + + let session = Session { + last_login: chrono::Utc::now(), //TODO write back to database + }; + //find free session_numb, set new session number and store new session + let session_id = state.free_session_ids.fetch_add(1, Ordering::Acquire); + let mut sessions = state.sessions.write().unwrap(); + sessions.insert(session_id as u16, Arc::new(Mutex::new(session))); + + //sign and send session id cookie to user + id.remember(session_id.to_string()); + info!("remembering session"); + + let end = std::time::Instant::now(); + println!("{:?}", end-now); + + Ok(HttpResponse::Found() + .header(http::header::LOCATION, req.path()["/login".len()..].to_owned()) + .finish()) +} + +pub fn make_random_cookie_key() -> [u8; 32] { + let mut cookie_private_key = [0u8; 32]; + let mut rng = rand::rngs::StdRng::from_entropy(); + rng.fill(&mut cookie_private_key[..]); + cookie_private_key +} \ No newline at end of file diff --git a/src/input/web_api/server/login_redirect.rs b/src/input/web_api/server/login_redirect.rs new file mode 100755 index 00000000..e7299014 --- /dev/null +++ b/src/input/web_api/server/login_redirect.rs @@ -0,0 +1,91 @@ +use actix_service::{Service, Transform}; +use actix_web::dev::{ServiceRequest, ServiceResponse}; +use actix_web::{http, Error, HttpResponse, web}; + +use futures::future::{ok, Either, FutureResult}; +use futures::Poll; + +use log::{info}; + +use super::State; +use actix_identity::RequestIdentity; + +#[derive(Default)] +pub struct CheckLogin; + +impl Transform for CheckLogin +where + S: Service, Error = Error>, + S::Future: 'static, +{ + type Request = ServiceRequest; + type Response = ServiceResponse; + type Error = Error; + type InitError = (); + type Transform = CheckLoginMiddleware; + type Future = FutureResult; + + fn new_transform(&self, service: S) -> Self::Future { + ok(CheckLoginMiddleware { service }) + } +} + +pub struct CheckLoginMiddleware { + service: S, +} + +//TODO can we get data into the middleware? look at existing identityservice +fn is_logged_in(state: &web::Data, id: String) -> Result<(),()> { + if let Ok(id) = id.parse::(){ + //check if valid session (identity key contained in sessions) + if state.sessions.read().unwrap().contains_key(&id){ + Ok(()) + } else { + Err(()) + } + } else {Err(()) } + +} + +impl Service for CheckLoginMiddleware +where + S: Service, Error = Error>, + S::Future: 'static, +{ + type Request = ServiceRequest; + type Response = ServiceResponse; + type Error = Error; + type Future = Either>; + + fn poll_ready(&mut self) -> Poll<(), Self::Error> { + self.service.poll_ready() + } + + fn call(&mut self, req: ServiceRequest) -> Self::Future { + // We only need to hook into the `start` for this middleware. + + if let Some(id) = req.get_identity() { + let data: web::Data = req.app_data().unwrap(); + if is_logged_in(&data, id).is_ok() { + Either::A(self.service.call(req)) + } else { + let redirect = "/login".to_owned()+req.path(); + Either::B(ok(req.into_response( + HttpResponse::Found() + .header(http::header::LOCATION, redirect) + .finish() + .into_body(), //TODO why comma? is needed? + ))) + } + } else { + info!("could not get identity thus redirecting"); + let redirect = "/login".to_owned()+req.path(); + Either::B(ok(req.into_response( + HttpResponse::Found() + .header(http::header::LOCATION, redirect) + .finish() + .into_body(), //TODO why comma? is needed? + ))) + } + } +} \ No newline at end of file diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs new file mode 100755 index 00000000..3d6a97f1 --- /dev/null +++ b/src/input/web_api/server/mod.rs @@ -0,0 +1,54 @@ +use chrono::{DateTime, Utc}; +use rustls::{NoClientAuth, ServerConfig}; +use rustls::internal::pemfile::{certs, pkcs8_private_keys}; +use actix_web::HttpRequest; + +use std::sync::{Arc, Mutex, RwLock, atomic::AtomicUsize}; +use std::collections::HashMap; +use std::path::Path; +use std::io::BufReader; +use std::fs::File; + +use crate::input; +use crate::controller::Event; + +pub mod database; +pub mod login_redirect; +pub mod login; + +pub use database::{PasswordDatabase,UserDatabase}; +pub use login::make_random_cookie_key; +pub use login_redirect::CheckLogin; + + +pub struct Session {//TODO deprecate + last_login: DateTime, + //add more temporary user specific data as needed +} + +pub struct State { + pub controller_addr: crossbeam_channel::Sender, + pub alarms: input::alarms::Alarms, + pub passw_db: PasswordDatabase, + pub user_db: UserDatabase, + pub sessions: Arc> >>> , + pub free_session_ids: Arc, + pub youtube_dl: input::YoutubeDownloader, +} + +pub fn make_tls_config>(signed_cert_path: P, private_key_path: P) -> rustls::ServerConfig{ + let mut tls_config = ServerConfig::new(NoClientAuth::new()); + let cert_file = &mut BufReader::new(File::open(signed_cert_path).unwrap()); + let key_file = &mut BufReader::new(File::open(private_key_path).unwrap()); + let cert_chain = certs(cert_file).unwrap(); + let mut key = pkcs8_private_keys(key_file).unwrap(); + + tls_config + .set_single_cert(cert_chain, key.pop().unwrap()) + .unwrap(); + tls_config +} + +pub fn index(_req: HttpRequest) -> &'static str { + "Hello world!" +} \ No newline at end of file diff --git a/src/input/web_api/server/static_webpages/login.css b/src/input/web_api/server/static_webpages/login.css new file mode 100755 index 00000000..be527f76 --- /dev/null +++ b/src/input/web_api/server/static_webpages/login.css @@ -0,0 +1,57 @@ +@import url(https://fonts.googleapis.com/css?family=Open+Sans); +.btn { display: inline-block; *display: inline; *zoom: 1; padding: 4px 10px 4px; margin-bottom: 0; font-size: 13px; line-height: 18px; color: #333333; text-align: center;text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); vertical-align: middle; background-color: #f5f5f5; background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); background-image: linear-gradient(top, #ffffff, #e6e6e6); background-repeat: repeat-x; filter: progid:dximagetransform.microsoft.gradient(startColorstr=#ffffff, endColorstr=#e6e6e6, GradientType=0); border-color: #e6e6e6 #e6e6e6 #e6e6e6; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border: 1px solid #e6e6e6; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); cursor: pointer; *margin-left: .3em; } +.btn:hover, .btn:active, .btn.active, .btn.disabled, .btn[disabled] { background-color: #e6e6e6; } +.btn-large { padding: 9px 14px; font-size: 15px; line-height: normal; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } +.btn:hover { color: #333333; text-decoration: none; background-color: #e6e6e6; background-position: 0 -15px; -webkit-transition: background-position 0.1s linear; -moz-transition: background-position 0.1s linear; -ms-transition: background-position 0.1s linear; -o-transition: background-position 0.1s linear; transition: background-position 0.1s linear; } +.btn-primary, .btn-primary:hover { text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); color: #ffffff; } +.btn-primary.active { color: rgba(255, 255, 255, 0.75); } +.btn-primary { background-color: #4a77d4; background-image: -moz-linear-gradient(top, #6eb6de, #4a77d4); background-image: -ms-linear-gradient(top, #6eb6de, #4a77d4); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#6eb6de), to(#4a77d4)); background-image: -webkit-linear-gradient(top, #6eb6de, #4a77d4); background-image: -o-linear-gradient(top, #6eb6de, #4a77d4); background-image: linear-gradient(top, #6eb6de, #4a77d4); background-repeat: repeat-x; filter: progid:dximagetransform.microsoft.gradient(startColorstr=#6eb6de, endColorstr=#4a77d4, GradientType=0); border: 1px solid #3762bc; text-shadow: 1px 1px 1px rgba(0,0,0,0.4); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.5); } +.btn-primary:hover, .btn-primary:active, .btn-primary.active, .btn-primary.disabled, .btn-primary[disabled] { filter: none; background-color: #4a77d4; } +.btn-block { width: 100%; display:block; } + +* { -webkit-box-sizing:border-box; -moz-box-sizing:border-box; -ms-box-sizing:border-box; -o-box-sizing:border-box; box-sizing:border-box; } + +html { width: 100%; height:100%; overflow:hidden; } + +body { + width: 100%; + height:100%; + font-family: 'Open Sans', sans-serif; + background: #092756; + background: -moz-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%),-moz-linear-gradient(top, rgba(57,173,219,.25) 0%, rgba(42,60,87,.4) 100%), -moz-linear-gradient(-45deg, #670d10 0%, #092756 100%); + background: -webkit-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%), -webkit-linear-gradient(top, rgba(57,173,219,.25) 0%,rgba(42,60,87,.4) 100%), -webkit-linear-gradient(-45deg, #670d10 0%,#092756 100%); + background: -o-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%), -o-linear-gradient(top, rgba(57,173,219,.25) 0%,rgba(42,60,87,.4) 100%), -o-linear-gradient(-45deg, #670d10 0%,#092756 100%); + background: -ms-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%), -ms-linear-gradient(top, rgba(57,173,219,.25) 0%,rgba(42,60,87,.4) 100%), -ms-linear-gradient(-45deg, #670d10 0%,#092756 100%); + background: -webkit-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%), linear-gradient(to bottom, rgba(57,173,219,.25) 0%,rgba(42,60,87,.4) 100%), linear-gradient(135deg, #670d10 0%,#092756 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3E1D6D', endColorstr='#092756',GradientType=1 ); +} +.login { + position: absolute; + top: 50%; + left: 50%; + margin: -150px 0 0 -150px; + width:300px; + height:300px; +} +.login h1 { color: #fff; text-shadow: 0 0 10px rgba(0,0,0,0.3); letter-spacing:1px; text-align:center; } + +input { + width: 100%; + margin-bottom: 10px; + background: rgba(0,0,0,0.3); + border: none; + outline: none; + padding: 10px; + font-size: 13px; + color: #fff; + text-shadow: 1px 1px 1px rgba(0,0,0,0.3); + border: 1px solid rgba(0,0,0,0.3); + border-radius: 4px; + box-shadow: inset 0 -5px 45px rgba(100,100,100,0.2), 0 1px 1px rgba(255,255,255,0.2); + -webkit-transition: box-shadow .5s ease; + -moz-transition: box-shadow .5s ease; + -o-transition: box-shadow .5s ease; + -ms-transition: box-shadow .5s ease; + transition: box-shadow .5s ease; +} +input:focus { box-shadow: inset 0 -5px 45px rgba(100,100,100,0.4), 0 1px 1px rgba(255,255,255,0.2); } diff --git a/src/input/web_api/server/static_webpages/login.html b/src/input/web_api/server/static_webpages/login.html new file mode 100755 index 00000000..00f96978 --- /dev/null +++ b/src/input/web_api/server/static_webpages/login.html @@ -0,0 +1,12 @@ + + +WebSocket Test + + diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs old mode 100644 new mode 100755 index 21f3232a..413076be --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -1,15 +1,11 @@ use std::process::Command; use std::io::copy; - use std::fs; use std::os::unix::fs::OpenOptionsExt; - -use std::time::Duration; use std::thread; -use crossbeam_channel::{unbounded, Receiver, Sender}; use std::path::Path; -use reqwest::{IntoUrl, get}; +use reqwest::{IntoUrl}; use crate::errors::Error; diff --git a/src/main.rs b/src/main.rs old mode 100644 new mode 100755 index 6a671a98..f3cd7e47 --- a/src/main.rs +++ b/src/main.rs @@ -1,26 +1,16 @@ -extern crate dataserver; -extern crate actix_web; #[macro_use] extern crate log; extern crate chrono; -use crate::actix_web::actix::Arbiter; -use crate::actix_web::{server,App,http::Method}; -use crate::actix_web::middleware::identity::{CookieIdentityPolicy, IdentityService}; - -use crate::chrono::Duration; +use actix_web::{HttpServer,App, web}; +use actix_identity::{CookieIdentityPolicy, IdentityService}; +use actix_files as fs; use sled; use std::sync::atomic::{AtomicUsize}; use std::thread; -use dataserver::{certificate_manager, httpserver}; -use dataserver::helper; -use dataserver::httpserver::{secure_database::PasswordDatabase, timeseries_interface, ServerHandle, DataRouterHandle, CheckLogin}; -use dataserver::httpserver::{ws_index, index, logout, newdata, plot_data, list_data, login_get_and_check, login_page, serve_file}; -use dataserver::httpserver::{InnerState, DataServerState}; - use std::sync::{Arc, RwLock}; use std::io::stdin; use std::collections::HashMap; @@ -30,147 +20,98 @@ use controller::Event; mod input; use input::web_api; +use input::web_api::server; +use server::{CheckLogin, PasswordDatabase, UserDatabase, index}; +use server::login::{login_get_and_check, login_page, logout}; mod errors; -pub struct ServerState { - controller_addr: crossbeam_channel::Sender, - alarms: input::alarms::Alarms, - dataserver_state: DataServerState, - youtube_dl: input::YoutubeDownloader, -} - -impl InnerState for ServerState { - fn inner_state(&self) -> &DataServerState { - &self.dataserver_state - } -} - -const FORCE_CERT_REGEN: bool = false; - #[cfg(feature = "live_server")] const SOCKETADDR: &'static str = "0.0.0.0:8080"; #[cfg(not(feature = "live_server"))] const SOCKETADDR: &'static str = "0.0.0.0:8070"; pub fn start_webserver(signed_cert: &str, private_key: &str, - data: Arc>, - passw_db: Arc>, - sessions: Arc>>, + passw_db: PasswordDatabase, + user_db: UserDatabase, controller_tx: crossbeam_channel::Sender, alarms: input::alarms::Alarms, youtube_dl: input::YoutubeDownloader, - mpd_status: input::MpdStatus, - ) -> (DataRouterHandle, ServerHandle) { + _mpd_status: input::MpdStatus, + ) -> actix_web::dev::Server { - let tls_config = httpserver::make_tls_config(signed_cert, private_key); - let cookie_key = httpserver::make_random_cookie_key(); - - let free_session_ids = Arc::new(AtomicUsize::new(0)); - let free_ws_session_ids = Arc::new(AtomicUsize::new(0)); + let tls_config = server::make_tls_config(signed_cert, private_key); + let cookie_key = server::make_random_cookie_key(); + let free_session_ids = Arc::new(AtomicUsize::new(0)); + let sessions = Arc::new(RwLock::new(HashMap::new())); let (tx, rx) = crossbeam_channel::unbounded(); + thread::spawn(move || { // Start data server actor in separate thread - let sys = actix::System::new("http-server"); - let data_server = Arbiter::start(|_| httpserver::websocket_data_router::DataServer::default()); - let data_server_clone = data_server.clone(); + let sys = actix_rt::System::new("http-server"); - let web_server = server::new(move || { + let web_server = HttpServer::new(move || { // data the webservers functions have access to - let dataserver_state = DataServerState { - passw_db: passw_db.clone(), - websocket_addr: data_server_clone.clone(), - data: data.clone(), - sessions: sessions.clone(), - free_session_ids: free_session_ids.clone(), - free_ws_session_ids: free_ws_session_ids.clone(), - }; - let state = ServerState { - controller_addr: controller_tx.clone(), + let data = actix_web::web::Data::new(server::State { + controller_addr: controller_tx.clone(), alarms: alarms.clone(), - dataserver_state, + passw_db: passw_db.clone(), + user_db: user_db.clone(), youtube_dl: youtube_dl.clone(), - }; - - App::with_state(state) - .middleware(IdentityService::new( - CookieIdentityPolicy::new(&cookie_key[..]) - .domain("deviousd.duckdns.org") - .name("auth-cookie") - .path("/") - .max_age(Duration::weeks(1)) - .secure(true), - )) - .middleware(CheckLogin{ - public_roots: vec!(String::from("/commands")), - ..CheckLogin::default() - }) - // homeautomation actions activated by https calls - .resource(r"/commands/lamps/toggle", |r| r.method(Method::GET).f(web_api::toggle)) - .resource(r"/commands/lamps/evening", |r| r.method(Method::GET).f(web_api::evening)) - .resource(r"/commands/lamps/night", |r| r.method(Method::GET).f(web_api::night)) - .resource(r"/commands/lamps/day", |r| r.method(Method::GET).f(web_api::normal)) - .resource(r"/commands/lamps/dimmest", |r| r.method(Method::GET).f(web_api::dimmest)) - .resource(r"/commands/lamps/dim", |r| r.method(Method::GET).f(web_api::dim)) - - .resource(r"/commands/lightLoop", |r| r.method(Method::GET).f(web_api::lightloop)) - - //currently not used - //.resource(r"/commands/set/wakeup_alarm", |r| r.method(Method::POST).with(web_api::set_alarm_minutes_from_now)) + sessions: sessions.clone(), + free_session_ids: free_session_ids.clone(), + }); + + App::new() + .register_data(data) + .wrap(IdentityService::new( + CookieIdentityPolicy::new(&cookie_key[..]) + .domain("deviousd.duckdns.org") + .name("auth-cookie") + .path("/") + .secure(true), + )) + .service( + web::scope("/login") + .service(web::resource(r"/{path}") + .route(web::post().to(login_get_and_check)) + .route(web::get().to(login_page)) + )) + .service(web::resource("/commands/lamps/toggle").to(web_api::toggle)) + .service(web::resource("/commands/lamps/evening").to(web_api::evening)) + .service(web::resource("/commands/lamps/night").to(web_api::night)) + .service(web::resource("/commands/lamps/day").to(web_api::normal)) + .service(web::resource("/commands/lamps/dimmest").to(web_api::dimmest)) + .service(web::resource("/commands/lamps/dim").to(web_api::dim)) + + .service(web::resource("/commands/lightloop").to(web_api::lightloop)) + .service(web::scope("/") + .wrap(CheckLogin) - // websocket route - // note some browsers need already existing http connection to - // this server for the upgrade to wss to work - .resource("/", |r| r.f(index)) - .resource("/ws/", |r| r.method(Method::GET).f(ws_index)) - .resource("/logout", |r| r.f(logout)) - .resource(r"/newdata", |r| r.method(Method::POST).f(newdata)) - .resource("/plot", |r| r.f(plot_data)) - .resource(r"/list_data.html", |r| r.method(Method::GET).f(list_data)) - - .resource(r"/add_song", |r| r.method(Method::POST).with(web_api::add_song_from_url)) - .resource(r"/set_alarm", |r| r.method(Method::POST).with(web_api::set_alarm_unix_timestamp)) - .resource(r"/list_alarms", |r| r.method(Method::GET).f(web_api::list_alarms)) - - //login route, every uri starting "/login" will be forwarded to the adress - //after "/login" once the client has been authenticated - .resource(r"/login/{tail:.*}", |r| { - r.method(Method::POST).with(login_get_and_check); - r.method(Method::GET).f(login_page); - }) + .service(web::resource("").to(index)) + .service(web::resource("logout/").to(logout)) + .service(web::resource("add_song").to(web_api::add_song_from_url)) + .service(web::resource("set_alarm").to(web_api::set_alarm_unix_timestamp)) + .service(web::resource("list_alarms").to(web_api::list_alarms)) //for all other urls we try to resolve to static files in the "web" dir - .resource(r"/{tail:.*}", |r| r.f(serve_file)) + .service(fs::Files::new("", "./web/")) + ) }) .bind_rustls(SOCKETADDR, tls_config).unwrap() //.bind("0.0.0.0:8080").unwrap() //without tcp use with debugging (note: https -> http, wss -> ws) .shutdown_timeout(5) // shut down 5 seconds after getting the signal to shut down .start(); - let _ = tx.send((data_server, web_server)); + let _ = tx.send(web_server); let _ = sys.run(); }); - let (data_handle, web_handle) = rx.recv().unwrap(); - (data_handle, web_handle) + let web_handle = rx.recv().unwrap(); + web_handle } fn main() { - //https://www.deviousd.duckdns.org:8080/index.html - //only do if certs need update - if FORCE_CERT_REGEN { - //generate_and_sign_keys - if let Err(error) = certificate_manager::generate_and_sign_keys( - "deviousd.duckdns.org", - "keys/cert.key", - "keys/cert.cert", - "keys/user.key", - ) { - println!("could not auto generate certificate, error: {:?}", error) - } - } - - helper::setup_logging(2).expect("could not set up debugging"); let config = sled::ConfigBuilder::new() .path("database".to_owned()) @@ -179,9 +120,9 @@ fn main() { let db = sled::Db::start(config).unwrap(); - let passw_db = Arc::new(RwLock::new(PasswordDatabase::load("").unwrap()));//replace with wrapper around db - let dataset_handle = Arc::new(RwLock::new(timeseries_interface::init("data").unwrap())); - let sessions = Arc::new(RwLock::new(HashMap::new())); + let passw_db = PasswordDatabase::from_db(&db).unwrap(); + let user_db = UserDatabase::from_db(&db).unwrap(); + let (controller_tx, controller_rx) = crossbeam_channel::unbounded(); let _controller_thread = controller::start(controller_rx).unwrap(); @@ -189,36 +130,30 @@ fn main() { let (youtube_dl, _downloader_thread) = input::YoutubeDownloader::init().unwrap(); let (mpd_status, _mpd_watcher_thread, updater_tx) = input::MpdStatus::start_updating().unwrap(); - //verify dataset integrity - input::attached_sensors::check_local_sensing_dataset(&dataset_handle).unwrap(); - //start the webserver - let (data_router_handle, web_handle) = start_webserver("keys/cert.key", "keys/cert.cert", - dataset_handle.clone(), passw_db.clone(), sessions.clone(), - controller_tx.clone(), alarms.clone(), youtube_dl.clone(), mpd_status.clone()); + let web_handle = start_webserver("keys/cert.key", "keys/cert.cert" + ,passw_db.clone(), user_db.clone(), controller_tx.clone() + ,alarms.clone(), youtube_dl.clone(), mpd_status.clone()); - //TODO start the telegram server - //TODO + //TODO start the telegram server (for sending commands) //start monitoring local sensors #[cfg(feature = "sensors_connected")] - input::attached_sensors::start_monitoring(controller_tx.clone(), data_router_handle, dataset_handle.clone()); + input::sensors::start_monitoring(controller_tx.clone()); + #[cfg(feature = "sensors_connected")] + input::buttons::start_monitoring(controller_tx.clone()); println!("press: t to send test data, n: to add a new user, q to quit, a to add new dataset, u to add fields to a user"); loop { let mut input = String::new(); stdin().read_line(&mut input).unwrap(); match input.as_str() { - "t\n" => helper::send_test_data_over_http(dataset_handle.clone(), 8080), - //"x\n" => httpserver::signal_newdata(data_handle.clone(),0), - "n\n" => helper::add_user(& passw_db), - "a\n" => helper::add_dataset(&passw_db, &dataset_handle), - "u\n" => helper::add_fields_to_user(&passw_db), + //"n\n" => helper::add_user(& passw_db), "q\n" => break, _ => println!("unhandled"), }; } println!("shutting down"); - httpserver::stop(web_handle); + web_handle.stop(true); input::MpdStatus::stop_updating(updater_tx); } diff --git a/web/add_song.html b/web/add_song.html old mode 100644 new mode 100755 diff --git a/web/graph.html b/web/graph.html old mode 100644 new mode 100755 diff --git a/web/graphDebug.html b/web/graphDebug.html old mode 100644 new mode 100755 diff --git a/web/login.css b/web/login.css old mode 100644 new mode 100755 diff --git a/web/login.html b/web/login.html old mode 100644 new mode 100755 diff --git a/web/plot.js b/web/plot.js old mode 100644 new mode 100755 diff --git a/web/plot_debug.js b/web/plot_debug.js old mode 100644 new mode 100755 diff --git a/web/set_alarm.html b/web/set_alarm.html old mode 100644 new mode 100755 diff --git a/web/test.html b/web/test.html old mode 100644 new mode 100755 diff --git a/web/test_decode.html b/web/test_decode.html old mode 100644 new mode 100755 diff --git a/web/test_graph_updates.html b/web/test_graph_updates.html old mode 100644 new mode 100755 diff --git a/web/test_ws_interface.html b/web/test_ws_interface.html old mode 100644 new mode 100755 diff --git a/web/websocket.html b/web/websocket.html old mode 100644 new mode 100755 diff --git a/web/websocket_getData.html b/web/websocket_getData.html old mode 100644 new mode 100755 diff --git a/web/websocket_getData2.html b/web/websocket_getData2.html old mode 100644 new mode 100755 From dd0755f8b30530fbe2f86dea20ff6806a44f1a26 Mon Sep 17 00:00:00 2001 From: dskleingeld Date: Sun, 3 Nov 2019 00:26:18 +0100 Subject: [PATCH 018/687] completes move to dataserver for showing data --- Cargo.lock | 76 +++++++-- Cargo.toml | 9 +- src/controller/mod.rs | 10 +- src/controller/states/lightloop.rs | 4 +- src/controller/states/normal.rs | 4 +- src/controller/states/wakeup.rs | 4 +- src/input/sensors/ble/mod.rs | 18 +-- src/input/sensors/fields/compression.rs | 200 ++++++++++++++++++++++++ src/input/sensors/fields/mod.rs | 42 +++++ src/input/sensors/local.rs | 23 +++ src/input/sensors/mod.rs | 99 ++++-------- src/main.rs | 1 + 12 files changed, 388 insertions(+), 102 deletions(-) create mode 100644 src/input/sensors/fields/compression.rs create mode 100644 src/input/sensors/fields/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 2a9f4535..7879008b 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,8 +22,9 @@ dependencies = [ "linux-embedded-hal 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mpd 0.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", - "philipshue 0.3.2", + "philipshue 0.3.2 (git+https://github.com/dskleingeld/philipshue)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", "retry 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -642,7 +643,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1559,7 +1560,20 @@ dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1568,26 +1582,45 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-bigint" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-complex" version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-complex" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-integer" version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1597,7 +1630,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1607,22 +1640,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-rational" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-traits" version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "num_cpus" @@ -1789,6 +1836,7 @@ dependencies = [ [[package]] name = "philipshue" version = "0.3.2" +source = "git+https://github.com/dskleingeld/philipshue#68eeaf2f006accaaa2cf289a992e347a92b5b013" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2237,6 +2285,7 @@ version = "0.1.0" dependencies = [ "aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3268,13 +3317,17 @@ dependencies = [ "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" "checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" +"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" "checksum num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" +"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" "checksum num-complex 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "b288631d7878aaf59442cffd36910ea604ecd7745c36054328595114001c9656" +"checksum num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" "checksum num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e" +"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" +"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" "checksum openssl 0.10.22 (registry+https://github.com/rust-lang/crates.io-index)" = "a51f452b82d622fc8dd973d7266e9055ac64af25b957d9ced3989142dc61cb6b" @@ -3292,6 +3345,7 @@ dependencies = [ "checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" +"checksum philipshue 0.3.2 (git+https://github.com/dskleingeld/philipshue)" = "" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" diff --git a/Cargo.toml b/Cargo.toml index 65b0527a..67a00d4f 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,9 +23,9 @@ actix-service = "0.4.1" actix-web-httpauth = "0.3.2" rustls = "0.15.2" -#philipshue = { git = "https://github.com/dskleingeld/philipshue", branch = "master" } -#for local dev purpose we use below targets -philipshue = { path = "../philipshue"} +philipshue = { git = "https://github.com/dskleingeld/philipshue", branch = "master" } +# for local dev purpose we use below targets +# philipshue = { path = "../philipshue"} secure-ble = { path = "../home_sensors/ble/central"} serde = { version = "1.0", features = ["derive"] } @@ -47,12 +47,13 @@ smallvec = "0.6.6" chrono = { version = "0.4.6", features = ["serde"] } bytes = "0.4.11" byteorder = "1.3.1" +num = { version = "0.2"} crossbeam-channel = "0.3" sled = "0.24.1" pagecache = "0.17.0" -reqwest = "0.9.17" +reqwest = "0.9.15" mpd = "0.0.12" dirs = "2.0.1" diff --git a/src/controller/mod.rs b/src/controller/mod.rs index b407c3b3..fb497045 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -14,13 +14,16 @@ use commands::{handle_cmd}; pub use commands::Command; pub use states::TargetState; - +#[cfg(feature = "sensors_connected")] +use crate::input::sensors::SensorValue; use crate::errors::Error; pub enum Event { Update, Alarm, Test, + #[cfg(feature = "sensors_connected")] + Sensor(SensorValue), Command(Command), } @@ -68,7 +71,7 @@ pub fn start(rx: crossbeam_channel::Receiver) -> Result) -> Result {state.update(&mut mods, &mut system, &mut env)}, (Event::Alarm, _) => {change_state(TargetState::WakeUp, &mut mods, &mut system)}, (Event::Test, _) => {dbg!("a test happend"); change_state(TargetState::WakeUp, &mut mods, &mut system)}, + + #[cfg(feature = "sensors_connected")] + (Event::Sensor(_), _) => {dbg!("sensor data recieved"); state} }; } }); diff --git a/src/controller/states/lightloop.rs b/src/controller/states/lightloop.rs index f588bf9c..4bb4be04 100755 --- a/src/controller/states/lightloop.rs +++ b/src/controller/states/lightloop.rs @@ -1,4 +1,4 @@ -use super::super::{Modifications, System}; +use super::super::{Modifications, System, Environment}; use super::{RoomState, ActiveState}; use super::normal; @@ -10,7 +10,7 @@ pub struct LightLoop { } impl RoomState for LightLoop { - fn update(mut self, mods: &mut Modifications, sys: &mut System) -> ActiveState { + fn update(mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> ActiveState { dbg!("updating lightloop state"); if self.counter == 0 { ActiveState::Normal(normal::Normal::enter(mods, sys)) diff --git a/src/controller/states/normal.rs b/src/controller/states/normal.rs index 6a55c368..a6479569 100755 --- a/src/controller/states/normal.rs +++ b/src/controller/states/normal.rs @@ -1,4 +1,4 @@ -use super::super::{Modifications, System}; +use super::super::{Modifications, System, Environment}; use super::{RoomState, ActiveState}; use std::time::{Duration, Instant}; @@ -7,7 +7,7 @@ use std::time::{Duration, Instant}; pub struct Normal {} impl RoomState for Normal { - fn update(self, _mods: &mut Modifications, _sys: &mut System) -> ActiveState { + fn update(self, _mods: &mut Modifications, _sys: &mut System, _env: &mut Environment) -> ActiveState { //dbg!("updating normal state"); ActiveState::Normal(self) } diff --git a/src/controller/states/wakeup.rs b/src/controller/states/wakeup.rs index 9f16ceda..904fcbfd 100755 --- a/src/controller/states/wakeup.rs +++ b/src/controller/states/wakeup.rs @@ -1,4 +1,4 @@ -use super::super::{Modifications, System}; +use super::super::{Modifications, System, Environment}; use super::{RoomState, ActiveState}; use super::Normal; use crate::controller::system; @@ -54,7 +54,7 @@ impl WakeUp { } impl RoomState for WakeUp { - fn update(self, mods: &mut Modifications, sys: &mut System) -> ActiveState { + fn update(self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> ActiveState { dbg!("updating wakeup state"); let elapsed = self.start.elapsed().as_secs(); diff --git a/src/input/sensors/ble/mod.rs b/src/input/sensors/ble/mod.rs index 145fbaf3..74ad4b63 100755 --- a/src/input/sensors/ble/mod.rs +++ b/src/input/sensors/ble/mod.rs @@ -1,22 +1,12 @@ -use secure_ble::{connect_to_adapter, connect_to_node, -authenticate_node, StreamCipher, subscribe, printvalues}; +//use secure_ble::{connect_to_adapter, connect_to_node, authenticate_node, StreamCipher, subscribe, printvalues}; mod node_credentials; use node_credentials::*; pub fn init(){ - let central = connect_to_adapter(); - - let mut bed_node = connect_to_node(central, node_bed::ADRESS, Duration::from_secs(100)).unwrap(); - authenticate_node(&mut node_bed, node::bed::HMAC_KEY); - let bed_decryptor = StreamCipher::from_node(&mut sensor_node, node_bed::KEY); - let bed_fast_rx = subscribe(sensor_node.clone(), node_bed::HMAC_KEY, SLOW_MEASURMENTS_UUID); - let bed_slow_rx = subscribe(sensor_node.clone(), node_bed::HMAC_KEY, FAST_MEASURMENTS_UUID); - - let mut bed_node = connect_to_node(central, node_bed::ADRESS, Duration::from_secs(100)).unwrap(); - authenticate_node(&mut node_bed, node::bed::HMAC_KEY); - let bed_decryptor = StreamCipher::from_node(&mut sensor_node, node_bed::KEY); - let bed_rx = subscribe(sensor_node, node_bed::HMAC_KEY); + //let central = connect_to_adapter(); + //let mut bed_node = connect_to_node(central, node_bed::ADRESS, Duration::from_secs(100)).unwrap(); + //authenticate_node(&mut bed_node, node_bed::HMAC_KEY); } \ No newline at end of file diff --git a/src/input/sensors/fields/compression.rs b/src/input/sensors/fields/compression.rs new file mode 100644 index 00000000..05af2d9b --- /dev/null +++ b/src/input/sensors/fields/compression.rs @@ -0,0 +1,200 @@ +#[inline] pub fn decode(line: &[u8], bit_offset: u8, length: u8) -> u32 { + let start_byte = (bit_offset /8) as usize; + let stop_byte = ((bit_offset+length) /8 ) as usize; + + let start_mask: u8 = !0 >> (bit_offset % 8); + //println!("start_mask: {}", start_mask); + let used_bits = bit_offset+length - stop_byte as u8 *8; + //println!("div: {}, {}",bit_offset,(((bit_offset+7)/8))*8); + //println!("used_bits: {}",used_bits); + let stop_mask = !(!0 >> used_bits); + //println!("stop mask {:b}",stop_mask); + + //decode first bit (never needs shifting (lowest part is used)) + let mut decoded: u32 = (line[start_byte] & start_mask) as u32; + let mut bits_read = 8-(bit_offset % 8); + //if we have more bits + if length > 8 { + //decode middle bits, no masking needed + for (i, byte) in line[start_byte+1..stop_byte].iter().enumerate(){ + decoded |= (*byte as u32) << (8-(bit_offset % 8) + (i as u8) *8) ; + bits_read+= 8; + } + } + //println!("stop_byte: {}",stop_byte); + //println!("############################\nstop_byte: {}, \nstop_mask: {:b}\nbits_read: {}\nmasked line: {:b}\nraw line: {:b}\n//////////////////////", + //stop_byte, stop_mask,bits_read,line[stop_byte] & stop_mask, line[stop_byte]); + let stop_byte = div_up(bit_offset+length, 8) as usize;//starts at 0 + decoded |= ((line[stop_byte-1] & stop_mask) as u32) << (bits_read-(8-used_bits)); + + decoded +} + +#[inline(always)] fn div_up(x: u8, y: u8) -> u8 { + (x+y-1)/y +} + +#[inline] pub fn encode(to_encode: u32, line: &mut [u8], bit_offset: u8, length: u8) { + + let start_mask = !0 >> (bit_offset % 8); + + let start_byte = (bit_offset /8) as usize; + let stop_byte = ((bit_offset+length) /8 ) as usize; + //println!("start_byte: {}, stop_byte: {}, bit_offset: {}, length: {}", start_byte, stop_byte, bit_offset, length); + + //encode first bit (never needs shifting (lowest part is used)) + line[start_byte] |= (to_encode as u8) & start_mask; + let mut bits_written = 8-(bit_offset % 8); + + if length > 8 { + //decode middle bits, no masking needed + //println!("stop_byte: {}, start_byte+1: {}", stop_byte, start_byte+1); + for byte in line[start_byte+1..stop_byte].iter_mut(){ + //println!("hihi"); + *byte |= (to_encode >> bits_written) as u8; + bits_written += 8; + } + } + + //println!("############################\nstart_byte: {}, stop_byte: {}, \nbits_written: {}\nraw line: {:b}\n//////////////////////", + //start_byte, stop_byte,bits_written,line[start_byte]); + + let used_bits = bit_offset+length -stop_byte as u8 *8; + //let used_bits = bit_offset+length - bits_written; + //println!("used_bits: {}", used_bits); + let stop_mask = !(!0 >> used_bits); + //println!("stop_mask: {}", stop_mask); + let stop_byte = div_up(bit_offset+length, 8) as usize;//starts at 0 + line[stop_byte-1] |= (to_encode >> (bits_written-(8-used_bits))) as u8 & stop_mask; +} + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn encode_and_decode_multiple_edge_case(){ + let mut line = vec!(0, 0, 0, 0, 0, 0, 0, 0); + encode(1,&mut line, 0, 8); + + print!("binary repr: "); + for byte in &line { + print!("{:b}, ",byte); + } println!(); + + encode(2,&mut line, 8, 8); + + print!("binary repr: "); + for byte in &line { + print!("{:b}, ",byte); + } println!(); + + let decoded1 = decode(&line, 0, 8); + let decoded2 = decode(&line, 8, 8); + + println!("0-10 {} {:b}", decoded1, decoded1); + println!("10-20 {} {:b}", decoded2, decoded2); + assert_eq!(decoded1, 1); + assert_eq!(decoded2, 2); + } + + #[test] + fn encode_and_decode_edge_case(){ + let test_case = u32::max_value(); + let mut line = vec!(0, 0, 0, 0); + encode(test_case,&mut line, 0, 32); + + print!("binary repr: "); + for byte in &line { + print!("{:b}, ",byte); + } println!(); + + let decoded1 = decode(&line, 0, 32); + + println!("0-{} {} {:b}", 32, decoded1, decoded1); + assert_eq!(decoded1, test_case); + } + + #[test] + fn encode_and_decode_start_case(){ + let test_case = 1023; + let mut line = vec!(0, 0, 0, 0); + encode(test_case,&mut line, 0, 10); + + print!("binary repr: "); + for byte in &line { + print!("{:b}, ",byte); + } println!(); + + print!("array repr: "); + for byte in &line { + print!("{}, ",byte); + } println!(); + + let decoded1 = decode(&line, 0, 10); + + println!("0-{} {} {:b}", 10, decoded1, decoded1); + assert_eq!(decoded1, test_case); + } + + #[test] + fn encode_and_decode_multiple(){ + for length in 8..33 { + for offset in 0..16 { + for _power1 in 0..length as u16 *10 { + for _power2 in 0..length as u16 *10 { + let power1 = _power1 as f32*0.1; + let power2 = _power2 as f32*0.1; + let mut array = vec!(0;12); + let test_numb1 = 2f32.powf(power1) as u32; + let test_numb2 = 2f32.powf(power2) as u32; + encode(test_numb1, array.as_mut_slice(), offset, length); + encode(test_numb2, array.as_mut_slice(), offset+length, length); + + // print!("binary repr: "); + // for byte in &array { + // print!("{:b}, ",byte); + // } println!(); + + let decoded_test_numb1 = decode(array.as_slice(), offset, length); + let decoded_test_numb2 = decode(array.as_slice(), offset+length, length); + assert_eq!(test_numb1, decoded_test_numb1, + "\n##### numb:1, \noffset: {},\nlength: {}, \nvalue1: {}, \nvalue2: {}", + offset, length, test_numb1, test_numb2); + assert_eq!(test_numb2, decoded_test_numb2, + "\n##### numb:2, \noffset: {},\nlength: {}, \nvalue1: {}, \nvalue2: {}", + offset+length, length, test_numb1, test_numb2); + } + } + } + } + + + } + + fn print_vec_bin(array: Vec) -> String { + let mut outstr = String::from("binary repr: "); + for byte in &array { + outstr.push_str(&format!("{:b}, ",byte)); + } outstr.push_str("\n"); + outstr + } + + #[test] + fn encode_and_decode(){ + for length in 8..32 { + for offset in 0..16 { + for _power in 0..length as u16 *10 { + let power = _power as f32*0.1; + let mut array = vec!(0;8); + let test_numb = 2f32.powf(power) as u32; + encode(test_numb, array.as_mut_slice(), offset, length); + + let decoded_test_numb = decode(array.as_slice(), offset, length); + assert_eq!(test_numb, decoded_test_numb, "offset: {}, length: {} {}", offset, length, print_vec_bin(array)); + } + } + } + } +} diff --git a/src/input/sensors/fields/mod.rs b/src/input/sensors/fields/mod.rs new file mode 100644 index 00000000..5b78ccc7 --- /dev/null +++ b/src/input/sensors/fields/mod.rs @@ -0,0 +1,42 @@ +mod compression; + +pub type FieldId = u8; +pub struct Field { + pub offset: u8, //bits + pub length: u8, //bits (max 32 bit variables) + + pub decode_scale: T, + pub decode_add: T, +} + +//TODO do away with generics in favor for speeeeed +impl Field +where T: num::cast::NumCast+std::fmt::Display+std::ops::Add+std::ops::SubAssign+std::ops::DivAssign+std::ops::MulAssign+std::marker::Copy { + pub fn decode(&self, line: &[u8]) -> D + where D: num::cast::NumCast+std::fmt::Display+std::ops::Add+std::ops::SubAssign+std::ops::MulAssign+std::ops::AddAssign{ + //where D: From+From+From+std::ops::Add+std::ops::SubAssign+std::ops::DivAssign+std::ops::AddAssign{ + let int_repr: u32 = compression::decode(line, self.offset, self.length); + //println!("int regr: {}", int_repr); + let mut decoded: D = num::cast(int_repr).unwrap(); + + //println!("add: {}", self.decode_add); + //println!("scale: {}", self.decode_scale); + + decoded *= num::cast(self.decode_scale).unwrap();//FIXME flip decode scale / and * + decoded += num::cast(self.decode_add).unwrap(); + + decoded + } + pub fn encode(&self, mut numb: T, line: &mut [u8]) + where D: num::cast::NumCast+std::fmt::Display+std::ops::Add+std::ops::SubAssign+std::ops::AddAssign+std::ops::DivAssign{ + + //println!("org: {}",numb); + numb -= num::cast(self.decode_add).unwrap(); + numb /= num::cast(self.decode_scale).unwrap(); + //println!("scale: {}, add: {}, numb: {}", self.decode_scale, self.decode_add, numb); + + let to_encode: u32 = num::cast(numb).unwrap(); + + compression::encode(to_encode, line, self.offset, self.length); + } +} \ No newline at end of file diff --git a/src/input/sensors/local.rs b/src/input/sensors/local.rs index 1a52f18b..a9fcd956 100755 --- a/src/input/sensors/local.rs +++ b/src/input/sensors/local.rs @@ -3,6 +3,29 @@ extern crate bme280; use hal::{Delay, I2cdev}; use bme280::BME280; +use super::fields::Field; + +pub const TEMPERATURE: Field = Field { + offset: 5, //bits + length: 3, //bits (max 32 bit variables) + + decode_scale: 1f32, + decode_add: 1f32, +}; +pub const HUMIDITY: Field = Field { + offset: 5, + length: 3, + + decode_scale: 1f32, + decode_add: 1f32, +}; +pub const PRESSURE: Field = Field { + offset: 5, + length: 3, + + decode_scale: 1f32, + decode_add: 1f32, +}; pub fn init() -> BME280 { // using Linux I2C Bus #1 in this example diff --git a/src/input/sensors/mod.rs b/src/input/sensors/mod.rs index 833cbe65..939e9caf 100755 --- a/src/input/sensors/mod.rs +++ b/src/input/sensors/mod.rs @@ -1,98 +1,67 @@ extern crate chrono; extern crate smallvec; extern crate bytes; +use byteorder::{LittleEndian, WriteBytesExt}; #[cfg(feature = "sensors_connected")] mod local; +mod fields; +mod ble; + +use std::thread; +use std::time::Duration; +use chrono::Utc; + +use crate::credentials; +use crate::controller::Event; +use local::{TEMPERATURE, HUMIDITY, PRESSURE}; + +pub enum SensorValue { + Temperature(f32), + Humidity(f32), + Pressure(f32), +} //const LOCAL_SENSING_ID: timeseries_interface::DatasetId = 0; //TODO mechanisme for shutdown #[cfg(feature = "sensors_connected")] -pub fn start_monitoring(tx: crossbeam_channel::Sender, data_router_handle: DataRouterHandle, dataset_handle: Arc>) { - - buttons::start(tx.clone()); - - //load the requird dataset - let data = dataset_handle.read().unwrap(); - let dataset = data.sets.get(&LOCAL_SENSING_ID).expect("dataset for local sensors is missing"); - let fields = dataset.metadata.fields.clone(); - drop(data); +pub fn start_monitoring(tx: crossbeam_channel::Sender) { //init all local sensors let mut local_sensors = local::init(); //subscribe and init remote sensors ble::init(); - - - /*thread::spawn(move || {//TODO figure out shutdown behaviour + thread::spawn(move || {//TODO figure out shutdown behaviour loop { //get all measurements - let (humidity, temperature, pressure) = bme280::measure_and_record(&mut bme); + let (hum, temp, pressure) = local::measure_and_record(&mut local_sensors); let now = Utc::now(); //TODO //process data into events and send off as event + tx.send(Event::Sensor(SensorValue::Temperature(temp))); + tx.send(Event::Sensor(SensorValue::Humidity(hum))); + tx.send(Event::Sensor(SensorValue::Pressure(pressure))); //encode all data let mut line: Vec = vec!(0;64); + + line.write_u16::(credentials::NODE_ID).unwrap(); + line.write_u64::(credentials::DATASERVER_KEY).unwrap(); - fields[0].encode::(humidity, &mut line); - fields[1].encode::(temperature, &mut line); - fields[2].encode::(pressure, &mut line); + HUMIDITY.encode::(hum, &mut line); + TEMPERATURE.encode::(temp, &mut line); + PRESSURE.encode::(pressure, &mut line); + //send data to dataserver - drop(data); + let client = reqwest::Client::new(); + client.post("http://www.deviousd.duckdns.org:8080/post_data") + .body(line) + .send().unwrap(); //sleep until 5 seconds are completed thread::sleep(Duration::from_secs(5)); } - });*/ -} - -/*fn make_local_sensing_spec() -> MetaDataSpec { - let humidity_desk = FieldSpec::BitLength( FieldLength { - name: String::from("humidity below desk"), - min_value: 0.0f32, - max_value: 100f32, - numb_of_bits: 10u8, //bits (max 32 bit variables) - }); - let temperature_desk = FieldSpec::Resolution( FieldResolution { - name: String::from("temperature below desk"), - min_value: -20f32, - max_value: 60f32, - resolution: 0.05f32, //bits (max 32 bit variables) - }); - let pressure_desk = FieldSpec::Resolution( FieldResolution { - name: String::from("pressure below desk"), - min_value: 100_000f32-50_000f32, - max_value: 100_000f32+50_000f32, - resolution: 0.1f32, }); - - MetaDataSpec { - name: String::from("home automation sensors"), - description: String::from("Data from homeautomation sensors"), - fields: vec!(humidity_desk, temperature_desk, pressure_desk), - } -} - -pub fn check_local_sensing_dataset(data: &Arc>) -> Result<(),()>{ - let mut data = data.write().unwrap(); - if let Some(dataset) = data.sets.get(&LOCAL_SENSING_ID){ - //check if name is right - if dataset.metadata.name == "home automation sensors" { - info!("loaded home automation data set"); - Ok(()) - } else { - error!("No existing home automation dataset, cant create one without overwriting, dataset id already taken by dataset: {}",dataset.metadata.name); - Err(()) - } - } else { - //TODO write specification that we can use - let spec = make_local_sensing_spec(); - data.add_specific_set(spec).expect("could not create the dataset for the given spec"); - info!("created home automation dataset"); - Ok(()) - } } -*/ diff --git a/src/main.rs b/src/main.rs index f3cd7e47..a636e275 100755 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,7 @@ use input::web_api::server; use server::{CheckLogin, PasswordDatabase, UserDatabase, index}; use server::login::{login_get_and_check, login_page, logout}; +mod credentials; mod errors; #[cfg(feature = "live_server")] From 47c1ea773f24a8047ed5a5231307b95fede990df Mon Sep 17 00:00:00 2001 From: dskleingeld Date: Wed, 29 Jan 2020 01:05:04 +0100 Subject: [PATCH 019/687] ported to actix-web 2.0 --- Cargo.lock | 2829 +++++++++++--------- Cargo.toml | 29 +- src/controller/commands.rs | 11 +- src/controller/mod.rs | 8 +- src/controller/system/mpd_control.rs | 35 + src/errors.rs | 10 + src/input/alarms.rs | 2 +- src/input/buttons.rs | 8 +- src/input/mod.rs | 2 +- src/input/mpd_status.rs | 10 + src/input/sensors/ble/mod.rs | 4 +- src/input/sensors/ble/node_credentials.rs | 24 - src/input/sensors/fields/compression.rs | 2 +- src/input/sensors/local.rs | 32 +- src/input/sensors/mod.rs | 26 +- src/input/web_api/server/database.rs | 123 +- src/input/web_api/server/login.rs | 11 +- src/input/web_api/server/login_redirect.rs | 36 +- src/input/web_api/server/mod.rs | 99 +- src/input/youtube_downloader.rs | 111 +- src/main.rs | 145 +- 21 files changed, 1905 insertions(+), 1652 deletions(-) mode change 100755 => 100644 Cargo.lock delete mode 100755 src/input/sensors/ble/node_credentials.rs diff --git a/Cargo.lock b/Cargo.lock old mode 100755 new mode 100644 index 7879008b..e7273343 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,39 +4,39 @@ name = "HomeAutomation" version = "0.1.0" dependencies = [ - "actix-files 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-identity 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-files 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-identity 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "actix-net 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-rt 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web-httpauth 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bme280 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web-httpauth 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bme280 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "linux-embedded-hal 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mpd 0.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "philipshue 0.3.2 (git+https://github.com/dskleingeld/philipshue)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", "retry 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "secure-ble 0.1.0", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", - "sled 0.24.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "sysfs_gpio 0.5.3 (git+https://github.com/rust-embedded/rust-sysfs-gpio)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", + "sled 0.30.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "sysfs_gpio 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -45,24 +45,24 @@ version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "actix_derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-proto 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -70,120 +70,128 @@ dependencies = [ [[package]] name = "actix-codec" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "actix-connect" -version = "0.2.5" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-rt 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-utils 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-rustls 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-resolver 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-proto 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-resolver 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "actix-files" -version = "0.1.4" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "actix-http 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "v_htmlescape 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-http 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "v_htmlescape 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "actix-http" -version = "0.2.10" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-connect 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-server-config 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-threadpool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-utils 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-connect 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-threadpool 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-resolver 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "actix-identity" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "actix-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "actix-net" version = "0.2.6" @@ -191,153 +199,169 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "actix 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "actix-router" -version = "0.1.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytestring 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "actix-rt" -version = "0.2.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "actix-threadpool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-macros 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-threadpool 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "actix-server" -version = "0.6.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "actix-rt 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-server-config 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-rustls 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "actix-server-config" -version = "0.1.2" +name = "actix-service" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-rustls 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "actix-service" -version = "0.4.2" +name = "actix-testing" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-macros 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-server 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "actix-threadpool" -version = "0.1.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "actix-utils" -version = "0.4.5" +name = "actix-tls" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "actix-web" -version = "1.0.7" +name = "actix-utils" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-http 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-router 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-rt 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-server 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-server-config 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-threadpool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-utils 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web-codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "awc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "actix-web" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-http 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-macros 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-router 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-server 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-testing 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-threadpool 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web-codegen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "awc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -345,24 +369,24 @@ dependencies = [ [[package]] name = "actix-web-codegen" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "actix-web-httpauth" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-locks 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -371,122 +395,119 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "adler32" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "aes" -version = "0.3.2" +name = "aho-corasick" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "aes-soft" -version = "0.3.3" +name = "ansi_term" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "aesni" -version = "0.6.0" +name = "anyhow" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "aho-corasick" -version = "0.7.3" +name = "arc-swap" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "arc-swap" -version = "0.3.11" +name = "arrayref" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "argon2rs" -version = "0.2.5" +name = "arrayvec" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "arrayvec" -version = "0.4.10" +name = "async-trait" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atty" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "autocfg" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "awc" -version = "0.2.6" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-http 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-http 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace" -version = "0.3.15" +version = "0.3.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.28" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -497,14 +518,19 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "base64" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bincode" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -519,48 +545,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "blake2-rfc" -version = "0.2.18" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-cipher-trait" -version = "0.6.2" +name = "blake2b_simd" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-padding" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bme280" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -571,8 +571,8 @@ name = "brotli-sys" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -581,7 +581,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -590,13 +590,8 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "build_const" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byte-tools" -version = "0.3.1" +name = "bumpalo" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -610,16 +605,29 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bytes" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bytestring" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "c2-chacha" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -629,36 +637,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cc" -version = "1.0.36" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.7" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "chrono" -version = "0.4.6" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "clap" +version = "2.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "constant_time_eq" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -676,12 +699,12 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "publicsuffix 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -698,7 +721,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -706,38 +729,20 @@ name = "core-foundation-sys" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "crc" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crc32fast" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-channel" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-deque" -version = "0.2.0" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -745,35 +750,34 @@ name = "crossbeam-deque" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-epoch" -version = "0.3.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-epoch" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -781,82 +785,64 @@ name = "crossbeam-queue" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-utils" -version = "0.2.2" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-utils" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crypto-mac" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ct-logs" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "sct 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "derive_more" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "digest" -version = "0.8.1" +version = "0.99.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "dirs" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "dirs-sys" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -866,7 +852,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "either" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -880,28 +866,21 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.17" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "enum-as-inner" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "enum_primitive" -version = "0.1.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -909,7 +888,7 @@ name = "error-chain" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -917,7 +896,7 @@ name = "error-chain" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -925,44 +904,39 @@ name = "error-chain" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure_derive" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "flate2" -version = "1.0.7" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -988,8 +962,8 @@ name = "fs2" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1002,7 +976,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1013,7 +987,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures" -version = "0.1.27" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-channel" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-core" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1021,107 +1023,158 @@ name = "futures-cpupool" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "futures-locks" -version = "0.3.3" +name = "futures-executor" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "fxhash" -version = "0.2.1" +name = "futures-io" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-macro" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "gcc" -version = "0.3.55" +name = "futures-sink" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "generic-array" -version = "0.12.3" +name = "futures-task" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-util" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fxhash" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "getrandom" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "h2" -version = "0.1.18" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "hashbrown" -version = "0.3.0" +name = "h2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "hashbrown" -version = "0.5.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "historian" -version = "4.0.3" +name = "heck" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "hmac" -version = "0.7.1" +name = "hermit-abi" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "historian" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "hostname" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "http" -version = "0.1.17" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1129,52 +1182,75 @@ dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "http" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "http-body" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "httparse" -version = "1.3.3" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hyper" -version = "0.12.28" +version = "0.12.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "hyper-rustls" -version = "0.16.1" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "ct-logs 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ct-logs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-rustls 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1183,21 +1259,21 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "i2cdev" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1222,16 +1298,18 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.0.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "iovec" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1240,9 +1318,9 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1251,9 +1329,9 @@ name = "ipconfig" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1262,6 +1340,14 @@ name = "itoa" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "js-sys" +version = "0.3.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -1278,12 +1364,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.62" +version = "0.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1298,9 +1384,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "i2cdev 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "i2cdev 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "spidev 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sysfs_gpio 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sysfs_gpio 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1322,18 +1408,10 @@ dependencies = [ [[package]] name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "log" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1351,72 +1429,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memchr" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memoffset" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "mime" -version = "0.3.13" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "mime_guess" -version = "2.0.0-alpha.6" +name = "mime" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "miniz-sys" -version = "0.1.11" +name = "mime_guess" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "miniz_oxide" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "miniz_oxide_c_api" -version = "0.2.1" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mio" -version = "0.6.19" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1428,9 +1485,9 @@ name = "mio-uds" version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1459,16 +1516,16 @@ name = "native-tls" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.22 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.52 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1481,9 +1538,9 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1492,8 +1549,8 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1501,44 +1558,19 @@ dependencies = [ [[package]] name = "nix" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "nix" -version = "0.11.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "nix" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "nodrop" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1546,23 +1578,10 @@ name = "nom" version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "num" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "num" version = "0.2.0" @@ -1570,56 +1589,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "num-bigint" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "num-bigint" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "num-complex" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "num-complex" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-integer" -version = "0.1.39" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1628,20 +1628,9 @@ name = "num-iter" version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-rational" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1649,17 +1638,9 @@ name = "num-rational" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-traits" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1668,33 +1649,29 @@ name = "num-traits" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num_cpus" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "openssl" -version = "0.10.22" +version = "0.10.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.52 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1704,14 +1681,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.46" +version = "0.9.52" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1727,20 +1704,20 @@ name = "pagecache" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "historian 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1762,16 +1739,25 @@ dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1779,13 +1765,26 @@ name = "parking_lot_core" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1799,60 +1798,92 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "phf" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "philipshue" +version = "0.3.2" +source = "git+https://github.com/dskleingeld/philipshue#68eeaf2f006accaaa2cf289a992e347a92b5b013" dependencies = [ - "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "phf_codegen" -version = "0.7.24" +name = "pin-project" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-internal 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "phf_generator" -version = "0.7.24" +name = "pin-project-internal" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "phf_shared" -version = "0.7.24" +name = "pin-project-lite" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pin-utils" +version = "0.1.0-alpha.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pkg-config" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ppv-lite86" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro-error" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error-attr 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustversion 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "philipshue" -version = "0.3.2" -source = "git+https://github.com/dskleingeld/philipshue#68eeaf2f006accaaa2cf289a992e347a92b5b013" +name = "proc-macro-error-attr" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustversion 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn-mid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "pkg-config" -version = "0.3.14" +name = "proc-macro-hack" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "ppv-lite86" -version = "0.2.5" +name = "proc-macro-nested" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1863,16 +1894,24 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "publicsuffix" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1882,22 +1921,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "0.6.12" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand" -version = "0.4.6" +name = "quote" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1907,9 +1942,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1917,17 +1952,17 @@ name = "rand" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1935,8 +1970,8 @@ name = "rand" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1947,7 +1982,7 @@ name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1956,7 +1991,7 @@ name = "rand_chacha" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1965,12 +2000,12 @@ name = "rand_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1978,7 +2013,7 @@ name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2010,9 +2045,9 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2022,10 +2057,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2033,8 +2068,8 @@ name = "rand_pcg" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2047,23 +2082,24 @@ dependencies = [ [[package]] name = "rayon" -version = "1.0.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon-core" -version = "1.4.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2076,82 +2112,79 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.54" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "redox_users" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.1.6" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.6" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "remove_dir_all" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "reqwest" -version = "0.9.17" +version = "0.9.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-rustls 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-rustls 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-rustls 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2173,38 +2206,31 @@ dependencies = [ [[package]] name = "ring" -version = "0.14.6" +version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rumble" -version = "0.3.0" -source = "git+https://github.com/Josh-Thompson/rumble#3117372692ccfd371909eb4751b3d994a0d59386" +name = "rust-argon2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "nix 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2230,36 +2256,40 @@ dependencies = [ [[package]] name = "rustls" -version = "0.15.2" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sct 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustversion" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ryu" -version = "0.2.8" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "schannel" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "scoped_threadpool" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "scopeguard" version = "0.3.3" @@ -2272,25 +2302,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "sct" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "secure-ble" -version = "0.1.0" -dependencies = [ - "aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rumble 0.3.0 (git+https://github.com/Josh-Thompson/rumble)", - "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2300,7 +2316,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2332,38 +2348,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_bytes" -version = "0.11.1" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.91" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.39" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2373,7 +2381,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2384,32 +2392,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_yaml" -version = "0.8.9" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "sha-1" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "sha1" version = "0.6.0" @@ -2417,27 +2414,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "signal-hook" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "signal-hook-registry 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "signal-hook-registry" -version = "1.0.1" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arc-swap 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "arc-swap 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "siphasher" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "slab" version = "0.4.2" @@ -2445,39 +2437,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "sled" -version = "0.24.1" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_bytes 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "smallvec" -version = "0.6.9" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "smallvec" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "socket2" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sourcefile" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "spidev" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2493,73 +2498,110 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "string" -version = "0.1.3" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "strsim" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "string" -version = "0.2.1" +name = "structopt" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "subtle" -version = "1.0.0" +name = "structopt-derive" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "syn" -version = "0.15.34" +version = "0.15.44" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "synstructure" -version = "0.10.1" +name = "syn" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "sysfs_gpio" -version = "0.5.3" -source = "git+https://github.com/rust-embedded/rust-sysfs-gpio#409bab143fbf4004613009aef204df7fc0c0ae8f" +name = "syn-mid" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "nix 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "sysfs_gpio" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nix 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tempfile" -version = "3.0.7" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2567,7 +2609,7 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2575,7 +2617,7 @@ name = "threadpool" version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2583,42 +2625,71 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio" -version = "0.1.19" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-buf" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-codec" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2627,17 +2698,17 @@ name = "tokio-current-thread" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2645,9 +2716,9 @@ name = "tokio-fs" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2656,37 +2727,50 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-reactor" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-rustls" -version = "0.9.3" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-rustls" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2694,24 +2778,24 @@ name = "tokio-signal" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "signal-hook 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "signal-hook 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-sync" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2720,60 +2804,52 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-trace-core" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-udp" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2782,15 +2858,28 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-util" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2798,7 +2887,7 @@ name = "tower-service" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2807,20 +2896,20 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2830,45 +2919,40 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trust-dns-proto" -version = "0.7.4" +version = "0.18.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "enum-as-inner 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "async-trait 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "enum-as-inner 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2876,35 +2960,35 @@ name = "trust-dns-resolver" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trust-dns-resolver" -version = "0.11.1" +version = "0.18.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-proto 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-proto 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2917,30 +3001,12 @@ name = "try_from" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "typenum" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ucd-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicase" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicase" -version = "2.4.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2959,17 +3025,32 @@ name = "unicode-normalization" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unicode-segmentation" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "untrusted" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2992,11 +3073,6 @@ dependencies = [ "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "utf8-ranges" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "uuid" version = "0.7.4" @@ -3007,36 +3083,40 @@ dependencies = [ [[package]] name = "v_escape" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "v_escape_derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "v_escape_derive 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "v_escape_derive" -version = "0.5.3" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "v_htmlescape" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "v_escape 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "v_escape 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "vcpkg" -version = "0.2.6" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vec_map" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3051,11 +3131,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "want" -version = "0.0.6" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3064,22 +3144,105 @@ name = "wasi" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "wasm-bindgen" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bumpalo 3.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro-support 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasm-bindgen-webidl" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "web-sys" +version = "0.3.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-webidl 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "webpki" -version = "0.19.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "webpki-roots" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "weedle" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3099,7 +3262,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3126,7 +3289,7 @@ name = "winreg" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3134,7 +3297,7 @@ name = "winreg" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3142,7 +3305,7 @@ name = "winutil" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3164,93 +3327,90 @@ dependencies = [ [metadata] "checksum actix 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c616db5fa4b0c40702fb75201c2af7f8aa8f3a2e2c1dda3b0655772aa949666" -"checksum actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9f2c11af4b06dc935d8e1b1491dad56bfb32febc49096a91e773f8535c176453" -"checksum actix-connect 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fade9bd4bb46bacde89f1e726c7a3dd230536092712f5d94d77ca57c087fca0" -"checksum actix-files 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e4640b28cd96059541c932f6f350c63c76688e43d68305cdb88e0004da12b5" -"checksum actix-http 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf758ebbc4abfecbdc1ce7408601b2d7e0cd7e4766ef61183cd8ce16c194d64" -"checksum actix-identity 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "84d972c0f80dc8beeceaff6f47b961a106b9f582c0b12ee6737cad30ed228edd" +"checksum actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09e55f0a5c2ca15795035d90c46bd0e73a5123b72f68f12596d6ba5282051380" +"checksum actix-connect 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c95cc9569221e9802bf4c377f6c18b90ef10227d787611decf79fd47d2a8e76c" +"checksum actix-files 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "301482841d3d74483a446ead63cb7d362e187d2c8b603f13d91995621ea53c46" +"checksum actix-http 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c16664cc4fdea8030837ad5a845eb231fb93fc3c5c171edfefb52fad92ce9019" +"checksum actix-identity 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a379b0639c293292d71defb8cc1f94c87b7705c904adf044338ad392df77c7a" +"checksum actix-macros 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21705adc76bbe4bc98434890e73a89cd00c6015e5704a60bb6eea6c3b72316b6" "checksum actix-net 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8bebfbe6629e0131730746718c9e032b58f02c6ce06ed7c982b9fef6c8545acd" -"checksum actix-router 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "23224bb527e204261d0291102cb9b52713084def67d94f7874923baefe04ccf7" -"checksum actix-rt 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "168620aaf00fcd2a16e621790abaf180ef7377c2f8355b4ca5775d6afc778ed8" -"checksum actix-server 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb3038e9e457e0a498ea682723e0f4e6cc2c4f362a1868d749808355275ad959" -"checksum actix-server-config 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "483a34989c682d93142bacad6300375bb6ad8002d2e0bb249dbad86128b9ff30" -"checksum actix-service 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bca5b48e928841ff7e7dce1fdb5b0d4582f6b1b976e08f4bac3f640643e0773f" -"checksum actix-threadpool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b5ae85d13da7e6fb86b1b7bc83185e0e3bd4cc5f421c887e1803796c034d35d" -"checksum actix-utils 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6ea501068a0173533704be321f149853f702d9e3c3ce9d57e7a96d94b1ab5aca" -"checksum actix-web 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8ced216f53d465f9d6478454b2b994d1fe91ec203ac9d056837cbe07e823cb83" -"checksum actix-web-codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe9e3cdec1e645b675f354766e0688c5705021c85ab3cf739be1c8999b91c76" -"checksum actix-web-httpauth 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7005033d05a151c86016468cca1d38febb84a894bbb7a332118479f4ed7398" +"checksum actix-router 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9d7a10ca4d94e8c8e7a87c5173aba1b97ba9a6563ca02b0e1cd23531093d3ec8" +"checksum actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6a0a55507046441a496b2f0d26a84a65e67c8cafffe279072412f624b5fb6d" +"checksum actix-server 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "51d3455eaac03ca3e49d7b822eb35c884b861f715627254ccbe4309d08f1841a" +"checksum actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3e4fc95dfa7e24171b2d0bb46b85f8ab0e8499e4e3caec691fc4ea65c287564" +"checksum actix-testing 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48494745b72d0ea8ff0cf874aaf9b622a3ee03d7081ee0c04edea4f26d32c911" +"checksum actix-threadpool 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4082192601de5f303013709ff84d81ca6a1bc4af7fb24f367a500a23c6e84e" +"checksum actix-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4e5b4faaf105e9a6d389c606c298dcdb033061b00d532af9df56ff3a54995a8" +"checksum actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fcf8f5631bf01adec2267808f00e228b761c60c0584cc9fa0b5364f41d147f4e" +"checksum actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3158e822461040822f0dbf1735b9c2ce1f95f93b651d7a7aded00b1efbb1f635" +"checksum actix-web-codegen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de0878b30e62623770a4713a6338329fd0119703bafc211d3e4144f4d4a7bdd5" +"checksum actix-web-httpauth 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7cccccfac88ec8c0475538f466384b90e4395a7420288f5384baf1c51fad73ec" "checksum actix_derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4300e9431455322ae393d43a2ba1ef96b8080573c0fc23b196219efedfb6ba69" -"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" -"checksum aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "54eb1d8fe354e5fc611daf4f2ea97dd45a765f4f1e4512306ec183ae2e8f20c9" -"checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" -"checksum aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" -"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c" -"checksum arc-swap 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "bc4662175ead9cd84451d5c35070517777949a2ed84551764129cedb88384841" -"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" -"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" -"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" -"checksum awc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "78c9c1e32d6084343b3857eacb1f43aaefb93a816e15aae4685bc3c0a9052964" -"checksum backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f106c02a3604afcdc0df5d36cc47b44b55917dbaf3d808f71c163a0ddba64637" -"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" +"checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" +"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" +"checksum arc-swap 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a1eca3195b729bbd64e292ef2f5fff6b1c28504fed762ce2b1013dde4d8e92" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" +"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +"checksum async-trait 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c8df72488e87761e772f14ae0c2480396810e51b2c2ade912f97f0f7e5b95e3c" +"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +"checksum awc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7601d4d1d7ef2335d6597a41b5fe069f6ab799b85f53565ab390e7b7065aac5" +"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" +"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "959c8e54c1ad412ffeeb95f05a9cade02d2d40a7b3c2f852d3353148f4beff35" +"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +"checksum bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ab639324e3ee8774d296864fbc0dbbb256cf1a41c490b94cba90c082915f92" "checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" -"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -"checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" -"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" -"checksum bme280 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d168c341491c9ba4e2c73d59470c108a5961377c67061dc1796a193fa945b452" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182" +"checksum bme280 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d48076b7293afafab5ff93e3db57435c567f1fc72755c27d377f7e96ea66678d" "checksum brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" "checksum brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" "checksum bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" -"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" -"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum bumpalo 3.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb8038c1ddc0a5f73787b130f4cc75151e96ed33e417fde765eb5a81e3532f4" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" +"checksum bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" +"checksum bytestring 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fc267467f58ef6cc8874064c62a0423eb0d099362c8a23edd1c6d044f46eead4" +"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" -"checksum cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a0c56216487bb80eec9c4516337b2588a4f2a2290d72a1416d930e4dcdb0c90d" -"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" -"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" +"checksum cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)" = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" +"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" "checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" "checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" "checksum copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ff9c56c9fb2a49c05ef0e431485a22400af20d33226dc0764d891d09e724127" "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" -"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" -"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" -"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" +"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" -"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" -"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" +"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" +"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" -"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" -"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" -"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" -"checksum ct-logs 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b4660f8b07a560a88c02d76286edb9f0d5d64e495d2b0f233186155aa51be1f" -"checksum derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a141330240c921ec6d074a3e188a7c7ef95668bb95e7d44fa0e5778ec2a7afe" -"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -"checksum dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4ef5a8b902d393339e2a2c7fe573af92ce7e0ee5a3ff827b4c9ad7e07e4fa1" -"checksum dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "937756392ec77d1f2dd9dc3ac9d69867d109a2121479d72c364e42f4cab21e2d" +"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" +"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" +"checksum ct-logs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d3686f5fa27dbc1d76c751300376e167c5a43387f44bb451fd1c24776e49113" +"checksum derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8" +"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" +"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" -"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" +"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ee4908a155094da7723c2d60d617b820061e3b4efcc3d9e293d206a5a76c170b" -"checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" -"checksum enum-as-inner 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d58266c97445680766be408285e798d3401c6d4c378ec5552e78737e681e37d" -"checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" +"checksum encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)" = "87240518927716f79692c2ed85bfe6e98196d18c6401ec75355760233a7e12e9" +"checksum enum-as-inner 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "900a6c7fbe523f4c2884eaf26b57b81bb69b6810a01a236390a7ac021d09492e" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" -"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" -"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" -"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" -"checksum flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f87e68aa82b2de08a6e037f1385455759df6e445a8df5e005b4297191dbf18aa" +"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" +"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" +"checksum flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" @@ -3258,108 +3418,114 @@ dependencies = [ "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)" = "a2037ec1c6c1c4f79557762eab1f7eae1f64f6cb418ace90fae88f0942b60139" +"checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" +"checksum futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987" +"checksum futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" +"checksum futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum futures-locks 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5658075ca5ae3918993c5bc95b43fcf22f927227660556a947da598f9f8981" +"checksum futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231" +"checksum futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff" +"checksum futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764" +"checksum futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16" +"checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" +"checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" -"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" -"checksum h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "85ab6286db06040ddefb71641b50017c06874614001a134b423783e2db2920bd" -"checksum hashbrown 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "570178d5e4952010d138b0f1d581271ff3a02406d990f887d1e87e3d6e43b0ac" -"checksum hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353" +"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" +"checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" +"checksum h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9433d71e471c1736fd5a61b671fc0b148d7a2992f666c958d03cd8feb3b88d1" +"checksum hashbrown 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "29fba9abe4742d586dfd0c06ae4f7e73a1c2d86b856933509b269d82cdf06e18" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" "checksum historian 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f653416eb756b69642a1f1498817970fafe409998a849622c27cc5b1b7df989c" -"checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" "checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" -"checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a" -"checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" -"checksum hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)" = "e8e4606fed1c162e3a63d408c07584429f49a4f34c7176cb6cbee60e78f2372c" -"checksum hyper-rustls 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "15b66d1bd4864ef036adf2363409caa3acd63ebb4725957b66e621c8a36631a3" +"checksum http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d7e06e336150b178206af098a055e3621e8336027e2b4d126bda0bc64824baaf" +"checksum http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b708cc7f06493459026f53b9a61a7a121a5d1ec6238dee58ea4941132b30156b" +"checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" +"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" +"checksum hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)" = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" +"checksum hyper-rustls 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "719d85c7df4a7f309a77d145340a063ea929dcb2e025bae46a80345cffec2952" "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" -"checksum i2cdev 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3dabb8dd1c6c973b20fa6342069a2703a11f062768d613cc57a5db29a3fe325c" +"checksum i2cdev 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db7cf03500911132bacb44430234aa58dba843bb6aa2820154e5abb696e3e3d9" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" -"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" +"checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" +"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" "checksum ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "08f7eadeaf4b52700de180d147c4805f199854600b36faa963d91114827b2ffc" "checksum ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa79fa216fbe60834a9c0737d7fcd30425b32d1c58854663e24d4c4b328ed83f" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" +"checksum js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "7889c7c36282151f6bf465be4700359318aef36baa951462382eae49e9577cf9" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum linux-embedded-hal 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "795096c0eecb0622afb591c3e1a97b1ba046688a7689957b70b8eee9cac8fb84" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" -"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" -"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" -"checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" -"checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649" -"checksum miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c468f2369f07d651a5d0bb2c9079f8488a66d5466efe42d0c5c6466edcb7f71e" -"checksum miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7fe927a42e3807ef71defb191dc87d4e24479b221e67015fe38ae2b7b447bab" -"checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" +"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +"checksum memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a85c1a8c329f11437034d7313dca647c79096523533a1c79e86f1d0f657c7cc" +"checksum mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "dd1d63acd1b78403cc0c325605908475dd9b9a3acbf65ed8bcab97e27014afcf" +"checksum mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" +"checksum miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6f3f74f726ae935c3f514300cc6773a0c9492abc5e972d42ba0c0ebb88757625" +"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum mpd 0.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "57a20784da57fa01bf7910a5da686d9f39ff37feaa774856b71f050e4331bf82" "checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b1411551beb3c11dedfb0a90a0fa256b47d28b9ec2cdff34c25a2fa59e45dbdc" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -"checksum nix 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b7fd5681d13fda646462cfbd4e5f2051279a89a544d50eb98c365b507246839f" -"checksum nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37e713a259ff641624b6cb20e3b12b2952313ba36b6823c0f16e6cfd9e5de17" -"checksum nix 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "319fffb13b63c0f4ff5a4e1c97566e7e741561ff5d03bf8bbf11653454bbd70b" +"checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" "checksum nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a7bb1da2be7da3cbffda73fc681d509ffd9e665af478d2bee1907cee0bc64b2" -"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" -"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" "checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" -"checksum num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" "checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" -"checksum num-complex 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "b288631d7878aaf59442cffd36910ea604ecd7745c36054328595114001c9656" "checksum num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc" -"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" +"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" -"checksum num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e" "checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" -"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" -"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" -"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" -"checksum openssl 0.10.22 (registry+https://github.com/rust-lang/crates.io-index)" = "a51f452b82d622fc8dd973d7266e9055ac64af25b957d9ced3989142dc61cb6b" +"checksum num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "155394f924cdddf08149da25bfb932d226b4a593ca7468b08191ff6335941af5" +"checksum openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2f372b2b53ce10fb823a337aaa674e3a7d072b957c6264d0f4ff0bd86e657449" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)" = "05636e06b4f8762d4b81d24a351f3966f38bd25ccbcfd235606c91fdb82cc60f" +"checksum openssl-sys 0.9.52 (registry+https://github.com/rust-lang/crates.io-index)" = "c977d08e1312e2f7e4b86f9ebaa0ed3b19d1daff75fae88bbb88108afbd801fc" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74a701d13e2f3ee32a50be43321da8f712cf1e6e9ff0e2be66ab7f5c6598a16a" +"checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" +"checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" -"checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" -"checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" -"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" -"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" "checksum philipshue 0.3.2 (git+https://github.com/dskleingeld/philipshue)" = "" -"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" -"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" +"checksum pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7804a463a8d9572f13453c516a5faea534a2403d7ced2f0c7e100eeff072772c" +"checksum pin-project-internal 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "385322a45f2ecf3410c68d2a549a4a2685e8051d0f278e39743ff4e451cb9b3f" +"checksum pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" +"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" +"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" +"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" +"checksum proc-macro-error 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1b79a464461615532fcc8a6ed8296fa66cc12350c18460ab3f4594a6cee0fcb6" +"checksum proc-macro-error-attr 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "23832e5eae6bac56bbac190500eef1aaede63776b5cd131eaa4ee7fe120cd892" +"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" +"checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5afecba86dcf1e4fd610246f89899d1924fe12e1e89f555eb7c7f710f3c5ad1d" +"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +"checksum publicsuffix 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9bf259a81de2b2eb9850ec990ec78e6a25319715584fd7652b9b26f96fcb1510" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" -"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" "checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" @@ -3368,115 +3534,128 @@ dependencies = [ "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" -"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" +"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" +"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" -"checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" -"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" -"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" -"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "e57803405f8ea0eb041c1567dac36127e0c8caa1251c843cb03d43fd767b3d50" +"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" +"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" +"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" +"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +"checksum reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab" "checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" "checksum retry 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ac83b31b3831aa4b07608db4170f6555ab12942197037c38570dc4c5ba5028" -"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c" -"checksum rumble 0.3.0 (git+https://github.com/Josh-Thompson/rumble)" = "" -"checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288" +"checksum ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6747f8da1f2b1fabbee1aaa4eb8a11abf9adef0bf58a41cee45db5d59cecdfac" +"checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" +"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f271e3552cd835fa28c541c34a7e8fdd8cdff09d77fe4eb8f6c42e87a11b096e" -"checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f" -"checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" -"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" +"checksum rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" +"checksum rustversion 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bba175698996010c4f6dce5e7f173b6eb781fce25d2cfc45e27091ce0b79f6" +"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" +"checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum sct 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f5adf8fbd58e1b1b52699dc8bed2630faecb6d8c7bee77d009d6bbe4af569b9" +"checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" "checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" "checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "a72e9b96fa45ce22a4bc23da3858dfccfd60acd28a25bcd328a98fdd6bea43fd" -"checksum serde_bytes 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aaff47db6ef8771cca5d88febef2f22f47f645420e51226374049f68c6b08569" -"checksum serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "101b495b109a3e3ca8c4cbe44cf62391527cdfb6ba15821c5ce80bcd5ea23f9f" -"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" +"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" +"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" +"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" "checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" -"checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582" -"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" +"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" -"checksum signal-hook 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "72ab58f1fda436857e6337dcb6a5aaa34f16c5ddc87b3a8b6ef7a212f90b9c5a" -"checksum signal-hook-registry 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cded4ffa32146722ec54ab1f16320568465aa922aa9ab4708129599740da85d7" -"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" +"checksum signal-hook 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cb543aecec4ba8b867f41284729ddfdb7e8fcd70ec3d7d37fca3007a4b53675f" +"checksum signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1797d48f38f91643908bb14e35e79928f9f4b3cefb2420a564dde0991b4358dc" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum sled 0.24.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a780266d241e270e52cab0010e11aecfc6d52e33aa98e52eb9792023abd23aa" -"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" -"checksum socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "4e626972d3593207547f14bf5fc9efa4d0e7283deb73fef1dff313dae9ab8878" +"checksum sled 0.30.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb8c32cb0e34e67ad74fae1a77f4635d0cc7ffc873088a0136f3c4849336d71" +"checksum smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "533e29e15d0748f28afbaf4ff7cab44d73e483a8e50b38c40bd13b7f3d48f542" +"checksum smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4" +"checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" +"checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" "checksum spidev 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ba01d3ef92a37e898fecac76cd3e1b33c999395e2d70787608d9678c4293e04" "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" -"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" -"checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" -"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" -"checksum sysfs_gpio 0.5.3 (git+https://github.com/rust-embedded/rust-sysfs-gpio)" = "" -"checksum sysfs_gpio 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d68f2cae3c7d39f54ce8a858cc31ffb01974744ee65e5b4999b6037cd691e3f" -"checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum structopt 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "df136b42d76b1fbea72e2ab3057343977b04b4a2e00836c3c7c0673829572713" +"checksum structopt-derive 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd50a87d2f7b8958055f3e73a963d78feaccca3836767a9069844e34b5b03c0a" +"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +"checksum syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7bedb3320d0f3035594b0b723c8a28d7d336a3eda3881db79e61d676fb644c" +"checksum syn-mid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd3937748a7eccff61ba5b90af1a20dbf610858923a9192ea0ecb0cb77db1d0" +"checksum synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" +"checksum sysfs_gpio 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "24961a55846623d8e4f6cec38718945116fed8d6970336a7110710a07aa9b5d1" +"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "cec6c34409089be085de9403ba2010b80e36938c9ca992c4f67f407bb13db0b1" +"checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" +"checksum tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8fdd17989496f49cdc57978c96f0c9fe5e4a58a8bddc6813c449a4624f6a030b" +"checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" "checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" -"checksum tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "83ea44c6c0773cc034771693711c35c677b4b5a4b21b9e7071704c54de7d555e" +"checksum tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f27ee0e6db01c5f0b2973824547ce7e637b2ed79b891a9677b0de9bd532b6ac" "checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" -"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" -"checksum tokio-rustls 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1600e90b2602df28ff54ae842519b408fbb25378c3c5aee1b795593e9263dc80" +"checksum tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c56391be9805bc80163151c0b9e5164ee64f4b0200962c346fea12773158f22d" +"checksum tokio-rustls 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2d7cf08f990090abd6c6a73cab46fed62f85e8aef8b99e4b918a9f4a637f0676" +"checksum tokio-rustls 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "141afec0978abae6573065a48882c6bae44c5cc61db9b511ac4abf6a09bfd9cc" "checksum tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "dd6dc5276ea05ce379a16de90083ec80836440d5ef8a6a39545a3207373b8296" -"checksum tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2f843ffdf8d6e1f90bddd48da43f99ab071660cd92b7ec560ef3cdfd7a409a" +"checksum tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d06554cce1ae4a50f42fba8023918afa931413aded705b560e29600ccf7c6d76" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72558af20be886ea124595ea0f806dd5703b8958e4705429dd58b3d8231f72f2" -"checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" -"checksum tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "350c9edade9830dc185ae48ba45667a445ab59f6167ef6d0254ec9d2430d9dd3" -"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" +"checksum tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd2c6a3885302581f4401c82af70d792bb9df1700e7437b0aeb4ada94d5388c" +"checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" +"checksum tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f02298505547f73e60f568359ef0d016d5acd6e830ab9bc7c4a5b3403440121b" "checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" +"checksum tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" "checksum tower-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b32f72af77f1bfe3d3d4da8516a238ebe7039b51dd8637a09841ac7f16d2c987" +"checksum trust-dns-proto 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2a7f3a2ab8a919f5eca52a468866a67ed7d3efa265d48a652a9a3452272b413f" "checksum trust-dns-proto 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0838272e89f1c693b4df38dc353412e389cf548ceed6f9fd1af5a8d6e0e7cf74" "checksum trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "09144f0992b0870fa8d2972cc069cbf1e3c0fda64d1f3d45c4d68d0e0b52ad4e" -"checksum trust-dns-proto 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5559ebdf6c2368ddd11e20b11d6bbaf9e46deb803acd7815e93f5a7b4a6d2901" "checksum trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a9f877f7a1ad821ab350505e1f1b146a4960402991787191d6d8cab2ce2de2c" -"checksum trust-dns-resolver 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c9992e58dba365798803c0b91018ff6c8d3fc77e06977c4539af2a6bfe0a039" +"checksum trust-dns-resolver 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" -"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" -"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" -"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -"checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" +"checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" +"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" +"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" -"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" -"checksum v_escape 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8865501b78eef9193c1b45486acf18ba889e5662eba98854d6fc59d8ecf3542d" -"checksum v_escape_derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "306896ff4b75998501263a1dc000456de442e21d68fe8c8bdf75c66a33a58e23" -"checksum v_htmlescape 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7fbbe0fa88dd36f9c8cf61a218d4b953ba669de4d0785832f33cc72bd081e1be" -"checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" +"checksum v_escape 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "660b101c07b5d0863deb9e7fb3138777e858d6d2a79f9e6049a27d1cc77c6da6" +"checksum v_escape_derive 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae" +"checksum v_htmlescape 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e33e939c0d8cf047514fb6ba7d5aac78bc56677a6938b2ee67000b91f2e97e41" +"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" +"checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" "checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" -"checksum webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4f7e1cd7900a3a6b65a3e8780c51a3e6b59c0e2c55c6dc69578c288d69f7d082" -"checksum webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c10fa4212003ba19a564f25cd8ab572c6791f99a03cc219c13ed35ccab00de0e" +"checksum wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "5205e9afdf42282b192e2310a5b463a6d1c1d774e30dc3c791ac37ab42d2616c" +"checksum wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "11cdb95816290b525b32587d76419facd99662a07e59d3cdb560488a819d9a45" +"checksum wasm-bindgen-macro 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "574094772ce6921576fb6f2e3f7497b8a76273b6db092be18fc48a082de09dc3" +"checksum wasm-bindgen-macro-support 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "e85031354f25eaebe78bb7db1c3d86140312a911a106b2e29f9cc440ce3e7668" +"checksum wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e7e61fc929f4c0dddb748b102ebf9f632e2b8d739f2016542b4de2965a9601" +"checksum wasm-bindgen-webidl 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ef012a0d93fc0432df126a8eaf547b2dce25a8ce9212e1d3cbeef5c11157975d" +"checksum web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "aaf97caf6aa8c2b1dac90faf0db529d9d63c93846cca4911856f78a83cebf53b" +"checksum webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7e664e770ac0110e2384769bcc59ed19e329d81f555916a6e072714957b81b4" +"checksum webpki-roots 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a262ae37dd9d60f60dd473d1158f9fbebf110ba7b6a5051c8160460f6043718b" +"checksum weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164" "checksum widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" "checksum widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 67a00d4f..bc8c2c2e 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,31 +14,32 @@ sensors_connected = [] live_server = [] [dependencies] -actix-web = { version = "1.0.3", features = ["rust-tls"] } -actix-net = "0.2.4" -actix-identity = "0.1.0" -actix-files = "0.1.3" -actix-rt = "0.2.4" -actix-service = "0.4.1" -actix-web-httpauth = "0.3.2" -rustls = "0.15.2" +futures = "0.3.1" +actix-web = { version = "2", features = ["rustls"] } +actix-net = "0.2.6" +actix-identity = "0.2.0" +actix-files = "0.2.1" +actix-rt = "1" +actix-service = "1.0" +actix-web-httpauth = "0.4" +rustls = "0.16" philipshue = { git = "https://github.com/dskleingeld/philipshue", branch = "master" } # for local dev purpose we use below targets # philipshue = { path = "../philipshue"} -secure-ble = { path = "../home_sensors/ble/central"} +# secure-ble = { path = "../home_sensors/ble/central"} +structopt = "0.3" serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.8" log = "0.4" -#sysfs_gpio = { version = "0.5.3", features = ["use_tokio"] } -sysfs_gpio = { git = "https://github.com/rust-embedded/rust-sysfs-gpio", branch = "master", features = ["use_tokio"] } +sysfs_gpio = { version = "0.5.4", features = ["use_tokio"] } +#sysfs_gpio = { git = "https://github.com/rust-embedded/rust-sysfs-gpio", branch = "master", features = ["use_tokio"] } tokio = "0.1.15" -futures = { version = "0.1"} bincode = "1.0.1" -ring = "0.14.6" +ring = "0.16" linux-embedded-hal = "0.2.2" bme280 = "0.1.1" @@ -51,7 +52,7 @@ num = { version = "0.2"} crossbeam-channel = "0.3" -sled = "0.24.1" +sled = "0.30" pagecache = "0.17.0" reqwest = "0.9.15" diff --git a/src/controller/commands.rs b/src/controller/commands.rs index e95afe03..ce42dc91 100755 --- a/src/controller/commands.rs +++ b/src/controller/commands.rs @@ -1,5 +1,6 @@ use super::{ActiveState, Modifications, System}; use crate::controller::states::*; +use crate::controller::system::mpd_control; #[derive(Copy, Clone)] pub enum Command { @@ -10,7 +11,10 @@ pub enum Command { LampsNight, LampsDay, - PauseMpd, + MpdPause, + MpdDecreaseVolume, + MpdIncreaseVolume, + GoToLinux, GoToWindows, @@ -19,6 +23,7 @@ pub enum Command { ChangeState(TargetState), } +//TODO handle error on command pub fn handle_cmd(cmd: Command, state: ActiveState, mods: &mut Modifications, sys: &mut System) -> ActiveState { println!("handled a command"); match cmd { @@ -37,7 +42,9 @@ pub fn handle_cmd(cmd: Command, state: ActiveState, mods: &mut Modifications, sy Command::GoToLinux => println!("should go to linux"), Command::GoToWindows => println!("should go to windows"), - Command::PauseMpd => println!("should pause mpd"), + Command::MpdPause => {mpd_control::toggle_playback(&mut sys.mpd).unwrap(); mods.mpd = true }, + Command::MpdDecreaseVolume => {mpd_control::increase_volume(&mut sys.mpd).unwrap(); mods.mpd = true }, + Command::MpdIncreaseVolume => {mpd_control::decrease_volume(&mut sys.mpd).unwrap(); mods.mpd = true }, Command::Test => { warn!("The Test command was just send")}, } diff --git a/src/controller/mod.rs b/src/controller/mod.rs index fb497045..d7825d99 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -16,6 +16,7 @@ pub use commands::Command; pub use states::TargetState; #[cfg(feature = "sensors_connected")] use crate::input::sensors::SensorValue; +use crate::input::mpd_status::MpdStatus; use crate::errors::Error; pub enum Event { @@ -45,6 +46,7 @@ pub struct System { next_update: Instant, lights: Lighting, + mpd: MpdStatus //mpd //etc @@ -59,14 +61,14 @@ fn saturating_duration_till(target: std::time::Instant) -> std::time::Duration{ } } -pub fn start(rx: crossbeam_channel::Receiver) -> Result, Error>{ +pub fn start(rx: crossbeam_channel::Receiver, mpd_status: MpdStatus) -> Result, Error>{ let mut system = System { update_period: Duration::from_secs(5), next_update: Instant::now()+Duration::from_secs(5), lights: Lighting::init()?, - //mpd init? + mpd: mpd_status, }; let handle = thread::spawn(move || { @@ -102,7 +104,7 @@ pub fn start(rx: crossbeam_channel::Receiver) -> Result {dbg!("a test happend"); change_state(TargetState::WakeUp, &mut mods, &mut system)}, #[cfg(feature = "sensors_connected")] - (Event::Sensor(_), _) => {dbg!("sensor data recieved"); state} + (Event::Sensor(_), _) => {dbg!("a sensor happend"); state} }; } }); diff --git a/src/controller/system/mpd_control.rs b/src/controller/system/mpd_control.rs index 8a4da0e1..603682ff 100755 --- a/src/controller/system/mpd_control.rs +++ b/src/controller/system/mpd_control.rs @@ -2,6 +2,8 @@ use crate::errors::Error; use chrono::Duration; use rand::Rng; +use crate::input::mpd_status::MpdStatus; + pub fn add_from_playlist(mpd: &mut mpd::Client, name: &str, minimal_play_time: Duration, maximal_play_time: Duration) -> Result<(),Error>{ let mut rng = rand::thread_rng(); @@ -31,6 +33,39 @@ pub fn add_from_playlist(mpd: &mut mpd::Client, name: &str, minimal_play_time: D Ok(()) } +pub fn increase_volume(mpd_status: &mut MpdStatus) -> Result<(),Error>{ + const VOLUME_INCREMENT: i8 = 1; + + let mut client = mpd::Client::connect("127.0.0.1:6600")?; + let current_volume = mpd_status.get_volume(); + if current_volume + VOLUME_INCREMENT > 100 {return Ok(()); } + + client.volume(current_volume+VOLUME_INCREMENT)?; + Ok(()) +} + +pub fn decrease_volume(mpd_status: &mut MpdStatus) -> Result<(),Error>{ + const VOLUME_INCREMENT: i8 = 1; + + let mut client = mpd::Client::connect("127.0.0.1:6600")?; + let current_volume = mpd_status.get_volume(); + if current_volume - VOLUME_INCREMENT < 0 {return Ok(()); } + + client.volume(current_volume-VOLUME_INCREMENT)?; + Ok(()) +} + +pub fn toggle_playback(mpd_status: &mut MpdStatus) -> Result<(), Error>{ + let mut client = mpd::Client::connect("127.0.0.1:6600")?; + + match mpd_status.is_playing() { + mpd::status::State::Stop => client.play()?, + mpd::status::State::Pause => client.toggle_pause()?, + mpd::status::State::Play => client.toggle_pause()?, + } + Ok(()) +} + pub fn save_current_playlist(mpd: &mut mpd::Client) -> Result<(),Error>{ dbg!(); mpd.pl_remove("temp")?; diff --git a/src/errors.rs b/src/errors.rs index d67b3e3e..4e3830f3 100755 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,4 +1,7 @@ //use std::fmt; +use std::sync::RwLock; + +use crate::input::youtube_downloader; #[derive(Debug)] pub enum Error { @@ -11,9 +14,16 @@ pub enum Error { Lamps(philipshue::errors::HueError), Mpd(mpd::error::Error), RetryLogic(String), + YoutubeDownloader(youtube_downloader::Error), UnTracked, } +impl From for Error { + fn from(err: youtube_downloader::Error) -> Self { + Error::YoutubeDownloader(err) + } +} + impl From for Error { fn from(error: serde_yaml::Error) -> Self { Error::YamlParsing(error) diff --git a/src/input/alarms.rs b/src/input/alarms.rs index e277b4ca..5d0126a2 100755 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -24,7 +24,7 @@ pub struct Alarms { #[derive(Clone)] pub struct AlarmList { - db: Arc, + db: sled::Tree, } fn waker(mut alarm_list: AlarmList, event_tx: crossbeam_channel::Sender, waker_rx: crossbeam_channel::Receiver<()>) { diff --git a/src/input/buttons.rs b/src/input/buttons.rs index 77ab6b29..07507f6e 100755 --- a/src/input/buttons.rs +++ b/src/input/buttons.rs @@ -51,13 +51,15 @@ fn stream(mut pin_numb_command_pairs: Vec<(u64, Command)>, tx: crossbeam_channel pub fn start_monitoring(tx: crossbeam_channel::Sender) { thread::spawn(move || { let pin_numb_command_pairs = vec!( + //buttons near lamp (16, Command::LampsDim), (12, Command::LampsDimmest), (13, Command::LampsToggle), - (27, Command::LampsToggle), //left 3, left - (22, Command::LampsToggle), //left 3, middle - (18, Command::LampsToggle), //left 3, right + //buttons on desk + (27, Command::MpdIncreaseVolume), //left 3, left + (22, Command::MpdPause), //left 3, middle + (18, Command::MpdDecreaseVolume), //left 3, right (23, Command::LampsNight), //right 4, left most (24, Command::LampsEvening), //right 4, left diff --git a/src/input/mod.rs b/src/input/mod.rs index da6e02af..88065909 100755 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -6,7 +6,7 @@ pub mod buttons; pub mod web_api; pub mod alarms; pub mod youtube_downloader; -mod mpd_status; +pub mod mpd_status; pub use youtube_downloader::YoutubeDownloader; pub use mpd_status::MpdStatus; \ No newline at end of file diff --git a/src/input/mpd_status.rs b/src/input/mpd_status.rs index e7413505..f893609f 100755 --- a/src/input/mpd_status.rs +++ b/src/input/mpd_status.rs @@ -12,6 +12,16 @@ pub struct MpdStatus { inner: Arc>, } +impl MpdStatus { + pub fn get_volume(&mut self) -> i8 { + self.inner.read().unwrap().volume + } + + pub fn is_playing(&mut self) -> mpd::status::State { + self.inner.read().unwrap().state + } +} + fn mpd_watcher(mut client: Client, status: MpdStatus, rx: Receiver<()>) { client.wait(&[Subsystem::Player, Subsystem::Mixer]).unwrap(); loop { diff --git a/src/input/sensors/ble/mod.rs b/src/input/sensors/ble/mod.rs index 74ad4b63..4fc4683c 100755 --- a/src/input/sensors/ble/mod.rs +++ b/src/input/sensors/ble/mod.rs @@ -1,7 +1,7 @@ //use secure_ble::{connect_to_adapter, connect_to_node, authenticate_node, StreamCipher, subscribe, printvalues}; -mod node_credentials; -use node_credentials::*; +mod ble_credentials; +use ble_credentials::*; pub fn init(){ diff --git a/src/input/sensors/ble/node_credentials.rs b/src/input/sensors/ble/node_credentials.rs deleted file mode 100755 index bfe5431b..00000000 --- a/src/input/sensors/ble/node_credentials.rs +++ /dev/null @@ -1,24 +0,0 @@ -use secure_ble::UUID; - -//shared -pub const FAST_MEASURMENTS_UUID: UUID = UUID::B128([137, 20, 153, 220, 231, 245, 91, 152, 153, 21, 183, 27, 175, 191, 112, 147]); -pub const SLOW_MEASURMENTS_UUID: UUID = UUID::B128([137, 20, 153, 220, 231, 245, 91, 152, 153, 21, 183, 27, 175, 191, 112, 147]); - -//specific -pub mod node_bed { - pub const KEY: [u8;16] - = [66,72,79,15,11,8,27,55,83,75,91,63,21,32,84,87]; - pub const HMAC_KEY: [u8;16] - = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; - pub const ADRESS: &str - = "C6:46:56:AC:2C:4C"; //TODO change -} - -pub mod node_bathroom { - pub const KEY: [u8;16] - = [66,72,79,15,11,8,27,55,83,75,91,63,21,32,84,87]; - pub const HMAC_KEY: [u8;16] - = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; - pub const ADRESS: &str - = "C6:46:56:AC:2C:4C"; -} \ No newline at end of file diff --git a/src/input/sensors/fields/compression.rs b/src/input/sensors/fields/compression.rs index 05af2d9b..91d9e60d 100644 --- a/src/input/sensors/fields/compression.rs +++ b/src/input/sensors/fields/compression.rs @@ -64,7 +64,7 @@ //println!("used_bits: {}", used_bits); let stop_mask = !(!0 >> used_bits); //println!("stop_mask: {}", stop_mask); - let stop_byte = div_up(bit_offset+length, 8) as usize;//starts at 0 + let stop_byte = div_up(bit_offset+length, 8) as usize;//starts at 0 line[stop_byte-1] |= (to_encode >> (bits_written-(8-used_bits))) as u8 & stop_mask; } diff --git a/src/input/sensors/local.rs b/src/input/sensors/local.rs index a9fcd956..672c75eb 100755 --- a/src/input/sensors/local.rs +++ b/src/input/sensors/local.rs @@ -5,27 +5,35 @@ use hal::{Delay, I2cdev}; use bme280::BME280; use super::fields::Field; +pub const START_ENCODE: u8 = 10*8; pub const TEMPERATURE: Field = Field { - offset: 5, //bits - length: 3, //bits (max 32 bit variables) + offset: START_ENCODE, //bits + length: 13, //bits (max 32 bit variables) - decode_scale: 1f32, - decode_add: 1f32, + decode_scale: 0.009999999776482582, + decode_add: -20.0f32, }; pub const HUMIDITY: Field = Field { - offset: 5, - length: 3, + offset: START_ENCODE + +TEMPERATURE.length, + length: 14, - decode_scale: 1f32, - decode_add: 1f32, + decode_scale: 0.00800000037997961, + decode_add: 0.0, }; pub const PRESSURE: Field = Field { - offset: 5, - length: 3, + offset: START_ENCODE + +TEMPERATURE.length + +HUMIDITY.length, + length: 19, - decode_scale: 1f32, - decode_add: 1f32, + decode_scale: 0.18000000715255738, + decode_add: 30000.0, }; +pub const STOP_ENCODE: usize = (START_ENCODE + +TEMPERATURE.length + +HUMIDITY.length + +PRESSURE.length) as usize; pub fn init() -> BME280 { // using Linux I2C Bus #1 in this example diff --git a/src/input/sensors/mod.rs b/src/input/sensors/mod.rs index 939e9caf..3852960c 100755 --- a/src/input/sensors/mod.rs +++ b/src/input/sensors/mod.rs @@ -1,7 +1,7 @@ extern crate chrono; extern crate smallvec; extern crate bytes; -use byteorder::{LittleEndian, WriteBytesExt}; +use byteorder::{LittleEndian, ByteOrder}; #[cfg(feature = "sensors_connected")] mod local; @@ -14,7 +14,7 @@ use chrono::Utc; use crate::credentials; use crate::controller::Event; -use local::{TEMPERATURE, HUMIDITY, PRESSURE}; +use local::{TEMPERATURE, HUMIDITY, PRESSURE, STOP_ENCODE}; pub enum SensorValue { Temperature(f32), @@ -41,24 +41,28 @@ pub fn start_monitoring(tx: crossbeam_channel::Sender) { //TODO //process data into events and send off as event tx.send(Event::Sensor(SensorValue::Temperature(temp))); - tx.send(Event::Sensor(SensorValue::Humidity(hum))); - tx.send(Event::Sensor(SensorValue::Pressure(pressure))); + tx.send(Event::Sensor(SensorValue::Humidity(hum))); + tx.send(Event::Sensor(SensorValue::Pressure(pressure))); //encode all data - let mut line: Vec = vec!(0;64); - - line.write_u16::(credentials::NODE_ID).unwrap(); - line.write_u64::(credentials::DATASERVER_KEY).unwrap(); + let mut line = vec!(0u8; (STOP_ENCODE+8-1)/8); + LittleEndian::write_u16(&mut line[0..2], credentials::NODE_ID); + LittleEndian::write_u64(&mut line[2..10], credentials::DATASERVER_KEY); - HUMIDITY.encode::(hum, &mut line); TEMPERATURE.encode::(temp, &mut line); + HUMIDITY.encode::(hum, &mut line); PRESSURE.encode::(pressure, &mut line); + + dbg!(&line); //send data to dataserver let client = reqwest::Client::new(); - client.post("http://www.deviousd.duckdns.org:8080/post_data") + if let Err(e) = client.post("https://www.deviousd.duckdns.org:38972/post_data") .body(line) - .send().unwrap(); + .send(){ + + error!("could not send data to dataserver, error: {:?}", e); + } //sleep until 5 seconds are completed thread::sleep(Duration::from_secs(5)); diff --git a/src/input/web_api/server/database.rs b/src/input/web_api/server/database.rs index 32c8904d..ac08f0c7 100755 --- a/src/input/web_api/server/database.rs +++ b/src/input/web_api/server/database.rs @@ -1,21 +1,10 @@ -use serde::{Deserialize,Serialize}; - use sled::{Db,Tree}; -use bincode; use ring::{digest, pbkdf2}; - use std::num::NonZeroU32; -use std::sync::Arc; - -use chrono::{DateTime, Utc}; -static DIGEST_ALG: &'static digest::Algorithm = &digest::SHA256; +static PBKDF2_ALG: pbkdf2::Algorithm = pbkdf2::PBKDF2_HMAC_SHA256; const CREDENTIAL_LEN: usize = digest::SHA256_OUTPUT_LEN; -const PBKDF2_ITERATIONS: NonZeroU32 = unsafe {NonZeroU32::new_unchecked(100_000)}; -const DB_SALT_COMPONENT: [u8; 16] = [ // This value was generated from a secure PRNG. //TODO check this - 0xd6, 0x26, 0x98, 0xda, 0xf4, 0xdc, 0x50, 0x52, - 0x24, 0xf2, 0x27, 0xd1, 0xfe, 0x39, 0x01, 0x8a]; pub enum PasswDbError { WrongUsername, @@ -25,43 +14,67 @@ pub enum PasswDbError { #[derive(Debug, Clone)] pub struct PasswordDatabase { - pub storage: Arc, + pbkdf2_iterations: NonZeroU32, + db_salt_component: [u8; 16], + pub storage: Tree, } impl PasswordDatabase { pub fn from_db(db: &Db) -> Result { Ok(Self { + pbkdf2_iterations: NonZeroU32::new(100_000).unwrap(), + db_salt_component: [ + // This value was generated from a secure PRNG. + 0xd6, 0x26, 0x98, 0xda, 0xf4, 0xdc, 0x50, 0x52, + 0x24, 0xf2, 0x27, 0xd1, 0xfe, 0x39, 0x01, 0x8a + ], storage: db.open_tree("passw_database")?, //created it not exist }) } pub fn set_password(&mut self, username: &[u8], password: &[u8]) - -> Result<(), sled::Error> { + -> Result<(), sled::Error> { let salt = self.salt(username); let mut credential = [0u8; CREDENTIAL_LEN]; - pbkdf2::derive(DIGEST_ALG, PBKDF2_ITERATIONS, &salt, password, &mut credential); + pbkdf2::derive(PBKDF2_ALG, self.pbkdf2_iterations, + &salt, password, &mut credential); - self.storage.set(username, &credential)?; + self.storage.insert(username, &credential)?; self.storage.flush()?; Ok(()) } + pub fn add_admin(&mut self, password: &str) -> Result<(), sled::Error>{ + self.set_password("admin".as_bytes(), password.as_bytes()) + } + + pub async fn remove_user(&self, username: &[u8]) -> Result<(), sled::Error> { + self.storage.remove(username)?; + self.storage.flush_async().await?; + Ok(()) + } + + pub fn update(&self, old_name: &str, new_name: &str) { + if old_name == new_name {return; } + let credential = self.storage.get(old_name.as_bytes()).unwrap().unwrap(); + self.storage.insert(new_name.as_bytes(), credential).unwrap(); + } + pub fn verify_password(&self, username: &[u8], attempted_password: &[u8]) -> Result<(), PasswDbError> { if let Ok(db_entry) = self.storage.get(username) { if let Some(credential) = db_entry { let salted_attempt = self.salt(username); - pbkdf2::verify(DIGEST_ALG, PBKDF2_ITERATIONS, &salted_attempt, - attempted_password, - &credential) + pbkdf2::verify(PBKDF2_ALG, self.pbkdf2_iterations, + &salted_attempt, attempted_password, &credential) .map_err(|_| PasswDbError::WrongPassword) } else { Err(PasswDbError::WrongUsername) } } else { Err(PasswDbError::Internal )} } - pub fn is_user_in_database(&self, username: &[u8]) -> Result { - self.storage.contains_key(username) - } + //pub fn is_user_in_database(&self, username: &[u8]) -> Result { + // self.storage.contains_key(username) + //} // The salt should have a user-specific component so that an attacker // cannot crack one password for multiple users in the database. It @@ -70,68 +83,10 @@ impl PasswordDatabase { // but common case that the user has used the same password for // multiple systems. pub fn salt(&self, username: &[u8]) -> Vec { - let mut salt = Vec::with_capacity(DB_SALT_COMPONENT.len() + username.len()); - salt.extend(DB_SALT_COMPONENT.as_ref()); + let mut salt = Vec::with_capacity(self.db_salt_component.len() + + username.len()); + salt.extend(self.db_salt_component.as_ref()); salt.extend(username); salt } -} - - - -#[derive(Debug, Clone)] -pub struct UserDatabase { - pub storage: Arc, -} - -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -pub struct UserInfo { - pub last_login: DateTime, - pub username: String, -} - -#[derive(Debug)] -pub enum UserDbError { - UserNotInDb, - DatabaseError(sled::Error), - SerializeError(bincode::Error), -} - -impl From for UserDbError { - fn from(error: sled::Error) -> Self { - UserDbError::DatabaseError(error) - } -} -impl From for UserDbError { - fn from(error: bincode::Error) -> Self { - UserDbError::SerializeError(error) - } -} - - -impl UserDatabase { - pub fn from_db(db: &Db) -> Result { - Ok(Self { - storage: db.open_tree("user_database")?, //created it not exist - }) - } - - pub fn get_userdata>(&self, username: T) -> Result { - let username = username.as_ref(); - if let Some(user_data) = self.storage.get(username)? { - let user_info = bincode::deserialize(&user_data)?; - Ok(user_info) - } else { - Err(UserDbError::UserNotInDb) - } - } - - pub fn set_userdata(&mut self, user_info: UserInfo) - -> Result <(),UserDbError> { - let username = user_info.username.as_str().as_bytes(); - let user_data = bincode::serialize(&user_info)?; - self.storage.set(username,user_data)?; - self.storage.flush()?; - Ok(()) - } -} +} \ No newline at end of file diff --git a/src/input/web_api/server/login.rs b/src/input/web_api/server/login.rs index 621b9651..22c19be1 100755 --- a/src/input/web_api/server/login.rs +++ b/src/input/web_api/server/login.rs @@ -29,7 +29,7 @@ pub struct Logindata { } /// State and POST Params -pub fn login_get_and_check( +pub async fn login_get_and_check( id: Identity, state: Data, req: HttpRequest, @@ -48,14 +48,7 @@ pub fn login_get_and_check( .body("incorrect password or username")); } else { info!("user logged in");} - //copy userinfo into new session - let _userinfo = state.user_db.get_userdata(¶ms.u).unwrap(); - //userinfo.last_login = Utc::now(); - //passw_db.set_userdata(params.u.as_str().as_bytes(), userinfo.clone()); - - let session = Session { - last_login: chrono::Utc::now(), //TODO write back to database - }; + let session = Session {};//kept in case we want it back in the future //find free session_numb, set new session number and store new session let session_id = state.free_session_ids.fetch_add(1, Ordering::Acquire); let mut sessions = state.sessions.write().unwrap(); diff --git a/src/input/web_api/server/login_redirect.rs b/src/input/web_api/server/login_redirect.rs index e7299014..6774c0d7 100755 --- a/src/input/web_api/server/login_redirect.rs +++ b/src/input/web_api/server/login_redirect.rs @@ -1,17 +1,20 @@ +use std::task::{Context, Poll}; + use actix_service::{Service, Transform}; use actix_web::dev::{ServiceRequest, ServiceResponse}; use actix_web::{http, Error, HttpResponse, web}; -use futures::future::{ok, Either, FutureResult}; -use futures::Poll; +use futures::future::{ok, Either, Ready}; use log::{info}; -use super::State; use actix_identity::RequestIdentity; +//example to mimic: https://github.com/actix/examples/blob/master/middleware/src/redirect.rs + +use super::State; #[derive(Default)] -pub struct CheckLogin; +pub struct CheckLogin{} impl Transform for CheckLogin where @@ -23,7 +26,7 @@ where type Error = Error; type InitError = (); type Transform = CheckLoginMiddleware; - type Future = FutureResult; + type Future = Ready>; fn new_transform(&self, service: S) -> Self::Future { ok(CheckLoginMiddleware { service }) @@ -55,37 +58,44 @@ where type Request = ServiceRequest; type Response = ServiceResponse; type Error = Error; - type Future = Either>; + type Future = Either>>; + //type Future = Pin>>>; - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - self.service.poll_ready() + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.service.poll_ready(cx) } fn call(&mut self, req: ServiceRequest) -> Self::Future { // We only need to hook into the `start` for this middleware. if let Some(id) = req.get_identity() { + //let id = req.get_identity().unwrap(); let data: web::Data = req.app_data().unwrap(); if is_logged_in(&data, id).is_ok() { - Either::A(self.service.call(req)) + //let fut = + Either::Left(self.service.call(req)) } else { let redirect = "/login".to_owned()+req.path(); - Either::B(ok(req.into_response( + Either::Right( + ok(req.into_response( HttpResponse::Found() .header(http::header::LOCATION, redirect) .finish() .into_body(), //TODO why comma? is needed? - ))) + )) + ) } } else { info!("could not get identity thus redirecting"); let redirect = "/login".to_owned()+req.path(); - Either::B(ok(req.into_response( + Either::Right( + ok(req.into_response( HttpResponse::Found() .header(http::header::LOCATION, redirect) .finish() .into_body(), //TODO why comma? is needed? - ))) + )) + ) } } } \ No newline at end of file diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index 3d6a97f1..3b10c817 100755 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -1,8 +1,14 @@ use chrono::{DateTime, Utc}; use rustls::{NoClientAuth, ServerConfig}; use rustls::internal::pemfile::{certs, pkcs8_private_keys}; + +use actix_rt::Runtime; +use actix_web::{HttpServer,App, web, Responder}; +use actix_identity::{CookieIdentityPolicy, IdentityService}; +use actix_files as fs; use actix_web::HttpRequest; +use std::thread; use std::sync::{Arc, Mutex, RwLock, atomic::AtomicUsize}; use std::collections::HashMap; use std::path::Path; @@ -10,27 +16,28 @@ use std::io::BufReader; use std::fs::File; use crate::input; +use crate::input::web_api; use crate::controller::Event; pub mod database; pub mod login_redirect; pub mod login; -pub use database::{PasswordDatabase,UserDatabase}; -pub use login::make_random_cookie_key; +pub use database::PasswordDatabase; +pub use login::{make_random_cookie_key, login_page, login_get_and_check, logout}; pub use login_redirect::CheckLogin; +#[cfg(feature = "live_server")] +const SOCKETADDR: &'static str = "0.0.0.0:8080"; +#[cfg(not(feature = "live_server"))] +const SOCKETADDR: &'static str = "0.0.0.0:8070"; -pub struct Session {//TODO deprecate - last_login: DateTime, - //add more temporary user specific data as needed -} +pub struct Session {}//TODO deprecate pub struct State { pub controller_addr: crossbeam_channel::Sender, pub alarms: input::alarms::Alarms, pub passw_db: PasswordDatabase, - pub user_db: UserDatabase, pub sessions: Arc> >>> , pub free_session_ids: Arc, pub youtube_dl: input::YoutubeDownloader, @@ -49,6 +56,82 @@ pub fn make_tls_config>(signed_cert_path: P, private_key_path: P) tls_config } -pub fn index(_req: HttpRequest) -> &'static str { +pub async fn index(_req: HttpRequest) -> impl Responder { "Hello world!" +} + +pub fn start_webserver(signed_cert: &str, private_key: &str, + passw_db: PasswordDatabase, + controller_tx: crossbeam_channel::Sender, + alarms: input::alarms::Alarms, + youtube_dl: input::YoutubeDownloader, + _mpd_status: input::MpdStatus, + ) -> actix_web::dev::Server { + + let tls_config = make_tls_config(signed_cert, private_key); + let cookie_key = make_random_cookie_key(); + + let free_session_ids = Arc::new(AtomicUsize::new(0)); + let sessions = Arc::new(RwLock::new(HashMap::new())); + let (tx, rx) = crossbeam_channel::unbounded(); + + thread::spawn(move || { + let web_server = HttpServer::new(move || { + // data the webservers functions have access to + let data = actix_web::web::Data::new(State { + controller_addr: controller_tx.clone(), + alarms: alarms.clone(), + passw_db: passw_db.clone(), + youtube_dl: youtube_dl.clone(), + sessions: sessions.clone(), + free_session_ids: free_session_ids.clone(), + }); + + App::new() + .app_data(data) + .wrap(IdentityService::new( + CookieIdentityPolicy::new(&cookie_key[..]) + .domain("deviousd.duckdns.org") + .name("auth-cookie") + .path("/") + .secure(true), + )) + .service( + web::scope("/login") + .service(web::resource(r"/{path}") + .route(web::post().to(login_get_and_check)) + .route(web::get().to(login_page)) + )) + .service(web::resource("/commands/lamps/toggle").to(web_api::toggle)) + .service(web::resource("/commands/lamps/evening").to(web_api::evening)) + .service(web::resource("/commands/lamps/night").to(web_api::night)) + .service(web::resource("/commands/lamps/day").to(web_api::normal)) + .service(web::resource("/commands/lamps/dimmest").to(web_api::dimmest)) + .service(web::resource("/commands/lamps/dim").to(web_api::dim)) + .service(web::resource("/commands/lightloop").to(web_api::lightloop)) + + .service(web::scope("/") + .wrap(CheckLogin{}) + + .service(web::resource("").to(index)) + .service(web::resource("logout/").to(logout)) + .service(web::resource("add_song").to(web_api::add_song_from_url)) + .service(web::resource("set_alarm").to(web_api::set_alarm_unix_timestamp)) + .service(web::resource("list_alarms").to(web_api::list_alarms)) + //for all other urls we try to resolve to static files in the "web" dir + .service(fs::Files::new("", "./web/")) + ) + }) + .bind_rustls(SOCKETADDR, tls_config).unwrap() + //.bind("0.0.0.0:8080").unwrap() //without tcp use with debugging (note: https -> http, wss -> ws) + .shutdown_timeout(5) // shut down 5 seconds after getting the signal to shut down + .run(); + + let _ = tx.send(web_server.clone()); + let mut rt = Runtime::new().unwrap(); + rt.block_on(web_server); + }); + + let web_handle = rx.recv().unwrap(); + web_handle } \ No newline at end of file diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index 413076be..5a51a11c 100755 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -4,18 +4,45 @@ use std::fs; use std::os::unix::fs::OpenOptionsExt; use std::thread; +use std::time::Duration; use std::path::Path; use reqwest::{IntoUrl}; -use crate::errors::Error; -fn download_file(url: U, save_path: &Path) -> Result<(), Error> { +const DIR: &str = "temp"; +const YOUTUBE_DL_LOC: &str = "temp/youtube-dl"; + +#[derive(Debug)] +pub enum Error{ + CouldNotDownloadExecutable(reqwest::Error), + CouldNotStoreExecutable(std::io::Error), + CouldNotDownloadSong, + CouldNotUpdateMpd(mpd::error::Error), +} + +impl From for Error { + fn from(err: reqwest::Error) -> Self { + Error::CouldNotDownloadExecutable(err) + } +} +impl From for Error { + fn from(err: std::io::Error) -> Self { + Error::CouldNotStoreExecutable(err) + } +} +impl From for Error { + fn from(err: mpd::error::Error) -> Self { + Error::CouldNotUpdateMpd(err) + } +} + +fn download_youtube_dl(url: U) -> Result<(), Error> { let mut dest = fs::OpenOptions::new() .create(true) .write(true) .mode(0o770) - .open(save_path)?; + .open(YOUTUBE_DL_LOC)?; let mut response = reqwest::get(url)?; copy(&mut response, &mut dest)?; @@ -28,33 +55,59 @@ pub struct YoutubeDownloader { url_tx: crossbeam_channel::Sender, } +fn run_youtube_dl(output_arg: &String, url: &str) + -> std::io::Result { + + let full_path = Path::new(YOUTUBE_DL_LOC); + Command::new(full_path) + .arg("--geo-bypass") + .arg("--ignore-config") + .arg("--add-metadata") + .arg("--metadata-from-title \"%(artist)s - %(title)s\"") + + .arg("--embed-thumbnail") + .arg("--audio-format") + .arg("m4a") + .arg("--audio-quality") + .arg("257") + .arg("--postprocessor-args") + .arg("\"-ar 44100\"") + .arg("--extract-audio") + .arg("--format") + .arg("bestaudio[acodec=opus]/bestaudio/best") + + .arg(&output_arg) + .arg(url) + .output() +} + fn download_song(url: &str) -> Result<(), Error> { - //let mut music_dir = dirs::home_dir().unwrap(); - //music_dir.push("Music"); let music_dir = std::path::PathBuf::from("/home/pi/Music"); let mut output_arg = String::from(music_dir.to_str().unwrap()); output_arg.push_str("/%(title)s.%(ext)s"); - let full_path = Path::new("temp/youtube-dl"); - let output = Command::new(full_path) - .arg("--format") - .arg("bestaudio/best") - .arg("--extract-audio") - .arg("--output") - .arg(&output_arg) - //.arg("--embed-thumbnail") - .arg(url) - .output()?; - + let output = run_youtube_dl(&output_arg, url)?; dbg!(&output); - if output.status.success() { - //TODO move to mpd music location - mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| c.rescan())?; - } else { - dbg!("HANDLE ERROR"); //update youtube downloader on fail (once if not recenty updated (check file meta)) + if !output.status.success() { + let since_last_updated = fs::metadata(YOUTUBE_DL_LOC).unwrap() + .created().unwrap() + .elapsed().unwrap_or(Duration::from_secs(0)); + + if since_last_updated > Duration::from_secs(60*60*24){ + return Err(Error::CouldNotDownloadSong); + } + + download_youtube_dl("https://yt-dl.org/downloads/latest/youtube-dl")?; + let output = run_youtube_dl(&output_arg, url)?; + dbg!(&output); + + if !output.status.success() { + return Err(Error::CouldNotDownloadSong); + } } + mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| c.rescan())?; Ok(()) } @@ -65,10 +118,14 @@ fn song_downloader(url_rx: crossbeam_channel::Receiver) { dbg!(&url); match download_song(&url) { Ok(_) => dbg!(), - Err(error) => error!("error during song download: {:?}", error), + Err(error) => { + error!("warn error during song download: {:?} \ + trying with updated youtube-dl", error); + }, }; }, - // return without url means YoutubeDownloader was dropped and we should stop + // Err means YoutubeDownloader + // was dropped and this thread should stop Err(_) => return, } } @@ -77,14 +134,14 @@ fn song_downloader(url_rx: crossbeam_channel::Receiver) { impl YoutubeDownloader { pub fn init() -> Result<(Self, thread::JoinHandle<()>), Error>{ - let dir_path = Path::new("temp"); - let full_path = Path::new("temp/youtube-dl"); - + let full_path = Path::new(YOUTUBE_DL_LOC); + let dir_path = Path::new(DIR); + if !full_path.exists() { if !dir_path.exists() { fs::create_dir(dir_path)?; } - download_file("https://yt-dl.org/downloads/latest/youtube-dl", full_path)?; + download_youtube_dl("https://yt-dl.org/downloads/latest/youtube-dl")?; } let (url_tx, url_rx) = crossbeam_channel::bounded(10); diff --git a/src/main.rs b/src/main.rs index a636e275..2ee56800 100755 --- a/src/main.rs +++ b/src/main.rs @@ -2,141 +2,62 @@ extern crate log; extern crate chrono; -use actix_web::{HttpServer,App, web}; -use actix_identity::{CookieIdentityPolicy, IdentityService}; -use actix_files as fs; - +use structopt::StructOpt; use sled; - -use std::sync::atomic::{AtomicUsize}; -use std::thread; - -use std::sync::{Arc, RwLock}; use std::io::stdin; -use std::collections::HashMap; mod controller; -use controller::Event; mod input; -use input::web_api; use input::web_api::server; -use server::{CheckLogin, PasswordDatabase, UserDatabase, index}; -use server::login::{login_get_and_check, login_page, logout}; +use input::web_api::server::PasswordDatabase; mod credentials; mod errors; -#[cfg(feature = "live_server")] -const SOCKETADDR: &'static str = "0.0.0.0:8080"; -#[cfg(not(feature = "live_server"))] -const SOCKETADDR: &'static str = "0.0.0.0:8070"; - -pub fn start_webserver(signed_cert: &str, private_key: &str, - passw_db: PasswordDatabase, - user_db: UserDatabase, - controller_tx: crossbeam_channel::Sender, - alarms: input::alarms::Alarms, - youtube_dl: input::YoutubeDownloader, - _mpd_status: input::MpdStatus, - ) -> actix_web::dev::Server { - - let tls_config = server::make_tls_config(signed_cert, private_key); - let cookie_key = server::make_random_cookie_key(); - - let free_session_ids = Arc::new(AtomicUsize::new(0)); - let sessions = Arc::new(RwLock::new(HashMap::new())); - let (tx, rx) = crossbeam_channel::unbounded(); - - thread::spawn(move || { - // Start data server actor in separate thread - let sys = actix_rt::System::new("http-server"); - - let web_server = HttpServer::new(move || { - // data the webservers functions have access to - let data = actix_web::web::Data::new(server::State { - controller_addr: controller_tx.clone(), - alarms: alarms.clone(), - passw_db: passw_db.clone(), - user_db: user_db.clone(), - youtube_dl: youtube_dl.clone(), - sessions: sessions.clone(), - free_session_ids: free_session_ids.clone(), - }); - - App::new() - .register_data(data) - .wrap(IdentityService::new( - CookieIdentityPolicy::new(&cookie_key[..]) - .domain("deviousd.duckdns.org") - .name("auth-cookie") - .path("/") - .secure(true), - )) - .service( - web::scope("/login") - .service(web::resource(r"/{path}") - .route(web::post().to(login_get_and_check)) - .route(web::get().to(login_page)) - )) - .service(web::resource("/commands/lamps/toggle").to(web_api::toggle)) - .service(web::resource("/commands/lamps/evening").to(web_api::evening)) - .service(web::resource("/commands/lamps/night").to(web_api::night)) - .service(web::resource("/commands/lamps/day").to(web_api::normal)) - .service(web::resource("/commands/lamps/dimmest").to(web_api::dimmest)) - .service(web::resource("/commands/lamps/dim").to(web_api::dim)) - - .service(web::resource("/commands/lightloop").to(web_api::lightloop)) - .service(web::scope("/") - .wrap(CheckLogin) - - .service(web::resource("").to(index)) - .service(web::resource("logout/").to(logout)) - .service(web::resource("add_song").to(web_api::add_song_from_url)) - .service(web::resource("set_alarm").to(web_api::set_alarm_unix_timestamp)) - .service(web::resource("list_alarms").to(web_api::list_alarms)) - //for all other urls we try to resolve to static files in the "web" dir - .service(fs::Files::new("", "./web/")) - ) - }) - .bind_rustls(SOCKETADDR, tls_config).unwrap() - //.bind("0.0.0.0:8080").unwrap() //without tcp use with debugging (note: https -> http, wss -> ws) - .shutdown_timeout(5) // shut down 5 seconds after getting the signal to shut down - .start(); - - let _ = tx.send(web_server); - let _ = sys.run(); - }); - - let web_handle = rx.recv().unwrap(); - web_handle +#[derive(StructOpt)] +#[structopt(name = "homeautomation")] +struct Opt { + // #[structopt(short = "p", long = "port", default_value = "8080")] + // port: u16, + + // #[structopt(short = "e", long = "external-port")] + // external_port: Option, + + // #[structopt(short = "t", long = "token")] + // token: String, + + // #[structopt(short = "d", long = "domain")] + // domain: String, + + #[structopt(short = "p", long = "admin-password")] + password: String, } fn main() { - - let config = sled::ConfigBuilder::new() - .path("database".to_owned()) + let opt = Opt::from_args(); + let db = sled::Config::default() //651ms + .path("database") .flush_every_ms(None) //do not flush to disk unless explicitly asked - .build(); - - let db = sled::Db::start(config).unwrap(); + .cache_capacity(1024 * 1024 * 32) //32 mb cache + .open().unwrap(); - let passw_db = PasswordDatabase::from_db(&db).unwrap(); - let user_db = UserDatabase::from_db(&db).unwrap(); + let mut passw_db = PasswordDatabase::from_db(&db).unwrap(); + passw_db.add_admin(&opt.password).unwrap(); let (controller_tx, controller_rx) = crossbeam_channel::unbounded(); - let _controller_thread = controller::start(controller_rx).unwrap(); let (alarms, _waker_thread) = input::alarms::Alarms::setup(controller_tx.clone(), db.clone()).unwrap(); let (youtube_dl, _downloader_thread) = input::YoutubeDownloader::init().unwrap(); let (mpd_status, _mpd_watcher_thread, updater_tx) = input::MpdStatus::start_updating().unwrap(); - //start the webserver - let web_handle = start_webserver("keys/cert.key", "keys/cert.cert" - ,passw_db.clone(), user_db.clone(), controller_tx.clone() - ,alarms.clone(), youtube_dl.clone(), mpd_status.clone()); + let _controller_thread = controller::start(controller_rx, mpd_status.clone()).unwrap(); - //TODO start the telegram server (for sending commands) + //start the webserver + let web_handle = server::start_webserver( + "keys/cert.key", "keys/cert.cert" + ,passw_db.clone(), controller_tx.clone() + ,alarms.clone(), youtube_dl.clone(), mpd_status); //start monitoring local sensors #[cfg(feature = "sensors_connected")] @@ -144,7 +65,7 @@ fn main() { #[cfg(feature = "sensors_connected")] input::buttons::start_monitoring(controller_tx.clone()); - println!("press: t to send test data, n: to add a new user, q to quit, a to add new dataset, u to add fields to a user"); + println!("press: q to quit"); loop { let mut input = String::new(); stdin().read_line(&mut input).unwrap(); From 3f4b6560cf9baf8aff5128acd02da24956dfce41 Mon Sep 17 00:00:00 2001 From: dskleingeld Date: Wed, 29 Jan 2020 01:28:34 +0100 Subject: [PATCH 020/687] adds groundwork for bot --- Cargo.lock | 205 ++++++++++++++++++++++++++++++- Cargo.toml | 5 +- src/errors.rs | 3 - src/input/alarms.rs | 7 +- src/input/bot/mod.rs | 206 ++++++++++++++++++++++++++++++++ src/input/mod.rs | 1 + src/input/web_api/server/mod.rs | 72 +++++++---- src/input/youtube_downloader.rs | 2 +- src/main.rs | 30 +++-- 9 files changed, 487 insertions(+), 44 deletions(-) create mode 100644 src/input/bot/mod.rs diff --git a/Cargo.lock b/Cargo.lock index e7273343..1d9e3dae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,16 +26,18 @@ dependencies = [ "pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "philipshue 0.3.2 (git+https://github.com/dskleingeld/philipshue)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "retry 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", "sled 0.30.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "sysfs_gpio 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "telegram-bot 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -420,6 +422,11 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "antidote" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "anyhow" version = "1.0.26" @@ -1203,6 +1210,15 @@ dependencies = [ "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "http-body" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "httparse" version = "1.3.4" @@ -1237,6 +1253,29 @@ dependencies = [ "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hyper" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hyper-rustls" version = "0.17.1" @@ -1265,6 +1304,18 @@ dependencies = [ "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hyper-tls" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "i2cdev" version = "0.4.2" @@ -1691,6 +1742,14 @@ dependencies = [ "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ordered-float" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "owning_ref" version = "0.4.0" @@ -2187,6 +2246,40 @@ dependencies = [ "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "reqwest" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-tls 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-futures 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "resolv-conf" version = "0.6.2" @@ -2290,6 +2383,11 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "scoped-tls" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "scopeguard" version = "0.3.3" @@ -2354,6 +2452,15 @@ dependencies = [ "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde-value" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serde_derive" version = "1.0.104" @@ -2583,6 +2690,32 @@ dependencies = [ "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "telegram-bot" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "telegram-bot-raw 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "telegram-bot-raw" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde-value 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tempfile" version = "3.1.0" @@ -2667,6 +2800,7 @@ dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2693,6 +2827,24 @@ dependencies = [ "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-core" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-current-thread" version = "0.1.6" @@ -2838,6 +2990,15 @@ dependencies = [ "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-udp" version = "0.1.5" @@ -2890,6 +3051,11 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tower-service" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "trust-dns-proto" version = "0.5.0" @@ -3139,6 +3305,15 @@ dependencies = [ "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "wasi" version = "0.7.0" @@ -3150,6 +3325,8 @@ version = "0.2.58" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-macro 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3167,6 +3344,17 @@ dependencies = [ "wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.58" @@ -3349,6 +3537,7 @@ dependencies = [ "checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" "checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" "checksum arc-swap 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a1eca3195b729bbd64e292ef2f5fff6b1c28504fed762ce2b1013dde4d8e92" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" @@ -3441,10 +3630,13 @@ dependencies = [ "checksum http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d7e06e336150b178206af098a055e3621e8336027e2b4d126bda0bc64824baaf" "checksum http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b708cc7f06493459026f53b9a61a7a121a5d1ec6238dee58ea4941132b30156b" "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" +"checksum http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)" = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" +"checksum hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8bf49cfb32edee45d890537d9057d1b02ed55f53b7b6a30bae83a38c9231749e" "checksum hyper-rustls 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "719d85c7df4a7f309a77d145340a063ea929dcb2e025bae46a80345cffec2952" "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" +"checksum hyper-tls 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3adcd308402b9553630734e9c36b77a7e48b3821251ca2493e8cd596763aafaa" "checksum i2cdev 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db7cf03500911132bacb44430234aa58dba843bb6aa2820154e5abb696e3e3d9" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" @@ -3492,6 +3684,7 @@ dependencies = [ "checksum openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2f372b2b53ce10fb823a337aaa674e3a7d072b957c6264d0f4ff0bd86e657449" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-sys 0.9.52 (registry+https://github.com/rust-lang/crates.io-index)" = "c977d08e1312e2f7e4b86f9ebaa0ed3b19d1daff75fae88bbb88108afbd801fc" +"checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74a701d13e2f3ee32a50be43321da8f712cf1e6e9ff0e2be66ab7f5c6598a16a" "checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" @@ -3542,6 +3735,7 @@ dependencies = [ "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +"checksum reqwest 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0e798e19e258bf6c30a304622e3e9ac820e483b06a1857a026e1f109b113fe4" "checksum reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab" "checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" "checksum retry 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ac83b31b3831aa4b07608db4170f6555ab12942197037c38570dc4c5ba5028" @@ -3555,6 +3749,7 @@ dependencies = [ "checksum rustversion 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bba175698996010c4f6dce5e7f173b6eb781fce25d2cfc45e27091ce0b79f6" "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" "checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" +"checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" @@ -3564,6 +3759,7 @@ dependencies = [ "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" +"checksum serde-value 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7a663f873dedc4eac1a559d4c6bc0d0b2c34dc5ac4702e105014b8281489e44f" "checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" "checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" @@ -3590,6 +3786,8 @@ dependencies = [ "checksum syn-mid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd3937748a7eccff61ba5b90af1a20dbf610858923a9192ea0ecb0cb77db1d0" "checksum synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" "checksum sysfs_gpio 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "24961a55846623d8e4f6cec38718945116fed8d6970336a7110710a07aa9b5d1" +"checksum telegram-bot 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "225d5eca220fcf23ad25b269991cdc8f8d421d97634c7f9e10b4c5dcdaa913b6" +"checksum telegram-bot-raw 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65578f718dadd17347cd60d45609a7e1d57a52b459797957002b922349ee9744" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" @@ -3599,6 +3797,7 @@ dependencies = [ "checksum tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8fdd17989496f49cdc57978c96f0c9fe5e4a58a8bddc6813c449a4624f6a030b" "checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" +"checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" "checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" "checksum tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f27ee0e6db01c5f0b2973824547ce7e637b2ed79b891a9677b0de9bd532b6ac" "checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" @@ -3611,10 +3810,12 @@ dependencies = [ "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" "checksum tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd2c6a3885302581f4401c82af70d792bb9df1700e7437b0aeb4ada94d5388c" "checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" +"checksum tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7bde02a3a5291395f59b06ec6945a3077602fac2b07eeeaf0dee2122f3619828" "checksum tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f02298505547f73e60f568359ef0d016d5acd6e830ab9bc7c4a5b3403440121b" "checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" "checksum tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" "checksum tower-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b32f72af77f1bfe3d3d4da8516a238ebe7039b51dd8637a09841ac7f16d2c987" +"checksum tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" "checksum trust-dns-proto 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2a7f3a2ab8a919f5eca52a468866a67ed7d3efa265d48a652a9a3452272b413f" "checksum trust-dns-proto 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0838272e89f1c693b4df38dc353412e389cf548ceed6f9fd1af5a8d6e0e7cf74" "checksum trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "09144f0992b0870fa8d2972cc069cbf1e3c0fda64d1f3d45c4d68d0e0b52ad4e" @@ -3641,9 +3842,11 @@ dependencies = [ "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" +"checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" "checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" "checksum wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "5205e9afdf42282b192e2310a5b463a6d1c1d774e30dc3c791ac37ab42d2616c" "checksum wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "11cdb95816290b525b32587d76419facd99662a07e59d3cdb560488a819d9a45" +"checksum wasm-bindgen-futures 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8bbdd49e3e28b40dec6a9ba8d17798245ce32b019513a845369c641b275135d9" "checksum wasm-bindgen-macro 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "574094772ce6921576fb6f2e3f7497b8a76273b6db092be18fc48a082de09dc3" "checksum wasm-bindgen-macro-support 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "e85031354f25eaebe78bb7db1c3d86140312a911a106b2e29f9cc440ce3e7668" "checksum wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e7e61fc929f4c0dddb748b102ebf9f632e2b8d739f2016542b4de2965a9601" diff --git a/Cargo.toml b/Cargo.toml index bc8c2c2e..41519bb2 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,9 +54,12 @@ crossbeam-channel = "0.3" sled = "0.30" pagecache = "0.17.0" -reqwest = "0.9.15" +reqwest = {version = "0.10", features = ["blocking"]} mpd = "0.0.12" dirs = "2.0.1" rand = "0.6" retry = "0.5.1" + +telegram-bot = "0.6" +serde_json = "1.0" \ No newline at end of file diff --git a/src/errors.rs b/src/errors.rs index 4e3830f3..80e819b8 100755 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,6 +1,3 @@ -//use std::fmt; -use std::sync::RwLock; - use crate::input::youtube_downloader; #[derive(Debug)] diff --git a/src/input/alarms.rs b/src/input/alarms.rs index 5d0126a2..20fbdf60 100755 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -126,7 +126,8 @@ impl AlarmList { //if there is already an alarm schedualed, postpone this one until there is a spot free //self.db.cas(&[1], None as Option<&[u8]>, Some(&[10]) //TODO check how this works and expand sled documentation for fail cases - while let Err(_old_event) = self.db.cas(×tamp_array, None as Option<&[u8]>, Some(&[0]))? {//cas unique creation + while let Err(_old_event) = self + .db.compare_and_swap(×tamp_array, None as Option<&[u8]>, Some(&[0]))? {//cas unique creation timestamp -= 1; timestamp_array = timestamp.to_be_bytes(); } @@ -134,7 +135,7 @@ impl AlarmList { } pub fn remove_alarm(&self, at_time: DateTime) -> Result<(), Error> { let timestamp = at_time.timestamp() as u64; - self.db.del(timestamp.to_be_bytes())?; + self.db.remove(timestamp.to_be_bytes())?; Ok(()) } @@ -144,7 +145,7 @@ impl AlarmList { let timestamp_array = timestamp.to_be_bytes(); for old_alarm in self.db.range(..timestamp_array).keys() { if let Ok(old_alarm) = old_alarm { - self.db.del(old_alarm)?; + self.db.remove(old_alarm)?; } } Ok(()) diff --git a/src/input/bot/mod.rs b/src/input/bot/mod.rs new file mode 100644 index 00000000..3db1d5fe --- /dev/null +++ b/src/input/bot/mod.rs @@ -0,0 +1,206 @@ +use actix_web::web::{HttpResponse, Data, Bytes}; +use actix_web::http::{StatusCode}; + +use reqwest; +use log::{warn, info ,error}; +use serde_json; + +use telegram_bot::types::update::Update; +use telegram_bot::types::update::UpdateKind; +use telegram_bot::types::message::MessageKind; +use telegram_bot::types::refs::{ChatId, UserId}; + +use crate::input::web_api::server::{State}; + +#[derive(Debug)] +pub enum Error{ + HttpClientError(reqwest::Error), + CouldNotSetWebhook, + InvalidServerResponse(reqwest::Response), + InvalidServerResponseBlocking(reqwest::blocking::Response), + UnhandledUpdateKind, + UnhandledMessageKind, + UnknownCommand(String) +} + +impl From for Error { + fn from(error: reqwest::Error) -> Self { + Error::HttpClientError(error) + } +} + +fn to_string_and_ids(update: Update) -> Result<(String, ChatId, UserId),Error>{ + if let UpdateKind::Message(message) = update.kind { + let chat_id = message.chat.id(); + let user_id = message.from.id; + if let MessageKind::Text{data, entities:_} = message.kind { + return Ok((data, chat_id, user_id)); + } else { + warn!("unhandled message kind"); + return Err(Error::UnhandledUpdateKind); + } + } else { + warn!("unhandled update from telegram: {:?}", update); + return Err(Error::UnhandledMessageKind); + } +} + +async fn handle_command(mut text: String, chat_id: ChatId, user_id: UserId, + state: &State) -> Result<(), Error>{ + + let token = &state.bot_token; + + let split = text.find(char::is_whitespace); + let mut command = text; + let args = command.split_off(split.unwrap_or(command.len())); + match command.as_str() { + "/test" => { + send_text_reply(chat_id, token, "hi").await?; + return Ok(()); + } + /*"/help" => { + help::send(chat_id, &user, token).await?; + break; + } + "/plotables" => { + plotables::send(chat_id, &user, state, token).await?; + break; + } + "/show" => { + show::send(chat_id, state, token, args, &user).await?; + break; + } + "/keyboard" => { + keyboard::show(chat_id, token, user).await?; + break; + } + "/keyboard_add" => { + keyboard::add_button(chat_id, state, token, args, user).await?; + break; + } + "/keyboard_remove" => { + keyboard::remove_button(chat_id, state, token, args, user).await?; + break; + } + "/alarm" => { + alarms::handle(chat_id, token, args, user, state).await?; + break; + } + "/alias" => { + alias::send(chat_id, state, token, args, user).await?; + break; + }*/ + &_ => {} + } + + warn!("no known command or alias: {:?}", &command); + return Err(Error::UnknownCommand(command)); +} + +const INT_ERR_TEXT: &str = "apologies, an internal error happend this has been reported and will be fixed as soon as possible"; +const UNHANDLED: &str = "sorry I can not understand your input"; +async fn handle_error(error: Error, chat_id: ChatId, user_id: UserId, token: &str) { + let error_message = match error { + Error::UnknownCommand(input) => + format!("Unknown command: {}", input), + Error::HttpClientError(err) => { + error!("Internal error in http client: {}", err); + String::from(INT_ERR_TEXT)}, + Error::InvalidServerResponse(resp) => { + error!("Incorrect bot api response {:?}", resp); + String::from(INT_ERR_TEXT)}, + Error::UnhandledMessageKind => { + String::from(UNHANDLED)} + Error::UnhandledUpdateKind => { + String::from(UNHANDLED)} + Error::CouldNotSetWebhook => unreachable!(), + Error::InvalidServerResponseBlocking(_) => unreachable!(), + }; + if let Err(error) = send_text_reply(chat_id, token, error_message).await{ + error!("Could not send text reply to user: {:?}", error); + } +} + +async fn handle(update: Update, state: State){ + let token = &state.bot_token; + if let Ok((text, chat_id, user_id)) = to_string_and_ids(update){ + if let Err(error) = handle_command(text, chat_id, user_id, &state).await{ + handle_error(error, chat_id, user_id, token).await; + } + } +} + +pub async fn handle_webhook(state: Data, raw_update: Bytes) + -> HttpResponse { + + let update: Update = serde_json::from_slice(&raw_update.to_vec()).unwrap(); + let state_cpy = state.get_ref().clone(); + handle(update, state_cpy).await; + + HttpResponse::Ok() + .status(StatusCode::OK) + .body("{}") +} + +pub async fn send_text_reply>(chat_id: ChatId, token: &str, text: T) + -> Result<(), Error>{//add as arg generic ToChatRef (should get from Update) + //TODO create a SendMessage, serialise it (use member function serialize) + //then use the HttpRequest fields, (url, method, and body) to send to telegram + let url = format!("https://api.telegram.org/bot{}/sendMessage", token); + let form = reqwest::multipart::Form::new() + .text("chat_id", chat_id.to_string()) + .text("text", text.into()); + + let client = reqwest::Client::new(); + let resp = client.post(&url) + .multipart(form).send().await?; + //https://stackoverflow.com/questions/57540455/error-blockingclientinfuturecontext-when-trying-to-make-a-request-from-within + + if resp.status() != reqwest::StatusCode::OK { + Err(Error::InvalidServerResponse(resp)) + } else { + info!("send message"); + Ok(()) + } +} + +pub fn send_text_reply_blocking>(chat_id: ChatId, token: &str, text: T) + -> Result<(), Error>{//add as arg generic ToChatRef (should get from Update) + //TODO create a SendMessage, serialise it (use member function serialize) + //then use the HttpRequest fields, (url, method, and body) to send to telegram + let url = format!("https://api.telegram.org/bot{}/sendMessage", token); + let form = reqwest::blocking::multipart::Form::new() + .text("chat_id", chat_id.to_string()) + .text("text", text.into()); + + let client = reqwest::blocking::Client::new(); + let resp = client.post(&url) + .multipart(form).send()?; + //https://stackoverflow.com/questions/57540455/error-blockingclientinfuturecontext-when-trying-to-make-a-request-from-within + + if resp.status() != reqwest::StatusCode::OK { + Err(Error::InvalidServerResponseBlocking(resp)) + } else { + info!("send message"); + Ok(()) + } +} + +pub async fn set_webhook(domain: &str, token: &str, port: u16) -> Result<(), Error> { + let url = format!("https://api.telegram.org/bot{}/setWebhook", token); + let webhook_url = format!("{}:{}/{}",domain, port, token); + dbg!(&webhook_url); + + let params = [("url", &webhook_url)]; + let client = reqwest::Client::new(); + let res = client.post(url.as_str()) + .form(¶ms) + .send().await?; + + if res.status() != reqwest::StatusCode::OK { + Err(Error::CouldNotSetWebhook) + } else { + info!("set webhook to: {}", webhook_url); + Ok(()) + } +} \ No newline at end of file diff --git a/src/input/mod.rs b/src/input/mod.rs index 88065909..359408ab 100755 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -3,6 +3,7 @@ pub mod sensors; #[cfg(feature = "sensors_connected")] pub mod buttons; +pub mod bot; pub mod web_api; pub mod alarms; pub mod youtube_downloader; diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index 3b10c817..6c375b0d 100755 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -16,9 +16,11 @@ use std::io::BufReader; use std::fs::File; use crate::input; +use crate::input::bot; use crate::input::web_api; use crate::controller::Event; + pub mod database; pub mod login_redirect; pub mod login; @@ -34,6 +36,7 @@ const SOCKETADDR: &'static str = "0.0.0.0:8070"; pub struct Session {}//TODO deprecate +#[derive(Clone)] pub struct State { pub controller_addr: crossbeam_channel::Sender, pub alarms: input::alarms::Alarms, @@ -41,6 +44,29 @@ pub struct State { pub sessions: Arc> >>> , pub free_session_ids: Arc, pub youtube_dl: input::YoutubeDownloader, + pub bot_token: String, +} + +impl State { + pub fn new(passw_db: PasswordDatabase, + controller_tx: crossbeam_channel::Sender, + alarms: input::alarms::Alarms, + youtube_dl: input::YoutubeDownloader, + bot_token: String) -> Self { + + let free_session_ids = Arc::new(AtomicUsize::new(0)); + let sessions = Arc::new(RwLock::new(HashMap::new())); + + State { + controller_addr: controller_tx, + alarms: alarms, + passw_db: passw_db, + youtube_dl: youtube_dl, + sessions: sessions, + free_session_ids: free_session_ids, + bot_token, + } + } } pub fn make_tls_config>(signed_cert_path: P, private_key_path: P) -> rustls::ServerConfig{ @@ -60,32 +86,17 @@ pub async fn index(_req: HttpRequest) -> impl Responder { "Hello world!" } -pub fn start_webserver(signed_cert: &str, private_key: &str, - passw_db: PasswordDatabase, - controller_tx: crossbeam_channel::Sender, - alarms: input::alarms::Alarms, - youtube_dl: input::YoutubeDownloader, - _mpd_status: input::MpdStatus, - ) -> actix_web::dev::Server { +pub fn start_webserver(signed_cert: &str, private_key: &str, state: State) + -> actix_web::dev::Server { let tls_config = make_tls_config(signed_cert, private_key); let cookie_key = make_random_cookie_key(); - - let free_session_ids = Arc::new(AtomicUsize::new(0)); - let sessions = Arc::new(RwLock::new(HashMap::new())); let (tx, rx) = crossbeam_channel::unbounded(); thread::spawn(move || { let web_server = HttpServer::new(move || { // data the webservers functions have access to - let data = actix_web::web::Data::new(State { - controller_addr: controller_tx.clone(), - alarms: alarms.clone(), - passw_db: passw_db.clone(), - youtube_dl: youtube_dl.clone(), - sessions: sessions.clone(), - free_session_ids: free_session_ids.clone(), - }); + let data = actix_web::web::Data::new(state.clone()); App::new() .app_data(data) @@ -102,14 +113,23 @@ pub fn start_webserver(signed_cert: &str, private_key: &str, .route(web::post().to(login_get_and_check)) .route(web::get().to(login_page)) )) - .service(web::resource("/commands/lamps/toggle").to(web_api::toggle)) - .service(web::resource("/commands/lamps/evening").to(web_api::evening)) - .service(web::resource("/commands/lamps/night").to(web_api::night)) - .service(web::resource("/commands/lamps/day").to(web_api::normal)) - .service(web::resource("/commands/lamps/dimmest").to(web_api::dimmest)) - .service(web::resource("/commands/lamps/dim").to(web_api::dim)) - .service(web::resource("/commands/lightloop").to(web_api::lightloop)) - + .service(web::resource("/commands/lamps/toggle") + .to(web_api::toggle)) + .service(web::resource("/commands/lamps/evening") + .to(web_api::evening)) + .service(web::resource("/commands/lamps/night") + .to(web_api::night)) + .service(web::resource("/commands/lamps/day") + .to(web_api::normal)) + .service(web::resource("/commands/lamps/dimmest") + .to(web_api::dimmest)) + .service(web::resource("/commands/lamps/dim") + .to(web_api::dim)) + .service(web::resource("/commands/lightloop") + .to(web_api::lightloop)) + .service(web::resource(&format!("/{}", &state.bot_token)) + .to(bot::handle_webhook)) + .service(web::scope("/") .wrap(CheckLogin{}) diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index 5a51a11c..01ff3d0b 100755 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -44,7 +44,7 @@ fn download_youtube_dl(url: U) -> Result<(), Error> { .mode(0o770) .open(YOUTUBE_DL_LOC)?; - let mut response = reqwest::get(url)?; + let mut response = reqwest::blocking::get(url)?; copy(&mut response, &mut dest)?; Ok(()) diff --git a/src/main.rs b/src/main.rs index 2ee56800..d7f24fa5 100755 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ mod controller; mod input; use input::web_api::server; -use input::web_api::server::PasswordDatabase; +use input::web_api::server::{PasswordDatabase, State}; mod credentials; mod errors; @@ -24,8 +24,8 @@ struct Opt { // #[structopt(short = "e", long = "external-port")] // external_port: Option, - // #[structopt(short = "t", long = "token")] - // token: String, + #[structopt(short = "t", long = "token")] + token: String, // #[structopt(short = "d", long = "domain")] // domain: String, @@ -47,17 +47,29 @@ fn main() { let (controller_tx, controller_rx) = crossbeam_channel::unbounded(); - let (alarms, _waker_thread) = input::alarms::Alarms::setup(controller_tx.clone(), db.clone()).unwrap(); + let (alarms, _waker_thread) = input::alarms::Alarms::setup( + controller_tx.clone(), + db.clone()).unwrap(); let (youtube_dl, _downloader_thread) = input::YoutubeDownloader::init().unwrap(); - let (mpd_status, _mpd_watcher_thread, updater_tx) = input::MpdStatus::start_updating().unwrap(); + let (mpd_status, _mpd_watcher_thread, updater_tx) = + input::MpdStatus::start_updating() + .unwrap(); - let _controller_thread = controller::start(controller_rx, mpd_status.clone()).unwrap(); + let _controller_thread = controller::start( + controller_rx, + mpd_status.clone()).unwrap(); + + let state = State::new( + passw_db, + controller_tx, + alarms, + youtube_dl, + opt.token.clone()); //start the webserver let web_handle = server::start_webserver( - "keys/cert.key", "keys/cert.cert" - ,passw_db.clone(), controller_tx.clone() - ,alarms.clone(), youtube_dl.clone(), mpd_status); + "keys/cert.key", "keys/cert.cert", state); + //start monitoring local sensors #[cfg(feature = "sensors_connected")] From 5340b54498488bf97f5fa90e7c6e1ad39137b848 Mon Sep 17 00:00:00 2001 From: dskleingeld Date: Wed, 29 Jan 2020 01:53:06 +0100 Subject: [PATCH 021/687] added webhook for telegram bot, made port and token arguments --- src/input/alarms.rs | 1 - src/input/web_api/server/mod.rs | 13 +++---------- src/main.rs | 23 +++++++++++++++-------- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/input/alarms.rs b/src/input/alarms.rs index 20fbdf60..554f0c83 100755 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -1,5 +1,4 @@ use crossbeam_channel; -use std::sync::{Arc}; use std::thread; use chrono::{DateTime, NaiveDateTime, Utc}; diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index 6c375b0d..4eae849a 100755 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -1,4 +1,3 @@ -use chrono::{DateTime, Utc}; use rustls::{NoClientAuth, ServerConfig}; use rustls::internal::pemfile::{certs, pkcs8_private_keys}; @@ -20,7 +19,6 @@ use crate::input::bot; use crate::input::web_api; use crate::controller::Event; - pub mod database; pub mod login_redirect; pub mod login; @@ -29,11 +27,6 @@ pub use database::PasswordDatabase; pub use login::{make_random_cookie_key, login_page, login_get_and_check, logout}; pub use login_redirect::CheckLogin; -#[cfg(feature = "live_server")] -const SOCKETADDR: &'static str = "0.0.0.0:8080"; -#[cfg(not(feature = "live_server"))] -const SOCKETADDR: &'static str = "0.0.0.0:8070"; - pub struct Session {}//TODO deprecate #[derive(Clone)] @@ -86,8 +79,8 @@ pub async fn index(_req: HttpRequest) -> impl Responder { "Hello world!" } -pub fn start_webserver(signed_cert: &str, private_key: &str, state: State) - -> actix_web::dev::Server { +pub fn start_webserver(signed_cert: &str, private_key: &str, + state: State, port: u16, domain: &str) -> actix_web::dev::Server { let tls_config = make_tls_config(signed_cert, private_key); let cookie_key = make_random_cookie_key(); @@ -142,7 +135,7 @@ pub fn start_webserver(signed_cert: &str, private_key: &str, state: State) .service(fs::Files::new("", "./web/")) ) }) - .bind_rustls(SOCKETADDR, tls_config).unwrap() + .bind_rustls(&format!("0.0.0.0:{}", port), tls_config).unwrap() //.bind("0.0.0.0:8080").unwrap() //without tcp use with debugging (note: https -> http, wss -> ws) .shutdown_timeout(5) // shut down 5 seconds after getting the signal to shut down .run(); diff --git a/src/main.rs b/src/main.rs index d7f24fa5..e6527639 100755 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ mod controller; mod input; use input::web_api::server; use input::web_api::server::{PasswordDatabase, State}; +use input::bot; mod credentials; mod errors; @@ -18,24 +19,26 @@ mod errors; #[derive(StructOpt)] #[structopt(name = "homeautomation")] struct Opt { - // #[structopt(short = "p", long = "port", default_value = "8080")] - // port: u16, + #[structopt(short = "p", long = "port", default_value = "8080")] + port: u16, - // #[structopt(short = "e", long = "external-port")] - // external_port: Option, + #[structopt(short = "e", long = "external-port")] + external_port: Option, #[structopt(short = "t", long = "token")] token: String, - // #[structopt(short = "d", long = "domain")] - // domain: String, + #[structopt(short = "d", long = "domain")] + domain: String, #[structopt(short = "p", long = "admin-password")] password: String, } -fn main() { +#[actix_rt::main] +async fn main() { let opt = Opt::from_args(); + let db = sled::Config::default() //651ms .path("database") .flush_every_ms(None) //do not flush to disk unless explicitly asked @@ -68,8 +71,12 @@ fn main() { //start the webserver let web_handle = server::start_webserver( - "keys/cert.key", "keys/cert.cert", state); + "keys/cert.key", "keys/cert.cert", state, opt.port, &opt.domain); + + bot::set_webhook( + &opt.domain, &opt.token, + opt.external_port.unwrap_or_else(|| opt.port)).await.unwrap(); //start monitoring local sensors #[cfg(feature = "sensors_connected")] From dcad0f767623f49445005334725ad765116deafe Mon Sep 17 00:00:00 2001 From: dskleingeld Date: Wed, 29 Jan 2020 01:57:26 +0100 Subject: [PATCH 022/687] various fixes --- src/input/bot/mod.rs | 10 +++++----- src/input/web_api/server/mod.rs | 6 +++--- src/main.rs | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/input/bot/mod.rs b/src/input/bot/mod.rs index 3db1d5fe..3cc40405 100644 --- a/src/input/bot/mod.rs +++ b/src/input/bot/mod.rs @@ -45,7 +45,7 @@ fn to_string_and_ids(update: Update) -> Result<(String, ChatId, UserId),Error>{ } } -async fn handle_command(mut text: String, chat_id: ChatId, user_id: UserId, +async fn handle_command(mut text: String, chat_id: ChatId, state: &State) -> Result<(), Error>{ let token = &state.bot_token; @@ -99,7 +99,7 @@ async fn handle_command(mut text: String, chat_id: ChatId, user_id: UserId, const INT_ERR_TEXT: &str = "apologies, an internal error happend this has been reported and will be fixed as soon as possible"; const UNHANDLED: &str = "sorry I can not understand your input"; -async fn handle_error(error: Error, chat_id: ChatId, user_id: UserId, token: &str) { +async fn handle_error(error: Error, chat_id: ChatId, token: &str) { let error_message = match error { Error::UnknownCommand(input) => format!("Unknown command: {}", input), @@ -123,9 +123,9 @@ async fn handle_error(error: Error, chat_id: ChatId, user_id: UserId, token: &st async fn handle(update: Update, state: State){ let token = &state.bot_token; - if let Ok((text, chat_id, user_id)) = to_string_and_ids(update){ - if let Err(error) = handle_command(text, chat_id, user_id, &state).await{ - handle_error(error, chat_id, user_id, token).await; + if let Ok((text, chat_id, _user_id)) = to_string_and_ids(update){ + if let Err(error) = handle_command(text, chat_id, &state).await{ + handle_error(error, chat_id, token).await; } } } diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index 4eae849a..218312f1 100755 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -80,7 +80,7 @@ pub async fn index(_req: HttpRequest) -> impl Responder { } pub fn start_webserver(signed_cert: &str, private_key: &str, - state: State, port: u16, domain: &str) -> actix_web::dev::Server { + state: State, port: u16, domain: String) -> actix_web::dev::Server { let tls_config = make_tls_config(signed_cert, private_key); let cookie_key = make_random_cookie_key(); @@ -95,7 +95,7 @@ pub fn start_webserver(signed_cert: &str, private_key: &str, .app_data(data) .wrap(IdentityService::new( CookieIdentityPolicy::new(&cookie_key[..]) - .domain("deviousd.duckdns.org") + .domain(&domain) .name("auth-cookie") .path("/") .secure(true), @@ -142,7 +142,7 @@ pub fn start_webserver(signed_cert: &str, private_key: &str, let _ = tx.send(web_server.clone()); let mut rt = Runtime::new().unwrap(); - rt.block_on(web_server); + rt.block_on(web_server).unwrap(); }); let web_handle = rx.recv().unwrap(); diff --git a/src/main.rs b/src/main.rs index e6527639..00977777 100755 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,6 @@ use input::web_api::server; use input::web_api::server::{PasswordDatabase, State}; use input::bot; -mod credentials; mod errors; #[derive(StructOpt)] @@ -71,7 +70,8 @@ async fn main() { //start the webserver let web_handle = server::start_webserver( - "keys/cert.key", "keys/cert.cert", state, opt.port, &opt.domain); + "keys/cert.key", "keys/cert.cert", + state, opt.port, opt.domain.clone()); bot::set_webhook( @@ -95,6 +95,6 @@ async fn main() { }; } println!("shutting down"); - web_handle.stop(true); + web_handle.stop(true).await; input::MpdStatus::stop_updating(updater_tx); } From b5f303fe3f2179648bd1ecb4a1094840fe88fa86 Mon Sep 17 00:00:00 2001 From: dskleingeld Date: Fri, 7 Feb 2020 01:01:19 +0100 Subject: [PATCH 023/687] port actix2.0 + sub dependencies and move from sysgpio to gpio_cdev --- src/controller/commands.rs | 3 + src/controller/mod.rs | 1 + src/errors.rs | 7 +- src/input/bot/mod.rs | 40 ++------ src/input/buttons.rs | 164 +++++++++++++++++++++----------- src/input/sensors/mod.rs | 48 ++++++---- src/input/web_api/mod.rs | 2 +- src/input/web_api/server/mod.rs | 8 +- src/main.rs | 17 +++- 9 files changed, 171 insertions(+), 119 deletions(-) diff --git a/src/controller/commands.rs b/src/controller/commands.rs index ce42dc91..da4ccc20 100755 --- a/src/controller/commands.rs +++ b/src/controller/commands.rs @@ -4,6 +4,8 @@ use crate::controller::system::mpd_control; #[derive(Copy, Clone)] pub enum Command { + None, + LampsToggle, LampsDim, LampsDimmest, @@ -47,6 +49,7 @@ pub fn handle_cmd(cmd: Command, state: ActiveState, mods: &mut Modifications, sy Command::MpdIncreaseVolume => {mpd_control::decrease_volume(&mut sys.mpd).unwrap(); mods.mpd = true }, Command::Test => { warn!("The Test command was just send")}, + Command::None => { error!("None command was issued, this should not happen")}, } state } diff --git a/src/controller/mod.rs b/src/controller/mod.rs index d7825d99..8c229e6f 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -19,6 +19,7 @@ use crate::input::sensors::SensorValue; use crate::input::mpd_status::MpdStatus; use crate::errors::Error; +#[derive(Clone, Copy)] pub enum Event { Update, Alarm, diff --git a/src/errors.rs b/src/errors.rs index 80e819b8..3e816e96 100755 --- a/src/errors.rs +++ b/src/errors.rs @@ -3,7 +3,8 @@ use crate::input::youtube_downloader; #[derive(Debug)] pub enum Error { IO(std::io::Error), - GPIO(sysfs_gpio::Error), + GPIO(gpio_cdev::errors::Error), + GPIONotFound, YamlParsing(serde_yaml::Error), Channel(crossbeam_channel::SendError<()>), DataBase(sled::Error), @@ -32,8 +33,8 @@ impl From for Error { } } -impl From for Error { - fn from(error: sysfs_gpio::Error) -> Self { +impl From for Error { + fn from(error: gpio_cdev::errors::Error) -> Self { Error::GPIO(error) } } diff --git a/src/input/bot/mod.rs b/src/input/bot/mod.rs index 3cc40405..da8cca18 100644 --- a/src/input/bot/mod.rs +++ b/src/input/bot/mod.rs @@ -45,7 +45,7 @@ fn to_string_and_ids(update: Update) -> Result<(String, ChatId, UserId),Error>{ } } -async fn handle_command(mut text: String, chat_id: ChatId, +async fn handle_command(text: String, chat_id: ChatId, state: &State) -> Result<(), Error>{ let token = &state.bot_token; @@ -58,39 +58,9 @@ async fn handle_command(mut text: String, chat_id: ChatId, send_text_reply(chat_id, token, "hi").await?; return Ok(()); } - /*"/help" => { - help::send(chat_id, &user, token).await?; - break; - } - "/plotables" => { - plotables::send(chat_id, &user, state, token).await?; - break; - } - "/show" => { - show::send(chat_id, state, token, args, &user).await?; - break; - } - "/keyboard" => { - keyboard::show(chat_id, token, user).await?; - break; - } - "/keyboard_add" => { - keyboard::add_button(chat_id, state, token, args, user).await?; - break; - } - "/keyboard_remove" => { - keyboard::remove_button(chat_id, state, token, args, user).await?; - break; - } - "/alarm" => { - alarms::handle(chat_id, token, args, user, state).await?; - break; - } - "/alias" => { - alias::send(chat_id, state, token, args, user).await?; - break; - }*/ - &_ => {} + &_ => { + + } } warn!("no known command or alias: {:?}", &command); @@ -186,6 +156,7 @@ pub fn send_text_reply_blocking>(chat_id: ChatId, token: &str, t } } +//Ports currently supported for Webhooks: 443, 80, 88, 8443. pub async fn set_webhook(domain: &str, token: &str, port: u16) -> Result<(), Error> { let url = format!("https://api.telegram.org/bot{}/setWebhook", token); let webhook_url = format!("{}:{}/{}",domain, port, token); @@ -197,6 +168,7 @@ pub async fn set_webhook(domain: &str, token: &str, port: u16) -> Result<(), Err .form(¶ms) .send().await?; + dbg!(&res); if res.status() != reqwest::StatusCode::OK { Err(Error::CouldNotSetWebhook) } else { diff --git a/src/input/buttons.rs b/src/input/buttons.rs index 07507f6e..c407ec26 100755 --- a/src/input/buttons.rs +++ b/src/input/buttons.rs @@ -1,72 +1,128 @@ -extern crate sysfs_gpio; -extern crate futures; -extern crate tokio; +use gpio_cdev::{Chip, LineRequestFlags, EventRequestFlags, LineEventHandle}; +use nix::poll::{PollFd, PollFlags, poll}; +use std::os::unix::io::{AsRawFd, RawFd}; +use smallvec::{SmallVec, smallvec}; -use futures::{Future, lazy, Stream}; -use sysfs_gpio::{Direction, Edge, Pin}; use std::thread; use std::time::{Duration, Instant}; use crossbeam_channel; +use crate::errors::Error; use crate::controller::{Command, Event}; // when pressing 22, 24 is often activated // 23 works perfectly // 24 also works perfectly +const MILLIS: u64 = 1_000_000; //nano to milli +const N_LINES: usize = 54; -fn stream(mut pin_numb_command_pairs: Vec<(u64, Command)>, tx: crossbeam_channel::Sender) -> sysfs_gpio::Result<()> { - // NOTE: this currently runs forever and as such if - // the app is stopped (Ctrl-C), no cleanup will happen - // and the GPIO will be left exported. Not much - // can be done about this as Rust signal handling isn't - // really present at the moment. Revisit later. - let task = lazy(move || { - for (pin_numb, command) in pin_numb_command_pairs.drain(..) { - let mut last_press = Instant::now(); - let pin = Pin::new(pin_numb); - pin.export().expect("could not export pin"); - pin.set_direction(Direction::In).expect("could not set direction for pin"); - pin.set_edge(Edge::RisingEdge).expect("could not set interrupt to rising edge for pin"); - let tx = tx.clone(); - tokio::spawn(pin.get_value_stream().unwrap() - .for_each(move |val| { //TODO refactor - if val == 1 { - if last_press.elapsed() > Duration::from_millis(50) { - last_press = Instant::now(); - dbg!(pin_numb); - dbg!(val); - tx.send(Event::Command(command.clone())).unwrap(); - } +fn detect_and_handle(chip: &mut Chip, offset_to_command: [Event; 54], + tx: crossbeam_channel::Sender) -> Result<(), Error>{ + + let offsets: [u32; 10] = [27,22,18, 23,24,26,17, 16,12,13]; + let (mut evt_handles, mut pollables) = configure_watching(chip, &offsets)?; + dbg!(); + thread::spawn(move || { + loop{ + let mut last_high = [0u64; N_LINES]; + let mut last_state = [0u8; N_LINES]; + if poll(&mut pollables, -1).unwrap() !=0 { + let key_presses = process_event(&pollables, + &mut evt_handles, &mut last_high, &mut last_state); + for (offset, down_duration) in key_presses { + dbg!(down_duration); + if down_duration > 10*MILLIS { + tx.send(offset_to_command[offset]).unwrap(); } - Ok(()) - }) - .map_err(|_| ())); + } + } } - Ok(()) }); - tokio::run(task); Ok(()) } -pub fn start_monitoring(tx: crossbeam_channel::Sender) { - thread::spawn(move || { - let pin_numb_command_pairs = vec!( - //buttons near lamp - (16, Command::LampsDim), - (12, Command::LampsDimmest), - (13, Command::LampsToggle), - - //buttons on desk - (27, Command::MpdIncreaseVolume), //left 3, left - (22, Command::MpdPause), //left 3, middle - (18, Command::MpdDecreaseVolume), //left 3, right - - (23, Command::LampsNight), //right 4, left most - (24, Command::LampsEvening), //right 4, left - (26, Command::LampsDay), //right 4, right - (17, Command::LampsToggle), //right 4, right most - ); //BCM pin number - - stream(pin_numb_command_pairs, tx).unwrap(); - }); +///returns keys that where held as the time they where held in nanoseconds +fn process_event(pollables: &Vec, evt_handles: &mut Vec, + last_rising: &mut [u64], last_state: &mut [u8]) + -> SmallVec::<[(usize,u64); 64]> { + + let mut key_presses = SmallVec::<[(usize,u64); 64]>::new(); + for i in 0..pollables.len() { + if let Some(poll_res) = pollables[i].revents() { + let h = &mut evt_handles[i]; + if poll_res.contains(PollFlags::POLLIN) { + let value = h.get_value().unwrap(); + let event = h.get_event().unwrap(); + let offset = h.line().offset() as usize; + + if value == 1 && last_state[offset] == 0 { + //rising + last_state[offset] = 1; + last_rising[offset] = event.timestamp(); + } else if value == 0 && last_state[offset] == 1 { + //falling update current state and store duration of keypress + last_state[offset] = 0; + let held_for = event.timestamp()-last_rising[offset]; + key_presses.push((offset, held_for)); + } + } + } + } + key_presses +} + +fn configure_watching(chip: &mut Chip, offsets: &[u32]) + -> Result<(Vec, Vec), Error>{ + // maps to the driver for the SoC (builtin) GPIO controller. + let evt_handles = offsets.iter() + .map(|off| chip.get_line(*off).unwrap()) + .map(|line| line.events( + LineRequestFlags::INPUT, + EventRequestFlags::BOTH_EDGES, + "homeautomation", ).unwrap()) + .collect::>(); + + let pollables = evt_handles.iter() + .map(|h| PollFd::new(h.as_raw_fd(), + PollFlags::POLLIN | + PollFlags::POLLPRI)) + .collect::>(); + + Ok((evt_handles, pollables)) +} + +pub fn start_monitoring(tx: crossbeam_channel::Sender) + -> Result<(), Error> { + + let mut offset_to_command = [Event::Command(Command::None); N_LINES]; + //buttons near lamp + offset_to_command[16] = Event::Command(Command::LampsDim); + offset_to_command[12] = Event::Command(Command::LampsDimmest); + offset_to_command[13] = Event::Command(Command::LampsToggle); + + //buttons on desk + offset_to_command[27] = Event::Command(Command::MpdIncreaseVolume); //left 3, left + offset_to_command[22] = Event::Command(Command::MpdPause); //left 3, middle + offset_to_command[18] = Event::Command(Command::MpdDecreaseVolume); //left 3, right + + offset_to_command[23] = Event::Command(Command::LampsNight); //right 4, left most + offset_to_command[24] = Event::Command(Command::LampsEvening); //right 4, left + offset_to_command[26] = Event::Command(Command::LampsDay); //right 4, right + offset_to_command[17] = Event::Command(Command::LampsToggle); //right 4, right most + + for chip in gpio_cdev::chips().unwrap() {dbg!(chip);} + if let Some(mut chip) = gpio_cdev::chips()? + .filter_map(Result::ok) + .inspect(|x| println!("{:?}",x)) + .filter(|c| c.label() == "pinctrl-bcm2835") + .inspect(|x| println!("{:?}",x)) + .next() { + + dbg!(); + detect_and_handle(&mut chip, offset_to_command, tx)?; + + Ok(()) + } else { + Err(Error::GPIONotFound) + } } diff --git a/src/input/sensors/mod.rs b/src/input/sensors/mod.rs index 3852960c..4edeb7fd 100755 --- a/src/input/sensors/mod.rs +++ b/src/input/sensors/mod.rs @@ -1,7 +1,5 @@ -extern crate chrono; -extern crate smallvec; -extern crate bytes; use byteorder::{LittleEndian, ByteOrder}; +use futures::future; #[cfg(feature = "sensors_connected")] mod local; @@ -11,11 +9,13 @@ mod ble; use std::thread; use std::time::Duration; use chrono::Utc; +use async_std::task; +use actix_rt; -use crate::credentials; use crate::controller::Event; use local::{TEMPERATURE, HUMIDITY, PRESSURE, STOP_ENCODE}; +#[derive(Debug, Clone, Copy)] pub enum SensorValue { Temperature(f32), Humidity(f32), @@ -25,7 +25,8 @@ pub enum SensorValue { //const LOCAL_SENSING_ID: timeseries_interface::DatasetId = 0; //TODO mechanisme for shutdown #[cfg(feature = "sensors_connected")] -pub fn start_monitoring(tx: crossbeam_channel::Sender) { +pub fn start_monitoring(tx: crossbeam_channel::Sender, + node_id: u16, dataserver_key: u64) { //init all local sensors let mut local_sensors = local::init(); @@ -33,6 +34,8 @@ pub fn start_monitoring(tx: crossbeam_channel::Sender) { ble::init(); thread::spawn(move || {//TODO figure out shutdown behaviour + + loop { //get all measurements let (hum, temp, pressure) = local::measure_and_record(&mut local_sensors); @@ -40,32 +43,37 @@ pub fn start_monitoring(tx: crossbeam_channel::Sender) { //TODO //process data into events and send off as event - tx.send(Event::Sensor(SensorValue::Temperature(temp))); - tx.send(Event::Sensor(SensorValue::Humidity(hum))); - tx.send(Event::Sensor(SensorValue::Pressure(pressure))); + tx.send(Event::Sensor(SensorValue::Temperature(temp))).unwrap(); + tx.send(Event::Sensor(SensorValue::Humidity(hum))).unwrap(); + tx.send(Event::Sensor(SensorValue::Pressure(pressure))).unwrap(); //encode all data let mut line = vec!(0u8; (STOP_ENCODE+8-1)/8); - LittleEndian::write_u16(&mut line[0..2], credentials::NODE_ID); - LittleEndian::write_u64(&mut line[2..10], credentials::DATASERVER_KEY); + LittleEndian::write_u16(&mut line[0..2], node_id); + LittleEndian::write_u64(&mut line[2..10], dataserver_key); TEMPERATURE.encode::(temp, &mut line); HUMIDITY.encode::(hum, &mut line); PRESSURE.encode::(pressure, &mut line); dbg!(&line); - - //send data to dataserver - let client = reqwest::Client::new(); - if let Err(e) = client.post("https://www.deviousd.duckdns.org:38972/post_data") - .body(line) - .send(){ + thread::sleep(Duration::from_secs(5)); - error!("could not send data to dataserver, error: {:?}", e); - } + /*task::block_on( async { FIXME TODO RE-ENABLE AND SOLVE RUNTIME ISSUES + + let client = reqwest::Client::new(); + let send = client.post("https://www.deviousd.duckdns.org:38972/post_data") + .body(line) + .send(); + let sleep = task::sleep(Duration::from_secs(5)); - //sleep until 5 seconds are completed - thread::sleep(Duration::from_secs(5)); + //send data to dataserver and sleep up to 5 sec + let (send_err, _) = future::join(send, sleep).await; + + if let Err(e) = send_err { + error!("could not send data to dataserver, error: {:?}", e); + } + })*/ } }); } diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index fc1f36ab..b2544fa2 100755 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -18,7 +18,7 @@ fn authenticated(auth: BasicAuth) -> bool { let username = auth.user_id(); if let Some(password) = auth.password(){ - command_logins::LIST.into_iter() + command_logins::LIST.iter() .filter(|x| x.username==username) .filter(|x| x.password==password) .next().is_some() diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index 218312f1..80454772 100755 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -2,6 +2,7 @@ use rustls::{NoClientAuth, ServerConfig}; use rustls::internal::pemfile::{certs, pkcs8_private_keys}; use actix_rt::Runtime; +use actix_rt::System; use actix_web::{HttpServer,App, web, Responder}; use actix_identity::{CookieIdentityPolicy, IdentityService}; use actix_files as fs; @@ -87,6 +88,7 @@ pub fn start_webserver(signed_cert: &str, private_key: &str, let (tx, rx) = crossbeam_channel::unbounded(); thread::spawn(move || { + let sys = System::new("HttpServer"); let web_server = HttpServer::new(move || { // data the webservers functions have access to let data = actix_web::web::Data::new(state.clone()); @@ -141,10 +143,12 @@ pub fn start_webserver(signed_cert: &str, private_key: &str, .run(); let _ = tx.send(web_server.clone()); - let mut rt = Runtime::new().unwrap(); - rt.block_on(web_server).unwrap(); + sys.run() + //let mut rt = Runtime::new().unwrap(); + //rt.block_on(web_server).unwrap(); }); let web_handle = rx.recv().unwrap(); + web_handle } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 00977777..47790625 100755 --- a/src/main.rs +++ b/src/main.rs @@ -30,8 +30,14 @@ struct Opt { #[structopt(short = "d", long = "domain")] domain: String, - #[structopt(short = "p", long = "admin-password")] - password: String, + #[structopt(short = "a", long = "admin-password")] + password: String, + + #[structopt(short = "n", long = "node-id", default_value= "3")] + node_id: u16, + + #[structopt(short = "k", long = "dataserver-key")] + dataserver_key: u64, } #[actix_rt::main] @@ -63,7 +69,7 @@ async fn main() { let state = State::new( passw_db, - controller_tx, + controller_tx.clone(), alarms, youtube_dl, opt.token.clone()); @@ -80,9 +86,10 @@ async fn main() { //start monitoring local sensors #[cfg(feature = "sensors_connected")] - input::sensors::start_monitoring(controller_tx.clone()); + input::sensors::start_monitoring(controller_tx.clone(), opt.node_id, + opt.dataserver_key); #[cfg(feature = "sensors_connected")] - input::buttons::start_monitoring(controller_tx.clone()); + input::buttons::start_monitoring(controller_tx.clone()).unwrap(); println!("press: q to quit"); loop { From 3b82120408413692e189d83188dba059094b6c8a Mon Sep 17 00:00:00 2001 From: dskleingeld Date: Sat, 8 Feb 2020 00:25:33 +0100 Subject: [PATCH 024/687] updates dependencies --- Cargo.lock | 1272 +++++++++++++++++++++++++++------------------------- Cargo.toml | 33 +- 2 files changed, 665 insertions(+), 640 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1d9e3dae..28d4622f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,34 +11,33 @@ dependencies = [ "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "actix-web-httpauth 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "bme280 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "gpio-cdev 0.2.1 (git+https://github.com/rust-embedded/gpio-cdev)", "linux-embedded-hal 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mpd 0.0.12 (registry+https://github.com/rust-lang/crates.io-index)", - "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "philipshue 0.3.2 (git+https://github.com/dskleingeld/philipshue)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "retry 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.11 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", "sled 0.30.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "sysfs_gpio 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "telegram-bot 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -53,18 +52,18 @@ dependencies = [ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-signal 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-proto 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -77,8 +76,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -95,14 +94,14 @@ dependencies = [ "actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-rustls 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-proto 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-resolver 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -116,9 +115,9 @@ dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "v_htmlescape 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -140,32 +139,32 @@ dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -179,9 +178,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -191,7 +190,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -205,15 +204,15 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -226,7 +225,7 @@ dependencies = [ "bytestring 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -238,7 +237,7 @@ dependencies = [ "actix-macros 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "actix-threadpool 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -251,12 +250,12 @@ dependencies = [ "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -265,7 +264,7 @@ name = "actix-service" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -278,7 +277,7 @@ dependencies = [ "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "actix-server 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -289,10 +288,10 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -308,11 +307,11 @@ dependencies = [ "actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-rustls 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", "webpki-roots 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -327,7 +326,7 @@ dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -353,20 +352,20 @@ dependencies = [ "awc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -374,9 +373,9 @@ name = "actix-web-codegen" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -388,7 +387,7 @@ dependencies = [ "actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -408,10 +407,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "aho-corasick" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -434,12 +433,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "arc-swap" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "arrayref" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -450,22 +449,28 @@ dependencies = [ "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayvec" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "async-trait" -version = "0.1.22" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "atty" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -474,6 +479,11 @@ name = "autocfg" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "awc" version = "1.0.1" @@ -486,25 +496,25 @@ dependencies = [ "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace" -version = "0.3.40" +version = "0.3.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -513,8 +523,8 @@ name = "backtrace-sys" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -522,7 +532,7 @@ name = "base64" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -532,11 +542,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bincode" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -557,12 +566,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "blake2b_simd" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -578,8 +587,8 @@ name = "brotli-sys" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -588,7 +597,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -598,12 +607,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bumpalo" -version = "3.1.2" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.3.2" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -611,7 +620,7 @@ name = "bytes" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -639,12 +648,15 @@ dependencies = [ [[package]] name = "cast" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "cc" -version = "1.0.46" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -654,12 +666,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "chrono" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -670,7 +681,7 @@ version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -688,7 +699,7 @@ dependencies = [ [[package]] name = "constant_time_eq" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -709,9 +720,9 @@ dependencies = [ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "publicsuffix 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "publicsuffix 1.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -728,7 +739,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -754,11 +765,11 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -770,7 +781,7 @@ dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -783,16 +794,17 @@ dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-queue" -version = "0.1.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -827,9 +839,9 @@ name = "derive_more" version = "0.99.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -847,14 +859,14 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "dtoa" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -873,7 +885,7 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.20" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -885,9 +897,9 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -895,7 +907,7 @@ name = "error-chain" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -903,7 +915,7 @@ name = "error-chain" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -911,7 +923,6 @@ name = "error-chain" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -920,7 +931,7 @@ name = "failure" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -929,10 +940,10 @@ name = "failure_derive" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -942,8 +953,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -969,7 +980,7 @@ name = "fs2" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -999,30 +1010,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-executor 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures-channel" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures-core" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1031,57 +1042,57 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures-executor" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures-io" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures-macro" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures-sink" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures-task" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures-util" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-macro 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1093,17 +1104,27 @@ name = "fxhash" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "getrandom" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gpio-cdev" +version = "0.2.1" +source = "git+https://github.com/rust-embedded/gpio-cdev#16fedc8e0f2bf5a442d0de7e475c2a8e10e48361" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1111,16 +1132,16 @@ name = "h2" version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1130,11 +1151,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1159,10 +1180,10 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1175,18 +1196,18 @@ name = "hostname" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "http" -version = "0.1.19" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1196,7 +1217,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1206,7 +1227,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1233,40 +1254,40 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "hyper" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1286,9 +1307,9 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-rustls 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", "webpki-roots 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1301,7 +1322,7 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1310,7 +1331,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1318,12 +1339,12 @@ dependencies = [ [[package]] name = "i2cdev" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1334,7 +1355,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1344,15 +1365,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "indexmap" -version = "1.3.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1360,7 +1381,7 @@ name = "iovec" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1388,7 +1409,7 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1420,7 +1441,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.65" +version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1433,9 +1454,9 @@ name = "linux-embedded-hal" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "i2cdev 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "i2cdev 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "spidev 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "sysfs_gpio 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1451,7 +1472,7 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1478,14 +1499,19 @@ name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memchr" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memoffset" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1493,7 +1519,7 @@ dependencies = [ [[package]] name = "mime" -version = "0.3.14" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1501,13 +1527,13 @@ name = "mime_guess" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "miniz_oxide" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1523,7 +1549,7 @@ dependencies = [ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1537,7 +1563,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1568,14 +1594,14 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.28 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.52 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.54 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1590,7 +1616,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1601,7 +1627,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1613,9 +1639,9 @@ version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1629,100 +1655,100 @@ name = "nom" version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-complex 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-bigint" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-complex" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-integer" -version = "0.1.41" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-iter" -version = "0.1.39" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-rational" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num_cpus" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "openssl" -version = "0.10.25" +version = "0.10.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.52 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1732,14 +1758,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.52" +version = "0.9.54" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1747,7 +1773,7 @@ name = "ordered-float" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1763,7 +1789,7 @@ name = "pagecache" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1773,9 +1799,9 @@ dependencies = [ "hashbrown 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "historian 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1793,7 +1819,7 @@ name = "parking_lot" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1803,7 +1829,7 @@ name = "parking_lot" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1812,10 +1838,10 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1826,10 +1852,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1840,9 +1866,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1865,7 +1891,7 @@ dependencies = [ "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1881,9 +1907,9 @@ name = "pin-project-internal" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1908,26 +1934,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro-error" -version = "0.4.5" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-error-attr 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error-attr 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustversion 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro-error-attr" -version = "0.4.5" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustversion 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn-mid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1935,9 +1961,9 @@ name = "proc-macro-hack" version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1955,7 +1981,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1963,19 +1989,19 @@ dependencies = [ [[package]] name = "publicsuffix" -version = "1.5.3" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "quick-error" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1991,7 +2017,7 @@ name = "quote" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2001,7 +2027,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2012,7 +2038,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2026,11 +2052,11 @@ dependencies = [ [[package]] name = "rand" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2072,7 +2098,7 @@ name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2104,7 +2130,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2116,7 +2142,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2141,24 +2167,24 @@ dependencies = [ [[package]] name = "rayon" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon-core" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2176,29 +2202,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "redox_users" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-argon2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.3.1" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.12" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2218,28 +2243,28 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-rustls 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "webpki-roots 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2253,17 +2278,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2273,7 +2298,7 @@ dependencies = [ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-futures 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2286,7 +2311,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2299,12 +2324,12 @@ dependencies = [ [[package]] name = "ring" -version = "0.16.9" +version = "0.16.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2313,12 +2338,13 @@ dependencies = [ [[package]] name = "rust-argon2" -version = "0.5.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2354,9 +2380,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.11 (registry+https://github.com/rust-lang/crates.io-index)", "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2364,9 +2390,9 @@ name = "rustversion" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2376,7 +2402,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "schannel" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2403,24 +2429,24 @@ name = "sct" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.11 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "security-framework" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "security-framework-sys" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2466,17 +2492,17 @@ name = "serde_derive" version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.41" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2486,8 +2512,8 @@ name = "serde_urlencoded" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2497,10 +2523,10 @@ name = "serde_urlencoded" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2508,7 +2534,7 @@ name = "serde_yaml" version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2519,22 +2545,13 @@ name = "sha1" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "signal-hook" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "signal-hook-registry" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arc-swap 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2552,19 +2569,22 @@ dependencies = [ "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "smallvec" -version = "0.6.12" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "smallvec" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2573,7 +2593,7 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2589,7 +2609,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2618,24 +2638,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "structopt" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "structopt-derive" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-error 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2650,32 +2670,32 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.7" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syn-mid" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "synstructure" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2684,10 +2704,7 @@ name = "sysfs_gpio" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2713,7 +2730,7 @@ dependencies = [ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde-value 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2722,8 +2739,8 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2739,7 +2756,7 @@ dependencies = [ [[package]] name = "thread_local" -version = "0.3.6" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2750,7 +2767,7 @@ name = "threadpool" version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2758,7 +2775,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2771,19 +2788,19 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2793,16 +2810,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2819,12 +2836,12 @@ dependencies = [ [[package]] name = "tokio-codec" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2839,43 +2856,43 @@ dependencies = [ "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-current-thread" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-fs" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-io" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2885,20 +2902,20 @@ dependencies = [ [[package]] name = "tokio-reactor" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2910,8 +2927,8 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2919,31 +2936,31 @@ name = "tokio-rustls" version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-signal" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "signal-hook 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-sync" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2952,42 +2969,42 @@ dependencies = [ [[package]] name = "tokio-tcp" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.16" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3001,33 +3018,33 @@ dependencies = [ [[package]] name = "tokio-udp" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-uds" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3036,8 +3053,8 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3061,21 +3078,21 @@ name = "trust-dns-proto" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3084,21 +3101,21 @@ name = "trust-dns-proto" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3107,18 +3124,18 @@ name = "trust-dns-proto" version = "0.18.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "async-trait 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "async-trait 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "enum-as-inner 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3134,7 +3151,7 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3146,13 +3163,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-proto 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3172,10 +3189,10 @@ dependencies = [ [[package]] name = "unicase" -version = "2.5.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3188,10 +3205,10 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.8" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3231,7 +3248,7 @@ dependencies = [ [[package]] name = "url" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3261,9 +3278,9 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3277,7 +3294,7 @@ dependencies = [ [[package]] name = "vcpkg" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3290,6 +3307,11 @@ name = "version_check" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "version_check" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "void" version = "1.0.2" @@ -3316,7 +3338,7 @@ dependencies = [ [[package]] name = "wasi" -version = "0.7.0" +version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3326,7 +3348,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-macro 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3335,12 +3357,12 @@ name = "wasm-bindgen-backend" version = "0.2.58" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bumpalo 3.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bumpalo 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3369,9 +3391,9 @@ name = "wasm-bindgen-macro-support" version = "0.2.58" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3389,9 +3411,9 @@ dependencies = [ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3410,10 +3432,10 @@ dependencies = [ [[package]] name = "webpki" -version = "0.21.0" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.11 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3422,7 +3444,7 @@ name = "webpki-roots" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3535,43 +3557,45 @@ dependencies = [ "checksum actix-web-httpauth 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7cccccfac88ec8c0475538f466384b90e4395a7420288f5384baf1c51fad73ec" "checksum actix_derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4300e9431455322ae393d43a2ba1ef96b8080573c0fc23b196219efedfb6ba69" "checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" -"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" +"checksum aho-corasick 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "743ad5a418686aad3b87fd14c43badd828cf26e214a00f92a384291cf22e1811" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" "checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" -"checksum arc-swap 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a1eca3195b729bbd64e292ef2f5fff6b1c28504fed762ce2b1013dde4d8e92" -"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" +"checksum arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d7b8a9123b8027467bce0099fe556c628a53c8d83df0507084c31e9ba2e39aff" +"checksum arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" "checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -"checksum async-trait 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c8df72488e87761e772f14ae0c2480396810e51b2c2ade912f97f0f7e5b95e3c" -"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" +"checksum async-trait 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "750b1c38a1dfadd108da0f01c08f4cdc7ff1bb39b325f9c82cc972361780a6e1" +"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" "checksum awc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7601d4d1d7ef2335d6597a41b5fe069f6ab799b85f53565ab390e7b7065aac5" -"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" +"checksum backtrace 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "7f80256bc78f67e7df7e36d77366f636ed976895d91fe2ab9efa3973e8fe8c4f" "checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" -"checksum bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ab639324e3ee8774d296864fbc0dbbb256cf1a41c490b94cba90c082915f92" +"checksum bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" "checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182" +"checksum blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" "checksum bme280 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d48076b7293afafab5ff93e3db57435c567f1fc72755c27d377f7e96ea66678d" "checksum brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" "checksum brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" "checksum bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" -"checksum bumpalo 3.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb8038c1ddc0a5f73787b130f4cc75151e96ed33e417fde765eb5a81e3532f4" -"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +"checksum bumpalo 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742" +"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" "checksum bytestring 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fc267467f58ef6cc8874064c62a0423eb0d099362c8a23edd1c6d044f46eead4" "checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" -"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" -"checksum cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)" = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c" +"checksum cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" +"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" +"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" +"checksum constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" "checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" "checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" "checksum copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ff9c56c9fb2a49c05ef0e431485a22400af20d33226dc0764d891d09e724127" @@ -3579,20 +3603,20 @@ dependencies = [ "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" -"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" +"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" "checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" -"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" +"checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" "checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" "checksum ct-logs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d3686f5fa27dbc1d76c751300376e167c5a43387f44bb451fd1c24776e49113" "checksum derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8" "checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" "checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" -"checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" +"checksum dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ee4908a155094da7723c2d60d617b820061e3b4efcc3d9e293d206a5a76c170b" -"checksum encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)" = "87240518927716f79692c2ed85bfe6e98196d18c6401ec75355760233a7e12e9" +"checksum encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28" "checksum enum-as-inner 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "900a6c7fbe523f4c2884eaf26b57b81bb69b6810a01a236390a7ac021d09492e" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" @@ -3608,60 +3632,62 @@ dependencies = [ "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" -"checksum futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987" -"checksum futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" -"checksum futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866" +"checksum futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5c329ae8753502fb44ae4fc2b622fa2a94652c41e795143765ba0927f92ab780" +"checksum futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8" +"checksum futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231" -"checksum futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff" -"checksum futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764" -"checksum futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16" -"checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" -"checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" +"checksum futures-executor 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba" +"checksum futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6" +"checksum futures-macro 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7" +"checksum futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6" +"checksum futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27" +"checksum futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5" "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" +"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +"checksum gpio-cdev 0.2.1 (git+https://github.com/rust-embedded/gpio-cdev)" = "" "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" "checksum h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9433d71e471c1736fd5a61b671fc0b148d7a2992f666c958d03cd8feb3b88d1" "checksum hashbrown 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "29fba9abe4742d586dfd0c06ae4f7e73a1c2d86b856933509b269d82cdf06e18" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -"checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" +"checksum hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772" "checksum historian 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f653416eb756b69642a1f1498817970fafe409998a849622c27cc5b1b7df989c" "checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" -"checksum http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d7e06e336150b178206af098a055e3621e8336027e2b4d126bda0bc64824baaf" +"checksum http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" "checksum http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b708cc7f06493459026f53b9a61a7a121a5d1ec6238dee58ea4941132b30156b" "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" "checksum http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)" = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" -"checksum hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8bf49cfb32edee45d890537d9057d1b02ed55f53b7b6a30bae83a38c9231749e" +"checksum hyper 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fa1c527bbc634be72aa7ba31e4e4def9bbb020f5416916279b7c705cd838893e" "checksum hyper-rustls 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "719d85c7df4a7f309a77d145340a063ea929dcb2e025bae46a80345cffec2952" "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum hyper-tls 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3adcd308402b9553630734e9c36b77a7e48b3821251ca2493e8cd596763aafaa" -"checksum i2cdev 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db7cf03500911132bacb44430234aa58dba843bb6aa2820154e5abb696e3e3d9" +"checksum i2cdev 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0eb3d9b6b02dc2508ee23439170004e44344bab9d53a490eb1f64c885b5003" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -"checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" +"checksum indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" "checksum ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "08f7eadeaf4b52700de180d147c4805f199854600b36faa963d91114827b2ffc" "checksum ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa79fa216fbe60834a9c0737d7fcd30425b32d1c58854663e24d4c4b328ed83f" -"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" +"checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" "checksum js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "7889c7c36282151f6bf465be4700359318aef36baa951462382eae49e9577cf9" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" +"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum linux-embedded-hal 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "795096c0eecb0622afb591c3e1a97b1ba046688a7689957b70b8eee9cac8fb84" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" +"checksum lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" -"checksum memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a85c1a8c329f11437034d7313dca647c79096523533a1c79e86f1d0f657c7cc" -"checksum mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "dd1d63acd1b78403cc0c325605908475dd9b9a3acbf65ed8bcab97e27014afcf" +"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" +"checksum memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223" +"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" +"checksum mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" "checksum mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" -"checksum miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6f3f74f726ae935c3f514300cc6773a0c9492abc5e972d42ba0c0ebb88757625" +"checksum miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5" "checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" @@ -3673,17 +3699,17 @@ dependencies = [ "checksum nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a7bb1da2be7da3cbffda73fc681d509ffd9e665af478d2bee1907cee0bc64b2" "checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" -"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" -"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" -"checksum num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc" -"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" -"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" -"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" -"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" -"checksum num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "155394f924cdddf08149da25bfb932d226b4a593ca7468b08191ff6335941af5" -"checksum openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2f372b2b53ce10fb823a337aaa674e3a7d072b957c6264d0f4ff0bd86e657449" +"checksum num 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" +"checksum num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +"checksum num-complex 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +"checksum num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00" +"checksum num-rational 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "da4dc79f9e6c81bef96148c8f6b8e72ad4541caa4a24373e900a36da07de03a3" +"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +"checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" +"checksum openssl 0.10.28 (registry+https://github.com/rust-lang/crates.io-index)" = "973293749822d7dd6370d6da1e523b0d1db19f06c459134c658b2a4261378b52" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.52 (registry+https://github.com/rust-lang/crates.io-index)" = "c977d08e1312e2f7e4b86f9ebaa0ed3b19d1daff75fae88bbb88108afbd801fc" +"checksum openssl-sys 0.9.54 (registry+https://github.com/rust-lang/crates.io-index)" = "1024c0a59774200a555087a6da3f253a9095a5f344e353b212ac4c8b8e450986" "checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74a701d13e2f3ee32a50be43321da8f712cf1e6e9ff0e2be66ab7f5c6598a16a" @@ -3702,19 +3728,19 @@ dependencies = [ "checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" "checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" "checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" -"checksum proc-macro-error 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1b79a464461615532fcc8a6ed8296fa66cc12350c18460ab3f4594a6cee0fcb6" -"checksum proc-macro-error-attr 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "23832e5eae6bac56bbac190500eef1aaede63776b5cd131eaa4ee7fe120cd892" +"checksum proc-macro-error 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "875077759af22fa20b610ad4471d8155b321c89c3f2785526c9839b099be4e0a" +"checksum proc-macro-error-attr 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c5717d9fa2664351a01ed73ba5ef6df09c01a521cb42cb65a061432a826f3c7a" "checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" -"checksum publicsuffix 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9bf259a81de2b2eb9850ec990ec78e6a25319715584fd7652b9b26f96fcb1510" -"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +"checksum proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548" +"checksum publicsuffix 1.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3bbaa49075179162b49acac1c6aa45fb4dafb5f13cf6794276d77bc7fd95757b" +"checksum quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" +"checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" @@ -3727,20 +3753,20 @@ dependencies = [ "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" -"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" +"checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" +"checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" -"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" -"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" +"checksum redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431" +"checksum regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" +"checksum regex-syntax 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b28dfe3fe9badec5dbf0a79a9cccad2cfc2ab5484bdb3e44cbd1ae8b3ba2be06" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum reqwest 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0e798e19e258bf6c30a304622e3e9ac820e483b06a1857a026e1f109b113fe4" "checksum reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab" "checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" "checksum retry 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ac83b31b3831aa4b07608db4170f6555ab12942197037c38570dc4c5ba5028" -"checksum ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6747f8da1f2b1fabbee1aaa4eb8a11abf9adef0bf58a41cee45db5d59cecdfac" -"checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" +"checksum ring 0.16.11 (registry+https://github.com/rust-lang/crates.io-index)" = "741ba1704ae21999c00942f9f5944f801e977f54302af346b596287599ad1862" +"checksum rust-argon2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" @@ -3748,30 +3774,29 @@ dependencies = [ "checksum rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" "checksum rustversion 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bba175698996010c4f6dce5e7f173b6eb781fce25d2cfc45e27091ce0b79f6" "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" -"checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" +"checksum schannel 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "507a9e6e8ffe0a4e0ebb9a10293e62fdf7657c06f1b8bb07a8fcf697d2abf295" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" -"checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" -"checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" +"checksum security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df" +"checksum security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" "checksum serde-value 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7a663f873dedc4eac1a559d4c6bc0d0b2c34dc5ac4702e105014b8281489e44f" "checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" -"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" +"checksum serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "15913895b61e0be854afd32fd4163fcd2a3df34142cf2cb961b310ce694cbf90" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" "checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" "checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" -"checksum signal-hook 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cb543aecec4ba8b867f41284729ddfdb7e8fcd70ec3d7d37fca3007a4b53675f" -"checksum signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1797d48f38f91643908bb14e35e79928f9f4b3cefb2420a564dde0991b4358dc" +"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum sled 0.30.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb8c32cb0e34e67ad74fae1a77f4635d0cc7ffc873088a0136f3c4849336d71" -"checksum smallvec 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "533e29e15d0748f28afbaf4ff7cab44d73e483a8e50b38c40bd13b7f3d48f542" -"checksum smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4" +"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" +"checksum smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" "checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" "checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" "checksum spidev 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ba01d3ef92a37e898fecac76cd3e1b33c999395e2d70787608d9678c4293e04" @@ -3779,40 +3804,40 @@ dependencies = [ "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum structopt 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "df136b42d76b1fbea72e2ab3057343977b04b4a2e00836c3c7c0673829572713" -"checksum structopt-derive 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd50a87d2f7b8958055f3e73a963d78feaccca3836767a9069844e34b5b03c0a" +"checksum structopt 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "a1bcbed7d48956fcbb5d80c6b95aedb553513de0a1b451ea92679d999c010e98" +"checksum structopt-derive 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "095064aa1f5b94d14e635d0a5684cf140c43ae40a0fd990708d38f5d669e5f64" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -"checksum syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7bedb3320d0f3035594b0b723c8a28d7d336a3eda3881db79e61d676fb644c" -"checksum syn-mid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd3937748a7eccff61ba5b90af1a20dbf610858923a9192ea0ecb0cb77db1d0" -"checksum synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" +"checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5" +"checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" +"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" "checksum sysfs_gpio 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "24961a55846623d8e4f6cec38718945116fed8d6970336a7110710a07aa9b5d1" "checksum telegram-bot 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "225d5eca220fcf23ad25b269991cdc8f8d421d97634c7f9e10b4c5dcdaa913b6" "checksum telegram-bot-raw 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65578f718dadd17347cd60d45609a7e1d57a52b459797957002b922349ee9744" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" "checksum tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8fdd17989496f49cdc57978c96f0c9fe5e4a58a8bddc6813c449a4624f6a030b" "checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" -"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" +"checksum tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" "checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" -"checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" -"checksum tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f27ee0e6db01c5f0b2973824547ce7e637b2ed79b891a9677b0de9bd532b6ac" -"checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" -"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" -"checksum tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c56391be9805bc80163151c0b9e5164ee64f4b0200962c346fea12773158f22d" +"checksum tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" +"checksum tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" +"checksum tokio-fs 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" +"checksum tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" +"checksum tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" "checksum tokio-rustls 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2d7cf08f990090abd6c6a73cab46fed62f85e8aef8b99e4b918a9f4a637f0676" "checksum tokio-rustls 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "141afec0978abae6573065a48882c6bae44c5cc61db9b511ac4abf6a09bfd9cc" -"checksum tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "dd6dc5276ea05ce379a16de90083ec80836440d5ef8a6a39545a3207373b8296" -"checksum tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d06554cce1ae4a50f42fba8023918afa931413aded705b560e29600ccf7c6d76" -"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd2c6a3885302581f4401c82af70d792bb9df1700e7437b0aeb4ada94d5388c" -"checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" +"checksum tokio-signal 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c34c6e548f101053321cba3da7cbb87a610b85555884c41b07da2eb91aff12" +"checksum tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" +"checksum tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" +"checksum tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" +"checksum tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" "checksum tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7bde02a3a5291395f59b06ec6945a3077602fac2b07eeeaf0dee2122f3619828" -"checksum tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f02298505547f73e60f568359ef0d016d5acd6e830ab9bc7c4a5b3403440121b" -"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" +"checksum tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" +"checksum tokio-uds 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5076db410d6fdc6523df7595447629099a1fdc47b3d9f896220780fa48faf798" "checksum tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" "checksum tower-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b32f72af77f1bfe3d3d4da8516a238ebe7039b51dd8637a09841ac7f16d2c987" "checksum tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" @@ -3823,27 +3848,28 @@ dependencies = [ "checksum trust-dns-resolver 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" -"checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" +"checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" +"checksum unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" "checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" "checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" +"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" "checksum v_escape 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "660b101c07b5d0863deb9e7fb3138777e858d6d2a79f9e6049a27d1cc77c6da6" "checksum v_escape_derive 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae" "checksum v_htmlescape 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e33e939c0d8cf047514fb6ba7d5aac78bc56677a6938b2ee67000b91f2e97e41" -"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" +"checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" "checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" +"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" "checksum wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "5205e9afdf42282b192e2310a5b463a6d1c1d774e30dc3c791ac37ab42d2616c" "checksum wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "11cdb95816290b525b32587d76419facd99662a07e59d3cdb560488a819d9a45" "checksum wasm-bindgen-futures 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8bbdd49e3e28b40dec6a9ba8d17798245ce32b019513a845369c641b275135d9" @@ -3852,7 +3878,7 @@ dependencies = [ "checksum wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e7e61fc929f4c0dddb748b102ebf9f632e2b8d739f2016542b4de2965a9601" "checksum wasm-bindgen-webidl 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ef012a0d93fc0432df126a8eaf547b2dce25a8ce9212e1d3cbeef5c11157975d" "checksum web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "aaf97caf6aa8c2b1dac90faf0db529d9d63c93846cca4911856f78a83cebf53b" -"checksum webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7e664e770ac0110e2384769bcc59ed19e329d81f555916a6e072714957b81b4" +"checksum webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1f50e1972865d6b1adb54167d1c8ed48606004c2c9d0ea5f1eeb34d95e863ef" "checksum webpki-roots 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a262ae37dd9d60f60dd473d1158f9fbebf110ba7b6a5051c8160460f6043718b" "checksum weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164" "checksum widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" diff --git a/Cargo.toml b/Cargo.toml index 41519bb2..51b841f9 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,11 +14,11 @@ sensors_connected = [] live_server = [] [dependencies] -futures = "0.3.1" +futures = "0.3" actix-web = { version = "2", features = ["rustls"] } -actix-net = "0.2.6" -actix-identity = "0.2.0" -actix-files = "0.2.1" +actix-net = "0.2" +actix-identity = "0.2" +actix-files = "0.2" actix-rt = "1" actix-service = "1.0" actix-web-httpauth = "0.4" @@ -34,32 +34,31 @@ serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.8" log = "0.4" -sysfs_gpio = { version = "0.5.4", features = ["use_tokio"] } -#sysfs_gpio = { git = "https://github.com/rust-embedded/rust-sysfs-gpio", branch = "master", features = ["use_tokio"] } +gpio-cdev = { git = "https://github.com/rust-embedded/gpio-cdev", branch = "master" } -tokio = "0.1.15" -bincode = "1.0.1" +#tokio = "0.1.15" +bincode = "1.0" ring = "0.16" -linux-embedded-hal = "0.2.2" -bme280 = "0.1.1" +linux-embedded-hal = "0.2" +bme280 = "0.1" -smallvec = "0.6.6" -chrono = { version = "0.4.6", features = ["serde"] } -bytes = "0.4.11" -byteorder = "1.3.1" +smallvec = "0.6" +chrono = { version = "0.4", features = ["serde"] } +bytes = "0.4" +byteorder = "1.3" num = { version = "0.2"} crossbeam-channel = "0.3" sled = "0.30" -pagecache = "0.17.0" +pagecache = "0.17" reqwest = {version = "0.10", features = ["blocking"]} mpd = "0.0.12" -dirs = "2.0.1" +dirs = "2" rand = "0.6" -retry = "0.5.1" +retry = "0.5" telegram-bot = "0.6" serde_json = "1.0" \ No newline at end of file From 729cc8446a7a96e3b42b8aaa2505551e3ed1108f Mon Sep 17 00:00:00 2001 From: dskleingeld Date: Sat, 8 Feb 2020 00:58:10 +0100 Subject: [PATCH 025/687] Create LICENSE.md --- LICENSE.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE.md diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..1550c40a --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 David Kleingeld + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From a470325216dac522ca1ad72af9c668e5c4cca7d7 Mon Sep 17 00:00:00 2001 From: dskleingeld Date: Sat, 8 Feb 2020 01:18:44 +0100 Subject: [PATCH 026/687] fixes buttons --- Cargo.lock | 3236 +++++++++++++++++++++--------------------- Cargo.toml | 3 + deny.toml | 196 +++ src/input/buttons.rs | 8 +- 4 files changed, 1860 insertions(+), 1583 deletions(-) create mode 100644 deny.toml diff --git a/Cargo.lock b/Cargo.lock index 28d4622f..35d90103 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,1117 +4,1277 @@ name = "HomeAutomation" version = "0.1.0" dependencies = [ - "actix-files 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-identity 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-net 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web-httpauth 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bme280 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "gpio-cdev 0.2.1 (git+https://github.com/rust-embedded/gpio-cdev)", - "linux-embedded-hal 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mpd 0.0.12 (registry+https://github.com/rust-lang/crates.io-index)", - "num 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", - "philipshue 0.3.2 (git+https://github.com/dskleingeld/philipshue)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "retry 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", - "sled 0.30.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "telegram-bot 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-files", + "actix-identity", + "actix-net", + "actix-rt", + "actix-service", + "actix-web", + "actix-web-httpauth", + "async-std", + "bincode", + "bme280", + "byteorder", + "bytes 0.4.12", + "chrono", + "crossbeam-channel 0.3.9", + "dirs", + "futures 0.3.4", + "gpio-cdev", + "linux-embedded-hal", + "log", + "mpd", + "nix 0.17.0", + "num", + "pagecache", + "philipshue", + "rand 0.6.5", + "reqwest 0.10.1", + "retry", + "ring", + "rustls", + "serde", + "serde_json", + "serde_yaml", + "sled", + "smallvec 0.6.13", + "structopt", + "telegram-bot", ] [[package]] name = "actix" version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "actix_derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-signal 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-proto 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", +checksum = "6c616db5fa4b0c40702fb75201c2af7f8aa8f3a2e2c1dda3b0655772aa949666" +dependencies = [ + "actix_derive", + "bitflags 1.2.1", + "bytes 0.4.12", + "crossbeam-channel 0.3.9", + "failure", + "fnv", + "futures 0.1.29", + "libc", + "log", + "parking_lot 0.7.1", + "smallvec 0.6.13", + "tokio 0.1.22", + "tokio-codec", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-signal", + "tokio-tcp", + "tokio-timer", + "trust-dns-proto 0.5.0", + "trust-dns-resolver 0.10.3", + "uuid", ] [[package]] name = "actix-codec" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09e55f0a5c2ca15795035d90c46bd0e73a5123b72f68f12596d6ba5282051380" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1", + "bytes 0.5.4", + "futures-core", + "futures-sink", + "log", + "tokio 0.2.11", + "tokio-util", ] [[package]] name = "actix-connect" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c95cc9569221e9802bf4c377f6c18b90ef10227d787611decf79fd47d2a8e76c" dependencies = [ - "actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-rustls 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-proto 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-resolver 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-codec", + "actix-rt", + "actix-service", + "actix-utils", + "derive_more", + "either", + "futures 0.3.4", + "http 0.2.0", + "log", + "rustls", + "tokio-rustls 0.12.2", + "trust-dns-proto 0.18.0-alpha.2", + "trust-dns-resolver 0.18.0-alpha.2", + "webpki", ] [[package]] name = "actix-files" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301482841d3d74483a446ead63cb7d362e187d2c8b603f13d91995621ea53c46" dependencies = [ - "actix-http 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "v_htmlescape 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-http", + "actix-service", + "actix-web", + "bitflags 1.2.1", + "bytes 0.5.4", + "derive_more", + "futures 0.3.4", + "log", + "mime", + "mime_guess", + "percent-encoding 2.1.0", + "v_htmlescape", ] [[package]] name = "actix-http" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-connect 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-threadpool 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +checksum = "c16664cc4fdea8030837ad5a845eb231fb93fc3c5c171edfefb52fad92ce9019" +dependencies = [ + "actix-codec", + "actix-connect", + "actix-rt", + "actix-service", + "actix-threadpool", + "actix-tls", + "actix-utils", + "base64 0.11.0", + "bitflags 1.2.1", + "brotli2", + "bytes 0.5.4", + "chrono", + "copyless", + "derive_more", + "either", + "encoding_rs", + "failure", + "flate2", + "futures-channel", + "futures-core", + "futures-util", + "fxhash", + "h2 0.2.1", + "http 0.2.0", + "httparse", + "indexmap", + "language-tags", + "lazy_static", + "log", + "mime", + "percent-encoding 2.1.0", + "pin-project", + "rand 0.7.3", + "regex", + "ring", + "serde", + "serde_json", + "serde_urlencoded 0.6.1", + "sha1", + "slab", + "time", ] [[package]] name = "actix-identity" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a379b0639c293292d71defb8cc1f94c87b7705c904adf044338ad392df77c7a" dependencies = [ - "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service", + "actix-web", + "futures 0.3.4", + "serde", + "serde_json", + "time", ] [[package]] name = "actix-macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21705adc76bbe4bc98434890e73a89cd00c6015e5704a60bb6eea6c3b72316b6" dependencies = [ - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2", + "syn 1.0.14", ] [[package]] name = "actix-net" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bebfbe6629e0131730746718c9e032b58f02c6ce06ed7c982b9fef6c8545acd" dependencies = [ - "actix 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tower-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", + "actix", + "bytes 0.4.12", + "futures 0.1.29", + "log", + "mio", + "net2", + "num_cpus", + "slab", + "tokio 0.1.22", + "tokio-codec", + "tokio-current-thread", + "tokio-io", + "tokio-reactor", + "tokio-tcp", + "tokio-timer", + "tower-service 0.1.0", + "trust-dns-resolver 0.10.3", ] [[package]] name = "actix-router" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d7a10ca4d94e8c8e7a87c5173aba1b97ba9a6563ca02b0e1cd23531093d3ec8" dependencies = [ - "bytestring 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "bytestring", + "http 0.2.0", + "log", + "regex", + "serde", ] [[package]] name = "actix-rt" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6a0a55507046441a496b2f0d26a84a65e67c8cafffe279072412f624b5fb6d" dependencies = [ - "actix-macros 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-threadpool 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-macros", + "actix-threadpool", + "copyless", + "futures 0.3.4", + "tokio 0.2.11", ] [[package]] name = "actix-server" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d3455eaac03ca3e49d7b822eb35c884b861f715627254ccbe4309d08f1841a" dependencies = [ - "actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-codec", + "actix-rt", + "actix-service", + "actix-utils", + "futures 0.3.4", + "log", + "mio", + "mio-uds", + "net2", + "num_cpus", + "slab", ] [[package]] name = "actix-service" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e4fc95dfa7e24171b2d0bb46b85f8ab0e8499e4e3caec691fc4ea65c287564" dependencies = [ - "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util", + "pin-project", ] [[package]] name = "actix-testing" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48494745b72d0ea8ff0cf874aaf9b622a3ee03d7081ee0c04edea4f26d32c911" dependencies = [ - "actix-macros 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-server 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-macros", + "actix-rt", + "actix-server", + "actix-service", + "futures 0.3.4", + "log", + "net2", ] [[package]] name = "actix-threadpool" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4082192601de5f303013709ff84d81ca6a1bc4af7fb24f367a500a23c6e84e" dependencies = [ - "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more", + "futures-channel", + "lazy_static", + "log", + "num_cpus", + "parking_lot 0.10.0", + "threadpool", ] [[package]] name = "actix-tls" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e5b4faaf105e9a6d389c606c298dcdb033061b00d532af9df56ff3a54995a8" dependencies = [ - "actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-rustls 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-codec", + "actix-rt", + "actix-service", + "actix-utils", + "derive_more", + "either", + "futures 0.3.4", + "log", + "rustls", + "tokio-rustls 0.12.2", + "webpki", + "webpki-roots", ] [[package]] name = "actix-utils" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf8f5631bf01adec2267808f00e228b761c60c0584cc9fa0b5364f41d147f4e" dependencies = [ - "actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-codec", + "actix-rt", + "actix-service", + "bitflags 1.2.1", + "bytes 0.5.4", + "either", + "futures 0.3.4", + "log", + "pin-project", + "slab", ] [[package]] name = "actix-web" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-http 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-macros 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-router 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-server 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-testing 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-threadpool 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web-codegen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "awc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +checksum = "3158e822461040822f0dbf1735b9c2ce1f95f93b651d7a7aded00b1efbb1f635" +dependencies = [ + "actix-codec", + "actix-http", + "actix-macros", + "actix-router", + "actix-rt", + "actix-server", + "actix-service", + "actix-testing", + "actix-threadpool", + "actix-tls", + "actix-utils", + "actix-web-codegen", + "awc", + "bytes 0.5.4", + "derive_more", + "encoding_rs", + "futures 0.3.4", + "fxhash", + "log", + "mime", + "net2", + "pin-project", + "regex", + "rustls", + "serde", + "serde_json", + "serde_urlencoded 0.6.1", + "time", + "url 2.1.1", ] [[package]] name = "actix-web-codegen" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0878b30e62623770a4713a6338329fd0119703bafc211d3e4144f4d4a7bdd5" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8", + "quote 1.0.2", + "syn 1.0.14", ] [[package]] name = "actix-web-httpauth" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cccccfac88ec8c0475538f466384b90e4395a7420288f5384baf1c51fad73ec" dependencies = [ - "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-service", + "actix-web", + "base64 0.11.0", + "bytes 0.5.4", + "futures 0.3.4", ] [[package]] name = "actix_derive" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4300e9431455322ae393d43a2ba1ef96b8080573c0fc23b196219efedfb6ba69" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", ] [[package]] name = "adler32" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" [[package]] name = "aho-corasick" version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743ad5a418686aad3b87fd14c43badd828cf26e214a00f92a384291cf22e1811" dependencies = [ - "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8", ] [[package]] name = "antidote" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" [[package]] name = "anyhow" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" [[package]] name = "arc-swap" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7b8a9123b8027467bce0099fe556c628a53c8d83df0507084c31e9ba2e39aff" [[package]] name = "arrayref" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" [[package]] name = "arrayvec" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" dependencies = [ - "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop", ] [[package]] name = "arrayvec" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" + +[[package]] +name = "async-std" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "538ecb01eb64eecd772087e5b6f7540cbc917f047727339a472dafed2185b267" +dependencies = [ + "async-task", + "crossbeam-channel 0.4.0", + "crossbeam-deque", + "crossbeam-utils 0.7.0", + "futures-core", + "futures-io", + "futures-timer", + "kv-log-macro", + "log", + "memchr", + "mio", + "mio-uds", + "num_cpus", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "async-task" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ac2c016b079e771204030951c366db398864f5026f84a44dafb0ff20f02085d" +dependencies = [ + "libc", + "winapi 0.3.8", +] [[package]] name = "async-trait" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "750b1c38a1dfadd108da0f01c08f4cdc7ff1bb39b325f9c82cc972361780a6e1" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8", + "quote 1.0.2", + "syn 1.0.14", ] [[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi", + "libc", + "winapi 0.3.8", ] [[package]] name = "autocfg" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" [[package]] name = "autocfg" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" [[package]] name = "awc" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7601d4d1d7ef2335d6597a41b5fe069f6ab799b85f53565ab390e7b7065aac5" dependencies = [ - "actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-http 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-codec", + "actix-http", + "actix-rt", + "actix-service", + "base64 0.11.0", + "bytes 0.5.4", + "derive_more", + "futures-core", + "log", + "mime", + "percent-encoding 2.1.0", + "rand 0.7.3", + "rustls", + "serde", + "serde_json", + "serde_urlencoded 0.6.1", ] [[package]] name = "backtrace" version = "0.3.43" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f80256bc78f67e7df7e36d77366f636ed976895d91fe2ab9efa3973e8fe8c4f" dependencies = [ - "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys", + "cfg-if", + "libc", + "rustc-demangle", ] [[package]] name = "backtrace-sys" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" dependencies = [ - "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", ] [[package]] name = "base64" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", ] [[package]] name = "base64" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" [[package]] name = "bincode" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "serde", ] [[package]] name = "bitflags" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" [[package]] name = "bitflags" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "blake2b_simd" version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" dependencies = [ - "arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref", + "arrayvec 0.5.1", + "constant_time_eq", ] [[package]] name = "bme280" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d48076b7293afafab5ff93e3db57435c567f1fc72755c27d377f7e96ea66678d" dependencies = [ - "embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "embedded-hal", ] [[package]] name = "brotli-sys" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" dependencies = [ - "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", ] [[package]] name = "brotli2" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" dependencies = [ - "brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "brotli-sys", + "libc", ] [[package]] name = "bufstream" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" [[package]] name = "bumpalo" version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742" [[package]] name = "byteorder" version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" [[package]] name = "bytes" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "either", + "iovec", ] [[package]] name = "bytes" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" [[package]] name = "bytestring" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc267467f58ef6cc8874064c62a0423eb0d099362c8a23edd1c6d044f46eead4" dependencies = [ - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4", ] [[package]] name = "c2-chacha" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" dependencies = [ - "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86", ] [[package]] name = "cast" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3", ] [[package]] name = "cc" version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" [[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "chrono" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" dependencies = [ - "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer", + "num-traits", + "serde", + "time", ] [[package]] name = "clap" version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term", + "atty", + "bitflags 1.2.1", + "strsim", + "textwrap", + "unicode-width", + "vec_map", ] [[package]] name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1", ] [[package]] name = "constant_time_eq" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "cookie" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" dependencies = [ - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "time", + "url 1.7.2", ] [[package]] name = "cookie_store" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" dependencies = [ - "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "publicsuffix 1.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie", + "failure", + "idna 0.1.5", + "log", + "publicsuffix", + "serde", + "serde_json", + "time", + "try_from", + "url 1.7.2", ] [[package]] name = "copyless" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff9c56c9fb2a49c05ef0e431485a22400af20d33226dc0764d891d09e724127" [[package]] name = "core-foundation" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" dependencies = [ - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys", + "libc", ] [[package]] name = "core-foundation-sys" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" [[package]] name = "crc32fast" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "crossbeam-channel" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6", +] + +[[package]] +name = "crossbeam-channel" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c" +dependencies = [ + "crossbeam-utils 0.7.0", ] [[package]] name = "crossbeam-deque" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" dependencies = [ - "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.8.0", + "crossbeam-utils 0.7.0", ] [[package]] name = "crossbeam-epoch" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" dependencies = [ - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.12", + "cfg-if", + "crossbeam-utils 0.6.6", + "lazy_static", + "memoffset", + "scopeguard 1.0.0", ] [[package]] name = "crossbeam-epoch" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7", + "cfg-if", + "crossbeam-utils 0.7.0", + "lazy_static", + "memoffset", + "scopeguard 1.0.0", ] [[package]] name = "crossbeam-queue" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "crossbeam-utils 0.7.0", ] [[package]] name = "crossbeam-utils" version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "lazy_static", ] [[package]] name = "crossbeam-utils" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7", + "cfg-if", + "lazy_static", ] [[package]] name = "ct-logs" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d3686f5fa27dbc1d76c751300376e167c5a43387f44bb451fd1c24776e49113" dependencies = [ - "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sct", ] [[package]] name = "derive_more" version = "0.99.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8", + "quote 1.0.2", + "syn 1.0.14", ] [[package]] name = "dirs" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "dirs-sys", ] [[package]] name = "dirs-sys" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "redox_users", + "winapi 0.3.8", ] [[package]] name = "dtoa" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" [[package]] name = "either" version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" [[package]] name = "embedded-hal" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4908a155094da7723c2d60d617b820061e3b4efcc3d9e293d206a5a76c170b" dependencies = [ - "nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "nb", + "void", ] [[package]] name = "encoding_rs" version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "enum-as-inner" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900a6c7fbe523f4c2884eaf26b57b81bb69b6810a01a236390a7ac021d09492e" dependencies = [ - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "heck", + "proc-macro2 1.0.8", + "quote 1.0.2", + "syn 1.0.14", ] [[package]] name = "error-chain" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" dependencies = [ - "backtrace 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace", ] [[package]] name = "error-chain" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" dependencies = [ - "backtrace 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace", ] [[package]] name = "error-chain" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5", ] [[package]] name = "failure" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" dependencies = [ - "backtrace 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace", + "failure_derive", ] [[package]] name = "failure_derive" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8", + "quote 1.0.2", + "syn 1.0.14", + "synstructure", ] [[package]] name = "flate2" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "crc32fast", + "libc", + "miniz_oxide", ] [[package]] name = "fnv" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" [[package]] name = "foreign-types" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types-shared", ] [[package]] name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "fs2" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "winapi 0.3.8", ] [[package]] name = "fuchsia-cprng" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1", + "fuchsia-zircon-sys", ] [[package]] name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futures" version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" [[package]] name = "futures" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c329ae8753502fb44ae4fc2b622fa2a94652c41e795143765ba0927f92ab780" dependencies = [ - "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-executor 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", ] [[package]] name = "futures-channel" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8" dependencies = [ - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core", + "futures-sink", ] [[package]] name = "futures-core" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a" [[package]] name = "futures-cpupool" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29", + "num_cpus", ] [[package]] name = "futures-executor" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba" dependencies = [ - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core", + "futures-task", + "futures-util", ] [[package]] name = "futures-io" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6" [[package]] name = "futures-macro" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7" dependencies = [ - "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack", + "proc-macro2 1.0.8", + "quote 1.0.2", + "syn 1.0.14", ] [[package]] name = "futures-sink" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6" [[package]] name = "futures-task" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27" + +[[package]] +name = "futures-timer" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6" [[package]] name = "futures-util" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5" dependencies = [ - "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-macro 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-utils", + "proc-macro-hack", + "proc-macro-nested", + "slab", ] [[package]] name = "fxhash" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", ] [[package]] name = "getrandom" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "wasi", ] [[package]] @@ -1122,2774 +1282,2690 @@ name = "gpio-cdev" version = "0.2.1" source = "git+https://github.com/rust-embedded/gpio-cdev#16fedc8e0f2bf5a442d0de7e475c2a8e10e48361" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1", + "libc", + "nix 0.14.1", ] [[package]] name = "h2" version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "bytes 0.4.12", + "fnv", + "futures 0.1.29", + "http 0.1.21", + "indexmap", + "log", + "slab", + "string", + "tokio-io", ] [[package]] name = "h2" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9433d71e471c1736fd5a61b671fc0b148d7a2992f666c958d03cd8feb3b88d1" dependencies = [ - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.0", + "indexmap", + "log", + "slab", + "tokio 0.2.11", + "tokio-util", ] [[package]] name = "hashbrown" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29fba9abe4742d586dfd0c06ae4f7e73a1c2d86b856933509b269d82cdf06e18" dependencies = [ - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", ] [[package]] name = "heck" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" dependencies = [ - "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation", ] [[package]] name = "hermit-abi" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "historian" version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f653416eb756b69642a1f1498817970fafe409998a849622c27cc5b1b7df989c" [[package]] name = "hostname" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "winutil", ] [[package]] name = "http" version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "fnv", + "itoa", ] [[package]] name = "http" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b708cc7f06493459026f53b9a61a7a121a5d1ec6238dee58ea4941132b30156b" dependencies = [ - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4", + "fnv", + "itoa", ] [[package]] name = "http-body" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "http 0.1.21", + "tokio-buf", ] [[package]] name = "http-body" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" dependencies = [ - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4", + "http 0.2.0", ] [[package]] name = "httparse" version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" [[package]] name = "hyper" version = "0.12.35" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +checksum = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.29", + "futures-cpupool", + "h2 0.1.26", + "http 0.1.21", + "http-body 0.1.0", + "httparse", + "iovec", + "itoa", + "log", + "net2", + "rustc_version 0.2.3", + "time", + "tokio 0.1.22", + "tokio-buf", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer", + "want 0.2.0", ] [[package]] name = "hyper" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa1c527bbc634be72aa7ba31e4e4def9bbb020f5416916279b7c705cd838893e" dependencies = [ - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.2.1", + "http 0.2.0", + "http-body 0.3.1", + "httparse", + "itoa", + "log", + "net2", + "pin-project", + "time", + "tokio 0.2.11", + "tower-service 0.3.0", + "want 0.3.0", ] [[package]] name = "hyper-rustls" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719d85c7df4a7f309a77d145340a063ea929dcb2e025bae46a80345cffec2952" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "ct-logs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-rustls 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "ct-logs", + "futures 0.1.29", + "hyper 0.12.35", + "rustls", + "tokio-io", + "tokio-rustls 0.10.3", + "webpki", + "webpki-roots", ] [[package]] name = "hyper-tls" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "hyper 0.12.35", + "native-tls", + "tokio-io", ] [[package]] name = "hyper-tls" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3adcd308402b9553630734e9c36b77a7e48b3821251ca2493e8cd596763aafaa" dependencies = [ - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4", + "hyper 0.13.2", + "native-tls", + "tokio 0.2.11", + "tokio-tls", ] [[package]] name = "i2cdev" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c0eb3d9b6b02dc2508ee23439170004e44344bab9d53a490eb1f64c885b5003" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1", + "byteorder", + "libc", + "nix 0.14.1", ] [[package]] name = "idna" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "matches", + "unicode-bidi", + "unicode-normalization", ] [[package]] name = "idna" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "matches", + "unicode-bidi", + "unicode-normalization", ] [[package]] name = "indexmap" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0", ] [[package]] name = "iovec" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "ipconfig" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f7eadeaf4b52700de180d147c4805f199854600b36faa963d91114827b2ffc" dependencies = [ - "error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.8.1", + "socket2", + "widestring 0.2.2", + "winapi 0.3.8", + "winreg 0.5.1", ] [[package]] name = "ipconfig" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa79fa216fbe60834a9c0737d7fcd30425b32d1c58854663e24d4c4b328ed83f" dependencies = [ - "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2", + "widestring 0.4.0", + "winapi 0.3.8", + "winreg 0.6.2", ] [[package]] name = "itoa" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" [[package]] name = "js-sys" version = "0.3.35" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7889c7c36282151f6bf465be4700359318aef36baa951462382eae49e9577cf9" dependencies = [ - "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen", ] [[package]] name = "kernel32-sys" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "kv-log-macro" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c54d9f465d530a752e6ebdc217e081a7a614b48cb200f6f0aee21ba6bc9aabb" +dependencies = [ + "log", ] [[package]] name = "language-tags" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" [[package]] name = "linked-hash-map" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" [[package]] name = "linux-embedded-hal" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "795096c0eecb0622afb591c3e1a97b1ba046688a7689957b70b8eee9cac8fb84" dependencies = [ - "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "i2cdev 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "spidev 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sysfs_gpio 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cast", + "embedded-hal", + "i2cdev", + "spidev", + "sysfs_gpio", ] [[package]] name = "lock_api" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" dependencies = [ - "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "owning_ref", + "scopeguard 0.3.3", ] [[package]] name = "lock_api" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" dependencies = [ - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0", ] [[package]] name = "log" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "lru-cache" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" dependencies = [ - "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map", ] [[package]] name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" [[package]] name = "maybe-uninit" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223" [[package]] name = "memoffset" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3", ] [[package]] name = "mime" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "mime_guess" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" dependencies = [ - "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mime", + "unicase", ] [[package]] name = "miniz_oxide" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5" dependencies = [ - "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "adler32", ] [[package]] name = "mio" version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab", + "winapi 0.2.8", ] [[package]] name = "mio-uds" version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" dependencies = [ - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec", + "libc", + "mio", ] [[package]] name = "miow" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", ] [[package]] name = "mpd" version = "0.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a20784da57fa01bf7910a5da686d9f39ff37feaa774856b71f050e4331bf82" dependencies = [ - "bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "bufstream", + "rustc-serialize", + "time", ] [[package]] name = "native-tls" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.28 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.54 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", ] [[package]] name = "nb" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1411551beb3c11dedfb0a90a0fa256b47d28b9ec2cdff34c25a2fa59e45dbdc" [[package]] name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "winapi 0.3.8", ] [[package]] name = "nix" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a7bb1da2be7da3cbffda73fc681d509ffd9e665af478d2bee1907cee0bc64b2" dependencies = [ - "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.4.0", + "cfg-if", + "libc", + "rustc_version 0.1.7", + "semver 0.1.20", + "void", ] [[package]] name = "nix" version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" +dependencies = [ + "bitflags 1.2.1", + "cc", + "cfg-if", + "libc", + "void", +] + +[[package]] +name = "nix" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1", + "cc", + "cfg-if", + "libc", + "void", ] [[package]] name = "nodrop" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" [[package]] name = "nom" version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" dependencies = [ - "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", + "version_check 0.1.5", ] [[package]] name = "num" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" dependencies = [ - "num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", ] [[package]] name = "num-bigint" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0", + "num-integer", + "num-traits", ] [[package]] name = "num-complex" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0", + "num-traits", ] [[package]] name = "num-integer" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0", + "num-traits", ] [[package]] name = "num-iter" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00" dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0", + "num-integer", + "num-traits", ] [[package]] name = "num-rational" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da4dc79f9e6c81bef96148c8f6b8e72ad4541caa4a24373e900a36da07de03a3" dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0", + "num-bigint", + "num-integer", + "num-traits", ] [[package]] name = "num-traits" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0", ] [[package]] name = "num_cpus" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" dependencies = [ - "hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi", + "libc", ] +[[package]] +name = "once_cell" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b" + [[package]] name = "openssl" version = "0.10.28" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "973293749822d7dd6370d6da1e523b0d1db19f06c459134c658b2a4261378b52" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.54 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1", + "cfg-if", + "foreign-types", + "lazy_static", + "libc", + "openssl-sys", ] [[package]] name = "openssl-probe" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-sys" version = "0.9.54" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1024c0a59774200a555087a6da3f253a9095a5f344e353b212ac4c8b8e450986" dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0", + "cc", + "libc", + "pkg-config", + "vcpkg", ] [[package]] name = "ordered-float" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518" dependencies = [ - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits", ] [[package]] name = "owning_ref" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" dependencies = [ - "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "stable_deref_trait", ] [[package]] name = "pagecache" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74a701d13e2f3ee32a50be43321da8f712cf1e6e9ff0e2be66ab7f5c6598a16a" dependencies = [ - "bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "historian 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "bincode", + "crc32fast", + "crossbeam-epoch 0.7.2", + "crossbeam-utils 0.6.6", + "fs2", + "futures 0.1.29", + "fxhash", + "hashbrown", + "historian", + "lazy_static", + "libc", + "log", + "rayon", + "serde", ] [[package]] name = "parking_lot" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" dependencies = [ - "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.1.5", + "parking_lot_core 0.4.0", ] [[package]] name = "parking_lot" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" dependencies = [ - "lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.3.3", + "parking_lot_core 0.6.2", + "rustc_version 0.2.3", ] [[package]] name = "parking_lot" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" dependencies = [ - "lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.3.3", + "parking_lot_core 0.7.0", ] [[package]] name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "rand 0.6.5", + "rustc_version 0.2.3", + "smallvec 0.6.13", + "winapi 0.3.8", ] [[package]] name = "parking_lot_core" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "cloudabi", + "libc", + "redox_syscall", + "rustc_version 0.2.3", + "smallvec 0.6.13", + "winapi 0.3.8", ] [[package]] name = "parking_lot_core" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "cloudabi", + "libc", + "redox_syscall", + "smallvec 1.2.0", + "winapi 0.3.8", ] [[package]] name = "percent-encoding" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" [[package]] name = "percent-encoding" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "philipshue" version = "0.3.2" source = "git+https://github.com/dskleingeld/philipshue#68eeaf2f006accaaa2cf289a992e347a92b5b013" dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0", + "reqwest 0.9.24", + "serde", + "serde_derive", + "serde_json", ] [[package]] name = "pin-project" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7804a463a8d9572f13453c516a5faea534a2403d7ced2f0c7e100eeff072772c" dependencies = [ - "pin-project-internal 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-internal", ] [[package]] name = "pin-project-internal" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385322a45f2ecf3410c68d2a549a4a2685e8051d0f278e39743ff4e451cb9b3f" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8", + "quote 1.0.2", + "syn 1.0.14", ] [[package]] name = "pin-project-lite" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" [[package]] name = "pin-utils" version = "0.1.0-alpha.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" [[package]] name = "pkg-config" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" [[package]] name = "ppv-lite86" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" [[package]] name = "proc-macro-error" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "875077759af22fa20b610ad4471d8155b321c89c3f2785526c9839b099be4e0a" dependencies = [ - "proc-macro-error-attr 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustversion 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error-attr", + "proc-macro2 1.0.8", + "quote 1.0.2", + "rustversion", + "syn 1.0.14", ] [[package]] name = "proc-macro-error-attr" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5717d9fa2664351a01ed73ba5ef6df09c01a521cb42cb65a061432a826f3c7a" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustversion 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", - "syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8", + "quote 1.0.2", + "rustversion", + "syn 1.0.14", + "syn-mid", ] [[package]] name = "proc-macro-hack" version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8", + "quote 1.0.2", + "syn 1.0.14", ] [[package]] name = "proc-macro-nested" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" [[package]] name = "proc-macro2" version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0", ] [[package]] name = "proc-macro2" version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548" dependencies = [ - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0", ] [[package]] name = "publicsuffix" version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bbaa49075179162b49acac1c6aa45fb4dafb5f13cf6794276d77bc7fd95757b" dependencies = [ - "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.1", + "idna 0.2.0", + "lazy_static", + "regex", + "url 2.1.1", ] [[package]] name = "quick-error" version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30", ] [[package]] name = "quote" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8", ] [[package]] name = "rand" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "winapi 0.3.8", ] [[package]] name = "rand" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7", + "libc", + "rand_chacha 0.1.1", + "rand_core 0.4.2", + "rand_hc 0.1.0", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi 0.3.8", ] [[package]] name = "rand" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", + "libc", + "rand_chacha 0.2.1", + "rand_core 0.5.1", + "rand_hc 0.2.0", ] [[package]] name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7", + "rand_core 0.3.1", ] [[package]] name = "rand_chacha" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" dependencies = [ - "c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "c2-chacha", + "rand_core 0.5.1", ] [[package]] name = "rand_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" dependencies = [ - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2", ] [[package]] name = "rand_core" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" [[package]] name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", ] [[package]] name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1", ] [[package]] name = "rand_hc" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1", ] [[package]] name = "rand_isaac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1", ] [[package]] name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "rand_core 0.4.2", + "winapi 0.3.8", ] [[package]] name = "rand_os" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi 0.3.8", ] [[package]] name = "rand_pcg" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7", + "rand_core 0.4.2", ] [[package]] name = "rand_xorshift" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1", ] [[package]] name = "rayon" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" dependencies = [ - "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque", + "either", + "rayon-core", ] [[package]] name = "rayon-core" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" dependencies = [ - "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils 0.7.0", + "lazy_static", + "num_cpus", ] [[package]] name = "rdrand" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1", ] [[package]] name = "redox_syscall" version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" [[package]] name = "redox_users" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431" dependencies = [ - "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "rust-argon2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", + "redox_syscall", + "rust-argon2", ] [[package]] name = "regex" version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" dependencies = [ - "aho-corasick 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", ] [[package]] name = "regex-syntax" version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b28dfe3fe9badec5dbf0a79a9cccad2cfc2ab5484bdb3e44cbd1ae8b3ba2be06" [[package]] name = "remove_dir_all" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8", ] [[package]] name = "reqwest" version = "0.9.24" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-rustls 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-rustls 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +checksum = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab" +dependencies = [ + "base64 0.10.1", + "bytes 0.4.12", + "cookie", + "cookie_store", + "encoding_rs", + "flate2", + "futures 0.1.29", + "http 0.1.21", + "hyper 0.12.35", + "hyper-rustls", + "hyper-tls 0.3.2", + "log", + "mime", + "mime_guess", + "native-tls", + "rustls", + "serde", + "serde_json", + "serde_urlencoded 0.5.5", + "time", + "tokio 0.1.22", + "tokio-executor", + "tokio-io", + "tokio-rustls 0.10.3", + "tokio-threadpool", + "tokio-timer", + "url 1.7.2", + "uuid", + "webpki-roots", + "winreg 0.6.2", ] [[package]] name = "reqwest" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-tls 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-futures 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", - "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +checksum = "c0e798e19e258bf6c30a304622e3e9ac820e483b06a1857a026e1f109b113fe4" +dependencies = [ + "base64 0.11.0", + "bytes 0.5.4", + "encoding_rs", + "futures-core", + "futures-util", + "http 0.2.0", + "http-body 0.3.1", + "hyper 0.13.2", + "hyper-tls 0.4.1", + "js-sys", + "lazy_static", + "log", + "mime", + "mime_guess", + "native-tls", + "percent-encoding 2.1.0", + "pin-project-lite", + "serde", + "serde_urlencoded 0.6.1", + "time", + "tokio 0.2.11", + "tokio-tls", + "url 2.1.1", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg 0.6.2", ] [[package]] name = "resolv-conf" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" dependencies = [ - "hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hostname", + "quick-error", ] [[package]] name = "retry" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ac83b31b3831aa4b07608db4170f6555ab12942197037c38570dc4c5ba5028" dependencies = [ - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5", ] [[package]] name = "ring" version = "0.16.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "741ba1704ae21999c00942f9f5944f801e977f54302af346b596287599ad1862" dependencies = [ - "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "lazy_static", + "libc", + "spin", + "untrusted", + "web-sys", + "winapi 0.3.8", ] [[package]] name = "rust-argon2" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" dependencies = [ - "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0", + "blake2b_simd", + "constant_time_eq", + "crossbeam-utils 0.7.0", ] [[package]] name = "rustc-demangle" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" [[package]] name = "rustc-serialize" version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" [[package]] name = "rustc_version" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" dependencies = [ - "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.1.20", ] [[package]] name = "rustc_version" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0", ] [[package]] name = "rustls" version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.11 (registry+https://github.com/rust-lang/crates.io-index)", - "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.10.1", + "log", + "ring", + "sct", + "webpki", ] [[package]] name = "rustversion" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3bba175698996010c4f6dce5e7f173b6eb781fce25d2cfc45e27091ce0b79f6" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8", + "quote 1.0.2", + "syn 1.0.14", ] [[package]] name = "ryu" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" [[package]] name = "schannel" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507a9e6e8ffe0a4e0ebb9a10293e62fdf7657c06f1b8bb07a8fcf697d2abf295" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "winapi 0.3.8", ] [[package]] name = "scoped-tls" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" [[package]] name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" [[package]] name = "scopeguard" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" [[package]] name = "sct" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" dependencies = [ - "ring 0.16.11 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ring", + "untrusted", ] [[package]] name = "security-framework" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df" dependencies = [ - "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", ] [[package]] name = "security-framework-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" dependencies = [ - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys", ] [[package]] name = "semver" version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" [[package]] name = "semver" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver-parser", ] [[package]] name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" dependencies = [ - "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive", ] [[package]] name = "serde-value" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a663f873dedc4eac1a559d4c6bc0d0b2c34dc5ac4702e105014b8281489e44f" dependencies = [ - "ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "ordered-float", + "serde", ] [[package]] name = "serde_derive" version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8", + "quote 1.0.2", + "syn 1.0.14", ] [[package]] name = "serde_json" version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15913895b61e0be854afd32fd4163fcd2a3df34142cf2cb961b310ce694cbf90" dependencies = [ - "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa", + "ryu", + "serde", ] [[package]] name = "serde_urlencoded" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" dependencies = [ - "dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa", + "itoa", + "serde", + "url 1.7.2", ] [[package]] name = "serde_urlencoded" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" dependencies = [ - "dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa", + "itoa", + "serde", + "url 2.1.1", ] [[package]] name = "serde_yaml" version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" dependencies = [ - "dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa", + "linked-hash-map", + "serde", + "yaml-rust", ] [[package]] name = "sha1" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" [[package]] name = "signal-hook-registry" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41" dependencies = [ - "arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "arc-swap", + "libc", ] [[package]] name = "slab" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "sled" version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb8c32cb0e34e67ad74fae1a77f4635d0cc7ffc873088a0136f3c4849336d71" dependencies = [ - "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crc32fast", + "crossbeam-epoch 0.8.0", + "crossbeam-utils 0.7.0", + "fs2", + "fxhash", + "libc", + "log", + "parking_lot 0.10.0", ] [[package]] name = "smallvec" version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" dependencies = [ - "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "maybe-uninit", ] [[package]] name = "smallvec" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" [[package]] name = "socket2" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "redox_syscall", + "winapi 0.3.8", ] [[package]] name = "sourcefile" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" [[package]] name = "spidev" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ba01d3ef92a37e898fecac76cd3e1b33c999395e2d70787608d9678c4293e04" dependencies = [ - "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.3.3", + "libc", + "nix 0.6.0", ] [[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "stable_deref_trait" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" [[package]] name = "string" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", ] [[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1bcbed7d48956fcbb5d80c6b95aedb553513de0a1b451ea92679d999c010e98" dependencies = [ - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clap", + "lazy_static", + "structopt-derive", ] [[package]] name = "structopt-derive" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "095064aa1f5b94d14e635d0a5684cf140c43ae40a0fd990708d38f5d669e5f64" dependencies = [ - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-error 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "heck", + "proc-macro-error", + "proc-macro2 1.0.8", + "quote 1.0.2", + "syn 1.0.14", ] [[package]] name = "syn" version = "0.15.44" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", ] [[package]] name = "syn" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8", + "quote 1.0.2", + "unicode-xid 0.2.0", ] [[package]] name = "syn-mid" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8", + "quote 1.0.2", + "syn 1.0.14", ] [[package]] name = "synstructure" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8", + "quote 1.0.2", + "syn 1.0.14", + "unicode-xid 0.2.0", ] [[package]] name = "sysfs_gpio" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24961a55846623d8e4f6cec38718945116fed8d6970336a7110710a07aa9b5d1" dependencies = [ - "nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.14.1", ] [[package]] name = "telegram-bot" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d5eca220fcf23ad25b269991cdc8f8d421d97634c7f9e10b4c5dcdaa913b6" dependencies = [ - "antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "telegram-bot-raw 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "antidote", + "error-chain 0.11.0", + "futures 0.1.29", + "hyper 0.12.35", + "hyper-tls 0.3.2", + "telegram-bot-raw", + "tokio-core", ] [[package]] name = "telegram-bot-raw" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65578f718dadd17347cd60d45609a7e1d57a52b459797957002b922349ee9744" dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde-value 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0", + "serde", + "serde-value", + "serde_derive", + "serde_json", ] [[package]] name = "tempfile" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "rand 0.7.3", + "redox_syscall", + "remove_dir_all", + "winapi 0.3.8", ] [[package]] name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width", ] [[package]] name = "thread_local" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", ] [[package]] name = "threadpool" version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" dependencies = [ - "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus", ] [[package]] name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "redox_syscall", + "winapi 0.3.8", ] [[package]] name = "tokio" version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "mio", + "num_cpus", + "tokio-codec", + "tokio-current-thread", + "tokio-executor", + "tokio-fs", + "tokio-io", + "tokio-reactor", + "tokio-sync", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer", + "tokio-udp", + "tokio-uds", ] [[package]] name = "tokio" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fdd17989496f49cdc57978c96f0c9fe5e4a58a8bddc6813c449a4624f6a030b" dependencies = [ - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4", + "fnv", + "futures-core", + "iovec", + "lazy_static", + "libc", + "memchr", + "mio", + "mio-uds", + "num_cpus", + "pin-project-lite", + "signal-hook-registry", + "slab", + "winapi 0.3.8", ] [[package]] name = "tokio-buf" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "either", + "futures 0.1.29", ] [[package]] name = "tokio-codec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "tokio-io", ] [[package]] name = "tokio-core" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "iovec", + "log", + "mio", + "scoped-tls", + "tokio 0.1.22", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-timer", ] [[package]] name = "tokio-current-thread" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29", + "tokio-executor", ] [[package]] name = "tokio-executor" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" dependencies = [ - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0", + "futures 0.1.29", ] [[package]] name = "tokio-fs" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29", + "tokio-io", + "tokio-threadpool", ] [[package]] name = "tokio-io" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "log", ] [[package]] name = "tokio-reactor" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" dependencies = [ - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0", + "futures 0.1.29", + "lazy_static", + "log", + "mio", + "num_cpus", + "parking_lot 0.9.0", + "slab", + "tokio-executor", + "tokio-io", + "tokio-sync", ] [[package]] name = "tokio-rustls" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7cf08f990090abd6c6a73cab46fed62f85e8aef8b99e4b918a9f4a637f0676" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "iovec", + "rustls", + "tokio-io", + "webpki", ] [[package]] name = "tokio-rustls" version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "141afec0978abae6573065a48882c6bae44c5cc61db9b511ac4abf6a09bfd9cc" dependencies = [ - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core", + "rustls", + "tokio 0.2.11", + "webpki", ] [[package]] name = "tokio-signal" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0c34c6e548f101053321cba3da7cbb87a610b85555884c41b07da2eb91aff12" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29", + "libc", + "mio", + "mio-uds", + "signal-hook-registry", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "winapi 0.3.8", ] [[package]] name = "tokio-sync" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" dependencies = [ - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv", + "futures 0.1.29", ] [[package]] name = "tokio-tcp" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "iovec", + "mio", + "tokio-io", + "tokio-reactor", ] [[package]] name = "tokio-threadpool" version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" dependencies = [ - "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils 0.7.0", + "futures 0.1.29", + "lazy_static", + "log", + "num_cpus", + "slab", + "tokio-executor", ] [[package]] name = "tokio-timer" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" dependencies = [ - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0", + "futures 0.1.29", + "slab", + "tokio-executor", ] [[package]] name = "tokio-tls" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bde02a3a5291395f59b06ec6945a3077602fac2b07eeeaf0dee2122f3619828" dependencies = [ - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls", + "tokio 0.2.11", ] [[package]] name = "tokio-udp" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "log", + "mio", + "tokio-codec", + "tokio-io", + "tokio-reactor", ] [[package]] name = "tokio-uds" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5076db410d6fdc6523df7595447629099a1fdc47b3d9f896220780fa48faf798" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "iovec", + "libc", + "log", + "mio", + "mio-uds", + "tokio-codec", + "tokio-io", + "tokio-reactor", ] [[package]] name = "tokio-util" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" dependencies = [ - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio 0.2.11", ] [[package]] name = "tower-service" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b32f72af77f1bfe3d3d4da8516a238ebe7039b51dd8637a09841ac7f16d2c987" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29", ] [[package]] name = "tower-service" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" [[package]] name = "trust-dns-proto" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0838272e89f1c693b4df38dc353412e389cf548ceed6f9fd1af5a8d6e0e7cf74" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "failure", + "futures 0.1.29", + "idna 0.1.5", + "lazy_static", + "log", + "rand 0.5.6", + "smallvec 0.6.13", + "socket2", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-tcp", + "tokio-timer", + "tokio-udp", + "url 1.7.2", ] [[package]] name = "trust-dns-proto" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09144f0992b0870fa8d2972cc069cbf1e3c0fda64d1f3d45c4d68d0e0b52ad4e" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "failure", + "futures 0.1.29", + "idna 0.1.5", + "lazy_static", + "log", + "rand 0.5.6", + "smallvec 0.6.13", + "socket2", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-tcp", + "tokio-timer", + "tokio-udp", + "url 1.7.2", ] [[package]] name = "trust-dns-proto" version = "0.18.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a7f3a2ab8a919f5eca52a468866a67ed7d3efa265d48a652a9a3452272b413f" dependencies = [ - "async-trait 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "enum-as-inner 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "async-trait", + "enum-as-inner", + "failure", + "futures 0.3.4", + "idna 0.2.0", + "lazy_static", + "log", + "rand 0.7.3", + "smallvec 1.2.0", + "socket2", + "tokio 0.2.11", + "url 2.1.1", ] [[package]] name = "trust-dns-resolver" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9f877f7a1ad821ab350505e1f1b146a4960402991787191d6d8cab2ce2de2c" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "failure", + "futures 0.1.29", + "ipconfig 0.1.9", + "lazy_static", + "log", + "lru-cache", + "resolv-conf", + "smallvec 0.6.13", + "tokio 0.1.22", + "trust-dns-proto 0.6.3", ] [[package]] name = "trust-dns-resolver" version = "0.18.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-proto 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "failure", + "futures 0.3.4", + "ipconfig 0.2.1", + "lazy_static", + "log", + "lru-cache", + "resolv-conf", + "smallvec 1.2.0", + "tokio 0.2.11", + "trust-dns-proto 0.18.0-alpha.2", ] [[package]] name = "try-lock" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" [[package]] name = "try_from" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "unicase" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" dependencies = [ - "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.1", ] [[package]] name = "unicode-bidi" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "matches", ] [[package]] name = "unicode-normalization" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" dependencies = [ - "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0", ] [[package]] name = "unicode-segmentation" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" [[package]] name = "unicode-width" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" [[package]] name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" [[package]] name = "untrusted" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece" [[package]] name = "url" version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" dependencies = [ - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.5", + "matches", + "percent-encoding 1.0.1", ] [[package]] name = "url" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" dependencies = [ - "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.2.0", + "matches", + "percent-encoding 2.1.0", ] [[package]] name = "uuid" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" dependencies = [ - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5", ] [[package]] name = "v_escape" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "660b101c07b5d0863deb9e7fb3138777e858d6d2a79f9e6049a27d1cc77c6da6" dependencies = [ - "v_escape_derive 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "v_escape_derive", ] [[package]] name = "v_escape_derive" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae" dependencies = [ - "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "nom", + "proc-macro2 1.0.8", + "quote 1.0.2", + "syn 1.0.14", ] [[package]] name = "v_htmlescape" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33e939c0d8cf047514fb6ba7d5aac78bc56677a6938b2ee67000b91f2e97e41" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "v_escape 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "v_escape", ] [[package]] name = "vcpkg" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" [[package]] name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" [[package]] name = "version_check" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" [[package]] name = "version_check" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" [[package]] name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "want" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29", + "log", + "try-lock", ] [[package]] name = "want" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" dependencies = [ - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log", + "try-lock", ] [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasm-bindgen" version = "0.2.58" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5205e9afdf42282b192e2310a5b463a6d1c1d774e30dc3c791ac37ab42d2616c" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "serde", + "serde_json", + "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.58" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11cdb95816290b525b32587d76419facd99662a07e59d3cdb560488a819d9a45" dependencies = [ - "bumpalo 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "bumpalo", + "lazy_static", + "log", + "proc-macro2 1.0.8", + "quote 1.0.2", + "syn 1.0.14", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bbdd49e3e28b40dec6a9ba8d17798245ce32b019513a845369c641b275135d9" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.58" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "574094772ce6921576fb6f2e3f7497b8a76273b6db092be18fc48a082de09dc3" dependencies = [ - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro-support 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2", + "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.58" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e85031354f25eaebe78bb7db1c3d86140312a911a106b2e29f9cc440ce3e7668" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8", + "quote 1.0.2", + "syn 1.0.14", + "wasm-bindgen-backend", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.58" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e7e61fc929f4c0dddb748b102ebf9f632e2b8d739f2016542b4de2965a9601" [[package]] name = "wasm-bindgen-webidl" version = "0.2.58" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef012a0d93fc0432df126a8eaf547b2dce25a8ce9212e1d3cbeef5c11157975d" dependencies = [ - "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "anyhow", + "heck", + "log", + "proc-macro2 1.0.8", + "quote 1.0.2", + "syn 1.0.14", + "wasm-bindgen-backend", + "weedle", ] [[package]] name = "web-sys" version = "0.3.35" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaf97caf6aa8c2b1dac90faf0db529d9d63c93846cca4911856f78a83cebf53b" dependencies = [ - "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", - "sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-webidl 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "anyhow", + "js-sys", + "sourcefile", + "wasm-bindgen", + "wasm-bindgen-webidl", ] [[package]] name = "webpki" version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f50e1972865d6b1adb54167d1c8ed48606004c2c9d0ea5f1eeb34d95e863ef" dependencies = [ - "ring 0.16.11 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ring", + "untrusted", ] [[package]] name = "webpki-roots" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a262ae37dd9d60f60dd473d1158f9fbebf110ba7b6a5051c8160460f6043718b" dependencies = [ - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki", ] [[package]] name = "weedle" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164" dependencies = [ - "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "nom", ] [[package]] name = "widestring" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" [[package]] name = "widestring" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6" [[package]] name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[package]] name = "winapi" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "winreg" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a27a759395c1195c4cc5cda607ef6f8f6498f64e78f7900f5de0a127a424704a" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8", ] [[package]] name = "winreg" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8", ] [[package]] name = "winutil" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8", ] [[package]] name = "ws2_32-sys" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8", + "winapi-build", ] [[package]] name = "yaml-rust" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" dependencies = [ - "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[metadata] -"checksum actix 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c616db5fa4b0c40702fb75201c2af7f8aa8f3a2e2c1dda3b0655772aa949666" -"checksum actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09e55f0a5c2ca15795035d90c46bd0e73a5123b72f68f12596d6ba5282051380" -"checksum actix-connect 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c95cc9569221e9802bf4c377f6c18b90ef10227d787611decf79fd47d2a8e76c" -"checksum actix-files 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "301482841d3d74483a446ead63cb7d362e187d2c8b603f13d91995621ea53c46" -"checksum actix-http 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c16664cc4fdea8030837ad5a845eb231fb93fc3c5c171edfefb52fad92ce9019" -"checksum actix-identity 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a379b0639c293292d71defb8cc1f94c87b7705c904adf044338ad392df77c7a" -"checksum actix-macros 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21705adc76bbe4bc98434890e73a89cd00c6015e5704a60bb6eea6c3b72316b6" -"checksum actix-net 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8bebfbe6629e0131730746718c9e032b58f02c6ce06ed7c982b9fef6c8545acd" -"checksum actix-router 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9d7a10ca4d94e8c8e7a87c5173aba1b97ba9a6563ca02b0e1cd23531093d3ec8" -"checksum actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6a0a55507046441a496b2f0d26a84a65e67c8cafffe279072412f624b5fb6d" -"checksum actix-server 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "51d3455eaac03ca3e49d7b822eb35c884b861f715627254ccbe4309d08f1841a" -"checksum actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3e4fc95dfa7e24171b2d0bb46b85f8ab0e8499e4e3caec691fc4ea65c287564" -"checksum actix-testing 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48494745b72d0ea8ff0cf874aaf9b622a3ee03d7081ee0c04edea4f26d32c911" -"checksum actix-threadpool 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4082192601de5f303013709ff84d81ca6a1bc4af7fb24f367a500a23c6e84e" -"checksum actix-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4e5b4faaf105e9a6d389c606c298dcdb033061b00d532af9df56ff3a54995a8" -"checksum actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fcf8f5631bf01adec2267808f00e228b761c60c0584cc9fa0b5364f41d147f4e" -"checksum actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3158e822461040822f0dbf1735b9c2ce1f95f93b651d7a7aded00b1efbb1f635" -"checksum actix-web-codegen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de0878b30e62623770a4713a6338329fd0119703bafc211d3e4144f4d4a7bdd5" -"checksum actix-web-httpauth 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7cccccfac88ec8c0475538f466384b90e4395a7420288f5384baf1c51fad73ec" -"checksum actix_derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4300e9431455322ae393d43a2ba1ef96b8080573c0fc23b196219efedfb6ba69" -"checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" -"checksum aho-corasick 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "743ad5a418686aad3b87fd14c43badd828cf26e214a00f92a384291cf22e1811" -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" -"checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" -"checksum arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d7b8a9123b8027467bce0099fe556c628a53c8d83df0507084c31e9ba2e39aff" -"checksum arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" -"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" -"checksum async-trait 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "750b1c38a1dfadd108da0f01c08f4cdc7ff1bb39b325f9c82cc972361780a6e1" -"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" -"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" -"checksum awc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7601d4d1d7ef2335d6597a41b5fe069f6ab799b85f53565ab390e7b7065aac5" -"checksum backtrace 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "7f80256bc78f67e7df7e36d77366f636ed976895d91fe2ab9efa3973e8fe8c4f" -"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" -"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" -"checksum bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" -"checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" -"checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" -"checksum bme280 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d48076b7293afafab5ff93e3db57435c567f1fc72755c27d377f7e96ea66678d" -"checksum brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" -"checksum brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" -"checksum bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" -"checksum bumpalo 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742" -"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" -"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -"checksum bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" -"checksum bytestring 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fc267467f58ef6cc8874064c62a0423eb0d099362c8a23edd1c6d044f46eead4" -"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" -"checksum cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" -"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" -"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" -"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" -"checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" -"checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" -"checksum copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ff9c56c9fb2a49c05ef0e431485a22400af20d33226dc0764d891d09e724127" -"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" -"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" -"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" -"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" -"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" -"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" -"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" -"checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" -"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" -"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" -"checksum ct-logs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d3686f5fa27dbc1d76c751300376e167c5a43387f44bb451fd1c24776e49113" -"checksum derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8" -"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" -"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" -"checksum dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" -"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" -"checksum embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ee4908a155094da7723c2d60d617b820061e3b4efcc3d9e293d206a5a76c170b" -"checksum encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28" -"checksum enum-as-inner 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "900a6c7fbe523f4c2884eaf26b57b81bb69b6810a01a236390a7ac021d09492e" -"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" -"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" -"checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" -"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" -"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" -"checksum flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f" -"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" -"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -"checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" -"checksum futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5c329ae8753502fb44ae4fc2b622fa2a94652c41e795143765ba0927f92ab780" -"checksum futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8" -"checksum futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a" -"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum futures-executor 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba" -"checksum futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6" -"checksum futures-macro 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7" -"checksum futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6" -"checksum futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27" -"checksum futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5" -"checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" -"checksum gpio-cdev 0.2.1 (git+https://github.com/rust-embedded/gpio-cdev)" = "" -"checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" -"checksum h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9433d71e471c1736fd5a61b671fc0b148d7a2992f666c958d03cd8feb3b88d1" -"checksum hashbrown 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "29fba9abe4742d586dfd0c06ae4f7e73a1c2d86b856933509b269d82cdf06e18" -"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -"checksum hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772" -"checksum historian 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f653416eb756b69642a1f1498817970fafe409998a849622c27cc5b1b7df989c" -"checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" -"checksum http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" -"checksum http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b708cc7f06493459026f53b9a61a7a121a5d1ec6238dee58ea4941132b30156b" -"checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" -"checksum http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" -"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" -"checksum hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)" = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" -"checksum hyper 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fa1c527bbc634be72aa7ba31e4e4def9bbb020f5416916279b7c705cd838893e" -"checksum hyper-rustls 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "719d85c7df4a7f309a77d145340a063ea929dcb2e025bae46a80345cffec2952" -"checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" -"checksum hyper-tls 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3adcd308402b9553630734e9c36b77a7e48b3821251ca2493e8cd596763aafaa" -"checksum i2cdev 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0eb3d9b6b02dc2508ee23439170004e44344bab9d53a490eb1f64c885b5003" -"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -"checksum indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" -"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -"checksum ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "08f7eadeaf4b52700de180d147c4805f199854600b36faa963d91114827b2ffc" -"checksum ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa79fa216fbe60834a9c0737d7fcd30425b32d1c58854663e24d4c4b328ed83f" -"checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" -"checksum js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "7889c7c36282151f6bf465be4700359318aef36baa951462382eae49e9577cf9" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" -"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" -"checksum linux-embedded-hal 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "795096c0eecb0622afb591c3e1a97b1ba046688a7689957b70b8eee9cac8fb84" -"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" -"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" -"checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" -"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" -"checksum memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223" -"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" -"checksum mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" -"checksum mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" -"checksum miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5" -"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" -"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" -"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum mpd 0.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "57a20784da57fa01bf7910a5da686d9f39ff37feaa774856b71f050e4331bf82" -"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" -"checksum nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b1411551beb3c11dedfb0a90a0fa256b47d28b9ec2cdff34c25a2fa59e45dbdc" -"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -"checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" -"checksum nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a7bb1da2be7da3cbffda73fc681d509ffd9e665af478d2bee1907cee0bc64b2" -"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" -"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" -"checksum num 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" -"checksum num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" -"checksum num-complex 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" -"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" -"checksum num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00" -"checksum num-rational 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "da4dc79f9e6c81bef96148c8f6b8e72ad4541caa4a24373e900a36da07de03a3" -"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" -"checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" -"checksum openssl 0.10.28 (registry+https://github.com/rust-lang/crates.io-index)" = "973293749822d7dd6370d6da1e523b0d1db19f06c459134c658b2a4261378b52" -"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.54 (registry+https://github.com/rust-lang/crates.io-index)" = "1024c0a59774200a555087a6da3f253a9095a5f344e353b212ac4c8b8e450986" -"checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518" -"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" -"checksum pagecache 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74a701d13e2f3ee32a50be43321da8f712cf1e6e9ff0e2be66ab7f5c6598a16a" -"checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" -"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" -"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" -"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -"checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" -"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" -"checksum philipshue 0.3.2 (git+https://github.com/dskleingeld/philipshue)" = "" -"checksum pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7804a463a8d9572f13453c516a5faea534a2403d7ced2f0c7e100eeff072772c" -"checksum pin-project-internal 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "385322a45f2ecf3410c68d2a549a4a2685e8051d0f278e39743ff4e451cb9b3f" -"checksum pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" -"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" -"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" -"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" -"checksum proc-macro-error 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "875077759af22fa20b610ad4471d8155b321c89c3f2785526c9839b099be4e0a" -"checksum proc-macro-error-attr 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c5717d9fa2664351a01ed73ba5ef6df09c01a521cb42cb65a061432a826f3c7a" -"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" -"checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" -"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548" -"checksum publicsuffix 1.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3bbaa49075179162b49acac1c6aa45fb4dafb5f13cf6794276d77bc7fd95757b" -"checksum quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" -"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" -"checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431" -"checksum regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" -"checksum regex-syntax 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b28dfe3fe9badec5dbf0a79a9cccad2cfc2ab5484bdb3e44cbd1ae8b3ba2be06" -"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -"checksum reqwest 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0e798e19e258bf6c30a304622e3e9ac820e483b06a1857a026e1f109b113fe4" -"checksum reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab" -"checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" -"checksum retry 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ac83b31b3831aa4b07608db4170f6555ab12942197037c38570dc4c5ba5028" -"checksum ring 0.16.11 (registry+https://github.com/rust-lang/crates.io-index)" = "741ba1704ae21999c00942f9f5944f801e977f54302af346b596287599ad1862" -"checksum rust-argon2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" -"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" -"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" -"checksum rustversion 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bba175698996010c4f6dce5e7f173b6eb781fce25d2cfc45e27091ce0b79f6" -"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" -"checksum schannel 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "507a9e6e8ffe0a4e0ebb9a10293e62fdf7657c06f1b8bb07a8fcf697d2abf295" -"checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" -"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" -"checksum security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df" -"checksum security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" -"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" -"checksum serde-value 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7a663f873dedc4eac1a559d4c6bc0d0b2c34dc5ac4702e105014b8281489e44f" -"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" -"checksum serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "15913895b61e0be854afd32fd4163fcd2a3df34142cf2cb961b310ce694cbf90" -"checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" -"checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" -"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" -"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" -"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41" -"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum sled 0.30.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb8c32cb0e34e67ad74fae1a77f4635d0cc7ffc873088a0136f3c4849336d71" -"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" -"checksum smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" -"checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" -"checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" -"checksum spidev 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ba01d3ef92a37e898fecac76cd3e1b33c999395e2d70787608d9678c4293e04" -"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" -"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum structopt 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "a1bcbed7d48956fcbb5d80c6b95aedb553513de0a1b451ea92679d999c010e98" -"checksum structopt-derive 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "095064aa1f5b94d14e635d0a5684cf140c43ae40a0fd990708d38f5d669e5f64" -"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -"checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5" -"checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" -"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" -"checksum sysfs_gpio 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "24961a55846623d8e4f6cec38718945116fed8d6970336a7110710a07aa9b5d1" -"checksum telegram-bot 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "225d5eca220fcf23ad25b269991cdc8f8d421d97634c7f9e10b4c5dcdaa913b6" -"checksum telegram-bot-raw 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65578f718dadd17347cd60d45609a7e1d57a52b459797957002b922349ee9744" -"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" -"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" -"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" -"checksum tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8fdd17989496f49cdc57978c96f0c9fe5e4a58a8bddc6813c449a4624f6a030b" -"checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" -"checksum tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" -"checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" -"checksum tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" -"checksum tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" -"checksum tokio-fs 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" -"checksum tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" -"checksum tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" -"checksum tokio-rustls 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2d7cf08f990090abd6c6a73cab46fed62f85e8aef8b99e4b918a9f4a637f0676" -"checksum tokio-rustls 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "141afec0978abae6573065a48882c6bae44c5cc61db9b511ac4abf6a09bfd9cc" -"checksum tokio-signal 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c34c6e548f101053321cba3da7cbb87a610b85555884c41b07da2eb91aff12" -"checksum tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" -"checksum tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" -"checksum tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" -"checksum tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" -"checksum tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7bde02a3a5291395f59b06ec6945a3077602fac2b07eeeaf0dee2122f3619828" -"checksum tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" -"checksum tokio-uds 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5076db410d6fdc6523df7595447629099a1fdc47b3d9f896220780fa48faf798" -"checksum tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" -"checksum tower-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b32f72af77f1bfe3d3d4da8516a238ebe7039b51dd8637a09841ac7f16d2c987" -"checksum tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" -"checksum trust-dns-proto 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2a7f3a2ab8a919f5eca52a468866a67ed7d3efa265d48a652a9a3452272b413f" -"checksum trust-dns-proto 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0838272e89f1c693b4df38dc353412e389cf548ceed6f9fd1af5a8d6e0e7cf74" -"checksum trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "09144f0992b0870fa8d2972cc069cbf1e3c0fda64d1f3d45c4d68d0e0b52ad4e" -"checksum trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a9f877f7a1ad821ab350505e1f1b146a4960402991787191d6d8cab2ce2de2c" -"checksum trust-dns-resolver 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f" -"checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -"checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" -"checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" -"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" -"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -"checksum untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece" -"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" -"checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" -"checksum v_escape 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "660b101c07b5d0863deb9e7fb3138777e858d6d2a79f9e6049a27d1cc77c6da6" -"checksum v_escape_derive 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae" -"checksum v_htmlescape 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e33e939c0d8cf047514fb6ba7d5aac78bc56677a6938b2ee67000b91f2e97e41" -"checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" -"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" -"checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -"checksum wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "5205e9afdf42282b192e2310a5b463a6d1c1d774e30dc3c791ac37ab42d2616c" -"checksum wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "11cdb95816290b525b32587d76419facd99662a07e59d3cdb560488a819d9a45" -"checksum wasm-bindgen-futures 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8bbdd49e3e28b40dec6a9ba8d17798245ce32b019513a845369c641b275135d9" -"checksum wasm-bindgen-macro 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "574094772ce6921576fb6f2e3f7497b8a76273b6db092be18fc48a082de09dc3" -"checksum wasm-bindgen-macro-support 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "e85031354f25eaebe78bb7db1c3d86140312a911a106b2e29f9cc440ce3e7668" -"checksum wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e7e61fc929f4c0dddb748b102ebf9f632e2b8d739f2016542b4de2965a9601" -"checksum wasm-bindgen-webidl 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ef012a0d93fc0432df126a8eaf547b2dce25a8ce9212e1d3cbeef5c11157975d" -"checksum web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "aaf97caf6aa8c2b1dac90faf0db529d9d63c93846cca4911856f78a83cebf53b" -"checksum webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1f50e1972865d6b1adb54167d1c8ed48606004c2c9d0ea5f1eeb34d95e863ef" -"checksum webpki-roots 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a262ae37dd9d60f60dd473d1158f9fbebf110ba7b6a5051c8160460f6043718b" -"checksum weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164" -"checksum widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" -"checksum widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a27a759395c1195c4cc5cda607ef6f8f6498f64e78f7900f5de0a127a424704a" -"checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" -"checksum winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e" -"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" + "linked-hash-map", +] diff --git a/Cargo.toml b/Cargo.toml index 51b841f9..c4b4d5cc 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,8 @@ live_server = [] [dependencies] futures = "0.3" +async-std = "1" + actix-web = { version = "2", features = ["rustls"] } actix-net = "0.2" actix-identity = "0.2" @@ -35,6 +37,7 @@ serde_yaml = "0.8" log = "0.4" gpio-cdev = { git = "https://github.com/rust-embedded/gpio-cdev", branch = "master" } +nix = "0.17" #tokio = "0.1.15" bincode = "1.0" diff --git a/deny.toml b/deny.toml new file mode 100644 index 00000000..acfbfb39 --- /dev/null +++ b/deny.toml @@ -0,0 +1,196 @@ +# This template contains all of the possible sections and their default values + +# Note that all fields that take a lint level have these possible values: +# * deny - An error will be produced and the check will fail +# * warn - A warning will be produced, but the check will not fail +# * allow - No warning or error will be produced, though in some cases a note +# will be + +# The values provided in this template are the default values that will be used +# when any section or field is not specified in your own configuration + +# If 1 or more target triples (and optionally, target_features) are specified, +# only the specified targets will be checked when running `cargo deny check`. +# This means, if a particular package is only ever used as a target specific +# dependency, such as, for example, the `nix` crate only being used via the +# `target_family = "unix"` configuration, that only having windows targets in +# this list would mean the nix crate, as well as any of its exclusive +# dependencies not shared by any other crates, would be ignored, as the target +# list here is effectively saying which targets you are building for. +targets = [ + # The triple can be any string, but only the target triples built in to + # rustc (as of 1.40) can be checked against actual config expressions + #{ triple = "x86_64-unknown-linux-musl" }, + # You can also specify which target_features you promise are enabled for a + # particular target. target_features are currently not validated against + # the actual valid features supported by the target architecture. + #{ triple = "wasm32-unknown-unknown", features = ["atomics"] }, +] + +# This section is considered when running `cargo deny check advisories` +# More documentation for the advisories section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html +[advisories] +# The path where the advisory database is cloned/fetched into +db-path = "~/.cargo/advisory-db" +# The url of the advisory database to use +db-url = "https://github.com/rustsec/advisory-db" +# The lint level for security vulnerabilities +vulnerability = "deny" +# The lint level for unmaintained crates +unmaintained = "warn" +# The lint level for crates that have been yanked from their source registry +yanked = "warn" +# The lint level for crates with security notices. Note that as of +# 2019-12-17 there are no security notice advisories in +# https://github.com/rustsec/advisory-db +notice = "warn" +# A list of advisory IDs to ignore. Note that ignored advisories will still +# output a note when they are encountered. +ignore = [ + #"RUSTSEC-0000-0000", +] +# Threshold for security vulnerabilities, any vulnerability with a CVSS score +# lower than the range specified will be ignored. Note that ignored advisories +# will still output a note when they are encountered. +# * None - CVSS Score 0.0 +# * Low - CVSS Score 0.1 - 3.9 +# * Medium - CVSS Score 4.0 - 6.9 +# * High - CVSS Score 7.0 - 8.9 +# * Critical - CVSS Score 9.0 - 10.0 +#severity-threshold = + +# This section is considered when running `cargo deny check licenses` +# More documentation for the licenses section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html +[licenses] +# The lint level for crates which do not have a detectable license +unlicensed = "deny" +# List of explictly allowed licenses +# See https://spdx.org/licenses/ for list of possible licenses +# [possible values: any SPDX 3.7 short identifier (+ optional exception)]. +allow = [ + "CC0-1.0", + "MIT", + "Apache-2.0", + "Apache-2.0 WITH LLVM-exception", + "BSD-2-Clause", #similar to MIT + "BSD-3-Clause", + "Zlib", + #"ring", + "MPL-2.0", #do not change mpl licenced source or you have to change your licence to MPL + "ISC", +] +# List of explictly disallowed licenses +# See https://spdx.org/licenses/ for list of possible licenses +# [possible values: any SPDX 3.7 short identifier (+ optional exception)]. +deny = [ + #"Nokia", +] +# Lint level for licenses considered copyleft +copyleft = "warn" +# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses +# * both - The license will be approved if it is both OSI-approved *AND* FSF +# * either - The license will be approved if it is either OSI-approved *OR* FSF +# * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF +# * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved +# * neither - This predicate is ignored and the default lint level is used +allow-osi-fsf-free = "neither" +# Lint level used when no other predicates are matched +# 1. License isn't in the allow or deny lists +# 2. License isn't copyleft +# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither" +default = "deny" +# The confidence threshold for detecting a license from license text. +# The higher the value, the more closely the license text must be to the +# canonical license text of a valid SPDX license file. +# [possible values: any between 0.0 and 1.0]. +confidence-threshold = 0.8 +# Allow 1 or more licenses on a per-crate basis, so that particular licenses +# aren't accepted for every possible crate as with the normal allow list +exceptions = [ + # Each entry is the crate and version constraint, and its specific allow + # list + #{ allow = ["Zlib"], name = "adler32", version = "*" }, +] + +# Some crates don't have (easily) machine readable licensing information, +# adding a clarification entry for it allows you to manually specify the +# licensing information +#[[licenses.clarify]] +# The name of the crate the clarification applies to +#name = "ring" +# THe optional version constraint for the crate +#version = "*" +# The SPDX expression for the license requirements of the crate +#expression = "MIT AND ISC AND OpenSSL" +# One or more files in the crate's source used as the "source of truth" for +# the license expression. If the contents match, the clarification will be used +# when running the license check, otherwise the clarification will be ignored +# and the crate will be checked normally, which may produce warnings or errors +# depending on the rest of your configuration +#license-files = [ + # Each entry is a crate relative path, and the (opaque) hash of its contents + #{ path = "LICENSE", hash = 0xbd0eed23 } +#] + +[licenses.private] +# If true, ignores workspace crates that aren't published, or are only +# published to private registries +ignore = false +# One or more private registries that you might publish crates to, if a crate +# is only published to private registries, and ignore is true, the crate will +# not have its license(s) checked +registries = [ + #"https://sekretz.com/registry +] + +# This section is considered when running `cargo deny check bans`. +# More documentation about the 'bans' section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html +[bans] +# Lint level for when multiple versions of the same crate are detected +multiple-versions = "warn" +# The graph highlighting used when creating dotgraphs for crates +# with multiple versions +# * lowest-version - The path to the lowest versioned duplicate is highlighted +# * simplest-path - The path to the version with the fewest edges is highlighted +# * all - Both lowest-version and simplest-path are used +highlight = "all" +# List of crates that are allowed. Use with care! +allow = [ + #{ name = "ansi_term", version = "=0.11.0" }, +] +# List of crates to deny +deny = [ + # Each entry the name of a crate and a version range. If version is + # not specified, all versions will be matched. + #{ name = "ansi_term", version = "=0.11.0" }, +] +# Certain crates/versions that will be skipped when doing duplicate detection. +skip = [ + #{ name = "ansi_term", version = "=0.11.0" }, +] +# Similarly to `skip` allows you to skip certain crates during duplicate +# detection. Unlike skip, it also includes the entire tree of transitive +# dependencies starting at the specified crate, up to a certain depth, which is +# by default infinite +skip-tree = [ + #{ name = "ansi_term", version = "=0.11.0", depth = 20 }, +] + +# This section is considered when running `cargo deny check sources`. +# More documentation about the 'sources' section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html +[sources] +# Lint level for what to happen when a crate from a crate registry that is not +# in the allow list is encountered +unknown-registry = "warn" +# Lint level for what to happen when a crate from a git repository that is not +# in the allow list is encountered +unknown-git = "warn" +# List of URLs for allowed crate registries. Defaults to the crates.io index +# if not specified. If it is specified but empty, no registries are allowed. +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +# List of URLs for allowed Git repositories +allow-git = [] diff --git a/src/input/buttons.rs b/src/input/buttons.rs index c407ec26..b677c36a 100755 --- a/src/input/buttons.rs +++ b/src/input/buttons.rs @@ -2,6 +2,7 @@ use gpio_cdev::{Chip, LineRequestFlags, EventRequestFlags, LineEventHandle}; use nix::poll::{PollFd, PollFlags, poll}; use std::os::unix::io::{AsRawFd, RawFd}; use smallvec::{SmallVec, smallvec}; +use log::error; use std::thread; use std::time::{Duration, Instant}; @@ -23,9 +24,10 @@ fn detect_and_handle(chip: &mut Chip, offset_to_command: [Event; 54], let (mut evt_handles, mut pollables) = configure_watching(chip, &offsets)?; dbg!(); thread::spawn(move || { + let mut last_high = [0u64; N_LINES]; + let mut last_state = [0u8; N_LINES]; + loop{ - let mut last_high = [0u64; N_LINES]; - let mut last_state = [0u8; N_LINES]; if poll(&mut pollables, -1).unwrap() !=0 { let key_presses = process_event(&pollables, &mut evt_handles, &mut last_high, &mut last_state); @@ -120,9 +122,9 @@ pub fn start_monitoring(tx: crossbeam_channel::Sender) dbg!(); detect_and_handle(&mut chip, offset_to_command, tx)?; - Ok(()) } else { + error!("could not find gpio chip"); Err(Error::GPIONotFound) } } From c1b214aad8b0de9dfa8b179d0a9547f3f0c71e0d Mon Sep 17 00:00:00 2001 From: dskleingeld Date: Sat, 8 Feb 2020 01:41:16 +0100 Subject: [PATCH 027/687] removes debug statements --- src/controller/mod.rs | 2 +- src/input/bot/mod.rs | 2 -- src/input/buttons.rs | 6 ------ src/input/sensors/mod.rs | 31 +++++++++++++++---------------- 4 files changed, 16 insertions(+), 25 deletions(-) diff --git a/src/controller/mod.rs b/src/controller/mod.rs index 8c229e6f..72ed2ebd 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -105,7 +105,7 @@ pub fn start(rx: crossbeam_channel::Receiver, mpd_status: MpdStatus) -> R (Event::Test, _) => {dbg!("a test happend"); change_state(TargetState::WakeUp, &mut mods, &mut system)}, #[cfg(feature = "sensors_connected")] - (Event::Sensor(_), _) => {dbg!("a sensor happend"); state} + (Event::Sensor(_), _) => {state} }; } }); diff --git a/src/input/bot/mod.rs b/src/input/bot/mod.rs index da8cca18..b3e30fe7 100644 --- a/src/input/bot/mod.rs +++ b/src/input/bot/mod.rs @@ -160,7 +160,6 @@ pub fn send_text_reply_blocking>(chat_id: ChatId, token: &str, t pub async fn set_webhook(domain: &str, token: &str, port: u16) -> Result<(), Error> { let url = format!("https://api.telegram.org/bot{}/setWebhook", token); let webhook_url = format!("{}:{}/{}",domain, port, token); - dbg!(&webhook_url); let params = [("url", &webhook_url)]; let client = reqwest::Client::new(); @@ -168,7 +167,6 @@ pub async fn set_webhook(domain: &str, token: &str, port: u16) -> Result<(), Err .form(¶ms) .send().await?; - dbg!(&res); if res.status() != reqwest::StatusCode::OK { Err(Error::CouldNotSetWebhook) } else { diff --git a/src/input/buttons.rs b/src/input/buttons.rs index b677c36a..be29f8fd 100755 --- a/src/input/buttons.rs +++ b/src/input/buttons.rs @@ -22,7 +22,6 @@ fn detect_and_handle(chip: &mut Chip, offset_to_command: [Event; 54], let offsets: [u32; 10] = [27,22,18, 23,24,26,17, 16,12,13]; let (mut evt_handles, mut pollables) = configure_watching(chip, &offsets)?; - dbg!(); thread::spawn(move || { let mut last_high = [0u64; N_LINES]; let mut last_state = [0u8; N_LINES]; @@ -32,7 +31,6 @@ fn detect_and_handle(chip: &mut Chip, offset_to_command: [Event; 54], let key_presses = process_event(&pollables, &mut evt_handles, &mut last_high, &mut last_state); for (offset, down_duration) in key_presses { - dbg!(down_duration); if down_duration > 10*MILLIS { tx.send(offset_to_command[offset]).unwrap(); } @@ -112,15 +110,11 @@ pub fn start_monitoring(tx: crossbeam_channel::Sender) offset_to_command[26] = Event::Command(Command::LampsDay); //right 4, right offset_to_command[17] = Event::Command(Command::LampsToggle); //right 4, right most - for chip in gpio_cdev::chips().unwrap() {dbg!(chip);} if let Some(mut chip) = gpio_cdev::chips()? .filter_map(Result::ok) - .inspect(|x| println!("{:?}",x)) .filter(|c| c.label() == "pinctrl-bcm2835") - .inspect(|x| println!("{:?}",x)) .next() { - dbg!(); detect_and_handle(&mut chip, offset_to_command, tx)?; Ok(()) } else { diff --git a/src/input/sensors/mod.rs b/src/input/sensors/mod.rs index 4edeb7fd..61ae7a70 100755 --- a/src/input/sensors/mod.rs +++ b/src/input/sensors/mod.rs @@ -22,6 +22,7 @@ pub enum SensorValue { Pressure(f32), } +use actix_rt::Runtime; //const LOCAL_SENSING_ID: timeseries_interface::DatasetId = 0; //TODO mechanisme for shutdown #[cfg(feature = "sensors_connected")] @@ -35,7 +36,8 @@ pub fn start_monitoring(tx: crossbeam_channel::Sender, thread::spawn(move || {//TODO figure out shutdown behaviour - + let mut rt = Runtime::new().unwrap(); + loop { //get all measurements let (hum, temp, pressure) = local::measure_and_record(&mut local_sensors); @@ -56,24 +58,21 @@ pub fn start_monitoring(tx: crossbeam_channel::Sender, HUMIDITY.encode::(hum, &mut line); PRESSURE.encode::(pressure, &mut line); - dbg!(&line); - thread::sleep(Duration::from_secs(5)); - - /*task::block_on( async { FIXME TODO RE-ENABLE AND SOLVE RUNTIME ISSUES + //FIXME TODO RE-ENABLE AND SOLVE RUNTIME ISSUES - let client = reqwest::Client::new(); - let send = client.post("https://www.deviousd.duckdns.org:38972/post_data") - .body(line) - .send(); - let sleep = task::sleep(Duration::from_secs(5)); + let client = reqwest::Client::new(); + let send = client.post("https://www.deviousd.duckdns.org:38972/post_data") + .body(line) + .send(); + let sleep = task::sleep(Duration::from_secs(5)); - //send data to dataserver and sleep up to 5 sec - let (send_err, _) = future::join(send, sleep).await; + //send data to dataserver and sleep up to 5 sec + let (send_err, _) = rt.block_on(future::join(send, sleep)); - if let Err(e) = send_err { - error!("could not send data to dataserver, error: {:?}", e); - } - })*/ + if let Err(e) = send_err { + error!("could not send data to dataserver, error: {:?}", e); + } + } }); } From 1152037dadcbbbdce25cb6909f6e0afc9343a5f3 Mon Sep 17 00:00:00 2001 From: dskleingeld Date: Sat, 8 Feb 2020 01:46:15 +0100 Subject: [PATCH 028/687] removes more debug statements --- src/input/alarms.rs | 1 - src/input/mpd_status.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/input/alarms.rs b/src/input/alarms.rs index 554f0c83..2e2de0f2 100755 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -27,7 +27,6 @@ pub struct AlarmList { } fn waker(mut alarm_list: AlarmList, event_tx: crossbeam_channel::Sender, waker_rx: crossbeam_channel::Receiver<()>) { - dbg!(); loop { //This can fail #TODO make sure an non waking error alarm is send to the user if let Some(current_alarm) = alarm_list.get_next() { diff --git a/src/input/mpd_status.rs b/src/input/mpd_status.rs index f893609f..370ba7b3 100755 --- a/src/input/mpd_status.rs +++ b/src/input/mpd_status.rs @@ -54,7 +54,6 @@ impl MpdStatus { pub fn start_updating() -> Result<(Self, thread::JoinHandle<()>, Sender<()>), Error>{ let mut client = mpd::Client::connect("127.0.0.1:6600")?; let status = client.status()?; - dbg!(&status); let mpd_status = Self { inner: Arc::new(RwLock::new(status))}; let mpd_status_cloned = mpd_status.clone(); From 64d1e369ece63e356003be86128a49b696a178ee Mon Sep 17 00:00:00 2001 From: dskleingeld Date: Tue, 18 Feb 2020 01:34:17 +0100 Subject: [PATCH 029/687] updates cert loader to be able to use certupdates, moves blocking reqwest to async, adds extra external port arg, various fixes --- Cargo.lock | 1 - Cargo.toml | 2 +- src/controller/states/wakeup.rs | 1 - src/errors.rs | 8 +++++ src/input/bot/mod.rs | 25 ------------- src/input/buttons.rs | 5 ++- src/input/sensors/fields/mod.rs | 1 + src/input/sensors/mod.rs | 7 +--- src/input/web_api/server/mod.rs | 63 +++++++++++++++++++++++++-------- src/input/youtube_downloader.rs | 24 ++++++++----- src/main.rs | 22 +++++++----- 11 files changed, 92 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 35d90103..018ca50e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3179,7 +3179,6 @@ dependencies = [ "memchr", "mio", "mio-uds", - "num_cpus", "pin-project-lite", "signal-hook-registry", "slab", diff --git a/Cargo.toml b/Cargo.toml index c4b4d5cc..9b848d5c 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,7 +56,7 @@ crossbeam-channel = "0.3" sled = "0.30" pagecache = "0.17" -reqwest = {version = "0.10", features = ["blocking"]} +reqwest = {version = "0.10"} mpd = "0.0.12" dirs = "2" diff --git a/src/controller/states/wakeup.rs b/src/controller/states/wakeup.rs index 904fcbfd..7237b322 100755 --- a/src/controller/states/wakeup.rs +++ b/src/controller/states/wakeup.rs @@ -82,7 +82,6 @@ impl RoomState for WakeUp { } ActiveState::WakeUp(self) - } fn enter(mods: &mut Modifications, sys: &mut System) -> Self { diff --git a/src/errors.rs b/src/errors.rs index 3e816e96..de03d733 100755 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,4 +1,5 @@ use crate::input::youtube_downloader; +use crate::input::web_api::server; #[derive(Debug)] pub enum Error { @@ -13,9 +14,16 @@ pub enum Error { Mpd(mpd::error::Error), RetryLogic(String), YoutubeDownloader(youtube_downloader::Error), + WebServerError(server::Error), UnTracked, } +impl From for Error { + fn from(err: server::Error) -> Self { + Error::WebServerError(err) + } +} + impl From for Error { fn from(err: youtube_downloader::Error) -> Self { Error::YoutubeDownloader(err) diff --git a/src/input/bot/mod.rs b/src/input/bot/mod.rs index b3e30fe7..99257a0b 100644 --- a/src/input/bot/mod.rs +++ b/src/input/bot/mod.rs @@ -17,7 +17,6 @@ pub enum Error{ HttpClientError(reqwest::Error), CouldNotSetWebhook, InvalidServerResponse(reqwest::Response), - InvalidServerResponseBlocking(reqwest::blocking::Response), UnhandledUpdateKind, UnhandledMessageKind, UnknownCommand(String) @@ -84,7 +83,6 @@ async fn handle_error(error: Error, chat_id: ChatId, token: &str) { Error::UnhandledUpdateKind => { String::from(UNHANDLED)} Error::CouldNotSetWebhook => unreachable!(), - Error::InvalidServerResponseBlocking(_) => unreachable!(), }; if let Err(error) = send_text_reply(chat_id, token, error_message).await{ error!("Could not send text reply to user: {:?}", error); @@ -102,7 +100,6 @@ async fn handle(update: Update, state: State){ pub async fn handle_webhook(state: Data, raw_update: Bytes) -> HttpResponse { - let update: Update = serde_json::from_slice(&raw_update.to_vec()).unwrap(); let state_cpy = state.get_ref().clone(); handle(update, state_cpy).await; @@ -134,28 +131,6 @@ pub async fn send_text_reply>(chat_id: ChatId, token: &str, text } } -pub fn send_text_reply_blocking>(chat_id: ChatId, token: &str, text: T) - -> Result<(), Error>{//add as arg generic ToChatRef (should get from Update) - //TODO create a SendMessage, serialise it (use member function serialize) - //then use the HttpRequest fields, (url, method, and body) to send to telegram - let url = format!("https://api.telegram.org/bot{}/sendMessage", token); - let form = reqwest::blocking::multipart::Form::new() - .text("chat_id", chat_id.to_string()) - .text("text", text.into()); - - let client = reqwest::blocking::Client::new(); - let resp = client.post(&url) - .multipart(form).send()?; - //https://stackoverflow.com/questions/57540455/error-blockingclientinfuturecontext-when-trying-to-make-a-request-from-within - - if resp.status() != reqwest::StatusCode::OK { - Err(Error::InvalidServerResponseBlocking(resp)) - } else { - info!("send message"); - Ok(()) - } -} - //Ports currently supported for Webhooks: 443, 80, 88, 8443. pub async fn set_webhook(domain: &str, token: &str, port: u16) -> Result<(), Error> { let url = format!("https://api.telegram.org/bot{}/setWebhook", token); diff --git a/src/input/buttons.rs b/src/input/buttons.rs index be29f8fd..1375f9f6 100755 --- a/src/input/buttons.rs +++ b/src/input/buttons.rs @@ -1,11 +1,10 @@ use gpio_cdev::{Chip, LineRequestFlags, EventRequestFlags, LineEventHandle}; use nix::poll::{PollFd, PollFlags, poll}; -use std::os::unix::io::{AsRawFd, RawFd}; -use smallvec::{SmallVec, smallvec}; +use std::os::unix::io::{AsRawFd}; +use smallvec::{SmallVec}; use log::error; use std::thread; -use std::time::{Duration, Instant}; use crossbeam_channel; use crate::errors::Error; diff --git a/src/input/sensors/fields/mod.rs b/src/input/sensors/fields/mod.rs index 5b78ccc7..8a4fd611 100644 --- a/src/input/sensors/fields/mod.rs +++ b/src/input/sensors/fields/mod.rs @@ -12,6 +12,7 @@ pub struct Field { //TODO do away with generics in favor for speeeeed impl Field where T: num::cast::NumCast+std::fmt::Display+std::ops::Add+std::ops::SubAssign+std::ops::DivAssign+std::ops::MulAssign+std::marker::Copy { + #[allow(dead_code)] pub fn decode(&self, line: &[u8]) -> D where D: num::cast::NumCast+std::fmt::Display+std::ops::Add+std::ops::SubAssign+std::ops::MulAssign+std::ops::AddAssign{ //where D: From+From+From+std::ops::Add+std::ops::SubAssign+std::ops::DivAssign+std::ops::AddAssign{ diff --git a/src/input/sensors/mod.rs b/src/input/sensors/mod.rs index 61ae7a70..7e6e8328 100755 --- a/src/input/sensors/mod.rs +++ b/src/input/sensors/mod.rs @@ -35,7 +35,6 @@ pub fn start_monitoring(tx: crossbeam_channel::Sender, ble::init(); thread::spawn(move || {//TODO figure out shutdown behaviour - let mut rt = Runtime::new().unwrap(); loop { @@ -58,17 +57,13 @@ pub fn start_monitoring(tx: crossbeam_channel::Sender, HUMIDITY.encode::(hum, &mut line); PRESSURE.encode::(pressure, &mut line); - //FIXME TODO RE-ENABLE AND SOLVE RUNTIME ISSUES - let client = reqwest::Client::new(); let send = client.post("https://www.deviousd.duckdns.org:38972/post_data") .body(line) .send(); let sleep = task::sleep(Duration::from_secs(5)); - //send data to dataserver and sleep up to 5 sec - let (send_err, _) = rt.block_on(future::join(send, sleep)); - + let (send_err, _) = rt.block_on(future::join(send, sleep)); if let Err(e) = send_err { error!("could not send data to dataserver, error: {:?}", e); } diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index 80454772..4ea93f51 100755 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -1,19 +1,18 @@ use rustls::{NoClientAuth, ServerConfig}; use rustls::internal::pemfile::{certs, pkcs8_private_keys}; -use actix_rt::Runtime; use actix_rt::System; use actix_web::{HttpServer,App, web, Responder}; use actix_identity::{CookieIdentityPolicy, IdentityService}; -use actix_files as fs; +use actix_files as axtix_fs; use actix_web::HttpRequest; use std::thread; use std::sync::{Arc, Mutex, RwLock, atomic::AtomicUsize}; use std::collections::HashMap; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::io::BufReader; -use std::fs::File; +use std::fs; use crate::input; use crate::input::bot; @@ -63,27 +62,64 @@ impl State { } } -pub fn make_tls_config>(signed_cert_path: P, private_key_path: P) -> rustls::ServerConfig{ +#[derive(Debug)] +pub enum Error { + NoKeyFound, + NoCertFound, +} + +fn get_key_and_cert(domain: &str, dir: &Path) -> Result<(PathBuf, PathBuf), Error> { + let mut cert_path = Err(Error::NoCertFound); + let mut key_path = Err(Error::NoKeyFound); + let domain = domain.replace(".", "_"); + for path in fs::read_dir(dir).unwrap() + .filter_map(Result::ok) + .map(|entry| entry.path()) { + + if let Some(stem) = path.file_stem().map(|s| s.to_str()).flatten(){ + if !stem.contains(&domain){ continue } + if let Some(ext) = path.extension().map(|s| s.to_str()).flatten(){ + match ext { + "key" => key_path = Ok(path), + "crt" => cert_path = Ok(path), + _ => continue, + } + } + } + } + + Ok((key_path?, cert_path?)) +} + +pub fn make_tls_config(domain: &str, key_dir: &Path) -> Result { + + //find cert and key + let (key_path, cert_path) = get_key_and_cert(domain, key_dir)?; + let mut tls_config = ServerConfig::new(NoClientAuth::new()); - let cert_file = &mut BufReader::new(File::open(signed_cert_path).unwrap()); - let key_file = &mut BufReader::new(File::open(private_key_path).unwrap()); + let cert_file = &mut BufReader::new(fs::File::open(&cert_path) + .expect(&format!("could not open certificate file: {:?}", cert_path))); + let key_file = &mut BufReader::new(fs::File::open(&key_path) + .expect(&format!("could not open key file: {:?}", key_path))); + let cert_chain = certs(cert_file).unwrap(); let mut key = pkcs8_private_keys(key_file).unwrap(); tls_config .set_single_cert(cert_chain, key.pop().unwrap()) .unwrap(); - tls_config + Ok(tls_config) } pub async fn index(_req: HttpRequest) -> impl Responder { "Hello world!" } -pub fn start_webserver(signed_cert: &str, private_key: &str, - state: State, port: u16, domain: String) -> actix_web::dev::Server { +pub fn start_webserver(key_dir: &Path, + state: State, port: u16, domain: String) + -> Result { - let tls_config = make_tls_config(signed_cert, private_key); + let tls_config = make_tls_config(&domain, key_dir)?; let cookie_key = make_random_cookie_key(); let (tx, rx) = crossbeam_channel::unbounded(); @@ -134,7 +170,7 @@ pub fn start_webserver(signed_cert: &str, private_key: &str, .service(web::resource("set_alarm").to(web_api::set_alarm_unix_timestamp)) .service(web::resource("list_alarms").to(web_api::list_alarms)) //for all other urls we try to resolve to static files in the "web" dir - .service(fs::Files::new("", "./web/")) + .service(axtix_fs::Files::new("", "./web/")) ) }) .bind_rustls(&format!("0.0.0.0:{}", port), tls_config).unwrap() @@ -149,6 +185,5 @@ pub fn start_webserver(signed_cert: &str, private_key: &str, }); let web_handle = rx.recv().unwrap(); - - web_handle + Ok(web_handle) } \ No newline at end of file diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index 01ff3d0b..01d22df7 100755 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -1,5 +1,5 @@ use std::process::Command; -use std::io::copy; +use std::io::Write; use std::fs; use std::os::unix::fs::OpenOptionsExt; use std::thread; @@ -7,7 +7,7 @@ use std::thread; use std::time::Duration; use std::path::Path; use reqwest::{IntoUrl}; - +use actix_rt; const DIR: &str = "temp"; const YOUTUBE_DL_LOC: &str = "temp/youtube-dl"; @@ -36,7 +36,7 @@ impl From for Error { } } -fn download_youtube_dl(url: U) -> Result<(), Error> { +async fn download_youtube_dl(url: U) -> Result<(), Error> { let mut dest = fs::OpenOptions::new() .create(true) @@ -44,9 +44,12 @@ fn download_youtube_dl(url: U) -> Result<(), Error> { .mode(0o770) .open(YOUTUBE_DL_LOC)?; - let mut response = reqwest::blocking::get(url)?; - copy(&mut response, &mut dest)?; + let response = reqwest::get(url) + .await? + .bytes() + .await?; + dest.write(&response)?; Ok(()) } @@ -98,7 +101,12 @@ fn download_song(url: &str) -> Result<(), Error> { return Err(Error::CouldNotDownloadSong); } - download_youtube_dl("https://yt-dl.org/downloads/latest/youtube-dl")?; + + let mut rt = actix_rt::Runtime::new().unwrap(); + rt.block_on( + download_youtube_dl("https://yt-dl.org/downloads/latest/youtube-dl") + )?; + let output = run_youtube_dl(&output_arg, url)?; dbg!(&output); @@ -133,7 +141,7 @@ fn song_downloader(url_rx: crossbeam_channel::Receiver) { impl YoutubeDownloader { - pub fn init() -> Result<(Self, thread::JoinHandle<()>), Error>{ + pub async fn init() -> Result<(Self, thread::JoinHandle<()>), Error>{ let full_path = Path::new(YOUTUBE_DL_LOC); let dir_path = Path::new(DIR); @@ -141,7 +149,7 @@ impl YoutubeDownloader { if !dir_path.exists() { fs::create_dir(dir_path)?; } - download_youtube_dl("https://yt-dl.org/downloads/latest/youtube-dl")?; + download_youtube_dl("https://yt-dl.org/downloads/latest/youtube-dl").await?; } let (url_tx, url_rx) = crossbeam_channel::bounded(10); diff --git a/src/main.rs b/src/main.rs index 47790625..82e8eead 100755 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ extern crate chrono; use structopt::StructOpt; use sled; -use std::io::stdin; +use std::path::PathBuf; mod controller; @@ -36,8 +36,11 @@ struct Opt { #[structopt(short = "n", long = "node-id", default_value= "3")] node_id: u16, - #[structopt(short = "k", long = "dataserver-key")] - dataserver_key: u64, + #[structopt(short = "s", long = "dataserver-key")] + dataserver_key: u64, + + #[structopt(short = "k", long = "keys", default_value="keys")] + key_dir: PathBuf, } #[actix_rt::main] @@ -58,7 +61,8 @@ async fn main() { let (alarms, _waker_thread) = input::alarms::Alarms::setup( controller_tx.clone(), db.clone()).unwrap(); - let (youtube_dl, _downloader_thread) = input::YoutubeDownloader::init().unwrap(); + let (youtube_dl, _downloader_thread) = input::YoutubeDownloader::init() + .await.unwrap(); let (mpd_status, _mpd_watcher_thread, updater_tx) = input::MpdStatus::start_updating() .unwrap(); @@ -76,8 +80,8 @@ async fn main() { //start the webserver let web_handle = server::start_webserver( - "keys/cert.key", "keys/cert.cert", - state, opt.port, opt.domain.clone()); + &opt.key_dir, state, opt.port, + opt.domain.clone()).unwrap(); bot::set_webhook( @@ -91,7 +95,9 @@ async fn main() { #[cfg(feature = "sensors_connected")] input::buttons::start_monitoring(controller_tx.clone()).unwrap(); - println!("press: q to quit"); + loop {} + + /*println!("press: q to quit"); loop { let mut input = String::new(); stdin().read_line(&mut input).unwrap(); @@ -103,5 +109,5 @@ async fn main() { } println!("shutting down"); web_handle.stop(true).await; - input::MpdStatus::stop_updating(updater_tx); + input::MpdStatus::stop_updating(updater_tx);*/ } From 371dfc9d040883e36b6e366e204c0f5c15788add Mon Sep 17 00:00:00 2001 From: dskleingeld Date: Sun, 23 Feb 2020 12:40:29 +0100 Subject: [PATCH 030/687] rewrites youtube downloader to allow adding metadata/confirming metadata later --- Cargo.lock | 1 + Cargo.toml | 5 +- src/input/bot/mod.rs | 8 +- src/input/mpd_status.rs | 1 - src/input/web_api/mod.rs | 4 +- src/input/youtube_downloader.rs | 322 +++++++++++++++++++++++++++----- src/main.rs | 4 +- 7 files changed, 288 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 018ca50e..a3505f76 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,6 +29,7 @@ dependencies = [ "pagecache", "philipshue", "rand 0.6.5", + "regex", "reqwest 0.10.1", "retry", "ring", diff --git a/Cargo.toml b/Cargo.toml index 9b848d5c..75315cb0 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,6 @@ gpio-cdev = { git = "https://github.com/rust-embedded/gpio-cdev", branch = "mast nix = "0.17" #tokio = "0.1.15" -bincode = "1.0" ring = "0.16" linux-embedded-hal = "0.2" @@ -64,4 +63,6 @@ rand = "0.6" retry = "0.5" telegram-bot = "0.6" -serde_json = "1.0" \ No newline at end of file +serde_json = "1.0" +regex = "1" +bincode = "1.2" \ No newline at end of file diff --git a/src/input/bot/mod.rs b/src/input/bot/mod.rs index 99257a0b..e2af3b2e 100644 --- a/src/input/bot/mod.rs +++ b/src/input/bot/mod.rs @@ -10,6 +10,7 @@ use telegram_bot::types::update::UpdateKind; use telegram_bot::types::message::MessageKind; use telegram_bot::types::refs::{ChatId, UserId}; +use crate::input::youtube_downloader::FeedbackChannel; use crate::input::web_api::server::{State}; #[derive(Debug)] @@ -48,10 +49,15 @@ async fn handle_command(text: String, chat_id: ChatId, state: &State) -> Result<(), Error>{ let token = &state.bot_token; + if text.contains("https://") || text.contains("http://") { + state.youtube_dl.add_song_to_queue(text, + FeedbackChannel::Telegram(chat_id)).unwrap(); + return Ok(()); + } let split = text.find(char::is_whitespace); let mut command = text; - let args = command.split_off(split.unwrap_or(command.len())); + //let args = command.split_off(split.unwrap_or(command.len())); match command.as_str() { "/test" => { send_text_reply(chat_id, token, "hi").await?; diff --git a/src/input/mpd_status.rs b/src/input/mpd_status.rs index 370ba7b3..97d51cd8 100755 --- a/src/input/mpd_status.rs +++ b/src/input/mpd_status.rs @@ -32,7 +32,6 @@ fn mpd_watcher(mut client: Client, status: MpdStatus, rx: Receiver<()>) { //this loop is stopped by sending a change to mpd server if let Ok(_) = client.wait(&[Subsystem::Player, Subsystem::Mixer]){ //update status - dbg!("updating mpd status"); let new_status = client.status().unwrap(); *(status.inner.write().unwrap()) = new_status; } else { diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index b2544fa2..dfcf461e 100755 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -8,6 +8,8 @@ use chrono::{DateTime, NaiveDateTime, Utc}; use serde::Deserialize; use actix_web::HttpResponse; + +use crate::input::youtube_downloader::FeedbackChannel; use crate::controller::{Command, TargetState, Event}; mod command_logins; @@ -185,7 +187,7 @@ pub fn add_song_from_url(params: Form, state: Data) -> HttpRespo let url = params.into_inner().url; dbg!(); - if state.youtube_dl.add_song_to_queue(url).is_ok(){ + if state.youtube_dl.add_song_to_queue(url, FeedbackChannel::None).is_ok(){ dbg!(); HttpResponse::Ok().finish() diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index 01d22df7..55cfa2d1 100755 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -6,18 +6,51 @@ use std::thread; use std::time::Duration; use std::path::Path; + +use telegram_bot::types::refs::ChatId; use reqwest::{IntoUrl}; use actix_rt; +use regex::Regex; +use serde::{Serialize, Deserialize}; +use bincode; +use crate::input::bot::send_text_reply; const DIR: &str = "temp"; const YOUTUBE_DL_LOC: &str = "temp/youtube-dl"; +const MUSIC_TEMP: &str = "temp/music"; +const MUSIC_DIR: &str = "/home/pi/Music/youtube"; #[derive(Debug)] pub enum Error{ CouldNotDownloadExecutable(reqwest::Error), CouldNotStoreExecutable(std::io::Error), - CouldNotDownloadSong, + CouldNotDownloadSong(std::process::Output), CouldNotUpdateMpd(mpd::error::Error), + CouldNotCreateTempDir(std::io::Error), + UnexpectedYoutubeDlStdOut(String), + UnsupportedSource(String), +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Error::CouldNotDownloadExecutable(e) => + write!(f, "Could not download executable, cause {}", e), + Error::CouldNotStoreExecutable(e) => + write!(f, "Could not store executable, cause: {}", e), + Error::CouldNotDownloadSong(e) => + write!(f, "Could not download song, cause: {}", + String::from_utf8(e.stderr.clone()).unwrap()), + Error::CouldNotUpdateMpd(e) => + write!(f, "Could not update mpd, cause: {}", e), + Error::CouldNotCreateTempDir(e) => + write!(f, "Could not create temp directory, cause: {}", e), + Error::UnexpectedYoutubeDlStdOut(s) => + write!(f, "Could not understand output of youtube-dl, output was: {}",s), + Error::UnsupportedSource(s) => + write!(f, "Could not find something to download: {}", s), + } + } } impl From for Error { @@ -36,6 +69,42 @@ impl From for Error { } } +#[derive(Debug, Clone)] +pub enum FeedbackChannel{ + Telegram(ChatId), + None, + //future expand with ... signal? +} + +#[derive(Debug)] +enum JobStatus { + Finished, + Downloaded, + Queued(MetaData), + Error, +} + +impl FeedbackChannel { + async fn send(self, status: JobStatus, token: &str) { + match self { + Self::Telegram(chat_id) => { + let message = format!("{:?}", status); + if let Err(e)=send_text_reply(chat_id, token, message).await { + error!("ran into error \ + sending text reply to bot user: {:?}", e); + }; + } + Self::None => (), + } + } +} + +struct Job { + id: u64, + url: String, + feedback: FeedbackChannel, +} + async fn download_youtube_dl(url: U) -> Result<(), Error> { let mut dest = fs::OpenOptions::new() @@ -48,100 +117,227 @@ async fn download_youtube_dl(url: U) -> Result<(), Error> { .await? .bytes() .await?; - + dbg!(&response.len()); dest.write(&response)?; Ok(()) } #[derive(Clone)] pub struct YoutubeDownloader { - url_tx: crossbeam_channel::Sender, + url_tx: crossbeam_channel::Sender, + db: sled::Db, + token: String, +} + +#[derive(Serialize, Deserialize, Default, Debug)] +pub struct MetaData { + artist: String, + title: String, +} + +#[derive(Serialize, Deserialize, Default)] +struct DbEntry { + downloaded: bool, //default val = false + meta: Option +} + +impl DbEntry { + fn empty() -> Self { + DbEntry { + downloaded: false, + meta: None, + } + } + fn downloaded() -> Self { + DbEntry { + downloaded: true, + meta: None, + } + } } -fn run_youtube_dl(output_arg: &String, url: &str) +fn get_meta(url: &str) -> Result { + + let full_path = Path::new(YOUTUBE_DL_LOC); + let output = Command::new(full_path) + //.arg("--verbose") //for debugging + .arg("--geo-bypass") + .arg("--no-playlist") + .arg("--ignore-config") + .arg("--get-filename") + + .arg("--max-filesize") + .arg("50m") + + .arg("--audio-format") + .arg("m4a") + .arg("--audio-quality") + .arg("257") + .arg("--format") + .arg("bestaudio[acodec=opus]/bestaudio/best") + + .arg("--output") + .arg("/%(title)s-#-#-%(artist)s") + .arg(url) + .output()?; + + let stdout = String::from_utf8(output.stdout).unwrap(); + let mut title_artist = stdout.splitn(2, "-#-#-"); + let metadata = MetaData { + artist: title_artist.next() + .map(|s| s.to_owned()) + .ok_or(Error::UnsupportedSource(stdout.clone()))?, + title: title_artist.next() + .map(|s| s.to_owned()) + .ok_or(Error::UnsupportedSource(stdout.clone()))?, + }; + + Ok(metadata) +} + +fn download_file(output_arg: &String, url: &str) -> std::io::Result { let full_path = Path::new(YOUTUBE_DL_LOC); Command::new(full_path) + //.arg("--verbose") //for debugging .arg("--geo-bypass") + .arg("--no-playlist") .arg("--ignore-config") - .arg("--add-metadata") - .arg("--metadata-from-title \"%(artist)s - %(title)s\"") - .arg("--embed-thumbnail") + .arg("--max-filesize") + .arg("50m") + + //.arg("--embed-thumbnail") //dependency can not be installed + .arg("--write-thumbnail") .arg("--audio-format") .arg("m4a") .arg("--audio-quality") .arg("257") - .arg("--postprocessor-args") - .arg("\"-ar 44100\"") + .arg("--postprocessor-args") //seems to take along time + .arg("-ar 44100") .arg("--extract-audio") .arg("--format") .arg("bestaudio[acodec=opus]/bestaudio/best") + .arg("--output") .arg(&output_arg) + .arg(url) .output() } -fn download_song(url: &str) -> Result<(), Error> { - let music_dir = std::path::PathBuf::from("/home/pi/Music"); - let mut output_arg = String::from(music_dir.to_str().unwrap()); - output_arg.push_str("/%(title)s.%(ext)s"); +async fn download_song(url: &str, id: u64) -> Result<(), Error> { + let temp_dir = std::path::PathBuf::from(MUSIC_TEMP); + if !temp_dir.exists() { + fs::create_dir(&temp_dir) + .map_err(|e| Error::CouldNotCreateTempDir(e))?; + } + + let mut output_arg = String::from(temp_dir.to_str().unwrap()); + output_arg.push_str(&format!("/{}",id)); - let output = run_youtube_dl(&output_arg, url)?; + let output = download_file(&output_arg, url)?; dbg!(&output); - if !output.status.success() { + let output = if !output.status.success() { let since_last_updated = fs::metadata(YOUTUBE_DL_LOC).unwrap() .created().unwrap() .elapsed().unwrap_or(Duration::from_secs(0)); + // updating youtube-dl wont do anything return error if since_last_updated > Duration::from_secs(60*60*24){ - return Err(Error::CouldNotDownloadSong); + return Err(Error::CouldNotDownloadSong(output)); } - - let mut rt = actix_rt::Runtime::new().unwrap(); - rt.block_on( - download_youtube_dl("https://yt-dl.org/downloads/latest/youtube-dl") - )?; - - let output = run_youtube_dl(&output_arg, url)?; - dbg!(&output); - + download_youtube_dl("https://yt-dl.org/downloads/latest/youtube-dl").await?; + let output = download_file(&output_arg, url)?; if !output.status.success() { - return Err(Error::CouldNotDownloadSong); + return Err(Error::CouldNotDownloadSong(output)); } + output + } else {output}; + + //let title = parse_stdout(output.stdout)?; + + //mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| c.rescan())?; + //Ok(title) + Ok(()) +} + +fn get_metadata(db: sled::Tree, id: u64) + -> Result, Error> { + + let modification = db.compare_and_swap( + id.to_be_bytes(), + Some(bincode::serialize(&DbEntry::empty()).unwrap() ), + Some(bincode::serialize(&DbEntry::downloaded()).unwrap() ), + ).unwrap(); + + //if the modification was an error (not swapped) the entry was not + //empty and thus has metadata, return the metadata. + if let Err(old_value) = modification { + let with_metadata: DbEntry = bincode::deserialize( + &old_value + .current.unwrap() + .to_vec() ).unwrap(); + Ok(with_metadata.meta) + } else { + Ok(None) } +} - mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| c.rescan())?; +fn write_metadata(meta: MetaData, id: u64) -> Result<(), Error> { + //move file from temp/id to music/artist/title + //or in case metadata is wierd (tbdefined) to + //music/youtube/title.. + todo!(); +} + +async fn handle_job(job: Job, token: String, db: sled::Tree) + -> Result<(), Error> { + + let status = match download_song(&job.url, job.id).await { + Ok(_) => { + if let Some(meta) = get_metadata(db, job.id)?{ + write_metadata(meta, job.id)?; + JobStatus::Finished + } else { + JobStatus::Downloaded + } + }, + Err(error) => { + error!("warn error during song download: {:?}", error); + JobStatus::Error + }, + }; + job.feedback.send(status, &token).await; Ok(()) } -fn song_downloader(url_rx: crossbeam_channel::Receiver) { +fn song_downloader(url_rx: crossbeam_channel::Receiver, + token: String, db: sled::Tree) { + + let mut rt = actix_rt::Runtime::new().unwrap(); + loop { match url_rx.recv() { - Ok(url) => { - dbg!(&url); - match download_song(&url) { - Ok(_) => dbg!(), - Err(error) => { - error!("warn error during song download: {:?} \ - trying with updated youtube-dl", error); - }, - }; + Ok(job) => { + rt.block_on( handle_job(job, token.clone(), db.clone())); }, // Err means YoutubeDownloader // was dropped and this thread should stop Err(_) => return, - } - } + } + } } impl YoutubeDownloader { - pub async fn init() -> Result<(Self, thread::JoinHandle<()>), Error>{ + pub async fn init(token: String, db: sled::Db) + -> Result<(Self, thread::JoinHandle<()>), Error> { + + let youtube_db = db.open_tree("youtube_dl").unwrap(); let full_path = Path::new(YOUTUBE_DL_LOC); let dir_path = Path::new(DIR); @@ -153,24 +349,50 @@ impl YoutubeDownloader { } let (url_tx, url_rx) = crossbeam_channel::bounded(10); - let downloader_thread = thread::spawn(move || song_downloader(url_rx) ); + let local_token = token.clone(); + let downloader_thread = thread::spawn(move || + song_downloader(url_rx, local_token, youtube_db) + ); - Ok((Self {url_tx}, downloader_thread)) + Ok((Self {url_tx, db, token}, downloader_thread)) } //TODO use youtube downloader to stream audio from youtube!!! /// checks if a song can be downloaded, if so sends the command to start download to /// a seperate thread - pub fn add_song_to_queue(&self, url: String) -> Result<(), ()> { + pub fn add_song_to_queue(&self, url: String, feedback: FeedbackChannel) + -> Result<(), Error> { - if self.url_tx.try_send(url).is_err(){ - error!("could not add song to downlaod list"); - Err(()) - } else { - dbg!(); - Ok(()) - } + //get metadata guess from youtube-dl + let meta_guess = get_meta(&url)?; + let id = self.db.generate_id().unwrap(); + let youtube_db = self.db.open_tree("youtube_dl").unwrap(); + + let db_entry = DbEntry::default(); + youtube_db.insert( + id.to_be_bytes(), + bincode::serialize(&db_entry).unwrap() + ).unwrap(); + + let job = Job {id, url: url, feedback: feedback.clone()}; + self.url_tx.try_send(job).unwrap(); + feedback.send(JobStatus::Queued(meta_guess), &self.token); + Ok(()) } +} + + +#[cfg(test)] +mod tests { + use super::*; + + /*#[test] + fn test_parse_stdout(){ + let test_case = String::from("[youtube] 1MZu2pD3QPY: Downloading webpage\n[youtube] 1MZu2pD3QPY: Downloading video info webpage\n[youtube] Downloading just video 1MZu2pD3QPY because of --no-playlist\n[download] Destination: /home/pi/Music/youtube/Trevor Jones - Promentory (The Last of the Mohicans).webm\n\r[download] 0.0% of 6.03MiB at 527.45KiB/s ETA 00:12\r[download] 0.0% of 6.03MiB at 1.06MiB/s ETA 00:05\r[download] 0.1% of 6.03MiB at 1.90MiB/s ETA 00:03\r[download] 0.2% of 6.03MiB at 3.33MiB/s ETA 00:01\r[download] 0.5% of 6.03MiB at 4.79MiB/s ETA 00:01\r[download] 1.0% of 6.03MiB at 6.59MiB/s ETA 00:00\r[download] 2.1% of 6.03MiB at 7.89MiB/s ETA 00:00\r[download] 4.1% of 6.03MiB at 9.44MiB/s ETA 00:00\r[download] 8.3% of 6.03MiB at 10.43MiB/s ETA 00:00\r[download] 16.6% of 6.03MiB at 10.76MiB/s ETA 00:00\r[download] 33.1% of 6.03MiB at 10.06MiB/s ETA 00:00\r[download] 66.3% of 6.03MiB at 10.36MiB/s ETA 00:00\r[download] 100.0% of 6.03MiB at 10.33MiB/s ETA 00:00\r[download] 100% of 6.03MiB in 00:00\n[fromtitle] parsed artist: Trevor Jones\n[fromtitle] parsed title: Promentory (The Last of the Mohicans)\n[ffmpeg] Destination: /home/pi/Music/youtube/Trevor Jones - Promentory (The Last of the Mohicans).m4a\nDeleting original file /home/pi/Music/youtube/Trevor Jones - Promentory (The Last of the Mohicans).webm (pass -k to keep)\n[ffmpeg] Adding metadata to \'/home/pi/Music/youtube/Trevor Jones - Promentory (The Last of the Mohicans).m4a\'\n"); + let test_case = test_case.into_bytes(); + let test_case_awnser = "Trevor Jones - Promentory (The Last of the Mohicans)"; + assert_eq!(parse_stdout(test_case).unwrap(), test_case_awnser); + }*/ } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 82e8eead..a267490b 100755 --- a/src/main.rs +++ b/src/main.rs @@ -61,8 +61,8 @@ async fn main() { let (alarms, _waker_thread) = input::alarms::Alarms::setup( controller_tx.clone(), db.clone()).unwrap(); - let (youtube_dl, _downloader_thread) = input::YoutubeDownloader::init() - .await.unwrap(); + let (youtube_dl, _downloader_thread) = input::YoutubeDownloader::init( + opt.token.clone(), db.clone()).await.unwrap(); let (mpd_status, _mpd_watcher_thread, updater_tx) = input::MpdStatus::start_updating() .unwrap(); From 5919cbbbfd9686bed6e6ce1d38b7c9422b9d589e Mon Sep 17 00:00:00 2001 From: dskleingeld Date: Mon, 2 Mar 2020 01:35:09 +0100 Subject: [PATCH 031/687] adds youtube downloader function for telegram bot with partially working feedback to user --- Cargo.lock | 24 ++++++++++ Cargo.toml | 3 ++ src/errors.rs | 70 ++++++++++++++++++++++------- src/input/bot/mod.rs | 60 ++++++++++++++++++------- src/input/bot/youtube_dl.rs | 80 +++++++++++++++++++++++++++++++++ src/input/web_api/mod.rs | 5 ++- src/input/web_api/server/mod.rs | 10 ++++- src/input/youtube_downloader.rs | 39 ++++++++-------- src/main.rs | 18 +++++--- 9 files changed, 253 insertions(+), 56 deletions(-) create mode 100644 src/input/bot/youtube_dl.rs diff --git a/Cargo.lock b/Cargo.lock index a3505f76..b413c6d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,6 +12,7 @@ dependencies = [ "actix-web", "actix-web-httpauth", "async-std", + "async-trait", "bincode", "bme280", "byteorder", @@ -19,6 +20,7 @@ dependencies = [ "chrono", "crossbeam-channel 0.3.9", "dirs", + "fern", "futures 0.3.4", "gpio-cdev", "linux-embedded-hal", @@ -794,6 +796,17 @@ dependencies = [ "bitflags 1.2.1", ] +[[package]] +name = "colored" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59" +dependencies = [ + "atty", + "lazy_static", + "winapi 0.3.8", +] + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -1080,6 +1093,17 @@ dependencies = [ "synstructure", ] +[[package]] +name = "fern" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e69ab0d5aca163e388c3a49d284fed6c3d0810700e77c5ae2756a50ec1a4daaa" +dependencies = [ + "chrono", + "colored", + "log", +] + [[package]] name = "flate2" version = "1.0.13" diff --git a/Cargo.toml b/Cargo.toml index 75315cb0..742e5222 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ live_server = [] [dependencies] futures = "0.3" async-std = "1" +async-trait = "0.1" actix-web = { version = "2", features = ["rustls"] } actix-net = "0.2" @@ -34,7 +35,9 @@ philipshue = { git = "https://github.com/dskleingeld/philipshue", branch = "mast structopt = "0.3" serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.8" + log = "0.4" +fern = { version = "0.5.6", features = ["colored"] } gpio-cdev = { git = "https://github.com/rust-embedded/gpio-cdev", branch = "master" } nix = "0.17" diff --git a/src/errors.rs b/src/errors.rs index de03d733..1709526c 100755 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,3 +1,5 @@ +use fern::colors::{Color, ColoredLevelConfig}; + use crate::input::youtube_downloader; use crate::input::web_api::server; @@ -76,11 +78,6 @@ impl From> for Error { } } } -//impl From for Error { -// fn from(error: crossbeam_channel::SendError<()>) -> Self { -// Error::Channel(error) -// } -//} impl From for Error { fn from(error: sled::Error) -> Self { @@ -106,13 +103,56 @@ impl From for Error { } } -/*impl fmt::Debug for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - dbg!(("heee")); - match self { - Error::IO(error) => error.fmt(f), - Error::GPIO(error) => error.fmt(f), - Error::YamlParsing(error) => error.fmt(f), - } - } -}*/ \ No newline at end of file +pub fn setup_logging(verbosity: u8) -> Result<(), fern::InitError> { + let mut base_config = fern::Dispatch::new(); + let colors = ColoredLevelConfig::new() + .info(Color::Green) + .debug(Color::Yellow) + .warn(Color::Magenta); + + base_config = match verbosity { + 0 => + base_config + .level(log::LevelFilter::Error), + 1 => + base_config + .level(log::LevelFilter::Warn), + 2 => + base_config.level(log::LevelFilter::Info) + .level_for("actix-web", log::LevelFilter::Warn), + 3 => + base_config.level(log::LevelFilter::Trace), + 4 => + base_config.level(log::LevelFilter::Error), + _4_or_more => + base_config.level(log::LevelFilter::Warn), + }; + + // Separate file config so we can include year, month and day in file logs + let file_config = fern::Dispatch::new() + .format(|out, message, record| { + out.finish(format_args!( + "{}[{}][{}] {}", + chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"), + record.target(), + record.level(), + message + )) + }) + .chain(fern::log_file("program.log")?); + + let stdout_config = fern::Dispatch::new() + .format(move |out, message, record| { + out.finish(format_args!( + "[{}][{}][{}] {}", + chrono::Local::now().format("%H:%M"), + record.target(), + colors.color(record.level()), + message + )) + }) + .chain(std::io::stdout()); + + base_config.chain(file_config).chain(stdout_config).apply()?; + Ok(()) +} \ No newline at end of file diff --git a/src/input/bot/mod.rs b/src/input/bot/mod.rs index e2af3b2e..2dcc2544 100644 --- a/src/input/bot/mod.rs +++ b/src/input/bot/mod.rs @@ -8,11 +8,14 @@ use serde_json; use telegram_bot::types::update::Update; use telegram_bot::types::update::UpdateKind; use telegram_bot::types::message::MessageKind; -use telegram_bot::types::refs::{ChatId, UserId}; +use telegram_bot::types::refs::{ChatId, MessageId, UserId}; -use crate::input::youtube_downloader::FeedbackChannel; +use crate::input::youtube_downloader::{self,FeedbackChannel}; use crate::input::web_api::server::{State}; +pub mod youtube_dl; +use youtube_dl::TelegramFeedback; + #[derive(Debug)] pub enum Error{ HttpClientError(reqwest::Error), @@ -20,7 +23,9 @@ pub enum Error{ InvalidServerResponse(reqwest::Response), UnhandledUpdateKind, UnhandledMessageKind, - UnknownCommand(String) + UnknownCommand(String), + SongDownloadError(youtube_downloader::Error), + Unauthorized(ChatId), } impl From for Error { @@ -29,12 +34,22 @@ impl From for Error { } } -fn to_string_and_ids(update: Update) -> Result<(String, ChatId, UserId),Error>{ +impl From for Error { + fn from(e: youtube_downloader::Error) -> Self { + Error::SongDownloadError(e) + } +} + +fn to_string_and_ids(update: Update) +-> Result<(String, ChatId, UserId, MessageId),Error>{ + if let UpdateKind::Message(message) = update.kind { let chat_id = message.chat.id(); let user_id = message.from.id; + let message_id = message.id; + if let MessageKind::Text{data, entities:_} = message.kind { - return Ok((data, chat_id, user_id)); + return Ok((data, chat_id, user_id, message_id)); } else { warn!("unhandled message kind"); return Err(Error::UnhandledUpdateKind); @@ -45,22 +60,27 @@ fn to_string_and_ids(update: Update) -> Result<(String, ChatId, UserId),Error>{ } } -async fn handle_command(text: String, chat_id: ChatId, - state: &State) -> Result<(), Error>{ +async fn handle_command(text: String, chat_id: ChatId, message_id: MessageId, + userid: UserId, state: &State) -> Result<(), Error>{ + if !state.valid_ids.contains(&userid){ + return Err(Error::Unauthorized(chat_id)); + } + let token = &state.bot_token; if text.contains("https://") || text.contains("http://") { + let fb = TelegramFeedback{chat_id, message_id}; state.youtube_dl.add_song_to_queue(text, - FeedbackChannel::Telegram(chat_id)).unwrap(); + FeedbackChannel::Telegram(fb)).await?; return Ok(()); } - let split = text.find(char::is_whitespace); - let mut command = text; + //let split = text.find(char::is_whitespace); + let command = text; //let args = command.split_off(split.unwrap_or(command.len())); match command.as_str() { "/test" => { - send_text_reply(chat_id, token, "hi").await?; + send_text(chat_id, token, "hi").await?; return Ok(()); } &_ => { @@ -84,21 +104,31 @@ async fn handle_error(error: Error, chat_id: ChatId, token: &str) { Error::InvalidServerResponse(resp) => { error!("Incorrect bot api response {:?}", resp); String::from(INT_ERR_TEXT)}, + Error::SongDownloadError(e) => { + error!("song download error {:?}", e); + String::from("Could not download song due to critical internal error") + } + Error::Unauthorized(chat_id) => { + format!("You are not authorized to use this bot, if you \ + believe this is a mistake ask for your telegram chat id \ + {} to be added", chat_id) + } Error::UnhandledMessageKind => { String::from(UNHANDLED)} Error::UnhandledUpdateKind => { String::from(UNHANDLED)} Error::CouldNotSetWebhook => unreachable!(), }; - if let Err(error) = send_text_reply(chat_id, token, error_message).await{ + if let Err(error) = send_text(chat_id, token, error_message).await{ error!("Could not send text reply to user: {:?}", error); } } async fn handle(update: Update, state: State){ let token = &state.bot_token; - if let Ok((text, chat_id, _user_id)) = to_string_and_ids(update){ - if let Err(error) = handle_command(text, chat_id, &state).await{ + if let Ok((text, chat_id, user_id, message_id)) = to_string_and_ids(update){ + if let Err(error) = handle_command(text, chat_id, + message_id, user_id, &state).await{ handle_error(error, chat_id, token).await; } } @@ -115,7 +145,7 @@ pub async fn handle_webhook(state: Data, raw_update: Bytes) .body("{}") } -pub async fn send_text_reply>(chat_id: ChatId, token: &str, text: T) +pub async fn send_text>(chat_id: ChatId, token: &str, text: T) -> Result<(), Error>{//add as arg generic ToChatRef (should get from Update) //TODO create a SendMessage, serialise it (use member function serialize) //then use the HttpRequest fields, (url, method, and body) to send to telegram diff --git a/src/input/bot/youtube_dl.rs b/src/input/bot/youtube_dl.rs new file mode 100644 index 00000000..ffd86906 --- /dev/null +++ b/src/input/bot/youtube_dl.rs @@ -0,0 +1,80 @@ +use telegram_bot::types::refs::{ChatId, MessageId}; +use async_trait::async_trait; + +use crate::input::youtube_downloader::{Feedback, JobStatus, MetaData}; +use super::{send_text, Error}; + +#[derive(Debug, Clone)] +pub struct TelegramFeedback { + pub chat_id: ChatId, + pub message_id: MessageId, +} + +//present options: +// Swap +// None +// Ok +// Lookup +impl TelegramFeedback { + async fn ask_name_artist(&self, token: &str, metadata: MetaData) + -> Result<(), Error> { + dbg!(); + let keyboard_json = "[\ + [{\"text\":\"swap\", \"callback_data\":\"swap\"}],\ + [{\"text\":\"none\", \"callback_data\":\"none\"}],\ + [{\"text\":\"ok\", \"callback_data\":\"none\"}],\ + [{\"text\":\"lookup\", \"callback_data\":\"none\"}]\ + ]"; + let reply_markup = format!("{{\"inline_keyboard\":{} }}", keyboard_json); + let text = format!("is _{}_ the title and the {} the artist?", + metadata.title, metadata.artist); + + let url = format!("https://api.telegram.org/bot{}/sendMessage", token); + let form = reqwest::multipart::Form::new() + .text("chat_id", self.chat_id.to_string()) + .text("text", text) + .text("parse_mode", "MarkdownV2"); + //.text("reply_to_message_id", self.message_id.to_string()) + //.text("reply_markup", reply_markup); + + dbg!(); + let client = reqwest::Client::new(); + let resp = client.post(&url) + .multipart(form).send().await?; + //https://stackoverflow.com/questions/57540455/error-blockingclientinfuturecontext-when-trying-to-make-a-request-from-within + + if resp.status() != reqwest::StatusCode::OK { + error!("telegram gave invalid response: {:?}", resp); + Err(Error::InvalidServerResponse(resp)) + } else { + dbg!("send message"); + Ok(()) + } + + } +} + +#[async_trait] +impl Feedback for TelegramFeedback { + //errors during feedback must be handled within feedback channel + async fn feedback(&self, status: JobStatus, token: &str) { + let res = match status { + JobStatus::Finished => { + send_text(self.chat_id, token, "finished").await + }, + JobStatus::Downloaded => { + send_text(self.chat_id, token, "done downloading").await + }, + JobStatus::Queued(meta_data) => { + self.ask_name_artist(token, meta_data).await + }, + JobStatus::Error => { + send_text(self.chat_id, token, "ran into error").await + }, + }; + + if let Err(e) = res { + error!("ran into error within feedback function: {:?}", e); + } + } +} \ No newline at end of file diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index dfcf461e..f2cc8be9 100755 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -183,11 +183,12 @@ pub struct SongUrl { url: String, } -pub fn add_song_from_url(params: Form, state: Data) -> HttpResponse { +pub async fn add_song_from_url(params: Form, state: Data) -> HttpResponse { let url = params.into_inner().url; dbg!(); - if state.youtube_dl.add_song_to_queue(url, FeedbackChannel::None).is_ok(){ + if state.youtube_dl.add_song_to_queue(url, FeedbackChannel::None) + .await.is_ok(){ dbg!(); HttpResponse::Ok().finish() diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index 4ea93f51..201bdecf 100755 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -1,5 +1,6 @@ use rustls::{NoClientAuth, ServerConfig}; use rustls::internal::pemfile::{certs, pkcs8_private_keys}; +use telegram_bot::types::refs::UserId; use actix_rt::System; use actix_web::{HttpServer,App, web, Responder}; @@ -38,6 +39,7 @@ pub struct State { pub free_session_ids: Arc, pub youtube_dl: input::YoutubeDownloader, pub bot_token: String, + pub valid_ids: Vec, } impl State { @@ -45,10 +47,15 @@ impl State { controller_tx: crossbeam_channel::Sender, alarms: input::alarms::Alarms, youtube_dl: input::YoutubeDownloader, - bot_token: String) -> Self { + bot_token: String, + valid_ids: Vec) -> Self { let free_session_ids = Arc::new(AtomicUsize::new(0)); let sessions = Arc::new(RwLock::new(HashMap::new())); + let valid_ids = valid_ids + .into_iter() + .map(|id| UserId::from(id)) + .collect(); State { controller_addr: controller_tx, @@ -58,6 +65,7 @@ impl State { sessions: sessions, free_session_ids: free_session_ids, bot_token, + valid_ids, } } } diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index 55cfa2d1..9dba0a06 100755 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -7,13 +7,14 @@ use std::thread; use std::time::Duration; use std::path::Path; -use telegram_bot::types::refs::ChatId; use reqwest::{IntoUrl}; use actix_rt; use regex::Regex; use serde::{Serialize, Deserialize}; use bincode; -use crate::input::bot::send_text_reply; +use async_trait::async_trait; + +use crate::input::bot::youtube_dl::TelegramFeedback; const DIR: &str = "temp"; const YOUTUBE_DL_LOC: &str = "temp/youtube-dl"; @@ -69,15 +70,20 @@ impl From for Error { } } +#[async_trait] +pub trait Feedback { + async fn feedback(&self, status: JobStatus, token: &str); +} + #[derive(Debug, Clone)] pub enum FeedbackChannel{ - Telegram(ChatId), + Telegram(TelegramFeedback), None, //future expand with ... signal? } #[derive(Debug)] -enum JobStatus { +pub enum JobStatus { Finished, Downloaded, Queued(MetaData), @@ -87,13 +93,7 @@ enum JobStatus { impl FeedbackChannel { async fn send(self, status: JobStatus, token: &str) { match self { - Self::Telegram(chat_id) => { - let message = format!("{:?}", status); - if let Err(e)=send_text_reply(chat_id, token, message).await { - error!("ran into error \ - sending text reply to bot user: {:?}", e); - }; - } + Self::Telegram(tel) => tel.feedback(status, token).await, Self::None => (), } } @@ -131,8 +131,8 @@ pub struct YoutubeDownloader { #[derive(Serialize, Deserialize, Default, Debug)] pub struct MetaData { - artist: String, - title: String, + pub artist: String, + pub title: String, } #[derive(Serialize, Deserialize, Default)] @@ -235,7 +235,7 @@ async fn download_song(url: &str, id: u64) -> Result<(), Error> { } let mut output_arg = String::from(temp_dir.to_str().unwrap()); - output_arg.push_str(&format!("/{}",id)); + output_arg.push_str(&format!("/{}.%(ext)s",id)); let output = download_file(&output_arg, url)?; dbg!(&output); @@ -323,7 +323,9 @@ fn song_downloader(url_rx: crossbeam_channel::Receiver, loop { match url_rx.recv() { Ok(job) => { - rt.block_on( handle_job(job, token.clone(), db.clone())); + if let Err(e) = rt.block_on( handle_job(job, token.clone(), db.clone())){ + error!("could not handle download job: {:?}", e); + } }, // Err means YoutubeDownloader // was dropped and this thread should stop @@ -361,8 +363,8 @@ impl YoutubeDownloader { /// checks if a song can be downloaded, if so sends the command to start download to /// a seperate thread - pub fn add_song_to_queue(&self, url: String, feedback: FeedbackChannel) - -> Result<(), Error> { + pub async fn add_song_to_queue(&self, url: String, + feedback: FeedbackChannel) -> Result<(), Error> { //get metadata guess from youtube-dl let meta_guess = get_meta(&url)?; @@ -377,7 +379,8 @@ impl YoutubeDownloader { let job = Job {id, url: url, feedback: feedback.clone()}; self.url_tx.try_send(job).unwrap(); - feedback.send(JobStatus::Queued(meta_guess), &self.token); + feedback.send(JobStatus::Queued(meta_guess), &self.token).await; + dbg!(); Ok(()) } } diff --git a/src/main.rs b/src/main.rs index a267490b..61c0fd69 100755 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,11 @@ #[macro_use] extern crate log; -extern crate chrono; +use chrono; use structopt::StructOpt; use sled; use std::path::PathBuf; +use telegram_bot::types::refs::UserId; mod controller; @@ -40,13 +41,17 @@ struct Opt { dataserver_key: u64, #[structopt(short = "k", long = "keys", default_value="keys")] - key_dir: PathBuf, + key_dir: PathBuf, + + #[structopt(short = "i", long = "allowed-telegram-ids")] + valid_ids: Vec, } #[actix_rt::main] async fn main() { let opt = Opt::from_args(); - + errors::setup_logging(1).unwrap(); + let db = sled::Config::default() //651ms .path("database") .flush_every_ms(None) //do not flush to disk unless explicitly asked @@ -76,7 +81,8 @@ async fn main() { controller_tx.clone(), alarms, youtube_dl, - opt.token.clone()); + opt.token.clone(), + opt.valid_ids.clone()); //start the webserver let web_handle = server::start_webserver( @@ -95,7 +101,9 @@ async fn main() { #[cfg(feature = "sensors_connected")] input::buttons::start_monitoring(controller_tx.clone()).unwrap(); - loop {} + loop { + std::thread::park(); + } /*println!("press: q to quit"); loop { From 91efec86e784ecadc5cd0b4f9fecd2b80050a84c Mon Sep 17 00:00:00 2001 From: dskleingeld Date: Mon, 2 Mar 2020 01:45:05 +0100 Subject: [PATCH 032/687] adds formatting to telegram feedback --- src/input/bot/youtube_dl.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/input/bot/youtube_dl.rs b/src/input/bot/youtube_dl.rs index ffd86906..c0cf0f30 100644 --- a/src/input/bot/youtube_dl.rs +++ b/src/input/bot/youtube_dl.rs @@ -26,16 +26,16 @@ impl TelegramFeedback { [{\"text\":\"lookup\", \"callback_data\":\"none\"}]\ ]"; let reply_markup = format!("{{\"inline_keyboard\":{} }}", keyboard_json); - let text = format!("is _{}_ the title and the {} the artist?", + let text = format!("is _{}_ the title and __{}__ the artist?", metadata.title, metadata.artist); let url = format!("https://api.telegram.org/bot{}/sendMessage", token); let form = reqwest::multipart::Form::new() .text("chat_id", self.chat_id.to_string()) .text("text", text) - .text("parse_mode", "MarkdownV2"); - //.text("reply_to_message_id", self.message_id.to_string()) - //.text("reply_markup", reply_markup); + .text("parse_mode", "Markdown") + .text("reply_to_message_id", self.message_id.to_string()) + .text("reply_markup", reply_markup); dbg!(); let client = reqwest::Client::new(); From ccc26eb99012c5c31dcdf9dae481ac880fdfcb70 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Sat, 7 Mar 2020 17:30:05 +0100 Subject: [PATCH 033/687] add youtube dl with save after artist/title confirm --- Cargo.toml | 2 +- src/input/bot/mod.rs | 54 ++++-- src/input/bot/youtube_dl.rs | 95 ++++++++-- src/input/youtube_downloader.rs | 302 ++++++++++++++++++++++++-------- src/main.rs | 6 +- 5 files changed, 349 insertions(+), 110 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 742e5222..15f8dc8f 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,7 +65,7 @@ dirs = "2" rand = "0.6" retry = "0.5" -telegram-bot = "0.6" +telegram-bot = "0.6.3" serde_json = "1.0" regex = "1" bincode = "1.2" \ No newline at end of file diff --git a/src/input/bot/mod.rs b/src/input/bot/mod.rs index 2dcc2544..37925b92 100644 --- a/src/input/bot/mod.rs +++ b/src/input/bot/mod.rs @@ -8,6 +8,8 @@ use serde_json; use telegram_bot::types::update::Update; use telegram_bot::types::update::UpdateKind; use telegram_bot::types::message::MessageKind; +use telegram_bot::types::message::Message; +use telegram_bot::types::callback_query::CallbackQuery; use telegram_bot::types::refs::{ChatId, MessageId, UserId}; use crate::input::youtube_downloader::{self,FeedbackChannel}; @@ -40,10 +42,9 @@ impl From for Error { } } -fn to_string_and_ids(update: Update) +fn to_string_and_ids(message: Message) -> Result<(String, ChatId, UserId, MessageId),Error>{ - if let UpdateKind::Message(message) = update.kind { let chat_id = message.chat.id(); let user_id = message.from.id; let message_id = message.id; @@ -54,10 +55,6 @@ fn to_string_and_ids(update: Update) warn!("unhandled message kind"); return Err(Error::UnhandledUpdateKind); } - } else { - warn!("unhandled update from telegram: {:?}", update); - return Err(Error::UnhandledMessageKind); - } } async fn handle_command(text: String, chat_id: ChatId, message_id: MessageId, @@ -92,6 +89,29 @@ async fn handle_command(text: String, chat_id: ChatId, message_id: MessageId, return Err(Error::UnknownCommand(command)); } +async fn handle_callback(callback: CallbackQuery, state: &State) { + + if !state.valid_ids.contains(&callback.from.id){ + warn!("Unauthorized callback, userid: {}", callback.from.id); + return; //no need for error handling, just drop callback + } + + let header = callback.data.split_terminator(":").next(); + let res = match header { + Some("ytdl") => { + youtube_dl::handle_callback(callback, state).await + } + _ => { + warn!("unhandled callback, data: {}\nfull_callback: {:?}", + callback.data, callback); + Ok(()) //user need not be warned as user is dev + }, + }; + if let Err(e) = res { + error!("ran into error handling callback: {:?}", e); + } +} + const INT_ERR_TEXT: &str = "apologies, an internal error happend this has been reported and will be fixed as soon as possible"; const UNHANDLED: &str = "sorry I can not understand your input"; async fn handle_error(error: Error, chat_id: ChatId, token: &str) { @@ -124,12 +144,24 @@ async fn handle_error(error: Error, chat_id: ChatId, token: &str) { } } -async fn handle(update: Update, state: State){ +async fn handle(update: Update, state: State){//TODO change to ref let token = &state.bot_token; - if let Ok((text, chat_id, user_id, message_id)) = to_string_and_ids(update){ - if let Err(error) = handle_command(text, chat_id, - message_id, user_id, &state).await{ - handle_error(error, chat_id, token).await; + match update.kind { + UpdateKind::Message(messg) => { + if let Ok((text, chat_id, user_id, message_id)) = to_string_and_ids(messg){ + if let Err(error) = handle_command(text, chat_id, + message_id, user_id, &state).await{ + handle_error(error, chat_id, token).await; + } + } + } + UpdateKind::CallbackQuery(callback) => { + let chat_id = callback.message.chat.id(); + handle_callback(callback, &state).await; + + } + _ => { + warn!("unhandled update from telegram: {:?}", update); } } } diff --git a/src/input/bot/youtube_dl.rs b/src/input/bot/youtube_dl.rs index c0cf0f30..65eb13c0 100644 --- a/src/input/bot/youtube_dl.rs +++ b/src/input/bot/youtube_dl.rs @@ -1,8 +1,11 @@ use telegram_bot::types::refs::{ChatId, MessageId}; +use telegram_bot::types::callback_query::CallbackQuery; use async_trait::async_trait; -use crate::input::youtube_downloader::{Feedback, JobStatus, MetaData}; -use super::{send_text, Error}; +use crate::input::youtube_downloader::{self, Feedback, JobStatus, MetaGuess}; +use crate::input::web_api::server::{State}; +use super::send_text; +use super::Error as BotError; #[derive(Debug, Clone)] pub struct TelegramFeedback { @@ -16,26 +19,30 @@ pub struct TelegramFeedback { // Ok // Lookup impl TelegramFeedback { - async fn ask_name_artist(&self, token: &str, metadata: MetaData) - -> Result<(), Error> { + async fn ask_name_artist(&self, token: &str, meta: MetaGuess, id: u64) + -> Result<(), BotError> { dbg!(); - let keyboard_json = "[\ - [{\"text\":\"swap\", \"callback_data\":\"swap\"}],\ - [{\"text\":\"none\", \"callback_data\":\"none\"}],\ - [{\"text\":\"ok\", \"callback_data\":\"none\"}],\ - [{\"text\":\"lookup\", \"callback_data\":\"none\"}]\ - ]"; + let keyboard_json = format!("[\ + [{{\"text\":\"swap\", \"callback_data\":\"ytdl:swap:{id}:{title}:{artist}\"}}],\ + [{{\"text\":\"no\", \"callback_data\":\"ytdl:no:{id}:{title}:{artist}\"}}],\ + [{{\"text\":\"ok\", \"callback_data\":\"ytdl:ok:{id}:{title}:{artist}\"}}],\ + [{{\"text\":\"lookup\", \"callback_data\":\"ytdl:lookup:{id}:{title}:{artist}\"}}]\ + ]",id=id,title=meta.title, artist=meta.artist); let reply_markup = format!("{{\"inline_keyboard\":{} }}", keyboard_json); - let text = format!("is _{}_ the title and __{}__ the artist?", - metadata.title, metadata.artist); + let text = format!("is _{}_ the title and _{}_ the artist?", + meta.title, meta.artist); + //TODO: should always base this on metadata guess, should make that a + //seperate type + dbg!(&text); + dbg!(&reply_markup); let url = format!("https://api.telegram.org/bot{}/sendMessage", token); let form = reqwest::multipart::Form::new() .text("chat_id", self.chat_id.to_string()) .text("text", text) .text("parse_mode", "Markdown") - .text("reply_to_message_id", self.message_id.to_string()) - .text("reply_markup", reply_markup); + .text("reply_to_message_id", self.message_id.to_string()); + //.text("reply_markup", reply_markup); dbg!(); let client = reqwest::Client::new(); @@ -45,7 +52,7 @@ impl TelegramFeedback { if resp.status() != reqwest::StatusCode::OK { error!("telegram gave invalid response: {:?}", resp); - Err(Error::InvalidServerResponse(resp)) + Err(BotError::InvalidServerResponse(resp)) } else { dbg!("send message"); Ok(()) @@ -58,15 +65,16 @@ impl TelegramFeedback { impl Feedback for TelegramFeedback { //errors during feedback must be handled within feedback channel async fn feedback(&self, status: JobStatus, token: &str) { - let res = match status { + let res: Result<(),BotError> = match status { JobStatus::Finished => { send_text(self.chat_id, token, "finished").await }, JobStatus::Downloaded => { send_text(self.chat_id, token, "done downloading").await }, - JobStatus::Queued(meta_data) => { - self.ask_name_artist(token, meta_data).await + JobStatus::Queued(meta_data, id) => { + self.ask_name_artist(token, meta_data, id).await + .map_err(|e| e.into()) }, JobStatus::Error => { send_text(self.chat_id, token, "ran into error").await @@ -77,4 +85,55 @@ impl Feedback for TelegramFeedback { error!("ran into error within feedback function: {:?}", e); } } +} + +#[derive(Debug)] +pub enum Error { + ParseError(std::num::ParseIntError), + YoutubeDlError(youtube_downloader::Error), + NotEnoughData, +} + +impl From for Error { + fn from(err: std::num::ParseIntError) -> Error { + Error::ParseError(err) + } +} + +impl From for Error { + fn from(err: youtube_downloader::Error) -> Error { + Error::YoutubeDlError(err) + } +} + +pub async fn handle_callback(callback: CallbackQuery, state: &State) + -> Result<(), Error> { + + let mut split = callback.data.split_terminator(":").skip(1); + let command = split.next(); + match command { + Some("swap") => { + let id = split.next().ok_or(Error::NotEnoughData)?.parse()?; + let title = split.next().ok_or(Error::NotEnoughData)?; + let artist = split.next().ok_or(Error::NotEnoughData)?; + state.youtube_dl.set_meta(id, artist, title).await? //artist an title swapped + } + Some("ok") => { + let id = split.next().ok_or(Error::NotEnoughData)?.parse()?; + let title = split.next().ok_or(Error::NotEnoughData)?; + let artist = split.next().ok_or(Error::NotEnoughData)?; + dbg!("handling callback"); + state.youtube_dl.set_meta(id, title, artist).await? + } + Some("no") => { + let id = split.next().ok_or(Error::NotEnoughData)?.parse()?; + let title = split.next().ok_or(Error::NotEnoughData)?; + state.youtube_dl.no_meta(id, title).await? + } + Some("lookup") => todo!(), + _ => { + error!("cant handle youtube_dl callback command: {:?}", command); + }, + } + Ok(()) } \ No newline at end of file diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index 9dba0a06..d560f8b2 100755 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -5,21 +5,22 @@ use std::os::unix::fs::OpenOptionsExt; use std::thread; use std::time::Duration; -use std::path::Path; +use std::path::{Path, PathBuf}; use reqwest::{IntoUrl}; use actix_rt; -use regex::Regex; use serde::{Serialize, Deserialize}; use bincode; use async_trait::async_trait; +use async_std::task; +use sled::Batch; use crate::input::bot::youtube_dl::TelegramFeedback; const DIR: &str = "temp"; const YOUTUBE_DL_LOC: &str = "temp/youtube-dl"; const MUSIC_TEMP: &str = "temp/music"; -const MUSIC_DIR: &str = "/home/pi/Music/youtube"; +const MUSIC_DIR: &str = "/home/pi/Music"; #[derive(Debug)] pub enum Error{ @@ -30,6 +31,9 @@ pub enum Error{ CouldNotCreateTempDir(std::io::Error), UnexpectedYoutubeDlStdOut(String), UnsupportedSource(String), + CanNoLongerUpdateMeta, + CanNotSwapArtistWithEmptyTitle, + IDWasDeleted, } impl std::fmt::Display for Error { @@ -50,6 +54,13 @@ impl std::fmt::Display for Error { write!(f, "Could not understand output of youtube-dl, output was: {}",s), Error::UnsupportedSource(s) => write!(f, "Could not find something to download: {}", s), + Error::CanNoLongerUpdateMeta => + write!(f, "Can no longer update metadata, was already done some time ago"), + Error::CanNotSwapArtistWithEmptyTitle => + write!(f, "Can not swap artist and title as the current artist \ + is empty and the title can not be empty. Not writing metadata"), + Error::IDWasDeleted => + write!(f, "Internal error, file not in database"), } } } @@ -86,7 +97,7 @@ pub enum FeedbackChannel{ pub enum JobStatus { Finished, Downloaded, - Queued(MetaData), + Queued(MetaGuess, u64), Error, } @@ -135,28 +146,49 @@ pub struct MetaData { pub title: String, } -#[derive(Serialize, Deserialize, Default)] -struct DbEntry { - downloaded: bool, //default val = false - meta: Option +#[derive(Serialize, Deserialize, Default, Debug, Clone)] +pub struct MetaGuess { + pub artist: String, + pub title: String, } -impl DbEntry { - fn empty() -> Self { - DbEntry { - downloaded: false, - meta: None, - } - } - fn downloaded() -> Self { - DbEntry { - downloaded: true, - meta: None, - } +// in the future queued an downloaded can be expanded +// with a MetaGuess +#[derive(Serialize, Deserialize)] +enum Status { + Queued(MetaGuess), //can go to Downloaded or ConfirmedMeta + Downloaded(MetaGuess), // can go to Metawritten (as soon as there is meta we write it to file) + MetaConfirmed(MetaData), //can go to MetaWritten (as soon as download is complete meta written to file) + MetaWritten((PathBuf, MetaData)), //can only tranfrom to WritingMeta +} + +fn split(to_split_on: &str) -> (&str, &str){ + //try splitting on title + let new_title; + let new_artist; + + if to_split_on.contains("-"){ + let mut split = to_split_on.splitn(2,"-"); + new_title = split.next().unwrap(); + new_artist = split.next().unwrap(); + } else if to_split_on.contains(":"){ + let mut split = to_split_on.splitn(2,":"); + new_title = split.next().unwrap(); + new_artist = split.next().unwrap(); + } else if to_split_on.contains("|"){ + let mut split = to_split_on.splitn(2,"|"); + new_title = split.next().unwrap(); + new_artist = split.next().unwrap(); + } else { + new_title = to_split_on; + new_artist = "unknown"; } + + (new_title.trim(), new_artist.trim()) } -fn get_meta(url: &str) -> Result { + +fn guess_meta(url: &str) -> Result { let full_path = Path::new(YOUTUBE_DL_LOC); let output = Command::new(full_path) @@ -177,22 +209,31 @@ fn get_meta(url: &str) -> Result { .arg("bestaudio[acodec=opus]/bestaudio/best") .arg("--output") - .arg("/%(title)s-#-#-%(artist)s") + .arg("%(title)s-#-#-%(artist)s") .arg(url) .output()?; let stdout = String::from_utf8(output.stdout).unwrap(); let mut title_artist = stdout.splitn(2, "-#-#-"); - let metadata = MetaData { - artist: title_artist.next() - .map(|s| s.to_owned()) - .ok_or(Error::UnsupportedSource(stdout.clone()))?, - title: title_artist.next() - .map(|s| s.to_owned()) - .ok_or(Error::UnsupportedSource(stdout.clone()))?, + let artist = title_artist.next() + .map(|s| s.trim()) + .ok_or(Error::UnsupportedSource(stdout.clone()))?; + let title = title_artist.next() + .map(|s| s.trim()) + .ok_or(Error::UnsupportedSource(stdout.clone()))?; + + let (artist, title) = if artist.contains("NA"){ + split(title) + } else if title.contains("NA"){ + split(artist) + } else { + (artist, title) }; - Ok(metadata) + Ok(MetaGuess { + artist: artist.to_owned(), + title: title.to_owned() + }) } fn download_file(output_arg: &String, url: &str) @@ -240,7 +281,7 @@ async fn download_song(url: &str, id: u64) -> Result<(), Error> { let output = download_file(&output_arg, url)?; dbg!(&output); - let output = if !output.status.success() { + if !output.status.success() { let since_last_updated = fs::metadata(YOUTUBE_DL_LOC).unwrap() .created().unwrap() .elapsed().unwrap_or(Duration::from_secs(0)); @@ -255,59 +296,93 @@ async fn download_song(url: &str, id: u64) -> Result<(), Error> { if !output.status.success() { return Err(Error::CouldNotDownloadSong(output)); } - output - } else {output}; - - //let title = parse_stdout(output.stdout)?; - - //mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| c.rescan())?; - //Ok(title) + } Ok(()) } -fn get_metadata(db: sled::Tree, id: u64) - -> Result, Error> { +fn write_metadata(id: u64, meta: &MetaData) -> Result { + let mut old_path = PathBuf::from(MUSIC_TEMP); + old_path.push(id.to_string()); + old_path.set_extension("m4a"); - let modification = db.compare_and_swap( - id.to_be_bytes(), - Some(bincode::serialize(&DbEntry::empty()).unwrap() ), - Some(bincode::serialize(&DbEntry::downloaded()).unwrap() ), - ).unwrap(); - - //if the modification was an error (not swapped) the entry was not - //empty and thus has metadata, return the metadata. - if let Err(old_value) = modification { - let with_metadata: DbEntry = bincode::deserialize( - &old_value - .current.unwrap() - .to_vec() ).unwrap(); - Ok(with_metadata.meta) - } else { - Ok(None) + let mut new_path = PathBuf::from(MUSIC_DIR); + new_path.push(&meta.artist); + if !new_path.exists() { + fs::create_dir(&new_path)?; } + new_path.push(&meta.title); + new_path.set_extension("m4a"); + dbg!(&old_path); + dbg!(&new_path); + fs::rename(old_path, &new_path).unwrap(); + mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| c.rescan())?; + + Ok(new_path) } -fn write_metadata(meta: MetaData, id: u64) -> Result<(), Error> { - //move file from temp/id to music/artist/title - //or in case metadata is wierd (tbdefined) to - //music/youtube/title.. - todo!(); +fn update_metadata(old_path: &Path, meta: &MetaData) -> Result { + let mut new_path = PathBuf::from(MUSIC_DIR); + new_path.push(&meta.artist); + if !new_path.exists() { + fs::create_dir(&new_path)?; + } + new_path.push(&meta.title); + new_path.set_extension("m4a"); + fs::rename(old_path, &new_path).unwrap(); + + //delete if parent dir is now empty + if let Some(dir) = old_path.parent(){ + if dir.read_dir().unwrap().count() == 0 { + fs::remove_dir(dir).unwrap(); + } + } + + mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| c.rescan())?; + + Ok(new_path) } async fn handle_job(job: Job, token: String, db: sled::Tree) -> Result<(), Error> { let status = match download_song(&job.url, job.id).await { - Ok(_) => { - if let Some(meta) = get_metadata(db, job.id)?{ - write_metadata(meta, job.id)?; - JobStatus::Finished - } else { - JobStatus::Downloaded - } + Ok(_) => { + aquire_db_mutex(&db, job.id).await; + let db_status = db.get(&status_key(job.id)) + .unwrap() + .ok_or(Error::CanNoLongerUpdateMeta)?; + let db_status = bincode::deserialize(&db_status.to_vec()).unwrap(); + let (new_db_status, job_status) = match db_status { + Status::Queued(meta_guess) => { + (Status::Downloaded(meta_guess), JobStatus::Downloaded) + }, + Status::MetaConfirmed(meta) => { + let new_path = write_metadata(job.id, &meta)?; //write meta + (Status::MetaWritten((new_path, meta)), JobStatus::Finished) + }, + Status::Downloaded(_) => { + panic!("file should not yet be download!") + }, + Status::MetaWritten((_, _)) => { + panic!("file should not yet be download!") + }, + }; + + let mut batch = Batch::default(); + batch.insert( + &status_key(job.id), + bincode::serialize(&new_db_status).unwrap() + ); + batch.insert( //unlock file lock + &db_mutex_key(job.id), + bincode::serialize(&false).unwrap() + ); + db.apply_batch(batch).unwrap(); + job_status }, Err(error) => { error!("warn error during song download: {:?}", error); + //TODO remove from database JobStatus::Error }, }; @@ -334,6 +409,26 @@ fn song_downloader(url_rx: crossbeam_channel::Receiver, } } +async fn aquire_db_mutex(db: &sled::Tree, id: u64){ + while let Err(_is_locked) = db.compare_and_swap( + &db_mutex_key(id), + Some(bincode::serialize(&false).unwrap()), + Some(bincode::serialize(&true).unwrap())).unwrap(){ + task::sleep(Duration::from_millis(10)).await; + dbg!("blocking on mutex aquisition"); + } +} + +fn db_mutex_key(id: u64) -> [u8;9]{ + let mut a = [0;9]; + a[..8].clone_from_slice(&id.to_be_bytes()); + return a; +} +fn status_key(id: u64) -> [u8;9]{ + let mut a = [1;9]; + a[..8].clone_from_slice(&id.to_be_bytes()); + return a; +} impl YoutubeDownloader { pub async fn init(token: String, db: sled::Db) @@ -367,22 +462,77 @@ impl YoutubeDownloader { feedback: FeedbackChannel) -> Result<(), Error> { //get metadata guess from youtube-dl - let meta_guess = get_meta(&url)?; + let meta_guess = guess_meta(&url)?; let id = self.db.generate_id().unwrap(); - let youtube_db = self.db.open_tree("youtube_dl").unwrap(); - - let db_entry = DbEntry::default(); - youtube_db.insert( - id.to_be_bytes(), + let db = self.db.open_tree("youtube_dl").unwrap(); + + let db_entry = Status::Queued(meta_guess.clone()); + let mut batch = Batch::default(); + batch.insert( + &status_key(id), bincode::serialize(&db_entry).unwrap() - ).unwrap(); + ); + batch.insert( + &db_mutex_key(id), + bincode::serialize(&false).unwrap() + ); + db.apply_batch(batch).unwrap(); let job = Job {id, url: url, feedback: feedback.clone()}; self.url_tx.try_send(job).unwrap(); - feedback.send(JobStatus::Queued(meta_guess), &self.token).await; + feedback.send(JobStatus::Queued(meta_guess, id), &self.token).await; dbg!(); Ok(()) } + + pub async fn set_meta(&self, id: u64, title: &str, artist: &str) + -> Result<(), Error> { + + let db = self.db.open_tree("youtube_dl").unwrap(); + + let new_meta = MetaData { + title: title.to_owned(), + artist: artist.to_owned(), + }; + + aquire_db_mutex(&db, id).await; + let job_status = db.get(&status_key(id)) + .unwrap() + .ok_or(Error::CanNoLongerUpdateMeta)?; + let job_status = bincode::deserialize(&job_status.to_vec()).unwrap(); + let new_status = match job_status { + Status::Queued(_) => { + Status::MetaConfirmed(new_meta) + }, + Status::MetaConfirmed(_) => { + Status::MetaConfirmed(new_meta) + }, + Status::Downloaded(_) => { + let new_path = write_metadata(id, &new_meta)?; + Status::MetaWritten((new_path, new_meta)) + }, + Status::MetaWritten((path, _)) => { + let new_path = update_metadata(&path, &new_meta)?; + Status::MetaWritten((new_path, new_meta)) + }, + }; + + let mut batch = Batch::default(); + batch.insert( + &status_key(id), + bincode::serialize(&new_status).unwrap() + ); + batch.insert( //unlock file lock + &db_mutex_key(id), + bincode::serialize(&false).unwrap() + ); + db.apply_batch(batch).unwrap(); + Ok(()) + } + + pub async fn no_meta(&self, id: u64, title: &str) -> Result<(), Error> { + self.set_meta(id, title, "none").await + } } diff --git a/src/main.rs b/src/main.rs index 61c0fd69..b4d97d85 100755 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,9 @@ #[macro_use] extern crate log; -use chrono; use structopt::StructOpt; use sled; use std::path::PathBuf; -use telegram_bot::types::refs::UserId; mod controller; @@ -68,7 +66,7 @@ async fn main() { db.clone()).unwrap(); let (youtube_dl, _downloader_thread) = input::YoutubeDownloader::init( opt.token.clone(), db.clone()).await.unwrap(); - let (mpd_status, _mpd_watcher_thread, updater_tx) = + let (mpd_status, _mpd_watcher_thread, _updater_tx) = input::MpdStatus::start_updating() .unwrap(); @@ -85,7 +83,7 @@ async fn main() { opt.valid_ids.clone()); //start the webserver - let web_handle = server::start_webserver( + let _web_handle = server::start_webserver( &opt.key_dir, state, opt.port, opt.domain.clone()).unwrap(); From 9b41a1bc7c3554441deedb11f865da32ae8749be Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Sat, 7 Mar 2020 22:34:34 +0100 Subject: [PATCH 034/687] youtube-dl ok and swap button working --- Cargo.toml | 3 +- src/input/bot/youtube_dl.rs | 25 ++--- src/input/youtube_downloader.rs | 173 ++++++++++++++++++++++++++------ 3 files changed, 155 insertions(+), 46 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 15f8dc8f..96b91f00 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,4 +68,5 @@ retry = "0.5" telegram-bot = "0.6.3" serde_json = "1.0" regex = "1" -bincode = "1.2" \ No newline at end of file +bincode = "1.2" +#id3 = "0.5.0" \ No newline at end of file diff --git a/src/input/bot/youtube_dl.rs b/src/input/bot/youtube_dl.rs index 65eb13c0..a0681ebc 100644 --- a/src/input/bot/youtube_dl.rs +++ b/src/input/bot/youtube_dl.rs @@ -23,11 +23,11 @@ impl TelegramFeedback { -> Result<(), BotError> { dbg!(); let keyboard_json = format!("[\ - [{{\"text\":\"swap\", \"callback_data\":\"ytdl:swap:{id}:{title}:{artist}\"}}],\ - [{{\"text\":\"no\", \"callback_data\":\"ytdl:no:{id}:{title}:{artist}\"}}],\ - [{{\"text\":\"ok\", \"callback_data\":\"ytdl:ok:{id}:{title}:{artist}\"}}],\ - [{{\"text\":\"lookup\", \"callback_data\":\"ytdl:lookup:{id}:{title}:{artist}\"}}]\ - ]",id=id,title=meta.title, artist=meta.artist); + [{{\"text\":\"swap\", \"callback_data\":\"ytdl:swap:{id}\"}}],\ + [{{\"text\":\"no\", \"callback_data\":\"ytdl:no:{id}\"}}],\ + [{{\"text\":\"ok\", \"callback_data\":\"ytdl:ok:{id}\"}}],\ + [{{\"text\":\"lookup\", \"callback_data\":\"ytdl:lookup:{id}\"}}]\ + ]",id=id); let reply_markup = format!("{{\"inline_keyboard\":{} }}", keyboard_json); let text = format!("is _{}_ the title and _{}_ the artist?", meta.title, meta.artist); @@ -41,8 +41,8 @@ impl TelegramFeedback { .text("chat_id", self.chat_id.to_string()) .text("text", text) .text("parse_mode", "Markdown") - .text("reply_to_message_id", self.message_id.to_string()); - //.text("reply_markup", reply_markup); + .text("reply_to_message_id", self.message_id.to_string()) + .text("reply_markup", reply_markup); dbg!(); let client = reqwest::Client::new(); @@ -114,21 +114,16 @@ pub async fn handle_callback(callback: CallbackQuery, state: &State) match command { Some("swap") => { let id = split.next().ok_or(Error::NotEnoughData)?.parse()?; - let title = split.next().ok_or(Error::NotEnoughData)?; - let artist = split.next().ok_or(Error::NotEnoughData)?; - state.youtube_dl.set_meta(id, artist, title).await? //artist an title swapped + state.youtube_dl.swap_meta(id).await? //artist an title swapped } Some("ok") => { let id = split.next().ok_or(Error::NotEnoughData)?.parse()?; - let title = split.next().ok_or(Error::NotEnoughData)?; - let artist = split.next().ok_or(Error::NotEnoughData)?; dbg!("handling callback"); - state.youtube_dl.set_meta(id, title, artist).await? + state.youtube_dl.meta_ok(id).await? } Some("no") => { let id = split.next().ok_or(Error::NotEnoughData)?.parse()?; - let title = split.next().ok_or(Error::NotEnoughData)?; - state.youtube_dl.no_meta(id, title).await? + state.youtube_dl.no_meta(id).await? } Some("lookup") => todo!(), _ => { diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index d560f8b2..db654c13 100755 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -14,6 +14,7 @@ use bincode; use async_trait::async_trait; use async_std::task; use sled::Batch; +use id3; use crate::input::bot::youtube_dl::TelegramFeedback; @@ -144,12 +145,24 @@ pub struct YoutubeDownloader { pub struct MetaData { pub artist: String, pub title: String, + pub source_url: String, } #[derive(Serialize, Deserialize, Default, Debug, Clone)] pub struct MetaGuess { pub artist: String, pub title: String, + pub source_url: String, +} + +impl MetaData { + fn to_tag(&self) -> id3::Tag { + let mut tag = id3::Tag::new(); + tag.set_artist(&self.artist); + tag.set_title(&self.title); + //tag.set_text("source: ",&self.source_url); + tag + } } // in the future queued an downloaded can be expanded @@ -209,30 +222,18 @@ fn guess_meta(url: &str) -> Result { .arg("bestaudio[acodec=opus]/bestaudio/best") .arg("--output") - .arg("%(title)s-#-#-%(artist)s") + .arg("%(title)s") .arg(url) .output()?; let stdout = String::from_utf8(output.stdout).unwrap(); - let mut title_artist = stdout.splitn(2, "-#-#-"); - let artist = title_artist.next() - .map(|s| s.trim()) - .ok_or(Error::UnsupportedSource(stdout.clone()))?; - let title = title_artist.next() - .map(|s| s.trim()) - .ok_or(Error::UnsupportedSource(stdout.clone()))?; - - let (artist, title) = if artist.contains("NA"){ - split(title) - } else if title.contains("NA"){ - split(artist) - } else { - (artist, title) - }; + dbg!(&stdout); + let (artist, title) = split(&stdout); Ok(MetaGuess { artist: artist.to_owned(), - title: title.to_owned() + title: title.to_owned(), + source_url: url.to_owned(), }) } @@ -315,6 +316,10 @@ fn write_metadata(id: u64, meta: &MetaData) -> Result { dbg!(&old_path); dbg!(&new_path); fs::rename(old_path, &new_path).unwrap(); + + /*meta.to_tag() //not working, corrupts files + .write_to_path(&new_path, id3::Version::Id3v24) + .unwrap();*/ mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| c.rescan())?; Ok(new_path) @@ -337,6 +342,9 @@ fn update_metadata(old_path: &Path, meta: &MetaData) -> Result { } } + /*meta.to_tag() //not working, corrupts files + .write_to_path(&new_path, id3::Version::Id3v24) + .unwrap();*/ mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| c.rescan())?; Ok(new_path) @@ -485,15 +493,55 @@ impl YoutubeDownloader { Ok(()) } - pub async fn set_meta(&self, id: u64, title: &str, artist: &str) + pub async fn meta_ok(&self, id: u64) -> Result<(), Error> { let db = self.db.open_tree("youtube_dl").unwrap(); - let new_meta = MetaData { - title: title.to_owned(), - artist: artist.to_owned(), + aquire_db_mutex(&db, id).await; + let job_status = db.get(&status_key(id)) + .unwrap() + .ok_or(Error::CanNoLongerUpdateMeta)?; + let job_status = bincode::deserialize(&job_status.to_vec()).unwrap(); + let new_status = match job_status { + Status::Queued(meta_guess) => { + let new_meta = MetaData { + title: meta_guess.title, + artist: meta_guess.artist, + source_url: meta_guess.source_url, + }; + Status::MetaConfirmed(new_meta) + }, + Status::MetaConfirmed(meta) => Status::MetaConfirmed(meta), + Status::Downloaded(meta_guess) => { + let new_meta = MetaData { + title: meta_guess.title, + artist: meta_guess.artist, + source_url: meta_guess.source_url, + }; + let new_path = write_metadata(id, &new_meta)?; + Status::MetaWritten((new_path, new_meta)) + }, + Status::MetaWritten(i) => Status::MetaWritten(i), }; + + let mut batch = Batch::default(); + batch.insert( + &status_key(id), + bincode::serialize(&new_status).unwrap() + ); + batch.insert( //unlock file lock + &db_mutex_key(id), + bincode::serialize(&false).unwrap() + ); + db.apply_batch(batch).unwrap(); + Ok(()) + } + + pub async fn swap_meta(&self, id: u64) + -> Result<(), Error> { + + let db = self.db.open_tree("youtube_dl").unwrap(); aquire_db_mutex(&db, id).await; let job_status = db.get(&status_key(id)) @@ -501,19 +549,33 @@ impl YoutubeDownloader { .ok_or(Error::CanNoLongerUpdateMeta)?; let job_status = bincode::deserialize(&job_status.to_vec()).unwrap(); let new_status = match job_status { - Status::Queued(_) => { + Status::Queued(meta_guess) => { + let new_meta = MetaData { + title: meta_guess.artist, + artist: meta_guess.title, + source_url: meta_guess.source_url, + }; Status::MetaConfirmed(new_meta) }, - Status::MetaConfirmed(_) => { - Status::MetaConfirmed(new_meta) + Status::MetaConfirmed(mut meta) => { + meta.title = meta.artist.clone(); + meta.artist = meta.title.clone(); + Status::MetaConfirmed(meta) }, - Status::Downloaded(_) => { + Status::Downloaded(meta_guess) => { + let new_meta = MetaData { + title: meta_guess.artist, + artist: meta_guess.title, + source_url: meta_guess.source_url, + }; let new_path = write_metadata(id, &new_meta)?; Status::MetaWritten((new_path, new_meta)) }, - Status::MetaWritten((path, _)) => { - let new_path = update_metadata(&path, &new_meta)?; - Status::MetaWritten((new_path, new_meta)) + Status::MetaWritten((path, mut meta)) => { + meta.artist = meta.title.clone(); + meta.title = meta.artist.clone(); + let new_path = update_metadata(&path, &meta)?; + Status::MetaWritten((new_path, meta)) }, }; @@ -530,8 +592,59 @@ impl YoutubeDownloader { Ok(()) } - pub async fn no_meta(&self, id: u64, title: &str) -> Result<(), Error> { - self.set_meta(id, title, "none").await + pub async fn no_meta(&self, id: u64) + -> Result<(), Error> { + + let db = self.db.open_tree("youtube_dl").unwrap(); + + aquire_db_mutex(&db, id).await; + let job_status = db.get(&status_key(id)) + .unwrap() + .ok_or(Error::CanNoLongerUpdateMeta)?; + let job_status = bincode::deserialize(&job_status.to_vec()).unwrap(); + let new_status = match job_status { + Status::Queued(meta) => { + let new_meta = MetaData { + title: format!("{} {}",meta.title,meta.artist), + artist: "".to_owned(), + source_url: meta.source_url, + }; + Status::MetaConfirmed(new_meta) + }, + Status::MetaConfirmed(mut meta) => { + meta.title = format!("{} {}",meta.title,meta.artist); + meta.artist = "".to_owned(); + Status::MetaConfirmed(meta) + }, + Status::Downloaded(meta) => { + let new_meta = MetaData { + title: format!("{} {}",meta.title,meta.artist), + artist: "".to_owned(), + source_url: meta.source_url, + }; + let new_path = write_metadata(id, &new_meta)?; + Status::MetaWritten((new_path, new_meta)) + }, + Status::MetaWritten((path, mut meta)) => { + meta.title = format!("{} {}",meta.title,meta.artist); + meta.artist = "".to_owned(); + let new_path = update_metadata(&path, &meta)?; + Status::MetaWritten((new_path, meta)) + }, + }; + + let mut batch = Batch::default(); + batch.insert( + &status_key(id), + bincode::serialize(&new_status).unwrap() + ); + batch.insert( //unlock file lock + &db_mutex_key(id), + bincode::serialize(&false).unwrap() + ); + db.apply_batch(batch).unwrap(); + + Ok(()) } } From 83a8707efa643bbcc43161439f3807fb943fb671 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Sat, 14 Mar 2020 02:42:33 +0100 Subject: [PATCH 035/687] derive and set metadata artist and name --- src/input/bot/youtube_dl.rs | 6 ++- src/input/youtube_downloader.rs | 66 +++++++++++++++++++++++++-------- 2 files changed, 55 insertions(+), 17 deletions(-) diff --git a/src/input/bot/youtube_dl.rs b/src/input/bot/youtube_dl.rs index a0681ebc..0d1aa6a1 100644 --- a/src/input/bot/youtube_dl.rs +++ b/src/input/bot/youtube_dl.rs @@ -19,7 +19,7 @@ pub struct TelegramFeedback { // Ok // Lookup impl TelegramFeedback { - async fn ask_name_artist(&self, token: &str, meta: MetaGuess, id: u64) + async fn ask_name_artist(&self, token: &str, mut meta: MetaGuess, id: u64) -> Result<(), BotError> { dbg!(); let keyboard_json = format!("[\ @@ -29,6 +29,10 @@ impl TelegramFeedback { [{{\"text\":\"lookup\", \"callback_data\":\"ytdl:lookup:{id}\"}}]\ ]",id=id); let reply_markup = format!("{{\"inline_keyboard\":{} }}", keyboard_json); + meta.title.retain(|c| c.is_ascii_alphanumeric() || + c.is_ascii_whitespace() || c=='-'); + meta.artist.retain(|c| c.is_ascii_alphanumeric() || + c.is_ascii_whitespace() || c=='-'); let text = format!("is _{}_ the title and _{}_ the artist?", meta.title, meta.artist); //TODO: should always base this on metadata guess, should make that a diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index db654c13..aed157dc 100755 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -14,7 +14,9 @@ use bincode; use async_trait::async_trait; use async_std::task; use sled::Batch; -use id3; +use std::ffi::OsStr; +use regex::Regex; +//use id3; use crate::input::bot::youtube_dl::TelegramFeedback; @@ -155,7 +157,7 @@ pub struct MetaGuess { pub source_url: String, } -impl MetaData { +/*impl MetaData { fn to_tag(&self) -> id3::Tag { let mut tag = id3::Tag::new(); tag.set_artist(&self.artist); @@ -163,7 +165,7 @@ impl MetaData { //tag.set_text("source: ",&self.source_url); tag } -} +}*/ // in the future queued an downloaded can be expanded // with a MetaGuess @@ -180,6 +182,7 @@ fn split(to_split_on: &str) -> (&str, &str){ let new_title; let new_artist; + let in_quotes = Regex::new(r#"(.*)\s*(?:'|")\s*(.*)\s*(?:'|")\s*(.*)"#).unwrap(); if to_split_on.contains("-"){ let mut split = to_split_on.splitn(2,"-"); new_title = split.next().unwrap(); @@ -192,6 +195,17 @@ fn split(to_split_on: &str) -> (&str, &str){ let mut split = to_split_on.splitn(2,"|"); new_title = split.next().unwrap(); new_artist = split.next().unwrap(); + } else if let Some(caps) = in_quotes.captures(to_split_on){ + dbg!(&caps); + let len_before = caps.get(1).unwrap().as_str().len(); + let len_after = caps.get(3).unwrap().as_str().len(); + if len_before > len_after { + new_title = caps.get(1).unwrap().as_str(); + new_artist = caps.get(2).unwrap().as_str(); + } else { + new_title = caps.get(2).unwrap().as_str(); + new_artist = caps.get(3).unwrap().as_str(); + } } else { new_title = to_split_on; new_artist = "unknown"; @@ -301,6 +315,24 @@ async fn download_song(url: &str, id: u64) -> Result<(), Error> { Ok(()) } +fn ffmpeg_set_meta(input: &Path, output: &Path, artist: &str, title: &str){ + let input = fs::canonicalize(input).unwrap(); + dbg!(&input); + dbg!(&output); + + let output = Command::new("ffmpeg") + .args(&[OsStr::new("-i"),input.as_os_str()]) + .args(&["-metadata", &format!("artist={}",artist)]) + .args(&["-metadata", &format!("title={}",title)]) + .args(&["-codec", "copy"]) + .arg(output.as_os_str()) + .output() + .expect("ffmpeg write metadata"); + + dbg!(output); + //ffmpeg -i InputFile -metadata key=value -codec copy OutputFile +} + fn write_metadata(id: u64, meta: &MetaData) -> Result { let mut old_path = PathBuf::from(MUSIC_TEMP); old_path.push(id.to_string()); @@ -313,15 +345,10 @@ fn write_metadata(id: u64, meta: &MetaData) -> Result { } new_path.push(&meta.title); new_path.set_extension("m4a"); - dbg!(&old_path); - dbg!(&new_path); - fs::rename(old_path, &new_path).unwrap(); - /*meta.to_tag() //not working, corrupts files - .write_to_path(&new_path, id3::Version::Id3v24) - .unwrap();*/ + ffmpeg_set_meta(&old_path, &new_path, &meta.artist, &meta.title); + fs::remove_file(old_path).unwrap(); mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| c.rescan())?; - Ok(new_path) } @@ -333,8 +360,10 @@ fn update_metadata(old_path: &Path, meta: &MetaData) -> Result { } new_path.push(&meta.title); new_path.set_extension("m4a"); - fs::rename(old_path, &new_path).unwrap(); - + + ffmpeg_set_meta(&old_path, &new_path, &meta.artist, &meta.title); + + fs::remove_file(old_path).unwrap(); //delete if parent dir is now empty if let Some(dir) = old_path.parent(){ if dir.read_dir().unwrap().count() == 0 { @@ -342,11 +371,7 @@ fn update_metadata(old_path: &Path, meta: &MetaData) -> Result { } } - /*meta.to_tag() //not working, corrupts files - .write_to_path(&new_path, id3::Version::Id3v24) - .unwrap();*/ mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| c.rescan())?; - Ok(new_path) } @@ -661,4 +686,13 @@ mod tests { let test_case_awnser = "Trevor Jones - Promentory (The Last of the Mohicans)"; assert_eq!(parse_stdout(test_case).unwrap(), test_case_awnser); }*/ + + #[test] + fn test_split(){ + let (artist, title) = split("Merlin 4 Soundtrack \"The Burial\" 04"); + assert_eq!(artist, "Merlin 4 Soundtrack"); + assert_eq!(title, "The Burial"); + } + + } \ No newline at end of file From 9a239baf5dd049a79351f6c48e773d42626de8d4 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Wed, 22 Apr 2020 01:47:16 +0200 Subject: [PATCH 036/687] small fixes and changes --- src/controller/system/mpd_control.rs | 4 ++-- src/input/youtube_downloader.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/controller/system/mpd_control.rs b/src/controller/system/mpd_control.rs index 603682ff..62871b36 100755 --- a/src/controller/system/mpd_control.rs +++ b/src/controller/system/mpd_control.rs @@ -34,7 +34,7 @@ pub fn add_from_playlist(mpd: &mut mpd::Client, name: &str, minimal_play_time: D } pub fn increase_volume(mpd_status: &mut MpdStatus) -> Result<(),Error>{ - const VOLUME_INCREMENT: i8 = 1; + const VOLUME_INCREMENT: i8 = 5; let mut client = mpd::Client::connect("127.0.0.1:6600")?; let current_volume = mpd_status.get_volume(); @@ -45,7 +45,7 @@ pub fn increase_volume(mpd_status: &mut MpdStatus) -> Result<(),Error>{ } pub fn decrease_volume(mpd_status: &mut MpdStatus) -> Result<(),Error>{ - const VOLUME_INCREMENT: i8 = 1; + const VOLUME_INCREMENT: i8 = 5; let mut client = mpd::Client::connect("127.0.0.1:6600")?; let current_volume = mpd_status.get_volume(); diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index aed157dc..9996c9a7 100755 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -242,7 +242,7 @@ fn guess_meta(url: &str) -> Result { let stdout = String::from_utf8(output.stdout).unwrap(); dbg!(&stdout); - let (artist, title) = split(&stdout); + let (title, artist) = split(&stdout); Ok(MetaGuess { artist: artist.to_owned(), From d4676a683c615e3ababec3b33019708628655518 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Sat, 9 May 2020 03:28:33 +0200 Subject: [PATCH 037/687] fixes youtube_dl not updating if binairy old --- src/input/youtube_downloader.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index 9996c9a7..bf3d0181 100755 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -296,15 +296,19 @@ async fn download_song(url: &str, id: u64) -> Result<(), Error> { let output = download_file(&output_arg, url)?; dbg!(&output); - if !output.status.success() { + dbg!(output.stderr.starts_with(b"ERROR:")); + if !output.status.success() || output.stderr.starts_with(b"ERROR:") { + dbg!("UPDATING YOUTUBE_DL"); let since_last_updated = fs::metadata(YOUTUBE_DL_LOC).unwrap() .created().unwrap() .elapsed().unwrap_or(Duration::from_secs(0)); // updating youtube-dl wont do anything return error - if since_last_updated > Duration::from_secs(60*60*24){ + dbg!(since_last_updated); + if since_last_updated < Duration::from_secs(60*60*24){ + dbg!("not updating youtube_dl, has been recently tried already"); return Err(Error::CouldNotDownloadSong(output)); - } + } download_youtube_dl("https://yt-dl.org/downloads/latest/youtube-dl").await?; let output = download_file(&output_arg, url)?; From 8112c5069c2dc7f38eaba8b8785c87edf2425693 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Sun, 17 May 2020 13:29:06 +0200 Subject: [PATCH 038/687] adds long press behaviour to desk buttons --- src/controller/commands.rs | 4 ++ src/controller/system/mpd_control.rs | 16 ++++++++ src/input/buttons.rs | 60 +++++++++++++++++----------- 3 files changed, 57 insertions(+), 23 deletions(-) diff --git a/src/controller/commands.rs b/src/controller/commands.rs index da4ccc20..f6cb558f 100755 --- a/src/controller/commands.rs +++ b/src/controller/commands.rs @@ -16,6 +16,8 @@ pub enum Command { MpdPause, MpdDecreaseVolume, MpdIncreaseVolume, + MpdNextSong, + MpdPrevSong, GoToLinux, GoToWindows, @@ -47,6 +49,8 @@ pub fn handle_cmd(cmd: Command, state: ActiveState, mods: &mut Modifications, sy Command::MpdPause => {mpd_control::toggle_playback(&mut sys.mpd).unwrap(); mods.mpd = true }, Command::MpdDecreaseVolume => {mpd_control::increase_volume(&mut sys.mpd).unwrap(); mods.mpd = true }, Command::MpdIncreaseVolume => {mpd_control::decrease_volume(&mut sys.mpd).unwrap(); mods.mpd = true }, + Command::MpdNextSong => {mpd_control::next_song().unwrap()}, + Command::MpdPrevSong => {mpd_control::prev_song().unwrap()}, Command::Test => { warn!("The Test command was just send")}, Command::None => { error!("None command was issued, this should not happen")}, diff --git a/src/controller/system/mpd_control.rs b/src/controller/system/mpd_control.rs index 62871b36..d768dba1 100755 --- a/src/controller/system/mpd_control.rs +++ b/src/controller/system/mpd_control.rs @@ -55,6 +55,22 @@ pub fn decrease_volume(mpd_status: &mut MpdStatus) -> Result<(),Error>{ Ok(()) } +pub fn next_song() -> Result<(),Error>{ + const VOLUME_INCREMENT: i8 = 5; + + let mut client = mpd::Client::connect("127.0.0.1:6600")?; + client.next()?; + Ok(()) +} + +pub fn prev_song() -> Result<(),Error>{ + const VOLUME_INCREMENT: i8 = 5; + + let mut client = mpd::Client::connect("127.0.0.1:6600")?; + client.prev()?; + Ok(()) +} + pub fn toggle_playback(mpd_status: &mut MpdStatus) -> Result<(), Error>{ let mut client = mpd::Client::connect("127.0.0.1:6600")?; diff --git a/src/input/buttons.rs b/src/input/buttons.rs index 1375f9f6..93cb1da3 100755 --- a/src/input/buttons.rs +++ b/src/input/buttons.rs @@ -14,12 +14,13 @@ use crate::controller::{Command, Event}; // 23 works perfectly // 24 also works perfectly const MILLIS: u64 = 1_000_000; //nano to milli +const MAX_TAP_LEN: u64 = 600 * MILLIS; const N_LINES: usize = 54; -fn detect_and_handle(chip: &mut Chip, offset_to_command: [Event; 54], - tx: crossbeam_channel::Sender) -> Result<(), Error>{ +fn detect_and_handle(chip: &mut Chip, tx: crossbeam_channel::Sender) + -> Result<(), Error>{ - let offsets: [u32; 10] = [27,22,18, 23,24,26,17, 16,12,13]; + let offsets: [u32; 10] = [27,22,18, 23,24,26,17, 16,12,13]; let (mut evt_handles, mut pollables) = configure_watching(chip, &offsets)?; thread::spawn(move || { let mut last_high = [0u64; N_LINES]; @@ -30,8 +31,10 @@ fn detect_and_handle(chip: &mut Chip, offset_to_command: [Event; 54], let key_presses = process_event(&pollables, &mut evt_handles, &mut last_high, &mut last_state); for (offset, down_duration) in key_presses { - if down_duration > 10*MILLIS { - tx.send(offset_to_command[offset]).unwrap(); + if down_duration > 10*MILLIS { //debounce + if let Some(event) = to_command(offset, down_duration){ + tx.send(event).unwrap(); + } } } } @@ -90,31 +93,42 @@ fn configure_watching(chip: &mut Chip, offsets: &[u32]) Ok((evt_handles, pollables)) } +fn to_command(offset: usize, duration: u64) -> Option { + if duration > MAX_TAP_LEN { + match offset { + 27 => Some(Event::Command(Command::MpdNextSong)), //left 3, left + 18 => Some(Event::Command(Command::MpdPrevSong)), //left 3, right + _ => None, + } + } else { + match offset { + 16 => Some(Event::Command(Command::LampsDim)), + 12 => Some(Event::Command(Command::LampsDimmest)), + 13 => Some(Event::Command(Command::LampsToggle)), + + //buttons on desk + 27 => Some(Event::Command(Command::MpdIncreaseVolume)), //left 3, left + 22 => Some(Event::Command(Command::MpdPause)), //left 3, middle + 18 => Some(Event::Command(Command::MpdDecreaseVolume)), //left 3, right + + 23 => Some(Event::Command(Command::LampsNight)), //right 4, left most + 24 => Some(Event::Command(Command::LampsEvening)), //right 4, left + 26 => Some(Event::Command(Command::LampsDay)), //right 4, right + 17 => Some(Event::Command(Command::LampsToggle)), //right 4, right most + _ => None, + } + } +} + pub fn start_monitoring(tx: crossbeam_channel::Sender) -> Result<(), Error> { - - let mut offset_to_command = [Event::Command(Command::None); N_LINES]; - //buttons near lamp - offset_to_command[16] = Event::Command(Command::LampsDim); - offset_to_command[12] = Event::Command(Command::LampsDimmest); - offset_to_command[13] = Event::Command(Command::LampsToggle); - - //buttons on desk - offset_to_command[27] = Event::Command(Command::MpdIncreaseVolume); //left 3, left - offset_to_command[22] = Event::Command(Command::MpdPause); //left 3, middle - offset_to_command[18] = Event::Command(Command::MpdDecreaseVolume); //left 3, right - - offset_to_command[23] = Event::Command(Command::LampsNight); //right 4, left most - offset_to_command[24] = Event::Command(Command::LampsEvening); //right 4, left - offset_to_command[26] = Event::Command(Command::LampsDay); //right 4, right - offset_to_command[17] = Event::Command(Command::LampsToggle); //right 4, right most - + if let Some(mut chip) = gpio_cdev::chips()? .filter_map(Result::ok) .filter(|c| c.label() == "pinctrl-bcm2835") .next() { - detect_and_handle(&mut chip, offset_to_command, tx)?; + detect_and_handle(&mut chip, tx)?; Ok(()) } else { error!("could not find gpio chip"); From 2e94120a7bf44ce9e559f21fc3ec4dc66e8e6766 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Sun, 17 May 2020 15:24:04 +0200 Subject: [PATCH 039/687] extends alarms with the action to perform --- Cargo.lock | 831 +++++++++++++++++------------------ src/controller/commands.rs | 4 +- src/controller/mod.rs | 3 +- src/controller/states/mod.rs | 3 +- src/input/alarms.rs | 114 +++-- src/input/bot/mod.rs | 31 +- src/input/sensors/mod.rs | 3 +- src/input/web_api/mod.rs | 6 +- 8 files changed, 516 insertions(+), 479 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b413c6d2..4a017f3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,7 +21,7 @@ dependencies = [ "crossbeam-channel 0.3.9", "dirs", "fern", - "futures 0.3.4", + "futures 0.3.5", "gpio-cdev", "linux-embedded-hal", "log", @@ -32,7 +32,7 @@ dependencies = [ "philipshue", "rand 0.6.5", "regex", - "reqwest 0.10.1", + "reqwest 0.10.4", "retry", "ring", "rustls", @@ -86,8 +86,8 @@ dependencies = [ "futures-core", "futures-sink", "log", - "tokio 0.2.11", - "tokio-util", + "tokio 0.2.21", + "tokio-util 0.2.0", ] [[package]] @@ -102,8 +102,8 @@ dependencies = [ "actix-utils", "derive_more", "either", - "futures 0.3.4", - "http 0.2.0", + "futures 0.3.5", + "http 0.2.1", "log", "rustls", "tokio-rustls 0.12.2", @@ -124,7 +124,7 @@ dependencies = [ "bitflags 1.2.1", "bytes 0.5.4", "derive_more", - "futures 0.3.4", + "futures 0.3.5", "log", "mime", "mime_guess", @@ -160,8 +160,8 @@ dependencies = [ "futures-core", "futures-util", "fxhash", - "h2 0.2.1", - "http 0.2.0", + "h2 0.2.5", + "http 0.2.1", "httparse", "indexmap", "language-tags", @@ -189,7 +189,7 @@ checksum = "2a379b0639c293292d71defb8cc1f94c87b7705c904adf044338ad392df77c7a" dependencies = [ "actix-service", "actix-web", - "futures 0.3.4", + "futures 0.3.5", "serde", "serde_json", "time", @@ -201,8 +201,8 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21705adc76bbe4bc98434890e73a89cd00c6015e5704a60bb6eea6c3b72316b6" dependencies = [ - "quote 1.0.2", - "syn 1.0.14", + "quote 1.0.5", + "syn 1.0.22", ] [[package]] @@ -237,7 +237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d7a10ca4d94e8c8e7a87c5173aba1b97ba9a6563ca02b0e1cd23531093d3ec8" dependencies = [ "bytestring", - "http 0.2.0", + "http 0.2.1", "log", "regex", "serde", @@ -245,28 +245,30 @@ dependencies = [ [[package]] name = "actix-rt" -version = "1.0.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6a0a55507046441a496b2f0d26a84a65e67c8cafffe279072412f624b5fb6d" +checksum = "143fcc2912e0d1de2bcf4e2f720d2a60c28652ab4179685a1ee159e0fb3db227" dependencies = [ "actix-macros", "actix-threadpool", "copyless", - "futures 0.3.4", - "tokio 0.2.11", + "futures-channel", + "futures-util", + "smallvec 1.4.0", + "tokio 0.2.21", ] [[package]] name = "actix-server" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d3455eaac03ca3e49d7b822eb35c884b861f715627254ccbe4309d08f1841a" +checksum = "582a7173c281a4f46b5aa168a11e7f37183dcb71177a39312cc2264da7a632c9" dependencies = [ "actix-codec", "actix-rt", "actix-service", "actix-utils", - "futures 0.3.4", + "futures 0.3.5", "log", "mio", "mio-uds", @@ -295,7 +297,7 @@ dependencies = [ "actix-rt", "actix-server", "actix-service", - "futures 0.3.4", + "futures 0.3.5", "log", "net2", ] @@ -311,7 +313,7 @@ dependencies = [ "lazy_static", "log", "num_cpus", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "threadpool", ] @@ -327,7 +329,7 @@ dependencies = [ "actix-utils", "derive_more", "either", - "futures 0.3.4", + "futures 0.3.5", "log", "rustls", "tokio-rustls 0.12.2", @@ -347,7 +349,7 @@ dependencies = [ "bitflags 1.2.1", "bytes 0.5.4", "either", - "futures 0.3.4", + "futures 0.3.5", "log", "pin-project", "slab", @@ -375,7 +377,7 @@ dependencies = [ "bytes 0.5.4", "derive_more", "encoding_rs", - "futures 0.3.4", + "futures 0.3.5", "fxhash", "log", "mime", @@ -392,26 +394,26 @@ dependencies = [ [[package]] name = "actix-web-codegen" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de0878b30e62623770a4713a6338329fd0119703bafc211d3e4144f4d4a7bdd5" +checksum = "4f00371942083469785f7e28c540164af1913ee7c96a4534acb9cea92c39f057" dependencies = [ - "proc-macro2 1.0.8", - "quote 1.0.2", - "syn 1.0.14", + "proc-macro2 1.0.13", + "quote 1.0.5", + "syn 1.0.22", ] [[package]] name = "actix-web-httpauth" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cccccfac88ec8c0475538f466384b90e4395a7420288f5384baf1c51fad73ec" +checksum = "e0dac4ea96f3f8f03731cecce375890fea6459a01f226bc9c31cc65cae047a03" dependencies = [ "actix-service", "actix-web", "base64 0.11.0", "bytes 0.5.4", - "futures 0.3.4", + "futures 0.3.5", ] [[package]] @@ -425,6 +427,15 @@ dependencies = [ "syn 0.15.44", ] +[[package]] +name = "addr2line" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456d75cbb82da1ad150c8a9d97285ffcd21c9931dcb11e995903e7d75141b38b" +dependencies = [ + "gimli", +] + [[package]] name = "adler32" version = "1.0.4" @@ -433,9 +444,9 @@ checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" [[package]] name = "aho-corasick" -version = "0.7.8" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743ad5a418686aad3b87fd14c43badd828cf26e214a00f92a384291cf22e1811" +checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" dependencies = [ "memchr", ] @@ -455,17 +466,11 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" -[[package]] -name = "anyhow" -version = "1.0.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" - [[package]] name = "arc-swap" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7b8a9123b8027467bce0099fe556c628a53c8d83df0507084c31e9ba2e39aff" +checksum = "b585a98a234c46fc563103e9278c9391fde1f4e6850334da895d27edb9580f62" [[package]] name = "arrayref" @@ -495,9 +500,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "538ecb01eb64eecd772087e5b6f7540cbc917f047727339a472dafed2185b267" dependencies = [ "async-task", - "crossbeam-channel 0.4.0", + "crossbeam-channel 0.4.2", "crossbeam-deque", - "crossbeam-utils 0.7.0", + "crossbeam-utils 0.7.2", "futures-core", "futures-io", "futures-timer", @@ -525,13 +530,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.24" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "750b1c38a1dfadd108da0f01c08f4cdc7ff1bb39b325f9c82cc972361780a6e1" +checksum = "26c4f3195085c36ea8d24d32b2f828d23296a9370a28aa39d111f6f16bef9f3b" dependencies = [ - "proc-macro2 1.0.8", - "quote 1.0.2", - "syn 1.0.14", + "proc-macro2 1.0.13", + "quote 1.0.5", + "syn 1.0.22", ] [[package]] @@ -583,26 +588,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.43" +version = "0.3.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f80256bc78f67e7df7e36d77366f636ed976895d91fe2ab9efa3973e8fe8c4f" +checksum = "0df2f85c8a2abbe3b7d7e748052fdd9b76a0458fdeb16ad4223f5eca78c7c130" dependencies = [ - "backtrace-sys", + "addr2line", "cfg-if", "libc", + "object", "rustc-demangle", ] -[[package]] -name = "backtrace-sys" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "base64" version = "0.10.1" @@ -694,9 +690,9 @@ checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" [[package]] name = "bumpalo" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742" +checksum = "5356f1d23ee24a1f785a56d1d1a5f0fd5b0f6a0c0fb2412ce11da71649ab78f6" [[package]] name = "byteorder" @@ -723,22 +719,13 @@ checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" [[package]] name = "bytestring" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc267467f58ef6cc8874064c62a0423eb0d099362c8a23edd1c6d044f46eead4" +checksum = "fc7c05fa5172da78a62d9949d662d2ac89d4cc7355d7b49adee5163f1fb3f363" dependencies = [ "bytes 0.5.4", ] -[[package]] -name = "c2-chacha" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" -dependencies = [ - "ppv-lite86", -] - [[package]] name = "cast" version = "0.2.3" @@ -750,9 +737,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.50" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" +checksum = "404b1fe4f65288577753b17e3b36a04596ee784493ec249bf81c7f2d2acd751c" [[package]] name = "cfg-if" @@ -762,9 +749,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "chrono" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" +checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" dependencies = [ "num-integer", "num-traits", @@ -774,9 +761,9 @@ dependencies = [ [[package]] name = "clap" -version = "2.33.0" +version = "2.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129" dependencies = [ "ansi_term", "atty", @@ -849,9 +836,9 @@ checksum = "6ff9c56c9fb2a49c05ef0e431485a22400af20d33226dc0764d891d09e724127" [[package]] name = "core-foundation" -version = "0.6.4" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" +checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" dependencies = [ "core-foundation-sys", "libc", @@ -859,9 +846,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" [[package]] name = "crc32fast" @@ -883,21 +870,23 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c" +checksum = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" dependencies = [ - "crossbeam-utils 0.7.0", + "crossbeam-utils 0.7.2", + "maybe-uninit", ] [[package]] name = "crossbeam-deque" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" +checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" dependencies = [ - "crossbeam-epoch 0.8.0", - "crossbeam-utils 0.7.0", + "crossbeam-epoch 0.8.2", + "crossbeam-utils 0.7.2", + "maybe-uninit", ] [[package]] @@ -911,21 +900,22 @@ dependencies = [ "crossbeam-utils 0.6.6", "lazy_static", "memoffset", - "scopeguard 1.0.0", + "scopeguard 1.1.0", ] [[package]] name = "crossbeam-epoch" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" +checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ - "autocfg 0.1.7", + "autocfg 1.0.0", "cfg-if", - "crossbeam-utils 0.7.0", + "crossbeam-utils 0.7.2", "lazy_static", + "maybe-uninit", "memoffset", - "scopeguard 1.0.0", + "scopeguard 1.1.0", ] [[package]] @@ -935,7 +925,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" dependencies = [ "cfg-if", - "crossbeam-utils 0.7.0", + "crossbeam-utils 0.7.2", ] [[package]] @@ -950,11 +940,11 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ - "autocfg 0.1.7", + "autocfg 1.0.0", "cfg-if", "lazy_static", ] @@ -970,13 +960,13 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.2" +version = "0.99.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8" +checksum = "2127768764f1556535c01b5326ef94bd60ff08dcfbdc544d53e69ed155610f5d" dependencies = [ - "proc-macro2 1.0.8", - "quote 1.0.2", - "syn 1.0.14", + "proc-macro2 1.0.13", + "quote 1.0.5", + "syn 1.0.22", ] [[package]] @@ -1025,23 +1015,23 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28" +checksum = "e8ac63f94732332f44fe654443c46f6375d1939684c17b0afb6cb56b0456e171" dependencies = [ "cfg-if", ] [[package]] name = "enum-as-inner" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900a6c7fbe523f4c2884eaf26b57b81bb69b6810a01a236390a7ac021d09492e" +checksum = "bc4bfcfacb61d231109d1d55202c1f33263319668b168843e02ad4652725ec9c" dependencies = [ "heck", - "proc-macro2 1.0.8", - "quote 1.0.2", - "syn 1.0.14", + "proc-macro2 1.0.13", + "quote 1.0.5", + "syn 1.0.22", ] [[package]] @@ -1064,18 +1054,18 @@ dependencies = [ [[package]] name = "error-chain" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" +checksum = "d371106cc88ffdfb1eabd7111e432da544f16f3e2d7bf1dfe8bf575f1df045cd" dependencies = [ - "version_check 0.1.5", + "version_check 0.9.1", ] [[package]] name = "failure" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" dependencies = [ "backtrace", "failure_derive", @@ -1083,13 +1073,13 @@ dependencies = [ [[package]] name = "failure_derive" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.8", - "quote 1.0.2", - "syn 1.0.14", + "proc-macro2 1.0.13", + "quote 1.0.5", + "syn 1.0.22", "synstructure", ] @@ -1106,9 +1096,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f" +checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42" dependencies = [ "cfg-if", "crc32fast", @@ -1118,9 +1108,9 @@ dependencies = [ [[package]] name = "fnv" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foreign-types" @@ -1177,9 +1167,9 @@ checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" [[package]] name = "futures" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c329ae8753502fb44ae4fc2b622fa2a94652c41e795143765ba0927f92ab780" +checksum = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613" dependencies = [ "futures-channel", "futures-core", @@ -1192,9 +1182,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8" +checksum = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5" dependencies = [ "futures-core", "futures-sink", @@ -1202,9 +1192,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a" +checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399" [[package]] name = "futures-cpupool" @@ -1218,9 +1208,9 @@ dependencies = [ [[package]] name = "futures-executor" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba" +checksum = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314" dependencies = [ "futures-core", "futures-task", @@ -1229,33 +1219,36 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6" +checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789" [[package]] name = "futures-macro" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7" +checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39" dependencies = [ "proc-macro-hack", - "proc-macro2 1.0.8", - "quote 1.0.2", - "syn 1.0.14", + "proc-macro2 1.0.13", + "quote 1.0.5", + "syn 1.0.22", ] [[package]] name = "futures-sink" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6" +checksum = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc" [[package]] name = "futures-task" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27" +checksum = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626" +dependencies = [ + "once_cell", +] [[package]] name = "futures-timer" @@ -1265,9 +1258,9 @@ checksum = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6" [[package]] name = "futures-util" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5" +checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6" dependencies = [ "futures-channel", "futures-core", @@ -1276,6 +1269,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", + "pin-project", "pin-utils", "proc-macro-hack", "proc-macro-nested", @@ -1302,10 +1296,16 @@ dependencies = [ "wasi", ] +[[package]] +name = "gimli" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc8e0c9bce37868955864dbecd2b1ab2bdf967e6f28066d65aaac620444b65c" + [[package]] name = "gpio-cdev" -version = "0.2.1" -source = "git+https://github.com/rust-embedded/gpio-cdev#16fedc8e0f2bf5a442d0de7e475c2a8e10e48361" +version = "0.3.0" +source = "git+https://github.com/rust-embedded/gpio-cdev#944a0867a2d6e471a2b6f5c61ce48c8a82affa34" dependencies = [ "bitflags 1.2.1", "libc", @@ -1332,21 +1332,21 @@ dependencies = [ [[package]] name = "h2" -version = "0.2.1" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9433d71e471c1736fd5a61b671fc0b148d7a2992f666c958d03cd8feb3b88d1" +checksum = "79b7246d7e4b979c03fa093da39cfb3617a96bbeee6310af63991668d7e843ff" dependencies = [ "bytes 0.5.4", "fnv", "futures-core", "futures-sink", "futures-util", - "http 0.2.0", + "http 0.2.1", "indexmap", "log", "slab", - "tokio 0.2.11", - "tokio-util", + "tokio 0.2.21", + "tokio-util 0.3.1", ] [[package]] @@ -1369,9 +1369,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.6" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772" +checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71" dependencies = [ "libc", ] @@ -1384,12 +1384,13 @@ checksum = "f653416eb756b69642a1f1498817970fafe409998a849622c27cc5b1b7df989c" [[package]] name = "hostname" -version = "0.1.5" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" dependencies = [ "libc", - "winutil", + "match_cfg", + "winapi 0.3.8", ] [[package]] @@ -1405,9 +1406,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b708cc7f06493459026f53b9a61a7a121a5d1ec6238dee58ea4941132b30156b" +checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" dependencies = [ "bytes 0.5.4", "fnv", @@ -1433,7 +1434,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" dependencies = [ "bytes 0.5.4", - "http 0.2.0", + "http 0.2.1", ] [[package]] @@ -1474,16 +1475,16 @@ dependencies = [ [[package]] name = "hyper" -version = "0.13.2" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa1c527bbc634be72aa7ba31e4e4def9bbb020f5416916279b7c705cd838893e" +checksum = "96816e1d921eca64d208a85aab4f7798455a8e34229ee5a88c935bdee1b78b14" dependencies = [ "bytes 0.5.4", "futures-channel", "futures-core", "futures-util", - "h2 0.2.1", - "http 0.2.0", + "h2 0.2.5", + "http 0.2.1", "http-body 0.3.1", "httparse", "itoa", @@ -1491,7 +1492,7 @@ dependencies = [ "net2", "pin-project", "time", - "tokio 0.2.11", + "tokio 0.2.21", "tower-service 0.3.0", "want 0.3.0", ] @@ -1533,9 +1534,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3adcd308402b9553630734e9c36b77a7e48b3821251ca2493e8cd596763aafaa" dependencies = [ "bytes 0.5.4", - "hyper 0.13.2", + "hyper 0.13.5", "native-tls", - "tokio 0.2.11", + "tokio 0.2.21", "tokio-tls", ] @@ -1606,9 +1607,9 @@ dependencies = [ [[package]] name = "ipconfig" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa79fa216fbe60834a9c0737d7fcd30425b32d1c58854663e24d4c4b328ed83f" +checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" dependencies = [ "socket2", "widestring 0.4.0", @@ -1624,9 +1625,9 @@ checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" [[package]] name = "js-sys" -version = "0.3.35" +version = "0.3.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7889c7c36282151f6bf465be4700359318aef36baa951462382eae49e9577cf9" +checksum = "fa5a448de267e7358beaf4a5d849518fe9a0c13fce7afd44b06e68550e5562a7" dependencies = [ "wasm-bindgen", ] @@ -1643,9 +1644,9 @@ dependencies = [ [[package]] name = "kv-log-macro" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c54d9f465d530a752e6ebdc217e081a7a614b48cb200f6f0aee21ba6bc9aabb" +checksum = "2a2d3beed37e5483887d81eb39de6de03a8346531410e1306ca48a9a89bd3a51" dependencies = [ "log", ] @@ -1664,15 +1665,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.66" +version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f" [[package]] name = "linked-hash-map" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" +checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" [[package]] name = "linux-embedded-hal" @@ -1699,11 +1700,11 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" +checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" dependencies = [ - "scopeguard 1.0.0", + "scopeguard 1.1.0", ] [[package]] @@ -1724,6 +1725,12 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + [[package]] name = "matches" version = "0.1.8" @@ -1738,17 +1745,17 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.3.0" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223" +checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" [[package]] name = "memoffset" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" +checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" dependencies = [ - "rustc_version 0.2.3", + "autocfg 1.0.0", ] [[package]] @@ -1759,9 +1766,9 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "mime_guess" -version = "2.0.1" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" +checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" dependencies = [ "mime", "unicase", @@ -1778,9 +1785,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.21" +version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" +checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" dependencies = [ "cfg-if", "fuchsia-zircon", @@ -1797,9 +1804,9 @@ dependencies = [ [[package]] name = "mio-uds" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" +checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" dependencies = [ "iovec", "libc", @@ -1831,9 +1838,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" +checksum = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" dependencies = [ "lazy_static", "libc", @@ -1855,9 +1862,9 @@ checksum = "b1411551beb3c11dedfb0a90a0fa256b47d28b9ec2cdff34c25a2fa59e45dbdc" [[package]] name = "net2" -version = "0.2.33" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7" dependencies = [ "cfg-if", "libc", @@ -1978,9 +1985,9 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da4dc79f9e6c81bef96148c8f6b8e72ad4541caa4a24373e900a36da07de03a3" +checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ "autocfg 1.0.0", "num-bigint", @@ -1999,25 +2006,31 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" dependencies = [ "hermit-abi", "libc", ] +[[package]] +name = "object" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2" + [[package]] name = "once_cell" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b" +checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d" [[package]] name = "openssl" -version = "0.10.28" +version = "0.10.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "973293749822d7dd6370d6da1e523b0d1db19f06c459134c658b2a4261378b52" +checksum = "cee6d85f4cb4c4f59a6a85d5b68a233d280c82e29e822913b9c8b129fbf20bdd" dependencies = [ "bitflags 1.2.1", "cfg-if", @@ -2035,9 +2048,9 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-sys" -version = "0.9.54" +version = "0.9.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1024c0a59774200a555087a6da3f253a9095a5f344e353b212ac4c8b8e450986" +checksum = "f02309a7f127000ed50594f0b50ecc69e7c654e16d41b4e8156d1b3df8e0b52e" dependencies = [ "autocfg 1.0.0", "cc", @@ -2057,9 +2070,9 @@ dependencies = [ [[package]] name = "owning_ref" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" +checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce" dependencies = [ "stable_deref_trait", ] @@ -2102,19 +2115,19 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" dependencies = [ - "lock_api 0.3.3", + "lock_api 0.3.4", "parking_lot_core 0.6.2", "rustc_version 0.2.3", ] [[package]] name = "parking_lot" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" +checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" dependencies = [ - "lock_api 0.3.3", - "parking_lot_core 0.7.0", + "lock_api 0.3.4", + "parking_lot_core 0.7.2", ] [[package]] @@ -2147,15 +2160,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" +checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" dependencies = [ "cfg-if", "cloudabi", "libc", "redox_syscall", - "smallvec 1.2.0", + "smallvec 1.4.0", "winapi 0.3.8", ] @@ -2185,35 +2198,35 @@ dependencies = [ [[package]] name = "pin-project" -version = "0.4.8" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7804a463a8d9572f13453c516a5faea534a2403d7ced2f0c7e100eeff072772c" +checksum = "81d480cb4e89522ccda96d0eed9af94180b7a5f93fb28f66e1fd7d68431663d1" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "0.4.8" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "385322a45f2ecf3410c68d2a549a4a2685e8051d0f278e39743ff4e451cb9b3f" +checksum = "a82996f11efccb19b685b14b5df818de31c1edcee3daa256ab5775dd98e72feb" dependencies = [ - "proc-macro2 1.0.8", - "quote 1.0.2", - "syn 1.0.14", + "proc-macro2 1.0.13", + "quote 1.0.5", + "syn 1.0.22", ] [[package]] name = "pin-project-lite" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" +checksum = "f7505eeebd78492e0f6108f7171c4948dbb120ee8119d9d77d0afa5469bef67f" [[package]] name = "pin-utils" -version = "0.1.0-alpha.4" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" @@ -2223,52 +2236,47 @@ checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" [[package]] name = "ppv-lite86" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" +checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" [[package]] name = "proc-macro-error" -version = "0.4.8" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875077759af22fa20b610ad4471d8155b321c89c3f2785526c9839b099be4e0a" +checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.8", - "quote 1.0.2", - "rustversion", - "syn 1.0.14", + "proc-macro2 1.0.13", + "quote 1.0.5", + "syn 1.0.22", + "version_check 0.9.1", ] [[package]] name = "proc-macro-error-attr" -version = "0.4.8" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5717d9fa2664351a01ed73ba5ef6df09c01a521cb42cb65a061432a826f3c7a" +checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53" dependencies = [ - "proc-macro2 1.0.8", - "quote 1.0.2", - "rustversion", - "syn 1.0.14", + "proc-macro2 1.0.13", + "quote 1.0.5", + "syn 1.0.22", "syn-mid", + "version_check 0.9.1", ] [[package]] name = "proc-macro-hack" -version = "0.5.11" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" -dependencies = [ - "proc-macro2 1.0.8", - "quote 1.0.2", - "syn 1.0.14", -] +checksum = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63" [[package]] name = "proc-macro-nested" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" +checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" [[package]] name = "proc-macro2" @@ -2281,9 +2289,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.8" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548" +checksum = "53f5ffe53a6b28e37c9c1ce74893477864d64f74778a93a4beb43c8fa167f639" dependencies = [ "unicode-xid 0.2.0", ] @@ -2294,7 +2302,7 @@ version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bbaa49075179162b49acac1c6aa45fb4dafb5f13cf6794276d77bc7fd95757b" dependencies = [ - "error-chain 0.12.1", + "error-chain 0.12.2", "idna 0.2.0", "lazy_static", "regex", @@ -2318,11 +2326,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.2" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +checksum = "42934bc9c8ab0d3b273a16d8551c8f0fcff46be73276ca083ec2414c15c4ba5e" dependencies = [ - "proc-macro2 1.0.8", + "proc-macro2 1.0.13", ] [[package]] @@ -2365,7 +2373,7 @@ checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ "getrandom", "libc", - "rand_chacha 0.2.1", + "rand_chacha 0.2.2", "rand_core 0.5.1", "rand_hc 0.2.0", ] @@ -2382,11 +2390,11 @@ dependencies = [ [[package]] name = "rand_chacha" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" dependencies = [ - "c2-chacha", + "ppv-lite86", "rand_core 0.5.1", ] @@ -2504,7 +2512,7 @@ checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" dependencies = [ "crossbeam-deque", "crossbeam-queue", - "crossbeam-utils 0.7.0", + "crossbeam-utils 0.7.2", "lazy_static", "num_cpus", ] @@ -2537,9 +2545,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.3.4" +version = "1.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" +checksum = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692" dependencies = [ "aho-corasick", "memchr", @@ -2549,9 +2557,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.14" +version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b28dfe3fe9badec5dbf0a79a9cccad2cfc2ab5484bdb3e44cbd1ae8b3ba2be06" +checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" [[package]] name = "remove_dir_all" @@ -2602,18 +2610,18 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.10.1" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0e798e19e258bf6c30a304622e3e9ac820e483b06a1857a026e1f109b113fe4" +checksum = "02b81e49ddec5109a9dcfc5f2a317ff53377c915e9ae9d4f2fb50914b85614e2" dependencies = [ "base64 0.11.0", "bytes 0.5.4", "encoding_rs", "futures-core", "futures-util", - "http 0.2.0", + "http 0.2.1", "http-body 0.3.1", - "hyper 0.13.2", + "hyper 0.13.5", "hyper-tls 0.4.1", "js-sys", "lazy_static", @@ -2626,7 +2634,7 @@ dependencies = [ "serde", "serde_urlencoded 0.6.1", "time", - "tokio 0.2.11", + "tokio 0.2.21", "tokio-tls", "url 2.1.1", "wasm-bindgen", @@ -2637,9 +2645,9 @@ dependencies = [ [[package]] name = "resolv-conf" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" +checksum = "11834e137f3b14e309437a8276714eed3a80d1ef894869e510f2c0c0b98b9f4a" dependencies = [ "hostname", "quick-error", @@ -2656,13 +2664,13 @@ dependencies = [ [[package]] name = "ring" -version = "0.16.11" +version = "0.16.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "741ba1704ae21999c00942f9f5944f801e977f54302af346b596287599ad1862" +checksum = "703516ae74571f24b465b4a1431e81e2ad51336cb0ded733a55a1aa3eccac196" dependencies = [ "cc", - "lazy_static", "libc", + "once_cell", "spin", "untrusted", "web-sys", @@ -2678,7 +2686,7 @@ dependencies = [ "base64 0.11.0", "blake2b_simd", "constant_time_eq", - "crossbeam-utils 0.7.0", + "crossbeam-utils 0.7.2", ] [[package]] @@ -2724,28 +2732,17 @@ dependencies = [ "webpki", ] -[[package]] -name = "rustversion" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3bba175698996010c4f6dce5e7f173b6eb781fce25d2cfc45e27091ce0b79f6" -dependencies = [ - "proc-macro2 1.0.8", - "quote 1.0.2", - "syn 1.0.14", -] - [[package]] name = "ryu" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" +checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" [[package]] name = "schannel" -version = "0.1.17" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507a9e6e8ffe0a4e0ebb9a10293e62fdf7657c06f1b8bb07a8fcf697d2abf295" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" dependencies = [ "lazy_static", "winapi 0.3.8", @@ -2765,9 +2762,9 @@ checksum = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" [[package]] name = "scopeguard" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "sct" @@ -2781,10 +2778,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "0.3.4" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df" +checksum = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535" dependencies = [ + "bitflags 1.2.1", "core-foundation", "core-foundation-sys", "libc", @@ -2793,11 +2791,12 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "0.3.3" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" +checksum = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405" dependencies = [ "core-foundation-sys", + "libc", ] [[package]] @@ -2823,9 +2822,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.104" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" +checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c" dependencies = [ "serde_derive", ] @@ -2842,20 +2841,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.104" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" +checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984" dependencies = [ - "proc-macro2 1.0.8", - "quote 1.0.2", - "syn 1.0.14", + "proc-macro2 1.0.13", + "quote 1.0.5", + "syn 1.0.22", ] [[package]] name = "serde_json" -version = "1.0.47" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15913895b61e0be854afd32fd4163fcd2a3df34142cf2cb961b310ce694cbf90" +checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2" dependencies = [ "itoa", "ryu", @@ -2888,9 +2887,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" +checksum = "16c7a592a1ec97c9c1c68d75b6e537dcbf60c7618e038e7841e00af1d9ccf0c4" dependencies = [ "dtoa", "linked-hash-map", @@ -2927,13 +2926,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb8c32cb0e34e67ad74fae1a77f4635d0cc7ffc873088a0136f3c4849336d71" dependencies = [ "crc32fast", - "crossbeam-epoch 0.8.0", - "crossbeam-utils 0.7.0", + "crossbeam-epoch 0.8.2", + "crossbeam-utils 0.7.2", "fs2", "fxhash", "libc", "log", - "parking_lot 0.10.0", + "parking_lot 0.10.2", ] [[package]] @@ -2947,15 +2946,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.2.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" +checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" [[package]] name = "socket2" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" +checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" dependencies = [ "cfg-if", "libc", @@ -2963,12 +2962,6 @@ dependencies = [ "winapi 0.3.8", ] -[[package]] -name = "sourcefile" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" - [[package]] name = "spidev" version = "0.3.0" @@ -3009,9 +3002,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.9" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1bcbed7d48956fcbb5d80c6b95aedb553513de0a1b451ea92679d999c010e98" +checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef" dependencies = [ "clap", "lazy_static", @@ -3020,15 +3013,15 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.2" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "095064aa1f5b94d14e635d0a5684cf140c43ae40a0fd990708d38f5d669e5f64" +checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.8", - "quote 1.0.2", - "syn 1.0.14", + "proc-macro2 1.0.13", + "quote 1.0.5", + "syn 1.0.22", ] [[package]] @@ -3044,12 +3037,12 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.14" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5" +checksum = "1425de3c33b0941002740a420b1a906a350b88d08b82b2c8a01035a3f9447bac" dependencies = [ - "proc-macro2 1.0.8", - "quote 1.0.2", + "proc-macro2 1.0.13", + "quote 1.0.5", "unicode-xid 0.2.0", ] @@ -3059,9 +3052,9 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" dependencies = [ - "proc-macro2 1.0.8", - "quote 1.0.2", - "syn 1.0.14", + "proc-macro2 1.0.13", + "quote 1.0.5", + "syn 1.0.22", ] [[package]] @@ -3070,9 +3063,9 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" dependencies = [ - "proc-macro2 1.0.8", - "quote 1.0.2", - "syn 1.0.14", + "proc-macro2 1.0.13", + "quote 1.0.5", + "syn 1.0.22", "unicode-xid 0.2.0", ] @@ -3147,21 +3140,20 @@ dependencies = [ [[package]] name = "threadpool" -version = "1.7.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" dependencies = [ "num_cpus", ] [[package]] name = "time" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "redox_syscall", "winapi 0.3.8", ] @@ -3191,9 +3183,9 @@ dependencies = [ [[package]] name = "tokio" -version = "0.2.11" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fdd17989496f49cdc57978c96f0c9fe5e4a58a8bddc6813c449a4624f6a030b" +checksum = "d099fa27b9702bed751524694adbe393e18b36b204da91eb1cbbbbb4a5ee2d58" dependencies = [ "bytes 0.5.4", "fnv", @@ -3267,7 +3259,7 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" dependencies = [ - "crossbeam-utils 0.7.0", + "crossbeam-utils 0.7.2", "futures 0.1.29", ] @@ -3299,7 +3291,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" dependencies = [ - "crossbeam-utils 0.7.0", + "crossbeam-utils 0.7.2", "futures 0.1.29", "lazy_static", "log", @@ -3334,7 +3326,7 @@ checksum = "141afec0978abae6573065a48882c6bae44c5cc61db9b511ac4abf6a09bfd9cc" dependencies = [ "futures-core", "rustls", - "tokio 0.2.11", + "tokio 0.2.21", "webpki", ] @@ -3387,7 +3379,7 @@ checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" dependencies = [ "crossbeam-deque", "crossbeam-queue", - "crossbeam-utils 0.7.0", + "crossbeam-utils 0.7.2", "futures 0.1.29", "lazy_static", "log", @@ -3402,7 +3394,7 @@ version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" dependencies = [ - "crossbeam-utils 0.7.0", + "crossbeam-utils 0.7.2", "futures 0.1.29", "slab", "tokio-executor", @@ -3410,12 +3402,12 @@ dependencies = [ [[package]] name = "tokio-tls" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bde02a3a5291395f59b06ec6945a3077602fac2b07eeeaf0dee2122f3619828" +checksum = "9a70f4fcd7b3b24fb194f837560168208f669ca8cb70d0c4b862944452396343" dependencies = [ "native-tls", - "tokio 0.2.11", + "tokio 0.2.21", ] [[package]] @@ -3462,7 +3454,21 @@ dependencies = [ "futures-sink", "log", "pin-project-lite", - "tokio 0.2.11", + "tokio 0.2.21", +] + +[[package]] +name = "tokio-util" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" +dependencies = [ + "bytes 0.5.4", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio 0.2.21", ] [[package]] @@ -3537,14 +3543,14 @@ dependencies = [ "async-trait", "enum-as-inner", "failure", - "futures 0.3.4", + "futures 0.3.5", "idna 0.2.0", "lazy_static", "log", "rand 0.7.3", - "smallvec 1.2.0", + "smallvec 1.4.0", "socket2", - "tokio 0.2.11", + "tokio 0.2.21", "url 2.1.1", ] @@ -3575,14 +3581,14 @@ checksum = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f" dependencies = [ "cfg-if", "failure", - "futures 0.3.4", - "ipconfig 0.2.1", + "futures 0.3.5", + "ipconfig 0.2.2", "lazy_static", "log", "lru-cache", "resolv-conf", - "smallvec 1.2.0", - "tokio 0.2.11", + "smallvec 1.4.0", + "tokio 0.2.21", "trust-dns-proto 0.18.0-alpha.2", ] @@ -3625,7 +3631,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" dependencies = [ - "smallvec 1.2.0", + "smallvec 1.4.0", ] [[package]] @@ -3654,9 +3660,9 @@ checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" [[package]] name = "untrusted" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" @@ -3705,9 +3711,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae" dependencies = [ "nom", - "proc-macro2 1.0.8", - "quote 1.0.2", - "syn 1.0.14", + "proc-macro2 1.0.13", + "quote 1.0.5", + "syn 1.0.22", ] [[package]] @@ -3728,9 +3734,9 @@ checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" [[package]] name = "vec_map" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" @@ -3779,9 +3785,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasm-bindgen" -version = "0.2.58" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5205e9afdf42282b192e2310a5b463a6d1c1d774e30dc3c791ac37ab42d2616c" +checksum = "e3c7d40d09cdbf0f4895ae58cf57d92e1e57a9dd8ed2e8390514b54a47cc5551" dependencies = [ "cfg-if", "serde", @@ -3791,24 +3797,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.58" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11cdb95816290b525b32587d76419facd99662a07e59d3cdb560488a819d9a45" +checksum = "c3972e137ebf830900db522d6c8fd74d1900dcfc733462e9a12e942b00b4ac94" dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.8", - "quote 1.0.2", - "syn 1.0.14", + "proc-macro2 1.0.13", + "quote 1.0.5", + "syn 1.0.22", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.8" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bbdd49e3e28b40dec6a9ba8d17798245ce32b019513a845369c641b275135d9" +checksum = "8a369c5e1dfb7569e14d62af4da642a3cbc2f9a3652fe586e26ac22222aa4b04" dependencies = [ "cfg-if", "js-sys", @@ -3818,60 +3824,41 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.58" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "574094772ce6921576fb6f2e3f7497b8a76273b6db092be18fc48a082de09dc3" +checksum = "2cd85aa2c579e8892442954685f0d801f9129de24fa2136b2c6a539c76b65776" dependencies = [ - "quote 1.0.2", + "quote 1.0.5", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.58" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e85031354f25eaebe78bb7db1c3d86140312a911a106b2e29f9cc440ce3e7668" +checksum = "8eb197bd3a47553334907ffd2f16507b4f4f01bbec3ac921a7719e0decdfe72a" dependencies = [ - "proc-macro2 1.0.8", - "quote 1.0.2", - "syn 1.0.14", + "proc-macro2 1.0.13", + "quote 1.0.5", + "syn 1.0.22", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e7e61fc929f4c0dddb748b102ebf9f632e2b8d739f2016542b4de2965a9601" - -[[package]] -name = "wasm-bindgen-webidl" -version = "0.2.58" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef012a0d93fc0432df126a8eaf547b2dce25a8ce9212e1d3cbeef5c11157975d" -dependencies = [ - "anyhow", - "heck", - "log", - "proc-macro2 1.0.8", - "quote 1.0.2", - "syn 1.0.14", - "wasm-bindgen-backend", - "weedle", -] +checksum = "a91c2916119c17a8e316507afaaa2dd94b47646048014bbdf6bef098c1bb58ad" [[package]] name = "web-sys" -version = "0.3.35" +version = "0.3.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf97caf6aa8c2b1dac90faf0db529d9d63c93846cca4911856f78a83cebf53b" +checksum = "8bc359e5dd3b46cb9687a051d50a2fdd228e4ba7cf6fcf861a5365c3d671a642" dependencies = [ - "anyhow", "js-sys", - "sourcefile", "wasm-bindgen", - "wasm-bindgen-webidl", ] [[package]] @@ -3893,15 +3880,6 @@ dependencies = [ "webpki", ] -[[package]] -name = "weedle" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164" -dependencies = [ - "nom", -] - [[package]] name = "widestring" version = "0.2.2" @@ -3966,15 +3944,6 @@ dependencies = [ "winapi 0.3.8", ] -[[package]] -name = "winutil" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e" -dependencies = [ - "winapi 0.3.8", -] - [[package]] name = "ws2_32-sys" version = "0.2.1" diff --git a/src/controller/commands.rs b/src/controller/commands.rs index f6cb558f..05b083b8 100755 --- a/src/controller/commands.rs +++ b/src/controller/commands.rs @@ -1,8 +1,10 @@ +use serde::{Serialize, Deserialize}; + use super::{ActiveState, Modifications, System}; use crate::controller::states::*; use crate::controller::system::mpd_control; -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Serialize, Deserialize)] pub enum Command { None, diff --git a/src/controller/mod.rs b/src/controller/mod.rs index 72ed2ebd..c130b2ac 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -1,5 +1,6 @@ use std::time::{Duration, Instant}; use std::thread; +use serde::{Serialize, Deserialize}; mod system; use system::{Lighting}; @@ -19,7 +20,7 @@ use crate::input::sensors::SensorValue; use crate::input::mpd_status::MpdStatus; use crate::errors::Error; -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Serialize, Deserialize)] pub enum Event { Update, Alarm, diff --git a/src/controller/states/mod.rs b/src/controller/states/mod.rs index 78fc8a57..d5855118 100755 --- a/src/controller/states/mod.rs +++ b/src/controller/states/mod.rs @@ -1,3 +1,4 @@ +use serde::{Serialize, Deserialize}; use super::{System, Modifications, Environment}; mod normal; @@ -15,7 +16,7 @@ pub enum ActiveState { WakeUp(wakeup::WakeUp), } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Serialize, Deserialize)] pub enum TargetState { Normal, LightLoop, diff --git a/src/input/alarms.rs b/src/input/alarms.rs index 2e2de0f2..32d511fb 100755 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -1,19 +1,69 @@ use crossbeam_channel; use std::thread; +use std::ops::Sub; -use chrono::{DateTime, NaiveDateTime, Utc}; +use chrono::{DateTime, NaiveDateTime, Utc, self}; use sled; use byteorder::{ByteOrder, BigEndian}; +use serde::{Serialize, Deserialize}; use crate::controller::Event; +use crate::controller::Command; use crate::errors::Error; //TODO, what to do on multiple alarms at the same time? // -add one a second later // -store in millisec to lower collision chance? +#[derive(Serialize, Deserialize)] +enum Action { + Event(Event), + Command(Command), +} + +impl From for Action { + fn from(event: Event) -> Self { + Action::Event(event) + } +} +impl From for Action { + fn from(command: Command) -> Self { + Action::Command(command) + } +} +#[derive(Serialize, Deserialize)] +pub struct Alarm { + time: DateTime, + action: Action, + expiration: Option, +} + +impl Alarm { + pub fn from(time: DateTime, action: impl Into, expiration: Option) + -> Self { + Alarm { + time, + action: action.into(), + expiration, + } + } +} +impl Sub for Alarm { + type Output = chrono::Duration; + + fn sub(self, other: Alarm) -> chrono::Duration { + self.time - other.time + } +} +impl Sub> for &Alarm { + type Output = chrono::Duration; + + fn sub(self, other: chrono::DateTime) -> chrono::Duration { + self.time - other + } +} #[derive(Clone)] pub struct Alarms { @@ -31,7 +81,16 @@ fn waker(mut alarm_list: AlarmList, event_tx: crossbeam_channel::Sender, //This can fail #TODO make sure an non waking error alarm is send to the user if let Some(current_alarm) = alarm_list.get_next() { let now = Utc::now(); - let timeout = (current_alarm - now ).to_std().unwrap();//TODO handle alarm in past + let timeout = ¤t_alarm - now; + if let Some(expiration) = current_alarm.expiration { + if timeout < -chrono::Duration::from_std(expiration).unwrap() { + error!("skipping alarm to far in the past"); + alarm_list.remove_alarm(current_alarm).unwrap(); + continue; //alarm to far in the past, skip and get next + } + } + let timeout = timeout.to_std() + .unwrap_or(std::time::Duration::from_secs(0)); info!("next alarm is in: {} seconds", timeout.as_secs()); //do we sound the an alarm or should we add or remove one? @@ -46,10 +105,8 @@ fn waker(mut alarm_list: AlarmList, event_tx: crossbeam_channel::Sender, error!("could not set off alarm: {:?}", error); }; //set //remove alarm from memory and file - if let Err(error) = alarm_list.remove_alarm(current_alarm){ - error!("could not remove alarm after its trigger time: {:?}", error); - }; - break; //get next alarm + alarm_list.remove_alarm(current_alarm).unwrap(); + continue; //get next alarm } //we should stop, end the thread by returning crossbeam_channel::RecvTimeoutError::Disconnected => return, @@ -75,7 +132,6 @@ impl Alarms { pub fn setup(event_tx: crossbeam_channel::Sender, db: sled::Db) -> Result<(Self, thread::JoinHandle<()>), Error> { let mut alarm_db = AlarmList { db: db.open_tree("alarms")? }; - alarm_db.remove_old()?; let (waker_tx, waker_rx) = crossbeam_channel::unbounded(); let waker_db_copy = alarm_db.clone(); @@ -86,14 +142,14 @@ impl Alarms { // we decrease the time till the alarm until there is a place in the database // as only one alarm can fire at the time, after an alarm gets a timeslot it is never changed - pub fn add_alarm(&self, at_time: DateTime) -> Result<(), Error> { - self.alarm_db.add_alarm(at_time)?; + pub fn add_alarm(&self, to_add: Alarm) -> Result<(), Error> { + self.alarm_db.add_alarm(to_add)?; //signal waker to update its next alarm self.waker_tx.send(())?; Ok(()) } - pub fn remove_alarm(&self, at_time: DateTime) -> Result<(), Error> { - self.alarm_db.remove_alarm(at_time)?; + pub fn remove_alarm(&self, to_remove: Alarm) -> Result<(), Error> { + self.alarm_db.remove_alarm(to_remove)?; self.waker_tx.send(())?; //signal waker to update its next alarm Ok(()) } @@ -116,51 +172,41 @@ impl Alarms { impl AlarmList { // we decrease the time till the alarm until there is a place in the database // as only one alarm can fire at the time, after an alarm gets a timeslot it is never changed - fn add_alarm(&self, at_time: DateTime) -> Result<(), Error> { - let mut timestamp = at_time.timestamp() as u64; + fn add_alarm(&self, to_add: Alarm) -> Result<(), Error> { + let mut timestamp = to_add.time.timestamp() as u64; let mut timestamp_array = timestamp.to_be_bytes(); + let mut alarm = bincode::serialize(&to_add).unwrap(); //create alarm entry if there is no alarm at this timestamp yet //if there is already an alarm schedualed, postpone this one until there is a spot free //self.db.cas(&[1], None as Option<&[u8]>, Some(&[10]) //TODO check how this works and expand sled documentation for fail cases while let Err(_old_event) = self - .db.compare_and_swap(×tamp_array, None as Option<&[u8]>, Some(&[0]))? {//cas unique creation + .db + .compare_and_swap(×tamp_array, None as Option<&[u8]>, Some(alarm.clone()))? { + //cas unique creation timestamp -= 1; timestamp_array = timestamp.to_be_bytes(); } Ok(()) } - pub fn remove_alarm(&self, at_time: DateTime) -> Result<(), Error> { - let timestamp = at_time.timestamp() as u64; + pub fn remove_alarm(&self, to_remove: Alarm) -> Result<(), Error> { + let timestamp = to_remove.time.timestamp() as u64; self.db.remove(timestamp.to_be_bytes())?; Ok(()) } - fn remove_old(&mut self) -> Result<(), Error> { - let now = Utc::now(); - let timestamp = now.timestamp() as u64; - let timestamp_array = timestamp.to_be_bytes(); - for old_alarm in self.db.range(..timestamp_array).keys() { - if let Ok(old_alarm) = old_alarm { - self.db.remove(old_alarm)?; - } - } - Ok(()) - } /// calculate time to the earliest alarm, remove it from the list if the current time is later /// then the alarm - fn get_next(&mut self) -> Option> { + fn get_next(&mut self) -> Option { let now = Utc::now(); - //the greater then is applied to the integer representation - let timestamp = (now.timestamp()-10) as u64; - match self.db.get_gt(timestamp.to_be_bytes()) { + //get earliest alarm time in db + match self.db.get_gt(0u64.to_be_bytes()) { Ok(entry) => { if let Some(entry) = entry { - let (timestamp, _action) = entry; - let timestamp = BigEndian::read_u64(×tamp) as i64; - let alarm = DateTime::::from_utc(NaiveDateTime::from_timestamp(timestamp, 0), Utc); + let (timestamp, alarm) = entry; + let alarm = bincode::deserialize(&alarm).unwrap(); Some(alarm) } else { None diff --git a/src/input/bot/mod.rs b/src/input/bot/mod.rs index 37925b92..b64e3486 100644 --- a/src/input/bot/mod.rs +++ b/src/input/bot/mod.rs @@ -17,6 +17,7 @@ use crate::input::web_api::server::{State}; pub mod youtube_dl; use youtube_dl::TelegramFeedback; +mod set_alarm; #[derive(Debug)] pub enum Error{ @@ -28,6 +29,7 @@ pub enum Error{ UnknownCommand(String), SongDownloadError(youtube_downloader::Error), Unauthorized(ChatId), + SetAlarmError(set_alarm::Error), } impl From for Error { @@ -42,6 +44,12 @@ impl From for Error { } } +impl From for Error { + fn from(err: set_alarm::Error) -> Self { + Error::SetAlarmError(err) + } +} + fn to_string_and_ids(message: Message) -> Result<(String, ChatId, UserId, MessageId),Error>{ @@ -72,21 +80,24 @@ async fn handle_command(text: String, chat_id: ChatId, message_id: MessageId, return Ok(()); } - //let split = text.find(char::is_whitespace); - let command = text; - //let args = command.split_off(split.unwrap_or(command.len())); - match command.as_str() { + let split = text.find(char::is_whitespace).unwrap_or(text.len()); + let command = &text[..split]; + let args = &text[..split]; + match command { "/test" => { send_text(chat_id, token, "hi").await?; - return Ok(()); - } + return Ok(()); + } + "/set_alarm" => { + set_alarm::handle(chat_id, token, args).await?; + } &_ => { } } warn!("no known command or alias: {:?}", &command); - return Err(Error::UnknownCommand(command)); + return Err(Error::UnknownCommand(command.to_owned())); } async fn handle_callback(callback: CallbackQuery, state: &State) { @@ -126,8 +137,10 @@ async fn handle_error(error: Error, chat_id: ChatId, token: &str) { String::from(INT_ERR_TEXT)}, Error::SongDownloadError(e) => { error!("song download error {:?}", e); - String::from("Could not download song due to critical internal error") - } + String::from("Could not download song due to critical internal error")} + Error::SetAlarmError(e) => { + error!("could not set alarm {:?}", e); + String::from("Could not set alarm")} Error::Unauthorized(chat_id) => { format!("You are not authorized to use this bot, if you \ believe this is a mistake ask for your telegram chat id \ diff --git a/src/input/sensors/mod.rs b/src/input/sensors/mod.rs index 7e6e8328..5503ffa4 100755 --- a/src/input/sensors/mod.rs +++ b/src/input/sensors/mod.rs @@ -11,11 +11,12 @@ use std::time::Duration; use chrono::Utc; use async_std::task; use actix_rt; +use serde::{Serialize, Deserialize}; use crate::controller::Event; use local::{TEMPERATURE, HUMIDITY, PRESSURE, STOP_ENCODE}; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] pub enum SensorValue { Temperature(f32), Humidity(f32), diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index f2cc8be9..ec78e114 100755 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -5,12 +5,14 @@ use actix_web_httpauth::headers::www_authenticate::WwwAuthenticate; use actix_web::http::StatusCode; use chrono::{DateTime, NaiveDateTime, Utc}; +use std::time::Duration; use serde::Deserialize; use actix_web::HttpResponse; use crate::input::youtube_downloader::FeedbackChannel; use crate::controller::{Command, TargetState, Event}; +use crate::input::alarms::Alarm; mod command_logins; pub mod server; @@ -146,7 +148,9 @@ pub fn set_alarm_unix_timestamp(params: Form, state: DataUtc::now() { - if state.alarms.add_alarm(time).is_ok() { + let alarm = Alarm::from(time, Event::Alarm, Some(Duration::from_secs(3600*2))); + + if state.alarms.add_alarm(alarm).is_ok() { dbg!("done setting alarm"); HttpResponse::Ok().finish() } else { From 3bfe9ee7d6605c7afe96620ea821d5aed7a6a8a5 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Mon, 18 May 2020 03:49:52 +0200 Subject: [PATCH 040/687] impl telegram bot function add alarm --- Cargo.lock | 7 ++ Cargo.toml | 1 + src/controller/commands.rs | 2 +- src/controller/mod.rs | 2 +- src/controller/states/mod.rs | 2 +- src/input/alarms.rs | 59 ++++++++------ src/input/bot/mod.rs | 19 +++-- src/input/bot/set_alarm.rs | 147 +++++++++++++++++++++++++++++++++++ src/input/web_api/mod.rs | 11 ++- 9 files changed, 209 insertions(+), 41 deletions(-) create mode 100644 src/input/bot/set_alarm.rs diff --git a/Cargo.lock b/Cargo.lock index 4a017f3a..023acc10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,7 @@ dependencies = [ "fern", "futures 0.3.5", "gpio-cdev", + "hex", "linux-embedded-hal", "log", "mpd", @@ -1376,6 +1377,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hex" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" + [[package]] name = "historian" version = "4.0.3" diff --git a/Cargo.toml b/Cargo.toml index 96b91f00..0f5d61e3 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,7 @@ chrono = { version = "0.4", features = ["serde"] } bytes = "0.4" byteorder = "1.3" num = { version = "0.2"} +hex = "0.4.2" crossbeam-channel = "0.3" diff --git a/src/controller/commands.rs b/src/controller/commands.rs index 05b083b8..0ce6080a 100755 --- a/src/controller/commands.rs +++ b/src/controller/commands.rs @@ -4,7 +4,7 @@ use super::{ActiveState, Modifications, System}; use crate::controller::states::*; use crate::controller::system::mpd_control; -#[derive(Copy, Clone, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub enum Command { None, diff --git a/src/controller/mod.rs b/src/controller/mod.rs index c130b2ac..dcc82c55 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -20,7 +20,7 @@ use crate::input::sensors::SensorValue; use crate::input::mpd_status::MpdStatus; use crate::errors::Error; -#[derive(Clone, Copy, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub enum Event { Update, Alarm, diff --git a/src/controller/states/mod.rs b/src/controller/states/mod.rs index d5855118..6fbe7eb4 100755 --- a/src/controller/states/mod.rs +++ b/src/controller/states/mod.rs @@ -16,7 +16,7 @@ pub enum ActiveState { WakeUp(wakeup::WakeUp), } -#[derive(Copy, Clone, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub enum TargetState { Normal, LightLoop, diff --git a/src/input/alarms.rs b/src/input/alarms.rs index 32d511fb..c94d3e3b 100755 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -4,7 +4,7 @@ use std::ops::Sub; use chrono::{DateTime, NaiveDateTime, Utc, self}; use sled; -use byteorder::{ByteOrder, BigEndian}; +use byteorder::{ByteOrder, BigEndian, ReadBytesExt}; use serde::{Serialize, Deserialize}; use crate::controller::Event; @@ -15,8 +15,8 @@ use crate::errors::Error; // -add one a second later // -store in millisec to lower collision chance? -#[derive(Serialize, Deserialize)] -enum Action { +#[derive(Serialize, Deserialize, Debug)] +pub enum Action { Event(Event), Command(Command), } @@ -32,11 +32,11 @@ impl From for Action { } } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Debug)] pub struct Alarm { - time: DateTime, - action: Action, - expiration: Option, + pub time: DateTime, + pub action: Action, + pub expiration: Option, } impl Alarm { @@ -79,13 +79,13 @@ pub struct AlarmList { fn waker(mut alarm_list: AlarmList, event_tx: crossbeam_channel::Sender, waker_rx: crossbeam_channel::Receiver<()>) { loop { //This can fail #TODO make sure an non waking error alarm is send to the user - if let Some(current_alarm) = alarm_list.get_next() { + if let Some((id, current_alarm)) = alarm_list.get_next() { let now = Utc::now(); let timeout = ¤t_alarm - now; if let Some(expiration) = current_alarm.expiration { if timeout < -chrono::Duration::from_std(expiration).unwrap() { error!("skipping alarm to far in the past"); - alarm_list.remove_alarm(current_alarm).unwrap(); + alarm_list.remove_alarm(id).unwrap(); continue; //alarm to far in the past, skip and get next } } @@ -105,7 +105,7 @@ fn waker(mut alarm_list: AlarmList, event_tx: crossbeam_channel::Sender, error!("could not set off alarm: {:?}", error); }; //set //remove alarm from memory and file - alarm_list.remove_alarm(current_alarm).unwrap(); + alarm_list.remove_alarm(id).unwrap(); continue; //get next alarm } //we should stop, end the thread by returning @@ -148,22 +148,22 @@ impl Alarms { self.waker_tx.send(())?; Ok(()) } - pub fn remove_alarm(&self, to_remove: Alarm) -> Result<(), Error> { - self.alarm_db.remove_alarm(to_remove)?; + pub fn remove_alarm(&self, to_remove: u64) -> Result, Error> { + let removed_alarm = self.alarm_db.remove_alarm(to_remove)?; self.waker_tx.send(())?; //signal waker to update its next alarm - Ok(()) + Ok(removed_alarm) } - pub fn list(&self) -> Vec> { + pub fn list(&self) -> Vec<(u64, Alarm)> { //self.alarm_list.iter().keys().map(|k| DateTime::::from_utc(NaiveDateTime::from_timestamp(k, 0), Utc);) let start: &[u8] = &[0]; let alarms = self.alarm_db.db.range(start..); let mut list = Vec::new(); //TODO placeholder - for (timestamp, _events) in alarms.filter_map(Result::ok) { - let timestamp = BigEndian::read_u64(×tamp) as i64; - let alarm = DateTime::::from_utc(NaiveDateTime::from_timestamp(timestamp, 0), Utc); - list.push(alarm); + for (key, alarm) in alarms.filter_map(Result::ok) { + let alarm = bincode::deserialize(&alarm).unwrap(); + let key = key.as_ref().read_u64::().unwrap(); + list.push((key,alarm)); } list } @@ -190,24 +190,33 @@ impl AlarmList { } Ok(()) } - pub fn remove_alarm(&self, to_remove: Alarm) -> Result<(), Error> { - let timestamp = to_remove.time.timestamp() as u64; - self.db.remove(timestamp.to_be_bytes())?; - Ok(()) + pub fn remove_alarm(&self, to_remove: u64) -> Result, Error> { + + Ok(self.db + .remove(to_remove.to_be_bytes())? + .map(|k| bincode::deserialize::(&k).unwrap())) + + /*if let Some(old) = old { + let alarm: Alarm = bincode::deserialize(&old).unwrap(); + dbg!(alarm); + }; + Ok(None) + // .and_then(|k| bincode::deserialize(&k).unwrap())*/ } /// calculate time to the earliest alarm, remove it from the list if the current time is later /// then the alarm - fn get_next(&mut self) -> Option { + fn get_next(&mut self) -> Option<(u64,Alarm)> { let now = Utc::now(); //get earliest alarm time in db match self.db.get_gt(0u64.to_be_bytes()) { Ok(entry) => { if let Some(entry) = entry { - let (timestamp, alarm) = entry; + let (id, alarm) = entry; + let id = id.as_ref().read_u64::().unwrap(); let alarm = bincode::deserialize(&alarm).unwrap(); - Some(alarm) + Some((id,alarm)) } else { None } diff --git a/src/input/bot/mod.rs b/src/input/bot/mod.rs index b64e3486..6766a721 100644 --- a/src/input/bot/mod.rs +++ b/src/input/bot/mod.rs @@ -80,24 +80,22 @@ async fn handle_command(text: String, chat_id: ChatId, message_id: MessageId, return Ok(()); } - let split = text.find(char::is_whitespace).unwrap_or(text.len()); - let command = &text[..split]; - let args = &text[..split]; + let mut split = text.split_whitespace(); + let command = split.next().unwrap(); match command { "/test" => { send_text(chat_id, token, "hi").await?; - return Ok(()); } - "/set_alarm" => { - set_alarm::handle(chat_id, token, args).await?; + "/alarm" => { + set_alarm::handle(chat_id, token, split, state).await?; } &_ => { - + warn!("no known command or alias: {:?}", &command); + Err(Error::UnknownCommand(command.to_owned()))?; } } - warn!("no known command or alias: {:?}", &command); - return Err(Error::UnknownCommand(command.to_owned())); + return Ok(()); } async fn handle_callback(callback: CallbackQuery, state: &State) { @@ -129,7 +127,7 @@ async fn handle_error(error: Error, chat_id: ChatId, token: &str) { let error_message = match error { Error::UnknownCommand(input) => format!("Unknown command: {}", input), - Error::HttpClientError(err) => { + Error::HttpClientError(err) => { error!("Internal error in http client: {}", err); String::from(INT_ERR_TEXT)}, Error::InvalidServerResponse(resp) => { @@ -146,6 +144,7 @@ async fn handle_error(error: Error, chat_id: ChatId, token: &str) { believe this is a mistake ask for your telegram chat id \ {} to be added", chat_id) } + Error::UnhandledMessageKind => { String::from(UNHANDLED)} Error::UnhandledUpdateKind => { diff --git a/src/input/bot/set_alarm.rs b/src/input/bot/set_alarm.rs new file mode 100644 index 00000000..13fcf7ce --- /dev/null +++ b/src/input/bot/set_alarm.rs @@ -0,0 +1,147 @@ +use telegram_bot::types::refs::ChatId; +use crate::input::web_api::server::State; +use crate::input::alarms::Alarm; +use crate::controller::Event; +use super::send_text; +use chrono::Utc; +use chrono::Timelike; +use chrono::Duration; +use hex::FromHex; + +#[derive(Debug)] +pub enum Error { + NoArguments, + InvalidOption, + CouldNotRespond, + NoTimeArgument, + InvalidHourArgument, + InvalidMinuteArgument, + WrongTimeFormat, + NoAlarmId, + MalformedAlarmId, + CouldNotRemove, +} + +pub async fn handle<'a>(chat_id: ChatId, token: &str, mut args: std::str::SplitWhitespace<'a>, state: &State) + -> Result<(),Error> { + + let command = args.next().ok_or(Error::NoArguments)?; + dbg!(command); + + match command { + "list" => { + list_alarm(chat_id, token, state).await? + } + "add" => { + add_alarm(chat_id, token, args, state).await? + } + "remove" => { + remove_alarm(chat_id, token, args, state).await? + } + &_ => Err(Error::InvalidOption)? + } + + Ok(()) +} + +pub async fn add_alarm<'a>(chat_id: ChatId, token: &str, mut args: std::str::SplitWhitespace<'a>, state: &State) + -> Result<(),Error> { + let time = args.next().ok_or(Error::NoTimeArgument)?; + + //assumes hh:mm + let mut time = time.split(':'); + let hour = time.next() + .ok_or(Error::WrongTimeFormat)? + .parse::() + .map_err(|e| Error::InvalidHourArgument)?; + let min = time.next() + .ok_or(Error::WrongTimeFormat)? + .parse::() + .map_err(|e| Error::InvalidHourArgument)?; + + if hour > 24 {return Err(Error::InvalidHourArgument);} + if min > 60 {return Err(Error::InvalidMinuteArgument);} + + let now = Utc::now(); + let alarm_sec_after_midnight = hour*3600+min*60; + let till_alarm = if alarm_sec_after_midnight < now.num_seconds_from_midnight(){ + let seconds_left_in_day = 3600*24 - now.num_seconds_from_midnight(); + Duration::seconds(seconds_left_in_day as i64) + +Duration::seconds(alarm_sec_after_midnight as i64) + } else { + let seconds_till_alarm = alarm_sec_after_midnight + - now.num_seconds_from_midnight(); + Duration::seconds(seconds_till_alarm as i64) + }; + + + let alarm = Alarm::from(now+till_alarm, + Event::Alarm, + Some(std::time::Duration::from_secs(3600*2))); + + state.alarms.add_alarm(alarm).unwrap(); + + let text = format!("set alarm for over {} hours and {} minutes from now", + till_alarm.num_hours(), till_alarm.num_minutes() % 60); + + send_text(chat_id, token, text).await + .map_err(|_| Error::CouldNotRespond)?; + + Ok(()) +} + +pub async fn list_alarm(chat_id: ChatId, token: &str, state: &State) + -> Result<(), Error> { + + let alarms = state.alarms.list(); + let mut list = String::with_capacity(alarms.len()*100); + + for (id, alarm) in alarms.into_iter() { + + list.push_str(&format!("{:x}, {}, {:?}, {:?}", + id, + &alarm.time.to_rfc2822(), + &alarm.action, + &alarm.expiration, + )); + list.push_str("\n"); + } + if list.is_empty() { + list.push_str("no alarms set"); + } + + send_text(chat_id, token, list).await//.unwrap(); + .map_err(|_| Error::CouldNotRespond)?; + Ok(()) +} + +pub async fn remove_alarm<'a>(chat_id: ChatId, token: &str, mut args: std::str::SplitWhitespace<'a>, state: &State) + -> Result<(), Error> { + + let to_remove = dbg!(args.next()) + .ok_or(Error::NoAlarmId)?; + //let to_remove = <[u8; 8]>::from_hex(to_remove) + // .unwrap(); + //.map_err(|_| Error::MalformedAlarmId)?; + //let to_remove = u64::from_be_bytes(to_remove); + let to_remove = u64::from_str_radix(to_remove, 16).unwrap(); + + let removed = state.alarms.remove_alarm(to_remove) + .unwrap(); //TODO //FIXME + //.map_err(|_| Error::CouldNotRemove)?; + + let text = if let Some(alarm) = removed { + format!("removed alarm {:x}: {}, {:?}, {:?}", + to_remove, + &alarm.time.to_rfc2822(), + &alarm.action, + &alarm.expiration, + ) + } else { + String::from("Alarm does not exist, no alarm removed") + }; + + send_text(chat_id, token, text).await//.unwrap(); + .map_err(|_| Error::CouldNotRespond)?; + Ok(()) +} \ No newline at end of file diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index ec78e114..38867afe 100755 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -171,9 +171,14 @@ pub fn list_alarms(state: Data) -> HttpResponse { //Code to parse alarm time let alarms = state.alarms.list(); - let mut list = String::with_capacity(alarms.len()*30); - for alarm in alarms { - list.push_str(&alarm.to_rfc2822()); + let mut list = String::with_capacity(alarms.len()*100); + for (id,alarm) in alarms { + list.push_str(&format!("{:x}, {}, {:?}, {:?}", + id, + &alarm.time.to_rfc2822(), + &alarm.action, + &alarm.expiration, + )); list.push_str("\n"); } dbg!(&list); From db275e76c88164c909b7c0ab177206ebeb371e94 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Mon, 18 May 2020 13:43:52 +0200 Subject: [PATCH 041/687] fixes wakeup state crash --- src/controller/states/wakeup.rs | 1 - src/controller/system/mpd_control.rs | 4 ++-- src/errors.rs | 1 + src/input/alarms.rs | 8 -------- src/input/bot/set_alarm.rs | 4 ---- 5 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/controller/states/wakeup.rs b/src/controller/states/wakeup.rs index 7237b322..b65568a1 100755 --- a/src/controller/states/wakeup.rs +++ b/src/controller/states/wakeup.rs @@ -55,7 +55,6 @@ impl WakeUp { impl RoomState for WakeUp { fn update(self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> ActiveState { - dbg!("updating wakeup state"); let elapsed = self.start.elapsed().as_secs(); if elapsed > WAKEUP_DURATION { diff --git a/src/controller/system/mpd_control.rs b/src/controller/system/mpd_control.rs index d768dba1..2ac05afb 100755 --- a/src/controller/system/mpd_control.rs +++ b/src/controller/system/mpd_control.rs @@ -5,6 +5,7 @@ use rand::Rng; use crate::input::mpd_status::MpdStatus; pub fn add_from_playlist(mpd: &mut mpd::Client, name: &str, minimal_play_time: Duration, maximal_play_time: Duration) -> Result<(),Error>{ + let mut rng = rand::thread_rng(); let songs = mpd.playlist(name); @@ -21,14 +22,13 @@ pub fn add_from_playlist(mpd: &mut mpd::Client, name: &str, minimal_play_time: D let mut time = Duration::seconds(0); //add random songs until the playtime is larger then the minimum - while time < minimal_play_time && songs.len()!=0 { + while time < minimal_play_time && songs.len()>1 { let idx = rng.gen_range(0, songs.len()-1); let song = songs.remove(idx); if time + song.duration.unwrap() < maximal_play_time { time = time + song.duration.unwrap(); mpd.push(song)?; } - dbg!(songs.len()); } Ok(()) } diff --git a/src/errors.rs b/src/errors.rs index 1709526c..2e3892b3 100755 --- a/src/errors.rs +++ b/src/errors.rs @@ -18,6 +18,7 @@ pub enum Error { YoutubeDownloader(youtube_downloader::Error), WebServerError(server::Error), UnTracked, + PlayListTooShort, } impl From for Error { diff --git a/src/input/alarms.rs b/src/input/alarms.rs index c94d3e3b..e3989ddd 100755 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -191,17 +191,9 @@ impl AlarmList { Ok(()) } pub fn remove_alarm(&self, to_remove: u64) -> Result, Error> { - Ok(self.db .remove(to_remove.to_be_bytes())? .map(|k| bincode::deserialize::(&k).unwrap())) - - /*if let Some(old) = old { - let alarm: Alarm = bincode::deserialize(&old).unwrap(); - dbg!(alarm); - }; - Ok(None) - // .and_then(|k| bincode::deserialize(&k).unwrap())*/ } /// calculate time to the earliest alarm, remove it from the list if the current time is later diff --git a/src/input/bot/set_alarm.rs b/src/input/bot/set_alarm.rs index 13fcf7ce..e5597d93 100644 --- a/src/input/bot/set_alarm.rs +++ b/src/input/bot/set_alarm.rs @@ -120,10 +120,6 @@ pub async fn remove_alarm<'a>(chat_id: ChatId, token: &str, mut args: std::str:: let to_remove = dbg!(args.next()) .ok_or(Error::NoAlarmId)?; - //let to_remove = <[u8; 8]>::from_hex(to_remove) - // .unwrap(); - //.map_err(|_| Error::MalformedAlarmId)?; - //let to_remove = u64::from_be_bytes(to_remove); let to_remove = u64::from_str_radix(to_remove, 16).unwrap(); let removed = state.alarms.remove_alarm(to_remove) From efc240732a85ef3cd48bb57647513998e92a4b9e Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Tue, 19 May 2020 03:13:52 +0200 Subject: [PATCH 042/687] alarms now displayed in local timezone, +flush after adding alarm --- Cargo.lock | 20 ++++++++++++++++++++ Cargo.toml | 1 + src/input/alarms.rs | 7 ++++--- src/input/bot/set_alarm.rs | 18 ++++++++++++------ src/input/web_api/mod.rs | 4 ++-- 5 files changed, 39 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 023acc10..3e70b0c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,6 +18,7 @@ dependencies = [ "byteorder", "bytes 0.4.12", "chrono", + "chrono-tz", "crossbeam-channel 0.3.9", "dirs", "fern", @@ -760,6 +761,16 @@ dependencies = [ "time", ] +[[package]] +name = "chrono-tz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0e430fad0384e4defc3dc6b1223d1b886087a8bf9b7080e5ae027f73851ea15" +dependencies = [ + "chrono", + "parse-zoneinfo", +] + [[package]] name = "clap" version = "2.33.1" @@ -2179,6 +2190,15 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "parse-zoneinfo" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feece9d0113b400182a7d00adcff81ccf29158c49c5abd11e2eed8589bf6ff07" +dependencies = [ + "regex", +] + [[package]] name = "percent-encoding" version = "1.0.1" diff --git a/Cargo.toml b/Cargo.toml index 0f5d61e3..57358029 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,7 @@ bme280 = "0.1" smallvec = "0.6" chrono = { version = "0.4", features = ["serde"] } +chrono-tz = "0.5.1" bytes = "0.4" byteorder = "1.3" num = { version = "0.2"} diff --git a/src/input/alarms.rs b/src/input/alarms.rs index e3989ddd..d4d54cbe 100755 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -142,8 +142,8 @@ impl Alarms { // we decrease the time till the alarm until there is a place in the database // as only one alarm can fire at the time, after an alarm gets a timeslot it is never changed - pub fn add_alarm(&self, to_add: Alarm) -> Result<(), Error> { - self.alarm_db.add_alarm(to_add)?; + pub async fn add_alarm(&self, to_add: Alarm) -> Result<(), Error> { + self.alarm_db.add_alarm(to_add).await?; //signal waker to update its next alarm self.waker_tx.send(())?; Ok(()) @@ -172,7 +172,7 @@ impl Alarms { impl AlarmList { // we decrease the time till the alarm until there is a place in the database // as only one alarm can fire at the time, after an alarm gets a timeslot it is never changed - fn add_alarm(&self, to_add: Alarm) -> Result<(), Error> { + async fn add_alarm(&self, to_add: Alarm) -> Result<(), Error> { let mut timestamp = to_add.time.timestamp() as u64; let mut timestamp_array = timestamp.to_be_bytes(); let mut alarm = bincode::serialize(&to_add).unwrap(); @@ -188,6 +188,7 @@ impl AlarmList { timestamp -= 1; timestamp_array = timestamp.to_be_bytes(); } + self.db.flush_async().await?; Ok(()) } pub fn remove_alarm(&self, to_remove: u64) -> Result, Error> { diff --git a/src/input/bot/set_alarm.rs b/src/input/bot/set_alarm.rs index e5597d93..257c7794 100644 --- a/src/input/bot/set_alarm.rs +++ b/src/input/bot/set_alarm.rs @@ -3,7 +3,9 @@ use crate::input::web_api::server::State; use crate::input::alarms::Alarm; use crate::controller::Event; use super::send_text; -use chrono::Utc; +use chrono::{TimeZone}; +use chrono_tz::Europe::Amsterdam; +use chrono::{Local, Utc, DateTime}; use chrono::Timelike; use chrono::Duration; use hex::FromHex; @@ -62,7 +64,11 @@ pub async fn add_alarm<'a>(chat_id: ChatId, token: &str, mut args: std::str::Spl if hour > 24 {return Err(Error::InvalidHourArgument);} if min > 60 {return Err(Error::InvalidMinuteArgument);} - let now = Utc::now(); + //let now = Amsterdam::now(); + let now = Local::now(); + //let now = Amsterdam.ymd(2016, 5, 10).and_hms(12, 0, 0); + //let now = dt.with_timezone + let alarm_sec_after_midnight = hour*3600+min*60; let till_alarm = if alarm_sec_after_midnight < now.num_seconds_from_midnight(){ let seconds_left_in_day = 3600*24 - now.num_seconds_from_midnight(); @@ -75,11 +81,11 @@ pub async fn add_alarm<'a>(chat_id: ChatId, token: &str, mut args: std::str::Spl }; - let alarm = Alarm::from(now+till_alarm, + let alarm = Alarm::from(Utc::now()+till_alarm, Event::Alarm, Some(std::time::Duration::from_secs(3600*2))); - state.alarms.add_alarm(alarm).unwrap(); + state.alarms.add_alarm(alarm).await.unwrap(); let text = format!("set alarm for over {} hours and {} minutes from now", till_alarm.num_hours(), till_alarm.num_minutes() % 60); @@ -100,7 +106,7 @@ pub async fn list_alarm(chat_id: ChatId, token: &str, state: &State) list.push_str(&format!("{:x}, {}, {:?}, {:?}", id, - &alarm.time.to_rfc2822(), + &alarm.time.with_timezone(&Local).to_rfc2822(), &alarm.action, &alarm.expiration, )); @@ -129,7 +135,7 @@ pub async fn remove_alarm<'a>(chat_id: ChatId, token: &str, mut args: std::str:: let text = if let Some(alarm) = removed { format!("removed alarm {:x}: {}, {:?}, {:?}", to_remove, - &alarm.time.to_rfc2822(), + &alarm.time.with_timezone(&Local).to_rfc2822(), &alarm.action, &alarm.expiration, ) diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index 38867afe..271628ed 100755 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -138,7 +138,7 @@ pub struct AlarmDataUnixTS { timestamp: String, } -pub fn set_alarm_unix_timestamp(params: Form, state: Data) -> HttpResponse { +pub async fn set_alarm_unix_timestamp(params: Form, state: Data) -> HttpResponse { //Code to parse alarm time dbg!(¶ms); @@ -150,7 +150,7 @@ pub fn set_alarm_unix_timestamp(params: Form, state: DataUtc::now() { let alarm = Alarm::from(time, Event::Alarm, Some(Duration::from_secs(3600*2))); - if state.alarms.add_alarm(alarm).is_ok() { + if state.alarms.add_alarm(alarm).await.is_ok() { dbg!("done setting alarm"); HttpResponse::Ok().finish() } else { From 6f6eb4db2e36c0c0e81831fe186001c91042154e Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Wed, 20 May 2020 03:38:18 +0200 Subject: [PATCH 043/687] adds sleep state and normal state --- src/controller/commands.rs | 10 ++-- src/controller/mod.rs | 7 +++ src/controller/states/lightloop.rs | 4 +- src/controller/states/mod.rs | 8 +++- src/controller/states/normal.rs | 28 ++++++++++- src/controller/states/wakeup.rs | 4 +- src/controller/system/lamps/mod.rs | 72 +++++++++++++++++++++++++++- src/controller/system/mpd_control.rs | 14 ++++-- src/input/buttons.rs | 3 ++ 9 files changed, 134 insertions(+), 16 deletions(-) diff --git a/src/controller/commands.rs b/src/controller/commands.rs index 0ce6080a..6262cb2f 100755 --- a/src/controller/commands.rs +++ b/src/controller/commands.rs @@ -39,11 +39,11 @@ pub fn handle_cmd(cmd: Command, state: ActiveState, mods: &mut Modifications, sy //Command::PauseMpd => {unimplemented!(); state}, Command::LampsToggle => {sys.lights.toggle().unwrap(); mods.lighting = true} - Command::LampsDim => {sys.lights.set_all_to(50,500).unwrap(); mods.lighting = true} - Command::LampsDimmest => {sys.lights.set_all_to(1,500).unwrap(); mods.lighting = true} - Command::LampsEvening => {sys.lights.set_all_to(254,320).unwrap(); mods.lighting = true} - Command::LampsNight => {sys.lights.set_all_to(220,500).unwrap(); mods.lighting = true} - Command::LampsDay => {sys.lights.set_all_to(254,240).unwrap(); mods.lighting = true} + Command::LampsDim => {sys.lights.set_all_ct(50,500).unwrap(); mods.lighting = true} + Command::LampsDimmest => {sys.lights.set_all_ct(1,500).unwrap(); mods.lighting = true} + Command::LampsEvening => {sys.lights.set_all_ct(254,320).unwrap(); mods.lighting = true} + Command::LampsNight => {sys.lights.set_all_ct(220,500).unwrap(); mods.lighting = true} + Command::LampsDay => {sys.lights.set_all_ct(254,240).unwrap(); mods.lighting = true} Command::GoToLinux => println!("should go to linux"), Command::GoToWindows => println!("should go to windows"), diff --git a/src/controller/mod.rs b/src/controller/mod.rs index dcc82c55..f186272e 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -37,6 +37,13 @@ pub struct Modifications { //change name to: alteration, deviation, overrides or //Alarm, } +impl Modifications { + fn reset(&mut self) { + self.lighting = false; + self.mpd = false; + } +} + impl Default for Modifications { fn default() -> Self { Modifications {lighting: false, mpd: false} diff --git a/src/controller/states/lightloop.rs b/src/controller/states/lightloop.rs index 4bb4be04..f46b6e15 100755 --- a/src/controller/states/lightloop.rs +++ b/src/controller/states/lightloop.rs @@ -16,7 +16,7 @@ impl RoomState for LightLoop { ActiveState::Normal(normal::Normal::enter(mods, sys)) } else { dbg!(self.counter); - sys.lights.set_all_to(self.counter, 200).unwrap(); + sys.lights.set_all_ct(self.counter, 200).unwrap(); self.counter -= 1; ActiveState::LightLoop(self) } @@ -24,7 +24,7 @@ impl RoomState for LightLoop { fn enter(mods: &mut Modifications, sys: &mut System) -> Self { dbg!("making everything rdy for the lightloop state"); - sys.lights.set_all_to(0, 200).unwrap(); + sys.lights.set_all_ct(0, 200).unwrap(); mods.lighting = false; sys.update_period = Duration::from_millis(500); diff --git a/src/controller/states/mod.rs b/src/controller/states/mod.rs index 6fbe7eb4..0c7ef913 100755 --- a/src/controller/states/mod.rs +++ b/src/controller/states/mod.rs @@ -4,16 +4,19 @@ use super::{System, Modifications, Environment}; mod normal; mod lightloop; mod wakeup; +mod sleep; pub use normal::Normal; pub use lightloop::LightLoop; pub use wakeup::WakeUp; +pub use sleep::Sleep; #[derive(Copy, Clone)] pub enum ActiveState { Normal(normal::Normal), LightLoop(lightloop::LightLoop), WakeUp(wakeup::WakeUp), + Sleep(sleep::Sleep), } #[derive(Copy, Clone, Debug, Serialize, Deserialize)] @@ -21,6 +24,7 @@ pub enum TargetState { Normal, LightLoop, WakeUp, + Sleep, } impl ActiveState { @@ -28,7 +32,8 @@ impl ActiveState { match self { ActiveState::Normal(state) => state.update(mods, system, env), ActiveState::LightLoop(state) => state.update(mods, system, env), - ActiveState::WakeUp(state) => state.update(mods, system, env), + ActiveState::WakeUp(state) => state.update(mods, system, env), + ActiveState::Sleep(state) => state.update(mods, system, env), } } } @@ -38,6 +43,7 @@ pub fn change_state(target_state: TargetState, mods: &mut Modifications, sys: &m TargetState::Normal => ActiveState::Normal(Normal::enter(mods, sys)), TargetState::LightLoop => ActiveState::LightLoop(LightLoop::enter(mods, sys)), TargetState::WakeUp => ActiveState::WakeUp(WakeUp::enter(mods, sys)), + TargetState::Sleep => ActiveState::Sleep(Sleep::enter(mods, sys)), } } diff --git a/src/controller/states/normal.rs b/src/controller/states/normal.rs index a6479569..e2a7bbc2 100755 --- a/src/controller/states/normal.rs +++ b/src/controller/states/normal.rs @@ -1,16 +1,40 @@ use super::super::{Modifications, System, Environment}; use super::{RoomState, ActiveState}; +use chrono::{Local, NaiveTime}; use std::time::{Duration, Instant}; +use log::error; + +fn update_lights(sys: &mut System) { + let now = Local::now(); + let res = if now.time() > NaiveTime::from_hms(22,0,0) { + sys.lights.set_all_ct(220,500) + } else if now.time() > NaiveTime::from_hms(17,0,0) { + sys.lights.set_all_ct(254,320) + } else if now.time() > NaiveTime::from_hms(6,0,0) { + sys.lights.set_all_ct(254,240) + } else { + return; + }; + + if let Err(e) = res { + error!("could not update lights: {:?}", e); + } +} + #[derive(Default, Clone, Copy)] pub struct Normal {} impl RoomState for Normal { - fn update(self, _mods: &mut Modifications, _sys: &mut System, _env: &mut Environment) -> ActiveState { + fn update(self, _mods: &mut Modifications, sys: &mut System, _env: &mut Environment) + -> ActiveState { + //dbg!("updating normal state"); + update_lights(sys); ActiveState::Normal(self) } + fn enter(_mods: &mut Modifications, sys: &mut System) -> Self { dbg!("making everything rdy for the normal state"); sys.update_period = Duration::from_secs(5); @@ -18,4 +42,4 @@ impl RoomState for Normal { Self::default() } -} +} \ No newline at end of file diff --git a/src/controller/states/wakeup.rs b/src/controller/states/wakeup.rs index b65568a1..45d88de6 100755 --- a/src/controller/states/wakeup.rs +++ b/src/controller/states/wakeup.rs @@ -64,7 +64,7 @@ impl RoomState for WakeUp { if !mods.lighting { // if lighting controls have not been modified externally since start let bri = (BRI_PER_SECOND*(elapsed as f32)) as u8; let ct = CT_BEGIN-(CT_PER_SECOND*(elapsed as f32)) as u16; - sys.lights.set_all_to(bri, ct).expect("could not update lights in wakeup"); + sys.lights.set_all_ct(bri, ct).expect("could not update lights in wakeup"); } if !mods.mpd { // if mpd controls have not been modified externally since start @@ -95,7 +95,7 @@ impl RoomState for WakeUp { dbg!("setting up playlist"); Self::setup_playlist().expect("error creating wakeup playlist"); dbg!("done with setting up playlist"); - sys.lights.set_all_to(0, CT_BEGIN).expect("could not set lights on entering wakeup state"); + sys.lights.set_all_ct(0, CT_BEGIN).expect("could not set lights on entering wakeup state"); Self{start: Instant::now(), playing: false} } } diff --git a/src/controller/system/lamps/mod.rs b/src/controller/system/lamps/mod.rs index f6f8f841..5da6cdec 100755 --- a/src/controller/system/lamps/mod.rs +++ b/src/controller/system/lamps/mod.rs @@ -177,8 +177,16 @@ impl Lighting { Ok(()) } + pub fn off(&mut self) -> Result<(),Error> { + let command = LightCommand::off(LightCommand::default() ); + self.bridge.set_group_state(0, &command)?; + self.lamps.values_mut().for_each(|lamp| lamp.on = false); + Ok(()) + } + + //how to deal with errors? - pub fn set_all_to(&mut self, bri: u8, ct: u16) -> Result<(),Error>{ + pub fn set_all_ct(&mut self, bri: u8, ct: u16) -> Result<(),Error>{ let command = LightCommand::default(); let command = command.on(); let command = command.with_bri(bri); @@ -189,4 +197,66 @@ impl Lighting { Ok(()) } + pub fn set_all_xy(&mut self, bri: u8, xy: (f32, f32)) -> Result<(),Error>{ + let command = LightCommand::default(); + let command = command.on(); + let command = command.with_bri(bri); + let command = command.with_xy(xy); + self.bridge.set_group_state(0, &command)?; + self.lamps.values_mut().for_each(|lamp| { + lamp.bri =bri; + lamp.xy = Some(xy); + lamp.on =true + }); + + Ok(()) + } + + pub fn set_all_rgb(&mut self, bri: u8, rgb: (f32,f32,f32)) -> Result<(),Error> { + let xy = xy_from_rgb(rgb); + + let command = LightCommand::default(); + let command = command.on(); + let command = command.with_bri(bri); + let command = command.with_xy(xy); + self.bridge.set_group_state(0, &command)?; + self.lamps.values_mut().for_each(|lamp| { + lamp.bri =bri; + lamp.xy = Some(xy); + lamp.on =true + }); + + Ok(()) + } + } + +fn gamma_correct(mut x: f32) -> f32 { + if x > 0.04045 { + x = (x + 0.055)/(1f32 + 0.055); + x.powf(2.4) + } else { + x / 12.92 + } +} + +//r,g,b between 0 and one +//https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d +fn xy_from_rgb(rgb: (f32,f32,f32)) -> (f32, f32) { + + let (r,g,b) = rgb; + let r = gamma_correct(r); + let g = gamma_correct(g); + let b = gamma_correct(b); + + let xyz_x = r * 0.649926 + g * 0.103455 + b * 0.197109; + let xyz_y = r * 0.234327 + g * 0.743075 + b * 0.022598; + let xyz_z = g * 0.053077 + b * 1.035763; + + let hue_x = xyz_x/(xyz_x+xyz_y+xyz_z); + let hue_y = xyz_y/(xyz_x+xyz_y+xyz_z); + + //TODO color gamut triangle stuff for finding closest valid value + + (hue_x, hue_y) +} \ No newline at end of file diff --git a/src/controller/system/mpd_control.rs b/src/controller/system/mpd_control.rs index 2ac05afb..d0c7a246 100755 --- a/src/controller/system/mpd_control.rs +++ b/src/controller/system/mpd_control.rs @@ -25,9 +25,11 @@ pub fn add_from_playlist(mpd: &mut mpd::Client, name: &str, minimal_play_time: D while time < minimal_play_time && songs.len()>1 { let idx = rng.gen_range(0, songs.len()-1); let song = songs.remove(idx); - if time + song.duration.unwrap() < maximal_play_time { - time = time + song.duration.unwrap(); - mpd.push(song)?; + if let Some(duration) = song.duration { + if time + duration < maximal_play_time { + time = time + song.duration.unwrap(); + mpd.push(song)?; + } } } Ok(()) @@ -82,6 +84,12 @@ pub fn toggle_playback(mpd_status: &mut MpdStatus) -> Result<(), Error>{ Ok(()) } +pub fn pause() -> Result<(), Error>{ + let mut client = mpd::Client::connect("127.0.0.1:6600")?; + client.pause(true)?; + Ok(()) +} + pub fn save_current_playlist(mpd: &mut mpd::Client) -> Result<(),Error>{ dbg!(); mpd.pl_remove("temp")?; diff --git a/src/input/buttons.rs b/src/input/buttons.rs index 93cb1da3..c0af8a7c 100755 --- a/src/input/buttons.rs +++ b/src/input/buttons.rs @@ -9,6 +9,7 @@ use crossbeam_channel; use crate::errors::Error; use crate::controller::{Command, Event}; +use crate::controller::TargetState::Sleep; // when pressing 22, 24 is often activated // 23 works perfectly @@ -98,6 +99,8 @@ fn to_command(offset: usize, duration: u64) -> Option { match offset { 27 => Some(Event::Command(Command::MpdNextSong)), //left 3, left 18 => Some(Event::Command(Command::MpdPrevSong)), //left 3, right + + 23 => Some(Event::Command(Command::ChangeState(Sleep))), _ => None, } } else { From 7dbca4638571bd623900d3361b86611d837315ae Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Fri, 22 May 2020 22:24:32 +0200 Subject: [PATCH 044/687] refactors controller loop and button system --- src/controller/commands.rs | 15 ++-- src/controller/mod.rs | 75 +++++++++++++++---- src/controller/{states => state}/lightloop.rs | 34 +++++---- src/controller/state/mod.rs | 29 +++++++ src/controller/{states => state}/normal.rs | 33 ++++---- src/controller/state/silent.rs | 37 +++++++++ src/controller/state/sleep.rs | 45 +++++++++++ src/controller/{states => state}/wakeup.rs | 44 ++++++----- src/controller/states/mod.rs | 53 ------------- src/controller/system/lamps/mod.rs | 6 ++ src/input/buttons.rs | 73 +++++++++++------- src/input/web_api/mod.rs | 4 +- 12 files changed, 298 insertions(+), 150 deletions(-) rename src/controller/{states => state}/lightloop.rs (64%) create mode 100755 src/controller/state/mod.rs rename src/controller/{states => state}/normal.rs (59%) create mode 100644 src/controller/state/silent.rs create mode 100644 src/controller/state/sleep.rs rename src/controller/{states => state}/wakeup.rs (89%) delete mode 100755 src/controller/states/mod.rs diff --git a/src/controller/commands.rs b/src/controller/commands.rs index 6262cb2f..e7bb36c9 100755 --- a/src/controller/commands.rs +++ b/src/controller/commands.rs @@ -1,7 +1,7 @@ use serde::{Serialize, Deserialize}; -use super::{ActiveState, Modifications, System}; -use crate::controller::states::*; +use super::{Modifications, System}; +use crate::controller::state::*; use crate::controller::system::mpd_control; #[derive(Copy, Clone, Debug, Serialize, Deserialize)] @@ -26,15 +26,16 @@ pub enum Command { Test, //prints a test message - ChangeState(TargetState), + ChangeState(State), } //TODO handle error on command -pub fn handle_cmd(cmd: Command, state: ActiveState, mods: &mut Modifications, sys: &mut System) -> ActiveState { - println!("handled a command"); +pub fn handle_cmd(cmd: Command, mods: &mut Modifications, sys: &mut System) -> Option { + + println!("handled a command"); match cmd { Command::ChangeState(target_state) => { - return change_state(target_state, mods, sys) + return Some(target_state); } //Command::PauseMpd => {unimplemented!(); state}, @@ -57,5 +58,5 @@ pub fn handle_cmd(cmd: Command, state: ActiveState, mods: &mut Modifications, sy Command::Test => { warn!("The Test command was just send")}, Command::None => { error!("None command was issued, this should not happen")}, } - state + None } diff --git a/src/controller/mod.rs b/src/controller/mod.rs index f186272e..b5308d01 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -8,16 +8,17 @@ use system::{Lighting}; mod environment; use environment::Environment; -mod states; -use states::{ActiveState, RoomState, change_state}; +mod state; +use state::{RoomState}; mod commands; use commands::{handle_cmd}; pub use commands::Command; -pub use states::TargetState; +pub use state::State; #[cfg(feature = "sensors_connected")] use crate::input::sensors::SensorValue; use crate::input::mpd_status::MpdStatus; +use crate::input::buttons::Button; use crate::errors::Error; #[derive(Clone, Copy, Debug, Serialize, Deserialize)] @@ -28,6 +29,8 @@ pub enum Event { #[cfg(feature = "sensors_connected")] Sensor(SensorValue), Command(Command), + PressShort(Button), + PressLong(Button), } pub struct Modifications { //change name to: alteration, deviation, overrides or something else? @@ -85,7 +88,8 @@ pub fn start(rx: crossbeam_channel::Receiver, mpd_status: MpdStatus) -> R let mut env = Environment::default(); // TODO guess best init state from statefile or lamps+mpd+time - let mut state = ActiveState::Normal(states::Normal::enter(&mut mods, &mut system)); //initial state + let mut state: Box = Box::new(state::Normal::setup(&mut mods, &mut system)); //initial state + let mut current_state = State::Normal; loop { //wait for next update or an incoming event @@ -102,21 +106,66 @@ pub fn start(rx: crossbeam_channel::Receiver, mpd_status: MpdStatus) -> R }; //state changes may not return errors - state = match (event, state) { + let next_state = match (event, current_state) { //specific test code for normal state - (Event::Test, ActiveState::Normal(state)) => {dbg!("a test happend while in normal state"); ActiveState::Normal(state)}, - + (Event::Test, State::Normal) => {dbg!("a test happend while in normal state"); None}, //general code that is the same for all functions, unless specific handlers exist above - (Event::Command(cmd), state) => {handle_cmd(cmd, state, &mut mods, &mut system)}, - (Event::Update, state) => {state.update(&mut mods, &mut system, &mut env)}, - (Event::Alarm, _) => {change_state(TargetState::WakeUp, &mut mods, &mut system)}, - (Event::Test, _) => {dbg!("a test happend"); change_state(TargetState::WakeUp, &mut mods, &mut system)}, + (Event::Command(cmd), _) => handle_cmd(cmd, &mut mods, &mut system), + (Event::Update, _) => state.update(&mut mods, &mut system, &mut env), + (Event::Alarm, _) => Some(State::WakeUp), + (Event::Test, _) => {dbg!("a test happend"); None}, - #[cfg(feature = "sensors_connected")] - (Event::Sensor(_), _) => {state} + // #[cfg(feature = "sensors_connected")] + (Event::Sensor(_), _) => None, + + (Event::PressShort(button), _) => { + let cmd = match button { + Button::LampLeft => Command::LampsDim, + Button::LampMid => Command::LampsDimmest, + Button::LampRight => Command::LampsToggle, + + Button::DeskLeftMost => Command::LampsNight, + Button::DeskLeft => Command::LampsEvening, + Button::DeskRight => Command::LampsDay, + Button::DeskRightMost => Command::LampsToggle, + + Button::DeskTop => Command::MpdIncreaseVolume, + Button::DeskMid => Command::MpdPause, + Button::DeskBottom => Command::MpdDecreaseVolume, + }; + handle_cmd(cmd, &mut mods, &mut system) + } + (Event::PressLong(button), _) => { + match button { + Button::LampLeft => Some(State::Silent), + Button::LampMid => Some(State::Silent), + Button::LampRight => Some(State::Silent), + + Button::DeskLeftMost => Some(State::Sleep), + Button::DeskLeft => Some(State::Normal), + Button::DeskRightMost => Some(State::LightLoop), + _ => None, + } + } }; + + if let Some(next_state) = next_state { + //state.breakdown() + state = change_state(next_state, &mut mods, &mut system); + current_state = next_state; + } } }); Ok(handle) } +fn change_state(next_state: State, mods: &mut Modifications, system: &mut System) -> Box { + + match next_state { + State::Normal => Box::new(state::Normal::setup(mods, system)), + State::LightLoop => Box::new(state::LightLoop::setup(mods, system)), + State::WakeUp => Box::new(state::WakeUp::setup(mods, system)), + State::Sleep => Box::new(state::Sleep::setup(mods, system)), + State::Silent => Box::new(state::Silent::setup(mods, system)), + } +} \ No newline at end of file diff --git a/src/controller/states/lightloop.rs b/src/controller/state/lightloop.rs similarity index 64% rename from src/controller/states/lightloop.rs rename to src/controller/state/lightloop.rs index f46b6e15..b95bac18 100755 --- a/src/controller/states/lightloop.rs +++ b/src/controller/state/lightloop.rs @@ -1,6 +1,5 @@ use super::super::{Modifications, System, Environment}; -use super::{RoomState, ActiveState}; -use super::normal; +use super::{RoomState, State}; use std::time::{Duration, Instant}; @@ -9,19 +8,8 @@ pub struct LightLoop { counter: u8, } -impl RoomState for LightLoop { - fn update(mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> ActiveState { - dbg!("updating lightloop state"); - if self.counter == 0 { - ActiveState::Normal(normal::Normal::enter(mods, sys)) - } else { - dbg!(self.counter); - sys.lights.set_all_ct(self.counter, 200).unwrap(); - self.counter -= 1; - ActiveState::LightLoop(self) - } - } - fn enter(mods: &mut Modifications, sys: &mut System) -> Self { +impl LightLoop { + pub fn setup(mods: &mut Modifications, sys: &mut System) -> Self { dbg!("making everything rdy for the lightloop state"); sys.lights.set_all_ct(0, 200).unwrap(); @@ -34,5 +22,21 @@ impl RoomState for LightLoop { } } +impl RoomState for LightLoop { + fn update(&mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> Option { + dbg!("updating lightloop state"); + if self.counter == 0 { + Some(State::Normal) + } else { + dbg!(self.counter); + sys.lights.set_all_ct(self.counter, 200).unwrap(); + self.counter -= 1; + None + } + } + fn breakdown(&self, _: &mut Modifications, _: &mut System) {} + fn state(&self) -> State {State::LightLoop } +} + diff --git a/src/controller/state/mod.rs b/src/controller/state/mod.rs new file mode 100755 index 00000000..7b68e57e --- /dev/null +++ b/src/controller/state/mod.rs @@ -0,0 +1,29 @@ +use serde::{Serialize, Deserialize}; +use super::{System, Modifications, Environment}; + +mod normal; +mod lightloop; +mod wakeup; +mod sleep; +mod silent; + +pub use normal::Normal; +pub use lightloop::LightLoop; +pub use wakeup::WakeUp; +pub use sleep::Sleep; +pub use silent::Silent; + +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] +pub enum State { + Normal, + LightLoop, + WakeUp, + Sleep, + Silent, +} + +pub trait RoomState { + fn update(&mut self, mods: &mut Modifications, system: &mut System, env: &mut Environment) -> Option; + fn breakdown(&self, mods: &mut Modifications, system: &mut System); + fn state(&self) -> State; +} \ No newline at end of file diff --git a/src/controller/states/normal.rs b/src/controller/state/normal.rs similarity index 59% rename from src/controller/states/normal.rs rename to src/controller/state/normal.rs index e2a7bbc2..3990192f 100755 --- a/src/controller/states/normal.rs +++ b/src/controller/state/normal.rs @@ -1,5 +1,5 @@ use super::super::{Modifications, System, Environment}; -use super::{RoomState, ActiveState}; +use super::{RoomState, State}; use chrono::{Local, NaiveTime}; use std::time::{Duration, Instant}; @@ -7,11 +7,11 @@ use log::error; fn update_lights(sys: &mut System) { let now = Local::now(); - let res = if now.time() > NaiveTime::from_hms(22,0,0) { + let res = if now.time() > NaiveTime::from_hms(22,0,0) || now.time() < NaiveTime::from_hms(6,0,0) { sys.lights.set_all_ct(220,500) } else if now.time() > NaiveTime::from_hms(17,0,0) { sys.lights.set_all_ct(254,320) - } else if now.time() > NaiveTime::from_hms(6,0,0) { + } else if now.time() >= NaiveTime::from_hms(6,0,0) { sys.lights.set_all_ct(254,240) } else { return; @@ -26,20 +26,27 @@ fn update_lights(sys: &mut System) { #[derive(Default, Clone, Copy)] pub struct Normal {} -impl RoomState for Normal { - fn update(self, _mods: &mut Modifications, sys: &mut System, _env: &mut Environment) - -> ActiveState { - - //dbg!("updating normal state"); - update_lights(sys); - ActiveState::Normal(self) - } - - fn enter(_mods: &mut Modifications, sys: &mut System) -> Self { +impl Normal { + pub fn setup(mods: &mut Modifications, sys: &mut System) -> Self { dbg!("making everything rdy for the normal state"); + mods.reset(); + sys.update_period = Duration::from_secs(5); sys.next_update = Instant::now()+sys.update_period; + update_lights(sys); Self::default() } +} + +impl RoomState for Normal { + fn update(&mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> Option { + + //dbg!("updating normal state"); + if !mods.lighting {update_lights(sys);} + None + } + + fn breakdown(&self, _: &mut Modifications, _: &mut System) {} + fn state(&self) -> State {State::LightLoop } } \ No newline at end of file diff --git a/src/controller/state/silent.rs b/src/controller/state/silent.rs new file mode 100644 index 00000000..f36ee135 --- /dev/null +++ b/src/controller/state/silent.rs @@ -0,0 +1,37 @@ +use super::super::{Modifications, System, Environment}; +use super::{RoomState, State}; +use crate::controller::system::mpd_control as mpd; + +use std::time::{Duration, Instant}; + +#[derive(Clone, Copy)] +pub struct Silent { +} + +impl Silent { + pub fn setup(mods: &mut Modifications, sys: &mut System) -> Self { + dbg!("entering silent mode"); + mods.reset(); + + sys.update_period = Duration::from_secs(60); + sys.next_update = Instant::now()+sys.update_period; + + mpd::pause(); + sys.lights.set_all_ct(50,500); + sys.lights.single_off(1); + + Silent { } + } +} + +impl RoomState for Silent { + fn update(&mut self, _: &mut Modifications, _: &mut System, _env: &mut Environment) + -> Option { + + + None + } + + fn breakdown(&self, _: &mut Modifications, _: &mut System) {} + fn state(&self) -> State {State::LightLoop } +} \ No newline at end of file diff --git a/src/controller/state/sleep.rs b/src/controller/state/sleep.rs new file mode 100644 index 00000000..e18b71bf --- /dev/null +++ b/src/controller/state/sleep.rs @@ -0,0 +1,45 @@ +use super::super::{Modifications, System, Environment}; +use super::{RoomState, State}; +use crate::controller::system::mpd_control as mpd; + +use std::time::{Duration, Instant}; + +#[derive(Clone, Copy)] +pub struct Sleep { + start: Instant, +} + +impl Sleep { + pub fn setup(mods: &mut Modifications, sys: &mut System) -> Self { + dbg!("entering sleep mode"); + mods.reset(); + + sys.update_period = Duration::from_secs(60); + sys.next_update = Instant::now()+sys.update_period; + + const RED: (f32,f32,f32) = (1f32, 0f32, 0f32); + sys.lights.set_all_rgb(0, RED); + + Sleep {start: Instant::now()} + } +} + +impl RoomState for Sleep { + + fn update(&mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> Option { + const LIGHTS_OFF: Duration = Duration::from_secs(60); + const MUSIC_OFF: Duration = Duration::from_secs(120); + + if self.start.elapsed() >= LIGHTS_OFF && !mods.lighting { + sys.lights.off(); + } + if self.start.elapsed() >= MUSIC_OFF && !mods.mpd { + mpd::pause(); + } + + None + } + + fn breakdown(&self, _: &mut Modifications, _: &mut System) {} + fn state(&self) -> State {State::LightLoop } +} \ No newline at end of file diff --git a/src/controller/states/wakeup.rs b/src/controller/state/wakeup.rs similarity index 89% rename from src/controller/states/wakeup.rs rename to src/controller/state/wakeup.rs index 45d88de6..21214925 100755 --- a/src/controller/states/wakeup.rs +++ b/src/controller/state/wakeup.rs @@ -1,6 +1,5 @@ use super::super::{Modifications, System, Environment}; -use super::{RoomState, ActiveState}; -use super::Normal; +use super::{RoomState, State}; use crate::controller::system; use crate::errors::Error; use retry::{retry, delay::Fixed}; @@ -53,12 +52,30 @@ impl WakeUp { } +impl WakeUp { + pub fn setup(mods: &mut Modifications, sys: &mut System) -> Self { + dbg!("starting wakeup state"); + sys.update_period = Duration::from_secs(UPDATE_PERIOD); + sys.next_update = Instant::now()+sys.update_period; + + // reset modifications on entering state + mods.lighting = false; + mods.mpd = false; + + dbg!("setting up playlist"); + Self::setup_playlist().expect("error creating wakeup playlist"); + dbg!("done with setting up playlist"); + sys.lights.set_all_ct(0, CT_BEGIN).expect("could not set lights on entering wakeup state"); + Self{start: Instant::now(), playing: false} + } +} + impl RoomState for WakeUp { - fn update(self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> ActiveState { + fn update(&mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> Option { let elapsed = self.start.elapsed().as_secs(); if elapsed > WAKEUP_DURATION { - return ActiveState::Normal(Normal::enter(mods, sys)) + return Some(State::Normal); } if !mods.lighting { // if lighting controls have not been modified externally since start @@ -80,22 +97,9 @@ impl RoomState for WakeUp { } } - ActiveState::WakeUp(self) + None } - fn enter(mods: &mut Modifications, sys: &mut System) -> Self { - dbg!("starting wakeup state"); - sys.update_period = Duration::from_secs(UPDATE_PERIOD); - sys.next_update = Instant::now()+sys.update_period; - - // reset modifications on entering state - mods.lighting = false; - mods.mpd = false; - - dbg!("setting up playlist"); - Self::setup_playlist().expect("error creating wakeup playlist"); - dbg!("done with setting up playlist"); - sys.lights.set_all_ct(0, CT_BEGIN).expect("could not set lights on entering wakeup state"); - Self{start: Instant::now(), playing: false} - } + fn breakdown(&self, _: &mut Modifications, _: &mut System) {} + fn state(&self) -> State {State::LightLoop } } diff --git a/src/controller/states/mod.rs b/src/controller/states/mod.rs deleted file mode 100755 index 0c7ef913..00000000 --- a/src/controller/states/mod.rs +++ /dev/null @@ -1,53 +0,0 @@ -use serde::{Serialize, Deserialize}; -use super::{System, Modifications, Environment}; - -mod normal; -mod lightloop; -mod wakeup; -mod sleep; - -pub use normal::Normal; -pub use lightloop::LightLoop; -pub use wakeup::WakeUp; -pub use sleep::Sleep; - -#[derive(Copy, Clone)] -pub enum ActiveState { - Normal(normal::Normal), - LightLoop(lightloop::LightLoop), - WakeUp(wakeup::WakeUp), - Sleep(sleep::Sleep), -} - -#[derive(Copy, Clone, Debug, Serialize, Deserialize)] -pub enum TargetState { - Normal, - LightLoop, - WakeUp, - Sleep, -} - -impl ActiveState { - pub fn update(self, mods: &mut Modifications, system: &mut System, env: &mut Environment) -> ActiveState { - match self { - ActiveState::Normal(state) => state.update(mods, system, env), - ActiveState::LightLoop(state) => state.update(mods, system, env), - ActiveState::WakeUp(state) => state.update(mods, system, env), - ActiveState::Sleep(state) => state.update(mods, system, env), - } - } -} - -pub fn change_state(target_state: TargetState, mods: &mut Modifications, sys: &mut System) -> ActiveState { - match target_state { - TargetState::Normal => ActiveState::Normal(Normal::enter(mods, sys)), - TargetState::LightLoop => ActiveState::LightLoop(LightLoop::enter(mods, sys)), - TargetState::WakeUp => ActiveState::WakeUp(WakeUp::enter(mods, sys)), - TargetState::Sleep => ActiveState::Sleep(Sleep::enter(mods, sys)), - } -} - -pub trait RoomState { - fn enter(mods: &mut Modifications, system: &mut System) -> Self; - fn update(self, mods: &mut Modifications, system: &mut System, env: &mut Environment) -> ActiveState; -} \ No newline at end of file diff --git a/src/controller/system/lamps/mod.rs b/src/controller/system/lamps/mod.rs index 5da6cdec..87ab8a1f 100755 --- a/src/controller/system/lamps/mod.rs +++ b/src/controller/system/lamps/mod.rs @@ -184,6 +184,12 @@ impl Lighting { Ok(()) } + pub fn single_off(&mut self, lamp_id: usize) -> Result<(),Error> { + let command = LightCommand::off(LightCommand::default() ); + self.bridge.set_light_state(lamp_id, &command); + self.lamps.get_mut(&lamp_id).unwrap().on = true; + Ok(()) + } //how to deal with errors? pub fn set_all_ct(&mut self, bri: u8, ct: u16) -> Result<(),Error>{ diff --git a/src/input/buttons.rs b/src/input/buttons.rs index c0af8a7c..d6f69f01 100755 --- a/src/input/buttons.rs +++ b/src/input/buttons.rs @@ -6,10 +6,48 @@ use log::error; use std::thread; use crossbeam_channel; +use serde::{Serialize, Deserialize}; use crate::errors::Error; -use crate::controller::{Command, Event}; -use crate::controller::TargetState::Sleep; +use crate::controller::Event; + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub enum Button { + LampLeft, + LampMid, + LampRight, + + DeskLeftMost, + DeskLeft, + DeskRight, + DeskRightMost, + + DeskTop, + DeskMid, + DeskBottom, +} + +impl Button { + fn from_offset(offset: usize) -> Option { + match offset { + 16 => Some(Self::LampLeft), + 12 => Some(Self::LampMid), + 13 => Some(Self::LampRight), + + //buttons on desk + 27 => Some(Self::DeskTop), + 22 => Some(Self::DeskMid), + 18 => Some(Self::DeskBottom), + + 23 => Some(Self::DeskLeftMost), + 24 => Some(Self::DeskLeft), + 26 => Some(Self::DeskRight), + 17 => Some(Self::DeskRightMost), + + _ => None, + } + } +} // when pressing 22, 24 is often activated // 23 works perfectly @@ -33,7 +71,7 @@ fn detect_and_handle(chip: &mut Chip, tx: crossbeam_channel::Sender) &mut evt_handles, &mut last_high, &mut last_state); for (offset, down_duration) in key_presses { if down_duration > 10*MILLIS { //debounce - if let Some(event) = to_command(offset, down_duration){ + if let Some(event) = to_event(offset, down_duration){ tx.send(event).unwrap(); } } @@ -94,32 +132,13 @@ fn configure_watching(chip: &mut Chip, offsets: &[u32]) Ok((evt_handles, pollables)) } -fn to_command(offset: usize, duration: u64) -> Option { - if duration > MAX_TAP_LEN { - match offset { - 27 => Some(Event::Command(Command::MpdNextSong)), //left 3, left - 18 => Some(Event::Command(Command::MpdPrevSong)), //left 3, right - 23 => Some(Event::Command(Command::ChangeState(Sleep))), - _ => None, - } +fn to_event(offset: usize, duration: u64) -> Option { + let button = Button::from_offset(offset)?; + if duration > MAX_TAP_LEN { + Some(Event::PressLong(button)) } else { - match offset { - 16 => Some(Event::Command(Command::LampsDim)), - 12 => Some(Event::Command(Command::LampsDimmest)), - 13 => Some(Event::Command(Command::LampsToggle)), - - //buttons on desk - 27 => Some(Event::Command(Command::MpdIncreaseVolume)), //left 3, left - 22 => Some(Event::Command(Command::MpdPause)), //left 3, middle - 18 => Some(Event::Command(Command::MpdDecreaseVolume)), //left 3, right - - 23 => Some(Event::Command(Command::LampsNight)), //right 4, left most - 24 => Some(Event::Command(Command::LampsEvening)), //right 4, left - 26 => Some(Event::Command(Command::LampsDay)), //right 4, right - 17 => Some(Event::Command(Command::LampsToggle)), //right 4, right most - _ => None, - } + Some(Event::PressShort(button)) } } diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index 271628ed..6f429e24 100755 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -11,7 +11,7 @@ use serde::Deserialize; use actix_web::HttpResponse; use crate::input::youtube_downloader::FeedbackChannel; -use crate::controller::{Command, TargetState, Event}; +use crate::controller::{Command, Event}; use crate::input::alarms::Alarm; mod command_logins; @@ -100,7 +100,7 @@ pub fn night(state: Data, auth: BasicAuth) -> HttpResponse { pub fn lightloop(state: Data, auth: BasicAuth) -> HttpResponse { if authenticated(auth) { - state.controller_addr.send(Event::Command(Command::ChangeState(TargetState::LightLoop))).unwrap(); + //state.controller_addr.send(Event::Command(Command::ChangeState(TargetState::LightLoop))).unwrap(); //TODO FIXME HttpResponse::Ok().finish() } else { make_auth_error() From d3e7993b17b18a6c496c2166c77881ca0feeed98 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Sun, 31 May 2020 01:50:36 +0200 Subject: [PATCH 045/687] adds error handling to states/controller --- src/controller/mod.rs | 137 ++++++++++++++++----------- src/controller/state/lightloop.rs | 24 ++--- src/controller/state/mod.rs | 13 ++- src/controller/state/normal.rs | 36 ++++--- src/controller/state/off.rs | 28 ++++++ src/controller/state/quiet.rs | 38 ++++++++ src/controller/state/silent.rs | 19 ++-- src/controller/state/sleep.rs | 18 ++-- src/controller/state/wakeup.rs | 19 ++-- src/controller/system/lamps/mod.rs | 28 +++++- src/controller/system/mpd_control.rs | 11 ++- 11 files changed, 249 insertions(+), 122 deletions(-) create mode 100644 src/controller/state/off.rs create mode 100644 src/controller/state/quiet.rs diff --git a/src/controller/mod.rs b/src/controller/mod.rs index b5308d01..e2de2601 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -87,8 +87,8 @@ pub fn start(rx: crossbeam_channel::Receiver, mpd_status: MpdStatus) -> R let mut mods = Modifications::default(); let mut env = Environment::default(); // TODO guess best init state from statefile or lamps+mpd+time - - let mut state: Box = Box::new(state::Normal::setup(&mut mods, &mut system)); //initial state + + let mut state: Box = state::Normal::setup(&mut mods, &mut system).unwrap(); //initial state let mut current_state = State::Normal; loop { @@ -105,67 +105,92 @@ pub fn start(rx: crossbeam_channel::Receiver, mpd_status: MpdStatus) -> R } }; - //state changes may not return errors - let next_state = match (event, current_state) { - //specific test code for normal state - (Event::Test, State::Normal) => {dbg!("a test happend while in normal state"); None}, - //general code that is the same for all functions, unless specific handlers exist above - (Event::Command(cmd), _) => handle_cmd(cmd, &mut mods, &mut system), - (Event::Update, _) => state.update(&mut mods, &mut system, &mut env), - (Event::Alarm, _) => Some(State::WakeUp), - (Event::Test, _) => {dbg!("a test happend"); None}, + match handle_event(event, current_state, &mut mods, + &mut system, &mut env, &mut state){ - // #[cfg(feature = "sensors_connected")] - (Event::Sensor(_), _) => None, - - (Event::PressShort(button), _) => { - let cmd = match button { - Button::LampLeft => Command::LampsDim, - Button::LampMid => Command::LampsDimmest, - Button::LampRight => Command::LampsToggle, - - Button::DeskLeftMost => Command::LampsNight, - Button::DeskLeft => Command::LampsEvening, - Button::DeskRight => Command::LampsDay, - Button::DeskRightMost => Command::LampsToggle, - - Button::DeskTop => Command::MpdIncreaseVolume, - Button::DeskMid => Command::MpdPause, - Button::DeskBottom => Command::MpdDecreaseVolume, - }; - handle_cmd(cmd, &mut mods, &mut system) - } - (Event::PressLong(button), _) => { - match button { - Button::LampLeft => Some(State::Silent), - Button::LampMid => Some(State::Silent), - Button::LampRight => Some(State::Silent), - - Button::DeskLeftMost => Some(State::Sleep), - Button::DeskLeft => Some(State::Normal), - Button::DeskRightMost => Some(State::LightLoop), - _ => None, - } - } - }; - - if let Some(next_state) = next_state { - //state.breakdown() - state = change_state(next_state, &mut mods, &mut system); - current_state = next_state; + Err(e) => error!("Ran into an error handling an event: {:?}", e), + Ok(Some(target_state)) => {//should switch to another state + if let Ok(new_state) = change_state(target_state, &mut mods, &mut system){ + state = new_state; + current_state = target_state; + } //if state setup ran into an error we do not switch state + }, + _ => (), } } }); Ok(handle) } -fn change_state(next_state: State, mods: &mut Modifications, system: &mut System) -> Box { +fn handle_event(event: Event, current_state: State, mods: &mut Modifications, + system: &mut System, env: &mut Environment, state: &mut Box) + -> Result, Error> { + + //state changes may not return errors + let next_state = match (event, current_state) { + //specific test code for normal state + (Event::Test, State::Normal) => {dbg!("a test happend while in normal state"); None}, + //general code that is the same for all functions, unless specific handlers exist above + (Event::Command(cmd), _) => handle_cmd(cmd, mods, system), + (Event::Update, _) => state.update(mods, system, env)?, + (Event::Alarm, _) => Some(State::WakeUp), + (Event::Test, _) => {dbg!("a test happend"); None}, + + // #[cfg(feature = "sensors_connected")] + (Event::Sensor(_), _) => None, + + (Event::PressShort(button), _) => { + match button { + Button::LampLeft => Some(State::Quite), + Button::LampMid => Some(State::Silent), + Button::LampRight => Some(State::Off), + + Button::DeskLeftMost => Some(State::Sleep), + Button::DeskLeft => Some(State::Normal), + Button::DeskRightMost => Some(State::Off), + + Button::DeskTop => handle_cmd(Command::MpdIncreaseVolume, mods, system), + Button::DeskMid => handle_cmd(Command::MpdPause, mods, system), + Button::DeskBottom => handle_cmd(Command::MpdDecreaseVolume, mods, system), + + _ => None, + } + } + (Event::PressLong(button), _) => { + let cmd = match button { + Button::LampLeft => Command::LampsDim, + Button::LampMid => Command::LampsDimmest, + Button::LampRight => Command::LampsToggle, + + Button::DeskLeftMost => Command::LampsNight, + Button::DeskLeft => Command::LampsEvening, + Button::DeskRight => Command::LampsDay, + Button::DeskRightMost => Command::LampsToggle, - match next_state { - State::Normal => Box::new(state::Normal::setup(mods, system)), - State::LightLoop => Box::new(state::LightLoop::setup(mods, system)), - State::WakeUp => Box::new(state::WakeUp::setup(mods, system)), - State::Sleep => Box::new(state::Sleep::setup(mods, system)), - State::Silent => Box::new(state::Silent::setup(mods, system)), + _ => return Ok(None), + }; + handle_cmd(cmd, mods, system) + } + }; + Ok(next_state) +} + +fn change_state(next_state: State, mods: &mut Modifications, system: &mut System) -> Result, Error> { + + let res = match &next_state { + State::Normal => state::Normal::setup(mods, system), + State::LightLoop => state::LightLoop::setup(mods, system), + State::WakeUp => state::WakeUp::setup(mods, system), + State::Sleep => state::Sleep::setup(mods, system), + State::Silent => state::Silent::setup(mods, system), + State::Quite => state::Quiet::setup(mods, system), + State::Off => state::Off::setup(mods, system), + }; + + if let Err(ref e) = &res { + error!("ran into error trying to switch to state: {:?}, error: {:?}", + next_state,e); } + + res } \ No newline at end of file diff --git a/src/controller/state/lightloop.rs b/src/controller/state/lightloop.rs index b95bac18..b6a7ca2b 100755 --- a/src/controller/state/lightloop.rs +++ b/src/controller/state/lightloop.rs @@ -1,6 +1,6 @@ use super::super::{Modifications, System, Environment}; use super::{RoomState, State}; - +use crate::errors::Error; use std::time::{Duration, Instant}; #[derive(Default, Clone, Copy)] @@ -9,32 +9,34 @@ pub struct LightLoop { } impl LightLoop { - pub fn setup(mods: &mut Modifications, sys: &mut System) -> Self { + pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { dbg!("making everything rdy for the lightloop state"); - sys.lights.set_all_ct(0, 200).unwrap(); + sys.lights.set_all_ct(0, 200)?; mods.lighting = false; sys.update_period = Duration::from_millis(500); sys.next_update = Instant::now()+sys.update_period; - Self {counter: 100, } + Ok(Box::new(Self {counter: 100, })) } } impl RoomState for LightLoop { - fn update(&mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> Option { + fn update(&mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> Result, Error> { dbg!("updating lightloop state"); if self.counter == 0 { - Some(State::Normal) + Ok(Some(State::Normal)) } else { - dbg!(self.counter); - sys.lights.set_all_ct(self.counter, 200).unwrap(); - self.counter -= 1; - None + if !mods.lighting { + dbg!(self.counter); + sys.lights.set_all_ct(self.counter, 200)?; + self.counter -= 1; + } + Ok(None) } } - fn breakdown(&self, _: &mut Modifications, _: &mut System) {} + fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> {Ok(())} fn state(&self) -> State {State::LightLoop } } diff --git a/src/controller/state/mod.rs b/src/controller/state/mod.rs index 7b68e57e..060f43db 100755 --- a/src/controller/state/mod.rs +++ b/src/controller/state/mod.rs @@ -1,17 +1,22 @@ use serde::{Serialize, Deserialize}; use super::{System, Modifications, Environment}; +use crate::errors::Error; mod normal; mod lightloop; mod wakeup; mod sleep; mod silent; +mod quiet; +mod off; pub use normal::Normal; pub use lightloop::LightLoop; pub use wakeup::WakeUp; pub use sleep::Sleep; pub use silent::Silent; +pub use quiet::Quiet; +pub use off::Off; #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub enum State { @@ -20,10 +25,14 @@ pub enum State { WakeUp, Sleep, Silent, + Quite, + Off, } pub trait RoomState { - fn update(&mut self, mods: &mut Modifications, system: &mut System, env: &mut Environment) -> Option; - fn breakdown(&self, mods: &mut Modifications, system: &mut System); + fn update(&mut self, mods: &mut Modifications, system: &mut System, + env: &mut Environment) -> Result, Error>; + fn breakdown(&self, mods: &mut Modifications, system: &mut System) + -> Result<(), Error>; fn state(&self) -> State; } \ No newline at end of file diff --git a/src/controller/state/normal.rs b/src/controller/state/normal.rs index 3990192f..eb3ac813 100755 --- a/src/controller/state/normal.rs +++ b/src/controller/state/normal.rs @@ -1,25 +1,20 @@ use super::super::{Modifications, System, Environment}; use super::{RoomState, State}; +use crate::errors::Error; use chrono::{Local, NaiveTime}; use std::time::{Duration, Instant}; -use log::error; -fn update_lights(sys: &mut System) { +fn update_lights(sys: &mut System) -> Result<(), Error> { let now = Local::now(); - let res = if now.time() > NaiveTime::from_hms(22,0,0) || now.time() < NaiveTime::from_hms(6,0,0) { - sys.lights.set_all_ct(220,500) + if now.time() > NaiveTime::from_hms(22,0,0) || now.time() < NaiveTime::from_hms(6,0,0) { + sys.lights.set_all_ct(220,500)?; } else if now.time() > NaiveTime::from_hms(17,0,0) { - sys.lights.set_all_ct(254,320) + sys.lights.set_all_ct(254,320)?; } else if now.time() >= NaiveTime::from_hms(6,0,0) { - sys.lights.set_all_ct(254,240) - } else { - return; + sys.lights.set_all_ct(254,240)?; }; - - if let Err(e) = res { - error!("could not update lights: {:?}", e); - } + Ok(()) } @@ -27,26 +22,27 @@ fn update_lights(sys: &mut System) { pub struct Normal {} impl Normal { - pub fn setup(mods: &mut Modifications, sys: &mut System) -> Self { + pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { dbg!("making everything rdy for the normal state"); mods.reset(); sys.update_period = Duration::from_secs(5); sys.next_update = Instant::now()+sys.update_period; - update_lights(sys); + update_lights(sys)?; + sys.lights.all_on()?; - Self::default() + Ok(Box::new(Self::default())) } } impl RoomState for Normal { - fn update(&mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> Option { + fn update(&mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> Result,Error> { //dbg!("updating normal state"); - if !mods.lighting {update_lights(sys);} - None + if !mods.lighting {update_lights(sys)?} + Ok(None) } - fn breakdown(&self, _: &mut Modifications, _: &mut System) {} - fn state(&self) -> State {State::LightLoop } + fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> {Ok(())} + fn state(&self) -> State {State::Normal } } \ No newline at end of file diff --git a/src/controller/state/off.rs b/src/controller/state/off.rs new file mode 100644 index 00000000..d67c6364 --- /dev/null +++ b/src/controller/state/off.rs @@ -0,0 +1,28 @@ +use super::super::{Modifications, System, Environment}; +use super::{RoomState, State}; +use crate::controller::system::mpd_control as mpd; +use crate::errors::Error; + +#[derive(Clone, Copy)] +pub struct Off { +} + +impl Off { + pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { + mods.reset(); + mpd::pause()?; + sys.lights.off()?; + Ok(Box::new(Off { })) + } +} + +impl RoomState for Off { + fn update(&mut self, _: &mut Modifications, _: &mut System, _env: &mut Environment) + -> Result, Error> { + + Ok(None) + } + + fn breakdown(&self, _: &mut Modifications, _sys: &mut System) -> Result<(), Error> {Ok(())} + fn state(&self) -> State {State::Off } +} \ No newline at end of file diff --git a/src/controller/state/quiet.rs b/src/controller/state/quiet.rs new file mode 100644 index 00000000..a1d066e7 --- /dev/null +++ b/src/controller/state/quiet.rs @@ -0,0 +1,38 @@ +use super::super::{Modifications, System, Environment}; +use super::{RoomState, State}; +use crate::controller::system::mpd_control as mpd; +use crate::errors::Error; + +use std::time::{Duration, Instant}; + +#[derive(Clone, Copy)] +pub struct Quiet { +} + +impl Quiet { + pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { + dbg!("entering silent mode"); + mods.reset(); + + sys.update_period = Duration::from_secs(60); + sys.next_update = Instant::now()+sys.update_period; + + mpd::set_volume(10)?; + + sys.lights.set_all_ct(1,500)?; + sys.lights.single_off(2)?; + + Ok(Box::new(Quiet { })) + } +} + +impl RoomState for Quiet { + fn update(&mut self, _: &mut Modifications, _: &mut System, _env: &mut Environment) + -> Result, Error> { + + Ok(None) + } + + fn breakdown(&self, _: &mut Modifications, _sys: &mut System) -> Result<(), Error> {Ok(())} + fn state(&self) -> State {State::Quite } +} \ No newline at end of file diff --git a/src/controller/state/silent.rs b/src/controller/state/silent.rs index f36ee135..dca28b93 100644 --- a/src/controller/state/silent.rs +++ b/src/controller/state/silent.rs @@ -1,6 +1,7 @@ use super::super::{Modifications, System, Environment}; use super::{RoomState, State}; use crate::controller::system::mpd_control as mpd; +use crate::errors::Error; use std::time::{Duration, Instant}; @@ -9,29 +10,29 @@ pub struct Silent { } impl Silent { - pub fn setup(mods: &mut Modifications, sys: &mut System) -> Self { + pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { dbg!("entering silent mode"); mods.reset(); sys.update_period = Duration::from_secs(60); sys.next_update = Instant::now()+sys.update_period; - mpd::pause(); - sys.lights.set_all_ct(50,500); - sys.lights.single_off(1); + mpd::pause()?; + sys.lights.set_all_ct(50,500)?; + sys.lights.single_off(2)?; - Silent { } + Ok(Box::new(Silent {})) } } impl RoomState for Silent { fn update(&mut self, _: &mut Modifications, _: &mut System, _env: &mut Environment) - -> Option { + -> Result, Error>{ - None + Ok(None) } - fn breakdown(&self, _: &mut Modifications, _: &mut System) {} - fn state(&self) -> State {State::LightLoop } + fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> {Ok(())} + fn state(&self) -> State {State::Silent } } \ No newline at end of file diff --git a/src/controller/state/sleep.rs b/src/controller/state/sleep.rs index e18b71bf..9fd96b09 100644 --- a/src/controller/state/sleep.rs +++ b/src/controller/state/sleep.rs @@ -1,6 +1,7 @@ use super::super::{Modifications, System, Environment}; use super::{RoomState, State}; use crate::controller::system::mpd_control as mpd; +use crate::errors::Error; use std::time::{Duration, Instant}; @@ -10,7 +11,7 @@ pub struct Sleep { } impl Sleep { - pub fn setup(mods: &mut Modifications, sys: &mut System) -> Self { + pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { dbg!("entering sleep mode"); mods.reset(); @@ -18,28 +19,29 @@ impl Sleep { sys.next_update = Instant::now()+sys.update_period; const RED: (f32,f32,f32) = (1f32, 0f32, 0f32); - sys.lights.set_all_rgb(0, RED); + sys.lights.set_all_rgb(0, RED)?; + sys.lights.all_on()?; - Sleep {start: Instant::now()} + Ok(Box::new(Sleep {start: Instant::now()})) } } impl RoomState for Sleep { - fn update(&mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> Option { + fn update(&mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> Result, Error> { const LIGHTS_OFF: Duration = Duration::from_secs(60); const MUSIC_OFF: Duration = Duration::from_secs(120); if self.start.elapsed() >= LIGHTS_OFF && !mods.lighting { - sys.lights.off(); + sys.lights.all_off()?; } if self.start.elapsed() >= MUSIC_OFF && !mods.mpd { - mpd::pause(); + mpd::pause()?; } - None + Ok(None) } - fn breakdown(&self, _: &mut Modifications, _: &mut System) {} + fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> {Ok(())} fn state(&self) -> State {State::LightLoop } } \ No newline at end of file diff --git a/src/controller/state/wakeup.rs b/src/controller/state/wakeup.rs index 21214925..fd5486bb 100755 --- a/src/controller/state/wakeup.rs +++ b/src/controller/state/wakeup.rs @@ -53,7 +53,7 @@ impl WakeUp { } impl WakeUp { - pub fn setup(mods: &mut Modifications, sys: &mut System) -> Self { + pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { dbg!("starting wakeup state"); sys.update_period = Duration::from_secs(UPDATE_PERIOD); sys.next_update = Instant::now()+sys.update_period; @@ -66,22 +66,23 @@ impl WakeUp { Self::setup_playlist().expect("error creating wakeup playlist"); dbg!("done with setting up playlist"); sys.lights.set_all_ct(0, CT_BEGIN).expect("could not set lights on entering wakeup state"); - Self{start: Instant::now(), playing: false} + + Ok(Box::new(Self{start: Instant::now(), playing: false})) } } impl RoomState for WakeUp { - fn update(&mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> Option { + fn update(&mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> Result, Error> { let elapsed = self.start.elapsed().as_secs(); if elapsed > WAKEUP_DURATION { - return Some(State::Normal); + return Ok(Some(State::Normal)); } if !mods.lighting { // if lighting controls have not been modified externally since start let bri = (BRI_PER_SECOND*(elapsed as f32)) as u8; let ct = CT_BEGIN-(CT_PER_SECOND*(elapsed as f32)) as u16; - sys.lights.set_all_ct(bri, ct).expect("could not update lights in wakeup"); + sys.lights.set_all_ct(bri, ct)?; //TODO map to terror error } if !mods.mpd { // if mpd controls have not been modified externally since start @@ -93,13 +94,13 @@ impl RoomState for WakeUp { } } else { mpd::Client::connect("127.0.0.1:6600") - .and_then(|mut c| c.volume((VOL_PER_SECOND*(elapsed-MUSIC_ON) as f32) as i8 )); + .and_then(|mut c| c.volume((VOL_PER_SECOND*(elapsed-MUSIC_ON) as f32) as i8 )); } } - None + Ok(None) } - fn breakdown(&self, _: &mut Modifications, _: &mut System) {} - fn state(&self) -> State {State::LightLoop } + fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> {Ok(())} + fn state(&self) -> State {State::WakeUp } } diff --git a/src/controller/system/lamps/mod.rs b/src/controller/system/lamps/mod.rs index 87ab8a1f..295e7038 100755 --- a/src/controller/system/lamps/mod.rs +++ b/src/controller/system/lamps/mod.rs @@ -119,6 +119,7 @@ fn get_bridge_and_status() -> Result<(Bridge, BTreeMap Result<(),Error>{ let numb_on: u8 = self.lamps.values().map(|lamp| lamp.on as u8).sum(); @@ -177,16 +183,31 @@ impl Lighting { Ok(()) } - pub fn off(&mut self) -> Result<(),Error> { + pub fn all_off(&mut self) -> Result<(),Error> { let command = LightCommand::off(LightCommand::default() ); self.bridge.set_group_state(0, &command)?; self.lamps.values_mut().for_each(|lamp| lamp.on = false); Ok(()) } + pub fn all_on(&mut self) -> Result<(),Error> { + let command = LightCommand::on(LightCommand::default() ); + self.bridge.set_group_state(0, &command)?; + self.lamps.values_mut().for_each(|lamp| lamp.on = false); + Ok(()) + } + pub fn single_off(&mut self, lamp_id: usize) -> Result<(),Error> { let command = LightCommand::off(LightCommand::default() ); - self.bridge.set_light_state(lamp_id, &command); + self.bridge.set_light_state(lamp_id, &command)?; + self.lamps.get_mut(&lamp_id).unwrap().on = true; + Ok(()) + } + + #[allow(dead_code)] + pub fn single_on(&mut self, lamp_id: usize) -> Result<(),Error> { + let command = LightCommand::on(LightCommand::default() ); + self.bridge.set_light_state(lamp_id, &command)?; self.lamps.get_mut(&lamp_id).unwrap().on = true; Ok(()) } @@ -194,7 +215,7 @@ impl Lighting { //how to deal with errors? pub fn set_all_ct(&mut self, bri: u8, ct: u16) -> Result<(),Error>{ let command = LightCommand::default(); - let command = command.on(); + //let command = command.on(); let command = command.with_bri(bri); let command = command.with_ct(ct); self.bridge.set_group_state(0, &command)?; @@ -203,6 +224,7 @@ impl Lighting { Ok(()) } + #[allow(dead_code)] pub fn set_all_xy(&mut self, bri: u8, xy: (f32, f32)) -> Result<(),Error>{ let command = LightCommand::default(); let command = command.on(); diff --git a/src/controller/system/mpd_control.rs b/src/controller/system/mpd_control.rs index d0c7a246..16b006c3 100755 --- a/src/controller/system/mpd_control.rs +++ b/src/controller/system/mpd_control.rs @@ -57,17 +57,20 @@ pub fn decrease_volume(mpd_status: &mut MpdStatus) -> Result<(),Error>{ Ok(()) } -pub fn next_song() -> Result<(),Error>{ - const VOLUME_INCREMENT: i8 = 5; +pub fn set_volume(volume: i8) -> Result<(),Error>{ + let mut client = mpd::Client::connect("127.0.0.1:6600")?; + client.volume(volume)?; + Ok(()) +} + +pub fn next_song() -> Result<(),Error>{ let mut client = mpd::Client::connect("127.0.0.1:6600")?; client.next()?; Ok(()) } pub fn prev_song() -> Result<(),Error>{ - const VOLUME_INCREMENT: i8 = 5; - let mut client = mpd::Client::connect("127.0.0.1:6600")?; client.prev()?; Ok(()) From 089aae343af68c1b1be4dc33015e6af2855f33f5 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Sun, 31 May 2020 01:51:06 +0200 Subject: [PATCH 046/687] updates some dependencies and fixes warnings --- Cargo.lock | 419 ++++++++++++++++++++------------ src/controller/state/off.rs | 2 +- src/errors.rs | 1 - src/input/alarms.rs | 12 +- src/input/bot/mod.rs | 5 +- src/input/bot/set_alarm.rs | 11 +- src/input/mpd_status.rs | 4 +- src/input/sensors/ble/mod.rs | 12 - src/input/sensors/fields/mod.rs | 1 - src/input/sensors/mod.rs | 4 - src/input/web_api/mod.rs | 3 +- src/input/youtube_downloader.rs | 8 +- 12 files changed, 279 insertions(+), 203 deletions(-) delete mode 100755 src/input/sensors/ble/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 3e70b0c3..9a653b40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,7 +34,7 @@ dependencies = [ "philipshue", "rand 0.6.5", "regex", - "reqwest 0.10.4", + "reqwest 0.10.6", "retry", "ring", "rustls", @@ -108,7 +108,7 @@ dependencies = [ "http 0.2.1", "log", "rustls", - "tokio-rustls 0.12.2", + "tokio-rustls 0.12.3", "trust-dns-proto 0.18.0-alpha.2", "trust-dns-resolver 0.18.0-alpha.2", "webpki", @@ -116,9 +116,9 @@ dependencies = [ [[package]] name = "actix-files" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301482841d3d74483a446ead63cb7d362e187d2c8b603f13d91995621ea53c46" +checksum = "193b22cb1f7b4ff12a4eb2415d6d19e47e44ea93e05930b30d05375ea29d3529" dependencies = [ "actix-http", "actix-service", @@ -126,7 +126,8 @@ dependencies = [ "bitflags 1.2.1", "bytes 0.5.4", "derive_more", - "futures 0.3.5", + "futures-core", + "futures-util", "log", "mime", "mime_guess", @@ -199,12 +200,12 @@ dependencies = [ [[package]] name = "actix-macros" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21705adc76bbe4bc98434890e73a89cd00c6015e5704a60bb6eea6c3b72316b6" +checksum = "a60f9ba7c4e6df97f3aacb14bb5c0cd7d98a49dcbaed0d7f292912ad9a6a3ed2" dependencies = [ - "quote 1.0.5", - "syn 1.0.22", + "quote 1.0.6", + "syn 1.0.29", ] [[package]] @@ -262,21 +263,22 @@ dependencies = [ [[package]] name = "actix-server" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "582a7173c281a4f46b5aa168a11e7f37183dcb71177a39312cc2264da7a632c9" +checksum = "e6d74b464215a473c973a2d7d03a69cc10f4ce1f4b38a7659c5193dc5c675630" dependencies = [ "actix-codec", "actix-rt", "actix-service", "actix-utils", - "futures 0.3.5", + "futures-channel", + "futures-util", "log", "mio", "mio-uds", - "net2", "num_cpus", "slab", + "socket2", ] [[package]] @@ -291,24 +293,23 @@ dependencies = [ [[package]] name = "actix-testing" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48494745b72d0ea8ff0cf874aaf9b622a3ee03d7081ee0c04edea4f26d32c911" +checksum = "47239ca38799ab74ee6a8a94d1ce857014b2ac36f242f70f3f75a66f691e791c" dependencies = [ "actix-macros", "actix-rt", "actix-server", "actix-service", - "futures 0.3.5", "log", - "net2", + "socket2", ] [[package]] name = "actix-threadpool" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4082192601de5f303013709ff84d81ca6a1bc4af7fb24f367a500a23c6e84e" +checksum = "91164716d956745c79dcea5e66d2aa04506549958accefcede5368c70f2fd4ff" dependencies = [ "derive_more", "futures-channel", @@ -334,7 +335,7 @@ dependencies = [ "futures 0.3.5", "log", "rustls", - "tokio-rustls 0.12.2", + "tokio-rustls 0.12.3", "webpki", "webpki-roots", ] @@ -396,13 +397,13 @@ dependencies = [ [[package]] name = "actix-web-codegen" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f00371942083469785f7e28c540164af1913ee7c96a4534acb9cea92c39f057" +checksum = "a71bf475cbe07281d0b3696abb48212db118e7e23219f13596ce865235ff5766" dependencies = [ - "proc-macro2 1.0.13", - "quote 1.0.5", - "syn 1.0.22", + "proc-macro2 1.0.17", + "quote 1.0.6", + "syn 1.0.29", ] [[package]] @@ -431,9 +432,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456d75cbb82da1ad150c8a9d97285ffcd21c9931dcb11e995903e7d75141b38b" +checksum = "a49806b9dadc843c61e7c97e72490ad7f7220ae249012fbda9ad0609457c0543" dependencies = [ "gimli", ] @@ -497,38 +498,33 @@ checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" [[package]] name = "async-std" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "538ecb01eb64eecd772087e5b6f7540cbc917f047727339a472dafed2185b267" +checksum = "a45cee2749d880d7066e328a7e161c7470ced883b2fd000ca4643e9f1dd5083a" dependencies = [ "async-task", - "crossbeam-channel 0.4.2", - "crossbeam-deque", "crossbeam-utils 0.7.2", + "futures-channel", "futures-core", "futures-io", "futures-timer", "kv-log-macro", "log", "memchr", - "mio", - "mio-uds", "num_cpus", "once_cell", "pin-project-lite", "pin-utils", "slab", + "smol", + "wasm-bindgen-futures", ] [[package]] name = "async-task" -version = "1.3.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ac2c016b079e771204030951c366db398864f5026f84a44dafb0ff20f02085d" -dependencies = [ - "libc", - "winapi 0.3.8", -] +checksum = "c17772156ef2829aadc587461c7753af20b7e8db1529bc66855add962a3b35d3" [[package]] name = "async-trait" @@ -536,9 +532,9 @@ version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26c4f3195085c36ea8d24d32b2f828d23296a9370a28aa39d111f6f16bef9f3b" dependencies = [ - "proc-macro2 1.0.13", - "quote 1.0.5", - "syn 1.0.22", + "proc-macro2 1.0.17", + "quote 1.0.6", + "syn 1.0.29", ] [[package]] @@ -616,6 +612,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +[[package]] +name = "base64" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d1ccbaf7d9ec9537465a97bf19edc1a4e158ecb49fc16178202238c569cc42" + [[package]] name = "bincode" version = "1.2.1" @@ -739,9 +741,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.53" +version = "1.0.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "404b1fe4f65288577753b17e3b36a04596ee784493ec249bf81c7f2d2acd751c" +checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311" [[package]] name = "cfg-if" @@ -871,6 +873,20 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69323bff1fb41c635347b8ead484a5ca6c3f11914d784170b158d8449ab07f8e" +dependencies = [ + "cfg-if", + "crossbeam-channel 0.4.2", + "crossbeam-deque", + "crossbeam-epoch 0.8.2", + "crossbeam-queue", + "crossbeam-utils 0.7.2", +] + [[package]] name = "crossbeam-channel" version = "0.3.9" @@ -932,9 +948,9 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" +checksum = "ab6bffe714b6bb07e42f201352c34f51fefd355ace793f9e638ebd52d23f98d2" dependencies = [ "cfg-if", "crossbeam-utils 0.7.2", @@ -976,9 +992,9 @@ version = "0.99.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2127768764f1556535c01b5326ef94bd60ff08dcfbdc544d53e69ed155610f5d" dependencies = [ - "proc-macro2 1.0.13", - "quote 1.0.5", - "syn 1.0.22", + "proc-macro2 1.0.17", + "quote 1.0.6", + "syn 1.0.29", ] [[package]] @@ -1041,9 +1057,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc4bfcfacb61d231109d1d55202c1f33263319668b168843e02ad4652725ec9c" dependencies = [ "heck", - "proc-macro2 1.0.13", - "quote 1.0.5", - "syn 1.0.22", + "proc-macro2 1.0.17", + "quote 1.0.6", + "syn 1.0.29", ] [[package]] @@ -1070,7 +1086,7 @@ version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d371106cc88ffdfb1eabd7111e432da544f16f3e2d7bf1dfe8bf575f1df045cd" dependencies = [ - "version_check 0.9.1", + "version_check 0.9.2", ] [[package]] @@ -1089,9 +1105,9 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.13", - "quote 1.0.5", - "syn 1.0.22", + "proc-macro2 1.0.17", + "quote 1.0.6", + "syn 1.0.29", "synstructure", ] @@ -1242,9 +1258,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39" dependencies = [ "proc-macro-hack", - "proc-macro2 1.0.13", - "quote 1.0.5", - "syn 1.0.22", + "proc-macro2 1.0.17", + "quote 1.0.6", + "syn 1.0.29", ] [[package]] @@ -1264,9 +1280,13 @@ dependencies = [ [[package]] name = "futures-timer" -version = "2.0.2" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" +dependencies = [ + "gloo-timers", + "send_wrapper", +] [[package]] name = "futures-util" @@ -1314,6 +1334,19 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bcc8e0c9bce37868955864dbecd2b1ab2bdf967e6f28066d65aaac620444b65c" +[[package]] +name = "gloo-timers" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "gpio-cdev" version = "0.3.0" @@ -1493,9 +1526,9 @@ dependencies = [ [[package]] name = "hyper" -version = "0.13.5" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96816e1d921eca64d208a85aab4f7798455a8e34229ee5a88c935bdee1b78b14" +checksum = "a6e7655b9594024ad0ee439f3b5a7299369dc2a3f459b47c696f9ff676f9aa1f" dependencies = [ "bytes 0.5.4", "futures-channel", @@ -1507,8 +1540,8 @@ dependencies = [ "httparse", "itoa", "log", - "net2", "pin-project", + "socket2", "time", "tokio 0.2.21", "tower-service 0.3.0", @@ -1552,7 +1585,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3adcd308402b9553630734e9c36b77a7e48b3821251ca2493e8cd596763aafaa" dependencies = [ "bytes 0.5.4", - "hyper 0.13.5", + "hyper 0.13.6", "native-tls", "tokio 0.2.21", "tokio-tls", @@ -1643,9 +1676,9 @@ checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" [[package]] name = "js-sys" -version = "0.3.39" +version = "0.3.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa5a448de267e7358beaf4a5d849518fe9a0c13fce7afd44b06e68550e5562a7" +checksum = "ce10c23ad2ea25ceca0093bd3192229da4c5b3c0f2de499c1ecac0d98d452177" dependencies = [ "wasm-bindgen", ] @@ -1662,9 +1695,9 @@ dependencies = [ [[package]] name = "kv-log-macro" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2d3beed37e5483887d81eb39de6de03a8346531410e1306ca48a9a89bd3a51" +checksum = "4ff57d6d215f7ca7eb35a9a64d656ba4d9d2bef114d741dc08048e75e2f5d418" dependencies = [ "log", ] @@ -1683,9 +1716,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.70" +version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f" +checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" [[package]] name = "linked-hash-map" @@ -2066,9 +2099,9 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-sys" -version = "0.9.56" +version = "0.9.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f02309a7f127000ed50594f0b50ecc69e7c654e16d41b4e8156d1b3df8e0b52e" +checksum = "7410fef80af8ac071d4f63755c0ab89ac3df0fd1ea91f1d1f37cf5cec4395990" dependencies = [ "autocfg 1.0.0", "cc", @@ -2225,22 +2258,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d480cb4e89522ccda96d0eed9af94180b7a5f93fb28f66e1fd7d68431663d1" +checksum = "edc93aeee735e60ecb40cf740eb319ff23eab1c5748abfdb5c180e4ce49f7791" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82996f11efccb19b685b14b5df818de31c1edcee3daa256ab5775dd98e72feb" +checksum = "e58db2081ba5b4c93bd6be09c40fd36cb9193a8336c384f3b40012e531aa7e40" dependencies = [ - "proc-macro2 1.0.13", - "quote 1.0.5", - "syn 1.0.22", + "proc-macro2 1.0.17", + "quote 1.0.6", + "syn 1.0.29", ] [[package]] @@ -2255,6 +2288,18 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b0deb65f46e873ba8aa7c6a8dbe3f23cb1bf59c339a81a1d56361dde4d66ac8" +dependencies = [ + "crossbeam-utils 0.7.2", + "futures-io", + "futures-sink", + "futures-util", +] + [[package]] name = "pkg-config" version = "0.3.17" @@ -2274,10 +2319,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.13", - "quote 1.0.5", - "syn 1.0.22", - "version_check 0.9.1", + "proc-macro2 1.0.17", + "quote 1.0.6", + "syn 1.0.29", + "version_check 0.9.2", ] [[package]] @@ -2286,18 +2331,18 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53" dependencies = [ - "proc-macro2 1.0.13", - "quote 1.0.5", - "syn 1.0.22", + "proc-macro2 1.0.17", + "quote 1.0.6", + "syn 1.0.29", "syn-mid", - "version_check 0.9.1", + "version_check 0.9.2", ] [[package]] name = "proc-macro-hack" -version = "0.5.15" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63" +checksum = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4" [[package]] name = "proc-macro-nested" @@ -2316,9 +2361,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.13" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53f5ffe53a6b28e37c9c1ce74893477864d64f74778a93a4beb43c8fa167f639" +checksum = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101" dependencies = [ "unicode-xid 0.2.0", ] @@ -2353,11 +2398,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42934bc9c8ab0d3b273a16d8551c8f0fcff46be73276ca083ec2414c15c4ba5e" +checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea" dependencies = [ - "proc-macro2 1.0.13", + "proc-macro2 1.0.17", ] [[package]] @@ -2572,9 +2617,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.3.7" +version = "1.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692" +checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" dependencies = [ "aho-corasick", "memchr", @@ -2584,9 +2629,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.17" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" +checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" [[package]] name = "remove_dir_all" @@ -2637,18 +2682,18 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.10.4" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b81e49ddec5109a9dcfc5f2a317ff53377c915e9ae9d4f2fb50914b85614e2" +checksum = "3b82c9238b305f26f53443e3a4bc8528d64b8d0bee408ec949eb7bf5635ec680" dependencies = [ - "base64 0.11.0", + "base64 0.12.1", "bytes 0.5.4", "encoding_rs", "futures-core", "futures-util", "http 0.2.1", "http-body 0.3.1", - "hyper 0.13.5", + "hyper 0.13.6", "hyper-tls 0.4.1", "js-sys", "lazy_static", @@ -2660,14 +2705,13 @@ dependencies = [ "pin-project-lite", "serde", "serde_urlencoded 0.6.1", - "time", "tokio 0.2.21", "tokio-tls", "url 2.1.1", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg 0.6.2", + "winreg 0.7.0", ] [[package]] @@ -2691,9 +2735,9 @@ dependencies = [ [[package]] name = "ring" -version = "0.16.13" +version = "0.16.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703516ae74571f24b465b4a1431e81e2ad51336cb0ded733a55a1aa3eccac196" +checksum = "06b3fefa4f12272808f809a0af618501fdaba41a58963c5fb72238ab0be09603" dependencies = [ "cc", "libc", @@ -2781,6 +2825,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" +[[package]] +name = "scoped-tls-hkt" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e9d7eaddb227e8fbaaa71136ae0e1e913ca159b86c7da82f3e8f0044ad3a63" + [[package]] name = "scopeguard" version = "0.3.3" @@ -2847,11 +2897,17 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "send_wrapper" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" + [[package]] name = "serde" -version = "1.0.110" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c" +checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d" dependencies = [ "serde_derive", ] @@ -2868,13 +2924,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.110" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984" +checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250" dependencies = [ - "proc-macro2 1.0.13", - "quote 1.0.5", - "syn 1.0.22", + "proc-macro2 1.0.17", + "quote 1.0.6", + "syn 1.0.29", ] [[package]] @@ -2977,6 +3033,25 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" +[[package]] +name = "smol" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686c634ad1873fffef6aed20f180eede424fbf3bb31802394c90fd7335a661b7" +dependencies = [ + "async-task", + "crossbeam", + "futures-io", + "futures-util", + "nix 0.17.0", + "once_cell", + "piper", + "scoped-tls-hkt", + "slab", + "socket2", + "wepoll-binding", +] + [[package]] name = "socket2" version = "0.3.12" @@ -3046,9 +3121,9 @@ checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.13", - "quote 1.0.5", - "syn 1.0.22", + "proc-macro2 1.0.17", + "quote 1.0.6", + "syn 1.0.29", ] [[package]] @@ -3064,12 +3139,12 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.22" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1425de3c33b0941002740a420b1a906a350b88d08b82b2c8a01035a3f9447bac" +checksum = "bb37da98a55b1d08529362d9cbb863be17556873df2585904ab9d2bc951291d0" dependencies = [ - "proc-macro2 1.0.13", - "quote 1.0.5", + "proc-macro2 1.0.17", + "quote 1.0.6", "unicode-xid 0.2.0", ] @@ -3079,9 +3154,9 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" dependencies = [ - "proc-macro2 1.0.13", - "quote 1.0.5", - "syn 1.0.22", + "proc-macro2 1.0.17", + "quote 1.0.6", + "syn 1.0.29", ] [[package]] @@ -3090,9 +3165,9 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" dependencies = [ - "proc-macro2 1.0.13", - "quote 1.0.5", - "syn 1.0.22", + "proc-macro2 1.0.17", + "quote 1.0.6", + "syn 1.0.29", "unicode-xid 0.2.0", ] @@ -3347,9 +3422,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "141afec0978abae6573065a48882c6bae44c5cc61db9b511ac4abf6a09bfd9cc" +checksum = "3068d891551949b37681724d6b73666787cc63fa8e255c812a41d2513aff9775" dependencies = [ "futures-core", "rustls", @@ -3640,7 +3715,7 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" dependencies = [ - "version_check 0.9.1", + "version_check 0.9.2", ] [[package]] @@ -3738,9 +3813,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae" dependencies = [ "nom", - "proc-macro2 1.0.13", - "quote 1.0.5", - "syn 1.0.22", + "proc-macro2 1.0.17", + "quote 1.0.6", + "syn 1.0.29", ] [[package]] @@ -3773,9 +3848,9 @@ checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" [[package]] name = "version_check" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" +checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" [[package]] name = "void" @@ -3812,9 +3887,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasm-bindgen" -version = "0.2.62" +version = "0.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c7d40d09cdbf0f4895ae58cf57d92e1e57a9dd8ed2e8390514b54a47cc5551" +checksum = "4c2dc4aa152834bc334f506c1a06b866416a8b6697d5c9f75b9a689c8486def0" dependencies = [ "cfg-if", "serde", @@ -3824,24 +3899,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.62" +version = "0.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3972e137ebf830900db522d6c8fd74d1900dcfc733462e9a12e942b00b4ac94" +checksum = "ded84f06e0ed21499f6184df0e0cb3494727b0c5da89534e0fcc55c51d812101" dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.13", - "quote 1.0.5", - "syn 1.0.22", + "proc-macro2 1.0.17", + "quote 1.0.6", + "syn 1.0.29", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a369c5e1dfb7569e14d62af4da642a3cbc2f9a3652fe586e26ac22222aa4b04" +checksum = "64487204d863f109eb77e8462189d111f27cb5712cc9fdb3461297a76963a2f6" dependencies = [ "cfg-if", "js-sys", @@ -3851,38 +3926,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.62" +version = "0.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd85aa2c579e8892442954685f0d801f9129de24fa2136b2c6a539c76b65776" +checksum = "838e423688dac18d73e31edce74ddfac468e37b1506ad163ffaf0a46f703ffe3" dependencies = [ - "quote 1.0.5", + "quote 1.0.6", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.62" +version = "0.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb197bd3a47553334907ffd2f16507b4f4f01bbec3ac921a7719e0decdfe72a" +checksum = "3156052d8ec77142051a533cdd686cba889537b213f948cd1d20869926e68e92" dependencies = [ - "proc-macro2 1.0.13", - "quote 1.0.5", - "syn 1.0.22", + "proc-macro2 1.0.17", + "quote 1.0.6", + "syn 1.0.29", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.62" +version = "0.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91c2916119c17a8e316507afaaa2dd94b47646048014bbdf6bef098c1bb58ad" +checksum = "c9ba19973a58daf4db6f352eda73dc0e289493cd29fb2632eb172085b6521acd" [[package]] name = "web-sys" -version = "0.3.39" +version = "0.3.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bc359e5dd3b46cb9687a051d50a2fdd228e4ba7cf6fcf861a5365c3d671a642" +checksum = "7b72fe77fd39e4bd3eaa4412fd299a0be6b3dfe9d2597e2f1c20beb968f41d17" dependencies = [ "js-sys", "wasm-bindgen", @@ -3890,9 +3965,9 @@ dependencies = [ [[package]] name = "webpki" -version = "0.21.2" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f50e1972865d6b1adb54167d1c8ed48606004c2c9d0ea5f1eeb34d95e863ef" +checksum = "ab146130f5f790d45f82aeeb09e55a256573373ec64409fc19a6fb82fb1032ae" dependencies = [ "ring", "untrusted", @@ -3907,6 +3982,25 @@ dependencies = [ "webpki", ] +[[package]] +name = "wepoll-binding" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374fff4ff9701ff8b6ad0d14bacd3156c44063632d8c136186ff5967d48999a7" +dependencies = [ + "bitflags 1.2.1", + "wepoll-sys", +] + +[[package]] +name = "wepoll-sys" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9082a777aed991f6769e2b654aa0cb29f1c3d615daf009829b07b66c7aff6a24" +dependencies = [ + "cc", +] + [[package]] name = "widestring" version = "0.2.2" @@ -3971,6 +4065,15 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "winreg" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +dependencies = [ + "winapi 0.3.8", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" diff --git a/src/controller/state/off.rs b/src/controller/state/off.rs index d67c6364..7971f842 100644 --- a/src/controller/state/off.rs +++ b/src/controller/state/off.rs @@ -11,7 +11,7 @@ impl Off { pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { mods.reset(); mpd::pause()?; - sys.lights.off()?; + sys.lights.all_off()?; Ok(Box::new(Off { })) } } diff --git a/src/errors.rs b/src/errors.rs index 2e3892b3..1709526c 100755 --- a/src/errors.rs +++ b/src/errors.rs @@ -18,7 +18,6 @@ pub enum Error { YoutubeDownloader(youtube_downloader::Error), WebServerError(server::Error), UnTracked, - PlayListTooShort, } impl From for Error { diff --git a/src/input/alarms.rs b/src/input/alarms.rs index d4d54cbe..25817b6d 100755 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -2,9 +2,9 @@ use crossbeam_channel; use std::thread; use std::ops::Sub; -use chrono::{DateTime, NaiveDateTime, Utc, self}; +use chrono::{DateTime, Utc, self}; use sled; -use byteorder::{ByteOrder, BigEndian, ReadBytesExt}; +use byteorder::{BigEndian, ReadBytesExt}; use serde::{Serialize, Deserialize}; use crate::controller::Event; @@ -131,7 +131,7 @@ impl Alarms { pub fn setup(event_tx: crossbeam_channel::Sender, db: sled::Db) -> Result<(Self, thread::JoinHandle<()>), Error> { - let mut alarm_db = AlarmList { db: db.open_tree("alarms")? }; + let alarm_db = AlarmList { db: db.open_tree("alarms")? }; let (waker_tx, waker_rx) = crossbeam_channel::unbounded(); let waker_db_copy = alarm_db.clone(); @@ -175,7 +175,7 @@ impl AlarmList { async fn add_alarm(&self, to_add: Alarm) -> Result<(), Error> { let mut timestamp = to_add.time.timestamp() as u64; let mut timestamp_array = timestamp.to_be_bytes(); - let mut alarm = bincode::serialize(&to_add).unwrap(); + let alarm = bincode::serialize(&to_add).unwrap(); //create alarm entry if there is no alarm at this timestamp yet //if there is already an alarm schedualed, postpone this one until there is a spot free @@ -199,9 +199,7 @@ impl AlarmList { /// calculate time to the earliest alarm, remove it from the list if the current time is later /// then the alarm - fn get_next(&mut self) -> Option<(u64,Alarm)> { - let now = Utc::now(); - + fn get_next(&mut self) -> Option<(u64,Alarm)> { //get earliest alarm time in db match self.db.get_gt(0u64.to_be_bytes()) { Ok(entry) => { diff --git a/src/input/bot/mod.rs b/src/input/bot/mod.rs index 6766a721..16118514 100644 --- a/src/input/bot/mod.rs +++ b/src/input/bot/mod.rs @@ -25,7 +25,6 @@ pub enum Error{ CouldNotSetWebhook, InvalidServerResponse(reqwest::Response), UnhandledUpdateKind, - UnhandledMessageKind, UnknownCommand(String), SongDownloadError(youtube_downloader::Error), Unauthorized(ChatId), @@ -145,8 +144,6 @@ async fn handle_error(error: Error, chat_id: ChatId, token: &str) { {} to be added", chat_id) } - Error::UnhandledMessageKind => { - String::from(UNHANDLED)} Error::UnhandledUpdateKind => { String::from(UNHANDLED)} Error::CouldNotSetWebhook => unreachable!(), @@ -168,7 +165,7 @@ async fn handle(update: Update, state: State){//TODO change to ref } } UpdateKind::CallbackQuery(callback) => { - let chat_id = callback.message.chat.id(); + //let chat_id = callback.message.chat.id(); handle_callback(callback, &state).await; } diff --git a/src/input/bot/set_alarm.rs b/src/input/bot/set_alarm.rs index 257c7794..ce0b40d8 100644 --- a/src/input/bot/set_alarm.rs +++ b/src/input/bot/set_alarm.rs @@ -3,12 +3,9 @@ use crate::input::web_api::server::State; use crate::input::alarms::Alarm; use crate::controller::Event; use super::send_text; -use chrono::{TimeZone}; -use chrono_tz::Europe::Amsterdam; -use chrono::{Local, Utc, DateTime}; +use chrono::{Local, Utc}; use chrono::Timelike; use chrono::Duration; -use hex::FromHex; #[derive(Debug)] pub enum Error { @@ -20,8 +17,6 @@ pub enum Error { InvalidMinuteArgument, WrongTimeFormat, NoAlarmId, - MalformedAlarmId, - CouldNotRemove, } pub async fn handle<'a>(chat_id: ChatId, token: &str, mut args: std::str::SplitWhitespace<'a>, state: &State) @@ -55,11 +50,11 @@ pub async fn add_alarm<'a>(chat_id: ChatId, token: &str, mut args: std::str::Spl let hour = time.next() .ok_or(Error::WrongTimeFormat)? .parse::() - .map_err(|e| Error::InvalidHourArgument)?; + .map_err(|_| Error::InvalidHourArgument)?; let min = time.next() .ok_or(Error::WrongTimeFormat)? .parse::() - .map_err(|e| Error::InvalidHourArgument)?; + .map_err(|_| Error::InvalidHourArgument)?; if hour > 24 {return Err(Error::InvalidHourArgument);} if min > 60 {return Err(Error::InvalidMinuteArgument);} diff --git a/src/input/mpd_status.rs b/src/input/mpd_status.rs index 97d51cd8..0f53e749 100755 --- a/src/input/mpd_status.rs +++ b/src/input/mpd_status.rs @@ -41,14 +41,14 @@ fn mpd_watcher(mut client: Client, status: MpdStatus, rx: Receiver<()>) { } impl MpdStatus { - pub fn stop_updating(tx: Sender<()>) { + /*pub fn stop_updating(tx: Sender<()>) { let mut client = mpd::Client::connect("127.0.0.1:6600").unwrap(); tx.send(()).unwrap(); //tell mpd watcher to shut down on next check //make a small change to a subsys that is watched to force mpd_watcher to stop idle mode let status = client.status().unwrap(); client.volume(status.volume+1).unwrap(); client.volume(status.volume).unwrap(); - } + }*/ pub fn start_updating() -> Result<(Self, thread::JoinHandle<()>, Sender<()>), Error>{ let mut client = mpd::Client::connect("127.0.0.1:6600")?; diff --git a/src/input/sensors/ble/mod.rs b/src/input/sensors/ble/mod.rs deleted file mode 100755 index 4fc4683c..00000000 --- a/src/input/sensors/ble/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -//use secure_ble::{connect_to_adapter, connect_to_node, authenticate_node, StreamCipher, subscribe, printvalues}; - -mod ble_credentials; -use ble_credentials::*; - - -pub fn init(){ - //let central = connect_to_adapter(); - - //let mut bed_node = connect_to_node(central, node_bed::ADRESS, Duration::from_secs(100)).unwrap(); - //authenticate_node(&mut bed_node, node_bed::HMAC_KEY); -} \ No newline at end of file diff --git a/src/input/sensors/fields/mod.rs b/src/input/sensors/fields/mod.rs index 8a4fd611..22ce6af2 100644 --- a/src/input/sensors/fields/mod.rs +++ b/src/input/sensors/fields/mod.rs @@ -1,6 +1,5 @@ mod compression; -pub type FieldId = u8; pub struct Field { pub offset: u8, //bits pub length: u8, //bits (max 32 bit variables) diff --git a/src/input/sensors/mod.rs b/src/input/sensors/mod.rs index 5503ffa4..438797c5 100755 --- a/src/input/sensors/mod.rs +++ b/src/input/sensors/mod.rs @@ -4,11 +4,9 @@ use futures::future; #[cfg(feature = "sensors_connected")] mod local; mod fields; -mod ble; use std::thread; use std::time::Duration; -use chrono::Utc; use async_std::task; use actix_rt; use serde::{Serialize, Deserialize}; @@ -33,7 +31,6 @@ pub fn start_monitoring(tx: crossbeam_channel::Sender, //init all local sensors let mut local_sensors = local::init(); //subscribe and init remote sensors - ble::init(); thread::spawn(move || {//TODO figure out shutdown behaviour let mut rt = Runtime::new().unwrap(); @@ -41,7 +38,6 @@ pub fn start_monitoring(tx: crossbeam_channel::Sender, loop { //get all measurements let (hum, temp, pressure) = local::measure_and_record(&mut local_sensors); - let now = Utc::now(); //TODO //process data into events and send off as event diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index 6f429e24..1e80284a 100755 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -12,6 +12,7 @@ use actix_web::HttpResponse; use crate::input::youtube_downloader::FeedbackChannel; use crate::controller::{Command, Event}; +use crate::controller::State as TargetState; use crate::input::alarms::Alarm; mod command_logins; @@ -100,7 +101,7 @@ pub fn night(state: Data, auth: BasicAuth) -> HttpResponse { pub fn lightloop(state: Data, auth: BasicAuth) -> HttpResponse { if authenticated(auth) { - //state.controller_addr.send(Event::Command(Command::ChangeState(TargetState::LightLoop))).unwrap(); //TODO FIXME + state.controller_addr.send(Event::Command(Command::ChangeState(TargetState::LightLoop))).unwrap(); //TODO FIXME HttpResponse::Ok().finish() } else { make_auth_error() diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index bf3d0181..a995e8c0 100755 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -31,12 +31,12 @@ pub enum Error{ CouldNotStoreExecutable(std::io::Error), CouldNotDownloadSong(std::process::Output), CouldNotUpdateMpd(mpd::error::Error), - CouldNotCreateTempDir(std::io::Error), + #[allow(dead_code)] CouldNotCreateTempDir(std::io::Error), UnexpectedYoutubeDlStdOut(String), - UnsupportedSource(String), + #[allow(dead_code)] UnsupportedSource(String), CanNoLongerUpdateMeta, - CanNotSwapArtistWithEmptyTitle, - IDWasDeleted, + #[allow(dead_code)] CanNotSwapArtistWithEmptyTitle, + #[allow(dead_code)] IDWasDeleted, } impl std::fmt::Display for Error { From a6ae7f8be88d3eaa6f13397852bac225be373f3e Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Thu, 25 Jun 2020 14:33:38 +0200 Subject: [PATCH 047/687] removes local sensor reading (is extracted to seperate program: sensor central --- .gitignore | 1 + src/controller/mod.rs | 11 +- src/controller/state/quiet.rs | 5 +- src/controller/state/silent.rs | 4 +- src/controller/state/wakeup.rs | 10 +- src/controller/system/lamps/mod.rs | 6 +- src/errors.rs | 8 - src/input/buttons.rs | 159 ------------------- src/input/mod.rs | 8 +- src/input/sensors/fields/compression.rs | 200 ------------------------ src/input/sensors/fields/mod.rs | 42 ----- src/input/sensors/local.rs | 54 ------- src/input/sensors/mod.rs | 70 --------- src/input/web_api/alarms.rs | 83 ++++++++++ src/input/web_api/command_logins.rs | 9 -- src/input/web_api/commands.rs | 75 +++++++++ src/input/web_api/mod.rs | 188 ++-------------------- src/input/web_api/music.rs | 29 ++++ src/input/web_api/sensors.rs | 38 +++++ src/input/web_api/server/mod.rs | 28 ++-- src/input/youtube_downloader.rs | 2 +- src/main.rs | 23 +-- 22 files changed, 278 insertions(+), 775 deletions(-) delete mode 100755 src/input/buttons.rs delete mode 100644 src/input/sensors/fields/compression.rs delete mode 100644 src/input/sensors/fields/mod.rs delete mode 100755 src/input/sensors/local.rs delete mode 100755 src/input/sensors/mod.rs create mode 100644 src/input/web_api/alarms.rs delete mode 100755 src/input/web_api/command_logins.rs create mode 100644 src/input/web_api/commands.rs create mode 100644 src/input/web_api/music.rs create mode 100644 src/input/web_api/sensors.rs diff --git a/.gitignore b/.gitignore index 9c404369..4e3fa2e2 100755 --- a/.gitignore +++ b/.gitignore @@ -72,3 +72,4 @@ userdb.hm # Rust # ##################### target/ +src/input/web_api/logins.rs diff --git a/src/controller/mod.rs b/src/controller/mod.rs index e2de2601..9d8283b1 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -15,22 +15,20 @@ use commands::{handle_cmd}; pub use commands::Command; pub use state::State; -#[cfg(feature = "sensors_connected")] -use crate::input::sensors::SensorValue; use crate::input::mpd_status::MpdStatus; -use crate::input::buttons::Button; use crate::errors::Error; +use crate::input::sensors::Button; #[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub enum Event { Update, Alarm, Test, - #[cfg(feature = "sensors_connected")] - Sensor(SensorValue), Command(Command), PressShort(Button), PressLong(Button), + + } pub struct Modifications { //change name to: alteration, deviation, overrides or something else? @@ -136,8 +134,7 @@ fn handle_event(event: Event, current_state: State, mods: &mut Modifications, (Event::Alarm, _) => Some(State::WakeUp), (Event::Test, _) => {dbg!("a test happend"); None}, - // #[cfg(feature = "sensors_connected")] - (Event::Sensor(_), _) => None, + //(Event::Sensor(_), _) => None, (Event::PressShort(button), _) => { match button { diff --git a/src/controller/state/quiet.rs b/src/controller/state/quiet.rs index a1d066e7..daa0e9e3 100644 --- a/src/controller/state/quiet.rs +++ b/src/controller/state/quiet.rs @@ -18,9 +18,10 @@ impl Quiet { sys.next_update = Instant::now()+sys.update_period; mpd::set_volume(10)?; - - sys.lights.set_all_ct(1,500)?; + sys.lights.single_off(2)?; + sys.lights.set_all_ct(1,500)?; + //sys.lights.single_on(2)?; Ok(Box::new(Quiet { })) } diff --git a/src/controller/state/silent.rs b/src/controller/state/silent.rs index dca28b93..1cc396c2 100644 --- a/src/controller/state/silent.rs +++ b/src/controller/state/silent.rs @@ -18,8 +18,10 @@ impl Silent { sys.next_update = Instant::now()+sys.update_period; mpd::pause()?; - sys.lights.set_all_ct(50,500)?; + sys.lights.single_off(2)?; + sys.lights.set_all_ct(50,500)?; + Ok(Box::new(Silent {})) } diff --git a/src/controller/state/wakeup.rs b/src/controller/state/wakeup.rs index fd5486bb..f161d435 100755 --- a/src/controller/state/wakeup.rs +++ b/src/controller/state/wakeup.rs @@ -62,10 +62,8 @@ impl WakeUp { mods.lighting = false; mods.mpd = false; - dbg!("setting up playlist"); - Self::setup_playlist().expect("error creating wakeup playlist"); - dbg!("done with setting up playlist"); - sys.lights.set_all_ct(0, CT_BEGIN).expect("could not set lights on entering wakeup state"); + Self::setup_playlist()?; + sys.lights.set_all_ct(0, CT_BEGIN)?; Ok(Box::new(Self{start: Instant::now(), playing: false})) } @@ -80,6 +78,10 @@ impl RoomState for WakeUp { } if !mods.lighting { // if lighting controls have not been modified externally since start + if sys.lights.numb_on() < 3 { + sys.lights.all_on()?; + } + let bri = (BRI_PER_SECOND*(elapsed as f32)) as u8; let ct = CT_BEGIN-(CT_PER_SECOND*(elapsed as f32)) as u16; sys.lights.set_all_ct(bri, ct)?; //TODO map to terror error diff --git a/src/controller/system/lamps/mod.rs b/src/controller/system/lamps/mod.rs index 295e7038..87d17c21 100755 --- a/src/controller/system/lamps/mod.rs +++ b/src/controller/system/lamps/mod.rs @@ -164,9 +164,13 @@ impl Lighting { dbg!(&self.lamps); } + pub fn numb_on(&self) -> u8 { + self.lamps.values().map(|lamp| lamp.on as u8).sum() + } + //how to deal with errors? pub fn toggle(&mut self) -> Result<(),Error>{ - let numb_on: u8 = self.lamps.values().map(|lamp| lamp.on as u8).sum(); + let numb_on: u8 = self.numb_on(); let numb_off = self.lamps.len() as u8 - numb_on; //group ID 0 is a special group containing all lights known to the bridge diff --git a/src/errors.rs b/src/errors.rs index 1709526c..88e58eae 100755 --- a/src/errors.rs +++ b/src/errors.rs @@ -6,8 +6,6 @@ use crate::input::web_api::server; #[derive(Debug)] pub enum Error { IO(std::io::Error), - GPIO(gpio_cdev::errors::Error), - GPIONotFound, YamlParsing(serde_yaml::Error), Channel(crossbeam_channel::SendError<()>), DataBase(sled::Error), @@ -43,12 +41,6 @@ impl From for Error { } } -impl From for Error { - fn from(error: gpio_cdev::errors::Error) -> Self { - Error::GPIO(error) - } -} - impl From> for Error { fn from(error: crossbeam_channel::SendError<()>) -> Self { Error::Channel(error) diff --git a/src/input/buttons.rs b/src/input/buttons.rs deleted file mode 100755 index d6f69f01..00000000 --- a/src/input/buttons.rs +++ /dev/null @@ -1,159 +0,0 @@ -use gpio_cdev::{Chip, LineRequestFlags, EventRequestFlags, LineEventHandle}; -use nix::poll::{PollFd, PollFlags, poll}; -use std::os::unix::io::{AsRawFd}; -use smallvec::{SmallVec}; -use log::error; - -use std::thread; -use crossbeam_channel; -use serde::{Serialize, Deserialize}; - -use crate::errors::Error; -use crate::controller::Event; - -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] -pub enum Button { - LampLeft, - LampMid, - LampRight, - - DeskLeftMost, - DeskLeft, - DeskRight, - DeskRightMost, - - DeskTop, - DeskMid, - DeskBottom, -} - -impl Button { - fn from_offset(offset: usize) -> Option { - match offset { - 16 => Some(Self::LampLeft), - 12 => Some(Self::LampMid), - 13 => Some(Self::LampRight), - - //buttons on desk - 27 => Some(Self::DeskTop), - 22 => Some(Self::DeskMid), - 18 => Some(Self::DeskBottom), - - 23 => Some(Self::DeskLeftMost), - 24 => Some(Self::DeskLeft), - 26 => Some(Self::DeskRight), - 17 => Some(Self::DeskRightMost), - - _ => None, - } - } -} - -// when pressing 22, 24 is often activated -// 23 works perfectly -// 24 also works perfectly -const MILLIS: u64 = 1_000_000; //nano to milli -const MAX_TAP_LEN: u64 = 600 * MILLIS; -const N_LINES: usize = 54; - -fn detect_and_handle(chip: &mut Chip, tx: crossbeam_channel::Sender) - -> Result<(), Error>{ - - let offsets: [u32; 10] = [27,22,18, 23,24,26,17, 16,12,13]; - let (mut evt_handles, mut pollables) = configure_watching(chip, &offsets)?; - thread::spawn(move || { - let mut last_high = [0u64; N_LINES]; - let mut last_state = [0u8; N_LINES]; - - loop{ - if poll(&mut pollables, -1).unwrap() !=0 { - let key_presses = process_event(&pollables, - &mut evt_handles, &mut last_high, &mut last_state); - for (offset, down_duration) in key_presses { - if down_duration > 10*MILLIS { //debounce - if let Some(event) = to_event(offset, down_duration){ - tx.send(event).unwrap(); - } - } - } - } - } - }); - Ok(()) -} - -///returns keys that where held as the time they where held in nanoseconds -fn process_event(pollables: &Vec, evt_handles: &mut Vec, - last_rising: &mut [u64], last_state: &mut [u8]) - -> SmallVec::<[(usize,u64); 64]> { - - let mut key_presses = SmallVec::<[(usize,u64); 64]>::new(); - for i in 0..pollables.len() { - if let Some(poll_res) = pollables[i].revents() { - let h = &mut evt_handles[i]; - if poll_res.contains(PollFlags::POLLIN) { - let value = h.get_value().unwrap(); - let event = h.get_event().unwrap(); - let offset = h.line().offset() as usize; - - if value == 1 && last_state[offset] == 0 { - //rising - last_state[offset] = 1; - last_rising[offset] = event.timestamp(); - } else if value == 0 && last_state[offset] == 1 { - //falling update current state and store duration of keypress - last_state[offset] = 0; - let held_for = event.timestamp()-last_rising[offset]; - key_presses.push((offset, held_for)); - } - } - } - } - key_presses -} - -fn configure_watching(chip: &mut Chip, offsets: &[u32]) - -> Result<(Vec, Vec), Error>{ - // maps to the driver for the SoC (builtin) GPIO controller. - let evt_handles = offsets.iter() - .map(|off| chip.get_line(*off).unwrap()) - .map(|line| line.events( - LineRequestFlags::INPUT, - EventRequestFlags::BOTH_EDGES, - "homeautomation", ).unwrap()) - .collect::>(); - - let pollables = evt_handles.iter() - .map(|h| PollFd::new(h.as_raw_fd(), - PollFlags::POLLIN | - PollFlags::POLLPRI)) - .collect::>(); - - Ok((evt_handles, pollables)) -} - - -fn to_event(offset: usize, duration: u64) -> Option { - let button = Button::from_offset(offset)?; - if duration > MAX_TAP_LEN { - Some(Event::PressLong(button)) - } else { - Some(Event::PressShort(button)) - } -} - -pub fn start_monitoring(tx: crossbeam_channel::Sender) - -> Result<(), Error> { - - if let Some(mut chip) = gpio_cdev::chips()? - .filter_map(Result::ok) - .filter(|c| c.label() == "pinctrl-bcm2835") - .next() { - - detect_and_handle(&mut chip, tx)?; - Ok(()) - } else { - error!("could not find gpio chip"); - Err(Error::GPIONotFound) - } -} diff --git a/src/input/mod.rs b/src/input/mod.rs index 359408ab..4db16622 100755 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -1,8 +1,3 @@ -#[cfg(feature = "sensors_connected")] -pub mod sensors; -#[cfg(feature = "sensors_connected")] -pub mod buttons; - pub mod bot; pub mod web_api; pub mod alarms; @@ -10,4 +5,5 @@ pub mod youtube_downloader; pub mod mpd_status; pub use youtube_downloader::YoutubeDownloader; -pub use mpd_status::MpdStatus; \ No newline at end of file +pub use mpd_status::MpdStatus; +pub use web_api::sensors; \ No newline at end of file diff --git a/src/input/sensors/fields/compression.rs b/src/input/sensors/fields/compression.rs deleted file mode 100644 index 91d9e60d..00000000 --- a/src/input/sensors/fields/compression.rs +++ /dev/null @@ -1,200 +0,0 @@ -#[inline] pub fn decode(line: &[u8], bit_offset: u8, length: u8) -> u32 { - let start_byte = (bit_offset /8) as usize; - let stop_byte = ((bit_offset+length) /8 ) as usize; - - let start_mask: u8 = !0 >> (bit_offset % 8); - //println!("start_mask: {}", start_mask); - let used_bits = bit_offset+length - stop_byte as u8 *8; - //println!("div: {}, {}",bit_offset,(((bit_offset+7)/8))*8); - //println!("used_bits: {}",used_bits); - let stop_mask = !(!0 >> used_bits); - //println!("stop mask {:b}",stop_mask); - - //decode first bit (never needs shifting (lowest part is used)) - let mut decoded: u32 = (line[start_byte] & start_mask) as u32; - let mut bits_read = 8-(bit_offset % 8); - //if we have more bits - if length > 8 { - //decode middle bits, no masking needed - for (i, byte) in line[start_byte+1..stop_byte].iter().enumerate(){ - decoded |= (*byte as u32) << (8-(bit_offset % 8) + (i as u8) *8) ; - bits_read+= 8; - } - } - //println!("stop_byte: {}",stop_byte); - //println!("############################\nstop_byte: {}, \nstop_mask: {:b}\nbits_read: {}\nmasked line: {:b}\nraw line: {:b}\n//////////////////////", - //stop_byte, stop_mask,bits_read,line[stop_byte] & stop_mask, line[stop_byte]); - let stop_byte = div_up(bit_offset+length, 8) as usize;//starts at 0 - decoded |= ((line[stop_byte-1] & stop_mask) as u32) << (bits_read-(8-used_bits)); - - decoded -} - -#[inline(always)] fn div_up(x: u8, y: u8) -> u8 { - (x+y-1)/y -} - -#[inline] pub fn encode(to_encode: u32, line: &mut [u8], bit_offset: u8, length: u8) { - - let start_mask = !0 >> (bit_offset % 8); - - let start_byte = (bit_offset /8) as usize; - let stop_byte = ((bit_offset+length) /8 ) as usize; - //println!("start_byte: {}, stop_byte: {}, bit_offset: {}, length: {}", start_byte, stop_byte, bit_offset, length); - - //encode first bit (never needs shifting (lowest part is used)) - line[start_byte] |= (to_encode as u8) & start_mask; - let mut bits_written = 8-(bit_offset % 8); - - if length > 8 { - //decode middle bits, no masking needed - //println!("stop_byte: {}, start_byte+1: {}", stop_byte, start_byte+1); - for byte in line[start_byte+1..stop_byte].iter_mut(){ - //println!("hihi"); - *byte |= (to_encode >> bits_written) as u8; - bits_written += 8; - } - } - - //println!("############################\nstart_byte: {}, stop_byte: {}, \nbits_written: {}\nraw line: {:b}\n//////////////////////", - //start_byte, stop_byte,bits_written,line[start_byte]); - - let used_bits = bit_offset+length -stop_byte as u8 *8; - //let used_bits = bit_offset+length - bits_written; - //println!("used_bits: {}", used_bits); - let stop_mask = !(!0 >> used_bits); - //println!("stop_mask: {}", stop_mask); - let stop_byte = div_up(bit_offset+length, 8) as usize;//starts at 0 - line[stop_byte-1] |= (to_encode >> (bits_written-(8-used_bits))) as u8 & stop_mask; -} - - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn encode_and_decode_multiple_edge_case(){ - let mut line = vec!(0, 0, 0, 0, 0, 0, 0, 0); - encode(1,&mut line, 0, 8); - - print!("binary repr: "); - for byte in &line { - print!("{:b}, ",byte); - } println!(); - - encode(2,&mut line, 8, 8); - - print!("binary repr: "); - for byte in &line { - print!("{:b}, ",byte); - } println!(); - - let decoded1 = decode(&line, 0, 8); - let decoded2 = decode(&line, 8, 8); - - println!("0-10 {} {:b}", decoded1, decoded1); - println!("10-20 {} {:b}", decoded2, decoded2); - assert_eq!(decoded1, 1); - assert_eq!(decoded2, 2); - } - - #[test] - fn encode_and_decode_edge_case(){ - let test_case = u32::max_value(); - let mut line = vec!(0, 0, 0, 0); - encode(test_case,&mut line, 0, 32); - - print!("binary repr: "); - for byte in &line { - print!("{:b}, ",byte); - } println!(); - - let decoded1 = decode(&line, 0, 32); - - println!("0-{} {} {:b}", 32, decoded1, decoded1); - assert_eq!(decoded1, test_case); - } - - #[test] - fn encode_and_decode_start_case(){ - let test_case = 1023; - let mut line = vec!(0, 0, 0, 0); - encode(test_case,&mut line, 0, 10); - - print!("binary repr: "); - for byte in &line { - print!("{:b}, ",byte); - } println!(); - - print!("array repr: "); - for byte in &line { - print!("{}, ",byte); - } println!(); - - let decoded1 = decode(&line, 0, 10); - - println!("0-{} {} {:b}", 10, decoded1, decoded1); - assert_eq!(decoded1, test_case); - } - - #[test] - fn encode_and_decode_multiple(){ - for length in 8..33 { - for offset in 0..16 { - for _power1 in 0..length as u16 *10 { - for _power2 in 0..length as u16 *10 { - let power1 = _power1 as f32*0.1; - let power2 = _power2 as f32*0.1; - let mut array = vec!(0;12); - let test_numb1 = 2f32.powf(power1) as u32; - let test_numb2 = 2f32.powf(power2) as u32; - encode(test_numb1, array.as_mut_slice(), offset, length); - encode(test_numb2, array.as_mut_slice(), offset+length, length); - - // print!("binary repr: "); - // for byte in &array { - // print!("{:b}, ",byte); - // } println!(); - - let decoded_test_numb1 = decode(array.as_slice(), offset, length); - let decoded_test_numb2 = decode(array.as_slice(), offset+length, length); - assert_eq!(test_numb1, decoded_test_numb1, - "\n##### numb:1, \noffset: {},\nlength: {}, \nvalue1: {}, \nvalue2: {}", - offset, length, test_numb1, test_numb2); - assert_eq!(test_numb2, decoded_test_numb2, - "\n##### numb:2, \noffset: {},\nlength: {}, \nvalue1: {}, \nvalue2: {}", - offset+length, length, test_numb1, test_numb2); - } - } - } - } - - - } - - fn print_vec_bin(array: Vec) -> String { - let mut outstr = String::from("binary repr: "); - for byte in &array { - outstr.push_str(&format!("{:b}, ",byte)); - } outstr.push_str("\n"); - outstr - } - - #[test] - fn encode_and_decode(){ - for length in 8..32 { - for offset in 0..16 { - for _power in 0..length as u16 *10 { - let power = _power as f32*0.1; - let mut array = vec!(0;8); - let test_numb = 2f32.powf(power) as u32; - encode(test_numb, array.as_mut_slice(), offset, length); - - let decoded_test_numb = decode(array.as_slice(), offset, length); - assert_eq!(test_numb, decoded_test_numb, "offset: {}, length: {} {}", offset, length, print_vec_bin(array)); - } - } - } - } -} diff --git a/src/input/sensors/fields/mod.rs b/src/input/sensors/fields/mod.rs deleted file mode 100644 index 22ce6af2..00000000 --- a/src/input/sensors/fields/mod.rs +++ /dev/null @@ -1,42 +0,0 @@ -mod compression; - -pub struct Field { - pub offset: u8, //bits - pub length: u8, //bits (max 32 bit variables) - - pub decode_scale: T, - pub decode_add: T, -} - -//TODO do away with generics in favor for speeeeed -impl Field -where T: num::cast::NumCast+std::fmt::Display+std::ops::Add+std::ops::SubAssign+std::ops::DivAssign+std::ops::MulAssign+std::marker::Copy { - #[allow(dead_code)] - pub fn decode(&self, line: &[u8]) -> D - where D: num::cast::NumCast+std::fmt::Display+std::ops::Add+std::ops::SubAssign+std::ops::MulAssign+std::ops::AddAssign{ - //where D: From+From+From+std::ops::Add+std::ops::SubAssign+std::ops::DivAssign+std::ops::AddAssign{ - let int_repr: u32 = compression::decode(line, self.offset, self.length); - //println!("int regr: {}", int_repr); - let mut decoded: D = num::cast(int_repr).unwrap(); - - //println!("add: {}", self.decode_add); - //println!("scale: {}", self.decode_scale); - - decoded *= num::cast(self.decode_scale).unwrap();//FIXME flip decode scale / and * - decoded += num::cast(self.decode_add).unwrap(); - - decoded - } - pub fn encode(&self, mut numb: T, line: &mut [u8]) - where D: num::cast::NumCast+std::fmt::Display+std::ops::Add+std::ops::SubAssign+std::ops::AddAssign+std::ops::DivAssign{ - - //println!("org: {}",numb); - numb -= num::cast(self.decode_add).unwrap(); - numb /= num::cast(self.decode_scale).unwrap(); - //println!("scale: {}, add: {}, numb: {}", self.decode_scale, self.decode_add, numb); - - let to_encode: u32 = num::cast(numb).unwrap(); - - compression::encode(to_encode, line, self.offset, self.length); - } -} \ No newline at end of file diff --git a/src/input/sensors/local.rs b/src/input/sensors/local.rs deleted file mode 100755 index 672c75eb..00000000 --- a/src/input/sensors/local.rs +++ /dev/null @@ -1,54 +0,0 @@ -extern crate linux_embedded_hal as hal; -extern crate bme280; - -use hal::{Delay, I2cdev}; -use bme280::BME280; -use super::fields::Field; - -pub const START_ENCODE: u8 = 10*8; -pub const TEMPERATURE: Field = Field { - offset: START_ENCODE, //bits - length: 13, //bits (max 32 bit variables) - - decode_scale: 0.009999999776482582, - decode_add: -20.0f32, -}; -pub const HUMIDITY: Field = Field { - offset: START_ENCODE - +TEMPERATURE.length, - length: 14, - - decode_scale: 0.00800000037997961, - decode_add: 0.0, -}; -pub const PRESSURE: Field = Field { - offset: START_ENCODE - +TEMPERATURE.length - +HUMIDITY.length, - length: 19, - - decode_scale: 0.18000000715255738, - decode_add: 30000.0, -}; -pub const STOP_ENCODE: usize = (START_ENCODE - +TEMPERATURE.length - +HUMIDITY.length - +PRESSURE.length) as usize; - -pub fn init() -> BME280 { - // using Linux I2C Bus #1 in this example - let i2c_bus = I2cdev::new("/dev/i2c-1").unwrap(); - // initialize the BME280 using the primary I2C address 0x77 - let mut bme280 = BME280::new_primary(i2c_bus, Delay); - // initialize the sensor - bme280.init().unwrap(); - bme280 -} - -pub fn measure_and_record(bme: &mut BME280 ) -> (f32, f32, f32) { - // measure temperature, pressure, and humidity - let measurements = bme.measure().unwrap(); - - (measurements.humidity, measurements.temperature, measurements.pressure) -} - diff --git a/src/input/sensors/mod.rs b/src/input/sensors/mod.rs deleted file mode 100755 index 438797c5..00000000 --- a/src/input/sensors/mod.rs +++ /dev/null @@ -1,70 +0,0 @@ -use byteorder::{LittleEndian, ByteOrder}; -use futures::future; - -#[cfg(feature = "sensors_connected")] -mod local; -mod fields; - -use std::thread; -use std::time::Duration; -use async_std::task; -use actix_rt; -use serde::{Serialize, Deserialize}; - -use crate::controller::Event; -use local::{TEMPERATURE, HUMIDITY, PRESSURE, STOP_ENCODE}; - -#[derive(Debug, Clone, Copy, Serialize, Deserialize)] -pub enum SensorValue { - Temperature(f32), - Humidity(f32), - Pressure(f32), -} - -use actix_rt::Runtime; -//const LOCAL_SENSING_ID: timeseries_interface::DatasetId = 0; -//TODO mechanisme for shutdown -#[cfg(feature = "sensors_connected")] -pub fn start_monitoring(tx: crossbeam_channel::Sender, - node_id: u16, dataserver_key: u64) { - - //init all local sensors - let mut local_sensors = local::init(); - //subscribe and init remote sensors - - thread::spawn(move || {//TODO figure out shutdown behaviour - let mut rt = Runtime::new().unwrap(); - - loop { - //get all measurements - let (hum, temp, pressure) = local::measure_and_record(&mut local_sensors); - - //TODO - //process data into events and send off as event - tx.send(Event::Sensor(SensorValue::Temperature(temp))).unwrap(); - tx.send(Event::Sensor(SensorValue::Humidity(hum))).unwrap(); - tx.send(Event::Sensor(SensorValue::Pressure(pressure))).unwrap(); - - //encode all data - let mut line = vec!(0u8; (STOP_ENCODE+8-1)/8); - LittleEndian::write_u16(&mut line[0..2], node_id); - LittleEndian::write_u64(&mut line[2..10], dataserver_key); - - TEMPERATURE.encode::(temp, &mut line); - HUMIDITY.encode::(hum, &mut line); - PRESSURE.encode::(pressure, &mut line); - - let client = reqwest::Client::new(); - let send = client.post("https://www.deviousd.duckdns.org:38972/post_data") - .body(line) - .send(); - let sleep = task::sleep(Duration::from_secs(5)); - //send data to dataserver and sleep up to 5 sec - let (send_err, _) = rt.block_on(future::join(send, sleep)); - if let Err(e) = send_err { - error!("could not send data to dataserver, error: {:?}", e); - } - - } - }); -} diff --git a/src/input/web_api/alarms.rs b/src/input/web_api/alarms.rs new file mode 100644 index 00000000..1d816ca3 --- /dev/null +++ b/src/input/web_api/alarms.rs @@ -0,0 +1,83 @@ +use chrono::{DateTime, NaiveDateTime, Utc}; +use std::time::Duration; +use serde::Deserialize; + +use crate::controller::Event; +use crate::input::alarms::Alarm; +use super::*; + +#[derive(Deserialize, Debug)] +pub struct AlarmDataMinFrom { + min_till_alarm: String, +} + +pub fn set_alarm_minutes_from_now(req: HttpRequest, params: Form, + state: Data, auth: BasicAuth) -> HttpResponse { + if authenticated(auth) { + //Code to parse alarm time + dbg!(¶ms); + + if let Ok(minutes) = params.min_till_alarm.parse(){ + let time = Utc::now() + chrono::Duration::minutes(minutes); + + //state.alarms.add_alarm(time).unwrap(); + HttpResponse::Ok().finish() + } else { + make_error(StatusCode::INTERNAL_SERVER_ERROR) + } + } else { + make_auth_error() + } +} + +#[derive(Deserialize, Debug)] +pub struct AlarmDataUnixTS { + timestamp: String, +} + +pub async fn set_alarm_unix_timestamp(params: Form, state: Data) -> HttpResponse { + //Code to parse alarm time + dbg!(¶ms); + + if let Ok(ts) = params.timestamp.parse(){ + let time = DateTime::::from_utc(NaiveDateTime::from_timestamp(ts, 0), Utc); + dbg!(time); + dbg!(Utc::now()); + + if time>Utc::now() { + let alarm = Alarm::from(time, Event::Alarm, Some(Duration::from_secs(3600*2))); + + if state.alarms.add_alarm(alarm).await.is_ok() { + dbg!("done setting alarm"); + HttpResponse::Ok().finish() + } else { + dbg!(); + make_error( StatusCode::INTERNAL_SERVER_ERROR) + } + } else { + dbg!(); + make_error(StatusCode::UNPROCESSABLE_ENTITY) + } + } else { + dbg!(); + make_error(StatusCode::INTERNAL_SERVER_ERROR) + } +} + +pub fn list_alarms(state: Data) -> HttpResponse { + //Code to parse alarm time + + let alarms = state.alarms.list(); + let mut list = String::with_capacity(alarms.len()*100); + for (id,alarm) in alarms { + list.push_str(&format!("{:x}, {}, {:?}, {:?}", + id, + &alarm.time.to_rfc2822(), + &alarm.action, + &alarm.expiration, + )); + list.push_str("\n"); + } + dbg!(&list); + HttpResponse::Ok().body(list) +} \ No newline at end of file diff --git a/src/input/web_api/command_logins.rs b/src/input/web_api/command_logins.rs deleted file mode 100755 index 0e0445f1..00000000 --- a/src/input/web_api/command_logins.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub struct CompileTimeLogin { - pub username: &'static str, - pub password: &'static str, -} - -pub const LIST: [CompileTimeLogin; 2] = [ - CompileTimeLogin {username: "eva", password: "superbabje"}, - CompileTimeLogin {username: "david", password: "12481632"}, -]; diff --git a/src/input/web_api/commands.rs b/src/input/web_api/commands.rs new file mode 100644 index 00000000..2baca748 --- /dev/null +++ b/src/input/web_api/commands.rs @@ -0,0 +1,75 @@ +use actix_web::web::Data; +use actix_web_httpauth::extractors::basic::{BasicAuth}; + +use actix_web::HttpResponse; + +use crate::controller::{Command, Event}; +use crate::controller::State as TargetState; +use super::*; + +///////////////////// lamp commands /////////////////////////////// + +pub fn toggle(state: Data, auth: BasicAuth) -> HttpResponse { + if authenticated(auth) { + state.controller_addr.send(Event::Command(Command::LampsToggle)).unwrap(); + HttpResponse::Ok().finish() + } else { + make_auth_error() + } +} + +pub fn dim(state: Data, auth: BasicAuth) -> HttpResponse { + if authenticated(auth) { + state.controller_addr.send(Event::Command(Command::LampsDim)).unwrap(); + HttpResponse::Ok().finish() + } else { + make_auth_error() + } +} + +pub fn dimmest(state: Data, auth: BasicAuth) -> HttpResponse { + if authenticated(auth) { + state.controller_addr.send(Event::Command(Command::LampsDimmest)).unwrap(); + HttpResponse::Ok().finish() + } else { + make_auth_error() + } +} + +pub fn normal(state: Data, auth: BasicAuth) -> HttpResponse { + if authenticated(auth) { + state.controller_addr.send(Event::Command(Command::LampsDay)).unwrap(); + HttpResponse::Ok().finish() + } else { + make_auth_error() + } +} + +pub fn evening(state: Data, auth: BasicAuth) -> HttpResponse { + if authenticated(auth) { + state.controller_addr.send(Event::Command(Command::LampsEvening)).unwrap(); + HttpResponse::Ok().finish() + } else { + make_auth_error() + } +} + +pub fn night(state: Data, auth: BasicAuth) -> HttpResponse { + if authenticated(auth) { + state.controller_addr.send(Event::Command(Command::LampsNight)).unwrap(); + HttpResponse::Ok().finish() + } else { + make_auth_error() + } +} + +//////////////////////// go to state commands ///////////////////////////////// + +pub fn lightloop(state: Data, auth: BasicAuth) -> HttpResponse { + if authenticated(auth) { + state.controller_addr.send(Event::Command(Command::ChangeState(TargetState::LightLoop))).unwrap(); //TODO FIXME + HttpResponse::Ok().finish() + } else { + make_auth_error() + } +} \ No newline at end of file diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index 1e80284a..2c8a963f 100755 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -1,21 +1,17 @@ -use actix_web::web::{Form, Data}; use actix_web_httpauth::extractors::basic::{BasicAuth}; use actix_web_httpauth::headers::www_authenticate::basic::Basic; use actix_web_httpauth::headers::www_authenticate::WwwAuthenticate; -use actix_web::http::StatusCode; - -use chrono::{DateTime, NaiveDateTime, Utc}; -use std::time::Duration; -use serde::Deserialize; -use actix_web::HttpResponse; +use actix_web::http::StatusCode; +use actix_web::{HttpResponse, HttpRequest}; +use actix_web::web::{Form, Data}; -use crate::input::youtube_downloader::FeedbackChannel; -use crate::controller::{Command, Event}; -use crate::controller::State as TargetState; -use crate::input::alarms::Alarm; +mod logins; +mod alarms; +mod music; +pub mod sensors; +mod commands; -mod command_logins; pub mod server; use server::State; @@ -23,7 +19,7 @@ fn authenticated(auth: BasicAuth) -> bool { let username = auth.user_id(); if let Some(password) = auth.password(){ - command_logins::LIST.iter() + logins::LIST.iter() .filter(|x| x.username==username) .filter(|x| x.password==password) .next().is_some() @@ -40,169 +36,3 @@ fn make_auth_error() -> HttpResponse { fn make_error(statuscode: StatusCode) -> HttpResponse { HttpResponse::build(statuscode).finish() } - -///////////////////// lamp commands /////////////////////////////// - -pub fn toggle(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { - state.controller_addr.send(Event::Command(Command::LampsToggle)).unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } -} - -pub fn dim(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { - state.controller_addr.send(Event::Command(Command::LampsDim)).unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } -} - -pub fn dimmest(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { - state.controller_addr.send(Event::Command(Command::LampsDimmest)).unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } -} - -pub fn normal(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { - state.controller_addr.send(Event::Command(Command::LampsDay)).unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } -} - -pub fn evening(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { - state.controller_addr.send(Event::Command(Command::LampsEvening)).unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } -} - -pub fn night(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { - state.controller_addr.send(Event::Command(Command::LampsNight)).unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } -} - -//////////////////////// go to state commands ///////////////////////////////// - -pub fn lightloop(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { - state.controller_addr.send(Event::Command(Command::ChangeState(TargetState::LightLoop))).unwrap(); //TODO FIXME - HttpResponse::Ok().finish() - } else { - make_auth_error() - } -} - -//////////////////////// control alarms commands ///////////////////////////////// - -#[derive(Deserialize, Debug)] -pub struct AlarmDataMinFrom { - min_till_alarm: String, -} - -/*pub fn set_alarm_minutes_from_now(req: HttpRequest, params: Form, - state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { - //Code to parse alarm time - dbg!(¶ms); - - if let Ok(minutes) = params.min_till_alarm.parse(){ - let time = Utc::now() + chrono::Duration::minutes(minutes); - - state.alarms.add_alarm(time).unwrap(); - HttpResponse::Ok().finish() - } else { - make_error(StatusCode::INTERNAL_SERVER_ERROR) - } - } else { - make_auth_error() - } -}*/ - -#[derive(Deserialize, Debug)] -pub struct AlarmDataUnixTS { - timestamp: String, -} - -pub async fn set_alarm_unix_timestamp(params: Form, state: Data) -> HttpResponse { - //Code to parse alarm time - dbg!(¶ms); - - if let Ok(ts) = params.timestamp.parse(){ - let time = DateTime::::from_utc(NaiveDateTime::from_timestamp(ts, 0), Utc); - dbg!(time); - dbg!(Utc::now()); - - if time>Utc::now() { - let alarm = Alarm::from(time, Event::Alarm, Some(Duration::from_secs(3600*2))); - - if state.alarms.add_alarm(alarm).await.is_ok() { - dbg!("done setting alarm"); - HttpResponse::Ok().finish() - } else { - dbg!(); - make_error( StatusCode::INTERNAL_SERVER_ERROR) - } - } else { - dbg!(); - make_error(StatusCode::UNPROCESSABLE_ENTITY) - } - } else { - dbg!(); - make_error(StatusCode::INTERNAL_SERVER_ERROR) - } -} - -pub fn list_alarms(state: Data) -> HttpResponse { - //Code to parse alarm time - - let alarms = state.alarms.list(); - let mut list = String::with_capacity(alarms.len()*100); - for (id,alarm) in alarms { - list.push_str(&format!("{:x}, {}, {:?}, {:?}", - id, - &alarm.time.to_rfc2822(), - &alarm.action, - &alarm.expiration, - )); - list.push_str("\n"); - } - dbg!(&list); - HttpResponse::Ok().body(list) -} - -//////////////////////// control mpd ///////////////////////////////// - -#[derive(Deserialize, Debug)] -pub struct SongUrl { - url: String, -} - -pub async fn add_song_from_url(params: Form, state: Data) -> HttpResponse { - let url = params.into_inner().url; - dbg!(); - - if state.youtube_dl.add_song_to_queue(url, FeedbackChannel::None) - .await.is_ok(){ - dbg!(); - - HttpResponse::Ok().finish() - } else { - make_error(StatusCode::INTERNAL_SERVER_ERROR) - } -} \ No newline at end of file diff --git a/src/input/web_api/music.rs b/src/input/web_api/music.rs new file mode 100644 index 00000000..0df1a5e1 --- /dev/null +++ b/src/input/web_api/music.rs @@ -0,0 +1,29 @@ +use actix_web::web::{Form, Data}; +use actix_web::http::StatusCode; + +use serde::Deserialize; + +use actix_web::HttpResponse; + +use crate::input::youtube_downloader::FeedbackChannel; +use super::*; + + +#[derive(Deserialize, Debug)] +pub struct SongUrl { + url: String, +} + +pub async fn add_song_from_url(params: Form, state: Data) -> HttpResponse { + let url = params.into_inner().url; + dbg!(); + + if state.youtube_dl.add_song_to_queue(url, FeedbackChannel::None) + .await.is_ok(){ + dbg!(); + + HttpResponse::Ok().finish() + } else { + make_error(StatusCode::INTERNAL_SERVER_ERROR) + } +} diff --git a/src/input/web_api/sensors.rs b/src/input/web_api/sensors.rs new file mode 100644 index 00000000..2442e73d --- /dev/null +++ b/src/input/web_api/sensors.rs @@ -0,0 +1,38 @@ +use actix_web::web::{Form, Data}; +use serde::{Deserialize, Serialize}; +use actix_web::HttpResponse; + +use super::*; + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub enum Button { + LampLeft, + LampMid, + LampRight, + + DeskLeftMost, + DeskLeft, + DeskRight, + DeskRightMost, + + DeskTop, + DeskMid, + DeskBottom, +} + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub enum ButtonPress { + Long(Button), + Short(Button), +} + +#[derive(Deserialize, Debug)] +pub struct SongUrl { + url: String, +} + +pub fn handle(params: Form, state: Data) -> HttpResponse { + let tx = &state.controller_addr; + + HttpResponse::Ok().finish() +} \ No newline at end of file diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index 201bdecf..a30db517 100755 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -17,7 +17,6 @@ use std::fs; use crate::input; use crate::input::bot; -use crate::input::web_api; use crate::controller::Event; pub mod database; @@ -27,6 +26,7 @@ pub mod login; pub use database::PasswordDatabase; pub use login::{make_random_cookie_key, login_page, login_get_and_check, logout}; pub use login_redirect::CheckLogin; +use super::{alarms, commands, music, sensors}; pub struct Session {}//TODO deprecate @@ -124,7 +124,7 @@ pub async fn index(_req: HttpRequest) -> impl Responder { } pub fn start_webserver(key_dir: &Path, - state: State, port: u16, domain: String) + state: State, port: u16, domain: String, sensor_token: String) -> Result { let tls_config = make_tls_config(&domain, key_dir)?; @@ -153,30 +153,34 @@ pub fn start_webserver(key_dir: &Path, .route(web::get().to(login_page)) )) .service(web::resource("/commands/lamps/toggle") - .to(web_api::toggle)) + .to(commands::toggle)) .service(web::resource("/commands/lamps/evening") - .to(web_api::evening)) + .to(commands::evening)) .service(web::resource("/commands/lamps/night") - .to(web_api::night)) + .to(commands::night)) .service(web::resource("/commands/lamps/day") - .to(web_api::normal)) + .to(commands::normal)) .service(web::resource("/commands/lamps/dimmest") - .to(web_api::dimmest)) + .to(commands::dimmest)) .service(web::resource("/commands/lamps/dim") - .to(web_api::dim)) + .to(commands::dim)) .service(web::resource("/commands/lightloop") - .to(web_api::lightloop)) + .to(commands::lightloop)) .service(web::resource(&format!("/{}", &state.bot_token)) .to(bot::handle_webhook)) + .service(web::scope(&format!("/{}", sensor_token)) + .service(web::resource("").to(sensors::handle)) + ) + .service(web::scope("/") .wrap(CheckLogin{}) .service(web::resource("").to(index)) .service(web::resource("logout/").to(logout)) - .service(web::resource("add_song").to(web_api::add_song_from_url)) - .service(web::resource("set_alarm").to(web_api::set_alarm_unix_timestamp)) - .service(web::resource("list_alarms").to(web_api::list_alarms)) + .service(web::resource("add_song").to(music::add_song_from_url)) + .service(web::resource("set_alarm").to(alarms::set_alarm_unix_timestamp)) + .service(web::resource("list_alarms").to(alarms::list_alarms)) //for all other urls we try to resolve to static files in the "web" dir .service(axtix_fs::Files::new("", "./web/")) ) diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index a995e8c0..66d3befe 100755 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -32,7 +32,7 @@ pub enum Error{ CouldNotDownloadSong(std::process::Output), CouldNotUpdateMpd(mpd::error::Error), #[allow(dead_code)] CouldNotCreateTempDir(std::io::Error), - UnexpectedYoutubeDlStdOut(String), + #[allow(dead_code)] UnexpectedYoutubeDlStdOut(String), #[allow(dead_code)] UnsupportedSource(String), CanNoLongerUpdateMeta, #[allow(dead_code)] CanNotSwapArtistWithEmptyTitle, diff --git a/src/main.rs b/src/main.rs index b4d97d85..f0975bf3 100755 --- a/src/main.rs +++ b/src/main.rs @@ -19,30 +19,20 @@ mod errors; struct Opt { #[structopt(short = "p", long = "port", default_value = "8080")] port: u16, - #[structopt(short = "e", long = "external-port")] external_port: Option, - #[structopt(short = "t", long = "token")] token: String, - #[structopt(short = "d", long = "domain")] domain: String, - #[structopt(short = "a", long = "admin-password")] password: String, - - #[structopt(short = "n", long = "node-id", default_value= "3")] - node_id: u16, - - #[structopt(short = "s", long = "dataserver-key")] - dataserver_key: u64, - #[structopt(short = "k", long = "keys", default_value="keys")] key_dir: PathBuf, - #[structopt(short = "i", long = "allowed-telegram-ids")] valid_ids: Vec, + #[structopt(short = "n", long = "sensor-id")] + sensor_id: String, } #[actix_rt::main] @@ -85,20 +75,13 @@ async fn main() { //start the webserver let _web_handle = server::start_webserver( &opt.key_dir, state, opt.port, - opt.domain.clone()).unwrap(); + opt.domain.clone(), opt.sensor_id.clone()).unwrap(); bot::set_webhook( &opt.domain, &opt.token, opt.external_port.unwrap_or_else(|| opt.port)).await.unwrap(); - //start monitoring local sensors - #[cfg(feature = "sensors_connected")] - input::sensors::start_monitoring(controller_tx.clone(), opt.node_id, - opt.dataserver_key); - #[cfg(feature = "sensors_connected")] - input::buttons::start_monitoring(controller_tx.clone()).unwrap(); - loop { std::thread::park(); } From 343d448d2fe9a2a0925d68b619c473f9efefc4d0 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Mon, 29 Jun 2020 12:43:37 +0200 Subject: [PATCH 048/687] adds web api input for sensor values --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- src/controller/mod.rs | 2 -- src/input/web_api/sensors.rs | 33 +++++++++++++++++++++++++++------ src/input/web_api/server/mod.rs | 9 ++++----- src/main.rs | 6 +++--- 6 files changed, 37 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9a653b40..979a4a69 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -620,9 +620,9 @@ checksum = "53d1ccbaf7d9ec9537465a97bf19edc1a4e158ecb49fc16178202238c569cc42" [[package]] name = "bincode" -version = "1.2.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" +checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d" dependencies = [ "byteorder", "serde", diff --git a/Cargo.toml b/Cargo.toml index 57358029..d37d531e 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ philipshue = { git = "https://github.com/dskleingeld/philipshue", branch = "mast structopt = "0.3" serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.8" +bincode = "1.3.1" log = "0.4" fern = { version = "0.5.6", features = ["colored"] } @@ -70,5 +71,4 @@ retry = "0.5" telegram-bot = "0.6.3" serde_json = "1.0" regex = "1" -bincode = "1.2" #id3 = "0.5.0" \ No newline at end of file diff --git a/src/controller/mod.rs b/src/controller/mod.rs index 9d8283b1..2e097d04 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -27,8 +27,6 @@ pub enum Event { Command(Command), PressShort(Button), PressLong(Button), - - } pub struct Modifications { //change name to: alteration, deviation, overrides or something else? diff --git a/src/input/web_api/sensors.rs b/src/input/web_api/sensors.rs index 2442e73d..ba695b6e 100644 --- a/src/input/web_api/sensors.rs +++ b/src/input/web_api/sensors.rs @@ -1,8 +1,10 @@ -use actix_web::web::{Form, Data}; +//use bytes::Bytes; +use actix_web::web::{Data, Bytes}; use serde::{Deserialize, Serialize}; use actix_web::HttpResponse; use super::*; +use crate::controller; #[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub enum Button { @@ -26,13 +28,32 @@ pub enum ButtonPress { Short(Button), } -#[derive(Deserialize, Debug)] -pub struct SongUrl { - url: String, +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +pub enum SensorValue { + ButtonPress(ButtonPress), + Temperature(f32), + Humidity(f32), + Pressure(f32), } -pub fn handle(params: Form, state: Data) -> HttpResponse { - let tx = &state.controller_addr; +pub fn handle(body: Bytes, state: Data) -> HttpResponse { + let res = bincode::deserialize::(&body[..]); + match res { + Err(e) => error!("deserialize sensorval failed: {:?}",e), + Ok(v) => { + //temp to ButtonPress + match v { + SensorValue::ButtonPress(p) => { + let event = match p{ + ButtonPress::Long(b) => controller::Event::PressLong(b), + ButtonPress::Short(b) => controller::Event::PressShort(b), + }; + state.controller_addr.send(event).unwrap(); + } + _ => (), + } + } + } HttpResponse::Ok().finish() } \ No newline at end of file diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index a30db517..352a705c 100755 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -124,7 +124,7 @@ pub async fn index(_req: HttpRequest) -> impl Responder { } pub fn start_webserver(key_dir: &Path, - state: State, port: u16, domain: String, sensor_token: String) + state: State, port: u16, domain: String, ha_key: String) -> Result { let tls_config = make_tls_config(&domain, key_dir)?; @@ -168,10 +168,9 @@ pub fn start_webserver(key_dir: &Path, .to(commands::lightloop)) .service(web::resource(&format!("/{}", &state.bot_token)) .to(bot::handle_webhook)) - - .service(web::scope(&format!("/{}", sensor_token)) - .service(web::resource("").to(sensors::handle)) - ) + .service(web::resource(&format!("/{}", ha_key)) + .route(web::post().to(sensors::handle)) + ) .service(web::scope("/") .wrap(CheckLogin{}) diff --git a/src/main.rs b/src/main.rs index f0975bf3..adcab967 100755 --- a/src/main.rs +++ b/src/main.rs @@ -31,8 +31,8 @@ struct Opt { key_dir: PathBuf, #[structopt(short = "i", long = "allowed-telegram-ids")] valid_ids: Vec, - #[structopt(short = "n", long = "sensor-id")] - sensor_id: String, + #[structopt(short = "h", long = "ha-key")] + ha_key: String, } #[actix_rt::main] @@ -75,7 +75,7 @@ async fn main() { //start the webserver let _web_handle = server::start_webserver( &opt.key_dir, state, opt.port, - opt.domain.clone(), opt.sensor_id.clone()).unwrap(); + opt.domain.clone(), opt.ha_key.clone()).unwrap(); bot::set_webhook( From 819db19d590bf6c701d1f6e9402c0590734ec05d Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Mon, 29 Jun 2020 13:07:48 +0200 Subject: [PATCH 049/687] fixes quite and silent mode lamps not turning on --- src/controller/mod.rs | 1 + src/controller/state/quiet.rs | 12 ++++++++++-- src/controller/state/silent.rs | 11 ++++++++++- src/controller/system/lamps/mod.rs | 6 +++--- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/controller/mod.rs b/src/controller/mod.rs index 2e097d04..43954708 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -142,6 +142,7 @@ fn handle_event(event: Event, current_state: State, mods: &mut Modifications, Button::DeskLeftMost => Some(State::Sleep), Button::DeskLeft => Some(State::Normal), + Button::DeskRight => {system.lights.print_info(); None}, Button::DeskRightMost => Some(State::Off), Button::DeskTop => handle_cmd(Command::MpdIncreaseVolume, mods, system), diff --git a/src/controller/state/quiet.rs b/src/controller/state/quiet.rs index daa0e9e3..c83447b9 100644 --- a/src/controller/state/quiet.rs +++ b/src/controller/state/quiet.rs @@ -3,6 +3,7 @@ use super::{RoomState, State}; use crate::controller::system::mpd_control as mpd; use crate::errors::Error; +use philipshue::hue::LightCommand; use std::time::{Duration, Instant}; #[derive(Clone, Copy)] @@ -20,8 +21,15 @@ impl Quiet { mpd::set_volume(10)?; sys.lights.single_off(2)?; - sys.lights.set_all_ct(1,500)?; - //sys.lights.single_on(2)?; + let command = LightCommand::default() + .on() + .with_bri(50) + .with_ct(500); + + for lamp_id in &[8,1,4,6] { + sys.lights.bridge.set_light_state(*lamp_id, &command)?; + sys.lights.lamps.get_mut(lamp_id).unwrap().on = true; + } Ok(Box::new(Quiet { })) } diff --git a/src/controller/state/silent.rs b/src/controller/state/silent.rs index 1cc396c2..423170a7 100644 --- a/src/controller/state/silent.rs +++ b/src/controller/state/silent.rs @@ -3,6 +3,7 @@ use super::{RoomState, State}; use crate::controller::system::mpd_control as mpd; use crate::errors::Error; +use philipshue::hue::LightCommand; use std::time::{Duration, Instant}; #[derive(Clone, Copy)] @@ -20,7 +21,15 @@ impl Silent { mpd::pause()?; sys.lights.single_off(2)?; - sys.lights.set_all_ct(50,500)?; + let command = LightCommand::default() + .on() + .with_bri(1) + .with_ct(500); + + for lamp_id in &[8,1,4,6] { + sys.lights.bridge.set_light_state(*lamp_id, &command)?; + sys.lights.lamps.get_mut(lamp_id).unwrap().on = true; + } Ok(Box::new(Silent {})) diff --git a/src/controller/system/lamps/mod.rs b/src/controller/system/lamps/mod.rs index 87d17c21..4ae12c12 100755 --- a/src/controller/system/lamps/mod.rs +++ b/src/controller/system/lamps/mod.rs @@ -120,7 +120,7 @@ fn get_bridge_and_status() -> Result<(Bridge, BTreeMap, @@ -131,9 +131,9 @@ struct Lamp { } pub struct Lighting { - bridge: Bridge, + pub bridge: Bridge, //local cache of current state (used for toggle) - lamps: HashMap, + pub lamps: HashMap, } impl From<&philipshue::hue::LightState> for Lamp{ From 72c579619fac893acb7fb8714c719b7d1c7334ca Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Mon, 28 Sep 2020 21:54:32 +0200 Subject: [PATCH 050/687] fixes lighting buttons --- src/controller/mod.rs | 6 +++--- src/controller/state/mod.rs | 2 +- src/controller/state/quiet.rs | 6 +++--- src/controller/state/silent.rs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/controller/mod.rs b/src/controller/mod.rs index 43954708..402c0c54 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -136,13 +136,13 @@ fn handle_event(event: Event, current_state: State, mods: &mut Modifications, (Event::PressShort(button), _) => { match button { - Button::LampLeft => Some(State::Quite), + Button::LampLeft => Some(State::Quiet), Button::LampMid => Some(State::Silent), Button::LampRight => Some(State::Off), Button::DeskLeftMost => Some(State::Sleep), Button::DeskLeft => Some(State::Normal), - Button::DeskRight => {system.lights.print_info(); None}, + Button::DeskRight => Some(State::Quiet), Button::DeskRightMost => Some(State::Off), Button::DeskTop => handle_cmd(Command::MpdIncreaseVolume, mods, system), @@ -179,7 +179,7 @@ fn change_state(next_state: State, mods: &mut Modifications, system: &mut System State::WakeUp => state::WakeUp::setup(mods, system), State::Sleep => state::Sleep::setup(mods, system), State::Silent => state::Silent::setup(mods, system), - State::Quite => state::Quiet::setup(mods, system), + State::Quiet => state::Quiet::setup(mods, system), State::Off => state::Off::setup(mods, system), }; diff --git a/src/controller/state/mod.rs b/src/controller/state/mod.rs index 060f43db..7044ba7e 100755 --- a/src/controller/state/mod.rs +++ b/src/controller/state/mod.rs @@ -25,7 +25,7 @@ pub enum State { WakeUp, Sleep, Silent, - Quite, + Quiet, Off, } diff --git a/src/controller/state/quiet.rs b/src/controller/state/quiet.rs index c83447b9..9527e898 100644 --- a/src/controller/state/quiet.rs +++ b/src/controller/state/quiet.rs @@ -20,13 +20,13 @@ impl Quiet { mpd::set_volume(10)?; - sys.lights.single_off(2)?; + sys.lights.single_off(2)?; //2 is desk lamp let command = LightCommand::default() .on() .with_bri(50) .with_ct(500); - for lamp_id in &[8,1,4,6] { + for lamp_id in &[1,8,5,4,6] { sys.lights.bridge.set_light_state(*lamp_id, &command)?; sys.lights.lamps.get_mut(lamp_id).unwrap().on = true; } @@ -43,5 +43,5 @@ impl RoomState for Quiet { } fn breakdown(&self, _: &mut Modifications, _sys: &mut System) -> Result<(), Error> {Ok(())} - fn state(&self) -> State {State::Quite } + fn state(&self) -> State {State::Quiet } } \ No newline at end of file diff --git a/src/controller/state/silent.rs b/src/controller/state/silent.rs index 423170a7..342b1b47 100644 --- a/src/controller/state/silent.rs +++ b/src/controller/state/silent.rs @@ -26,7 +26,7 @@ impl Silent { .with_bri(1) .with_ct(500); - for lamp_id in &[8,1,4,6] { + for lamp_id in &[1,8,5,4,6] { sys.lights.bridge.set_light_state(*lamp_id, &command)?; sys.lights.lamps.get_mut(lamp_id).unwrap().on = true; } From e82f09712443ba6228792e11f557a572037a3f1b Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Mon, 28 Sep 2020 23:45:35 +0200 Subject: [PATCH 051/687] remove openssl dep, only increase volume if playing --- Cargo.lock | 1624 +++++++++++++++++++++-------------- Cargo.toml | 6 +- src/controller/commands.rs | 9 +- src/input/bot/mod.rs | 13 +- src/input/bot/youtube_dl.rs | 6 +- 5 files changed, 982 insertions(+), 676 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 979a4a69..07d5ccb3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,7 +26,7 @@ dependencies = [ "gpio-cdev", "hex", "linux-embedded-hal", - "log", + "log 0.4.11", "mpd", "nix 0.17.0", "num", @@ -34,10 +34,10 @@ dependencies = [ "philipshue", "rand 0.6.5", "regex", - "reqwest 0.10.6", + "reqwest 0.10.8", "retry", "ring", - "rustls", + "rustls 0.16.0", "serde", "serde_json", "serde_yaml", @@ -61,7 +61,7 @@ dependencies = [ "fnv", "futures 0.1.29", "libc", - "log", + "log 0.4.11", "parking_lot 0.7.1", "smallvec 0.6.13", "tokio 0.1.22", @@ -84,30 +84,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09e55f0a5c2ca15795035d90c46bd0e73a5123b72f68f12596d6ba5282051380" dependencies = [ "bitflags 1.2.1", - "bytes 0.5.4", + "bytes 0.5.6", "futures-core", "futures-sink", - "log", - "tokio 0.2.21", + "log 0.4.11", + "tokio 0.2.22", "tokio-util 0.2.0", ] +[[package]] +name = "actix-codec" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78d1833b3838dbe990df0f1f87baf640cf6146e898166afe401839d1b001e570" +dependencies = [ + "bitflags 1.2.1", + "bytes 0.5.6", + "futures-core", + "futures-sink", + "log 0.4.11", + "pin-project", + "tokio 0.2.22", + "tokio-util 0.3.1", +] + [[package]] name = "actix-connect" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c95cc9569221e9802bf4c377f6c18b90ef10227d787611decf79fd47d2a8e76c" dependencies = [ - "actix-codec", + "actix-codec 0.2.0", "actix-rt", "actix-service", - "actix-utils", + "actix-utils 1.0.6", "derive_more", "either", "futures 0.3.5", "http 0.2.1", - "log", - "rustls", + "log 0.4.11", + "rustls 0.16.0", "tokio-rustls 0.12.3", "trust-dns-proto 0.18.0-alpha.2", "trust-dns-resolver 0.18.0-alpha.2", @@ -124,13 +140,13 @@ dependencies = [ "actix-service", "actix-web", "bitflags 1.2.1", - "bytes 0.5.4", + "bytes 0.5.6", "derive_more", "futures-core", "futures-util", - "log", - "mime", - "mime_guess", + "log 0.4.11", + "mime 0.3.16", + "mime_guess 2.0.3", "percent-encoding 2.1.0", "v_htmlescape", ] @@ -141,17 +157,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c16664cc4fdea8030837ad5a845eb231fb93fc3c5c171edfefb52fad92ce9019" dependencies = [ - "actix-codec", + "actix-codec 0.2.0", "actix-connect", "actix-rt", "actix-service", "actix-threadpool", "actix-tls", - "actix-utils", + "actix-utils 1.0.6", "base64 0.11.0", "bitflags 1.2.1", "brotli2", - "bytes 0.5.4", + "bytes 0.5.6", "chrono", "copyless", "derive_more", @@ -163,14 +179,14 @@ dependencies = [ "futures-core", "futures-util", "fxhash", - "h2 0.2.5", + "h2 0.2.6", "http 0.2.1", "httparse", "indexmap", "language-tags", "lazy_static", - "log", - "mime", + "log 0.4.11", + "mime 0.3.16", "percent-encoding 2.1.0", "pin-project", "rand 0.7.3", @@ -204,8 +220,8 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a60f9ba7c4e6df97f3aacb14bb5c0cd7d98a49dcbaed0d7f292912ad9a6a3ed2" dependencies = [ - "quote 1.0.6", - "syn 1.0.29", + "quote 1.0.7", + "syn 1.0.42", ] [[package]] @@ -217,7 +233,7 @@ dependencies = [ "actix", "bytes 0.4.12", "futures 0.1.29", - "log", + "log 0.4.11", "mio", "net2", "num_cpus", @@ -235,13 +251,13 @@ dependencies = [ [[package]] name = "actix-router" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d7a10ca4d94e8c8e7a87c5173aba1b97ba9a6563ca02b0e1cd23531093d3ec8" +checksum = "bbd1f7dbda1645bf7da33554db60891755f6c01c1b2169e2f4c492098d30c235" dependencies = [ "bytestring", "http 0.2.1", - "log", + "log 0.4.11", "regex", "serde", ] @@ -257,23 +273,23 @@ dependencies = [ "copyless", "futures-channel", "futures-util", - "smallvec 1.4.0", - "tokio 0.2.21", + "smallvec 1.4.2", + "tokio 0.2.22", ] [[package]] name = "actix-server" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d74b464215a473c973a2d7d03a69cc10f4ce1f4b38a7659c5193dc5c675630" +checksum = "45407e6e672ca24784baa667c5d32ef109ccdd8d5e0b5ebb9ef8a67f4dfb708e" dependencies = [ - "actix-codec", + "actix-codec 0.3.0", "actix-rt", "actix-service", - "actix-utils", + "actix-utils 2.0.0", "futures-channel", "futures-util", - "log", + "log 0.4.11", "mio", "mio-uds", "num_cpus", @@ -283,9 +299,9 @@ dependencies = [ [[package]] name = "actix-service" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e4fc95dfa7e24171b2d0bb46b85f8ab0e8499e4e3caec691fc4ea65c287564" +checksum = "0052435d581b5be835d11f4eb3bce417c8af18d87ddf8ace99f8e67e595882bb" dependencies = [ "futures-util", "pin-project", @@ -301,22 +317,22 @@ dependencies = [ "actix-rt", "actix-server", "actix-service", - "log", + "log 0.4.11", "socket2", ] [[package]] name = "actix-threadpool" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91164716d956745c79dcea5e66d2aa04506549958accefcede5368c70f2fd4ff" +checksum = "d209f04d002854b9afd3743032a27b066158817965bf5d036824d19ac2cc0e30" dependencies = [ "derive_more", "futures-channel", "lazy_static", - "log", + "log 0.4.11", "num_cpus", - "parking_lot 0.10.2", + "parking_lot 0.11.0", "threadpool", ] @@ -326,18 +342,18 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4e5b4faaf105e9a6d389c606c298dcdb033061b00d532af9df56ff3a54995a8" dependencies = [ - "actix-codec", + "actix-codec 0.2.0", "actix-rt", "actix-service", - "actix-utils", + "actix-utils 1.0.6", "derive_more", "either", "futures 0.3.5", - "log", - "rustls", + "log 0.4.11", + "rustls 0.16.0", "tokio-rustls 0.12.3", "webpki", - "webpki-roots", + "webpki-roots 0.17.0", ] [[package]] @@ -346,14 +362,34 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcf8f5631bf01adec2267808f00e228b761c60c0584cc9fa0b5364f41d147f4e" dependencies = [ - "actix-codec", + "actix-codec 0.2.0", "actix-rt", "actix-service", "bitflags 1.2.1", - "bytes 0.5.4", + "bytes 0.5.6", "either", "futures 0.3.5", - "log", + "log 0.4.11", + "pin-project", + "slab", +] + +[[package]] +name = "actix-utils" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9022dec56632d1d7979e59af14f0597a28a830a9c1c7fec8b2327eb9f16b5a" +dependencies = [ + "actix-codec 0.3.0", + "actix-rt", + "actix-service", + "bitflags 1.2.1", + "bytes 0.5.6", + "either", + "futures-channel", + "futures-sink", + "futures-util", + "log 0.4.11", "pin-project", "slab", ] @@ -364,7 +400,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3158e822461040822f0dbf1735b9c2ce1f95f93b651d7a7aded00b1efbb1f635" dependencies = [ - "actix-codec", + "actix-codec 0.2.0", "actix-http", "actix-macros", "actix-router", @@ -374,20 +410,20 @@ dependencies = [ "actix-testing", "actix-threadpool", "actix-tls", - "actix-utils", + "actix-utils 1.0.6", "actix-web-codegen", "awc", - "bytes 0.5.4", + "bytes 0.5.6", "derive_more", "encoding_rs", "futures 0.3.5", "fxhash", - "log", - "mime", + "log 0.4.11", + "mime 0.3.16", "net2", "pin-project", "regex", - "rustls", + "rustls 0.16.0", "serde", "serde_json", "serde_urlencoded 0.6.1", @@ -401,22 +437,22 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a71bf475cbe07281d0b3696abb48212db118e7e23219f13596ce865235ff5766" dependencies = [ - "proc-macro2 1.0.17", - "quote 1.0.6", - "syn 1.0.29", + "proc-macro2 1.0.23", + "quote 1.0.7", + "syn 1.0.42", ] [[package]] name = "actix-web-httpauth" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0dac4ea96f3f8f03731cecce375890fea6459a01f226bc9c31cc65cae047a03" +checksum = "0ea25b3a3e113d04ae74bfbc3ba617f6254437dbd03576d9b479e8e8df894285" dependencies = [ "actix-service", "actix-web", - "base64 0.11.0", - "bytes 0.5.4", - "futures 0.3.5", + "base64 0.12.3", + "bytes 0.5.6", + "futures-util", ] [[package]] @@ -432,24 +468,24 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a49806b9dadc843c61e7c97e72490ad7f7220ae249012fbda9ad0609457c0543" +checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072" dependencies = [ "gimli", ] [[package]] -name = "adler32" -version = "1.0.4" +name = "adler" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" +checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" [[package]] name = "aho-corasick" -version = "0.7.10" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" +checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" dependencies = [ "memchr", ] @@ -460,20 +496,14 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] -[[package]] -name = "antidote" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" - [[package]] name = "arc-swap" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b585a98a234c46fc563103e9278c9391fde1f4e6850334da895d27edb9580f62" +checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034" [[package]] name = "arrayref" @@ -497,46 +527,120 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" [[package]] -name = "async-std" -version = "1.6.0" +name = "async-channel" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21279cfaa4f47df10b1816007e738ca3747ef2ee53ffc51cdbf57a8bb266fee3" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45cee2749d880d7066e328a7e161c7470ced883b2fd000ca4643e9f1dd5083a" +checksum = "d373d78ded7d0b3fa8039375718cde0aace493f2e34fb60f51cbf567562ca801" dependencies = [ "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "once_cell", + "vec-arena", +] + +[[package]] +name = "async-global-executor" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fefeb39da249f4c33af940b779a56723ce45809ef5c54dad84bb538d4ffb6d9e" +dependencies = [ + "async-executor", + "async-io", + "futures-lite", + "num_cpus", + "once_cell", +] + +[[package]] +name = "async-io" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33be191d05a54ec120e4667375e2ad49fe506b846463df384460ab801c7ae5dc" +dependencies = [ + "concurrent-queue", + "fastrand", + "futures-lite", + "log 0.4.11", + "nb-connect", + "once_cell", + "parking", + "polling", + "vec-arena", + "waker-fn", +] + +[[package]] +name = "async-mutex" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-std" +version = "1.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9fa76751505e8df1c7a77762f60486f60c71bbd9b8557f4da6ad47d083732ed" +dependencies = [ + "async-global-executor", + "async-io", + "async-mutex", + "blocking", "crossbeam-utils 0.7.2", "futures-channel", "futures-core", "futures-io", - "futures-timer", + "futures-lite", + "gloo-timers", "kv-log-macro", - "log", + "log 0.4.11", "memchr", "num_cpus", "once_cell", "pin-project-lite", "pin-utils", "slab", - "smol", "wasm-bindgen-futures", ] [[package]] name = "async-task" -version = "3.0.0" +version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17772156ef2829aadc587461c7753af20b7e8db1529bc66855add962a3b35d3" +checksum = "8ab27c1aa62945039e44edaeee1dc23c74cc0c303dd5fe0fb462a184f1c3a518" [[package]] name = "async-trait" -version = "0.1.31" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c4f3195085c36ea8d24d32b2f828d23296a9370a28aa39d111f6f16bef9f3b" +checksum = "687c230d85c0a52504709705fc8a53e4a692b83a2184f03dae73e38e1e93a783" dependencies = [ - "proc-macro2 1.0.17", - "quote 1.0.6", - "syn 1.0.29", + "proc-macro2 1.0.23", + "quote 1.0.7", + "syn 1.0.42", ] +[[package]] +name = "atomic-waker" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" + [[package]] name = "atty" version = "0.2.14" @@ -545,7 +649,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -556,9 +660,9 @@ checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" [[package]] name = "autocfg" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "awc" @@ -566,19 +670,19 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7601d4d1d7ef2335d6597a41b5fe069f6ab799b85f53565ab390e7b7065aac5" dependencies = [ - "actix-codec", + "actix-codec 0.2.0", "actix-http", "actix-rt", "actix-service", "base64 0.11.0", - "bytes 0.5.4", + "bytes 0.5.6", "derive_more", "futures-core", - "log", - "mime", + "log 0.4.11", + "mime 0.3.16", "percent-encoding 2.1.0", "rand 0.7.3", - "rustls", + "rustls 0.16.0", "serde", "serde_json", "serde_urlencoded 0.6.1", @@ -586,13 +690,14 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.48" +version = "0.3.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df2f85c8a2abbe3b7d7e748052fdd9b76a0458fdeb16ad4223f5eca78c7c130" +checksum = "46254cf2fdcdf1badb5934448c1bcbe046a56537b3987d96c51a7afc5d03f293" dependencies = [ "addr2line", "cfg-if", "libc", + "miniz_oxide", "object", "rustc-demangle", ] @@ -614,9 +719,9 @@ checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" [[package]] name = "base64" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d1ccbaf7d9ec9537465a97bf19edc1a4e158ecb49fc16178202238c569cc42" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" [[package]] name = "bincode" @@ -657,6 +762,20 @@ dependencies = [ "constant_time_eq", ] +[[package]] +name = "blocking" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2640778f8053e72c11f621b0a5175a0560a269282aa98ed85107773ab8e2a556" +dependencies = [ + "async-channel", + "atomic-waker", + "fastrand", + "futures-lite", + "once_cell", + "waker-fn", +] + [[package]] name = "bme280" version = "0.1.2" @@ -694,9 +813,9 @@ checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" [[package]] name = "bumpalo" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5356f1d23ee24a1f785a56d1d1a5f0fd5b0f6a0c0fb2412ce11da71649ab78f6" +checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" [[package]] name = "byteorder" @@ -717,9 +836,9 @@ dependencies = [ [[package]] name = "bytes" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" +checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" [[package]] name = "bytestring" @@ -727,9 +846,15 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7c05fa5172da78a62d9949d662d2ac89d4cc7355d7b49adee5163f1fb3f363" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.6", ] +[[package]] +name = "cache-padded" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" + [[package]] name = "cast" version = "0.2.3" @@ -741,9 +866,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.54" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311" +checksum = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c" [[package]] name = "cfg-if" @@ -753,21 +878,23 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "chrono" -version = "0.4.11" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" +checksum = "d021fddb7bd3e734370acfa4a83f34095571d8570c039f1420d77540f68d5772" dependencies = [ + "libc", "num-integer", "num-traits", "serde", "time", + "winapi 0.3.9", ] [[package]] name = "chrono-tz" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0e430fad0384e4defc3dc6b1223d1b886087a8bf9b7080e5ae027f73851ea15" +checksum = "2554a3155fec064362507487171dcc4edc3df60cb10f3a1fb10ed8094822b120" dependencies = [ "chrono", "parse-zoneinfo", @@ -775,9 +902,9 @@ dependencies = [ [[package]] name = "clap" -version = "2.33.1" +version = "2.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129" +checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" dependencies = [ "ansi_term", "atty", @@ -797,6 +924,15 @@ dependencies = [ "bitflags 1.2.1", ] +[[package]] +name = "cloudabi" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467" +dependencies = [ + "bitflags 1.2.1", +] + [[package]] name = "colored" version = "1.9.3" @@ -805,7 +941,16 @@ checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59" dependencies = [ "atty", "lazy_static", - "winapi 0.3.8", + "winapi 0.3.9", +] + +[[package]] +name = "concurrent-queue" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" +dependencies = [ + "cache-padded", ] [[package]] @@ -833,7 +978,7 @@ dependencies = [ "cookie", "failure", "idna 0.1.5", - "log", + "log 0.4.11", "publicsuffix", "serde", "serde_json", @@ -844,15 +989,15 @@ dependencies = [ [[package]] name = "copyless" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff9c56c9fb2a49c05ef0e431485a22400af20d33226dc0764d891d09e724127" +checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" [[package]] name = "core-foundation" -version = "0.7.0" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +checksum = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" dependencies = [ "core-foundation-sys", "libc", @@ -860,9 +1005,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.7.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" +checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" [[package]] name = "crc32fast" @@ -873,20 +1018,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69323bff1fb41c635347b8ead484a5ca6c3f11914d784170b158d8449ab07f8e" -dependencies = [ - "cfg-if", - "crossbeam-channel 0.4.2", - "crossbeam-deque", - "crossbeam-epoch 0.8.2", - "crossbeam-queue", - "crossbeam-utils 0.7.2", -] - [[package]] name = "crossbeam-channel" version = "0.3.9" @@ -898,9 +1029,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" +checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" dependencies = [ "crossbeam-utils 0.7.2", "maybe-uninit", @@ -937,7 +1068,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", "cfg-if", "crossbeam-utils 0.7.2", "lazy_static", @@ -948,12 +1079,13 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab6bffe714b6bb07e42f201352c34f51fefd355ace793f9e638ebd52d23f98d2" +checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" dependencies = [ "cfg-if", "crossbeam-utils 0.7.2", + "maybe-uninit", ] [[package]] @@ -972,7 +1104,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", "cfg-if", "lazy_static", ] @@ -988,13 +1120,13 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.7" +version = "0.99.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2127768764f1556535c01b5326ef94bd60ff08dcfbdc544d53e69ed155610f5d" +checksum = "1dcfabdab475c16a93d669dddfc393027803e347d09663f524447f642fbb84ba" dependencies = [ - "proc-macro2 1.0.17", - "quote 1.0.6", - "syn 1.0.29", + "proc-macro2 1.0.23", + "quote 1.0.7", + "syn 1.0.42", ] [[package]] @@ -1009,57 +1141,56 @@ dependencies = [ [[package]] name = "dirs-sys" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" +checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a" dependencies = [ - "cfg-if", "libc", "redox_users", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] name = "dtoa" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" +checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b" [[package]] name = "either" -version = "1.5.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "embedded-hal" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee4908a155094da7723c2d60d617b820061e3b4efcc3d9e293d206a5a76c170b" +checksum = "fa998ce59ec9765d15216393af37a58961ddcefb14c753b4816ba2191d865fcb" dependencies = [ - "nb", + "nb 0.1.3", "void", ] [[package]] name = "encoding_rs" -version = "0.8.23" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ac63f94732332f44fe654443c46f6375d1939684c17b0afb6cb56b0456e171" +checksum = "a51b8cf747471cb9499b6d59e59b0444f4c90eba8968c4e44874e92b5b64ace2" dependencies = [ "cfg-if", ] [[package]] name = "enum-as-inner" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc4bfcfacb61d231109d1d55202c1f33263319668b168843e02ad4652725ec9c" +checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595" dependencies = [ "heck", - "proc-macro2 1.0.17", - "quote 1.0.6", - "syn 1.0.29", + "proc-macro2 1.0.23", + "quote 1.0.7", + "syn 1.0.42", ] [[package]] @@ -1082,13 +1213,19 @@ dependencies = [ [[package]] name = "error-chain" -version = "0.12.2" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d371106cc88ffdfb1eabd7111e432da544f16f3e2d7bf1dfe8bf575f1df045cd" +checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" dependencies = [ "version_check 0.9.2", ] +[[package]] +name = "event-listener" +version = "2.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" + [[package]] name = "failure" version = "0.1.8" @@ -1105,12 +1242,18 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.17", - "quote 1.0.6", - "syn 1.0.29", + "proc-macro2 1.0.23", + "quote 1.0.7", + "syn 1.0.42", "synstructure", ] +[[package]] +name = "fastrand" +version = "1.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c85295147490b8fcf2ea3d104080a105a8b2c63f9c319e82c02d8e952388919" + [[package]] name = "fern" version = "0.5.9" @@ -1119,14 +1262,14 @@ checksum = "e69ab0d5aca163e388c3a49d284fed6c3d0810700e77c5ae2756a50ec1a4daaa" dependencies = [ "chrono", "colored", - "log", + "log 0.4.11", ] [[package]] name = "flate2" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42" +checksum = "766d0e77a2c1502169d4a93ff3b8c15a71fd946cd0126309752104e5f3c46d94" dependencies = [ "cfg-if", "crc32fast", @@ -1140,21 +1283,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "fs2" version = "0.4.3" @@ -1162,7 +1290,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" dependencies = [ "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1251,6 +1379,21 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789" +[[package]] +name = "futures-lite" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0db18c5f58083b54b0c416638ea73066722c2815c1e54dd8ba85ee3def593c3a" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + [[package]] name = "futures-macro" version = "0.3.5" @@ -1258,9 +1401,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39" dependencies = [ "proc-macro-hack", - "proc-macro2 1.0.17", - "quote 1.0.6", - "syn 1.0.29", + "proc-macro2 1.0.23", + "quote 1.0.7", + "syn 1.0.42", ] [[package]] @@ -1278,16 +1421,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "futures-timer" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" -dependencies = [ - "gloo-timers", - "send_wrapper", -] - [[package]] name = "futures-util" version = "0.3.5" @@ -1319,20 +1452,20 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] name = "gimli" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc8e0c9bce37868955864dbecd2b1ab2bdf967e6f28066d65aaac620444b65c" +checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724" [[package]] name = "gloo-timers" @@ -1349,8 +1482,8 @@ dependencies = [ [[package]] name = "gpio-cdev" -version = "0.3.0" -source = "git+https://github.com/rust-embedded/gpio-cdev#944a0867a2d6e471a2b6f5c61ce48c8a82affa34" +version = "0.4.0" +source = "git+https://github.com/rust-embedded/gpio-cdev#a8c1c10f3b5f5d76ef34e4581fb0c621865b364b" dependencies = [ "bitflags 1.2.1", "libc", @@ -1369,7 +1502,7 @@ dependencies = [ "futures 0.1.29", "http 0.1.21", "indexmap", - "log", + "log 0.4.11", "slab", "string", "tokio-io", @@ -1377,21 +1510,21 @@ dependencies = [ [[package]] name = "h2" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79b7246d7e4b979c03fa093da39cfb3617a96bbeee6310af63991668d7e843ff" +checksum = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.6", "fnv", "futures-core", "futures-sink", "futures-util", "http 0.2.1", "indexmap", - "log", "slab", - "tokio 0.2.21", + "tokio 0.2.22", "tokio-util 0.3.1", + "tracing", ] [[package]] @@ -1403,6 +1536,12 @@ dependencies = [ "serde", ] +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" + [[package]] name = "heck" version = "0.3.1" @@ -1414,9 +1553,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.13" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71" +checksum = "4c30f6d0bc6b00693347368a67d41b58f2fb851215ff1da49e90fe2c5c667151" dependencies = [ "libc", ] @@ -1441,7 +1580,7 @@ checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" dependencies = [ "libc", "match_cfg", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1461,7 +1600,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.6", "fnv", "itoa", ] @@ -1484,7 +1623,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.6", "http 0.2.1", ] @@ -1494,6 +1633,12 @@ version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" +[[package]] +name = "httpdate" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" + [[package]] name = "hyper" version = "0.12.35" @@ -1509,7 +1654,7 @@ dependencies = [ "httparse", "iovec", "itoa", - "log", + "log 0.4.11", "net2", "rustc_version 0.2.3", "time", @@ -1526,25 +1671,25 @@ dependencies = [ [[package]] name = "hyper" -version = "0.13.6" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6e7655b9594024ad0ee439f3b5a7299369dc2a3f459b47c696f9ff676f9aa1f" +checksum = "2f3afcfae8af5ad0576a31e768415edb627824129e8e5a29b8bfccb2f234e835" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.6", "futures-channel", "futures-core", "futures-util", - "h2 0.2.5", + "h2 0.2.6", "http 0.2.1", "http-body 0.3.1", "httparse", + "httpdate", "itoa", - "log", "pin-project", "socket2", - "time", - "tokio 0.2.21", + "tokio 0.2.22", "tower-service 0.3.0", + "tracing", "want 0.3.0", ] @@ -1558,37 +1703,44 @@ dependencies = [ "ct-logs", "futures 0.1.29", "hyper 0.12.35", - "rustls", + "rustls 0.16.0", "tokio-io", "tokio-rustls 0.10.3", "webpki", - "webpki-roots", + "webpki-roots 0.17.0", ] [[package]] -name = "hyper-tls" -version = "0.3.2" +name = "hyper-rustls" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" +checksum = "f6ea6215c7314d450ee45970ab8b3851ab447a0e6bafdd19e31b20a42dbb7faf" dependencies = [ - "bytes 0.4.12", - "futures 0.1.29", - "hyper 0.12.35", - "native-tls", - "tokio-io", + "bytes 0.5.6", + "ct-logs", + "futures-util", + "hyper 0.13.8", + "rustls 0.16.0", + "rustls-native-certs", + "tokio 0.2.22", + "tokio-rustls 0.12.3", + "webpki", ] [[package]] -name = "hyper-tls" -version = "0.4.1" +name = "hyper-rustls" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3adcd308402b9553630734e9c36b77a7e48b3821251ca2493e8cd596763aafaa" +checksum = "37743cc83e8ee85eacfce90f2f4102030d9ff0a95244098d781e9bee4a90abb6" dependencies = [ - "bytes 0.5.4", - "hyper 0.13.6", - "native-tls", - "tokio 0.2.21", - "tokio-tls", + "bytes 0.5.6", + "futures-util", + "hyper 0.13.8", + "log 0.4.11", + "rustls 0.18.1", + "tokio 0.2.22", + "tokio-rustls 0.14.1", + "webpki", ] [[package]] @@ -1627,11 +1779,21 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.3.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" +checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", + "hashbrown 0.9.1", +] + +[[package]] +name = "instant" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66" +dependencies = [ + "cfg-if", ] [[package]] @@ -1652,7 +1814,7 @@ dependencies = [ "error-chain 0.8.1", "socket2", "widestring 0.2.2", - "winapi 0.3.8", + "winapi 0.3.9", "winreg 0.5.1", ] @@ -1663,22 +1825,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" dependencies = [ "socket2", - "widestring 0.4.0", - "winapi 0.3.8", + "widestring 0.4.2", + "winapi 0.3.9", "winreg 0.6.2", ] +[[package]] +name = "ipnet" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" + [[package]] name = "itoa" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" +checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" [[package]] name = "js-sys" -version = "0.3.40" +version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce10c23ad2ea25ceca0093bd3192229da4c5b3c0f2de499c1ecac0d98d452177" +checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8" dependencies = [ "wasm-bindgen", ] @@ -1695,11 +1863,11 @@ dependencies = [ [[package]] name = "kv-log-macro" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ff57d6d215f7ca7eb35a9a64d656ba4d9d2bef114d741dc08048e75e2f5d418" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" dependencies = [ - "log", + "log 0.4.11", ] [[package]] @@ -1716,9 +1884,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.71" +version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" +checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" [[package]] name = "linked-hash-map" @@ -1758,11 +1926,29 @@ dependencies = [ "scopeguard 1.1.0", ] +[[package]] +name = "lock_api" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c" +dependencies = [ + "scopeguard 1.1.0", +] + +[[package]] +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +dependencies = [ + "log 0.4.11", +] + [[package]] name = "log" -version = "0.4.8" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" dependencies = [ "cfg-if", ] @@ -1802,11 +1988,20 @@ checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" [[package]] name = "memoffset" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" +checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", +] + +[[package]] +name = "mime" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" +dependencies = [ + "log 0.3.9", ] [[package]] @@ -1815,23 +2010,36 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "mime_guess" +version = "1.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216929a5ee4dd316b1702eedf5e74548c123d370f47841ceaac38ca154690ca3" +dependencies = [ + "mime 0.2.6", + "phf", + "phf_codegen", + "unicase 1.4.2", +] + [[package]] name = "mime_guess" version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" dependencies = [ - "mime", - "unicase", + "mime 0.3.16", + "unicase 2.6.0", ] [[package]] name = "miniz_oxide" -version = "0.3.6" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5" +checksum = "c60c0dfe32c10b43a144bad8fc83538c52f58302c92300ea7ec7bf7b38d5a7b9" dependencies = [ - "adler32", + "adler", + "autocfg 1.0.1", ] [[package]] @@ -1846,7 +2054,7 @@ dependencies = [ "iovec", "kernel32-sys", "libc", - "log", + "log 0.4.11", "miow", "net2", "slab", @@ -1888,38 +2096,52 @@ dependencies = [ ] [[package]] -name = "native-tls" -version = "0.2.4" +name = "multipart" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" +checksum = "136eed74cadb9edd2651ffba732b19a450316b680e4f48d6c79e905799e19d01" dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", + "log 0.4.11", + "mime 0.2.6", + "mime_guess 1.8.8", + "rand 0.6.5", "tempfile", ] [[package]] name = "nb" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1411551beb3c11dedfb0a90a0fa256b47d28b9ec2cdff34c25a2fa59e45dbdc" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.0.0", +] + +[[package]] +name = "nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" + +[[package]] +name = "nb-connect" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e847c76b390f44529c2071ef06d0b52fbb4bdb04cc8987a5cfa63954c000abca" +dependencies = [ + "libc", + "winapi 0.3.9", +] [[package]] name = "net2" -version = "0.2.34" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7" +checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853" dependencies = [ "cfg-if", "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1998,7 +2220,7 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", "num-integer", "num-traits", ] @@ -2009,27 +2231,27 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", "num-traits", ] [[package]] name = "num-integer" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00" +checksum = "7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", "num-integer", "num-traits", ] @@ -2040,7 +2262,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", "num-bigint", "num-integer", "num-traits", @@ -2048,11 +2270,11 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", ] [[package]] @@ -2067,29 +2289,15 @@ dependencies = [ [[package]] name = "object" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2" +checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5" [[package]] name = "once_cell" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d" - -[[package]] -name = "openssl" -version = "0.10.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee6d85f4cb4c4f59a6a85d5b68a233d280c82e29e822913b9c8b129fbf20bdd" -dependencies = [ - "bitflags 1.2.1", - "cfg-if", - "foreign-types", - "lazy_static", - "libc", - "openssl-sys", -] +checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad" [[package]] name = "openssl-probe" @@ -2097,24 +2305,11 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -[[package]] -name = "openssl-sys" -version = "0.9.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7410fef80af8ac071d4f63755c0ab89ac3df0fd1ea91f1d1f37cf5cec4395990" -dependencies = [ - "autocfg 1.0.0", - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "ordered-float" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518" +checksum = "3741934be594d77de1c8461ebcbbe866f585ea616a9753aa78f2bdc69f0e4579" dependencies = [ "num-traits", ] @@ -2141,15 +2336,21 @@ dependencies = [ "fs2", "futures 0.1.29", "fxhash", - "hashbrown", + "hashbrown 0.3.1", "historian", "lazy_static", "libc", - "log", + "log 0.4.11", "rayon", "serde", ] +[[package]] +name = "parking" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" + [[package]] name = "parking_lot" version = "0.7.1" @@ -2181,6 +2382,17 @@ dependencies = [ "parking_lot_core 0.7.2", ] +[[package]] +name = "parking_lot" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733" +dependencies = [ + "instant", + "lock_api 0.4.1", + "parking_lot_core 0.8.0", +] + [[package]] name = "parking_lot_core" version = "0.4.0" @@ -2191,7 +2403,7 @@ dependencies = [ "rand 0.6.5", "rustc_version 0.2.3", "smallvec 0.6.13", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -2201,12 +2413,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" dependencies = [ "cfg-if", - "cloudabi", + "cloudabi 0.0.3", "libc", "redox_syscall", "rustc_version 0.2.3", "smallvec 0.6.13", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -2216,18 +2428,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" dependencies = [ "cfg-if", - "cloudabi", + "cloudabi 0.0.3", + "libc", + "redox_syscall", + "smallvec 1.4.2", + "winapi 0.3.9", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" +dependencies = [ + "cfg-if", + "cloudabi 0.1.0", + "instant", "libc", "redox_syscall", - "smallvec 1.4.0", - "winapi 0.3.8", + "smallvec 1.4.2", + "winapi 0.3.9", ] [[package]] name = "parse-zoneinfo" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feece9d0113b400182a7d00adcff81ccf29158c49c5abd11e2eed8589bf6ff07" +checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" dependencies = [ "regex", ] @@ -2244,10 +2471,49 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +[[package]] +name = "phf" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" +dependencies = [ + "phf_shared", + "rand 0.6.5", +] + +[[package]] +name = "phf_shared" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" +dependencies = [ + "siphasher", + "unicase 1.4.2", +] + [[package]] name = "philipshue" version = "0.3.2" -source = "git+https://github.com/dskleingeld/philipshue#68eeaf2f006accaaa2cf289a992e347a92b5b013" +source = "git+https://github.com/dskleingeld/philipshue#c52c7fa306a78c3432f5619bb4de75ccd55fb19f" dependencies = [ "error-chain 0.11.0", "reqwest 0.9.24", @@ -2258,29 +2524,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "0.4.17" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc93aeee735e60ecb40cf740eb319ff23eab1c5748abfdb5c180e4ce49f7791" +checksum = "f48fad7cfbff853437be7cf54d7b993af21f53be7f0988cbfe4a51535aa77205" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "0.4.17" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e58db2081ba5b4c93bd6be09c40fd36cb9193a8336c384f3b40012e531aa7e40" +checksum = "24c6d293bdd3ca5a1697997854c6cf7855e43fb6a0ba1c47af57a5bcafd158ae" dependencies = [ - "proc-macro2 1.0.17", - "quote 1.0.6", - "syn 1.0.29", + "proc-macro2 1.0.23", + "quote 1.0.7", + "syn 1.0.42", ] [[package]] name = "pin-project-lite" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7505eeebd78492e0f6108f7171c4948dbb120ee8119d9d77d0afa5469bef67f" +checksum = "71f349a4f0e70676ffb2dbafe16d0c992382d02f0a952e3ddf584fc289dac6b3" [[package]] name = "pin-utils" @@ -2289,66 +2555,59 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "piper" -version = "0.1.2" +name = "polling" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b0deb65f46e873ba8aa7c6a8dbe3f23cb1bf59c339a81a1d56361dde4d66ac8" +checksum = "e0720e0b9ea9d52451cf29d3413ba8a9303f8815d9d9653ef70e03ff73e65566" dependencies = [ - "crossbeam-utils 0.7.2", - "futures-io", - "futures-sink", - "futures-util", + "cfg-if", + "libc", + "log 0.4.11", + "wepoll-sys-stjepang", + "winapi 0.3.9", ] -[[package]] -name = "pkg-config" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" - [[package]] name = "ppv-lite86" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" +checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" [[package]] name = "proc-macro-error" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.17", - "quote 1.0.6", - "syn 1.0.29", + "proc-macro2 1.0.23", + "quote 1.0.7", + "syn 1.0.42", "version_check 0.9.2", ] [[package]] name = "proc-macro-error-attr" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.17", - "quote 1.0.6", - "syn 1.0.29", - "syn-mid", + "proc-macro2 1.0.23", + "quote 1.0.7", "version_check 0.9.2", ] [[package]] name = "proc-macro-hack" -version = "0.5.16" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4" +checksum = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598" [[package]] name = "proc-macro-nested" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" +checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a" [[package]] name = "proc-macro2" @@ -2361,11 +2620,11 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.17" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101" +checksum = "51ef7cd2518ead700af67bf9d1a658d90b6037d77110fd9c0445429d0ba1c6c9" dependencies = [ - "unicode-xid 0.2.0", + "unicode-xid 0.2.1", ] [[package]] @@ -2374,7 +2633,7 @@ version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bbaa49075179162b49acac1c6aa45fb4dafb5f13cf6794276d77bc7fd95757b" dependencies = [ - "error-chain 0.12.2", + "error-chain 0.12.4", "idna 0.2.0", "lazy_static", "regex", @@ -2398,11 +2657,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ - "proc-macro2 1.0.17", + "proc-macro2 1.0.23", ] [[package]] @@ -2411,11 +2670,11 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" dependencies = [ - "cloudabi", + "cloudabi 0.0.3", "fuchsia-cprng", "libc", "rand_core 0.3.1", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -2434,7 +2693,7 @@ dependencies = [ "rand_os", "rand_pcg", "rand_xorshift", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -2529,7 +2788,7 @@ checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" dependencies = [ "libc", "rand_core 0.4.2", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -2538,12 +2797,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" dependencies = [ - "cloudabi", + "cloudabi 0.0.3", "fuchsia-cprng", "libc", "rand_core 0.4.2", "rdrand", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -2567,10 +2826,11 @@ dependencies = [ [[package]] name = "rayon" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" +checksum = "cfd016f0c045ad38b5251be2c9c0ab806917f82da4d36b2a327e5166adad9270" dependencies = [ + "autocfg 1.0.1", "crossbeam-deque", "either", "rayon-core", @@ -2578,12 +2838,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" +checksum = "e8c4fec834fb6e6d2dd5eece3c7b432a52f0ba887cf40e595190c4107edc08bf" dependencies = [ + "crossbeam-channel 0.4.4", "crossbeam-deque", - "crossbeam-queue", "crossbeam-utils 0.7.2", "lazy_static", "num_cpus", @@ -2600,15 +2860,15 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.56" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_users" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431" +checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" dependencies = [ "getrandom", "redox_syscall", @@ -2635,11 +2895,11 @@ checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" [[package]] name = "remove_dir_all" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -2657,13 +2917,11 @@ dependencies = [ "futures 0.1.29", "http 0.1.21", "hyper 0.12.35", - "hyper-rustls", - "hyper-tls 0.3.2", - "log", - "mime", - "mime_guess", - "native-tls", - "rustls", + "hyper-rustls 0.17.1", + "log 0.4.11", + "mime 0.3.16", + "mime_guess 2.0.3", + "rustls 0.16.0", "serde", "serde_json", "serde_urlencoded 0.5.5", @@ -2676,41 +2934,43 @@ dependencies = [ "tokio-timer", "url 1.7.2", "uuid", - "webpki-roots", + "webpki-roots 0.17.0", "winreg 0.6.2", ] [[package]] name = "reqwest" -version = "0.10.6" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b82c9238b305f26f53443e3a4bc8528d64b8d0bee408ec949eb7bf5635ec680" +checksum = "e9eaa17ac5d7b838b7503d118fa16ad88f440498bf9ffe5424e621f93190d61e" dependencies = [ - "base64 0.12.1", - "bytes 0.5.4", + "base64 0.12.3", + "bytes 0.5.6", "encoding_rs", "futures-core", "futures-util", "http 0.2.1", "http-body 0.3.1", - "hyper 0.13.6", - "hyper-tls 0.4.1", + "hyper 0.13.8", + "hyper-rustls 0.21.0", + "ipnet", "js-sys", "lazy_static", - "log", - "mime", - "mime_guess", - "native-tls", + "log 0.4.11", + "mime 0.3.16", + "mime_guess 2.0.3", "percent-encoding 2.1.0", "pin-project-lite", + "rustls 0.18.1", "serde", "serde_urlencoded 0.6.1", - "tokio 0.2.21", - "tokio-tls", + "tokio 0.2.22", + "tokio-rustls 0.14.1", "url 2.1.1", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots 0.19.0", "winreg 0.7.0", ] @@ -2735,9 +2995,9 @@ dependencies = [ [[package]] name = "ring" -version = "0.16.14" +version = "0.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06b3fefa4f12272808f809a0af618501fdaba41a58963c5fb72238ab0be09603" +checksum = "952cd6b98c85bbc30efa1ba5783b8abf12fec8b3287ffa52605b9432313e34e4" dependencies = [ "cc", "libc", @@ -2745,16 +3005,16 @@ dependencies = [ "spin", "untrusted", "web-sys", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] name = "rust-argon2" -version = "0.7.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" +checksum = "9dab61250775933275e84053ac235621dfb739556d5c54a2f2e9313b7cf43a19" dependencies = [ - "base64 0.11.0", + "base64 0.12.3", "blake2b_simd", "constant_time_eq", "crossbeam-utils 0.7.2", @@ -2797,39 +3057,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" dependencies = [ "base64 0.10.1", - "log", + "log 0.4.11", "ring", "sct", "webpki", ] [[package]] -name = "ryu" -version = "1.0.4" +name = "rustls" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" +checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81" +dependencies = [ + "base64 0.12.3", + "log 0.4.11", + "ring", + "sct", + "webpki", +] [[package]] -name = "schannel" -version = "0.1.19" +name = "rustls-native-certs" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +checksum = "51ffebdbb48c14f84eba0b715197d673aff1dd22cc1007ca647e28483bbcc307" dependencies = [ - "lazy_static", - "winapi 0.3.8", + "openssl-probe", + "rustls 0.16.0", + "schannel", + "security-framework", ] [[package]] -name = "scoped-tls" -version = "0.1.2" +name = "ryu" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] -name = "scoped-tls-hkt" -version = "0.1.2" +name = "schannel" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e9d7eaddb227e8fbaaa71136ae0e1e913ca159b86c7da82f3e8f0044ad3a63" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +dependencies = [ + "lazy_static", + "winapi 0.3.9", +] [[package]] name = "scopeguard" @@ -2855,11 +3128,10 @@ dependencies = [ [[package]] name = "security-framework" -version = "0.4.4" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535" +checksum = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df" dependencies = [ - "bitflags 1.2.1", "core-foundation", "core-foundation-sys", "libc", @@ -2868,12 +3140,11 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "0.4.3" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405" +checksum = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" dependencies = [ "core-foundation-sys", - "libc", ] [[package]] @@ -2897,17 +3168,11 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -[[package]] -name = "send_wrapper" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" - [[package]] name = "serde" -version = "1.0.111" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d" +checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5" dependencies = [ "serde_derive", ] @@ -2924,20 +3189,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.111" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250" +checksum = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8" dependencies = [ - "proc-macro2 1.0.17", - "quote 1.0.6", - "syn 1.0.29", + "proc-macro2 1.0.23", + "quote 1.0.7", + "syn 1.0.42", ] [[package]] name = "serde_json" -version = "1.0.53" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2" +checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c" dependencies = [ "itoa", "ryu", @@ -2970,9 +3235,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.8.12" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16c7a592a1ec97c9c1c68d75b6e537dcbf60c7618e038e7841e00af1d9ccf0c4" +checksum = "ae3e2dd40a7cdc18ca80db804b7f461a39bb721160a85c9a1fa30134bf3c02a5" dependencies = [ "dtoa", "linked-hash-map", @@ -2988,14 +3253,20 @@ checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" [[package]] name = "signal-hook-registry" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41" +checksum = "a3e12110bc539e657a646068aaf5eb5b63af9d0c1f7b29c97113fad80e15f035" dependencies = [ "arc-swap", "libc", ] +[[package]] +name = "siphasher" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" + [[package]] name = "slab" version = "0.4.2" @@ -3014,7 +3285,7 @@ dependencies = [ "fs2", "fxhash", "libc", - "log", + "log 0.4.11", "parking_lot 0.10.2", ] @@ -3029,39 +3300,20 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" - -[[package]] -name = "smol" -version = "0.1.10" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686c634ad1873fffef6aed20f180eede424fbf3bb31802394c90fd7335a661b7" -dependencies = [ - "async-task", - "crossbeam", - "futures-io", - "futures-util", - "nix 0.17.0", - "once_cell", - "piper", - "scoped-tls-hkt", - "slab", - "socket2", - "wepoll-binding", -] +checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252" [[package]] name = "socket2" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" +checksum = "b1fa70dc5c8104ec096f4fe7ede7a221d35ae13dcd19ba1ad9a81d2cab9a1c44" dependencies = [ "cfg-if", "libc", "redox_syscall", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -3083,9 +3335,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "stable_deref_trait" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "string" @@ -3104,9 +3356,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.14" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef" +checksum = "a33f6461027d7f08a13715659b2948e1602c31a3756aeae9378bfe7518c72e82" dependencies = [ "clap", "lazy_static", @@ -3115,15 +3367,15 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.7" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a" +checksum = "c92e775028122a4b3dd55d58f14fc5120289c69bee99df1d117ae30f84b225c9" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.17", - "quote 1.0.6", - "syn 1.0.29", + "proc-macro2 1.0.23", + "quote 1.0.7", + "syn 1.0.42", ] [[package]] @@ -3139,36 +3391,25 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb37da98a55b1d08529362d9cbb863be17556873df2585904ab9d2bc951291d0" -dependencies = [ - "proc-macro2 1.0.17", - "quote 1.0.6", - "unicode-xid 0.2.0", -] - -[[package]] -name = "syn-mid" -version = "0.5.0" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" +checksum = "9c51d92969d209b54a98397e1b91c8ae82d8c87a7bb87df0b29aa2ad81454228" dependencies = [ - "proc-macro2 1.0.17", - "quote 1.0.6", - "syn 1.0.29", + "proc-macro2 1.0.23", + "quote 1.0.7", + "unicode-xid 0.2.1", ] [[package]] name = "synstructure" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" +checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ - "proc-macro2 1.0.17", - "quote 1.0.6", - "syn 1.0.29", - "unicode-xid 0.2.0", + "proc-macro2 1.0.23", + "quote 1.0.7", + "syn 1.0.42", + "unicode-xid 0.2.1", ] [[package]] @@ -3182,26 +3423,28 @@ dependencies = [ [[package]] name = "telegram-bot" -version = "0.6.3" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d5eca220fcf23ad25b269991cdc8f8d421d97634c7f9e10b4c5dcdaa913b6" +checksum = "bb29fb11ef40c839c1c6b4e9c2ec4f357f9f674491e9df5a8c94f8cc2005f860" dependencies = [ - "antidote", - "error-chain 0.11.0", - "futures 0.1.29", - "hyper 0.12.35", - "hyper-tls 0.3.2", + "bytes 0.5.6", + "futures 0.3.5", + "hyper 0.13.8", + "hyper-rustls 0.19.1", + "multipart", "telegram-bot-raw", - "tokio-core", + "tokio 0.2.22", + "tracing", + "tracing-futures", ] [[package]] name = "telegram-bot-raw" -version = "0.6.3" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65578f718dadd17347cd60d45609a7e1d57a52b459797957002b922349ee9744" +checksum = "add65834bee405351f092b18a4647cae05d1c40699570054eadc6d4035d9692c" dependencies = [ - "error-chain 0.11.0", + "bytes 0.5.6", "serde", "serde-value", "serde_derive", @@ -3219,7 +3462,7 @@ dependencies = [ "rand 0.7.3", "redox_syscall", "remove_dir_all", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -3251,14 +3494,21 @@ dependencies = [ [[package]] name = "time" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", - "winapi 0.3.8", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi 0.3.9", ] +[[package]] +name = "tinyvec" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" + [[package]] name = "tokio" version = "0.1.22" @@ -3285,11 +3535,11 @@ dependencies = [ [[package]] name = "tokio" -version = "0.2.21" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d099fa27b9702bed751524694adbe393e18b36b204da91eb1cbbbbb4a5ee2d58" +checksum = "5d34ca54d84bf2b5b4d7d31e901a8464f7b60ac145a284fba25ceb801f2ddccd" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.6", "fnv", "futures-core", "iovec", @@ -3301,7 +3551,7 @@ dependencies = [ "pin-project-lite", "signal-hook-registry", "slab", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -3326,25 +3576,6 @@ dependencies = [ "tokio-io", ] -[[package]] -name = "tokio-core" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.29", - "iovec", - "log", - "mio", - "scoped-tls", - "tokio 0.1.22", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "tokio-timer", -] - [[package]] name = "tokio-current-thread" version = "0.1.7" @@ -3384,7 +3615,7 @@ checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" dependencies = [ "bytes 0.4.12", "futures 0.1.29", - "log", + "log 0.4.11", ] [[package]] @@ -3396,7 +3627,7 @@ dependencies = [ "crossbeam-utils 0.7.2", "futures 0.1.29", "lazy_static", - "log", + "log 0.4.11", "mio", "num_cpus", "parking_lot 0.9.0", @@ -3415,7 +3646,7 @@ dependencies = [ "bytes 0.4.12", "futures 0.1.29", "iovec", - "rustls", + "rustls 0.16.0", "tokio-io", "webpki", ] @@ -3427,8 +3658,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3068d891551949b37681724d6b73666787cc63fa8e255c812a41d2513aff9775" dependencies = [ "futures-core", - "rustls", - "tokio 0.2.21", + "rustls 0.16.0", + "tokio 0.2.22", + "webpki", +] + +[[package]] +name = "tokio-rustls" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12831b255bcfa39dc0436b01e19fea231a37db570686c06ee72c423479f889a" +dependencies = [ + "futures-core", + "rustls 0.18.1", + "tokio 0.2.22", "webpki", ] @@ -3446,7 +3689,7 @@ dependencies = [ "tokio-executor", "tokio-io", "tokio-reactor", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -3484,7 +3727,7 @@ dependencies = [ "crossbeam-utils 0.7.2", "futures 0.1.29", "lazy_static", - "log", + "log 0.4.11", "num_cpus", "slab", "tokio-executor", @@ -3502,16 +3745,6 @@ dependencies = [ "tokio-executor", ] -[[package]] -name = "tokio-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a70f4fcd7b3b24fb194f837560168208f669ca8cb70d0c4b862944452396343" -dependencies = [ - "native-tls", - "tokio 0.2.21", -] - [[package]] name = "tokio-udp" version = "0.1.6" @@ -3520,7 +3753,7 @@ checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" dependencies = [ "bytes 0.4.12", "futures 0.1.29", - "log", + "log 0.4.11", "mio", "tokio-codec", "tokio-io", @@ -3529,15 +3762,15 @@ dependencies = [ [[package]] name = "tokio-uds" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5076db410d6fdc6523df7595447629099a1fdc47b3d9f896220780fa48faf798" +checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0" dependencies = [ "bytes 0.4.12", "futures 0.1.29", "iovec", "libc", - "log", + "log 0.4.11", "mio", "mio-uds", "tokio-codec", @@ -3551,12 +3784,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.6", "futures-core", "futures-sink", - "log", + "log 0.4.11", "pin-project-lite", - "tokio 0.2.21", + "tokio 0.2.22", ] [[package]] @@ -3565,12 +3798,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.6", "futures-core", "futures-sink", - "log", + "log 0.4.11", "pin-project-lite", - "tokio 0.2.21", + "tokio 0.2.22", ] [[package]] @@ -3588,6 +3821,49 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" +[[package]] +name = "tracing" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0987850db3733619253fe60e17cb59b82d37c7e6c0236bb81e4d6b87c879f27" +dependencies = [ + "cfg-if", + "log 0.4.11", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada" +dependencies = [ + "proc-macro2 1.0.23", + "quote 1.0.7", + "syn 1.0.42", +] + +[[package]] +name = "tracing-core" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "tracing-futures" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c" +dependencies = [ + "pin-project", + "tracing", +] + [[package]] name = "trust-dns-proto" version = "0.5.0" @@ -3599,7 +3875,7 @@ dependencies = [ "futures 0.1.29", "idna 0.1.5", "lazy_static", - "log", + "log 0.4.11", "rand 0.5.6", "smallvec 0.6.13", "socket2", @@ -3623,7 +3899,7 @@ dependencies = [ "futures 0.1.29", "idna 0.1.5", "lazy_static", - "log", + "log 0.4.11", "rand 0.5.6", "smallvec 0.6.13", "socket2", @@ -3648,11 +3924,11 @@ dependencies = [ "futures 0.3.5", "idna 0.2.0", "lazy_static", - "log", + "log 0.4.11", "rand 0.7.3", - "smallvec 1.4.0", + "smallvec 1.4.2", "socket2", - "tokio 0.2.21", + "tokio 0.2.22", "url 2.1.1", ] @@ -3667,7 +3943,7 @@ dependencies = [ "futures 0.1.29", "ipconfig 0.1.9", "lazy_static", - "log", + "log 0.4.11", "lru-cache", "resolv-conf", "smallvec 0.6.13", @@ -3686,19 +3962,19 @@ dependencies = [ "futures 0.3.5", "ipconfig 0.2.2", "lazy_static", - "log", + "log 0.4.11", "lru-cache", "resolv-conf", - "smallvec 1.4.0", - "tokio 0.2.21", + "smallvec 1.4.2", + "tokio 0.2.22", "trust-dns-proto 0.18.0-alpha.2", ] [[package]] name = "try-lock" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "try_from" @@ -3709,6 +3985,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "unicase" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +dependencies = [ + "version_check 0.1.5", +] + [[package]] name = "unicase" version = "2.6.0" @@ -3729,11 +4014,11 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" +checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977" dependencies = [ - "smallvec 1.4.0", + "tinyvec", ] [[package]] @@ -3744,9 +4029,9 @@ checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" [[package]] name = "unicode-width" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" [[package]] name = "unicode-xid" @@ -3756,9 +4041,9 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "untrusted" @@ -3813,9 +4098,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae" dependencies = [ "nom", - "proc-macro2 1.0.17", - "quote 1.0.6", - "syn 1.0.29", + "proc-macro2 1.0.23", + "quote 1.0.7", + "syn 1.0.42", ] [[package]] @@ -3829,10 +4114,10 @@ dependencies = [ ] [[package]] -name = "vcpkg" -version = "0.2.8" +name = "vec-arena" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" +checksum = "eafc1b9b2dfc6f5529177b62cf806484db55b32dc7c9658a118e11bbeb33061d" [[package]] name = "vec_map" @@ -3858,6 +4143,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + [[package]] name = "want" version = "0.2.0" @@ -3865,7 +4156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" dependencies = [ "futures 0.1.29", - "log", + "log 0.4.11", "try-lock", ] @@ -3875,7 +4166,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" dependencies = [ - "log", + "log 0.4.11", "try-lock", ] @@ -3885,11 +4176,17 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wasm-bindgen" -version = "0.2.63" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2dc4aa152834bc334f506c1a06b866416a8b6697d5c9f75b9a689c8486def0" +checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" dependencies = [ "cfg-if", "serde", @@ -3899,24 +4196,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.63" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded84f06e0ed21499f6184df0e0cb3494727b0c5da89534e0fcc55c51d812101" +checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68" dependencies = [ "bumpalo", "lazy_static", - "log", - "proc-macro2 1.0.17", - "quote 1.0.6", - "syn 1.0.29", + "log 0.4.11", + "proc-macro2 1.0.23", + "quote 1.0.7", + "syn 1.0.42", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.13" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64487204d863f109eb77e8462189d111f27cb5712cc9fdb3461297a76963a2f6" +checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da" dependencies = [ "cfg-if", "js-sys", @@ -3926,38 +4223,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.63" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "838e423688dac18d73e31edce74ddfac468e37b1506ad163ffaf0a46f703ffe3" +checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" dependencies = [ - "quote 1.0.6", + "quote 1.0.7", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.63" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3156052d8ec77142051a533cdd686cba889537b213f948cd1d20869926e68e92" +checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" dependencies = [ - "proc-macro2 1.0.17", - "quote 1.0.6", - "syn 1.0.29", + "proc-macro2 1.0.23", + "quote 1.0.7", + "syn 1.0.42", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.63" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9ba19973a58daf4db6f352eda73dc0e289493cd29fb2632eb172085b6521acd" +checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" [[package]] name = "web-sys" -version = "0.3.40" +version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b72fe77fd39e4bd3eaa4412fd299a0be6b3dfe9d2597e2f1c20beb968f41d17" +checksum = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d" dependencies = [ "js-sys", "wasm-bindgen", @@ -3983,20 +4280,19 @@ dependencies = [ ] [[package]] -name = "wepoll-binding" -version = "2.0.2" +name = "webpki-roots" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374fff4ff9701ff8b6ad0d14bacd3156c44063632d8c136186ff5967d48999a7" +checksum = "f8eff4b7516a57307f9349c64bf34caa34b940b66fed4b2fb3136cb7386e5739" dependencies = [ - "bitflags 1.2.1", - "wepoll-sys", + "webpki", ] [[package]] -name = "wepoll-sys" -version = "2.0.0" +name = "wepoll-sys-stjepang" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9082a777aed991f6769e2b654aa0cb29f1c3d615daf009829b07b66c7aff6a24" +checksum = "1fdfbb03f290ca0b27922e8d48a0997b4ceea12df33269b9f75e713311eb178d" dependencies = [ "cc", ] @@ -4009,9 +4305,9 @@ checksum = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" [[package]] name = "widestring" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6" +checksum = "a763e303c0e0f23b0da40888724762e802a8ffefbc22de4127ef42493c2ea68c" [[package]] name = "winapi" @@ -4021,9 +4317,9 @@ checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", @@ -4053,7 +4349,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a27a759395c1195c4cc5cda607ef6f8f6498f64e78f7900f5de0a127a424704a" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -4062,7 +4358,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -4071,7 +4367,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -4086,9 +4382,9 @@ dependencies = [ [[package]] name = "yaml-rust" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" +checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d" dependencies = [ "linked-hash-map", ] diff --git a/Cargo.toml b/Cargo.toml index d37d531e..fa5bbf2c 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,14 +61,14 @@ crossbeam-channel = "0.3" sled = "0.30" pagecache = "0.17" -reqwest = {version = "0.10"} +reqwest = {version = "0.10", default-features = false, features = ["rustls-tls"]} mpd = "0.0.12" dirs = "2" rand = "0.6" retry = "0.5" -telegram-bot = "0.6.3" +telegram-bot = {version = "0.7", default-features = false, features = ["rustls"]} serde_json = "1.0" regex = "1" -#id3 = "0.5.0" \ No newline at end of file +#id3 = "0.5.0" diff --git a/src/controller/commands.rs b/src/controller/commands.rs index e7bb36c9..b251efe1 100755 --- a/src/controller/commands.rs +++ b/src/controller/commands.rs @@ -50,8 +50,13 @@ pub fn handle_cmd(cmd: Command, mods: &mut Modifications, sys: &mut System) -> O Command::GoToWindows => println!("should go to windows"), Command::MpdPause => {mpd_control::toggle_playback(&mut sys.mpd).unwrap(); mods.mpd = true }, - Command::MpdDecreaseVolume => {mpd_control::increase_volume(&mut sys.mpd).unwrap(); mods.mpd = true }, - Command::MpdIncreaseVolume => {mpd_control::decrease_volume(&mut sys.mpd).unwrap(); mods.mpd = true }, + Command::MpdDecreaseVolume => {mpd_control::decrease_volume(&mut sys.mpd).unwrap(); mods.mpd = true }, + Command::MpdIncreaseVolume => { + if sys.mpd.is_playing() { + mpd_control::increase_volume(&mut sys.mpd).unwrap(); + mods.mpd = true + } + }, Command::MpdNextSong => {mpd_control::next_song().unwrap()}, Command::MpdPrevSong => {mpd_control::prev_song().unwrap()}, diff --git a/src/input/bot/mod.rs b/src/input/bot/mod.rs index 16118514..50c97a52 100644 --- a/src/input/bot/mod.rs +++ b/src/input/bot/mod.rs @@ -104,14 +104,19 @@ async fn handle_callback(callback: CallbackQuery, state: &State) { return; //no need for error handling, just drop callback } - let header = callback.data.split_terminator(":").next(); + if callback.data.is_none() { + debug!("no data in callback"); + return; //not allowed, drop callback + } + let data = callback.data.as_ref().unwrap(); + let header = data.split_terminator(":").next(); let res = match header { Some("ytdl") => { - youtube_dl::handle_callback(callback, state).await + youtube_dl::handle_callback(data, state).await } _ => { warn!("unhandled callback, data: {}\nfull_callback: {:?}", - callback.data, callback); + data, callback); Ok(()) //user need not be warned as user is dev }, }; @@ -225,4 +230,4 @@ pub async fn set_webhook(domain: &str, token: &str, port: u16) -> Result<(), Err info!("set webhook to: {}", webhook_url); Ok(()) } -} \ No newline at end of file +} diff --git a/src/input/bot/youtube_dl.rs b/src/input/bot/youtube_dl.rs index 0d1aa6a1..0df97177 100644 --- a/src/input/bot/youtube_dl.rs +++ b/src/input/bot/youtube_dl.rs @@ -110,10 +110,10 @@ impl From for Error { } } -pub async fn handle_callback(callback: CallbackQuery, state: &State) +pub async fn handle_callback(callback_data: &str, state: &State) -> Result<(), Error> { - let mut split = callback.data.split_terminator(":").skip(1); + let mut split = callback_data.split_terminator(":").skip(1); let command = split.next(); match command { Some("swap") => { @@ -135,4 +135,4 @@ pub async fn handle_callback(callback: CallbackQuery, state: &State) }, } Ok(()) -} \ No newline at end of file +} From c2fdf4a21496930669ed74480b50646400294932 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:13:47 +0200 Subject: [PATCH 052/687] bugfix --- src/controller/commands.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controller/commands.rs b/src/controller/commands.rs index b251efe1..8e2a9953 100755 --- a/src/controller/commands.rs +++ b/src/controller/commands.rs @@ -52,7 +52,7 @@ pub fn handle_cmd(cmd: Command, mods: &mut Modifications, sys: &mut System) -> O Command::MpdPause => {mpd_control::toggle_playback(&mut sys.mpd).unwrap(); mods.mpd = true }, Command::MpdDecreaseVolume => {mpd_control::decrease_volume(&mut sys.mpd).unwrap(); mods.mpd = true }, Command::MpdIncreaseVolume => { - if sys.mpd.is_playing() { + if let mpd::State::Play = sys.mpd.is_playing() { mpd_control::increase_volume(&mut sys.mpd).unwrap(); mods.mpd = true } From 1036493f96b79712f1ae153186bfd734f9b8402c Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Sun, 11 Oct 2020 02:26:03 +0200 Subject: [PATCH 053/687] moved Sensorvalue to external crate --- Cargo.lock | 320 ++++++++++++++++-------------- Cargo.toml | 1 + src/controller/environment/mod.rs | 17 +- src/controller/mod.rs | 100 +++++----- src/input/mod.rs | 1 - src/input/web_api/mod.rs | 1 - src/input/web_api/sensors.rs | 59 ------ src/input/web_api/server/mod.rs | 28 ++- 8 files changed, 257 insertions(+), 270 deletions(-) delete mode 100644 src/input/web_api/sensors.rs diff --git a/Cargo.lock b/Cargo.lock index 07d5ccb3..8dd3fe1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,7 +22,7 @@ dependencies = [ "crossbeam-channel 0.3.9", "dirs", "fern", - "futures 0.3.5", + "futures 0.3.6", "gpio-cdev", "hex", "linux-embedded-hal", @@ -38,6 +38,7 @@ dependencies = [ "retry", "ring", "rustls 0.16.0", + "sensor_value", "serde", "serde_json", "serde_yaml", @@ -59,7 +60,7 @@ dependencies = [ "crossbeam-channel 0.3.9", "failure", "fnv", - "futures 0.1.29", + "futures 0.1.30", "libc", "log 0.4.11", "parking_lot 0.7.1", @@ -120,7 +121,7 @@ dependencies = [ "actix-utils 1.0.6", "derive_more", "either", - "futures 0.3.5", + "futures 0.3.6", "http 0.2.1", "log 0.4.11", "rustls 0.16.0", @@ -208,7 +209,7 @@ checksum = "2a379b0639c293292d71defb8cc1f94c87b7705c904adf044338ad392df77c7a" dependencies = [ "actix-service", "actix-web", - "futures 0.3.5", + "futures 0.3.6", "serde", "serde_json", "time", @@ -221,7 +222,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a60f9ba7c4e6df97f3aacb14bb5c0cd7d98a49dcbaed0d7f292912ad9a6a3ed2" dependencies = [ "quote 1.0.7", - "syn 1.0.42", + "syn 1.0.44", ] [[package]] @@ -232,7 +233,7 @@ checksum = "8bebfbe6629e0131730746718c9e032b58f02c6ce06ed7c982b9fef6c8545acd" dependencies = [ "actix", "bytes 0.4.12", - "futures 0.1.29", + "futures 0.1.30", "log 0.4.11", "mio", "net2", @@ -348,7 +349,7 @@ dependencies = [ "actix-utils 1.0.6", "derive_more", "either", - "futures 0.3.5", + "futures 0.3.6", "log 0.4.11", "rustls 0.16.0", "tokio-rustls 0.12.3", @@ -368,7 +369,7 @@ dependencies = [ "bitflags 1.2.1", "bytes 0.5.6", "either", - "futures 0.3.5", + "futures 0.3.6", "log 0.4.11", "pin-project", "slab", @@ -416,7 +417,7 @@ dependencies = [ "bytes 0.5.6", "derive_more", "encoding_rs", - "futures 0.3.5", + "futures 0.3.6", "fxhash", "log 0.4.11", "mime 0.3.16", @@ -437,9 +438,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a71bf475cbe07281d0b3696abb48212db118e7e23219f13596ce865235ff5766" dependencies = [ - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.42", + "syn 1.0.44", ] [[package]] @@ -528,9 +529,9 @@ checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" [[package]] name = "async-channel" -version = "1.4.2" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21279cfaa4f47df10b1816007e738ca3747ef2ee53ffc51cdbf57a8bb266fee3" +checksum = "59740d83946db6a5af71ae25ddf9562c2b176b2ca42cf99a455f09f4a220d6b9" dependencies = [ "concurrent-queue", "event-listener", @@ -566,13 +567,14 @@ dependencies = [ [[package]] name = "async-io" -version = "1.1.4" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33be191d05a54ec120e4667375e2ad49fe506b846463df384460ab801c7ae5dc" +checksum = "d54bc4c1c7292475efb2253227dbcfad8fe1ca4c02bc62c510cc2f3da5c4704e" dependencies = [ "concurrent-queue", "fastrand", "futures-lite", + "libc", "log 0.4.11", "nb-connect", "once_cell", @@ -580,6 +582,7 @@ dependencies = [ "polling", "vec-arena", "waker-fn", + "winapi 0.3.9", ] [[package]] @@ -626,13 +629,13 @@ checksum = "8ab27c1aa62945039e44edaeee1dc23c74cc0c303dd5fe0fb462a184f1c3a518" [[package]] name = "async-trait" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "687c230d85c0a52504709705fc8a53e4a692b83a2184f03dae73e38e1e93a783" +checksum = "b246867b8b3b6ae56035f1eb1ed557c1d8eae97f0d53696138a50fa0e3a3b8c0" dependencies = [ - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.42", + "syn 1.0.44", ] [[package]] @@ -690,9 +693,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.50" +version = "0.3.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46254cf2fdcdf1badb5934448c1bcbe046a56537b3987d96c51a7afc5d03f293" +checksum = "f813291114c186a042350e787af10c26534601062603d888be110f59f85ef8fa" dependencies = [ "addr2line", "cfg-if", @@ -764,16 +767,16 @@ dependencies = [ [[package]] name = "blocking" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2640778f8053e72c11f621b0a5175a0560a269282aa98ed85107773ab8e2a556" +checksum = "c5e170dbede1f740736619b776d7251cb1b9095c435c34d8ca9f57fcd2f335e9" dependencies = [ "async-channel", + "async-task", "atomic-waker", "fastrand", "futures-lite", "once_cell", - "waker-fn", ] [[package]] @@ -866,9 +869,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c" +checksum = "ed67cbde08356238e75fc4656be4749481eeffb09e19f320a25237d5221c985d" [[package]] name = "cfg-if" @@ -878,9 +881,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "chrono" -version = "0.4.18" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d021fddb7bd3e734370acfa4a83f34095571d8570c039f1420d77540f68d5772" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ "libc", "num-integer", @@ -1120,13 +1123,13 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.10" +version = "0.99.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dcfabdab475c16a93d669dddfc393027803e347d09663f524447f642fbb84ba" +checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c" dependencies = [ - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.42", + "syn 1.0.44", ] [[package]] @@ -1188,9 +1191,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595" dependencies = [ "heck", - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.42", + "syn 1.0.44", ] [[package]] @@ -1242,17 +1245,20 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.42", + "syn 1.0.44", "synstructure", ] [[package]] name = "fastrand" -version = "1.3.5" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c85295147490b8fcf2ea3d104080a105a8b2c63f9c319e82c02d8e952388919" +checksum = "ca5faf057445ce5c9d4329e382b2ce7ca38550ef3b73a5348362d5f24e0c7fe3" +dependencies = [ + "instant", +] [[package]] name = "fern" @@ -1267,9 +1273,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "766d0e77a2c1502169d4a93ff3b8c15a71fd946cd0126309752104e5f3c46d94" +checksum = "da80be589a72651dcda34d8b35bcdc9b7254ad06325611074d9cc0fbb19f60ee" dependencies = [ "cfg-if", "crc32fast", @@ -1317,15 +1323,15 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futures" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" +checksum = "4c7e4c2612746b0df8fed4ce0c69156021b704c9aefa360311c04e6e9e002eed" [[package]] name = "futures" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613" +checksum = "5d8e3078b7b2a8a671cb7a3d17b4760e4181ea243227776ba83fd043b4ca034e" dependencies = [ "futures-channel", "futures-core", @@ -1338,9 +1344,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5" +checksum = "a7a4d35f7401e948629c9c3d6638fb9bf94e0b2121e96c3b428cc4e631f3eb74" dependencies = [ "futures-core", "futures-sink", @@ -1348,9 +1354,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399" +checksum = "d674eaa0056896d5ada519900dbf97ead2e46a7b6621e8160d79e2f2e1e2784b" [[package]] name = "futures-cpupool" @@ -1358,15 +1364,15 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" dependencies = [ - "futures 0.1.29", + "futures 0.1.30", "num_cpus", ] [[package]] name = "futures-executor" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314" +checksum = "cc709ca1da6f66143b8c9bec8e6260181869893714e9b5a490b169b0414144ab" dependencies = [ "futures-core", "futures-task", @@ -1375,15 +1381,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789" +checksum = "5fc94b64bb39543b4e432f1790b6bf18e3ee3b74653c5449f63310e9a74b123c" [[package]] name = "futures-lite" -version = "1.8.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0db18c5f58083b54b0c416638ea73066722c2815c1e54dd8ba85ee3def593c3a" +checksum = "381a7ad57b1bad34693f63f6f377e1abded7a9c85c9d3eb6771e11c60aaadab9" dependencies = [ "fastrand", "futures-core", @@ -1396,36 +1402,36 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39" +checksum = "f57ed14da4603b2554682e9f2ff3c65d7567b53188db96cb71538217fc64581b" dependencies = [ "proc-macro-hack", - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.42", + "syn 1.0.44", ] [[package]] name = "futures-sink" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc" +checksum = "0d8764258ed64ebc5d9ed185cf86a95db5cac810269c5d20ececb32e0088abbd" [[package]] name = "futures-task" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626" +checksum = "4dd26820a9f3637f1302da8bceba3ff33adbe53464b54ca24d4e2d4f1db30f94" dependencies = [ "once_cell", ] [[package]] name = "futures-util" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6" +checksum = "8a894a0acddba51a2d49a6f4263b1e64b8c579ece8af50fa86503d52cd1eea34" dependencies = [ "futures-channel", "futures-core", @@ -1499,7 +1505,7 @@ dependencies = [ "byteorder", "bytes 0.4.12", "fnv", - "futures 0.1.29", + "futures 0.1.30", "http 0.1.21", "indexmap", "log 0.4.11", @@ -1553,9 +1559,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c30f6d0bc6b00693347368a67d41b58f2fb851215ff1da49e90fe2c5c667151" +checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" dependencies = [ "libc", ] @@ -1612,7 +1618,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" dependencies = [ "bytes 0.4.12", - "futures 0.1.29", + "futures 0.1.30", "http 0.1.21", "tokio-buf", ] @@ -1646,7 +1652,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" dependencies = [ "bytes 0.4.12", - "futures 0.1.29", + "futures 0.1.30", "futures-cpupool", "h2 0.1.26", "http 0.1.21", @@ -1701,7 +1707,7 @@ checksum = "719d85c7df4a7f309a77d145340a063ea929dcb2e025bae46a80345cffec2952" dependencies = [ "bytes 0.4.12", "ct-logs", - "futures 0.1.29", + "futures 0.1.30", "hyper 0.12.35", "rustls 0.16.0", "tokio-io", @@ -1825,7 +1831,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" dependencies = [ "socket2", - "widestring 0.4.2", + "widestring 0.4.3", "winapi 0.3.9", "winreg 0.6.2", ] @@ -1884,9 +1890,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.77" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" +checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743" [[package]] name = "linked-hash-map" @@ -2034,9 +2040,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c60c0dfe32c10b43a144bad8fc83538c52f58302c92300ea7ec7bf7b38d5a7b9" +checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" dependencies = [ "adler", "autocfg 1.0.1", @@ -2125,9 +2131,9 @@ checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" [[package]] name = "nb-connect" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e847c76b390f44529c2071ef06d0b52fbb4bdb04cc8987a5cfa63954c000abca" +checksum = "8123a81538e457d44b933a02faf885d3fe8408806b23fa700e8f01c6c3a98998" dependencies = [ "libc", "winapi 0.3.9", @@ -2334,7 +2340,7 @@ dependencies = [ "crossbeam-epoch 0.7.2", "crossbeam-utils 0.6.6", "fs2", - "futures 0.1.29", + "futures 0.1.30", "fxhash", "hashbrown 0.3.1", "historian", @@ -2524,29 +2530,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "0.4.24" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f48fad7cfbff853437be7cf54d7b993af21f53be7f0988cbfe4a51535aa77205" +checksum = "13fbdfd6bdee3dc9be46452f86af4a4072975899cf8592466668620bebfbcc17" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "0.4.24" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24c6d293bdd3ca5a1697997854c6cf7855e43fb6a0ba1c47af57a5bcafd158ae" +checksum = "c82fb1329f632c3552cf352d14427d57a511b1cf41db93b3a7d77906a82dcc8e" dependencies = [ - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.42", + "syn 1.0.44", ] [[package]] name = "pin-project-lite" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71f349a4f0e70676ffb2dbafe16d0c992382d02f0a952e3ddf584fc289dac6b3" +checksum = "e555d9e657502182ac97b539fb3dae8b79cda19e3e4f8ffb5e8de4f18df93c95" [[package]] name = "pin-utils" @@ -2556,14 +2562,14 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "polling" -version = "1.1.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0720e0b9ea9d52451cf29d3413ba8a9303f8815d9d9653ef70e03ff73e65566" +checksum = "ab773feb154f12c49ffcfd66ab8bdcf9a1843f950db48b0d8be9d4393783b058" dependencies = [ "cfg-if", "libc", "log 0.4.11", - "wepoll-sys-stjepang", + "wepoll-sys", "winapi 0.3.9", ] @@ -2580,9 +2586,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.42", + "syn 1.0.44", "version_check 0.9.2", ] @@ -2592,7 +2598,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", "quote 1.0.7", "version_check 0.9.2", ] @@ -2620,9 +2626,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51ef7cd2518ead700af67bf9d1a658d90b6037d77110fd9c0445429d0ba1c6c9" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" dependencies = [ "unicode-xid 0.2.1", ] @@ -2661,7 +2667,7 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", ] [[package]] @@ -2826,9 +2832,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfd016f0c045ad38b5251be2c9c0ab806917f82da4d36b2a327e5166adad9270" +checksum = "dcf6960dc9a5b4ee8d3e4c5787b4a112a8818e0290a42ff664ad60692fdf2032" dependencies = [ "autocfg 1.0.1", "crossbeam-deque", @@ -2914,7 +2920,7 @@ dependencies = [ "cookie_store", "encoding_rs", "flate2", - "futures 0.1.29", + "futures 0.1.30", "http 0.1.21", "hyper 0.12.35", "hyper-rustls 0.17.1", @@ -3022,9 +3028,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +checksum = "b2610b7f643d18c87dff3b489950269617e6601a51f1f05aa5daefee36f64f0b" [[package]] name = "rustc-serialize" @@ -3168,6 +3174,14 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "sensor_value" +version = "0.1.0" +source = "git+https://github.com/dskleingeld/sensor_central.git?branch=boolean-fields#cec0bceefb1af5d9e968b6904a03f6933225f9c2" +dependencies = [ + "serde", +] + [[package]] name = "serde" version = "1.0.116" @@ -3193,16 +3207,16 @@ version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8" dependencies = [ - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.42", + "syn 1.0.44", ] [[package]] name = "serde_json" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c" +checksum = "a230ea9107ca2220eea9d46de97eddcb04cd00e92d13dda78e478dd33fa82bd4" dependencies = [ "itoa", "ryu", @@ -3356,9 +3370,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33f6461027d7f08a13715659b2948e1602c31a3756aeae9378bfe7518c72e82" +checksum = "a7a7159e7d0dbcab6f9c980d7971ef50f3ff5753081461eeda120d5974a4ee95" dependencies = [ "clap", "lazy_static", @@ -3367,15 +3381,15 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92e775028122a4b3dd55d58f14fc5120289c69bee99df1d117ae30f84b225c9" +checksum = "8fc47de4dfba76248d1e9169ccff240eea2a4dc1e34e309b95b2393109b4b383" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.42", + "syn 1.0.44", ] [[package]] @@ -3391,11 +3405,11 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.42" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c51d92969d209b54a98397e1b91c8ae82d8c87a7bb87df0b29aa2ad81454228" +checksum = "e03e57e4fcbfe7749842d53e24ccb9aa12b7252dbe5e91d2acad31834c8b8fdd" dependencies = [ - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", "quote 1.0.7", "unicode-xid 0.2.1", ] @@ -3406,9 +3420,9 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.42", + "syn 1.0.44", "unicode-xid 0.2.1", ] @@ -3428,7 +3442,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb29fb11ef40c839c1c6b4e9c2ec4f357f9f674491e9df5a8c94f8cc2005f860" dependencies = [ "bytes 0.5.6", - "futures 0.3.5", + "futures 0.3.6", "hyper 0.13.8", "hyper-rustls 0.19.1", "multipart", @@ -3516,7 +3530,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" dependencies = [ "bytes 0.4.12", - "futures 0.1.29", + "futures 0.1.30", "mio", "num_cpus", "tokio-codec", @@ -3562,7 +3576,7 @@ checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" dependencies = [ "bytes 0.4.12", "either", - "futures 0.1.29", + "futures 0.1.30", ] [[package]] @@ -3572,7 +3586,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" dependencies = [ "bytes 0.4.12", - "futures 0.1.29", + "futures 0.1.30", "tokio-io", ] @@ -3582,7 +3596,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" dependencies = [ - "futures 0.1.29", + "futures 0.1.30", "tokio-executor", ] @@ -3593,7 +3607,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" dependencies = [ "crossbeam-utils 0.7.2", - "futures 0.1.29", + "futures 0.1.30", ] [[package]] @@ -3602,7 +3616,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" dependencies = [ - "futures 0.1.29", + "futures 0.1.30", "tokio-io", "tokio-threadpool", ] @@ -3614,7 +3628,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" dependencies = [ "bytes 0.4.12", - "futures 0.1.29", + "futures 0.1.30", "log 0.4.11", ] @@ -3625,7 +3639,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" dependencies = [ "crossbeam-utils 0.7.2", - "futures 0.1.29", + "futures 0.1.30", "lazy_static", "log 0.4.11", "mio", @@ -3644,7 +3658,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d7cf08f990090abd6c6a73cab46fed62f85e8aef8b99e4b918a9f4a637f0676" dependencies = [ "bytes 0.4.12", - "futures 0.1.29", + "futures 0.1.30", "iovec", "rustls 0.16.0", "tokio-io", @@ -3681,7 +3695,7 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0c34c6e548f101053321cba3da7cbb87a610b85555884c41b07da2eb91aff12" dependencies = [ - "futures 0.1.29", + "futures 0.1.30", "libc", "mio", "mio-uds", @@ -3699,7 +3713,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" dependencies = [ "fnv", - "futures 0.1.29", + "futures 0.1.30", ] [[package]] @@ -3709,7 +3723,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" dependencies = [ "bytes 0.4.12", - "futures 0.1.29", + "futures 0.1.30", "iovec", "mio", "tokio-io", @@ -3725,7 +3739,7 @@ dependencies = [ "crossbeam-deque", "crossbeam-queue", "crossbeam-utils 0.7.2", - "futures 0.1.29", + "futures 0.1.30", "lazy_static", "log 0.4.11", "num_cpus", @@ -3740,7 +3754,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" dependencies = [ "crossbeam-utils 0.7.2", - "futures 0.1.29", + "futures 0.1.30", "slab", "tokio-executor", ] @@ -3752,7 +3766,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" dependencies = [ "bytes 0.4.12", - "futures 0.1.29", + "futures 0.1.30", "log 0.4.11", "mio", "tokio-codec", @@ -3767,7 +3781,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0" dependencies = [ "bytes 0.4.12", - "futures 0.1.29", + "futures 0.1.30", "iovec", "libc", "log 0.4.11", @@ -3812,7 +3826,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b32f72af77f1bfe3d3d4da8516a238ebe7039b51dd8637a09841ac7f16d2c987" dependencies = [ - "futures 0.1.29", + "futures 0.1.30", ] [[package]] @@ -3840,9 +3854,9 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada" dependencies = [ - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.42", + "syn 1.0.44", ] [[package]] @@ -3872,7 +3886,7 @@ checksum = "0838272e89f1c693b4df38dc353412e389cf548ceed6f9fd1af5a8d6e0e7cf74" dependencies = [ "byteorder", "failure", - "futures 0.1.29", + "futures 0.1.30", "idna 0.1.5", "lazy_static", "log 0.4.11", @@ -3896,7 +3910,7 @@ checksum = "09144f0992b0870fa8d2972cc069cbf1e3c0fda64d1f3d45c4d68d0e0b52ad4e" dependencies = [ "byteorder", "failure", - "futures 0.1.29", + "futures 0.1.30", "idna 0.1.5", "lazy_static", "log 0.4.11", @@ -3921,7 +3935,7 @@ dependencies = [ "async-trait", "enum-as-inner", "failure", - "futures 0.3.5", + "futures 0.3.6", "idna 0.2.0", "lazy_static", "log 0.4.11", @@ -3940,7 +3954,7 @@ checksum = "8a9f877f7a1ad821ab350505e1f1b146a4960402991787191d6d8cab2ce2de2c" dependencies = [ "cfg-if", "failure", - "futures 0.1.29", + "futures 0.1.30", "ipconfig 0.1.9", "lazy_static", "log 0.4.11", @@ -3959,7 +3973,7 @@ checksum = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f" dependencies = [ "cfg-if", "failure", - "futures 0.3.5", + "futures 0.3.6", "ipconfig 0.2.2", "lazy_static", "log 0.4.11", @@ -4098,9 +4112,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae" dependencies = [ "nom", - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.42", + "syn 1.0.44", ] [[package]] @@ -4155,7 +4169,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" dependencies = [ - "futures 0.1.29", + "futures 0.1.30", "log 0.4.11", "try-lock", ] @@ -4203,9 +4217,9 @@ dependencies = [ "bumpalo", "lazy_static", "log 0.4.11", - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.42", + "syn 1.0.44", "wasm-bindgen-shared", ] @@ -4237,9 +4251,9 @@ version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" dependencies = [ - "proc-macro2 1.0.23", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.42", + "syn 1.0.44", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4289,10 +4303,10 @@ dependencies = [ ] [[package]] -name = "wepoll-sys-stjepang" -version = "1.0.8" +name = "wepoll-sys" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fdfbb03f290ca0b27922e8d48a0997b4ceea12df33269b9f75e713311eb178d" +checksum = "142bc2cba3fe88be1a8fcb55c727fa4cd5b0cf2d7438722792e22f26f04bc1e0" dependencies = [ "cc", ] @@ -4305,9 +4319,9 @@ checksum = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" [[package]] name = "widestring" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a763e303c0e0f23b0da40888724762e802a8ffefbc22de4127ef42493c2ea68c" +checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" [[package]] name = "winapi" diff --git a/Cargo.toml b/Cargo.toml index fa5bbf2c..0432301c 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,7 @@ bincode = "1.3.1" log = "0.4" fern = { version = "0.5.6", features = ["colored"] } +sensor_value = { git = "https://github.com/dskleingeld/sensor_central.git", branch = "boolean-fields" } gpio-cdev = { git = "https://github.com/rust-embedded/gpio-cdev", branch = "master" } nix = "0.17" diff --git a/src/controller/environment/mod.rs b/src/controller/environment/mod.rs index d6c5ec09..0f195c82 100755 --- a/src/controller/environment/mod.rs +++ b/src/controller/environment/mod.rs @@ -1,12 +1,23 @@ +use sensor_value::SensorValue; + +struct History { + last_values: Vec, +} pub struct Environment { - light: [f32; 100], + light: History, +} + +impl Environment { + pub fn update(&self, s: SensorValue){ + + } } impl std::default::Default for Environment { fn default() -> Self { Environment { - light: [0f32; 100], + light: History{last_values: Vec::new()}, } } -} \ No newline at end of file +} diff --git a/src/controller/mod.rs b/src/controller/mod.rs index 402c0c54..d932d8a7 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -3,21 +3,21 @@ use std::thread; use serde::{Serialize, Deserialize}; mod system; -use system::{Lighting}; +use system::Lighting; mod environment; use environment::Environment; mod state; -use state::{RoomState}; +use state::RoomState; mod commands; -use commands::{handle_cmd}; +use commands::handle_cmd; pub use commands::Command; pub use state::State; use crate::input::mpd_status::MpdStatus; use crate::errors::Error; -use crate::input::sensors::Button; +use sensor_value::{Button, Press, SensorValue}; #[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub enum Event { @@ -25,8 +25,7 @@ pub enum Event { Alarm, Test, Command(Command), - PressShort(Button), - PressLong(Button), + Sensor(SensorValue), } pub struct Modifications { //change name to: alteration, deviation, overrides or something else? @@ -113,6 +112,10 @@ pub fn start(rx: crossbeam_channel::Receiver, mpd_status: MpdStatus) -> R }, _ => (), } + + if let Event::Sensor(s) = event { + env.update(s); + } } }); Ok(handle) @@ -131,47 +134,55 @@ fn handle_event(event: Event, current_state: State, mods: &mut Modifications, (Event::Update, _) => state.update(mods, system, env)?, (Event::Alarm, _) => Some(State::WakeUp), (Event::Test, _) => {dbg!("a test happend"); None}, - - //(Event::Sensor(_), _) => None, - - (Event::PressShort(button), _) => { - match button { - Button::LampLeft => Some(State::Quiet), - Button::LampMid => Some(State::Silent), - Button::LampRight => Some(State::Off), - - Button::DeskLeftMost => Some(State::Sleep), - Button::DeskLeft => Some(State::Normal), - Button::DeskRight => Some(State::Quiet), - Button::DeskRightMost => Some(State::Off), - - Button::DeskTop => handle_cmd(Command::MpdIncreaseVolume, mods, system), - Button::DeskMid => handle_cmd(Command::MpdPause, mods, system), - Button::DeskBottom => handle_cmd(Command::MpdDecreaseVolume, mods, system), - - _ => None, - } - } - (Event::PressLong(button), _) => { - let cmd = match button { - Button::LampLeft => Command::LampsDim, - Button::LampMid => Command::LampsDimmest, - Button::LampRight => Command::LampsToggle, - - Button::DeskLeftMost => Command::LampsNight, - Button::DeskLeft => Command::LampsEvening, - Button::DeskRight => Command::LampsDay, - Button::DeskRightMost => Command::LampsToggle, - - _ => return Ok(None), - }; - handle_cmd(cmd, mods, system) - } + + (Event::Sensor(s), _) => handle_sensor(s, mods, system), + }; Ok(next_state) } -fn change_state(next_state: State, mods: &mut Modifications, system: &mut System) -> Result, Error> { +fn handle_sensor(value: SensorValue, mods: &mut Modifications, system: &mut System) -> Option { + match value { + SensorValue::ButtonPress(press) => handle_buttonpress(press, mods, system), + _ => todo!(), + } +} + +fn handle_buttonpress(press: Press, mods: &mut Modifications, system: &mut System) -> Option { + if press.duration > 10*1000 {// millisec + match press.button { + Button::LampLeft => Some(State::Quiet), + Button::LampMid => Some(State::Silent), + Button::LampRight => Some(State::Off), + + Button::DeskLeftMost => Some(State::Sleep), + Button::DeskLeft => Some(State::Normal), + Button::DeskRight => Some(State::Quiet), + Button::DeskRightMost => Some(State::Off), + + Button::DeskTop => handle_cmd(Command::MpdIncreaseVolume, mods, system), + Button::DeskMid => handle_cmd(Command::MpdPause, mods, system), + Button::DeskBottom => handle_cmd(Command::MpdDecreaseVolume, mods, system), + } + } else { + let cmd = match press.button { + Button::LampLeft => Command::LampsDim, + Button::LampMid => Command::LampsDimmest, + Button::LampRight => Command::LampsToggle, + + Button::DeskLeftMost => Command::LampsNight, + Button::DeskLeft => Command::LampsEvening, + Button::DeskRight => Command::LampsDay, + Button::DeskRightMost => Command::LampsToggle, + + _ => return None, + }; + handle_cmd(cmd, mods, system) + } +} + +fn change_state(next_state: State, mods: &mut Modifications, system: &mut System) + -> Result, Error> { let res = match &next_state { State::Normal => state::Normal::setup(mods, system), @@ -187,6 +198,5 @@ fn change_state(next_state: State, mods: &mut Modifications, system: &mut System error!("ran into error trying to switch to state: {:?}, error: {:?}", next_state,e); } - res -} \ No newline at end of file +} diff --git a/src/input/mod.rs b/src/input/mod.rs index 4db16622..a07d1781 100755 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -6,4 +6,3 @@ pub mod mpd_status; pub use youtube_downloader::YoutubeDownloader; pub use mpd_status::MpdStatus; -pub use web_api::sensors; \ No newline at end of file diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index 2c8a963f..5107511b 100755 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -9,7 +9,6 @@ use actix_web::web::{Form, Data}; mod logins; mod alarms; mod music; -pub mod sensors; mod commands; pub mod server; diff --git a/src/input/web_api/sensors.rs b/src/input/web_api/sensors.rs deleted file mode 100644 index ba695b6e..00000000 --- a/src/input/web_api/sensors.rs +++ /dev/null @@ -1,59 +0,0 @@ -//use bytes::Bytes; -use actix_web::web::{Data, Bytes}; -use serde::{Deserialize, Serialize}; -use actix_web::HttpResponse; - -use super::*; -use crate::controller; - -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] -pub enum Button { - LampLeft, - LampMid, - LampRight, - - DeskLeftMost, - DeskLeft, - DeskRight, - DeskRightMost, - - DeskTop, - DeskMid, - DeskBottom, -} - -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] -pub enum ButtonPress { - Long(Button), - Short(Button), -} - -#[derive(Debug, Clone, Copy, Serialize, Deserialize)] -pub enum SensorValue { - ButtonPress(ButtonPress), - Temperature(f32), - Humidity(f32), - Pressure(f32), -} - -pub fn handle(body: Bytes, state: Data) -> HttpResponse { - let res = bincode::deserialize::(&body[..]); - match res { - Err(e) => error!("deserialize sensorval failed: {:?}",e), - Ok(v) => { - //temp to ButtonPress - match v { - SensorValue::ButtonPress(p) => { - let event = match p{ - ButtonPress::Long(b) => controller::Event::PressLong(b), - ButtonPress::Short(b) => controller::Event::PressShort(b), - }; - state.controller_addr.send(event).unwrap(); - } - _ => (), - } - } - } - - HttpResponse::Ok().finish() -} \ No newline at end of file diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index 352a705c..d5e7183c 100755 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -1,12 +1,15 @@ use rustls::{NoClientAuth, ServerConfig}; use rustls::internal::pemfile::{certs, pkcs8_private_keys}; use telegram_bot::types::refs::UserId; +use sensor_value::SensorValue; use actix_rt::System; use actix_web::{HttpServer,App, web, Responder}; use actix_identity::{CookieIdentityPolicy, IdentityService}; use actix_files as axtix_fs; use actix_web::HttpRequest; +use actix_web::web::{Data, Bytes}; +use actix_web::HttpResponse; use std::thread; use std::sync::{Arc, Mutex, RwLock, atomic::AtomicUsize}; @@ -26,7 +29,7 @@ pub mod login; pub use database::PasswordDatabase; pub use login::{make_random_cookie_key, login_page, login_get_and_check, logout}; pub use login_redirect::CheckLogin; -use super::{alarms, commands, music, sensors}; +use super::{alarms, commands, music}; pub struct Session {}//TODO deprecate @@ -59,11 +62,11 @@ impl State { State { controller_addr: controller_tx, - alarms: alarms, - passw_db: passw_db, - youtube_dl: youtube_dl, - sessions: sessions, - free_session_ids: free_session_ids, + alarms, + passw_db, + youtube_dl, + sessions, + free_session_ids, bot_token, valid_ids, } @@ -169,7 +172,7 @@ pub fn start_webserver(key_dir: &Path, .service(web::resource(&format!("/{}", &state.bot_token)) .to(bot::handle_webhook)) .service(web::resource(&format!("/{}", ha_key)) - .route(web::post().to(sensors::handle)) + .route(web::post().to(handle_sensor)) ) .service(web::scope("/") @@ -197,4 +200,13 @@ pub fn start_webserver(key_dir: &Path, let web_handle = rx.recv().unwrap(); Ok(web_handle) -} \ No newline at end of file +} + +pub fn handle_sensor(body: Bytes, state: Data) -> HttpResponse { + let res = bincode::deserialize::(&body[..]); + match res { + Err(err) => error!("deserialize sensorval failed: {:?}", err), + Ok(event) => state.controller_addr.send(Event::Sensor(event)).unwrap(), + } + HttpResponse::Ok().finish() +} From 21569aa47c220432b17331adefc7c142e26bc232 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Sun, 11 Oct 2020 02:26:53 +0200 Subject: [PATCH 054/687] cargo fmt --- src/controller/commands.rs | 104 ++-- src/controller/environment/mod.rs | 8 +- src/controller/mod.rs | 281 ++++++----- src/controller/state/lightloop.rs | 24 +- src/controller/state/mod.rs | 37 +- src/controller/state/normal.rs | 41 +- src/controller/state/off.rs | 26 +- src/controller/state/quiet.rs | 37 +- src/controller/state/silent.rs | 39 +- src/controller/state/sleep.rs | 32 +- src/controller/state/wakeup.rs | 117 +++-- src/controller/system/lamps/mod.rs | 528 +++++++++++---------- src/controller/system/mod.rs | 2 +- src/controller/system/mpd_control.rs | 53 ++- src/errors.rs | 114 ++--- src/input/alarms.rs | 98 ++-- src/input/bot/mod.rs | 357 +++++++------- src/input/bot/set_alarm.rs | 135 +++--- src/input/bot/youtube_dl.rs | 75 ++- src/input/mod.rs | 6 +- src/input/mpd_status.rs | 18 +- src/input/web_api/alarms.rs | 126 ++--- src/input/web_api/commands.rs | 113 +++-- src/input/web_api/mod.rs | 39 +- src/input/web_api/music.rs | 31 +- src/input/web_api/server/database.rs | 159 ++++--- src/input/web_api/server/login.rs | 104 ++-- src/input/web_api/server/login_redirect.rs | 39 +- src/input/web_api/server/mod.rs | 323 +++++++------ src/input/youtube_downloader.rs | 375 +++++++-------- src/main.rs | 156 +++--- 31 files changed, 1928 insertions(+), 1669 deletions(-) diff --git a/src/controller/commands.rs b/src/controller/commands.rs index 8e2a9953..98355ad6 100755 --- a/src/controller/commands.rs +++ b/src/controller/commands.rs @@ -1,4 +1,4 @@ -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use super::{Modifications, System}; use crate::controller::state::*; @@ -6,62 +6,84 @@ use crate::controller::system::mpd_control; #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub enum Command { - None, + None, - LampsToggle, - LampsDim, - LampsDimmest, - LampsEvening, - LampsNight, - LampsDay, + LampsToggle, + LampsDim, + LampsDimmest, + LampsEvening, + LampsNight, + LampsDay, - MpdPause, - MpdDecreaseVolume, - MpdIncreaseVolume, - MpdNextSong, - MpdPrevSong, + MpdPause, + MpdDecreaseVolume, + MpdIncreaseVolume, + MpdNextSong, + MpdPrevSong, - GoToLinux, - GoToWindows, - - Test, //prints a test message + GoToLinux, + GoToWindows, - ChangeState(State), + Test, //prints a test message + + ChangeState(State), } //TODO handle error on command pub fn handle_cmd(cmd: Command, mods: &mut Modifications, sys: &mut System) -> Option { - - println!("handled a command"); + println!("handled a command"); match cmd { - Command::ChangeState(target_state) => { - return Some(target_state); - } - //Command::PauseMpd => {unimplemented!(); state}, - - Command::LampsToggle => {sys.lights.toggle().unwrap(); mods.lighting = true} - Command::LampsDim => {sys.lights.set_all_ct(50,500).unwrap(); mods.lighting = true} - Command::LampsDimmest => {sys.lights.set_all_ct(1,500).unwrap(); mods.lighting = true} - Command::LampsEvening => {sys.lights.set_all_ct(254,320).unwrap(); mods.lighting = true} - Command::LampsNight => {sys.lights.set_all_ct(220,500).unwrap(); mods.lighting = true} - Command::LampsDay => {sys.lights.set_all_ct(254,240).unwrap(); mods.lighting = true} + Command::ChangeState(target_state) => { + return Some(target_state); + } + //Command::PauseMpd => {unimplemented!(); state}, + Command::LampsToggle => { + sys.lights.toggle().unwrap(); + mods.lighting = true + } + Command::LampsDim => { + sys.lights.set_all_ct(50, 500).unwrap(); + mods.lighting = true + } + Command::LampsDimmest => { + sys.lights.set_all_ct(1, 500).unwrap(); + mods.lighting = true + } + Command::LampsEvening => { + sys.lights.set_all_ct(254, 320).unwrap(); + mods.lighting = true + } + Command::LampsNight => { + sys.lights.set_all_ct(220, 500).unwrap(); + mods.lighting = true + } + Command::LampsDay => { + sys.lights.set_all_ct(254, 240).unwrap(); + mods.lighting = true + } Command::GoToLinux => println!("should go to linux"), Command::GoToWindows => println!("should go to windows"), - - Command::MpdPause => {mpd_control::toggle_playback(&mut sys.mpd).unwrap(); mods.mpd = true }, - Command::MpdDecreaseVolume => {mpd_control::decrease_volume(&mut sys.mpd).unwrap(); mods.mpd = true }, + + Command::MpdPause => { + mpd_control::toggle_playback(&mut sys.mpd).unwrap(); + mods.mpd = true + } + Command::MpdDecreaseVolume => { + mpd_control::decrease_volume(&mut sys.mpd).unwrap(); + mods.mpd = true + } Command::MpdIncreaseVolume => { if let mpd::State::Play = sys.mpd.is_playing() { - mpd_control::increase_volume(&mut sys.mpd).unwrap(); - mods.mpd = true + mpd_control::increase_volume(&mut sys.mpd).unwrap(); + mods.mpd = true } - }, - Command::MpdNextSong => {mpd_control::next_song().unwrap()}, - Command::MpdPrevSong => {mpd_control::prev_song().unwrap()}, + } + Command::MpdNextSong => mpd_control::next_song().unwrap(), + Command::MpdPrevSong => mpd_control::prev_song().unwrap(), - Command::Test => { warn!("The Test command was just send")}, - Command::None => { error!("None command was issued, this should not happen")}, + Command::Test => warn!("The Test command was just send"), + Command::None => error!("None command was issued, this should not happen"), } None } diff --git a/src/controller/environment/mod.rs b/src/controller/environment/mod.rs index 0f195c82..1a12dcc1 100755 --- a/src/controller/environment/mod.rs +++ b/src/controller/environment/mod.rs @@ -9,15 +9,15 @@ pub struct Environment { } impl Environment { - pub fn update(&self, s: SensorValue){ - - } + pub fn update(&self, s: SensorValue) {} } impl std::default::Default for Environment { fn default() -> Self { Environment { - light: History{last_values: Vec::new()}, + light: History { + last_values: Vec::new(), + }, } } } diff --git a/src/controller/mod.rs b/src/controller/mod.rs index d932d8a7..b34ad61f 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -1,6 +1,6 @@ -use std::time::{Duration, Instant}; +use serde::{Deserialize, Serialize}; use std::thread; -use serde::{Serialize, Deserialize}; +use std::time::{Duration, Instant}; mod system; use system::Lighting; @@ -13,143 +13,172 @@ use state::RoomState; mod commands; use commands::handle_cmd; -pub use commands::Command; -pub use state::State; -use crate::input::mpd_status::MpdStatus; use crate::errors::Error; +use crate::input::mpd_status::MpdStatus; +pub use commands::Command; use sensor_value::{Button, Press, SensorValue}; +pub use state::State; #[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub enum Event { - Update, - Alarm, - Test, - Command(Command), - Sensor(SensorValue), + Update, + Alarm, + Test, + Command(Command), + Sensor(SensorValue), } -pub struct Modifications { //change name to: alteration, deviation, overrides or something else? - lighting: bool, - mpd: bool, - //Desk, - //Alarm, +pub struct Modifications { + //change name to: alteration, deviation, overrides or something else? + lighting: bool, + mpd: bool, + //Desk, + //Alarm, } impl Modifications { - fn reset(&mut self) { - self.lighting = false; - self.mpd = false; - } + fn reset(&mut self) { + self.lighting = false; + self.mpd = false; + } } impl Default for Modifications { - fn default() -> Self { - Modifications {lighting: false, mpd: false} - } + fn default() -> Self { + Modifications { + lighting: false, + mpd: false, + } + } } pub struct System { - update_period: Duration, - next_update: Instant, + update_period: Duration, + next_update: Instant, - lights: Lighting, - mpd: MpdStatus - //mpd + lights: Lighting, + mpd: MpdStatus, //mpd - //etc + //etc } -fn saturating_duration_till(target: std::time::Instant) -> std::time::Duration{ - let now = Instant::now(); - if now < target { - target - now - } else { - Duration::from_secs(0) - } +fn saturating_duration_till(target: std::time::Instant) -> std::time::Duration { + let now = Instant::now(); + if now < target { + target - now + } else { + Duration::from_secs(0) + } } -pub fn start(rx: crossbeam_channel::Receiver, mpd_status: MpdStatus) -> Result, Error>{ - - let mut system = System { - update_period: Duration::from_secs(5), - next_update: Instant::now()+Duration::from_secs(5), - - lights: Lighting::init()?, - mpd: mpd_status, - }; - - let handle = thread::spawn(move || { - let mut mods = Modifications::default(); - let mut env = Environment::default(); - // TODO guess best init state from statefile or lamps+mpd+time - - let mut state: Box = state::Normal::setup(&mut mods, &mut system).unwrap(); //initial state - let mut current_state = State::Normal; - - loop { - //wait for next update or an incoming event - let time_till_update = saturating_duration_till(system.next_update); - let event = match rx.recv_timeout(time_till_update){ - Ok(event) => event, - Err(error) => match error { - crossbeam_channel::RecvTimeoutError::Timeout => { - system.next_update = Instant::now()+system.update_period; - Event::Update - }, - crossbeam_channel::RecvTimeoutError::Disconnected => return (), - } - }; - - match handle_event(event, current_state, &mut mods, - &mut system, &mut env, &mut state){ - - Err(e) => error!("Ran into an error handling an event: {:?}", e), - Ok(Some(target_state)) => {//should switch to another state - if let Ok(new_state) = change_state(target_state, &mut mods, &mut system){ - state = new_state; - current_state = target_state; - } //if state setup ran into an error we do not switch state - }, - _ => (), - } - +pub fn start( + rx: crossbeam_channel::Receiver, + mpd_status: MpdStatus, +) -> Result, Error> { + let mut system = System { + update_period: Duration::from_secs(5), + next_update: Instant::now() + Duration::from_secs(5), + + lights: Lighting::init()?, + mpd: mpd_status, + }; + + let handle = thread::spawn(move || { + let mut mods = Modifications::default(); + let mut env = Environment::default(); + // TODO guess best init state from statefile or lamps+mpd+time + + let mut state: Box = state::Normal::setup(&mut mods, &mut system).unwrap(); //initial state + let mut current_state = State::Normal; + + loop { + //wait for next update or an incoming event + let time_till_update = saturating_duration_till(system.next_update); + let event = match rx.recv_timeout(time_till_update) { + Ok(event) => event, + Err(error) => match error { + crossbeam_channel::RecvTimeoutError::Timeout => { + system.next_update = Instant::now() + system.update_period; + Event::Update + } + crossbeam_channel::RecvTimeoutError::Disconnected => return (), + }, + }; + + match handle_event( + event, + current_state, + &mut mods, + &mut system, + &mut env, + &mut state, + ) { + Err(e) => error!("Ran into an error handling an event: {:?}", e), + Ok(Some(target_state)) => { + //should switch to another state + if let Ok(new_state) = change_state(target_state, &mut mods, &mut system) { + state = new_state; + current_state = target_state; + } //if state setup ran into an error we do not switch state + } + _ => (), + } + if let Event::Sensor(s) = event { env.update(s); } - } - }); - Ok(handle) + } + }); + Ok(handle) } -fn handle_event(event: Event, current_state: State, mods: &mut Modifications, - system: &mut System, env: &mut Environment, state: &mut Box) - -> Result, Error> { - - //state changes may not return errors - let next_state = match (event, current_state) { - //specific test code for normal state - (Event::Test, State::Normal) => {dbg!("a test happend while in normal state"); None}, - //general code that is the same for all functions, unless specific handlers exist above - (Event::Command(cmd), _) => handle_cmd(cmd, mods, system), - (Event::Update, _) => state.update(mods, system, env)?, - (Event::Alarm, _) => Some(State::WakeUp), - (Event::Test, _) => {dbg!("a test happend"); None}, - - (Event::Sensor(s), _) => handle_sensor(s, mods, system), - - }; - Ok(next_state) +fn handle_event( + event: Event, + current_state: State, + mods: &mut Modifications, + system: &mut System, + env: &mut Environment, + state: &mut Box, +) -> Result, Error> { + //state changes may not return errors + let next_state = match (event, current_state) { + //specific test code for normal state + (Event::Test, State::Normal) => { + dbg!("a test happend while in normal state"); + None + } + //general code that is the same for all functions, unless specific handlers exist above + (Event::Command(cmd), _) => handle_cmd(cmd, mods, system), + (Event::Update, _) => state.update(mods, system, env)?, + (Event::Alarm, _) => Some(State::WakeUp), + (Event::Test, _) => { + dbg!("a test happend"); + None + } + + (Event::Sensor(s), _) => handle_sensor(s, mods, system), + }; + Ok(next_state) } -fn handle_sensor(value: SensorValue, mods: &mut Modifications, system: &mut System) -> Option { +fn handle_sensor( + value: SensorValue, + mods: &mut Modifications, + system: &mut System, +) -> Option { match value { SensorValue::ButtonPress(press) => handle_buttonpress(press, mods, system), _ => todo!(), } } -fn handle_buttonpress(press: Press, mods: &mut Modifications, system: &mut System) -> Option { - if press.duration > 10*1000 {// millisec +fn handle_buttonpress( + press: Press, + mods: &mut Modifications, + system: &mut System, +) -> Option { + if press.duration > 10 * 1000 { + // millisec match press.button { Button::LampLeft => Some(State::Quiet), Button::LampMid => Some(State::Silent), @@ -159,7 +188,7 @@ fn handle_buttonpress(press: Press, mods: &mut Modifications, system: &mut Syste Button::DeskLeft => Some(State::Normal), Button::DeskRight => Some(State::Quiet), Button::DeskRightMost => Some(State::Off), - + Button::DeskTop => handle_cmd(Command::MpdIncreaseVolume, mods, system), Button::DeskMid => handle_cmd(Command::MpdPause, mods, system), Button::DeskBottom => handle_cmd(Command::MpdDecreaseVolume, mods, system), @@ -169,7 +198,7 @@ fn handle_buttonpress(press: Press, mods: &mut Modifications, system: &mut Syste Button::LampLeft => Command::LampsDim, Button::LampMid => Command::LampsDimmest, Button::LampRight => Command::LampsToggle, - + Button::DeskLeftMost => Command::LampsNight, Button::DeskLeft => Command::LampsEvening, Button::DeskRight => Command::LampsDay, @@ -181,22 +210,26 @@ fn handle_buttonpress(press: Press, mods: &mut Modifications, system: &mut Syste } } -fn change_state(next_state: State, mods: &mut Modifications, system: &mut System) - -> Result, Error> { - - let res = match &next_state { - State::Normal => state::Normal::setup(mods, system), - State::LightLoop => state::LightLoop::setup(mods, system), - State::WakeUp => state::WakeUp::setup(mods, system), - State::Sleep => state::Sleep::setup(mods, system), - State::Silent => state::Silent::setup(mods, system), - State::Quiet => state::Quiet::setup(mods, system), - State::Off => state::Off::setup(mods, system), - }; - - if let Err(ref e) = &res { - error!("ran into error trying to switch to state: {:?}, error: {:?}", - next_state,e); - } - res +fn change_state( + next_state: State, + mods: &mut Modifications, + system: &mut System, +) -> Result, Error> { + let res = match &next_state { + State::Normal => state::Normal::setup(mods, system), + State::LightLoop => state::LightLoop::setup(mods, system), + State::WakeUp => state::WakeUp::setup(mods, system), + State::Sleep => state::Sleep::setup(mods, system), + State::Silent => state::Silent::setup(mods, system), + State::Quiet => state::Quiet::setup(mods, system), + State::Off => state::Off::setup(mods, system), + }; + + if let Err(ref e) = &res { + error!( + "ran into error trying to switch to state: {:?}, error: {:?}", + next_state, e + ); + } + res } diff --git a/src/controller/state/lightloop.rs b/src/controller/state/lightloop.rs index b6a7ca2b..dd31e92e 100755 --- a/src/controller/state/lightloop.rs +++ b/src/controller/state/lightloop.rs @@ -1,4 +1,4 @@ -use super::super::{Modifications, System, Environment}; +use super::super::{Environment, Modifications, System}; use super::{RoomState, State}; use crate::errors::Error; use std::time::{Duration, Instant}; @@ -16,14 +16,19 @@ impl LightLoop { mods.lighting = false; sys.update_period = Duration::from_millis(500); - sys.next_update = Instant::now()+sys.update_period; + sys.next_update = Instant::now() + sys.update_period; - Ok(Box::new(Self {counter: 100, })) + Ok(Box::new(Self { counter: 100 })) } } impl RoomState for LightLoop { - fn update(&mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> Result, Error> { + fn update( + &mut self, + mods: &mut Modifications, + sys: &mut System, + _env: &mut Environment, + ) -> Result, Error> { dbg!("updating lightloop state"); if self.counter == 0 { Ok(Some(State::Normal)) @@ -36,9 +41,10 @@ impl RoomState for LightLoop { Ok(None) } } - fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> {Ok(())} - fn state(&self) -> State {State::LightLoop } + fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> { + Ok(()) + } + fn state(&self) -> State { + State::LightLoop + } } - - - diff --git a/src/controller/state/mod.rs b/src/controller/state/mod.rs index 7044ba7e..9cdbcd4d 100755 --- a/src/controller/state/mod.rs +++ b/src/controller/state/mod.rs @@ -1,22 +1,22 @@ -use serde::{Serialize, Deserialize}; -use super::{System, Modifications, Environment}; +use super::{Environment, Modifications, System}; use crate::errors::Error; +use serde::{Deserialize, Serialize}; -mod normal; mod lightloop; -mod wakeup; -mod sleep; -mod silent; -mod quiet; +mod normal; mod off; +mod quiet; +mod silent; +mod sleep; +mod wakeup; -pub use normal::Normal; pub use lightloop::LightLoop; -pub use wakeup::WakeUp; -pub use sleep::Sleep; -pub use silent::Silent; -pub use quiet::Quiet; +pub use normal::Normal; pub use off::Off; +pub use quiet::Quiet; +pub use silent::Silent; +pub use sleep::Sleep; +pub use wakeup::WakeUp; #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub enum State { @@ -30,9 +30,12 @@ pub enum State { } pub trait RoomState { - fn update(&mut self, mods: &mut Modifications, system: &mut System, - env: &mut Environment) -> Result, Error>; - fn breakdown(&self, mods: &mut Modifications, system: &mut System) - -> Result<(), Error>; + fn update( + &mut self, + mods: &mut Modifications, + system: &mut System, + env: &mut Environment, + ) -> Result, Error>; + fn breakdown(&self, mods: &mut Modifications, system: &mut System) -> Result<(), Error>; fn state(&self) -> State; -} \ No newline at end of file +} diff --git a/src/controller/state/normal.rs b/src/controller/state/normal.rs index eb3ac813..12c4e85d 100755 --- a/src/controller/state/normal.rs +++ b/src/controller/state/normal.rs @@ -1,4 +1,4 @@ -use super::super::{Modifications, System, Environment}; +use super::super::{Environment, Modifications, System}; use super::{RoomState, State}; use crate::errors::Error; @@ -7,17 +7,16 @@ use std::time::{Duration, Instant}; fn update_lights(sys: &mut System) -> Result<(), Error> { let now = Local::now(); - if now.time() > NaiveTime::from_hms(22,0,0) || now.time() < NaiveTime::from_hms(6,0,0) { - sys.lights.set_all_ct(220,500)?; - } else if now.time() > NaiveTime::from_hms(17,0,0) { - sys.lights.set_all_ct(254,320)?; - } else if now.time() >= NaiveTime::from_hms(6,0,0) { - sys.lights.set_all_ct(254,240)?; + if now.time() > NaiveTime::from_hms(22, 0, 0) || now.time() < NaiveTime::from_hms(6, 0, 0) { + sys.lights.set_all_ct(220, 500)?; + } else if now.time() > NaiveTime::from_hms(17, 0, 0) { + sys.lights.set_all_ct(254, 320)?; + } else if now.time() >= NaiveTime::from_hms(6, 0, 0) { + sys.lights.set_all_ct(254, 240)?; }; Ok(()) } - #[derive(Default, Clone, Copy)] pub struct Normal {} @@ -25,9 +24,9 @@ impl Normal { pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { dbg!("making everything rdy for the normal state"); mods.reset(); - + sys.update_period = Duration::from_secs(5); - sys.next_update = Instant::now()+sys.update_period; + sys.next_update = Instant::now() + sys.update_period; update_lights(sys)?; sys.lights.all_on()?; @@ -36,13 +35,23 @@ impl Normal { } impl RoomState for Normal { - fn update(&mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> Result,Error> { - + fn update( + &mut self, + mods: &mut Modifications, + sys: &mut System, + _env: &mut Environment, + ) -> Result, Error> { //dbg!("updating normal state"); - if !mods.lighting {update_lights(sys)?} + if !mods.lighting { + update_lights(sys)? + } Ok(None) } - fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> {Ok(())} - fn state(&self) -> State {State::Normal } -} \ No newline at end of file + fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> { + Ok(()) + } + fn state(&self) -> State { + State::Normal + } +} diff --git a/src/controller/state/off.rs b/src/controller/state/off.rs index 7971f842..b296cc38 100644 --- a/src/controller/state/off.rs +++ b/src/controller/state/off.rs @@ -1,28 +1,34 @@ -use super::super::{Modifications, System, Environment}; +use super::super::{Environment, Modifications, System}; use super::{RoomState, State}; use crate::controller::system::mpd_control as mpd; use crate::errors::Error; #[derive(Clone, Copy)] -pub struct Off { -} +pub struct Off {} impl Off { pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { mods.reset(); mpd::pause()?; sys.lights.all_off()?; - Ok(Box::new(Off { })) + Ok(Box::new(Off {})) } } impl RoomState for Off { - fn update(&mut self, _: &mut Modifications, _: &mut System, _env: &mut Environment) - -> Result, Error> { - + fn update( + &mut self, + _: &mut Modifications, + _: &mut System, + _env: &mut Environment, + ) -> Result, Error> { Ok(None) } - fn breakdown(&self, _: &mut Modifications, _sys: &mut System) -> Result<(), Error> {Ok(())} - fn state(&self) -> State {State::Off } -} \ No newline at end of file + fn breakdown(&self, _: &mut Modifications, _sys: &mut System) -> Result<(), Error> { + Ok(()) + } + fn state(&self) -> State { + State::Off + } +} diff --git a/src/controller/state/quiet.rs b/src/controller/state/quiet.rs index 9527e898..a99dc087 100644 --- a/src/controller/state/quiet.rs +++ b/src/controller/state/quiet.rs @@ -1,4 +1,4 @@ -use super::super::{Modifications, System, Environment}; +use super::super::{Environment, Modifications, System}; use super::{RoomState, State}; use crate::controller::system::mpd_control as mpd; use crate::errors::Error; @@ -7,41 +7,44 @@ use philipshue::hue::LightCommand; use std::time::{Duration, Instant}; #[derive(Clone, Copy)] -pub struct Quiet { -} +pub struct Quiet {} impl Quiet { pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { dbg!("entering silent mode"); mods.reset(); - + sys.update_period = Duration::from_secs(60); - sys.next_update = Instant::now()+sys.update_period; + sys.next_update = Instant::now() + sys.update_period; mpd::set_volume(10)?; sys.lights.single_off(2)?; //2 is desk lamp - let command = LightCommand::default() - .on() - .with_bri(50) - .with_ct(500); + let command = LightCommand::default().on().with_bri(50).with_ct(500); - for lamp_id in &[1,8,5,4,6] { + for lamp_id in &[1, 8, 5, 4, 6] { sys.lights.bridge.set_light_state(*lamp_id, &command)?; sys.lights.lamps.get_mut(lamp_id).unwrap().on = true; } - Ok(Box::new(Quiet { })) + Ok(Box::new(Quiet {})) } } impl RoomState for Quiet { - fn update(&mut self, _: &mut Modifications, _: &mut System, _env: &mut Environment) - -> Result, Error> { - + fn update( + &mut self, + _: &mut Modifications, + _: &mut System, + _env: &mut Environment, + ) -> Result, Error> { Ok(None) } - fn breakdown(&self, _: &mut Modifications, _sys: &mut System) -> Result<(), Error> {Ok(())} - fn state(&self) -> State {State::Quiet } -} \ No newline at end of file + fn breakdown(&self, _: &mut Modifications, _sys: &mut System) -> Result<(), Error> { + Ok(()) + } + fn state(&self) -> State { + State::Quiet + } +} diff --git a/src/controller/state/silent.rs b/src/controller/state/silent.rs index 342b1b47..24e87a6b 100644 --- a/src/controller/state/silent.rs +++ b/src/controller/state/silent.rs @@ -1,4 +1,4 @@ -use super::super::{Modifications, System, Environment}; +use super::super::{Environment, Modifications, System}; use super::{RoomState, State}; use crate::controller::system::mpd_control as mpd; use crate::errors::Error; @@ -7,43 +7,44 @@ use philipshue::hue::LightCommand; use std::time::{Duration, Instant}; #[derive(Clone, Copy)] -pub struct Silent { -} +pub struct Silent {} impl Silent { pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { dbg!("entering silent mode"); mods.reset(); - + sys.update_period = Duration::from_secs(60); - sys.next_update = Instant::now()+sys.update_period; + sys.next_update = Instant::now() + sys.update_period; mpd::pause()?; - + sys.lights.single_off(2)?; - let command = LightCommand::default() - .on() - .with_bri(1) - .with_ct(500); + let command = LightCommand::default().on().with_bri(1).with_ct(500); - for lamp_id in &[1,8,5,4,6] { + for lamp_id in &[1, 8, 5, 4, 6] { sys.lights.bridge.set_light_state(*lamp_id, &command)?; sys.lights.lamps.get_mut(lamp_id).unwrap().on = true; } - Ok(Box::new(Silent {})) } } impl RoomState for Silent { - fn update(&mut self, _: &mut Modifications, _: &mut System, _env: &mut Environment) - -> Result, Error>{ - - + fn update( + &mut self, + _: &mut Modifications, + _: &mut System, + _env: &mut Environment, + ) -> Result, Error> { Ok(None) } - fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> {Ok(())} - fn state(&self) -> State {State::Silent } -} \ No newline at end of file + fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> { + Ok(()) + } + fn state(&self) -> State { + State::Silent + } +} diff --git a/src/controller/state/sleep.rs b/src/controller/state/sleep.rs index 9fd96b09..993ab682 100644 --- a/src/controller/state/sleep.rs +++ b/src/controller/state/sleep.rs @@ -1,4 +1,4 @@ -use super::super::{Modifications, System, Environment}; +use super::super::{Environment, Modifications, System}; use super::{RoomState, State}; use crate::controller::system::mpd_control as mpd; use crate::errors::Error; @@ -14,21 +14,27 @@ impl Sleep { pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { dbg!("entering sleep mode"); mods.reset(); - + sys.update_period = Duration::from_secs(60); - sys.next_update = Instant::now()+sys.update_period; + sys.next_update = Instant::now() + sys.update_period; - const RED: (f32,f32,f32) = (1f32, 0f32, 0f32); + const RED: (f32, f32, f32) = (1f32, 0f32, 0f32); sys.lights.set_all_rgb(0, RED)?; sys.lights.all_on()?; - Ok(Box::new(Sleep {start: Instant::now()})) + Ok(Box::new(Sleep { + start: Instant::now(), + })) } } impl RoomState for Sleep { - - fn update(&mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> Result, Error> { + fn update( + &mut self, + mods: &mut Modifications, + sys: &mut System, + _env: &mut Environment, + ) -> Result, Error> { const LIGHTS_OFF: Duration = Duration::from_secs(60); const MUSIC_OFF: Duration = Duration::from_secs(120); @@ -38,10 +44,14 @@ impl RoomState for Sleep { if self.start.elapsed() >= MUSIC_OFF && !mods.mpd { mpd::pause()?; } - + Ok(None) } - fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> {Ok(())} - fn state(&self) -> State {State::LightLoop } -} \ No newline at end of file + fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> { + Ok(()) + } + fn state(&self) -> State { + State::LightLoop + } +} diff --git a/src/controller/state/wakeup.rs b/src/controller/state/wakeup.rs index f161d435..88277230 100755 --- a/src/controller/state/wakeup.rs +++ b/src/controller/state/wakeup.rs @@ -1,22 +1,23 @@ -use super::super::{Modifications, System, Environment}; +use super::super::{Environment, Modifications, System}; use super::{RoomState, State}; use crate::controller::system; use crate::errors::Error; -use retry::{retry, delay::Fixed}; +use retry::{delay::Fixed, retry}; use std::time::{Duration, Instant}; const UPDATE_PERIOD: u64 = 5; -const WAKEUP_DURATION: u64 = 60*15; //in seconds +const WAKEUP_DURATION: u64 = 60 * 15; //in seconds -const CT_BEGIN: u16 = 500; const CT_END: u16 = 280; -const CT_PER_SECOND: f32 = ((CT_BEGIN-CT_END) as f32)/(WAKEUP_DURATION as f32); -const BRI_PER_SECOND: f32 = 254./(WAKEUP_DURATION as f32); //in seconds +const CT_BEGIN: u16 = 500; +const CT_END: u16 = 280; +const CT_PER_SECOND: f32 = ((CT_BEGIN - CT_END) as f32) / (WAKEUP_DURATION as f32); +const BRI_PER_SECOND: f32 = 254. / (WAKEUP_DURATION as f32); //in seconds -const MUSIC_ON: u64 = 60*5; +const MUSIC_ON: u64 = 60 * 5; const MAX_VOLUME: i8 = 40; const MIN_VOLUME: i8 = 10; -const VOL_PER_SECOND: f32 = (MAX_VOLUME-MIN_VOLUME) as f32/(WAKEUP_DURATION-MUSIC_ON) as f32; +const VOL_PER_SECOND: f32 = (MAX_VOLUME - MIN_VOLUME) as f32 / (WAKEUP_DURATION - MUSIC_ON) as f32; #[derive(Clone, Copy)] pub struct WakeUp { @@ -25,38 +26,49 @@ pub struct WakeUp { } impl WakeUp { - fn setup_playlist() -> Result<(), Error> { - let mpd = &mut retry(Fixed::from_millis(100), || mpd::Client::connect("127.0.0.1:6600"))?; + let mpd = &mut retry(Fixed::from_millis(100), || { + mpd::Client::connect("127.0.0.1:6600") + })?; dbg!(); - retry(Fixed::from_millis(100).take(3), || system::mpd_control::save_current_playlist(mpd))?; + retry(Fixed::from_millis(100).take(3), || { + system::mpd_control::save_current_playlist(mpd) + })?; dbg!(); - retry(Fixed::from_millis(100).take(3), || - system::mpd_control::add_from_playlist(mpd, "calm", - chrono::Duration::seconds(3*60), - chrono::Duration::seconds(5*60)) - )?; + retry(Fixed::from_millis(100).take(3), || { + system::mpd_control::add_from_playlist( + mpd, + "calm", + chrono::Duration::seconds(3 * 60), + chrono::Duration::seconds(5 * 60), + ) + })?; dbg!(); - retry(Fixed::from_millis(100).take(3), || - system::mpd_control::add_from_playlist(mpd, "energetic", - chrono::Duration::seconds(10*60), - chrono::Duration::seconds(11*60)) - )?; - retry(Fixed::from_millis(100).take(3), || - system::mpd_control::add_from_playlist(mpd, "active", - chrono::Duration::seconds(30*60), - chrono::Duration::seconds(60*60)) - )?; - Ok(()) + retry(Fixed::from_millis(100).take(3), || { + system::mpd_control::add_from_playlist( + mpd, + "energetic", + chrono::Duration::seconds(10 * 60), + chrono::Duration::seconds(11 * 60), + ) + })?; + retry(Fixed::from_millis(100).take(3), || { + system::mpd_control::add_from_playlist( + mpd, + "active", + chrono::Duration::seconds(30 * 60), + chrono::Duration::seconds(60 * 60), + ) + })?; + Ok(()) } - } impl WakeUp { pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { dbg!("starting wakeup state"); sys.update_period = Duration::from_secs(UPDATE_PERIOD); - sys.next_update = Instant::now()+sys.update_period; + sys.next_update = Instant::now() + sys.update_period; // reset modifications on entering state mods.lighting = false; @@ -64,45 +76,60 @@ impl WakeUp { Self::setup_playlist()?; sys.lights.set_all_ct(0, CT_BEGIN)?; - - Ok(Box::new(Self{start: Instant::now(), playing: false})) + + Ok(Box::new(Self { + start: Instant::now(), + playing: false, + })) } } impl RoomState for WakeUp { - fn update(&mut self, mods: &mut Modifications, sys: &mut System, _env: &mut Environment) -> Result, Error> { + fn update( + &mut self, + mods: &mut Modifications, + sys: &mut System, + _env: &mut Environment, + ) -> Result, Error> { let elapsed = self.start.elapsed().as_secs(); - + if elapsed > WAKEUP_DURATION { return Ok(Some(State::Normal)); } - - if !mods.lighting { // if lighting controls have not been modified externally since start + + if !mods.lighting { + // if lighting controls have not been modified externally since start if sys.lights.numb_on() < 3 { sys.lights.all_on()?; } - - let bri = (BRI_PER_SECOND*(elapsed as f32)) as u8; - let ct = CT_BEGIN-(CT_PER_SECOND*(elapsed as f32)) as u16; + + let bri = (BRI_PER_SECOND * (elapsed as f32)) as u8; + let ct = CT_BEGIN - (CT_PER_SECOND * (elapsed as f32)) as u16; sys.lights.set_all_ct(bri, ct)?; //TODO map to terror error } - if !mods.mpd { // if mpd controls have not been modified externally since start + if !mods.mpd { + // if mpd controls have not been modified externally since start if !self.playing { if elapsed > MUSIC_ON { mpd::Client::connect("127.0.0.1:6600") - .and_then(|ref mut c| c.volume(MIN_VOLUME) - .and_then(|_| c.play())); //only play if the volume was set correctly + .and_then(|ref mut c| c.volume(MIN_VOLUME).and_then(|_| c.play())); + //only play if the volume was set correctly } } else { - mpd::Client::connect("127.0.0.1:6600") - .and_then(|mut c| c.volume((VOL_PER_SECOND*(elapsed-MUSIC_ON) as f32) as i8 )); + mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| { + c.volume((VOL_PER_SECOND * (elapsed - MUSIC_ON) as f32) as i8) + }); } } Ok(None) } - fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> {Ok(())} - fn state(&self) -> State {State::WakeUp } + fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> { + Ok(()) + } + fn state(&self) -> State { + State::WakeUp + } } diff --git a/src/controller/system/lamps/mod.rs b/src/controller/system/lamps/mod.rs index 4ae12c12..8cb0d6d9 100755 --- a/src/controller/system/lamps/mod.rs +++ b/src/controller/system/lamps/mod.rs @@ -3,292 +3,324 @@ extern crate serde_yaml; use philipshue::bridge; use philipshue::bridge::Bridge; +use philipshue::errors::{ + BridgeError::{DeviceIsUnreachable, LinkButtonNotPressed}, + HueError, HueErrorKind, +}; use philipshue::hue::LightCommand; -use philipshue::errors::{HueError, HueErrorKind, BridgeError::{LinkButtonNotPressed, DeviceIsUnreachable}}; -use std::thread; -use std::time::Duration; +use crate::errors::Error; +use std::collections::{BTreeMap, HashMap}; use std::fs::File; use std::path::Path; -use std::collections::{HashMap, BTreeMap}; -use crate::errors::Error; +use std::thread; +use std::time::Duration; -fn register(ip: &str) -> Result{ - for _ in 0..5 {//try 5 times to connect - match bridge::register_user(ip, "homeAutomationSys") { - Ok(recieved_login) => { - println!("Success, linked to brige"); - info!("User registered: {}, on IP: {}", &recieved_login, ip); - return Ok(recieved_login); - } - Err(HueError(HueErrorKind::BridgeError { error: LinkButtonNotPressed, .. }, _)) => { - println!("Please, press the link on the bridge. Retrying in 5 seconds"); - thread::sleep(Duration::from_secs(5)); - } - Err(e) => { - println!("Unexpected error occured: {}", e); - return Err(()); - } - } - } - return Err(()); +fn register(ip: &str) -> Result { + for _ in 0..5 { + //try 5 times to connect + match bridge::register_user(ip, "homeAutomationSys") { + Ok(recieved_login) => { + println!("Success, linked to brige"); + info!("User registered: {}, on IP: {}", &recieved_login, ip); + return Ok(recieved_login); + } + Err(HueError( + HueErrorKind::BridgeError { + error: LinkButtonNotPressed, + .. + }, + _, + )) => { + println!("Please, press the link on the bridge. Retrying in 5 seconds"); + thread::sleep(Duration::from_secs(5)); + } + Err(e) => { + println!("Unexpected error occured: {}", e); + return Err(()); + } + } + } + return Err(()); } fn find_bridge_ip() -> Result { - let mut discovered = bridge::discover()?; - if discovered.len() == 0 { - error!("No bridge found!"); - return Err(Error::Lamps(HueError::from_kind(HueErrorKind::Msg("no bridge found".into())))); - } else if discovered.len() > 1 { - error!("Found multiple hue bridges: {:?}, continueing with first one in list", discovered); - } - - Ok(discovered.pop().unwrap().into_ip()) + let mut discovered = bridge::discover()?; + if discovered.len() == 0 { + error!("No bridge found!"); + return Err(Error::Lamps(HueError::from_kind(HueErrorKind::Msg( + "no bridge found".into(), + )))); + } else if discovered.len() > 1 { + error!( + "Found multiple hue bridges: {:?}, continueing with first one in list", + discovered + ); + } + + Ok(discovered.pop().unwrap().into_ip()) } -fn saved_bridge_info() -> Result<(String, String),()> { - let path = Path::new("hueBridgeLogin"); - match File::open(&path){ - Err(e) => error!("find ip and login file, error: {}", e), - Ok(f) => { - match serde_yaml::from_reader(f){ - Ok((ip, login))=> return Ok((ip, login)), - Err(_) => error!("could not read ip and login from file"), - } - }, - } - Err(()) +fn saved_bridge_info() -> Result<(String, String), ()> { + let path = Path::new("hueBridgeLogin"); + match File::open(&path) { + Err(e) => error!("find ip and login file, error: {}", e), + Ok(f) => match serde_yaml::from_reader(f) { + Ok((ip, login)) => return Ok((ip, login)), + Err(_) => error!("could not read ip and login from file"), + }, + } + Err(()) } fn update_saved_bridge_info(bridge_ip: &str, login: &str) -> Result<(), ()> { - let path = Path::new("hueBridgeLogin"); - match File::create(&path){ - Ok(f) => if let Err(e) = serde_yaml::to_writer(f,&(bridge_ip, login)){ - error!("could not write ip and login from file, error: {}", e); - } else { return Ok(()) }, - Err(e) => { - error!("cant open ip and login file, error: {}", e); - }, - } - Err(()) + let path = Path::new("hueBridgeLogin"); + match File::create(&path) { + Ok(f) => { + if let Err(e) = serde_yaml::to_writer(f, &(bridge_ip, login)) { + error!("could not write ip and login from file, error: {}", e); + } else { + return Ok(()); + } + } + Err(e) => { + error!("cant open ip and login file, error: {}", e); + } + } + Err(()) } fn get_bridge_and_status() -> Result<(Bridge, BTreeMap), Error> { - - if let Ok((mut ip, mut login)) = saved_bridge_info(){ - let mut update_ip_or_login = false; - loop { - let bridge = Bridge::new(&ip, &login); - match bridge.get_all_lights(){ - Ok(lights_info) => { - if update_ip_or_login { - if update_saved_bridge_info(&ip, &login).is_err() { - error!("Could not save new bridge ip and login, next run will fail without user intervention") - } - } - return Ok((bridge, lights_info)); - }, - //cant find bridge on given ip - Err(HueError(HueErrorKind::BridgeError{error: DeviceIsUnreachable, ..}, _)) => { - ip = find_bridge_ip()?; - update_ip_or_login = true; - }, - //cant register as button was not pressed in time - Err(HueError(HueErrorKind::BridgeError{error: LinkButtonNotPressed, ..}, _)) => { - login = register(&ip)?; - update_ip_or_login = true; - }, - Err(e) => { - error!("Unexpected error occured: {:?}", e); - return Err(e.into()); - }, - } - } - } else { - let ip = find_bridge_ip()?; - let login = register(&ip)?; - if update_saved_bridge_info(&ip, &login).is_err() { - error!("Could not save new bridge ip and login, next run will fail without user intervention") - }; - - let bridge = Bridge::new(&ip, &login); - let lights_info = bridge.get_all_lights()?; - return Ok((bridge, lights_info)); - } + if let Ok((mut ip, mut login)) = saved_bridge_info() { + let mut update_ip_or_login = false; + loop { + let bridge = Bridge::new(&ip, &login); + match bridge.get_all_lights() { + Ok(lights_info) => { + if update_ip_or_login { + if update_saved_bridge_info(&ip, &login).is_err() { + error!("Could not save new bridge ip and login, next run will fail without user intervention") + } + } + return Ok((bridge, lights_info)); + } + //cant find bridge on given ip + Err(HueError( + HueErrorKind::BridgeError { + error: DeviceIsUnreachable, + .. + }, + _, + )) => { + ip = find_bridge_ip()?; + update_ip_or_login = true; + } + //cant register as button was not pressed in time + Err(HueError( + HueErrorKind::BridgeError { + error: LinkButtonNotPressed, + .. + }, + _, + )) => { + login = register(&ip)?; + update_ip_or_login = true; + } + Err(e) => { + error!("Unexpected error occured: {:?}", e); + return Err(e.into()); + } + } + } + } else { + let ip = find_bridge_ip()?; + let login = register(&ip)?; + if update_saved_bridge_info(&ip, &login).is_err() { + error!("Could not save new bridge ip and login, next run will fail without user intervention") + }; + + let bridge = Bridge::new(&ip, &login); + let lights_info = bridge.get_all_lights()?; + return Ok((bridge, lights_info)); + } } //adaptation from philipshue LightState that adds some //values and removes unused #[derive(Debug)] pub struct Lamp { - pub on: bool, - pub bri: u8, - pub hue: Option, - pub sat: Option, - pub xy: Option<(f32, f32)>, - pub ct: Option, - pub reachable: bool, + pub on: bool, + pub bri: u8, + pub hue: Option, + pub sat: Option, + pub xy: Option<(f32, f32)>, + pub ct: Option, + pub reachable: bool, } pub struct Lighting { - pub bridge: Bridge, - //local cache of current state (used for toggle) - pub lamps: HashMap, + pub bridge: Bridge, + //local cache of current state (used for toggle) + pub lamps: HashMap, } -impl From<&philipshue::hue::LightState> for Lamp{ - fn from(state: &philipshue::hue::LightState) -> Self { - Lamp{ - on: state.on, - bri: state.bri, - hue: state.hue, - sat: state.sat, - xy: state.xy, - ct: state.ct, - reachable: state.reachable, - } - } +impl From<&philipshue::hue::LightState> for Lamp { + fn from(state: &philipshue::hue::LightState) -> Self { + Lamp { + on: state.on, + bri: state.bri, + hue: state.hue, + sat: state.sat, + xy: state.xy, + ct: state.ct, + reachable: state.reachable, + } + } } impl Lighting { - - pub fn init() -> Result { - let (bridge, lights_info) = get_bridge_and_status()?; - let lamps: HashMap = lights_info.iter().map(|(id,light)| (*id, Lamp::from(&light.state))).collect(); - - Ok(Self {bridge, lamps}) - } - - #[allow(unused)] - pub fn print_info(&self){ - dbg!(&self.lamps); - } - - pub fn numb_on(&self) -> u8 { - self.lamps.values().map(|lamp| lamp.on as u8).sum() - } - - //how to deal with errors? - pub fn toggle(&mut self) -> Result<(),Error>{ - let numb_on: u8 = self.numb_on(); - let numb_off = self.lamps.len() as u8 - numb_on; - - //group ID 0 is a special group containing all lights known to the bridge - if numb_on > numb_off { - let command = LightCommand::off(LightCommand::default() ); - self.bridge.set_group_state(0, &command)?; - self.lamps.values_mut().for_each(|lamp| lamp.on = false); - } else { - let command = LightCommand::on(LightCommand::default() ); - self.bridge.set_group_state(0, &command)?; - self.lamps.values_mut().for_each(|lamp| lamp.on = true); - } - - Ok(()) - } - - pub fn all_off(&mut self) -> Result<(),Error> { - let command = LightCommand::off(LightCommand::default() ); - self.bridge.set_group_state(0, &command)?; - self.lamps.values_mut().for_each(|lamp| lamp.on = false); - Ok(()) - } - - pub fn all_on(&mut self) -> Result<(),Error> { - let command = LightCommand::on(LightCommand::default() ); - self.bridge.set_group_state(0, &command)?; - self.lamps.values_mut().for_each(|lamp| lamp.on = false); - Ok(()) - } - - pub fn single_off(&mut self, lamp_id: usize) -> Result<(),Error> { - let command = LightCommand::off(LightCommand::default() ); - self.bridge.set_light_state(lamp_id, &command)?; - self.lamps.get_mut(&lamp_id).unwrap().on = true; - Ok(()) - } - - #[allow(dead_code)] - pub fn single_on(&mut self, lamp_id: usize) -> Result<(),Error> { - let command = LightCommand::on(LightCommand::default() ); - self.bridge.set_light_state(lamp_id, &command)?; - self.lamps.get_mut(&lamp_id).unwrap().on = true; - Ok(()) - } - - //how to deal with errors? - pub fn set_all_ct(&mut self, bri: u8, ct: u16) -> Result<(),Error>{ - let command = LightCommand::default(); - //let command = command.on(); - let command = command.with_bri(bri); - let command = command.with_ct(ct); - self.bridge.set_group_state(0, &command)?; - self.lamps.values_mut().for_each(|lamp| {lamp.bri =bri; lamp.ct =Some(ct); lamp.on =true}); - - Ok(()) - } - - #[allow(dead_code)] - pub fn set_all_xy(&mut self, bri: u8, xy: (f32, f32)) -> Result<(),Error>{ - let command = LightCommand::default(); - let command = command.on(); - let command = command.with_bri(bri); - let command = command.with_xy(xy); - self.bridge.set_group_state(0, &command)?; - self.lamps.values_mut().for_each(|lamp| { - lamp.bri =bri; - lamp.xy = Some(xy); - lamp.on =true - }); - - Ok(()) - } - - pub fn set_all_rgb(&mut self, bri: u8, rgb: (f32,f32,f32)) -> Result<(),Error> { - let xy = xy_from_rgb(rgb); - - let command = LightCommand::default(); - let command = command.on(); - let command = command.with_bri(bri); - let command = command.with_xy(xy); - self.bridge.set_group_state(0, &command)?; - self.lamps.values_mut().for_each(|lamp| { - lamp.bri =bri; - lamp.xy = Some(xy); - lamp.on =true - }); - - Ok(()) - } - + pub fn init() -> Result { + let (bridge, lights_info) = get_bridge_and_status()?; + let lamps: HashMap = lights_info + .iter() + .map(|(id, light)| (*id, Lamp::from(&light.state))) + .collect(); + + Ok(Self { bridge, lamps }) + } + + #[allow(unused)] + pub fn print_info(&self) { + dbg!(&self.lamps); + } + + pub fn numb_on(&self) -> u8 { + self.lamps.values().map(|lamp| lamp.on as u8).sum() + } + + //how to deal with errors? + pub fn toggle(&mut self) -> Result<(), Error> { + let numb_on: u8 = self.numb_on(); + let numb_off = self.lamps.len() as u8 - numb_on; + + //group ID 0 is a special group containing all lights known to the bridge + if numb_on > numb_off { + let command = LightCommand::off(LightCommand::default()); + self.bridge.set_group_state(0, &command)?; + self.lamps.values_mut().for_each(|lamp| lamp.on = false); + } else { + let command = LightCommand::on(LightCommand::default()); + self.bridge.set_group_state(0, &command)?; + self.lamps.values_mut().for_each(|lamp| lamp.on = true); + } + + Ok(()) + } + + pub fn all_off(&mut self) -> Result<(), Error> { + let command = LightCommand::off(LightCommand::default()); + self.bridge.set_group_state(0, &command)?; + self.lamps.values_mut().for_each(|lamp| lamp.on = false); + Ok(()) + } + + pub fn all_on(&mut self) -> Result<(), Error> { + let command = LightCommand::on(LightCommand::default()); + self.bridge.set_group_state(0, &command)?; + self.lamps.values_mut().for_each(|lamp| lamp.on = false); + Ok(()) + } + + pub fn single_off(&mut self, lamp_id: usize) -> Result<(), Error> { + let command = LightCommand::off(LightCommand::default()); + self.bridge.set_light_state(lamp_id, &command)?; + self.lamps.get_mut(&lamp_id).unwrap().on = true; + Ok(()) + } + + #[allow(dead_code)] + pub fn single_on(&mut self, lamp_id: usize) -> Result<(), Error> { + let command = LightCommand::on(LightCommand::default()); + self.bridge.set_light_state(lamp_id, &command)?; + self.lamps.get_mut(&lamp_id).unwrap().on = true; + Ok(()) + } + + //how to deal with errors? + pub fn set_all_ct(&mut self, bri: u8, ct: u16) -> Result<(), Error> { + let command = LightCommand::default(); + //let command = command.on(); + let command = command.with_bri(bri); + let command = command.with_ct(ct); + self.bridge.set_group_state(0, &command)?; + self.lamps.values_mut().for_each(|lamp| { + lamp.bri = bri; + lamp.ct = Some(ct); + lamp.on = true + }); + + Ok(()) + } + + #[allow(dead_code)] + pub fn set_all_xy(&mut self, bri: u8, xy: (f32, f32)) -> Result<(), Error> { + let command = LightCommand::default(); + let command = command.on(); + let command = command.with_bri(bri); + let command = command.with_xy(xy); + self.bridge.set_group_state(0, &command)?; + self.lamps.values_mut().for_each(|lamp| { + lamp.bri = bri; + lamp.xy = Some(xy); + lamp.on = true + }); + + Ok(()) + } + + pub fn set_all_rgb(&mut self, bri: u8, rgb: (f32, f32, f32)) -> Result<(), Error> { + let xy = xy_from_rgb(rgb); + + let command = LightCommand::default(); + let command = command.on(); + let command = command.with_bri(bri); + let command = command.with_xy(xy); + self.bridge.set_group_state(0, &command)?; + self.lamps.values_mut().for_each(|lamp| { + lamp.bri = bri; + lamp.xy = Some(xy); + lamp.on = true + }); + + Ok(()) + } } fn gamma_correct(mut x: f32) -> f32 { - if x > 0.04045 { - x = (x + 0.055)/(1f32 + 0.055); - x.powf(2.4) - } else { - x / 12.92 - } + if x > 0.04045 { + x = (x + 0.055) / (1f32 + 0.055); + x.powf(2.4) + } else { + x / 12.92 + } } //r,g,b between 0 and one //https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d -fn xy_from_rgb(rgb: (f32,f32,f32)) -> (f32, f32) { +fn xy_from_rgb(rgb: (f32, f32, f32)) -> (f32, f32) { + let (r, g, b) = rgb; + let r = gamma_correct(r); + let g = gamma_correct(g); + let b = gamma_correct(b); - let (r,g,b) = rgb; - let r = gamma_correct(r); - let g = gamma_correct(g); - let b = gamma_correct(b); + let xyz_x = r * 0.649926 + g * 0.103455 + b * 0.197109; + let xyz_y = r * 0.234327 + g * 0.743075 + b * 0.022598; + let xyz_z = g * 0.053077 + b * 1.035763; - let xyz_x = r * 0.649926 + g * 0.103455 + b * 0.197109; - let xyz_y = r * 0.234327 + g * 0.743075 + b * 0.022598; - let xyz_z = g * 0.053077 + b * 1.035763; + let hue_x = xyz_x / (xyz_x + xyz_y + xyz_z); + let hue_y = xyz_y / (xyz_x + xyz_y + xyz_z); - let hue_x = xyz_x/(xyz_x+xyz_y+xyz_z); - let hue_y = xyz_y/(xyz_x+xyz_y+xyz_z); + //TODO color gamut triangle stuff for finding closest valid value - //TODO color gamut triangle stuff for finding closest valid value - - (hue_x, hue_y) -} \ No newline at end of file + (hue_x, hue_y) +} diff --git a/src/controller/system/mod.rs b/src/controller/system/mod.rs index a5e6158a..ff31482d 100755 --- a/src/controller/system/mod.rs +++ b/src/controller/system/mod.rs @@ -1,3 +1,3 @@ mod lamps; pub mod mpd_control; -pub use lamps::Lighting; \ No newline at end of file +pub use lamps::Lighting; diff --git a/src/controller/system/mpd_control.rs b/src/controller/system/mpd_control.rs index 16b006c3..fd200b42 100755 --- a/src/controller/system/mpd_control.rs +++ b/src/controller/system/mpd_control.rs @@ -4,16 +4,24 @@ use rand::Rng; use crate::input::mpd_status::MpdStatus; -pub fn add_from_playlist(mpd: &mut mpd::Client, name: &str, minimal_play_time: Duration, maximal_play_time: Duration) -> Result<(),Error>{ - +pub fn add_from_playlist( + mpd: &mut mpd::Client, + name: &str, + minimal_play_time: Duration, + maximal_play_time: Duration, +) -> Result<(), Error> { let mut rng = rand::thread_rng(); let songs = mpd.playlist(name); - let mut songs = match songs{ //report all errors except non existing playlist + let mut songs = match songs { + //report all errors except non existing playlist Ok(songs) => songs, Err(error) => match error { mpd::error::Error::Server(serv_error) => match serv_error.code { - mpd::error::ErrorCode::NoExist => {warn!("could not find playlist: {}", name); return Ok(())}, + mpd::error::ErrorCode::NoExist => { + warn!("could not find playlist: {}", name); + return Ok(()); + } _ => return Err(mpd::error::Error::Server(serv_error).into()), }, _ => return Err(error.into()), @@ -22,8 +30,8 @@ pub fn add_from_playlist(mpd: &mut mpd::Client, name: &str, minimal_play_time: D let mut time = Duration::seconds(0); //add random songs until the playtime is larger then the minimum - while time < minimal_play_time && songs.len()>1 { - let idx = rng.gen_range(0, songs.len()-1); + while time < minimal_play_time && songs.len() > 1 { + let idx = rng.gen_range(0, songs.len() - 1); let song = songs.remove(idx); if let Some(duration) = song.duration { if time + duration < maximal_play_time { @@ -35,50 +43,53 @@ pub fn add_from_playlist(mpd: &mut mpd::Client, name: &str, minimal_play_time: D Ok(()) } -pub fn increase_volume(mpd_status: &mut MpdStatus) -> Result<(),Error>{ +pub fn increase_volume(mpd_status: &mut MpdStatus) -> Result<(), Error> { const VOLUME_INCREMENT: i8 = 5; let mut client = mpd::Client::connect("127.0.0.1:6600")?; let current_volume = mpd_status.get_volume(); - if current_volume + VOLUME_INCREMENT > 100 {return Ok(()); } + if current_volume + VOLUME_INCREMENT > 100 { + return Ok(()); + } - client.volume(current_volume+VOLUME_INCREMENT)?; + client.volume(current_volume + VOLUME_INCREMENT)?; Ok(()) } -pub fn decrease_volume(mpd_status: &mut MpdStatus) -> Result<(),Error>{ +pub fn decrease_volume(mpd_status: &mut MpdStatus) -> Result<(), Error> { const VOLUME_INCREMENT: i8 = 5; let mut client = mpd::Client::connect("127.0.0.1:6600")?; let current_volume = mpd_status.get_volume(); - if current_volume - VOLUME_INCREMENT < 0 {return Ok(()); } + if current_volume - VOLUME_INCREMENT < 0 { + return Ok(()); + } - client.volume(current_volume-VOLUME_INCREMENT)?; + client.volume(current_volume - VOLUME_INCREMENT)?; Ok(()) } -pub fn set_volume(volume: i8) -> Result<(),Error>{ +pub fn set_volume(volume: i8) -> Result<(), Error> { let mut client = mpd::Client::connect("127.0.0.1:6600")?; client.volume(volume)?; Ok(()) } - -pub fn next_song() -> Result<(),Error>{ +pub fn next_song() -> Result<(), Error> { let mut client = mpd::Client::connect("127.0.0.1:6600")?; client.next()?; Ok(()) } -pub fn prev_song() -> Result<(),Error>{ +pub fn prev_song() -> Result<(), Error> { let mut client = mpd::Client::connect("127.0.0.1:6600")?; client.prev()?; Ok(()) } -pub fn toggle_playback(mpd_status: &mut MpdStatus) -> Result<(), Error>{ +pub fn toggle_playback(mpd_status: &mut MpdStatus) -> Result<(), Error> { let mut client = mpd::Client::connect("127.0.0.1:6600")?; - + match mpd_status.is_playing() { mpd::status::State::Stop => client.play()?, mpd::status::State::Pause => client.toggle_pause()?, @@ -87,17 +98,17 @@ pub fn toggle_playback(mpd_status: &mut MpdStatus) -> Result<(), Error>{ Ok(()) } -pub fn pause() -> Result<(), Error>{ +pub fn pause() -> Result<(), Error> { let mut client = mpd::Client::connect("127.0.0.1:6600")?; client.pause(true)?; Ok(()) } -pub fn save_current_playlist(mpd: &mut mpd::Client) -> Result<(),Error>{ +pub fn save_current_playlist(mpd: &mut mpd::Client) -> Result<(), Error> { dbg!(); mpd.pl_remove("temp")?; dbg!(); mpd.save("temp")?; dbg!(); Ok(()) -} \ No newline at end of file +} diff --git a/src/errors.rs b/src/errors.rs index 88e58eae..af05706e 100755 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,7 +1,7 @@ use fern::colors::{Color, ColoredLevelConfig}; -use crate::input::youtube_downloader; use crate::input::web_api::server; +use crate::input::youtube_downloader; #[derive(Debug)] pub enum Error { @@ -56,7 +56,11 @@ impl From for Error { impl From> for Error { fn from(error: retry::Error) -> Self { match error { - retry::Error::Operation{error, total_delay: _total_delay, tries: _tries} => error, + retry::Error::Operation { + error, + total_delay: _total_delay, + tries: _tries, + } => error, retry::Error::Internal(error_str) => Error::RetryLogic(error_str), } } @@ -65,7 +69,11 @@ impl From> for Error { impl From> for Error { fn from(error: retry::Error) -> Self { match error { - retry::Error::Operation{error, total_delay: _total_delay, tries: _tries} => Error::Mpd(error), + retry::Error::Operation { + error, + total_delay: _total_delay, + tries: _tries, + } => Error::Mpd(error), retry::Error::Internal(error_str) => Error::RetryLogic(error_str), } } @@ -96,55 +104,51 @@ impl From for Error { } pub fn setup_logging(verbosity: u8) -> Result<(), fern::InitError> { - let mut base_config = fern::Dispatch::new(); - let colors = ColoredLevelConfig::new() - .info(Color::Green) - .debug(Color::Yellow) - .warn(Color::Magenta); - - base_config = match verbosity { - 0 => - base_config - .level(log::LevelFilter::Error), - 1 => - base_config - .level(log::LevelFilter::Warn), - 2 => - base_config.level(log::LevelFilter::Info) - .level_for("actix-web", log::LevelFilter::Warn), - 3 => - base_config.level(log::LevelFilter::Trace), - 4 => - base_config.level(log::LevelFilter::Error), - _4_or_more => - base_config.level(log::LevelFilter::Warn), - }; - - // Separate file config so we can include year, month and day in file logs - let file_config = fern::Dispatch::new() - .format(|out, message, record| { - out.finish(format_args!( - "{}[{}][{}] {}", - chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"), - record.target(), - record.level(), - message - )) - }) - .chain(fern::log_file("program.log")?); - - let stdout_config = fern::Dispatch::new() - .format(move |out, message, record| { - out.finish(format_args!( - "[{}][{}][{}] {}", - chrono::Local::now().format("%H:%M"), - record.target(), - colors.color(record.level()), - message - )) - }) - .chain(std::io::stdout()); - - base_config.chain(file_config).chain(stdout_config).apply()?; - Ok(()) -} \ No newline at end of file + let mut base_config = fern::Dispatch::new(); + let colors = ColoredLevelConfig::new() + .info(Color::Green) + .debug(Color::Yellow) + .warn(Color::Magenta); + + base_config = match verbosity { + 0 => base_config.level(log::LevelFilter::Error), + 1 => base_config.level(log::LevelFilter::Warn), + 2 => base_config + .level(log::LevelFilter::Info) + .level_for("actix-web", log::LevelFilter::Warn), + 3 => base_config.level(log::LevelFilter::Trace), + 4 => base_config.level(log::LevelFilter::Error), + _4_or_more => base_config.level(log::LevelFilter::Warn), + }; + + // Separate file config so we can include year, month and day in file logs + let file_config = fern::Dispatch::new() + .format(|out, message, record| { + out.finish(format_args!( + "{}[{}][{}] {}", + chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"), + record.target(), + record.level(), + message + )) + }) + .chain(fern::log_file("program.log")?); + + let stdout_config = fern::Dispatch::new() + .format(move |out, message, record| { + out.finish(format_args!( + "[{}][{}][{}] {}", + chrono::Local::now().format("%H:%M"), + record.target(), + colors.color(record.level()), + message + )) + }) + .chain(std::io::stdout()); + + base_config + .chain(file_config) + .chain(stdout_config) + .apply()?; + Ok(()) +} diff --git a/src/input/alarms.rs b/src/input/alarms.rs index 25817b6d..c4fa0bc1 100755 --- a/src/input/alarms.rs +++ b/src/input/alarms.rs @@ -1,14 +1,14 @@ use crossbeam_channel; -use std::thread; use std::ops::Sub; +use std::thread; -use chrono::{DateTime, Utc, self}; -use sled; use byteorder::{BigEndian, ReadBytesExt}; -use serde::{Serialize, Deserialize}; +use chrono::{self, DateTime, Utc}; +use serde::{Deserialize, Serialize}; +use sled; -use crate::controller::Event; use crate::controller::Command; +use crate::controller::Event; use crate::errors::Error; //TODO, what to do on multiple alarms at the same time? @@ -40,8 +40,11 @@ pub struct Alarm { } impl Alarm { - pub fn from(time: DateTime, action: impl Into, expiration: Option) - -> Self { + pub fn from( + time: DateTime, + action: impl Into, + expiration: Option, + ) -> Self { Alarm { time, action: action.into(), @@ -52,14 +55,14 @@ impl Alarm { impl Sub for Alarm { type Output = chrono::Duration; - + fn sub(self, other: Alarm) -> chrono::Duration { self.time - other.time } } impl Sub> for &Alarm { type Output = chrono::Duration; - + fn sub(self, other: chrono::DateTime) -> chrono::Duration { self.time - other } @@ -76,8 +79,12 @@ pub struct AlarmList { db: sled::Tree, } -fn waker(mut alarm_list: AlarmList, event_tx: crossbeam_channel::Sender, waker_rx: crossbeam_channel::Receiver<()>) { - loop { +fn waker( + mut alarm_list: AlarmList, + event_tx: crossbeam_channel::Sender, + waker_rx: crossbeam_channel::Receiver<()>, +) { + loop { //This can fail #TODO make sure an non waking error alarm is send to the user if let Some((id, current_alarm)) = alarm_list.get_next() { let now = Utc::now(); @@ -89,28 +96,32 @@ fn waker(mut alarm_list: AlarmList, event_tx: crossbeam_channel::Sender, continue; //alarm to far in the past, skip and get next } } - let timeout = timeout.to_std() + let timeout = timeout + .to_std() .unwrap_or(std::time::Duration::from_secs(0)); info!("next alarm is in: {} seconds", timeout.as_secs()); //do we sound the an alarm or should we add or remove one? match waker_rx.recv_timeout(timeout) { //do not set off alarm - Ok(_) => {dbg!(); ()},//should recheck if "current alarm" is still the right one as we removed one - - - Err(error) => match error {//should the alarm go off or should we stop? + Ok(_) => { + dbg!(); + () + } //should recheck if "current alarm" is still the right one as we removed one + + Err(error) => match error { + //should the alarm go off or should we stop? crossbeam_channel::RecvTimeoutError::Timeout => { - if let Err(error) = event_tx.send(Event::Alarm){ + if let Err(error) = event_tx.send(Event::Alarm) { error!("could not set off alarm: {:?}", error); - }; //set - //remove alarm from memory and file + }; //set + //remove alarm from memory and file alarm_list.remove_alarm(id).unwrap(); continue; //get next alarm } //we should stop, end the thread by returning - crossbeam_channel::RecvTimeoutError::Disconnected => return, - } + crossbeam_channel::RecvTimeoutError::Disconnected => return, + }, } } else { //no alarm to wait on, wait for instructions @@ -118,31 +129,33 @@ fn waker(mut alarm_list: AlarmList, event_tx: crossbeam_channel::Sender, loop { //A message through the mpsc signals an alarm has been added match waker_rx.recv() { - Ok(_) => break, //alarms were added or remove, go back and start waiting on it + Ok(_) => break, //alarms were added or remove, go back and start waiting on it Err(_) => return, //cant have timed out thus program should exit } } } - } } impl Alarms { - - pub fn setup(event_tx: crossbeam_channel::Sender, db: sled::Db) -> Result<(Self, thread::JoinHandle<()>), Error> { - - let alarm_db = AlarmList { db: db.open_tree("alarms")? }; + pub fn setup( + event_tx: crossbeam_channel::Sender, + db: sled::Db, + ) -> Result<(Self, thread::JoinHandle<()>), Error> { + let alarm_db = AlarmList { + db: db.open_tree("alarms")?, + }; let (waker_tx, waker_rx) = crossbeam_channel::unbounded(); let waker_db_copy = alarm_db.clone(); - let waker_thread = thread::spawn(move || { waker(waker_db_copy, event_tx, waker_rx)}); + let waker_thread = thread::spawn(move || waker(waker_db_copy, event_tx, waker_rx)); - Ok((Self {alarm_db, waker_tx}, waker_thread)) + Ok((Self { alarm_db, waker_tx }, waker_thread)) } // we decrease the time till the alarm until there is a place in the database // as only one alarm can fire at the time, after an alarm gets a timeslot it is never changed - pub async fn add_alarm(&self, to_add: Alarm) -> Result<(), Error> { + pub async fn add_alarm(&self, to_add: Alarm) -> Result<(), Error> { self.alarm_db.add_alarm(to_add).await?; //signal waker to update its next alarm self.waker_tx.send(())?; @@ -163,7 +176,7 @@ impl Alarms { for (key, alarm) in alarms.filter_map(Result::ok) { let alarm = bincode::deserialize(&alarm).unwrap(); let key = key.as_ref().read_u64::().unwrap(); - list.push((key,alarm)); + list.push((key, alarm)); } list } @@ -181,9 +194,11 @@ impl AlarmList { //if there is already an alarm schedualed, postpone this one until there is a spot free //self.db.cas(&[1], None as Option<&[u8]>, Some(&[10]) //TODO check how this works and expand sled documentation for fail cases - while let Err(_old_event) = self - .db - .compare_and_swap(×tamp_array, None as Option<&[u8]>, Some(alarm.clone()))? { + while let Err(_old_event) = self.db.compare_and_swap( + ×tamp_array, + None as Option<&[u8]>, + Some(alarm.clone()), + )? { //cas unique creation timestamp -= 1; timestamp_array = timestamp.to_be_bytes(); @@ -192,14 +207,15 @@ impl AlarmList { Ok(()) } pub fn remove_alarm(&self, to_remove: u64) -> Result, Error> { - Ok(self.db + Ok(self + .db .remove(to_remove.to_be_bytes())? .map(|k| bincode::deserialize::(&k).unwrap())) } /// calculate time to the earliest alarm, remove it from the list if the current time is later /// then the alarm - fn get_next(&mut self) -> Option<(u64,Alarm)> { + fn get_next(&mut self) -> Option<(u64, Alarm)> { //get earliest alarm time in db match self.db.get_gt(0u64.to_be_bytes()) { Ok(entry) => { @@ -207,15 +223,15 @@ impl AlarmList { let (id, alarm) = entry; let id = id.as_ref().read_u64::().unwrap(); let alarm = bincode::deserialize(&alarm).unwrap(); - Some((id,alarm)) - } else { + Some((id, alarm)) + } else { None } - }, + } Err(error) => { - error!("Could not retrieve next alarm: {:?}",error); + error!("Could not retrieve next alarm: {:?}", error); None } } } -} \ No newline at end of file +} diff --git a/src/input/bot/mod.rs b/src/input/bot/mod.rs index 50c97a52..d79e0617 100644 --- a/src/input/bot/mod.rs +++ b/src/input/bot/mod.rs @@ -1,233 +1,240 @@ -use actix_web::web::{HttpResponse, Data, Bytes}; -use actix_web::http::{StatusCode}; +use actix_web::http::StatusCode; +use actix_web::web::{Bytes, Data, HttpResponse}; +use log::{error, info, warn}; use reqwest; -use log::{warn, info ,error}; use serde_json; -use telegram_bot::types::update::Update; -use telegram_bot::types::update::UpdateKind; -use telegram_bot::types::message::MessageKind; -use telegram_bot::types::message::Message; use telegram_bot::types::callback_query::CallbackQuery; +use telegram_bot::types::message::Message; +use telegram_bot::types::message::MessageKind; use telegram_bot::types::refs::{ChatId, MessageId, UserId}; +use telegram_bot::types::update::Update; +use telegram_bot::types::update::UpdateKind; -use crate::input::youtube_downloader::{self,FeedbackChannel}; -use crate::input::web_api::server::{State}; +use crate::input::web_api::server::State; +use crate::input::youtube_downloader::{self, FeedbackChannel}; pub mod youtube_dl; use youtube_dl::TelegramFeedback; mod set_alarm; #[derive(Debug)] -pub enum Error{ - HttpClientError(reqwest::Error), - CouldNotSetWebhook, - InvalidServerResponse(reqwest::Response), - UnhandledUpdateKind, - UnknownCommand(String), - SongDownloadError(youtube_downloader::Error), - Unauthorized(ChatId), - SetAlarmError(set_alarm::Error), +pub enum Error { + HttpClientError(reqwest::Error), + CouldNotSetWebhook, + InvalidServerResponse(reqwest::Response), + UnhandledUpdateKind, + UnknownCommand(String), + SongDownloadError(youtube_downloader::Error), + Unauthorized(ChatId), + SetAlarmError(set_alarm::Error), } impl From for Error { - fn from(error: reqwest::Error) -> Self { - Error::HttpClientError(error) - } + fn from(error: reqwest::Error) -> Self { + Error::HttpClientError(error) + } } impl From for Error { - fn from(e: youtube_downloader::Error) -> Self { - Error::SongDownloadError(e) - } + fn from(e: youtube_downloader::Error) -> Self { + Error::SongDownloadError(e) + } } impl From for Error { - fn from(err: set_alarm::Error) -> Self { - Error::SetAlarmError(err) - } + fn from(err: set_alarm::Error) -> Self { + Error::SetAlarmError(err) + } } -fn to_string_and_ids(message: Message) --> Result<(String, ChatId, UserId, MessageId),Error>{ - - let chat_id = message.chat.id(); - let user_id = message.from.id; - let message_id = message.id; - - if let MessageKind::Text{data, entities:_} = message.kind { - return Ok((data, chat_id, user_id, message_id)); - } else { - warn!("unhandled message kind"); - return Err(Error::UnhandledUpdateKind); - } +fn to_string_and_ids(message: Message) -> Result<(String, ChatId, UserId, MessageId), Error> { + let chat_id = message.chat.id(); + let user_id = message.from.id; + let message_id = message.id; + + if let MessageKind::Text { data, entities: _ } = message.kind { + return Ok((data, chat_id, user_id, message_id)); + } else { + warn!("unhandled message kind"); + return Err(Error::UnhandledUpdateKind); + } } -async fn handle_command(text: String, chat_id: ChatId, message_id: MessageId, - userid: UserId, state: &State) -> Result<(), Error>{ - - if !state.valid_ids.contains(&userid){ - return Err(Error::Unauthorized(chat_id)); - } - - let token = &state.bot_token; - if text.contains("https://") || text.contains("http://") { - let fb = TelegramFeedback{chat_id, message_id}; - state.youtube_dl.add_song_to_queue(text, - FeedbackChannel::Telegram(fb)).await?; - return Ok(()); - } - - let mut split = text.split_whitespace(); +async fn handle_command( + text: String, + chat_id: ChatId, + message_id: MessageId, + userid: UserId, + state: &State, +) -> Result<(), Error> { + if !state.valid_ids.contains(&userid) { + return Err(Error::Unauthorized(chat_id)); + } + + let token = &state.bot_token; + if text.contains("https://") || text.contains("http://") { + let fb = TelegramFeedback { + chat_id, + message_id, + }; + state + .youtube_dl + .add_song_to_queue(text, FeedbackChannel::Telegram(fb)) + .await?; + return Ok(()); + } + + let mut split = text.split_whitespace(); let command = split.next().unwrap(); match command { "/test" => { - send_text(chat_id, token, "hi").await?; - } - "/alarm" => { - set_alarm::handle(chat_id, token, split, state).await?; - } + send_text(chat_id, token, "hi").await?; + } + "/alarm" => { + set_alarm::handle(chat_id, token, split, state).await?; + } &_ => { - warn!("no known command or alias: {:?}", &command); - Err(Error::UnknownCommand(command.to_owned()))?; - } + warn!("no known command or alias: {:?}", &command); + Err(Error::UnknownCommand(command.to_owned()))?; + } } - - return Ok(()); + + return Ok(()); } async fn handle_callback(callback: CallbackQuery, state: &State) { - - if !state.valid_ids.contains(&callback.from.id){ - warn!("Unauthorized callback, userid: {}", callback.from.id); - return; //no need for error handling, just drop callback - } + if !state.valid_ids.contains(&callback.from.id) { + warn!("Unauthorized callback, userid: {}", callback.from.id); + return; //no need for error handling, just drop callback + } if callback.data.is_none() { debug!("no data in callback"); return; //not allowed, drop callback } let data = callback.data.as_ref().unwrap(); - let header = data.split_terminator(":").next(); - let res = match header { - Some("ytdl") => { - youtube_dl::handle_callback(data, state).await - } - _ => { - warn!("unhandled callback, data: {}\nfull_callback: {:?}", - data, callback); - Ok(()) //user need not be warned as user is dev - }, - }; - if let Err(e) = res { - error!("ran into error handling callback: {:?}", e); - } + let header = data.split_terminator(":").next(); + let res = match header { + Some("ytdl") => youtube_dl::handle_callback(data, state).await, + _ => { + warn!( + "unhandled callback, data: {}\nfull_callback: {:?}", + data, callback + ); + Ok(()) //user need not be warned as user is dev + } + }; + if let Err(e) = res { + error!("ran into error handling callback: {:?}", e); + } } const INT_ERR_TEXT: &str = "apologies, an internal error happend this has been reported and will be fixed as soon as possible"; const UNHANDLED: &str = "sorry I can not understand your input"; async fn handle_error(error: Error, chat_id: ChatId, token: &str) { - let error_message = match error { - Error::UnknownCommand(input) => - format!("Unknown command: {}", input), - Error::HttpClientError(err) => { - error!("Internal error in http client: {}", err); - String::from(INT_ERR_TEXT)}, - Error::InvalidServerResponse(resp) => { - error!("Incorrect bot api response {:?}", resp); - String::from(INT_ERR_TEXT)}, - Error::SongDownloadError(e) => { - error!("song download error {:?}", e); - String::from("Could not download song due to critical internal error")} - Error::SetAlarmError(e) => { - error!("could not set alarm {:?}", e); - String::from("Could not set alarm")} - Error::Unauthorized(chat_id) => { - format!("You are not authorized to use this bot, if you \ + let error_message = match error { + Error::UnknownCommand(input) => format!("Unknown command: {}", input), + Error::HttpClientError(err) => { + error!("Internal error in http client: {}", err); + String::from(INT_ERR_TEXT) + } + Error::InvalidServerResponse(resp) => { + error!("Incorrect bot api response {:?}", resp); + String::from(INT_ERR_TEXT) + } + Error::SongDownloadError(e) => { + error!("song download error {:?}", e); + String::from("Could not download song due to critical internal error") + } + Error::SetAlarmError(e) => { + error!("could not set alarm {:?}", e); + String::from("Could not set alarm") + } + Error::Unauthorized(chat_id) => format!( + "You are not authorized to use this bot, if you \ believe this is a mistake ask for your telegram chat id \ - {} to be added", chat_id) - } - - Error::UnhandledUpdateKind => { - String::from(UNHANDLED)} - Error::CouldNotSetWebhook => unreachable!(), - }; - if let Err(error) = send_text(chat_id, token, error_message).await{ - error!("Could not send text reply to user: {:?}", error); - } + {} to be added", + chat_id + ), + + Error::UnhandledUpdateKind => String::from(UNHANDLED), + Error::CouldNotSetWebhook => unreachable!(), + }; + if let Err(error) = send_text(chat_id, token, error_message).await { + error!("Could not send text reply to user: {:?}", error); + } } -async fn handle(update: Update, state: State){//TODO change to ref - let token = &state.bot_token; - match update.kind { - UpdateKind::Message(messg) => { - if let Ok((text, chat_id, user_id, message_id)) = to_string_and_ids(messg){ - if let Err(error) = handle_command(text, chat_id, - message_id, user_id, &state).await{ - handle_error(error, chat_id, token).await; - } - } - } - UpdateKind::CallbackQuery(callback) => { - //let chat_id = callback.message.chat.id(); - handle_callback(callback, &state).await; - - } - _ => { - warn!("unhandled update from telegram: {:?}", update); - } - } +async fn handle(update: Update, state: State) { + //TODO change to ref + let token = &state.bot_token; + match update.kind { + UpdateKind::Message(messg) => { + if let Ok((text, chat_id, user_id, message_id)) = to_string_and_ids(messg) { + if let Err(error) = handle_command(text, chat_id, message_id, user_id, &state).await + { + handle_error(error, chat_id, token).await; + } + } + } + UpdateKind::CallbackQuery(callback) => { + //let chat_id = callback.message.chat.id(); + handle_callback(callback, &state).await; + } + _ => { + warn!("unhandled update from telegram: {:?}", update); + } + } } -pub async fn handle_webhook(state: Data, raw_update: Bytes) - -> HttpResponse { - let update: Update = serde_json::from_slice(&raw_update.to_vec()).unwrap(); - let state_cpy = state.get_ref().clone(); - handle(update, state_cpy).await; +pub async fn handle_webhook(state: Data, raw_update: Bytes) -> HttpResponse { + let update: Update = serde_json::from_slice(&raw_update.to_vec()).unwrap(); + let state_cpy = state.get_ref().clone(); + handle(update, state_cpy).await; - HttpResponse::Ok() - .status(StatusCode::OK) - .body("{}") + HttpResponse::Ok().status(StatusCode::OK).body("{}") } -pub async fn send_text>(chat_id: ChatId, token: &str, text: T) - -> Result<(), Error>{//add as arg generic ToChatRef (should get from Update) - //TODO create a SendMessage, serialise it (use member function serialize) - //then use the HttpRequest fields, (url, method, and body) to send to telegram - let url = format!("https://api.telegram.org/bot{}/sendMessage", token); - let form = reqwest::multipart::Form::new() - .text("chat_id", chat_id.to_string()) - .text("text", text.into()); - - let client = reqwest::Client::new(); - let resp = client.post(&url) - .multipart(form).send().await?; - //https://stackoverflow.com/questions/57540455/error-blockingclientinfuturecontext-when-trying-to-make-a-request-from-within - - if resp.status() != reqwest::StatusCode::OK { - Err(Error::InvalidServerResponse(resp)) - } else { - info!("send message"); - Ok(()) - } +pub async fn send_text>( + chat_id: ChatId, + token: &str, + text: T, +) -> Result<(), Error> { + //add as arg generic ToChatRef (should get from Update) + //TODO create a SendMessage, serialise it (use member function serialize) + //then use the HttpRequest fields, (url, method, and body) to send to telegram + let url = format!("https://api.telegram.org/bot{}/sendMessage", token); + let form = reqwest::multipart::Form::new() + .text("chat_id", chat_id.to_string()) + .text("text", text.into()); + + let client = reqwest::Client::new(); + let resp = client.post(&url).multipart(form).send().await?; + //https://stackoverflow.com/questions/57540455/error-blockingclientinfuturecontext-when-trying-to-make-a-request-from-within + + if resp.status() != reqwest::StatusCode::OK { + Err(Error::InvalidServerResponse(resp)) + } else { + info!("send message"); + Ok(()) + } } //Ports currently supported for Webhooks: 443, 80, 88, 8443. pub async fn set_webhook(domain: &str, token: &str, port: u16) -> Result<(), Error> { - let url = format!("https://api.telegram.org/bot{}/setWebhook", token); - let webhook_url = format!("{}:{}/{}",domain, port, token); - - let params = [("url", &webhook_url)]; - let client = reqwest::Client::new(); - let res = client.post(url.as_str()) - .form(¶ms) - .send().await?; - - if res.status() != reqwest::StatusCode::OK { - Err(Error::CouldNotSetWebhook) - } else { - info!("set webhook to: {}", webhook_url); - Ok(()) - } + let url = format!("https://api.telegram.org/bot{}/setWebhook", token); + let webhook_url = format!("{}:{}/{}", domain, port, token); + + let params = [("url", &webhook_url)]; + let client = reqwest::Client::new(); + let res = client.post(url.as_str()).form(¶ms).send().await?; + + if res.status() != reqwest::StatusCode::OK { + Err(Error::CouldNotSetWebhook) + } else { + info!("set webhook to: {}", webhook_url); + Ok(()) + } } diff --git a/src/input/bot/set_alarm.rs b/src/input/bot/set_alarm.rs index ce0b40d8..224e1c82 100644 --- a/src/input/bot/set_alarm.rs +++ b/src/input/bot/set_alarm.rs @@ -1,11 +1,11 @@ -use telegram_bot::types::refs::ChatId; -use crate::input::web_api::server::State; -use crate::input::alarms::Alarm; -use crate::controller::Event; use super::send_text; -use chrono::{Local, Utc}; -use chrono::Timelike; +use crate::controller::Event; +use crate::input::alarms::Alarm; +use crate::input::web_api::server::State; use chrono::Duration; +use chrono::Timelike; +use chrono::{Local, Utc}; +use telegram_bot::types::refs::ChatId; #[derive(Debug)] pub enum Error { @@ -19,87 +19,96 @@ pub enum Error { NoAlarmId, } -pub async fn handle<'a>(chat_id: ChatId, token: &str, mut args: std::str::SplitWhitespace<'a>, state: &State) - -> Result<(),Error> { - +pub async fn handle<'a>( + chat_id: ChatId, + token: &str, + mut args: std::str::SplitWhitespace<'a>, + state: &State, +) -> Result<(), Error> { let command = args.next().ok_or(Error::NoArguments)?; dbg!(command); match command { - "list" => { - list_alarm(chat_id, token, state).await? - } - "add" => { - add_alarm(chat_id, token, args, state).await? - } - "remove" => { - remove_alarm(chat_id, token, args, state).await? - } - &_ => Err(Error::InvalidOption)? + "list" => list_alarm(chat_id, token, state).await?, + "add" => add_alarm(chat_id, token, args, state).await?, + "remove" => remove_alarm(chat_id, token, args, state).await?, + &_ => Err(Error::InvalidOption)?, } Ok(()) } -pub async fn add_alarm<'a>(chat_id: ChatId, token: &str, mut args: std::str::SplitWhitespace<'a>, state: &State) - -> Result<(),Error> { +pub async fn add_alarm<'a>( + chat_id: ChatId, + token: &str, + mut args: std::str::SplitWhitespace<'a>, + state: &State, +) -> Result<(), Error> { let time = args.next().ok_or(Error::NoTimeArgument)?; //assumes hh:mm let mut time = time.split(':'); - let hour = time.next() + let hour = time + .next() .ok_or(Error::WrongTimeFormat)? .parse::() .map_err(|_| Error::InvalidHourArgument)?; - let min = time.next() + let min = time + .next() .ok_or(Error::WrongTimeFormat)? .parse::() .map_err(|_| Error::InvalidHourArgument)?; - - if hour > 24 {return Err(Error::InvalidHourArgument);} - if min > 60 {return Err(Error::InvalidMinuteArgument);} + + if hour > 24 { + return Err(Error::InvalidHourArgument); + } + if min > 60 { + return Err(Error::InvalidMinuteArgument); + } //let now = Amsterdam::now(); let now = Local::now(); //let now = Amsterdam.ymd(2016, 5, 10).and_hms(12, 0, 0); //let now = dt.with_timezone - let alarm_sec_after_midnight = hour*3600+min*60; - let till_alarm = if alarm_sec_after_midnight < now.num_seconds_from_midnight(){ - let seconds_left_in_day = 3600*24 - now.num_seconds_from_midnight(); + let alarm_sec_after_midnight = hour * 3600 + min * 60; + let till_alarm = if alarm_sec_after_midnight < now.num_seconds_from_midnight() { + let seconds_left_in_day = 3600 * 24 - now.num_seconds_from_midnight(); Duration::seconds(seconds_left_in_day as i64) - +Duration::seconds(alarm_sec_after_midnight as i64) + + Duration::seconds(alarm_sec_after_midnight as i64) } else { - let seconds_till_alarm = alarm_sec_after_midnight - - now.num_seconds_from_midnight(); - Duration::seconds(seconds_till_alarm as i64) + let seconds_till_alarm = alarm_sec_after_midnight - now.num_seconds_from_midnight(); + Duration::seconds(seconds_till_alarm as i64) }; - - let alarm = Alarm::from(Utc::now()+till_alarm, - Event::Alarm, - Some(std::time::Duration::from_secs(3600*2))); + let alarm = Alarm::from( + Utc::now() + till_alarm, + Event::Alarm, + Some(std::time::Duration::from_secs(3600 * 2)), + ); state.alarms.add_alarm(alarm).await.unwrap(); - - let text = format!("set alarm for over {} hours and {} minutes from now", - till_alarm.num_hours(), till_alarm.num_minutes() % 60); - send_text(chat_id, token, text).await + let text = format!( + "set alarm for over {} hours and {} minutes from now", + till_alarm.num_hours(), + till_alarm.num_minutes() % 60 + ); + + send_text(chat_id, token, text) + .await .map_err(|_| Error::CouldNotRespond)?; Ok(()) } -pub async fn list_alarm(chat_id: ChatId, token: &str, state: &State) - -> Result<(), Error> { - +pub async fn list_alarm(chat_id: ChatId, token: &str, state: &State) -> Result<(), Error> { let alarms = state.alarms.list(); - let mut list = String::with_capacity(alarms.len()*100); - + let mut list = String::with_capacity(alarms.len() * 100); + for (id, alarm) in alarms.into_iter() { - - list.push_str(&format!("{:x}, {}, {:?}, {:?}", + list.push_str(&format!( + "{:x}, {}, {:?}, {:?}", id, &alarm.time.with_timezone(&Local).to_rfc2822(), &alarm.action, @@ -111,24 +120,27 @@ pub async fn list_alarm(chat_id: ChatId, token: &str, state: &State) list.push_str("no alarms set"); } - send_text(chat_id, token, list).await//.unwrap(); + send_text(chat_id, token, list) + .await //.unwrap(); .map_err(|_| Error::CouldNotRespond)?; Ok(()) } -pub async fn remove_alarm<'a>(chat_id: ChatId, token: &str, mut args: std::str::SplitWhitespace<'a>, state: &State) - -> Result<(), Error> { - - let to_remove = dbg!(args.next()) - .ok_or(Error::NoAlarmId)?; +pub async fn remove_alarm<'a>( + chat_id: ChatId, + token: &str, + mut args: std::str::SplitWhitespace<'a>, + state: &State, +) -> Result<(), Error> { + let to_remove = dbg!(args.next()).ok_or(Error::NoAlarmId)?; let to_remove = u64::from_str_radix(to_remove, 16).unwrap(); - - let removed = state.alarms.remove_alarm(to_remove) - .unwrap(); //TODO //FIXME - //.map_err(|_| Error::CouldNotRemove)?; + + let removed = state.alarms.remove_alarm(to_remove).unwrap(); //TODO //FIXME + //.map_err(|_| Error::CouldNotRemove)?; let text = if let Some(alarm) = removed { - format!("removed alarm {:x}: {}, {:?}, {:?}", + format!( + "removed alarm {:x}: {}, {:?}, {:?}", to_remove, &alarm.time.with_timezone(&Local).to_rfc2822(), &alarm.action, @@ -138,7 +150,8 @@ pub async fn remove_alarm<'a>(chat_id: ChatId, token: &str, mut args: std::str:: String::from("Alarm does not exist, no alarm removed") }; - send_text(chat_id, token, text).await//.unwrap(); + send_text(chat_id, token, text) + .await //.unwrap(); .map_err(|_| Error::CouldNotRespond)?; Ok(()) -} \ No newline at end of file +} diff --git a/src/input/bot/youtube_dl.rs b/src/input/bot/youtube_dl.rs index 0df97177..38a91cff 100644 --- a/src/input/bot/youtube_dl.rs +++ b/src/input/bot/youtube_dl.rs @@ -1,11 +1,11 @@ -use telegram_bot::types::refs::{ChatId, MessageId}; -use telegram_bot::types::callback_query::CallbackQuery; use async_trait::async_trait; +use telegram_bot::types::callback_query::CallbackQuery; +use telegram_bot::types::refs::{ChatId, MessageId}; -use crate::input::youtube_downloader::{self, Feedback, JobStatus, MetaGuess}; -use crate::input::web_api::server::{State}; use super::send_text; use super::Error as BotError; +use crate::input::web_api::server::State; +use crate::input::youtube_downloader::{self, Feedback, JobStatus, MetaGuess}; #[derive(Debug, Clone)] pub struct TelegramFeedback { @@ -13,34 +13,43 @@ pub struct TelegramFeedback { pub message_id: MessageId, } -//present options: +//present options: // Swap // None // Ok // Lookup impl TelegramFeedback { - async fn ask_name_artist(&self, token: &str, mut meta: MetaGuess, id: u64) - -> Result<(), BotError> { + async fn ask_name_artist( + &self, + token: &str, + mut meta: MetaGuess, + id: u64, + ) -> Result<(), BotError> { dbg!(); - let keyboard_json = format!("[\ + let keyboard_json = format!( + "[\ [{{\"text\":\"swap\", \"callback_data\":\"ytdl:swap:{id}\"}}],\ [{{\"text\":\"no\", \"callback_data\":\"ytdl:no:{id}\"}}],\ [{{\"text\":\"ok\", \"callback_data\":\"ytdl:ok:{id}\"}}],\ [{{\"text\":\"lookup\", \"callback_data\":\"ytdl:lookup:{id}\"}}]\ - ]",id=id); + ]", + id = id + ); let reply_markup = format!("{{\"inline_keyboard\":{} }}", keyboard_json); - meta.title.retain(|c| c.is_ascii_alphanumeric() || - c.is_ascii_whitespace() || c=='-'); - meta.artist.retain(|c| c.is_ascii_alphanumeric() || - c.is_ascii_whitespace() || c=='-'); - let text = format!("is _{}_ the title and _{}_ the artist?", - meta.title, meta.artist); + meta.title + .retain(|c| c.is_ascii_alphanumeric() || c.is_ascii_whitespace() || c == '-'); + meta.artist + .retain(|c| c.is_ascii_alphanumeric() || c.is_ascii_whitespace() || c == '-'); + let text = format!( + "is _{}_ the title and _{}_ the artist?", + meta.title, meta.artist + ); //TODO: should always base this on metadata guess, should make that a //seperate type dbg!(&text); dbg!(&reply_markup); - let url = format!("https://api.telegram.org/bot{}/sendMessage", token); + let url = format!("https://api.telegram.org/bot{}/sendMessage", token); let form = reqwest::multipart::Form::new() .text("chat_id", self.chat_id.to_string()) .text("text", text) @@ -50,10 +59,9 @@ impl TelegramFeedback { dbg!(); let client = reqwest::Client::new(); - let resp = client.post(&url) - .multipart(form).send().await?; + let resp = client.post(&url).multipart(form).send().await?; //https://stackoverflow.com/questions/57540455/error-blockingclientinfuturecontext-when-trying-to-make-a-request-from-within - + if resp.status() != reqwest::StatusCode::OK { error!("telegram gave invalid response: {:?}", resp); Err(BotError::InvalidServerResponse(resp)) @@ -61,7 +69,6 @@ impl TelegramFeedback { dbg!("send message"); Ok(()) } - } } @@ -69,20 +76,14 @@ impl TelegramFeedback { impl Feedback for TelegramFeedback { //errors during feedback must be handled within feedback channel async fn feedback(&self, status: JobStatus, token: &str) { - let res: Result<(),BotError> = match status { - JobStatus::Finished => { - send_text(self.chat_id, token, "finished").await - }, - JobStatus::Downloaded => { - send_text(self.chat_id, token, "done downloading").await - }, - JobStatus::Queued(meta_data, id) => { - self.ask_name_artist(token, meta_data, id).await - .map_err(|e| e.into()) - }, - JobStatus::Error => { - send_text(self.chat_id, token, "ran into error").await - }, + let res: Result<(), BotError> = match status { + JobStatus::Finished => send_text(self.chat_id, token, "finished").await, + JobStatus::Downloaded => send_text(self.chat_id, token, "done downloading").await, + JobStatus::Queued(meta_data, id) => self + .ask_name_artist(token, meta_data, id) + .await + .map_err(|e| e.into()), + JobStatus::Error => send_text(self.chat_id, token, "ran into error").await, }; if let Err(e) = res { @@ -110,9 +111,7 @@ impl From for Error { } } -pub async fn handle_callback(callback_data: &str, state: &State) - -> Result<(), Error> { - +pub async fn handle_callback(callback_data: &str, state: &State) -> Result<(), Error> { let mut split = callback_data.split_terminator(":").skip(1); let command = split.next(); match command { @@ -132,7 +131,7 @@ pub async fn handle_callback(callback_data: &str, state: &State) Some("lookup") => todo!(), _ => { error!("cant handle youtube_dl callback command: {:?}", command); - }, + } } Ok(()) } diff --git a/src/input/mod.rs b/src/input/mod.rs index a07d1781..3749cab6 100755 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -1,8 +1,8 @@ +pub mod alarms; pub mod bot; +pub mod mpd_status; pub mod web_api; -pub mod alarms; pub mod youtube_downloader; -pub mod mpd_status; -pub use youtube_downloader::YoutubeDownloader; pub use mpd_status::MpdStatus; +pub use youtube_downloader::YoutubeDownloader; diff --git a/src/input/mpd_status.rs b/src/input/mpd_status.rs index 0f53e749..963b5205 100755 --- a/src/input/mpd_status.rs +++ b/src/input/mpd_status.rs @@ -1,8 +1,8 @@ -use mpd::{idle::Idle, idle::Subsystem, Client}; use crate::errors::Error; -use std::thread; -use std::sync::{Arc, RwLock}; use crossbeam_channel::{Receiver, Sender}; +use mpd::{idle::Idle, idle::Subsystem, Client}; +use std::sync::{Arc, RwLock}; +use std::thread; //mpd watcher, waits on mpd sys changes and stores in struct/sends updates to whomever needs to know //mpd command sender (opens new connection for every command?) @@ -26,11 +26,11 @@ fn mpd_watcher(mut client: Client, status: MpdStatus, rx: Receiver<()>) { client.wait(&[Subsystem::Player, Subsystem::Mixer]).unwrap(); loop { //if we have a message that means we should shut down - if let Ok(_) = rx.try_recv(){ + if let Ok(_) = rx.try_recv() { return; } //this loop is stopped by sending a change to mpd server - if let Ok(_) = client.wait(&[Subsystem::Player, Subsystem::Mixer]){ + if let Ok(_) = client.wait(&[Subsystem::Player, Subsystem::Mixer]) { //update status let new_status = client.status().unwrap(); *(status.inner.write().unwrap()) = new_status; @@ -50,11 +50,13 @@ impl MpdStatus { client.volume(status.volume).unwrap(); }*/ - pub fn start_updating() -> Result<(Self, thread::JoinHandle<()>, Sender<()>), Error>{ + pub fn start_updating() -> Result<(Self, thread::JoinHandle<()>, Sender<()>), Error> { let mut client = mpd::Client::connect("127.0.0.1:6600")?; let status = client.status()?; - let mpd_status = Self { inner: Arc::new(RwLock::new(status))}; + let mpd_status = Self { + inner: Arc::new(RwLock::new(status)), + }; let mpd_status_cloned = mpd_status.clone(); let (tx, rx) = crossbeam_channel::bounded(1); @@ -64,4 +66,4 @@ impl MpdStatus { Ok((mpd_status, mpd_watcher_thread, tx)) } -} \ No newline at end of file +} diff --git a/src/input/web_api/alarms.rs b/src/input/web_api/alarms.rs index 1d816ca3..1aa08272 100644 --- a/src/input/web_api/alarms.rs +++ b/src/input/web_api/alarms.rs @@ -1,83 +1,91 @@ use chrono::{DateTime, NaiveDateTime, Utc}; -use std::time::Duration; use serde::Deserialize; +use std::time::Duration; +use super::*; use crate::controller::Event; use crate::input::alarms::Alarm; -use super::*; #[derive(Deserialize, Debug)] pub struct AlarmDataMinFrom { - min_till_alarm: String, + min_till_alarm: String, } -pub fn set_alarm_minutes_from_now(req: HttpRequest, params: Form, - state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { - //Code to parse alarm time - dbg!(¶ms); +pub fn set_alarm_minutes_from_now( + req: HttpRequest, + params: Form, + state: Data, + auth: BasicAuth, +) -> HttpResponse { + if authenticated(auth) { + //Code to parse alarm time + dbg!(¶ms); - if let Ok(minutes) = params.min_till_alarm.parse(){ - let time = Utc::now() + chrono::Duration::minutes(minutes); + if let Ok(minutes) = params.min_till_alarm.parse() { + let time = Utc::now() + chrono::Duration::minutes(minutes); - //state.alarms.add_alarm(time).unwrap(); - HttpResponse::Ok().finish() - } else { - make_error(StatusCode::INTERNAL_SERVER_ERROR) - } - } else { - make_auth_error() - } + //state.alarms.add_alarm(time).unwrap(); + HttpResponse::Ok().finish() + } else { + make_error(StatusCode::INTERNAL_SERVER_ERROR) + } + } else { + make_auth_error() + } } #[derive(Deserialize, Debug)] pub struct AlarmDataUnixTS { - timestamp: String, + timestamp: String, } -pub async fn set_alarm_unix_timestamp(params: Form, state: Data) -> HttpResponse { - //Code to parse alarm time - dbg!(¶ms); +pub async fn set_alarm_unix_timestamp( + params: Form, + state: Data, +) -> HttpResponse { + //Code to parse alarm time + dbg!(¶ms); - if let Ok(ts) = params.timestamp.parse(){ - let time = DateTime::::from_utc(NaiveDateTime::from_timestamp(ts, 0), Utc); - dbg!(time); - dbg!(Utc::now()); + if let Ok(ts) = params.timestamp.parse() { + let time = DateTime::::from_utc(NaiveDateTime::from_timestamp(ts, 0), Utc); + dbg!(time); + dbg!(Utc::now()); - if time>Utc::now() { - let alarm = Alarm::from(time, Event::Alarm, Some(Duration::from_secs(3600*2))); + if time > Utc::now() { + let alarm = Alarm::from(time, Event::Alarm, Some(Duration::from_secs(3600 * 2))); - if state.alarms.add_alarm(alarm).await.is_ok() { - dbg!("done setting alarm"); - HttpResponse::Ok().finish() - } else { - dbg!(); - make_error( StatusCode::INTERNAL_SERVER_ERROR) - } - } else { - dbg!(); - make_error(StatusCode::UNPROCESSABLE_ENTITY) - } - } else { - dbg!(); - make_error(StatusCode::INTERNAL_SERVER_ERROR) - } + if state.alarms.add_alarm(alarm).await.is_ok() { + dbg!("done setting alarm"); + HttpResponse::Ok().finish() + } else { + dbg!(); + make_error(StatusCode::INTERNAL_SERVER_ERROR) + } + } else { + dbg!(); + make_error(StatusCode::UNPROCESSABLE_ENTITY) + } + } else { + dbg!(); + make_error(StatusCode::INTERNAL_SERVER_ERROR) + } } pub fn list_alarms(state: Data) -> HttpResponse { - //Code to parse alarm time - - let alarms = state.alarms.list(); - let mut list = String::with_capacity(alarms.len()*100); - for (id,alarm) in alarms { - list.push_str(&format!("{:x}, {}, {:?}, {:?}", - id, - &alarm.time.to_rfc2822(), - &alarm.action, - &alarm.expiration, - )); - list.push_str("\n"); - } - dbg!(&list); - HttpResponse::Ok().body(list) -} \ No newline at end of file + //Code to parse alarm time + + let alarms = state.alarms.list(); + let mut list = String::with_capacity(alarms.len() * 100); + for (id, alarm) in alarms { + list.push_str(&format!( + "{:x}, {}, {:?}, {:?}", + id, + &alarm.time.to_rfc2822(), + &alarm.action, + &alarm.expiration, + )); + list.push_str("\n"); + } + dbg!(&list); + HttpResponse::Ok().body(list) +} diff --git a/src/input/web_api/commands.rs b/src/input/web_api/commands.rs index 2baca748..bd0d7527 100644 --- a/src/input/web_api/commands.rs +++ b/src/input/web_api/commands.rs @@ -1,75 +1,96 @@ use actix_web::web::Data; -use actix_web_httpauth::extractors::basic::{BasicAuth}; +use actix_web_httpauth::extractors::basic::BasicAuth; use actix_web::HttpResponse; -use crate::controller::{Command, Event}; -use crate::controller::State as TargetState; use super::*; +use crate::controller::State as TargetState; +use crate::controller::{Command, Event}; ///////////////////// lamp commands /////////////////////////////// pub fn toggle(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { - state.controller_addr.send(Event::Command(Command::LampsToggle)).unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } + if authenticated(auth) { + state + .controller_addr + .send(Event::Command(Command::LampsToggle)) + .unwrap(); + HttpResponse::Ok().finish() + } else { + make_auth_error() + } } pub fn dim(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { - state.controller_addr.send(Event::Command(Command::LampsDim)).unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } + if authenticated(auth) { + state + .controller_addr + .send(Event::Command(Command::LampsDim)) + .unwrap(); + HttpResponse::Ok().finish() + } else { + make_auth_error() + } } pub fn dimmest(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { - state.controller_addr.send(Event::Command(Command::LampsDimmest)).unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } + if authenticated(auth) { + state + .controller_addr + .send(Event::Command(Command::LampsDimmest)) + .unwrap(); + HttpResponse::Ok().finish() + } else { + make_auth_error() + } } pub fn normal(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { - state.controller_addr.send(Event::Command(Command::LampsDay)).unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } + if authenticated(auth) { + state + .controller_addr + .send(Event::Command(Command::LampsDay)) + .unwrap(); + HttpResponse::Ok().finish() + } else { + make_auth_error() + } } pub fn evening(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { - state.controller_addr.send(Event::Command(Command::LampsEvening)).unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } + if authenticated(auth) { + state + .controller_addr + .send(Event::Command(Command::LampsEvening)) + .unwrap(); + HttpResponse::Ok().finish() + } else { + make_auth_error() + } } pub fn night(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { - state.controller_addr.send(Event::Command(Command::LampsNight)).unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } + if authenticated(auth) { + state + .controller_addr + .send(Event::Command(Command::LampsNight)) + .unwrap(); + HttpResponse::Ok().finish() + } else { + make_auth_error() + } } //////////////////////// go to state commands ///////////////////////////////// pub fn lightloop(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { - state.controller_addr.send(Event::Command(Command::ChangeState(TargetState::LightLoop))).unwrap(); //TODO FIXME - HttpResponse::Ok().finish() - } else { - make_auth_error() - } -} \ No newline at end of file + if authenticated(auth) { + state + .controller_addr + .send(Event::Command(Command::ChangeState(TargetState::LightLoop))) + .unwrap(); //TODO FIXME + HttpResponse::Ok().finish() + } else { + make_auth_error() + } +} diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index 5107511b..64bfaab8 100755 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -1,37 +1,40 @@ -use actix_web_httpauth::extractors::basic::{BasicAuth}; +use actix_web_httpauth::extractors::basic::BasicAuth; use actix_web_httpauth::headers::www_authenticate::basic::Basic; use actix_web_httpauth::headers::www_authenticate::WwwAuthenticate; use actix_web::http::StatusCode; -use actix_web::{HttpResponse, HttpRequest}; -use actix_web::web::{Form, Data}; +use actix_web::web::{Data, Form}; +use actix_web::{HttpRequest, HttpResponse}; -mod logins; mod alarms; -mod music; mod commands; +mod logins; +mod music; pub mod server; use server::State; fn authenticated(auth: BasicAuth) -> bool { - - let username = auth.user_id(); - if let Some(password) = auth.password(){ - logins::LIST.iter() - .filter(|x| x.username==username) - .filter(|x| x.password==password) - .next().is_some() - } else {false } + let username = auth.user_id(); + if let Some(password) = auth.password() { + logins::LIST + .iter() + .filter(|x| x.username == username) + .filter(|x| x.password == password) + .next() + .is_some() + } else { + false + } } fn make_auth_error() -> HttpResponse { - let challenge = Basic::with_realm("Restricted area"); - HttpResponse::Unauthorized() - .set(WwwAuthenticate(challenge)) - .finish() + let challenge = Basic::with_realm("Restricted area"); + HttpResponse::Unauthorized() + .set(WwwAuthenticate(challenge)) + .finish() } fn make_error(statuscode: StatusCode) -> HttpResponse { - HttpResponse::build(statuscode).finish() + HttpResponse::build(statuscode).finish() } diff --git a/src/input/web_api/music.rs b/src/input/web_api/music.rs index 0df1a5e1..78d357dc 100644 --- a/src/input/web_api/music.rs +++ b/src/input/web_api/music.rs @@ -1,29 +1,32 @@ -use actix_web::web::{Form, Data}; use actix_web::http::StatusCode; +use actix_web::web::{Data, Form}; use serde::Deserialize; use actix_web::HttpResponse; -use crate::input::youtube_downloader::FeedbackChannel; use super::*; - +use crate::input::youtube_downloader::FeedbackChannel; #[derive(Deserialize, Debug)] pub struct SongUrl { - url: String, + url: String, } pub async fn add_song_from_url(params: Form, state: Data) -> HttpResponse { - let url = params.into_inner().url; - dbg!(); + let url = params.into_inner().url; + dbg!(); + + if state + .youtube_dl + .add_song_to_queue(url, FeedbackChannel::None) + .await + .is_ok() + { + dbg!(); - if state.youtube_dl.add_song_to_queue(url, FeedbackChannel::None) - .await.is_ok(){ - dbg!(); - - HttpResponse::Ok().finish() - } else { - make_error(StatusCode::INTERNAL_SERVER_ERROR) - } + HttpResponse::Ok().finish() + } else { + make_error(StatusCode::INTERNAL_SERVER_ERROR) + } } diff --git a/src/input/web_api/server/database.rs b/src/input/web_api/server/database.rs index ac08f0c7..c2a2be55 100755 --- a/src/input/web_api/server/database.rs +++ b/src/input/web_api/server/database.rs @@ -1,4 +1,4 @@ -use sled::{Db,Tree}; +use sled::{Db, Tree}; use ring::{digest, pbkdf2}; use std::num::NonZeroU32; @@ -7,86 +7,105 @@ static PBKDF2_ALG: pbkdf2::Algorithm = pbkdf2::PBKDF2_HMAC_SHA256; const CREDENTIAL_LEN: usize = digest::SHA256_OUTPUT_LEN; pub enum PasswDbError { - WrongUsername, - WrongPassword, - Internal, + WrongUsername, + WrongPassword, + Internal, } #[derive(Debug, Clone)] pub struct PasswordDatabase { - pbkdf2_iterations: NonZeroU32, - db_salt_component: [u8; 16], + pbkdf2_iterations: NonZeroU32, + db_salt_component: [u8; 16], pub storage: Tree, } impl PasswordDatabase { - pub fn from_db(db: &Db) -> Result { - Ok(Self { - pbkdf2_iterations: NonZeroU32::new(100_000).unwrap(), - db_salt_component: [ - // This value was generated from a secure PRNG. - 0xd6, 0x26, 0x98, 0xda, 0xf4, 0xdc, 0x50, 0x52, - 0x24, 0xf2, 0x27, 0xd1, 0xfe, 0x39, 0x01, 0x8a - ], - storage: db.open_tree("passw_database")?, //created it not exist - }) - } - - pub fn set_password(&mut self, username: &[u8], password: &[u8]) - -> Result<(), sled::Error> { - let salt = self.salt(username); - let mut credential = [0u8; CREDENTIAL_LEN]; - pbkdf2::derive(PBKDF2_ALG, self.pbkdf2_iterations, - &salt, password, &mut credential); - - self.storage.insert(username, &credential)?; - self.storage.flush()?; - Ok(()) - } + pub fn from_db(db: &Db) -> Result { + Ok(Self { + pbkdf2_iterations: NonZeroU32::new(100_000).unwrap(), + db_salt_component: [ + // This value was generated from a secure PRNG. + 0xd6, 0x26, 0x98, 0xda, 0xf4, 0xdc, 0x50, 0x52, 0x24, 0xf2, 0x27, 0xd1, 0xfe, 0x39, + 0x01, 0x8a, + ], + storage: db.open_tree("passw_database")?, //created it not exist + }) + } - pub fn add_admin(&mut self, password: &str) -> Result<(), sled::Error>{ - self.set_password("admin".as_bytes(), password.as_bytes()) - } + pub fn set_password(&mut self, username: &[u8], password: &[u8]) -> Result<(), sled::Error> { + let salt = self.salt(username); + let mut credential = [0u8; CREDENTIAL_LEN]; + pbkdf2::derive( + PBKDF2_ALG, + self.pbkdf2_iterations, + &salt, + password, + &mut credential, + ); - pub async fn remove_user(&self, username: &[u8]) -> Result<(), sled::Error> { - self.storage.remove(username)?; - self.storage.flush_async().await?; - Ok(()) - } + self.storage.insert(username, &credential)?; + self.storage.flush()?; + Ok(()) + } - pub fn update(&self, old_name: &str, new_name: &str) { - if old_name == new_name {return; } - let credential = self.storage.get(old_name.as_bytes()).unwrap().unwrap(); - self.storage.insert(new_name.as_bytes(), credential).unwrap(); - } + pub fn add_admin(&mut self, password: &str) -> Result<(), sled::Error> { + self.set_password("admin".as_bytes(), password.as_bytes()) + } - pub fn verify_password(&self, username: &[u8], attempted_password: &[u8]) - -> Result<(), PasswDbError> { - if let Ok(db_entry) = self.storage.get(username) { - if let Some(credential) = db_entry { - let salted_attempt = self.salt(username); - pbkdf2::verify(PBKDF2_ALG, self.pbkdf2_iterations, - &salted_attempt, attempted_password, &credential) - .map_err(|_| PasswDbError::WrongPassword) - } else { Err(PasswDbError::WrongUsername) } - } else { Err(PasswDbError::Internal )} - } + pub async fn remove_user(&self, username: &[u8]) -> Result<(), sled::Error> { + self.storage.remove(username)?; + self.storage.flush_async().await?; + Ok(()) + } - //pub fn is_user_in_database(&self, username: &[u8]) -> Result { - // self.storage.contains_key(username) - //} + pub fn update(&self, old_name: &str, new_name: &str) { + if old_name == new_name { + return; + } + let credential = self.storage.get(old_name.as_bytes()).unwrap().unwrap(); + self.storage + .insert(new_name.as_bytes(), credential) + .unwrap(); + } - // The salt should have a user-specific component so that an attacker - // cannot crack one password for multiple users in the database. It - // should have a database-unique component so that an attacker cannot - // crack the same user's password across databases in the unfortunate - // but common case that the user has used the same password for - // multiple systems. - pub fn salt(&self, username: &[u8]) -> Vec { - let mut salt = Vec::with_capacity(self.db_salt_component.len() - + username.len()); - salt.extend(self.db_salt_component.as_ref()); - salt.extend(username); - salt - } -} \ No newline at end of file + pub fn verify_password( + &self, + username: &[u8], + attempted_password: &[u8], + ) -> Result<(), PasswDbError> { + if let Ok(db_entry) = self.storage.get(username) { + if let Some(credential) = db_entry { + let salted_attempt = self.salt(username); + pbkdf2::verify( + PBKDF2_ALG, + self.pbkdf2_iterations, + &salted_attempt, + attempted_password, + &credential, + ) + .map_err(|_| PasswDbError::WrongPassword) + } else { + Err(PasswDbError::WrongUsername) + } + } else { + Err(PasswDbError::Internal) + } + } + + //pub fn is_user_in_database(&self, username: &[u8]) -> Result { + // self.storage.contains_key(username) + //} + + // The salt should have a user-specific component so that an attacker + // cannot crack one password for multiple users in the database. It + // should have a database-unique component so that an attacker cannot + // crack the same user's password across databases in the unfortunate + // but common case that the user has used the same password for + // multiple systems. + pub fn salt(&self, username: &[u8]) -> Vec { + let mut salt = Vec::with_capacity(self.db_salt_component.len() + username.len()); + salt.extend(self.db_salt_component.as_ref()); + salt.extend(username); + salt + } +} diff --git a/src/input/web_api/server/login.rs b/src/input/web_api/server/login.rs index 22c19be1..b1f8ea59 100755 --- a/src/input/web_api/server/login.rs +++ b/src/input/web_api/server/login.rs @@ -1,74 +1,82 @@ -use actix_identity::{Identity}; -use actix_web::Result as wResult; -use actix_web::{ - http, - HttpRequest, HttpResponse, -}; +use actix_identity::Identity; use actix_web::web::{Data, Form}; -use rand::{Rng,FromEntropy}; +use actix_web::Result as wResult; +use actix_web::{http, HttpRequest, HttpResponse}; +use rand::{FromEntropy, Rng}; use serde::Deserialize; -use std::sync::{Arc, Mutex, atomic::Ordering}; +use std::sync::{atomic::Ordering, Arc, Mutex}; -use super::{State, Session}; +use super::{Session, State}; pub fn logout(id: Identity) -> HttpResponse { - id.forget(); - HttpResponse::Found().finish() + id.forget(); + HttpResponse::Found().finish() } pub fn login_page() -> HttpResponse { - let page = include_str!("static_webpages/login.html"); - HttpResponse::Ok().header(http::header::CONTENT_TYPE, "text/html; charset=utf-8").body(page) + let page = include_str!("static_webpages/login.html"); + HttpResponse::Ok() + .header(http::header::CONTENT_TYPE, "text/html; charset=utf-8") + .body(page) } #[derive(Deserialize)] pub struct Logindata { - u: String, - p: String, + u: String, + p: String, } /// State and POST Params pub async fn login_get_and_check( - id: Identity, - state: Data, - req: HttpRequest, - params: Form) -> wResult { - - trace!("checking login"); + id: Identity, + state: Data, + req: HttpRequest, + params: Form, +) -> wResult { + trace!("checking login"); - //time function duration - let now = std::time::Instant::now(); + //time function duration + let now = std::time::Instant::now(); //if login valid (check passwdb) load userinfo - if state.passw_db.verify_password(params.u.as_str().as_bytes(), params.p.as_str().as_bytes()).is_err(){ - warn!("incorrect password"); - return Ok(HttpResponse::build(http::StatusCode::UNAUTHORIZED) - .content_type("text/plain") - .body("incorrect password or username")); - } else { info!("user logged in");} - - let session = Session {};//kept in case we want it back in the future - //find free session_numb, set new session number and store new session - let session_id = state.free_session_ids.fetch_add(1, Ordering::Acquire); - let mut sessions = state.sessions.write().unwrap(); - sessions.insert(session_id as u16, Arc::new(Mutex::new(session))); - - //sign and send session id cookie to user + if state + .passw_db + .verify_password(params.u.as_str().as_bytes(), params.p.as_str().as_bytes()) + .is_err() + { + warn!("incorrect password"); + return Ok(HttpResponse::build(http::StatusCode::UNAUTHORIZED) + .content_type("text/plain") + .body("incorrect password or username")); + } else { + info!("user logged in"); + } + + let session = Session {}; //kept in case we want it back in the future + //find free session_numb, set new session number and store new session + let session_id = state.free_session_ids.fetch_add(1, Ordering::Acquire); + let mut sessions = state.sessions.write().unwrap(); + sessions.insert(session_id as u16, Arc::new(Mutex::new(session))); + + //sign and send session id cookie to user id.remember(session_id.to_string()); - info!("remembering session"); - - let end = std::time::Instant::now(); - println!("{:?}", end-now); + info!("remembering session"); + + let end = std::time::Instant::now(); + println!("{:?}", end - now); Ok(HttpResponse::Found() - .header(http::header::LOCATION, req.path()["/login".len()..].to_owned()) - .finish()) + .header( + http::header::LOCATION, + req.path()["/login".len()..].to_owned(), + ) + .finish()) } pub fn make_random_cookie_key() -> [u8; 32] { - let mut cookie_private_key = [0u8; 32]; - let mut rng = rand::rngs::StdRng::from_entropy(); - rng.fill(&mut cookie_private_key[..]); - cookie_private_key -} \ No newline at end of file + let mut cookie_private_key = [0u8; 32]; + let mut rng = rand::rngs::StdRng::from_entropy(); + rng.fill(&mut cookie_private_key[..]); + cookie_private_key +} diff --git a/src/input/web_api/server/login_redirect.rs b/src/input/web_api/server/login_redirect.rs index 6774c0d7..5424a111 100755 --- a/src/input/web_api/server/login_redirect.rs +++ b/src/input/web_api/server/login_redirect.rs @@ -2,11 +2,11 @@ use std::task::{Context, Poll}; use actix_service::{Service, Transform}; use actix_web::dev::{ServiceRequest, ServiceResponse}; -use actix_web::{http, Error, HttpResponse, web}; +use actix_web::{http, web, Error, HttpResponse}; use futures::future::{ok, Either, Ready}; -use log::{info}; +use log::info; use actix_identity::RequestIdentity; //example to mimic: https://github.com/actix/examples/blob/master/middleware/src/redirect.rs @@ -14,7 +14,7 @@ use actix_identity::RequestIdentity; use super::State; #[derive(Default)] -pub struct CheckLogin{} +pub struct CheckLogin {} impl Transform for CheckLogin where @@ -38,16 +38,17 @@ pub struct CheckLoginMiddleware { } //TODO can we get data into the middleware? look at existing identityservice -fn is_logged_in(state: &web::Data, id: String) -> Result<(),()> { - if let Ok(id) = id.parse::(){ +fn is_logged_in(state: &web::Data, id: String) -> Result<(), ()> { + if let Ok(id) = id.parse::() { //check if valid session (identity key contained in sessions) - if state.sessions.read().unwrap().contains_key(&id){ + if state.sessions.read().unwrap().contains_key(&id) { Ok(()) } else { Err(()) } - } else {Err(()) } - + } else { + Err(()) + } } impl Service for CheckLoginMiddleware @@ -72,30 +73,26 @@ where //let id = req.get_identity().unwrap(); let data: web::Data = req.app_data().unwrap(); if is_logged_in(&data, id).is_ok() { - //let fut = + //let fut = Either::Left(self.service.call(req)) } else { - let redirect = "/login".to_owned()+req.path(); - Either::Right( - ok(req.into_response( + let redirect = "/login".to_owned() + req.path(); + Either::Right(ok(req.into_response( HttpResponse::Found() .header(http::header::LOCATION, redirect) .finish() .into_body(), //TODO why comma? is needed? - )) - ) + ))) } } else { info!("could not get identity thus redirecting"); - let redirect = "/login".to_owned()+req.path(); - Either::Right( - ok(req.into_response( + let redirect = "/login".to_owned() + req.path(); + Either::Right(ok(req.into_response( HttpResponse::Found() .header(http::header::LOCATION, redirect) .finish() - .into_body(), //TODO why comma? is needed? - )) - ) + .into_body(), //TODO why comma? is needed? + ))) } } -} \ No newline at end of file +} diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index d5e7183c..ba9efa76 100755 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -1,205 +1,204 @@ -use rustls::{NoClientAuth, ServerConfig}; use rustls::internal::pemfile::{certs, pkcs8_private_keys}; -use telegram_bot::types::refs::UserId; +use rustls::{NoClientAuth, ServerConfig}; use sensor_value::SensorValue; +use telegram_bot::types::refs::UserId; -use actix_rt::System; -use actix_web::{HttpServer,App, web, Responder}; -use actix_identity::{CookieIdentityPolicy, IdentityService}; use actix_files as axtix_fs; +use actix_identity::{CookieIdentityPolicy, IdentityService}; +use actix_rt::System; +use actix_web::web::{Bytes, Data}; use actix_web::HttpRequest; -use actix_web::web::{Data, Bytes}; use actix_web::HttpResponse; +use actix_web::{web, App, HttpServer, Responder}; -use std::thread; -use std::sync::{Arc, Mutex, RwLock, atomic::AtomicUsize}; use std::collections::HashMap; -use std::path::{Path, PathBuf}; -use std::io::BufReader; use std::fs; +use std::io::BufReader; +use std::path::{Path, PathBuf}; +use std::sync::{atomic::AtomicUsize, Arc, Mutex, RwLock}; +use std::thread; +use crate::controller::Event; use crate::input; use crate::input::bot; -use crate::controller::Event; pub mod database; -pub mod login_redirect; pub mod login; +pub mod login_redirect; +use super::{alarms, commands, music}; pub use database::PasswordDatabase; -pub use login::{make_random_cookie_key, login_page, login_get_and_check, logout}; +pub use login::{login_get_and_check, login_page, logout, make_random_cookie_key}; pub use login_redirect::CheckLogin; -use super::{alarms, commands, music}; -pub struct Session {}//TODO deprecate +pub struct Session {} //TODO deprecate #[derive(Clone)] pub struct State { - pub controller_addr: crossbeam_channel::Sender, - pub alarms: input::alarms::Alarms, - pub passw_db: PasswordDatabase, - pub sessions: Arc> >>> , - pub free_session_ids: Arc, - pub youtube_dl: input::YoutubeDownloader, - pub bot_token: String, - pub valid_ids: Vec, + pub controller_addr: crossbeam_channel::Sender, + pub alarms: input::alarms::Alarms, + pub passw_db: PasswordDatabase, + pub sessions: Arc>>>>, + pub free_session_ids: Arc, + pub youtube_dl: input::YoutubeDownloader, + pub bot_token: String, + pub valid_ids: Vec, } impl State { - pub fn new(passw_db: PasswordDatabase, - controller_tx: crossbeam_channel::Sender, - alarms: input::alarms::Alarms, - youtube_dl: input::YoutubeDownloader, - bot_token: String, - valid_ids: Vec) -> Self { - - let free_session_ids = Arc::new(AtomicUsize::new(0)); - let sessions = Arc::new(RwLock::new(HashMap::new())); - let valid_ids = valid_ids - .into_iter() - .map(|id| UserId::from(id)) - .collect(); - - State { - controller_addr: controller_tx, - alarms, - passw_db, - youtube_dl, - sessions, - free_session_ids, - bot_token, - valid_ids, - } - } + pub fn new( + passw_db: PasswordDatabase, + controller_tx: crossbeam_channel::Sender, + alarms: input::alarms::Alarms, + youtube_dl: input::YoutubeDownloader, + bot_token: String, + valid_ids: Vec, + ) -> Self { + let free_session_ids = Arc::new(AtomicUsize::new(0)); + let sessions = Arc::new(RwLock::new(HashMap::new())); + let valid_ids = valid_ids.into_iter().map(|id| UserId::from(id)).collect(); + + State { + controller_addr: controller_tx, + alarms, + passw_db, + youtube_dl, + sessions, + free_session_ids, + bot_token, + valid_ids, + } + } } #[derive(Debug)] pub enum Error { - NoKeyFound, - NoCertFound, + NoKeyFound, + NoCertFound, } fn get_key_and_cert(domain: &str, dir: &Path) -> Result<(PathBuf, PathBuf), Error> { - let mut cert_path = Err(Error::NoCertFound); - let mut key_path = Err(Error::NoKeyFound); - let domain = domain.replace(".", "_"); - for path in fs::read_dir(dir).unwrap() - .filter_map(Result::ok) - .map(|entry| entry.path()) { - - if let Some(stem) = path.file_stem().map(|s| s.to_str()).flatten(){ - if !stem.contains(&domain){ continue } - if let Some(ext) = path.extension().map(|s| s.to_str()).flatten(){ - match ext { - "key" => key_path = Ok(path), - "crt" => cert_path = Ok(path), - _ => continue, - } - } - } - } - - Ok((key_path?, cert_path?)) + let mut cert_path = Err(Error::NoCertFound); + let mut key_path = Err(Error::NoKeyFound); + let domain = domain.replace(".", "_"); + for path in fs::read_dir(dir) + .unwrap() + .filter_map(Result::ok) + .map(|entry| entry.path()) + { + if let Some(stem) = path.file_stem().map(|s| s.to_str()).flatten() { + if !stem.contains(&domain) { + continue; + } + if let Some(ext) = path.extension().map(|s| s.to_str()).flatten() { + match ext { + "key" => key_path = Ok(path), + "crt" => cert_path = Ok(path), + _ => continue, + } + } + } + } + + Ok((key_path?, cert_path?)) } pub fn make_tls_config(domain: &str, key_dir: &Path) -> Result { - - //find cert and key - let (key_path, cert_path) = get_key_and_cert(domain, key_dir)?; - - let mut tls_config = ServerConfig::new(NoClientAuth::new()); - let cert_file = &mut BufReader::new(fs::File::open(&cert_path) - .expect(&format!("could not open certificate file: {:?}", cert_path))); - let key_file = &mut BufReader::new(fs::File::open(&key_path) - .expect(&format!("could not open key file: {:?}", key_path))); - - let cert_chain = certs(cert_file).unwrap(); - let mut key = pkcs8_private_keys(key_file).unwrap(); - - tls_config - .set_single_cert(cert_chain, key.pop().unwrap()) - .unwrap(); - Ok(tls_config) + //find cert and key + let (key_path, cert_path) = get_key_and_cert(domain, key_dir)?; + + let mut tls_config = ServerConfig::new(NoClientAuth::new()); + let cert_file = &mut BufReader::new( + fs::File::open(&cert_path) + .expect(&format!("could not open certificate file: {:?}", cert_path)), + ); + let key_file = &mut BufReader::new( + fs::File::open(&key_path).expect(&format!("could not open key file: {:?}", key_path)), + ); + + let cert_chain = certs(cert_file).unwrap(); + let mut key = pkcs8_private_keys(key_file).unwrap(); + + tls_config + .set_single_cert(cert_chain, key.pop().unwrap()) + .unwrap(); + Ok(tls_config) } pub async fn index(_req: HttpRequest) -> impl Responder { "Hello world!" } -pub fn start_webserver(key_dir: &Path, - state: State, port: u16, domain: String, ha_key: String) - -> Result { - - let tls_config = make_tls_config(&domain, key_dir)?; - let cookie_key = make_random_cookie_key(); - let (tx, rx) = crossbeam_channel::unbounded(); - - thread::spawn(move || { - let sys = System::new("HttpServer"); - let web_server = HttpServer::new(move || { - // data the webservers functions have access to - let data = actix_web::web::Data::new(state.clone()); - - App::new() - .app_data(data) - .wrap(IdentityService::new( - CookieIdentityPolicy::new(&cookie_key[..]) - .domain(&domain) - .name("auth-cookie") - .path("/") - .secure(true), - )) - .service( - web::scope("/login") - .service(web::resource(r"/{path}") - .route(web::post().to(login_get_and_check)) - .route(web::get().to(login_page)) - )) - .service(web::resource("/commands/lamps/toggle") - .to(commands::toggle)) - .service(web::resource("/commands/lamps/evening") - .to(commands::evening)) - .service(web::resource("/commands/lamps/night") - .to(commands::night)) - .service(web::resource("/commands/lamps/day") - .to(commands::normal)) - .service(web::resource("/commands/lamps/dimmest") - .to(commands::dimmest)) - .service(web::resource("/commands/lamps/dim") - .to(commands::dim)) - .service(web::resource("/commands/lightloop") - .to(commands::lightloop)) - .service(web::resource(&format!("/{}", &state.bot_token)) - .to(bot::handle_webhook)) - .service(web::resource(&format!("/{}", ha_key)) - .route(web::post().to(handle_sensor)) - ) - - .service(web::scope("/") - .wrap(CheckLogin{}) - - .service(web::resource("").to(index)) - .service(web::resource("logout/").to(logout)) - .service(web::resource("add_song").to(music::add_song_from_url)) - .service(web::resource("set_alarm").to(alarms::set_alarm_unix_timestamp)) - .service(web::resource("list_alarms").to(alarms::list_alarms)) - //for all other urls we try to resolve to static files in the "web" dir - .service(axtix_fs::Files::new("", "./web/")) - ) - }) - .bind_rustls(&format!("0.0.0.0:{}", port), tls_config).unwrap() - //.bind("0.0.0.0:8080").unwrap() //without tcp use with debugging (note: https -> http, wss -> ws) - .shutdown_timeout(5) // shut down 5 seconds after getting the signal to shut down - .run(); - - let _ = tx.send(web_server.clone()); - sys.run() - //let mut rt = Runtime::new().unwrap(); - //rt.block_on(web_server).unwrap(); - }); - - let web_handle = rx.recv().unwrap(); - Ok(web_handle) +pub fn start_webserver( + key_dir: &Path, + state: State, + port: u16, + domain: String, + ha_key: String, +) -> Result { + let tls_config = make_tls_config(&domain, key_dir)?; + let cookie_key = make_random_cookie_key(); + let (tx, rx) = crossbeam_channel::unbounded(); + + thread::spawn(move || { + let sys = System::new("HttpServer"); + let web_server = HttpServer::new(move || { + // data the webservers functions have access to + let data = actix_web::web::Data::new(state.clone()); + + App::new() + .app_data(data) + .wrap(IdentityService::new( + CookieIdentityPolicy::new(&cookie_key[..]) + .domain(&domain) + .name("auth-cookie") + .path("/") + .secure(true), + )) + .service( + web::scope("/login").service( + web::resource(r"/{path}") + .route(web::post().to(login_get_and_check)) + .route(web::get().to(login_page)), + ), + ) + .service(web::resource("/commands/lamps/toggle").to(commands::toggle)) + .service(web::resource("/commands/lamps/evening").to(commands::evening)) + .service(web::resource("/commands/lamps/night").to(commands::night)) + .service(web::resource("/commands/lamps/day").to(commands::normal)) + .service(web::resource("/commands/lamps/dimmest").to(commands::dimmest)) + .service(web::resource("/commands/lamps/dim").to(commands::dim)) + .service(web::resource("/commands/lightloop").to(commands::lightloop)) + .service(web::resource(&format!("/{}", &state.bot_token)).to(bot::handle_webhook)) + .service( + web::resource(&format!("/{}", ha_key)).route(web::post().to(handle_sensor)), + ) + .service( + web::scope("/") + .wrap(CheckLogin {}) + .service(web::resource("").to(index)) + .service(web::resource("logout/").to(logout)) + .service(web::resource("add_song").to(music::add_song_from_url)) + .service(web::resource("set_alarm").to(alarms::set_alarm_unix_timestamp)) + .service(web::resource("list_alarms").to(alarms::list_alarms)) + //for all other urls we try to resolve to static files in the "web" dir + .service(axtix_fs::Files::new("", "./web/")), + ) + }) + .bind_rustls(&format!("0.0.0.0:{}", port), tls_config) + .unwrap() + //.bind("0.0.0.0:8080").unwrap() //without tcp use with debugging (note: https -> http, wss -> ws) + .shutdown_timeout(5) // shut down 5 seconds after getting the signal to shut down + .run(); + + let _ = tx.send(web_server.clone()); + sys.run() + //let mut rt = Runtime::new().unwrap(); + //rt.block_on(web_server).unwrap(); + }); + + let web_handle = rx.recv().unwrap(); + Ok(web_handle) } pub fn handle_sensor(body: Bytes, state: Data) -> HttpResponse { @@ -208,5 +207,5 @@ pub fn handle_sensor(body: Bytes, state: Data) -> HttpResponse { Err(err) => error!("deserialize sensorval failed: {:?}", err), Ok(event) => state.controller_addr.send(Event::Sensor(event)).unwrap(), } - HttpResponse::Ok().finish() + HttpResponse::Ok().finish() } diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs index 66d3befe..49d5f3f1 100755 --- a/src/input/youtube_downloader.rs +++ b/src/input/youtube_downloader.rs @@ -1,21 +1,21 @@ -use std::process::Command; -use std::io::Write; use std::fs; +use std::io::Write; use std::os::unix::fs::OpenOptionsExt; +use std::process::Command; use std::thread; -use std::time::Duration; use std::path::{Path, PathBuf}; +use std::time::Duration; -use reqwest::{IntoUrl}; use actix_rt; -use serde::{Serialize, Deserialize}; -use bincode; -use async_trait::async_trait; use async_std::task; +use async_trait::async_trait; +use bincode; +use regex::Regex; +use reqwest::IntoUrl; +use serde::{Deserialize, Serialize}; use sled::Batch; use std::ffi::OsStr; -use regex::Regex; //use id3; use crate::input::bot::youtube_dl::TelegramFeedback; @@ -26,44 +26,58 @@ const MUSIC_TEMP: &str = "temp/music"; const MUSIC_DIR: &str = "/home/pi/Music"; #[derive(Debug)] -pub enum Error{ +pub enum Error { CouldNotDownloadExecutable(reqwest::Error), CouldNotStoreExecutable(std::io::Error), CouldNotDownloadSong(std::process::Output), CouldNotUpdateMpd(mpd::error::Error), - #[allow(dead_code)] CouldNotCreateTempDir(std::io::Error), - #[allow(dead_code)] UnexpectedYoutubeDlStdOut(String), - #[allow(dead_code)] UnsupportedSource(String), + #[allow(dead_code)] + CouldNotCreateTempDir(std::io::Error), + #[allow(dead_code)] + UnexpectedYoutubeDlStdOut(String), + #[allow(dead_code)] + UnsupportedSource(String), CanNoLongerUpdateMeta, - #[allow(dead_code)] CanNotSwapArtistWithEmptyTitle, - #[allow(dead_code)] IDWasDeleted, + #[allow(dead_code)] + CanNotSwapArtistWithEmptyTitle, + #[allow(dead_code)] + IDWasDeleted, } impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { - Error::CouldNotDownloadExecutable(e) => - write!(f, "Could not download executable, cause {}", e), - Error::CouldNotStoreExecutable(e) => - write!(f, "Could not store executable, cause: {}", e), - Error::CouldNotDownloadSong(e) => - write!(f, "Could not download song, cause: {}", - String::from_utf8(e.stderr.clone()).unwrap()), - Error::CouldNotUpdateMpd(e) => - write!(f, "Could not update mpd, cause: {}", e), - Error::CouldNotCreateTempDir(e) => - write!(f, "Could not create temp directory, cause: {}", e), - Error::UnexpectedYoutubeDlStdOut(s) => - write!(f, "Could not understand output of youtube-dl, output was: {}",s), - Error::UnsupportedSource(s) => - write!(f, "Could not find something to download: {}", s), - Error::CanNoLongerUpdateMeta => - write!(f, "Can no longer update metadata, was already done some time ago"), - Error::CanNotSwapArtistWithEmptyTitle => - write!(f, "Can not swap artist and title as the current artist \ - is empty and the title can not be empty. Not writing metadata"), - Error::IDWasDeleted => - write!(f, "Internal error, file not in database"), + Error::CouldNotDownloadExecutable(e) => { + write!(f, "Could not download executable, cause {}", e) + } + Error::CouldNotStoreExecutable(e) => { + write!(f, "Could not store executable, cause: {}", e) + } + Error::CouldNotDownloadSong(e) => write!( + f, + "Could not download song, cause: {}", + String::from_utf8(e.stderr.clone()).unwrap() + ), + Error::CouldNotUpdateMpd(e) => write!(f, "Could not update mpd, cause: {}", e), + Error::CouldNotCreateTempDir(e) => { + write!(f, "Could not create temp directory, cause: {}", e) + } + Error::UnexpectedYoutubeDlStdOut(s) => write!( + f, + "Could not understand output of youtube-dl, output was: {}", + s + ), + Error::UnsupportedSource(s) => write!(f, "Could not find something to download: {}", s), + Error::CanNoLongerUpdateMeta => write!( + f, + "Can no longer update metadata, was already done some time ago" + ), + Error::CanNotSwapArtistWithEmptyTitle => write!( + f, + "Can not swap artist and title as the current artist \ + is empty and the title can not be empty. Not writing metadata" + ), + Error::IDWasDeleted => write!(f, "Internal error, file not in database"), } } } @@ -90,7 +104,7 @@ pub trait Feedback { } #[derive(Debug, Clone)] -pub enum FeedbackChannel{ +pub enum FeedbackChannel { Telegram(TelegramFeedback), None, //future expand with ... signal? @@ -120,17 +134,13 @@ struct Job { } async fn download_youtube_dl(url: U) -> Result<(), Error> { - let mut dest = fs::OpenOptions::new() .create(true) .write(true) .mode(0o770) .open(YOUTUBE_DL_LOC)?; - let response = reqwest::get(url) - .await? - .bytes() - .await?; + let response = reqwest::get(url).await?.bytes().await?; dbg!(&response.len()); dest.write(&response)?; Ok(()) @@ -169,33 +179,33 @@ pub struct MetaGuess { // in the future queued an downloaded can be expanded // with a MetaGuess -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize)] enum Status { - Queued(MetaGuess), //can go to Downloaded or ConfirmedMeta + Queued(MetaGuess), //can go to Downloaded or ConfirmedMeta Downloaded(MetaGuess), // can go to Metawritten (as soon as there is meta we write it to file) MetaConfirmed(MetaData), //can go to MetaWritten (as soon as download is complete meta written to file) MetaWritten((PathBuf, MetaData)), //can only tranfrom to WritingMeta } -fn split(to_split_on: &str) -> (&str, &str){ +fn split(to_split_on: &str) -> (&str, &str) { //try splitting on title let new_title; let new_artist; let in_quotes = Regex::new(r#"(.*)\s*(?:'|")\s*(.*)\s*(?:'|")\s*(.*)"#).unwrap(); - if to_split_on.contains("-"){ - let mut split = to_split_on.splitn(2,"-"); + if to_split_on.contains("-") { + let mut split = to_split_on.splitn(2, "-"); new_title = split.next().unwrap(); new_artist = split.next().unwrap(); - } else if to_split_on.contains(":"){ - let mut split = to_split_on.splitn(2,":"); + } else if to_split_on.contains(":") { + let mut split = to_split_on.splitn(2, ":"); new_title = split.next().unwrap(); new_artist = split.next().unwrap(); - } else if to_split_on.contains("|"){ - let mut split = to_split_on.splitn(2,"|"); + } else if to_split_on.contains("|") { + let mut split = to_split_on.splitn(2, "|"); new_title = split.next().unwrap(); new_artist = split.next().unwrap(); - } else if let Some(caps) = in_quotes.captures(to_split_on){ + } else if let Some(caps) = in_quotes.captures(to_split_on) { dbg!(&caps); let len_before = caps.get(1).unwrap().as_str().len(); let len_after = caps.get(3).unwrap().as_str().len(); @@ -214,9 +224,7 @@ fn split(to_split_on: &str) -> (&str, &str){ (new_title.trim(), new_artist.trim()) } - fn guess_meta(url: &str) -> Result { - let full_path = Path::new(YOUTUBE_DL_LOC); let output = Command::new(full_path) //.arg("--verbose") //for debugging @@ -224,17 +232,14 @@ fn guess_meta(url: &str) -> Result { .arg("--no-playlist") .arg("--ignore-config") .arg("--get-filename") - - .arg("--max-filesize") + .arg("--max-filesize") .arg("50m") - .arg("--audio-format") .arg("m4a") .arg("--audio-quality") .arg("257") .arg("--format") .arg("bestaudio[acodec=opus]/bestaudio/best") - .arg("--output") .arg("%(title)s") .arg(url) @@ -245,25 +250,21 @@ fn guess_meta(url: &str) -> Result { let (title, artist) = split(&stdout); Ok(MetaGuess { - artist: artist.to_owned(), + artist: artist.to_owned(), title: title.to_owned(), source_url: url.to_owned(), }) } -fn download_file(output_arg: &String, url: &str) - -> std::io::Result { - +fn download_file(output_arg: &String, url: &str) -> std::io::Result { let full_path = Path::new(YOUTUBE_DL_LOC); Command::new(full_path) //.arg("--verbose") //for debugging .arg("--geo-bypass") .arg("--no-playlist") .arg("--ignore-config") - - .arg("--max-filesize") + .arg("--max-filesize") .arg("50m") - //.arg("--embed-thumbnail") //dependency can not be installed .arg("--write-thumbnail") .arg("--audio-format") @@ -275,10 +276,8 @@ fn download_file(output_arg: &String, url: &str) .arg("--extract-audio") .arg("--format") .arg("bestaudio[acodec=opus]/bestaudio/best") - .arg("--output") .arg(&output_arg) - .arg(url) .output() } @@ -286,12 +285,11 @@ fn download_file(output_arg: &String, url: &str) async fn download_song(url: &str, id: u64) -> Result<(), Error> { let temp_dir = std::path::PathBuf::from(MUSIC_TEMP); if !temp_dir.exists() { - fs::create_dir(&temp_dir) - .map_err(|e| Error::CouldNotCreateTempDir(e))?; + fs::create_dir(&temp_dir).map_err(|e| Error::CouldNotCreateTempDir(e))?; } let mut output_arg = String::from(temp_dir.to_str().unwrap()); - output_arg.push_str(&format!("/{}.%(ext)s",id)); + output_arg.push_str(&format!("/{}.%(ext)s", id)); let output = download_file(&output_arg, url)?; dbg!(&output); @@ -299,17 +297,20 @@ async fn download_song(url: &str, id: u64) -> Result<(), Error> { dbg!(output.stderr.starts_with(b"ERROR:")); if !output.status.success() || output.stderr.starts_with(b"ERROR:") { dbg!("UPDATING YOUTUBE_DL"); - let since_last_updated = fs::metadata(YOUTUBE_DL_LOC).unwrap() - .created().unwrap() - .elapsed().unwrap_or(Duration::from_secs(0)); - + let since_last_updated = fs::metadata(YOUTUBE_DL_LOC) + .unwrap() + .created() + .unwrap() + .elapsed() + .unwrap_or(Duration::from_secs(0)); + // updating youtube-dl wont do anything return error dbg!(since_last_updated); - if since_last_updated < Duration::from_secs(60*60*24){ + if since_last_updated < Duration::from_secs(60 * 60 * 24) { dbg!("not updating youtube_dl, has been recently tried already"); return Err(Error::CouldNotDownloadSong(output)); } - + download_youtube_dl("https://yt-dl.org/downloads/latest/youtube-dl").await?; let output = download_file(&output_arg, url)?; if !output.status.success() { @@ -319,15 +320,15 @@ async fn download_song(url: &str, id: u64) -> Result<(), Error> { Ok(()) } -fn ffmpeg_set_meta(input: &Path, output: &Path, artist: &str, title: &str){ +fn ffmpeg_set_meta(input: &Path, output: &Path, artist: &str, title: &str) { let input = fs::canonicalize(input).unwrap(); dbg!(&input); dbg!(&output); let output = Command::new("ffmpeg") - .args(&[OsStr::new("-i"),input.as_os_str()]) - .args(&["-metadata", &format!("artist={}",artist)]) - .args(&["-metadata", &format!("title={}",title)]) + .args(&[OsStr::new("-i"), input.as_os_str()]) + .args(&["-metadata", &format!("artist={}", artist)]) + .args(&["-metadata", &format!("title={}", title)]) .args(&["-codec", "copy"]) .arg(output.as_os_str()) .output() @@ -364,12 +365,12 @@ fn update_metadata(old_path: &Path, meta: &MetaData) -> Result { } new_path.push(&meta.title); new_path.set_extension("m4a"); - + ffmpeg_set_meta(&old_path, &new_path, &meta.artist, &meta.title); - + fs::remove_file(old_path).unwrap(); //delete if parent dir is now empty - if let Some(dir) = old_path.parent(){ + if let Some(dir) = old_path.parent() { if dir.read_dir().unwrap().count() == 0 { fs::remove_dir(dir).unwrap(); } @@ -379,98 +380,97 @@ fn update_metadata(old_path: &Path, meta: &MetaData) -> Result { Ok(new_path) } -async fn handle_job(job: Job, token: String, db: sled::Tree) - -> Result<(), Error> { - +async fn handle_job(job: Job, token: String, db: sled::Tree) -> Result<(), Error> { let status = match download_song(&job.url, job.id).await { - Ok(_) => { + Ok(_) => { aquire_db_mutex(&db, job.id).await; - let db_status = db.get(&status_key(job.id)) + let db_status = db + .get(&status_key(job.id)) .unwrap() .ok_or(Error::CanNoLongerUpdateMeta)?; let db_status = bincode::deserialize(&db_status.to_vec()).unwrap(); let (new_db_status, job_status) = match db_status { Status::Queued(meta_guess) => { (Status::Downloaded(meta_guess), JobStatus::Downloaded) - }, + } Status::MetaConfirmed(meta) => { let new_path = write_metadata(job.id, &meta)?; //write meta (Status::MetaWritten((new_path, meta)), JobStatus::Finished) - }, - Status::Downloaded(_) => { - panic!("file should not yet be download!") - }, - Status::MetaWritten((_, _)) => { - panic!("file should not yet be download!") - }, + } + Status::Downloaded(_) => panic!("file should not yet be download!"), + Status::MetaWritten((_, _)) => panic!("file should not yet be download!"), }; - + let mut batch = Batch::default(); batch.insert( - &status_key(job.id), - bincode::serialize(&new_db_status).unwrap() + &status_key(job.id), + bincode::serialize(&new_db_status).unwrap(), ); - batch.insert( //unlock file lock + batch.insert( + //unlock file lock &db_mutex_key(job.id), - bincode::serialize(&false).unwrap() + bincode::serialize(&false).unwrap(), ); db.apply_batch(batch).unwrap(); job_status - }, + } Err(error) => { error!("warn error during song download: {:?}", error); //TODO remove from database JobStatus::Error - }, + } }; job.feedback.send(status, &token).await; Ok(()) } -fn song_downloader(url_rx: crossbeam_channel::Receiver, - token: String, db: sled::Tree) { - +fn song_downloader(url_rx: crossbeam_channel::Receiver, token: String, db: sled::Tree) { let mut rt = actix_rt::Runtime::new().unwrap(); - + loop { match url_rx.recv() { Ok(job) => { - if let Err(e) = rt.block_on( handle_job(job, token.clone(), db.clone())){ + if let Err(e) = rt.block_on(handle_job(job, token.clone(), db.clone())) { error!("could not handle download job: {:?}", e); } - }, - // Err means YoutubeDownloader + } + // Err means YoutubeDownloader // was dropped and this thread should stop Err(_) => return, } } } -async fn aquire_db_mutex(db: &sled::Tree, id: u64){ - while let Err(_is_locked) = db.compare_and_swap( - &db_mutex_key(id), - Some(bincode::serialize(&false).unwrap()), - Some(bincode::serialize(&true).unwrap())).unwrap(){ +async fn aquire_db_mutex(db: &sled::Tree, id: u64) { + while let Err(_is_locked) = db + .compare_and_swap( + &db_mutex_key(id), + Some(bincode::serialize(&false).unwrap()), + Some(bincode::serialize(&true).unwrap()), + ) + .unwrap() + { task::sleep(Duration::from_millis(10)).await; dbg!("blocking on mutex aquisition"); } } -fn db_mutex_key(id: u64) -> [u8;9]{ - let mut a = [0;9]; +fn db_mutex_key(id: u64) -> [u8; 9] { + let mut a = [0; 9]; a[..8].clone_from_slice(&id.to_be_bytes()); return a; } -fn status_key(id: u64) -> [u8;9]{ - let mut a = [1;9]; +fn status_key(id: u64) -> [u8; 9] { + let mut a = [1; 9]; a[..8].clone_from_slice(&id.to_be_bytes()); return a; } impl YoutubeDownloader { - pub async fn init(token: String, db: sled::Db) - -> Result<(Self, thread::JoinHandle<()>), Error> { - + pub async fn init( + token: String, + db: sled::Db, + ) -> Result<(Self, thread::JoinHandle<()>), Error> { let youtube_db = db.open_tree("youtube_dl").unwrap(); let full_path = Path::new(YOUTUBE_DL_LOC); let dir_path = Path::new(DIR); @@ -484,51 +484,51 @@ impl YoutubeDownloader { let (url_tx, url_rx) = crossbeam_channel::bounded(10); let local_token = token.clone(); - let downloader_thread = thread::spawn(move || - song_downloader(url_rx, local_token, youtube_db) - ); + let downloader_thread = + thread::spawn(move || song_downloader(url_rx, local_token, youtube_db)); - Ok((Self {url_tx, db, token}, downloader_thread)) + Ok((Self { url_tx, db, token }, downloader_thread)) } //TODO use youtube downloader to stream audio from youtube!!! - /// checks if a song can be downloaded, if so sends the command to start download to + /// checks if a song can be downloaded, if so sends the command to start download to /// a seperate thread - pub async fn add_song_to_queue(&self, url: String, - feedback: FeedbackChannel) -> Result<(), Error> { - + pub async fn add_song_to_queue( + &self, + url: String, + feedback: FeedbackChannel, + ) -> Result<(), Error> { //get metadata guess from youtube-dl let meta_guess = guess_meta(&url)?; let id = self.db.generate_id().unwrap(); let db = self.db.open_tree("youtube_dl").unwrap(); - + let db_entry = Status::Queued(meta_guess.clone()); let mut batch = Batch::default(); - batch.insert( - &status_key(id), - bincode::serialize(&db_entry).unwrap() - ); - batch.insert( - &db_mutex_key(id), - bincode::serialize(&false).unwrap() - ); + batch.insert(&status_key(id), bincode::serialize(&db_entry).unwrap()); + batch.insert(&db_mutex_key(id), bincode::serialize(&false).unwrap()); db.apply_batch(batch).unwrap(); - let job = Job {id, url: url, feedback: feedback.clone()}; + let job = Job { + id, + url: url, + feedback: feedback.clone(), + }; self.url_tx.try_send(job).unwrap(); - feedback.send(JobStatus::Queued(meta_guess, id), &self.token).await; + feedback + .send(JobStatus::Queued(meta_guess, id), &self.token) + .await; dbg!(); Ok(()) } - pub async fn meta_ok(&self, id: u64) - -> Result<(), Error> { - + pub async fn meta_ok(&self, id: u64) -> Result<(), Error> { let db = self.db.open_tree("youtube_dl").unwrap(); aquire_db_mutex(&db, id).await; - let job_status = db.get(&status_key(id)) + let job_status = db + .get(&status_key(id)) .unwrap() .ok_or(Error::CanNoLongerUpdateMeta)?; let job_status = bincode::deserialize(&job_status.to_vec()).unwrap(); @@ -540,7 +540,7 @@ impl YoutubeDownloader { source_url: meta_guess.source_url, }; Status::MetaConfirmed(new_meta) - }, + } Status::MetaConfirmed(meta) => Status::MetaConfirmed(meta), Status::Downloaded(meta_guess) => { let new_meta = MetaData { @@ -550,30 +550,27 @@ impl YoutubeDownloader { }; let new_path = write_metadata(id, &new_meta)?; Status::MetaWritten((new_path, new_meta)) - }, + } Status::MetaWritten(i) => Status::MetaWritten(i), }; - + let mut batch = Batch::default(); + batch.insert(&status_key(id), bincode::serialize(&new_status).unwrap()); batch.insert( - &status_key(id), - bincode::serialize(&new_status).unwrap() - ); - batch.insert( //unlock file lock + //unlock file lock &db_mutex_key(id), - bincode::serialize(&false).unwrap() + bincode::serialize(&false).unwrap(), ); - db.apply_batch(batch).unwrap(); + db.apply_batch(batch).unwrap(); Ok(()) } - pub async fn swap_meta(&self, id: u64) - -> Result<(), Error> { - + pub async fn swap_meta(&self, id: u64) -> Result<(), Error> { let db = self.db.open_tree("youtube_dl").unwrap(); aquire_db_mutex(&db, id).await; - let job_status = db.get(&status_key(id)) + let job_status = db + .get(&status_key(id)) .unwrap() .ok_or(Error::CanNoLongerUpdateMeta)?; let job_status = bincode::deserialize(&job_status.to_vec()).unwrap(); @@ -585,12 +582,12 @@ impl YoutubeDownloader { source_url: meta_guess.source_url, }; Status::MetaConfirmed(new_meta) - }, + } Status::MetaConfirmed(mut meta) => { meta.title = meta.artist.clone(); meta.artist = meta.title.clone(); Status::MetaConfirmed(meta) - }, + } Status::Downloaded(meta_guess) => { let new_meta = MetaData { title: meta_guess.artist, @@ -599,85 +596,79 @@ impl YoutubeDownloader { }; let new_path = write_metadata(id, &new_meta)?; Status::MetaWritten((new_path, new_meta)) - }, + } Status::MetaWritten((path, mut meta)) => { meta.artist = meta.title.clone(); meta.title = meta.artist.clone(); let new_path = update_metadata(&path, &meta)?; Status::MetaWritten((new_path, meta)) - }, + } }; - + let mut batch = Batch::default(); + batch.insert(&status_key(id), bincode::serialize(&new_status).unwrap()); batch.insert( - &status_key(id), - bincode::serialize(&new_status).unwrap() - ); - batch.insert( //unlock file lock + //unlock file lock &db_mutex_key(id), - bincode::serialize(&false).unwrap() + bincode::serialize(&false).unwrap(), ); - db.apply_batch(batch).unwrap(); + db.apply_batch(batch).unwrap(); Ok(()) } - pub async fn no_meta(&self, id: u64) - -> Result<(), Error> { - + pub async fn no_meta(&self, id: u64) -> Result<(), Error> { let db = self.db.open_tree("youtube_dl").unwrap(); aquire_db_mutex(&db, id).await; - let job_status = db.get(&status_key(id)) + let job_status = db + .get(&status_key(id)) .unwrap() .ok_or(Error::CanNoLongerUpdateMeta)?; let job_status = bincode::deserialize(&job_status.to_vec()).unwrap(); let new_status = match job_status { Status::Queued(meta) => { let new_meta = MetaData { - title: format!("{} {}",meta.title,meta.artist), + title: format!("{} {}", meta.title, meta.artist), artist: "".to_owned(), source_url: meta.source_url, }; Status::MetaConfirmed(new_meta) - }, + } Status::MetaConfirmed(mut meta) => { - meta.title = format!("{} {}",meta.title,meta.artist); + meta.title = format!("{} {}", meta.title, meta.artist); meta.artist = "".to_owned(); Status::MetaConfirmed(meta) - }, + } Status::Downloaded(meta) => { let new_meta = MetaData { - title: format!("{} {}",meta.title,meta.artist), + title: format!("{} {}", meta.title, meta.artist), artist: "".to_owned(), source_url: meta.source_url, }; let new_path = write_metadata(id, &new_meta)?; Status::MetaWritten((new_path, new_meta)) - }, + } Status::MetaWritten((path, mut meta)) => { - meta.title = format!("{} {}",meta.title,meta.artist); + meta.title = format!("{} {}", meta.title, meta.artist); meta.artist = "".to_owned(); let new_path = update_metadata(&path, &meta)?; Status::MetaWritten((new_path, meta)) - }, + } }; - + let mut batch = Batch::default(); + batch.insert(&status_key(id), bincode::serialize(&new_status).unwrap()); batch.insert( - &status_key(id), - bincode::serialize(&new_status).unwrap() - ); - batch.insert( //unlock file lock + //unlock file lock &db_mutex_key(id), - bincode::serialize(&false).unwrap() + bincode::serialize(&false).unwrap(), ); db.apply_batch(batch).unwrap(); - + Ok(()) } } - #[cfg(test)] mod tests { use super::*; @@ -692,11 +683,9 @@ mod tests { }*/ #[test] - fn test_split(){ + fn test_split() { let (artist, title) = split("Merlin 4 Soundtrack \"The Burial\" 04"); assert_eq!(artist, "Merlin 4 Soundtrack"); assert_eq!(title, "The Burial"); } - - -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index adcab967..f96bc423 100755 --- a/src/main.rs +++ b/src/main.rs @@ -1,16 +1,16 @@ #[macro_use] extern crate log; -use structopt::StructOpt; use sled; use std::path::PathBuf; +use structopt::StructOpt; mod controller; mod input; +use input::bot; use input::web_api::server; use input::web_api::server::{PasswordDatabase, State}; -use input::bot; mod errors; @@ -18,85 +18,93 @@ mod errors; #[structopt(name = "homeautomation")] struct Opt { #[structopt(short = "p", long = "port", default_value = "8080")] - port: u16, - #[structopt(short = "e", long = "external-port")] - external_port: Option, + port: u16, + #[structopt(short = "e", long = "external-port")] + external_port: Option, #[structopt(short = "t", long = "token")] - token: String, + token: String, #[structopt(short = "d", long = "domain")] - domain: String, + domain: String, #[structopt(short = "a", long = "admin-password")] - password: String, - #[structopt(short = "k", long = "keys", default_value="keys")] - key_dir: PathBuf, + password: String, + #[structopt(short = "k", long = "keys", default_value = "keys")] + key_dir: PathBuf, #[structopt(short = "i", long = "allowed-telegram-ids")] - valid_ids: Vec, + valid_ids: Vec, #[structopt(short = "h", long = "ha-key")] - ha_key: String, + ha_key: String, } #[actix_rt::main] async fn main() { - let opt = Opt::from_args(); - errors::setup_logging(1).unwrap(); - - let db = sled::Config::default() //651ms - .path("database") - .flush_every_ms(None) //do not flush to disk unless explicitly asked - .cache_capacity(1024 * 1024 * 32) //32 mb cache - .open().unwrap(); - - let mut passw_db = PasswordDatabase::from_db(&db).unwrap(); - passw_db.add_admin(&opt.password).unwrap(); - - let (controller_tx, controller_rx) = crossbeam_channel::unbounded(); - - let (alarms, _waker_thread) = input::alarms::Alarms::setup( - controller_tx.clone(), - db.clone()).unwrap(); - let (youtube_dl, _downloader_thread) = input::YoutubeDownloader::init( - opt.token.clone(), db.clone()).await.unwrap(); - let (mpd_status, _mpd_watcher_thread, _updater_tx) = - input::MpdStatus::start_updating() - .unwrap(); - - let _controller_thread = controller::start( - controller_rx, - mpd_status.clone()).unwrap(); - - let state = State::new( - passw_db, - controller_tx.clone(), - alarms, - youtube_dl, - opt.token.clone(), - opt.valid_ids.clone()); - - //start the webserver - let _web_handle = server::start_webserver( - &opt.key_dir, state, opt.port, - opt.domain.clone(), opt.ha_key.clone()).unwrap(); - - - bot::set_webhook( - &opt.domain, &opt.token, - opt.external_port.unwrap_or_else(|| opt.port)).await.unwrap(); - - loop { - std::thread::park(); - } - - /*println!("press: q to quit"); - loop { - let mut input = String::new(); - stdin().read_line(&mut input).unwrap(); - match input.as_str() { - //"n\n" => helper::add_user(& passw_db), - "q\n" => break, - _ => println!("unhandled"), - }; - } - println!("shutting down"); - web_handle.stop(true).await; - input::MpdStatus::stop_updating(updater_tx);*/ + let opt = Opt::from_args(); + errors::setup_logging(1).unwrap(); + + let db = sled::Config::default() //651ms + .path("database") + .flush_every_ms(None) //do not flush to disk unless explicitly asked + .cache_capacity(1024 * 1024 * 32) //32 mb cache + .open() + .unwrap(); + + let mut passw_db = PasswordDatabase::from_db(&db).unwrap(); + passw_db.add_admin(&opt.password).unwrap(); + + let (controller_tx, controller_rx) = crossbeam_channel::unbounded(); + + let (alarms, _waker_thread) = + input::alarms::Alarms::setup(controller_tx.clone(), db.clone()).unwrap(); + let (youtube_dl, _downloader_thread) = + input::YoutubeDownloader::init(opt.token.clone(), db.clone()) + .await + .unwrap(); + let (mpd_status, _mpd_watcher_thread, _updater_tx) = + input::MpdStatus::start_updating().unwrap(); + + let _controller_thread = controller::start(controller_rx, mpd_status.clone()).unwrap(); + + let state = State::new( + passw_db, + controller_tx.clone(), + alarms, + youtube_dl, + opt.token.clone(), + opt.valid_ids.clone(), + ); + + //start the webserver + let _web_handle = server::start_webserver( + &opt.key_dir, + state, + opt.port, + opt.domain.clone(), + opt.ha_key.clone(), + ) + .unwrap(); + + bot::set_webhook( + &opt.domain, + &opt.token, + opt.external_port.unwrap_or_else(|| opt.port), + ) + .await + .unwrap(); + + loop { + std::thread::park(); + } + + /*println!("press: q to quit"); + loop { + let mut input = String::new(); + stdin().read_line(&mut input).unwrap(); + match input.as_str() { + //"n\n" => helper::add_user(& passw_db), + "q\n" => break, + _ => println!("unhandled"), + }; + } + println!("shutting down"); + web_handle.stop(true).await; + input::MpdStatus::stop_updating(updater_tx);*/ } From d0da775330140772b8a1289dc62d12a882d45b98 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Sun, 11 Oct 2020 02:48:51 +0200 Subject: [PATCH 055/687] removes todo() to prevent crash --- src/controller/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controller/mod.rs b/src/controller/mod.rs index b34ad61f..f75491b4 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -168,7 +168,7 @@ fn handle_sensor( ) -> Option { match value { SensorValue::ButtonPress(press) => handle_buttonpress(press, mods, system), - _ => todo!(), + _ => None, // for now we ignore the other sensor data } } From ac06f80fa59f7c22c9d05e588e90f122d5fc0b08 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Wed, 27 Jan 2021 22:15:09 +0100 Subject: [PATCH 056/687] adjusts long press/short press behavior --- Cargo.lock | 626 ++++++++++++++++++++++++++---------------- src/controller/mod.rs | 11 +- src/main.rs | 14 - 3 files changed, 397 insertions(+), 254 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8dd3fe1f..22e03c29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,14 +22,14 @@ dependencies = [ "crossbeam-channel 0.3.9", "dirs", "fern", - "futures 0.3.6", + "futures 0.3.8", "gpio-cdev", "hex", "linux-embedded-hal", "log 0.4.11", "mpd", "nix 0.17.0", - "num", + "num 0.2.1", "pagecache", "philipshue", "rand 0.6.5", @@ -89,7 +89,7 @@ dependencies = [ "futures-core", "futures-sink", "log 0.4.11", - "tokio 0.2.22", + "tokio 0.2.23", "tokio-util 0.2.0", ] @@ -104,8 +104,8 @@ dependencies = [ "futures-core", "futures-sink", "log 0.4.11", - "pin-project", - "tokio 0.2.22", + "pin-project 0.4.27", + "tokio 0.2.23", "tokio-util 0.3.1", ] @@ -121,7 +121,7 @@ dependencies = [ "actix-utils 1.0.6", "derive_more", "either", - "futures 0.3.6", + "futures 0.3.8", "http 0.2.1", "log 0.4.11", "rustls 0.16.0", @@ -180,7 +180,7 @@ dependencies = [ "futures-core", "futures-util", "fxhash", - "h2 0.2.6", + "h2 0.2.7", "http 0.2.1", "httparse", "indexmap", @@ -189,7 +189,7 @@ dependencies = [ "log 0.4.11", "mime 0.3.16", "percent-encoding 2.1.0", - "pin-project", + "pin-project 0.4.27", "rand 0.7.3", "regex", "ring", @@ -209,7 +209,7 @@ checksum = "2a379b0639c293292d71defb8cc1f94c87b7705c904adf044338ad392df77c7a" dependencies = [ "actix-service", "actix-web", - "futures 0.3.6", + "futures 0.3.8", "serde", "serde_json", "time", @@ -222,7 +222,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a60f9ba7c4e6df97f3aacb14bb5c0cd7d98a49dcbaed0d7f292912ad9a6a3ed2" dependencies = [ "quote 1.0.7", - "syn 1.0.44", + "syn 1.0.48", ] [[package]] @@ -275,7 +275,7 @@ dependencies = [ "futures-channel", "futures-util", "smallvec 1.4.2", - "tokio 0.2.22", + "tokio 0.2.23", ] [[package]] @@ -305,7 +305,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0052435d581b5be835d11f4eb3bce417c8af18d87ddf8ace99f8e67e595882bb" dependencies = [ "futures-util", - "pin-project", + "pin-project 0.4.27", ] [[package]] @@ -349,7 +349,7 @@ dependencies = [ "actix-utils 1.0.6", "derive_more", "either", - "futures 0.3.6", + "futures 0.3.8", "log 0.4.11", "rustls 0.16.0", "tokio-rustls 0.12.3", @@ -369,9 +369,9 @@ dependencies = [ "bitflags 1.2.1", "bytes 0.5.6", "either", - "futures 0.3.6", + "futures 0.3.8", "log 0.4.11", - "pin-project", + "pin-project 0.4.27", "slab", ] @@ -391,7 +391,7 @@ dependencies = [ "futures-sink", "futures-util", "log 0.4.11", - "pin-project", + "pin-project 0.4.27", "slab", ] @@ -417,19 +417,19 @@ dependencies = [ "bytes 0.5.6", "derive_more", "encoding_rs", - "futures 0.3.6", + "futures 0.3.8", "fxhash", "log 0.4.11", "mime 0.3.16", "net2", - "pin-project", + "pin-project 0.4.27", "regex", "rustls 0.16.0", "serde", "serde_json", "serde_urlencoded 0.6.1", "time", - "url 2.1.1", + "url 2.2.0", ] [[package]] @@ -440,7 +440,7 @@ checksum = "a71bf475cbe07281d0b3696abb48212db118e7e23219f13596ce865235ff5766" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.44", + "syn 1.0.48", ] [[package]] @@ -469,9 +469,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072" +checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423" dependencies = [ "gimli", ] @@ -484,9 +484,9 @@ checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" [[package]] name = "aho-corasick" -version = "0.7.13" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" dependencies = [ "memchr", ] @@ -500,12 +500,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "arc-swap" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034" - [[package]] name = "arrayref" version = "0.3.6" @@ -523,9 +517,9 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "async-channel" @@ -540,9 +534,9 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d373d78ded7d0b3fa8039375718cde0aace493f2e34fb60f51cbf567562ca801" +checksum = "eb877970c7b440ead138f6321a3b5395d6061183af779340b65e20c0fede9146" dependencies = [ "async-task", "concurrent-queue", @@ -554,9 +548,9 @@ dependencies = [ [[package]] name = "async-global-executor" -version = "1.3.0" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fefeb39da249f4c33af940b779a56723ce45809ef5c54dad84bb538d4ffb6d9e" +checksum = "73079b49cd26b8fd5a15f68fc7707fc78698dc2a3d61430f2a7a9430230dfa04" dependencies = [ "async-executor", "async-io", @@ -567,9 +561,9 @@ dependencies = [ [[package]] name = "async-io" -version = "1.1.10" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54bc4c1c7292475efb2253227dbcfad8fe1ca4c02bc62c510cc2f3da5c4704e" +checksum = "40a0b2bb8ae20fede194e779150fe283f65a4a08461b496de546ec366b174ad9" dependencies = [ "concurrent-queue", "fastrand", @@ -596,15 +590,15 @@ dependencies = [ [[package]] name = "async-std" -version = "1.6.5" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9fa76751505e8df1c7a77762f60486f60c71bbd9b8557f4da6ad47d083732ed" +checksum = "a7e82538bc65a25dbdff70e4c5439d52f068048ab97cdea0acd73f131594caa1" dependencies = [ "async-global-executor", "async-io", "async-mutex", "blocking", - "crossbeam-utils 0.7.2", + "crossbeam-utils 0.8.0", "futures-channel", "futures-core", "futures-io", @@ -623,9 +617,9 @@ dependencies = [ [[package]] name = "async-task" -version = "4.0.2" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ab27c1aa62945039e44edaeee1dc23c74cc0c303dd5fe0fb462a184f1c3a518" +checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" [[package]] name = "async-trait" @@ -635,7 +629,7 @@ checksum = "b246867b8b3b6ae56035f1eb1ed557c1d8eae97f0d53696138a50fa0e3a3b8c0" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.44", + "syn 1.0.48", ] [[package]] @@ -693,12 +687,12 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.52" +version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f813291114c186a042350e787af10c26534601062603d888be110f59f85ef8fa" +checksum = "2baad346b2d4e94a24347adeee9c7a93f412ee94b9cc26e5b59dea23848e9f28" dependencies = [ "addr2line", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object", @@ -754,14 +748,28 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "bitspec" +version = "1.0.0" +source = "git+https://github.com/dskleingeld/bitspec?branch=bool-fields#65e92b1ad3d3900a634cc6828785ed4054c83985" +dependencies = [ + "log 0.4.11", + "num 0.3.1", + "rand 0.5.6", + "serde", + "serde_derive", + "serde_yaml", + "text_io", +] + [[package]] name = "blake2b_simd" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" dependencies = [ "arrayref", - "arrayvec 0.5.1", + "arrayvec 0.5.2", "constant_time_eq", ] @@ -869,9 +877,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed67cbde08356238e75fc4656be4749481eeffb09e19f320a25237d5221c985d" +checksum = "f1770ced377336a88a67c473594ccc14eca6f4559217c34f64aac8f83d641b40" [[package]] name = "cfg-if" @@ -879,6 +887,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "chrono" version = "0.4.19" @@ -956,6 +970,12 @@ dependencies = [ "cache-padded", ] +[[package]] +name = "const_fn" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab" + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -1014,11 +1034,11 @@ checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" [[package]] name = "crc32fast" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1032,12 +1052,12 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.4.4" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" +checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" dependencies = [ - "crossbeam-utils 0.7.2", - "maybe-uninit", + "cfg-if 1.0.0", + "crossbeam-utils 0.8.0", ] [[package]] @@ -1051,6 +1071,17 @@ dependencies = [ "maybe-uninit", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-epoch 0.9.0", + "crossbeam-utils 0.8.0", +] + [[package]] name = "crossbeam-epoch" version = "0.7.2" @@ -1058,7 +1089,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" dependencies = [ "arrayvec 0.4.12", - "cfg-if", + "cfg-if 0.1.10", "crossbeam-utils 0.6.6", "lazy_static", "memoffset", @@ -1072,7 +1103,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ "autocfg 1.0.1", - "cfg-if", + "cfg-if 0.1.10", "crossbeam-utils 0.7.2", "lazy_static", "maybe-uninit", @@ -1080,13 +1111,27 @@ dependencies = [ "scopeguard 1.1.0", ] +[[package]] +name = "crossbeam-epoch" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0f606a85340376eef0d6d8fec399e6d4a544d648386c6645eb6d0653b27d9f" +dependencies = [ + "cfg-if 1.0.0", + "const_fn", + "crossbeam-utils 0.8.0", + "lazy_static", + "memoffset", + "scopeguard 1.1.0", +] + [[package]] name = "crossbeam-queue" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "crossbeam-utils 0.7.2", "maybe-uninit", ] @@ -1097,7 +1142,7 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "lazy_static", ] @@ -1108,7 +1153,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ "autocfg 1.0.1", - "cfg-if", + "cfg-if 0.1.10", + "lazy_static", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec91540d98355f690a86367e566ecad2e9e579f230230eb7c21398372be73ea5" +dependencies = [ + "autocfg 1.0.1", + "cfg-if 1.0.0", + "const_fn", "lazy_static", ] @@ -1129,7 +1186,7 @@ checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.44", + "syn 1.0.48", ] [[package]] @@ -1138,7 +1195,7 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "dirs-sys", ] @@ -1177,11 +1234,11 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.24" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a51b8cf747471cb9499b6d59e59b0444f4c90eba8968c4e44874e92b5b64ace2" +checksum = "801bbab217d7f79c0062f4f7205b5d4427c6d1a7bd7aafdd1475f7c59d62b283" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1193,7 +1250,7 @@ dependencies = [ "heck", "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.44", + "syn 1.0.48", ] [[package]] @@ -1247,7 +1304,7 @@ checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.44", + "syn 1.0.48", "synstructure", ] @@ -1273,11 +1330,11 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da80be589a72651dcda34d8b35bcdc9b7254ad06325611074d9cc0fbb19f60ee" +checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crc32fast", "libc", "miniz_oxide", @@ -1289,6 +1346,16 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "form_urlencoded" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00" +dependencies = [ + "matches", + "percent-encoding 2.1.0", +] + [[package]] name = "fs2" version = "0.4.3" @@ -1329,9 +1396,9 @@ checksum = "4c7e4c2612746b0df8fed4ce0c69156021b704c9aefa360311c04e6e9e002eed" [[package]] name = "futures" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8e3078b7b2a8a671cb7a3d17b4760e4181ea243227776ba83fd043b4ca034e" +checksum = "9b3b0c040a1fe6529d30b3c5944b280c7f0dcb2930d2c3062bca967b602583d0" dependencies = [ "futures-channel", "futures-core", @@ -1344,9 +1411,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a4d35f7401e948629c9c3d6638fb9bf94e0b2121e96c3b428cc4e631f3eb74" +checksum = "4b7109687aa4e177ef6fe84553af6280ef2778bdb7783ba44c9dc3399110fe64" dependencies = [ "futures-core", "futures-sink", @@ -1354,9 +1421,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d674eaa0056896d5ada519900dbf97ead2e46a7b6621e8160d79e2f2e1e2784b" +checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748" [[package]] name = "futures-cpupool" @@ -1370,9 +1437,9 @@ dependencies = [ [[package]] name = "futures-executor" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc709ca1da6f66143b8c9bec8e6260181869893714e9b5a490b169b0414144ab" +checksum = "4caa2b2b68b880003057c1dd49f1ed937e38f22fcf6c212188a121f08cf40a65" dependencies = [ "futures-core", "futures-task", @@ -1381,15 +1448,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc94b64bb39543b4e432f1790b6bf18e3ee3b74653c5449f63310e9a74b123c" +checksum = "611834ce18aaa1bd13c4b374f5d653e1027cf99b6b502584ff8c9a64413b30bb" [[package]] name = "futures-lite" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "381a7ad57b1bad34693f63f6f377e1abded7a9c85c9d3eb6771e11c60aaadab9" +checksum = "5e6c079abfac3ab269e2927ec048dabc89d009ebfdda6b8ee86624f30c689658" dependencies = [ "fastrand", "futures-core", @@ -1402,36 +1469,36 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f57ed14da4603b2554682e9f2ff3c65d7567b53188db96cb71538217fc64581b" +checksum = "77408a692f1f97bcc61dc001d752e00643408fbc922e4d634c655df50d595556" dependencies = [ "proc-macro-hack", "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.44", + "syn 1.0.48", ] [[package]] name = "futures-sink" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8764258ed64ebc5d9ed185cf86a95db5cac810269c5d20ececb32e0088abbd" +checksum = "f878195a49cee50e006b02b93cf7e0a95a38ac7b776b4c4d9cc1207cd20fcb3d" [[package]] name = "futures-task" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd26820a9f3637f1302da8bceba3ff33adbe53464b54ca24d4e2d4f1db30f94" +checksum = "7c554eb5bf48b2426c4771ab68c6b14468b6e76cc90996f528c3338d761a4d0d" dependencies = [ "once_cell", ] [[package]] name = "futures-util" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a894a0acddba51a2d49a6f4263b1e64b8c579ece8af50fa86503d52cd1eea34" +checksum = "d304cff4a7b99cfb7986f7d43fbe93d175e72e704a8860787cc95e9ffd85cbd2" dependencies = [ "futures-channel", "futures-core", @@ -1440,7 +1507,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project", + "pin-project 1.0.1", "pin-utils", "proc-macro-hack", "proc-macro-nested", @@ -1462,16 +1529,16 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] name = "gimli" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724" +checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" [[package]] name = "gloo-timers" @@ -1489,7 +1556,7 @@ dependencies = [ [[package]] name = "gpio-cdev" version = "0.4.0" -source = "git+https://github.com/rust-embedded/gpio-cdev#a8c1c10f3b5f5d76ef34e4581fb0c621865b364b" +source = "git+https://github.com/rust-embedded/gpio-cdev?branch=master#a8c1c10f3b5f5d76ef34e4581fb0c621865b364b" dependencies = [ "bitflags 1.2.1", "libc", @@ -1516,9 +1583,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53" +checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535" dependencies = [ "bytes 0.5.6", "fnv", @@ -1528,9 +1595,10 @@ dependencies = [ "http 0.2.1", "indexmap", "slab", - "tokio 0.2.22", + "tokio 0.2.23", "tokio-util 0.3.1", "tracing", + "tracing-futures", ] [[package]] @@ -1677,23 +1745,23 @@ dependencies = [ [[package]] name = "hyper" -version = "0.13.8" +version = "0.13.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f3afcfae8af5ad0576a31e768415edb627824129e8e5a29b8bfccb2f234e835" +checksum = "f6ad767baac13b44d4529fcf58ba2cd0995e36e7b435bc5b039de6f47e880dbf" dependencies = [ "bytes 0.5.6", "futures-channel", "futures-core", "futures-util", - "h2 0.2.6", + "h2 0.2.7", "http 0.2.1", "http-body 0.3.1", "httparse", "httpdate", "itoa", - "pin-project", + "pin-project 1.0.1", "socket2", - "tokio 0.2.22", + "tokio 0.2.23", "tower-service 0.3.0", "tracing", "want 0.3.0", @@ -1725,10 +1793,10 @@ dependencies = [ "bytes 0.5.6", "ct-logs", "futures-util", - "hyper 0.13.8", + "hyper 0.13.9", "rustls 0.16.0", "rustls-native-certs", - "tokio 0.2.22", + "tokio 0.2.23", "tokio-rustls 0.12.3", "webpki", ] @@ -1741,10 +1809,10 @@ checksum = "37743cc83e8ee85eacfce90f2f4102030d9ff0a95244098d781e9bee4a90abb6" dependencies = [ "bytes 0.5.6", "futures-util", - "hyper 0.13.8", + "hyper 0.13.9", "log 0.4.11", "rustls 0.18.1", - "tokio 0.2.22", + "tokio 0.2.23", "tokio-rustls 0.14.1", "webpki", ] @@ -1795,11 +1863,11 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66" +checksum = "cb1fc4429a33e1f80d41dc9fea4d108a88bec1de8053878898ae448a0b52f613" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1890,9 +1958,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.79" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743" +checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614" [[package]] name = "linked-hash-map" @@ -1956,7 +2024,7 @@ version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", ] [[package]] @@ -1988,9 +2056,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.3.3" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" [[package]] name = "memoffset" @@ -2054,7 +2122,7 @@ version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "fuchsia-zircon", "fuchsia-zircon-sys", "iovec", @@ -2145,7 +2213,7 @@ version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "winapi 0.3.9", ] @@ -2157,7 +2225,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a7bb1da2be7da3cbffda73fc681d509ffd9e665af478d2bee1907cee0bc64b2" dependencies = [ "bitflags 0.4.0", - "cfg-if", + "cfg-if 0.1.10", "libc", "rustc_version 0.1.7", "semver 0.1.20", @@ -2172,7 +2240,7 @@ checksum = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" dependencies = [ "bitflags 1.2.1", "cc", - "cfg-if", + "cfg-if 0.1.10", "libc", "void", ] @@ -2185,7 +2253,7 @@ checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" dependencies = [ "bitflags 1.2.1", "cc", - "cfg-if", + "cfg-if 0.1.10", "libc", "void", ] @@ -2212,11 +2280,25 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" dependencies = [ - "num-bigint", - "num-complex", + "num-bigint 0.2.6", + "num-complex 0.2.4", + "num-integer", + "num-iter", + "num-rational 0.2.4", + "num-traits", +] + +[[package]] +name = "num" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" +dependencies = [ + "num-bigint 0.3.1", + "num-complex 0.3.1", "num-integer", "num-iter", - "num-rational", + "num-rational 0.3.2", "num-traits", ] @@ -2231,6 +2313,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e9a41747ae4633fce5adffb4d2e81ffc5e89593cb19917f8fb2cc5ff76507bf" +dependencies = [ + "autocfg 1.0.1", + "num-integer", + "num-traits", +] + [[package]] name = "num-complex" version = "0.2.4" @@ -2241,11 +2334,20 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-complex" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" +dependencies = [ + "num-traits", +] + [[package]] name = "num-integer" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" dependencies = [ "autocfg 1.0.1", "num-traits", @@ -2253,9 +2355,9 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.41" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f" +checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" dependencies = [ "autocfg 1.0.1", "num-integer", @@ -2269,16 +2371,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ "autocfg 1.0.1", - "num-bigint", + "num-bigint 0.2.6", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +dependencies = [ + "autocfg 1.0.1", + "num-bigint 0.3.1", "num-integer", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ "autocfg 1.0.1", ] @@ -2295,15 +2409,15 @@ dependencies = [ [[package]] name = "object" -version = "0.20.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5" +checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" [[package]] name = "once_cell" -version = "1.4.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad" +checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" [[package]] name = "openssl-probe" @@ -2418,7 +2532,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "cloudabi 0.0.3", "libc", "redox_syscall", @@ -2433,7 +2547,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "cloudabi 0.0.3", "libc", "redox_syscall", @@ -2447,7 +2561,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "cloudabi 0.1.0", "instant", "libc", @@ -2519,7 +2633,7 @@ dependencies = [ [[package]] name = "philipshue" version = "0.3.2" -source = "git+https://github.com/dskleingeld/philipshue#c52c7fa306a78c3432f5619bb4de75ccd55fb19f" +source = "git+https://github.com/dskleingeld/philipshue?branch=master#c52c7fa306a78c3432f5619bb4de75ccd55fb19f" dependencies = [ "error-chain 0.11.0", "reqwest 0.9.24", @@ -2530,29 +2644,49 @@ dependencies = [ [[package]] name = "pin-project" -version = "0.4.26" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffbc8e94b38ea3d2d8ba92aea2983b503cd75d0888d75b86bb37970b5698e15" +dependencies = [ + "pin-project-internal 0.4.27", +] + +[[package]] +name = "pin-project" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13fbdfd6bdee3dc9be46452f86af4a4072975899cf8592466668620bebfbcc17" +checksum = "ee41d838744f60d959d7074e3afb6b35c7456d0f61cad38a24e35e6553f73841" dependencies = [ - "pin-project-internal", + "pin-project-internal 1.0.1", ] [[package]] name = "pin-project-internal" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82fb1329f632c3552cf352d14427d57a511b1cf41db93b3a7d77906a82dcc8e" +checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.44", + "syn 1.0.48", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81a4ffa594b66bff340084d4081df649a7dc049ac8d7fc458d8e628bfbbb2f86" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.7", + "syn 1.0.48", ] [[package]] name = "pin-project-lite" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e555d9e657502182ac97b539fb3dae8b79cda19e3e4f8ffb5e8de4f18df93c95" +checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b" [[package]] name = "pin-utils" @@ -2562,11 +2696,11 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "polling" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab773feb154f12c49ffcfd66ab8bdcf9a1843f950db48b0d8be9d4393783b058" +checksum = "a2a7bc6b2a29e632e45451c941832803a18cce6781db04de8a04696cdca8bde4" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "log 0.4.11", "wepoll-sys", @@ -2575,9 +2709,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "proc-macro-error" @@ -2588,7 +2722,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.44", + "syn 1.0.48", "version_check 0.9.2", ] @@ -2605,9 +2739,9 @@ dependencies = [ [[package]] name = "proc-macro-hack" -version = "0.5.18" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro-nested" @@ -2643,7 +2777,7 @@ dependencies = [ "idna 0.2.0", "lazy_static", "regex", - "url 2.1.1", + "url 2.2.0", ] [[package]] @@ -2832,25 +2966,25 @@ dependencies = [ [[package]] name = "rayon" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf6960dc9a5b4ee8d3e4c5787b4a112a8818e0290a42ff664ad60692fdf2032" +checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" dependencies = [ "autocfg 1.0.1", - "crossbeam-deque", + "crossbeam-deque 0.8.0", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c4fec834fb6e6d2dd5eece3c7b432a52f0ba887cf40e595190c4107edc08bf" +checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" dependencies = [ - "crossbeam-channel 0.4.4", - "crossbeam-deque", - "crossbeam-utils 0.7.2", + "crossbeam-channel 0.5.0", + "crossbeam-deque 0.8.0", + "crossbeam-utils 0.8.0", "lazy_static", "num_cpus", ] @@ -2883,9 +3017,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.3.9" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" +checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" dependencies = [ "aho-corasick", "memchr", @@ -2895,9 +3029,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.18" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" +checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" [[package]] name = "remove_dir_all" @@ -2957,7 +3091,7 @@ dependencies = [ "futures-util", "http 0.2.1", "http-body 0.3.1", - "hyper 0.13.8", + "hyper 0.13.9", "hyper-rustls 0.21.0", "ipnet", "js-sys", @@ -2970,9 +3104,9 @@ dependencies = [ "rustls 0.18.1", "serde", "serde_urlencoded 0.6.1", - "tokio 0.2.22", + "tokio 0.2.23", "tokio-rustls 0.14.1", - "url 2.1.1", + "url 2.2.0", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -3028,9 +3162,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2610b7f643d18c87dff3b489950269617e6601a51f1f05aa5daefee36f64f0b" +checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" [[package]] name = "rustc-serialize" @@ -3177,16 +3311,17 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "sensor_value" version = "0.1.0" -source = "git+https://github.com/dskleingeld/sensor_central.git?branch=boolean-fields#cec0bceefb1af5d9e968b6904a03f6933225f9c2" +source = "git+https://github.com/dskleingeld/sensor_central.git?branch=boolean-fields#1768323c876411071d6db297c34986eaf0aaaccf" dependencies = [ + "bitspec", "serde", ] [[package]] name = "serde" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5" +checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a" dependencies = [ "serde_derive", ] @@ -3203,20 +3338,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8" +checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.44", + "syn 1.0.48", ] [[package]] name = "serde_json" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a230ea9107ca2220eea9d46de97eddcb04cd00e92d13dda78e478dd33fa82bd4" +checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95" dependencies = [ "itoa", "ryu", @@ -3244,14 +3379,14 @@ dependencies = [ "dtoa", "itoa", "serde", - "url 2.1.1", + "url 2.2.0", ] [[package]] name = "serde_yaml" -version = "0.8.13" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae3e2dd40a7cdc18ca80db804b7f461a39bb721160a85c9a1fa30134bf3c02a5" +checksum = "f7baae0a99f1a324984bcdc5f0718384c1f69775f1c7eec8b859b71b443e3fd7" dependencies = [ "dtoa", "linked-hash-map", @@ -3267,11 +3402,10 @@ checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" [[package]] name = "signal-hook-registry" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e12110bc539e657a646068aaf5eb5b63af9d0c1f7b29c97113fad80e15f035" +checksum = "ce32ea0c6c56d5eacaeb814fbed9960547021d3edd010ded1425f180536b20ab" dependencies = [ - "arc-swap", "libc", ] @@ -3320,11 +3454,11 @@ checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252" [[package]] name = "socket2" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1fa70dc5c8104ec096f4fe7ede7a221d35ae13dcd19ba1ad9a81d2cab9a1c44" +checksum = "7fd8b795c389288baa5f355489c65e71fd48a02104600d15c4cfbc561e9e429d" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "redox_syscall", "winapi 0.3.9", @@ -3370,9 +3504,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a7159e7d0dbcab6f9c980d7971ef50f3ff5753081461eeda120d5974a4ee95" +checksum = "126d630294ec449fae0b16f964e35bf3c74f940da9dca17ee9b905f7b3112eb8" dependencies = [ "clap", "lazy_static", @@ -3381,15 +3515,15 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc47de4dfba76248d1e9169ccff240eea2a4dc1e34e309b95b2393109b4b383" +checksum = "65e51c492f9e23a220534971ff5afc14037289de430e3c83f9daf6a1b6ae91e8" dependencies = [ "heck", "proc-macro-error", "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.44", + "syn 1.0.48", ] [[package]] @@ -3405,9 +3539,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.44" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e03e57e4fcbfe7749842d53e24ccb9aa12b7252dbe5e91d2acad31834c8b8fdd" +checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", @@ -3422,7 +3556,7 @@ checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.44", + "syn 1.0.48", "unicode-xid 0.2.1", ] @@ -3442,12 +3576,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb29fb11ef40c839c1c6b4e9c2ec4f357f9f674491e9df5a8c94f8cc2005f860" dependencies = [ "bytes 0.5.6", - "futures 0.3.6", - "hyper 0.13.8", + "futures 0.3.8", + "hyper 0.13.9", "hyper-rustls 0.19.1", "multipart", "telegram-bot-raw", - "tokio 0.2.22", + "tokio 0.2.23", "tracing", "tracing-futures", ] @@ -3471,7 +3605,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "rand 0.7.3", "redox_syscall", @@ -3479,6 +3613,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "text_io" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb170b4f47dc48835fbc56259c12d8963e542b05a24be2e3a1f5a6c320fd2d4" + [[package]] name = "textwrap" version = "0.11.0" @@ -3519,9 +3659,18 @@ dependencies = [ [[package]] name = "tinyvec" -version = "0.3.4" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b78a366903f506d2ad52ca8dc552102ffdd3e937ba8a227f024dc1d1eae28575" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" @@ -3549,9 +3698,9 @@ dependencies = [ [[package]] name = "tokio" -version = "0.2.22" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d34ca54d84bf2b5b4d7d31e901a8464f7b60ac145a284fba25ceb801f2ddccd" +checksum = "a6d7ad61edd59bfcc7e80dababf0f4aed2e6d5e0ba1659356ae889752dfc12ff" dependencies = [ "bytes 0.5.6", "fnv", @@ -3673,7 +3822,7 @@ checksum = "3068d891551949b37681724d6b73666787cc63fa8e255c812a41d2513aff9775" dependencies = [ "futures-core", "rustls 0.16.0", - "tokio 0.2.22", + "tokio 0.2.23", "webpki", ] @@ -3685,7 +3834,7 @@ checksum = "e12831b255bcfa39dc0436b01e19fea231a37db570686c06ee72c423479f889a" dependencies = [ "futures-core", "rustls 0.18.1", - "tokio 0.2.22", + "tokio 0.2.23", "webpki", ] @@ -3736,7 +3885,7 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" dependencies = [ - "crossbeam-deque", + "crossbeam-deque 0.7.3", "crossbeam-queue", "crossbeam-utils 0.7.2", "futures 0.1.30", @@ -3803,7 +3952,7 @@ dependencies = [ "futures-sink", "log 0.4.11", "pin-project-lite", - "tokio 0.2.22", + "tokio 0.2.23", ] [[package]] @@ -3817,7 +3966,7 @@ dependencies = [ "futures-sink", "log 0.4.11", "pin-project-lite", - "tokio 0.2.22", + "tokio 0.2.23", ] [[package]] @@ -3841,7 +3990,7 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0987850db3733619253fe60e17cb59b82d37c7e6c0236bb81e4d6b87c879f27" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "log 0.4.11", "pin-project-lite", "tracing-attributes", @@ -3856,7 +4005,7 @@ checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.44", + "syn 1.0.48", ] [[package]] @@ -3874,7 +4023,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c" dependencies = [ - "pin-project", + "pin-project 0.4.27", "tracing", ] @@ -3935,15 +4084,15 @@ dependencies = [ "async-trait", "enum-as-inner", "failure", - "futures 0.3.6", + "futures 0.3.8", "idna 0.2.0", "lazy_static", "log 0.4.11", "rand 0.7.3", "smallvec 1.4.2", "socket2", - "tokio 0.2.22", - "url 2.1.1", + "tokio 0.2.23", + "url 2.2.0", ] [[package]] @@ -3952,7 +4101,7 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9f877f7a1ad821ab350505e1f1b146a4960402991787191d6d8cab2ce2de2c" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "failure", "futures 0.1.30", "ipconfig 0.1.9", @@ -3971,16 +4120,16 @@ version = "0.18.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "failure", - "futures 0.3.6", + "futures 0.3.8", "ipconfig 0.2.2", "lazy_static", "log 0.4.11", "lru-cache", "resolv-conf", "smallvec 1.4.2", - "tokio 0.2.22", + "tokio 0.2.23", "trust-dns-proto 0.18.0-alpha.2", ] @@ -3996,7 +4145,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", ] [[package]] @@ -4028,9 +4177,9 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977" +checksum = "b7f98e67a4d84f730d343392f9bfff7d21e3fca562b9cb7a43b768350beeddc6" dependencies = [ "tinyvec", ] @@ -4078,10 +4227,11 @@ dependencies = [ [[package]] name = "url" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" +checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e" dependencies = [ + "form_urlencoded", "idna 0.2.0", "matches", "percent-encoding 2.1.0", @@ -4114,7 +4264,7 @@ dependencies = [ "nom", "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.44", + "syn 1.0.48", ] [[package]] @@ -4123,7 +4273,7 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e33e939c0d8cf047514fb6ba7d5aac78bc56677a6938b2ee67000b91f2e97e41" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "v_escape", ] @@ -4202,7 +4352,7 @@ version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "serde", "serde_json", "wasm-bindgen-macro", @@ -4219,7 +4369,7 @@ dependencies = [ "log 0.4.11", "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.44", + "syn 1.0.48", "wasm-bindgen-shared", ] @@ -4229,7 +4379,7 @@ version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "js-sys", "wasm-bindgen", "web-sys", @@ -4253,7 +4403,7 @@ checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.44", + "syn 1.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4304,9 +4454,9 @@ dependencies = [ [[package]] name = "wepoll-sys" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "142bc2cba3fe88be1a8fcb55c727fa4cd5b0cf2d7438722792e22f26f04bc1e0" +checksum = "0fcb14dea929042224824779fbc82d9fab8d2e6d3cbc0ac404de8edf489e77ff" dependencies = [ "cc", ] diff --git a/src/controller/mod.rs b/src/controller/mod.rs index f75491b4..33bec3d3 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -168,6 +168,10 @@ fn handle_sensor( ) -> Option { match value { SensorValue::ButtonPress(press) => handle_buttonpress(press, mods, system), + // SensorValue::BathroomHum(b) => {dbg!(b); None} + // SensorValue::BathroomTemp(t) => {dbg!(t); None} + // SensorValue::MovementShower => {dbg!(b); None} + // SensorValue::MovementToilet => {dbg!(b); None} _ => None, // for now we ignore the other sensor data } } @@ -177,7 +181,8 @@ fn handle_buttonpress( mods: &mut Modifications, system: &mut System, ) -> Option { - if press.duration > 10 * 1000 { + const LONG_PRESS: u16 = 500; //ms + if press.duration < LONG_PRESS { // millisec match press.button { Button::LampLeft => Some(State::Quiet), @@ -204,7 +209,9 @@ fn handle_buttonpress( Button::DeskRight => Command::LampsDay, Button::DeskRightMost => Command::LampsToggle, - _ => return None, + Button::DeskTop => Command::MpdIncreaseVolume, + Button::DeskMid => Command::MpdPause, + Button::DeskBottom => Command::MpdDecreaseVolume, }; handle_cmd(cmd, mods, system) } diff --git a/src/main.rs b/src/main.rs index f96bc423..6c8405eb 100755 --- a/src/main.rs +++ b/src/main.rs @@ -93,18 +93,4 @@ async fn main() { loop { std::thread::park(); } - - /*println!("press: q to quit"); - loop { - let mut input = String::new(); - stdin().read_line(&mut input).unwrap(); - match input.as_str() { - //"n\n" => helper::add_user(& passw_db), - "q\n" => break, - _ => println!("unhandled"), - }; - } - println!("shutting down"); - web_handle.stop(true).await; - input::MpdStatus::stop_updating(updater_tx);*/ } From 9d7ac1693b1208c26c32b3b3e182ac0fc32f2ace Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Thu, 11 Feb 2021 01:44:35 +0100 Subject: [PATCH 057/687] switched color temp to actual min 2000 --- src/controller/state/quiet.rs | 50 ---------------------------------- src/controller/state/silent.rs | 2 +- 2 files changed, 1 insertion(+), 51 deletions(-) delete mode 100644 src/controller/state/quiet.rs diff --git a/src/controller/state/quiet.rs b/src/controller/state/quiet.rs deleted file mode 100644 index a99dc087..00000000 --- a/src/controller/state/quiet.rs +++ /dev/null @@ -1,50 +0,0 @@ -use super::super::{Environment, Modifications, System}; -use super::{RoomState, State}; -use crate::controller::system::mpd_control as mpd; -use crate::errors::Error; - -use philipshue::hue::LightCommand; -use std::time::{Duration, Instant}; - -#[derive(Clone, Copy)] -pub struct Quiet {} - -impl Quiet { - pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { - dbg!("entering silent mode"); - mods.reset(); - - sys.update_period = Duration::from_secs(60); - sys.next_update = Instant::now() + sys.update_period; - - mpd::set_volume(10)?; - - sys.lights.single_off(2)?; //2 is desk lamp - let command = LightCommand::default().on().with_bri(50).with_ct(500); - - for lamp_id in &[1, 8, 5, 4, 6] { - sys.lights.bridge.set_light_state(*lamp_id, &command)?; - sys.lights.lamps.get_mut(lamp_id).unwrap().on = true; - } - - Ok(Box::new(Quiet {})) - } -} - -impl RoomState for Quiet { - fn update( - &mut self, - _: &mut Modifications, - _: &mut System, - _env: &mut Environment, - ) -> Result, Error> { - Ok(None) - } - - fn breakdown(&self, _: &mut Modifications, _sys: &mut System) -> Result<(), Error> { - Ok(()) - } - fn state(&self) -> State { - State::Quiet - } -} diff --git a/src/controller/state/silent.rs b/src/controller/state/silent.rs index 24e87a6b..03bb4d21 100644 --- a/src/controller/state/silent.rs +++ b/src/controller/state/silent.rs @@ -20,7 +20,7 @@ impl Silent { mpd::pause()?; sys.lights.single_off(2)?; - let command = LightCommand::default().on().with_bri(1).with_ct(500); + let command = LightCommand::default().on().with_bri(1).with_ct(2000); for lamp_id in &[1, 8, 5, 4, 6] { sys.lights.bridge.set_light_state(*lamp_id, &command)?; From fef0ad8f40b7e66ac11b638cdfaca7d735a95e58 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Thu, 18 Feb 2021 03:01:29 +0100 Subject: [PATCH 058/687] rebuilding alarm system --- .gitignore | 1 + src/controller/mod.rs | 35 +++++----- src/input/bot/set_alarm.rs | 16 ++--- src/input/{alarms.rs => jobs.rs} | 107 +++++++++++++++---------------- src/input/jobs/wakeup.rs | 59 +++++++++++++++++ src/input/mod.rs | 2 +- src/input/web_api/alarms.rs | 8 +-- src/input/web_api/server/mod.rs | 9 ++- src/main.rs | 11 ++-- 9 files changed, 156 insertions(+), 92 deletions(-) rename src/input/{alarms.rs => jobs.rs} (71%) mode change 100755 => 100644 create mode 100644 src/input/jobs/wakeup.rs diff --git a/.gitignore b/.gitignore index 4e3fa2e2..41422ce1 100755 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,4 @@ userdb.hm ##################### target/ src/input/web_api/logins.rs +deploy_optimized.sh diff --git a/src/controller/mod.rs b/src/controller/mod.rs index 33bec3d3..032f220a 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -1,3 +1,4 @@ +use crossbeam_channel::RecvTimeoutError::*; use serde::{Deserialize, Serialize}; use std::thread; use std::time::{Duration, Instant}; @@ -14,6 +15,7 @@ mod commands; use commands::handle_cmd; use crate::errors::Error; +use crate::input::jobs::WakeUp; use crate::input::mpd_status::MpdStatus; pub use commands::Command; use sensor_value::{Button, Press, SensorValue}; @@ -22,7 +24,7 @@ pub use state::State; #[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub enum Event { Update, - Alarm, + WakeUp, Test, Command(Command), Sensor(SensorValue), @@ -55,11 +57,9 @@ impl Default for Modifications { pub struct System { update_period: Duration, next_update: Instant, - lights: Lighting, - mpd: MpdStatus, //mpd - - //etc + mpd: MpdStatus, + wakeup: WakeUp, } fn saturating_duration_till(target: std::time::Instant) -> std::time::Duration { @@ -74,13 +74,14 @@ fn saturating_duration_till(target: std::time::Instant) -> std::time::Duration { pub fn start( rx: crossbeam_channel::Receiver, mpd_status: MpdStatus, + wakeup: WakeUp, ) -> Result, Error> { let mut system = System { update_period: Duration::from_secs(5), next_update: Instant::now() + Duration::from_secs(5), - lights: Lighting::init()?, mpd: mpd_status, + wakeup, }; let handle = thread::spawn(move || { @@ -96,23 +97,22 @@ pub fn start( let time_till_update = saturating_duration_till(system.next_update); let event = match rx.recv_timeout(time_till_update) { Ok(event) => event, - Err(error) => match error { - crossbeam_channel::RecvTimeoutError::Timeout => { - system.next_update = Instant::now() + system.update_period; - Event::Update - } - crossbeam_channel::RecvTimeoutError::Disconnected => return (), - }, + Err(Timeout) => { + system.next_update = Instant::now() + system.update_period; + Event::Update + } + Err(Disconnected) => return, }; - match handle_event( + let res = handle_event( event, current_state, &mut mods, &mut system, &mut env, &mut state, - ) { + ); + match res { Err(e) => error!("Ran into an error handling an event: {:?}", e), Ok(Some(target_state)) => { //should switch to another state @@ -150,7 +150,10 @@ fn handle_event( //general code that is the same for all functions, unless specific handlers exist above (Event::Command(cmd), _) => handle_cmd(cmd, mods, system), (Event::Update, _) => state.update(mods, system, env)?, - (Event::Alarm, _) => Some(State::WakeUp), + (Event::WakeUp, _) => { + system.wakeup.reset(); + Some(State::WakeUp) + } (Event::Test, _) => { dbg!("a test happend"); None diff --git a/src/input/bot/set_alarm.rs b/src/input/bot/set_alarm.rs index 224e1c82..2ec5db00 100644 --- a/src/input/bot/set_alarm.rs +++ b/src/input/bot/set_alarm.rs @@ -1,6 +1,6 @@ use super::send_text; use crate::controller::Event; -use crate::input::alarms::Alarm; +use crate::input::jobs::Job; use crate::input::web_api::server::State; use chrono::Duration; use chrono::Timelike; @@ -66,11 +66,7 @@ pub async fn add_alarm<'a>( return Err(Error::InvalidMinuteArgument); } - //let now = Amsterdam::now(); let now = Local::now(); - //let now = Amsterdam.ymd(2016, 5, 10).and_hms(12, 0, 0); - //let now = dt.with_timezone - let alarm_sec_after_midnight = hour * 3600 + min * 60; let till_alarm = if alarm_sec_after_midnight < now.num_seconds_from_midnight() { let seconds_left_in_day = 3600 * 24 - now.num_seconds_from_midnight(); @@ -81,13 +77,13 @@ pub async fn add_alarm<'a>( Duration::seconds(seconds_till_alarm as i64) }; - let alarm = Alarm::from( + let alarm = Job::from( Utc::now() + till_alarm, Event::Alarm, Some(std::time::Duration::from_secs(3600 * 2)), ); - state.alarms.add_alarm(alarm).await.unwrap(); + state.jobs.add_alarm(alarm).await.unwrap(); let text = format!( "set alarm for over {} hours and {} minutes from now", @@ -103,7 +99,7 @@ pub async fn add_alarm<'a>( } pub async fn list_alarm(chat_id: ChatId, token: &str, state: &State) -> Result<(), Error> { - let alarms = state.alarms.list(); + let alarms = state.jobs.list(); let mut list = String::with_capacity(alarms.len() * 100); for (id, alarm) in alarms.into_iter() { @@ -135,8 +131,8 @@ pub async fn remove_alarm<'a>( let to_remove = dbg!(args.next()).ok_or(Error::NoAlarmId)?; let to_remove = u64::from_str_radix(to_remove, 16).unwrap(); - let removed = state.alarms.remove_alarm(to_remove).unwrap(); //TODO //FIXME - //.map_err(|_| Error::CouldNotRemove)?; + let removed = state.jobs.remove_alarm(to_remove).unwrap(); //TODO //FIXME + //.map_err(|_| Error::CouldNotRemove)?; let text = if let Some(alarm) = removed { format!( diff --git a/src/input/alarms.rs b/src/input/jobs.rs old mode 100755 new mode 100644 similarity index 71% rename from src/input/alarms.rs rename to src/input/jobs.rs index c4fa0bc1..90d2d75c --- a/src/input/alarms.rs +++ b/src/input/jobs.rs @@ -11,41 +11,42 @@ use crate::controller::Command; use crate::controller::Event; use crate::errors::Error; -//TODO, what to do on multiple alarms at the same time? -// -add one a second later -// -store in millisec to lower collision chance? +mod wakeup; +pub use wakeup::WakeUp; #[derive(Serialize, Deserialize, Debug)] pub enum Action { - Event(Event), - Command(Command), + SendEvent(Event), + SendCommand(Command), } impl From for Action { fn from(event: Event) -> Self { - Action::Event(event) + Action::SendEvent(event) } } impl From for Action { fn from(command: Command) -> Self { - Action::Command(command) + Action::SendCommand(command) } } #[derive(Serialize, Deserialize, Debug)] -pub struct Alarm { +pub struct Job { pub time: DateTime, pub action: Action, + /// how long after the time was missed the alarm + /// should still go off pub expiration: Option, } -impl Alarm { +impl Job { pub fn from( time: DateTime, action: impl Into, expiration: Option, ) -> Self { - Alarm { + Job { time, action: action.into(), expiration, @@ -53,14 +54,14 @@ impl Alarm { } } -impl Sub for Alarm { +impl Sub for Job { type Output = chrono::Duration; - fn sub(self, other: Alarm) -> chrono::Duration { + fn sub(self, other: Job) -> chrono::Duration { self.time - other.time } } -impl Sub> for &Alarm { +impl Sub> for &Job { type Output = chrono::Duration; fn sub(self, other: chrono::DateTime) -> chrono::Duration { @@ -69,24 +70,25 @@ impl Sub> for &Alarm { } #[derive(Clone)] -pub struct Alarms { +pub struct Jobs { waker_tx: crossbeam_channel::Sender<()>, - alarm_db: AlarmList, + list: JobList, } #[derive(Clone)] -pub struct AlarmList { +pub struct JobList { db: sled::Tree, } +use crossbeam_channel::RecvTimeoutError::*; fn waker( - mut alarm_list: AlarmList, + mut alarm_list: JobList, event_tx: crossbeam_channel::Sender, waker_rx: crossbeam_channel::Receiver<()>, ) { loop { //This can fail #TODO make sure an non waking error alarm is send to the user - if let Some((id, current_alarm)) = alarm_list.get_next() { + if let Some((id, current_alarm)) = alarm_list.peek_next() { let now = Utc::now(); let timeout = ¤t_alarm - now; if let Some(expiration) = current_alarm.expiration { @@ -101,27 +103,16 @@ fn waker( .unwrap_or(std::time::Duration::from_secs(0)); info!("next alarm is in: {} seconds", timeout.as_secs()); - //do we sound the an alarm or should we add or remove one? + //do we sound an alarm or should we add or remove one? match waker_rx.recv_timeout(timeout) { - //do not set off alarm - Ok(_) => { - dbg!(); - () - } //should recheck if "current alarm" is still the right one as we removed one - - Err(error) => match error { - //should the alarm go off or should we stop? - crossbeam_channel::RecvTimeoutError::Timeout => { - if let Err(error) = event_tx.send(Event::Alarm) { - error!("could not set off alarm: {:?}", error); - }; //set - //remove alarm from memory and file - alarm_list.remove_alarm(id).unwrap(); - continue; //get next alarm - } - //we should stop, end the thread by returning - crossbeam_channel::RecvTimeoutError::Disconnected => return, - }, + Ok(_) => continue, // new alarm entered restart loop + Err(Disconnected) => return, + Err(Timeout) => { + // time to sound the alarm + sound_alarm(&mut alarm_list, &event_tx, current_alarm); + alarm_list.remove_alarm(id).unwrap(); + continue; //get next alarm + } } } else { //no alarm to wait on, wait for instructions @@ -137,40 +128,47 @@ fn waker( } } -impl Alarms { +fn sound_alarm(list: &mut JobList, event_tx: &crossbeam_channel::Sender, job: Job) { + match job.action { + Action::SendEvent(ev) => event_tx.send(ev).unwrap(), + Action::SendCommand(cmd) => event_tx.send(Event::Command(cmd)).unwrap(), + } +} + +impl Jobs { pub fn setup( event_tx: crossbeam_channel::Sender, db: sled::Db, ) -> Result<(Self, thread::JoinHandle<()>), Error> { - let alarm_db = AlarmList { + let list = JobList { db: db.open_tree("alarms")?, }; let (waker_tx, waker_rx) = crossbeam_channel::unbounded(); - let waker_db_copy = alarm_db.clone(); + let waker_db_copy = list.clone(); let waker_thread = thread::spawn(move || waker(waker_db_copy, event_tx, waker_rx)); - Ok((Self { alarm_db, waker_tx }, waker_thread)) + Ok((Self { list, waker_tx }, waker_thread)) } // we decrease the time till the alarm until there is a place in the database // as only one alarm can fire at the time, after an alarm gets a timeslot it is never changed - pub async fn add_alarm(&self, to_add: Alarm) -> Result<(), Error> { - self.alarm_db.add_alarm(to_add).await?; + pub async fn add_alarm(&self, to_add: Job) -> Result<(), Error> { + self.list.add_alarm(to_add).await?; //signal waker to update its next alarm self.waker_tx.send(())?; Ok(()) } - pub fn remove_alarm(&self, to_remove: u64) -> Result, Error> { - let removed_alarm = self.alarm_db.remove_alarm(to_remove)?; + pub fn remove_alarm(&self, to_remove: u64) -> Result, Error> { + let removed_alarm = self.list.remove_alarm(to_remove)?; self.waker_tx.send(())?; //signal waker to update its next alarm Ok(removed_alarm) } - pub fn list(&self) -> Vec<(u64, Alarm)> { + pub fn list(&self) -> Vec<(u64, Job)> { //self.alarm_list.iter().keys().map(|k| DateTime::::from_utc(NaiveDateTime::from_timestamp(k, 0), Utc);) let start: &[u8] = &[0]; - let alarms = self.alarm_db.db.range(start..); + let alarms = self.list.db.range(start..); let mut list = Vec::new(); //TODO placeholder for (key, alarm) in alarms.filter_map(Result::ok) { @@ -182,10 +180,11 @@ impl Alarms { } } -impl AlarmList { +impl JobList { // we decrease the time till the alarm until there is a place in the database // as only one alarm can fire at the time, after an alarm gets a timeslot it is never changed - async fn add_alarm(&self, to_add: Alarm) -> Result<(), Error> { + /// return the key for the alarm + async fn add_alarm(&self, to_add: Job) -> Result { let mut timestamp = to_add.time.timestamp() as u64; let mut timestamp_array = timestamp.to_be_bytes(); let alarm = bincode::serialize(&to_add).unwrap(); @@ -204,18 +203,18 @@ impl AlarmList { timestamp_array = timestamp.to_be_bytes(); } self.db.flush_async().await?; - Ok(()) + Ok(timestamp) } - pub fn remove_alarm(&self, to_remove: u64) -> Result, Error> { + pub fn remove_alarm(&self, to_remove: u64) -> Result, Error> { Ok(self .db .remove(to_remove.to_be_bytes())? - .map(|k| bincode::deserialize::(&k).unwrap())) + .map(|k| bincode::deserialize::(&k).unwrap())) } /// calculate time to the earliest alarm, remove it from the list if the current time is later /// then the alarm - fn get_next(&mut self) -> Option<(u64, Alarm)> { + fn peek_next(&mut self) -> Option<(u64, Job)> { //get earliest alarm time in db match self.db.get_gt(0u64.to_be_bytes()) { Ok(entry) => { diff --git a/src/input/jobs/wakeup.rs b/src/input/jobs/wakeup.rs new file mode 100644 index 00000000..86f974b7 --- /dev/null +++ b/src/input/jobs/wakeup.rs @@ -0,0 +1,59 @@ +use super::{Jobs, Job, Action}; +use crate::errors::Error; +use crate::controller::Event; +use std::time::Duration; +use chrono::{Utc, Local, DateTime, Timelike}; + +#[derive(Clone)] +pub struct WakeUp { + db: sled::Tree, + tomorrow: Option<(u8, u8)>, + usually: Option<(u8, u8)>, + job_id: Option, + jobs: Jobs, +} + +impl WakeUp { + pub fn setup(db: sled::Db, jobs: Jobs) -> Result { + let db = db.open_tree("wakeup")?; + let tomorrow = db + .get("tomorrow") + .unwrap() + .map(|b| bincode::deserialize(&b).unwrap()); + let usually = db + .get("usually") + .unwrap() + .map(|b| bincode::deserialize(&b).unwrap()); + let job_id = db + .get("job_id") + .unwrap() + .map(|b| bincode::deserialize(&b).unwrap()); + + Ok(Self { + db, + tomorrow, + usually, + job_id, + jobs, + }) + } + + pub fn reset(&mut self) { + if let Some(hour_min) = self.usually { + let job = Job { + time: to_datetime(hour_min), + action: Action::SendEvent(Event::WakeUp), + expiration: Some(Duration::from_secs(3*60*60)), + }; + self.jobs.add_alarm(job); + } + } +} + +fn to_datetime((hour, min): (u8, u8)) -> DateTime { + let (hour, min) = (hour as u32, min as u32); + let now = Utc::now(); + + let tomorrow = now.date().succ(); + tomorrow.and_hms(hour, min, 0) +} diff --git a/src/input/mod.rs b/src/input/mod.rs index 3749cab6..d7240b7e 100755 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -1,5 +1,5 @@ -pub mod alarms; pub mod bot; +pub mod jobs; pub mod mpd_status; pub mod web_api; pub mod youtube_downloader; diff --git a/src/input/web_api/alarms.rs b/src/input/web_api/alarms.rs index 1aa08272..727cdb55 100644 --- a/src/input/web_api/alarms.rs +++ b/src/input/web_api/alarms.rs @@ -4,7 +4,7 @@ use std::time::Duration; use super::*; use crate::controller::Event; -use crate::input::alarms::Alarm; +use crate::input::jobs::Job; #[derive(Deserialize, Debug)] pub struct AlarmDataMinFrom { @@ -52,9 +52,9 @@ pub async fn set_alarm_unix_timestamp( dbg!(Utc::now()); if time > Utc::now() { - let alarm = Alarm::from(time, Event::Alarm, Some(Duration::from_secs(3600 * 2))); + let alarm = Job::from(time, Event::Alarm, Some(Duration::from_secs(3600 * 2))); - if state.alarms.add_alarm(alarm).await.is_ok() { + if state.jobs.add_alarm(alarm).await.is_ok() { dbg!("done setting alarm"); HttpResponse::Ok().finish() } else { @@ -74,7 +74,7 @@ pub async fn set_alarm_unix_timestamp( pub fn list_alarms(state: Data) -> HttpResponse { //Code to parse alarm time - let alarms = state.alarms.list(); + let alarms = state.jobs.list(); let mut list = String::with_capacity(alarms.len() * 100); for (id, alarm) in alarms { list.push_str(&format!( diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index ba9efa76..30c0d4be 100755 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -36,7 +36,8 @@ pub struct Session {} //TODO deprecate #[derive(Clone)] pub struct State { pub controller_addr: crossbeam_channel::Sender, - pub alarms: input::alarms::Alarms, + pub jobs: input::jobs::Jobs, + pub wakeup: input::jobs::WakeUp, pub passw_db: PasswordDatabase, pub sessions: Arc>>>>, pub free_session_ids: Arc, @@ -49,7 +50,8 @@ impl State { pub fn new( passw_db: PasswordDatabase, controller_tx: crossbeam_channel::Sender, - alarms: input::alarms::Alarms, + jobs: input::jobs::Jobs, + wakeup: input::jobs::WakeUp, youtube_dl: input::YoutubeDownloader, bot_token: String, valid_ids: Vec, @@ -60,7 +62,8 @@ impl State { State { controller_addr: controller_tx, - alarms, + jobs, + wakeup, passw_db, youtube_dl, sessions, diff --git a/src/main.rs b/src/main.rs index 6c8405eb..7d38a1e8 100755 --- a/src/main.rs +++ b/src/main.rs @@ -52,8 +52,9 @@ async fn main() { let (controller_tx, controller_rx) = crossbeam_channel::unbounded(); - let (alarms, _waker_thread) = - input::alarms::Alarms::setup(controller_tx.clone(), db.clone()).unwrap(); + let (joblist, _waker_thread) = + input::jobs::Jobs::setup(controller_tx.clone(), db.clone()).unwrap(); + let wakeup = input::jobs::WakeUp::setup(db.clone(), joblist.clone()).unwrap(); let (youtube_dl, _downloader_thread) = input::YoutubeDownloader::init(opt.token.clone(), db.clone()) .await @@ -61,12 +62,14 @@ async fn main() { let (mpd_status, _mpd_watcher_thread, _updater_tx) = input::MpdStatus::start_updating().unwrap(); - let _controller_thread = controller::start(controller_rx, mpd_status.clone()).unwrap(); + let _controller_thread = + controller::start(controller_rx, mpd_status.clone(), wakeup.clone()).unwrap(); let state = State::new( passw_db, controller_tx.clone(), - alarms, + joblist, + wakeup, youtube_dl, opt.token.clone(), opt.valid_ids.clone(), From cbfd0dca0b5b3fc8b9bed5bff880c678885cf051 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Fri, 19 Feb 2021 03:06:44 +0100 Subject: [PATCH 059/687] fixed alarm always on next day --- src/input/bot/set_alarm.rs | 74 ++++++++++++++++++------------ src/input/jobs.rs | 6 +-- src/input/jobs/wakeup.rs | 90 ++++++++++++++++++++++++++++++------- src/input/web_api/alarms.rs | 8 ++-- 4 files changed, 128 insertions(+), 50 deletions(-) diff --git a/src/input/bot/set_alarm.rs b/src/input/bot/set_alarm.rs index 2ec5db00..e3ff111d 100644 --- a/src/input/bot/set_alarm.rs +++ b/src/input/bot/set_alarm.rs @@ -1,10 +1,6 @@ use super::send_text; -use crate::controller::Event; -use crate::input::jobs::Job; use crate::input::web_api::server::State; -use chrono::Duration; -use chrono::Timelike; -use chrono::{Local, Utc}; +use chrono::{Local, Utc, Timelike}; use telegram_bot::types::refs::ChatId; #[derive(Debug)] @@ -30,7 +26,8 @@ pub async fn handle<'a>( match command { "list" => list_alarm(chat_id, token, state).await?, - "add" => add_alarm(chat_id, token, args, state).await?, + "tomorrow" => add_tomorrow(chat_id, token, args, state).await?, + "usually" => add_usually(chat_id, token, args, state).await?, "remove" => remove_alarm(chat_id, token, args, state).await?, &_ => Err(Error::InvalidOption)?, } @@ -38,12 +35,44 @@ pub async fn handle<'a>( Ok(()) } -pub async fn add_alarm<'a>( +pub async fn add_tomorrow<'a>( chat_id: ChatId, token: &str, mut args: std::str::SplitWhitespace<'a>, state: &State, ) -> Result<(), Error> { + let (hour, min, text) = add_alarm(chat_id, token, args, state)?; + + state.wakeup.set_tomorrow(hour as u8, min as u8).await; + send_text(chat_id, token, text) + .await + .map_err(|_| Error::CouldNotRespond)?; + + Ok(()) +} + +pub async fn add_usually<'a>( + chat_id: ChatId, + token: &str, + mut args: std::str::SplitWhitespace<'a>, + state: &State, +) -> Result<(), Error> { + let (hour, min, text) = add_alarm(chat_id, token, args, state)?; + + state.wakeup.set_usually(hour as u8, min as u8).await; + send_text(chat_id, token, text) + .await + .map_err(|_| Error::CouldNotRespond)?; + + Ok(()) +} + +pub fn add_alarm<'a>( + chat_id: ChatId, + token: &str, + mut args: std::str::SplitWhitespace<'a>, + state: &State, +) -> Result<(u8, u8, String), Error> { let time = args.next().ok_or(Error::NoTimeArgument)?; //assumes hh:mm @@ -66,24 +95,17 @@ pub async fn add_alarm<'a>( return Err(Error::InvalidMinuteArgument); } - let now = Local::now(); - let alarm_sec_after_midnight = hour * 3600 + min * 60; - let till_alarm = if alarm_sec_after_midnight < now.num_seconds_from_midnight() { - let seconds_left_in_day = 3600 * 24 - now.num_seconds_from_midnight(); - Duration::seconds(seconds_left_in_day as i64) - + Duration::seconds(alarm_sec_after_midnight as i64) - } else { - let seconds_till_alarm = alarm_sec_after_midnight - now.num_seconds_from_midnight(); - Duration::seconds(seconds_till_alarm as i64) - }; + let now = Utc::now(); + let mut alarm = now + .with_hour(hour).unwrap() + .with_minute(min).unwrap(); - let alarm = Job::from( - Utc::now() + till_alarm, - Event::Alarm, - Some(std::time::Duration::from_secs(3600 * 2)), - ); + if alarm < now { + let tomorrow = now.date().succ(); + alarm = tomorrow.and_hms(hour, min, 0); + } - state.jobs.add_alarm(alarm).await.unwrap(); + let till_alarm = alarm-now; let text = format!( "set alarm for over {} hours and {} minutes from now", @@ -91,11 +113,7 @@ pub async fn add_alarm<'a>( till_alarm.num_minutes() % 60 ); - send_text(chat_id, token, text) - .await - .map_err(|_| Error::CouldNotRespond)?; - - Ok(()) + Ok((hour as u8, min as u8, text)) } pub async fn list_alarm(chat_id: ChatId, token: &str, state: &State) -> Result<(), Error> { diff --git a/src/input/jobs.rs b/src/input/jobs.rs index 90d2d75c..197f4b95 100644 --- a/src/input/jobs.rs +++ b/src/input/jobs.rs @@ -153,11 +153,11 @@ impl Jobs { // we decrease the time till the alarm until there is a place in the database // as only one alarm can fire at the time, after an alarm gets a timeslot it is never changed - pub async fn add_alarm(&self, to_add: Job) -> Result<(), Error> { - self.list.add_alarm(to_add).await?; + pub async fn add_alarm(&self, to_add: Job) -> Result { + let id = self.list.add_alarm(to_add).await?; //signal waker to update its next alarm self.waker_tx.send(())?; - Ok(()) + Ok(id) } pub fn remove_alarm(&self, to_remove: u64) -> Result, Error> { let removed_alarm = self.list.remove_alarm(to_remove)?; diff --git a/src/input/jobs/wakeup.rs b/src/input/jobs/wakeup.rs index 86f974b7..070ec39b 100644 --- a/src/input/jobs/wakeup.rs +++ b/src/input/jobs/wakeup.rs @@ -2,18 +2,37 @@ use super::{Jobs, Job, Action}; use crate::errors::Error; use crate::controller::Event; use std::time::Duration; +use std::sync::{Arc, Mutex}; use chrono::{Utc, Local, DateTime, Timelike}; #[derive(Clone)] -pub struct WakeUp { +pub struct WakeUp(Arc>); +impl WakeUp { + pub fn setup(db: sled::Db, jobs: Jobs) -> Result { + let inner = Inner::setup(db, jobs)?; + let inner = Arc::new(Mutex::new(inner)); + Ok(Self(inner)) + } + pub async fn reset(&self) -> Result<(), Error> { + self.0.lock().unwrap().reset().await + } + pub async fn set_tomorrow(&self, hour: u8, min: u8) -> Result<(), Error> { + self.0.lock().unwrap().set_tomorrow(hour, min).await + } + pub async fn set_usually(&self, hour: u8, min: u8) -> Result<(), Error> { + self.0.lock().unwrap().set_usually(hour, min).await + } +} + +struct Inner { db: sled::Tree, - tomorrow: Option<(u8, u8)>, - usually: Option<(u8, u8)>, + pub tomorrow: Option<(u8, u8)>, + pub usually: Option<(u8, u8)>, job_id: Option, jobs: Jobs, } -impl WakeUp { +impl Inner { pub fn setup(db: sled::Db, jobs: Jobs) -> Result { let db = db.open_tree("wakeup")?; let tomorrow = db @@ -38,22 +57,63 @@ impl WakeUp { }) } - pub fn reset(&mut self) { - if let Some(hour_min) = self.usually { - let job = Job { - time: to_datetime(hour_min), - action: Action::SendEvent(Event::WakeUp), - expiration: Some(Duration::from_secs(3*60*60)), - }; - self.jobs.add_alarm(job); + fn remove_existing_job(&self) { + if let Some(job_id) = self.job_id { + self.jobs.remove_alarm(job_id).unwrap(); + } + } + + async fn add_new_job(&mut self, job: Job) -> Result<(),Error> { + let id = self.jobs + .add_alarm(job) + .await?; + self.remove_existing_job(); + self.job_id = Some(id); + Ok(()) + } + + pub async fn reset(&mut self) -> Result<(),Error> { + if let Some((hour,min)) = self.usually { + let job = wakeup_job(hour, min); + self.add_new_job(job).await?; } + Ok(()) + } + + pub async fn set_tomorrow(&mut self, hour: u8, min: u8) -> Result<(),Error> { + let job = wakeup_job(hour, min); + self.tomorrow = Some((hour,min)); + self.add_new_job(job).await?; + Ok(()) + } + + pub async fn set_usually(&mut self, hour: u8, min: u8) -> Result<(), Error> { + let job = wakeup_job(hour, min); + self.usually = Some((hour,min)); + self.add_new_job(job).await?; + Ok(()) } } -fn to_datetime((hour, min): (u8, u8)) -> DateTime { +fn wakeup_job(hour: u8, min: u8) -> Job { + Job { + time: to_datetime(hour,min), + action: Action::SendEvent(Event::WakeUp), + expiration: Some(Duration::from_secs(3*60*60)), + } +} + +fn to_datetime(hour: u8, min: u8) -> DateTime { let (hour, min) = (hour as u32, min as u32); let now = Utc::now(); + let alarm = now + .with_hour(hour).unwrap() + .with_minute(min).unwrap(); - let tomorrow = now.date().succ(); - tomorrow.and_hms(hour, min, 0) + if alarm < now { + let tomorrow = now.date().succ(); + tomorrow.and_hms(hour, min, 0) + } else { + alarm + } } diff --git a/src/input/web_api/alarms.rs b/src/input/web_api/alarms.rs index 727cdb55..01590e24 100644 --- a/src/input/web_api/alarms.rs +++ b/src/input/web_api/alarms.rs @@ -1,4 +1,4 @@ -use chrono::{DateTime, NaiveDateTime, Utc}; +use chrono::{DateTime, NaiveDateTime, Utc, Timelike}; use serde::Deserialize; use std::time::Duration; @@ -52,9 +52,9 @@ pub async fn set_alarm_unix_timestamp( dbg!(Utc::now()); if time > Utc::now() { - let alarm = Job::from(time, Event::Alarm, Some(Duration::from_secs(3600 * 2))); - - if state.jobs.add_alarm(alarm).await.is_ok() { + let hour = time.time().hour() as u8; + let min = time.time().minute() as u8; + if state.wakeup.set_tomorrow(hour, min).await.is_ok() { dbg!("done setting alarm"); HttpResponse::Ok().finish() } else { From 497963296b8bc3731f04d4e5d33399460c0bbfc3 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Sat, 20 Feb 2021 04:14:16 +0100 Subject: [PATCH 060/687] fixed Utc used instead of local timezone --- src/input/bot/set_alarm.rs | 14 +++++++------- src/input/jobs/wakeup.rs | 6 ++++++ src/input/web_api/commands.rs | 29 +++++++++++++++++++++++++++-- src/input/web_api/server/mod.rs | 2 ++ 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/input/bot/set_alarm.rs b/src/input/bot/set_alarm.rs index e3ff111d..39321c0f 100644 --- a/src/input/bot/set_alarm.rs +++ b/src/input/bot/set_alarm.rs @@ -1,6 +1,6 @@ use super::send_text; use crate::input::web_api::server::State; -use chrono::{Local, Utc, Timelike}; +use chrono::{Local, Timelike}; use telegram_bot::types::refs::ChatId; #[derive(Debug)] @@ -38,10 +38,10 @@ pub async fn handle<'a>( pub async fn add_tomorrow<'a>( chat_id: ChatId, token: &str, - mut args: std::str::SplitWhitespace<'a>, + args: std::str::SplitWhitespace<'a>, state: &State, ) -> Result<(), Error> { - let (hour, min, text) = add_alarm(chat_id, token, args, state)?; + let (hour, min, text) = parse_args(chat_id, token, args, state)?; state.wakeup.set_tomorrow(hour as u8, min as u8).await; send_text(chat_id, token, text) @@ -54,10 +54,10 @@ pub async fn add_tomorrow<'a>( pub async fn add_usually<'a>( chat_id: ChatId, token: &str, - mut args: std::str::SplitWhitespace<'a>, + args: std::str::SplitWhitespace<'a>, state: &State, ) -> Result<(), Error> { - let (hour, min, text) = add_alarm(chat_id, token, args, state)?; + let (hour, min, text) = parse_args(chat_id, token, args, state)?; state.wakeup.set_usually(hour as u8, min as u8).await; send_text(chat_id, token, text) @@ -67,7 +67,7 @@ pub async fn add_usually<'a>( Ok(()) } -pub fn add_alarm<'a>( +fn parse_args<'a>( chat_id: ChatId, token: &str, mut args: std::str::SplitWhitespace<'a>, @@ -95,7 +95,7 @@ pub fn add_alarm<'a>( return Err(Error::InvalidMinuteArgument); } - let now = Utc::now(); + let now = Local::now(); let mut alarm = now .with_hour(hour).unwrap() .with_minute(min).unwrap(); diff --git a/src/input/jobs/wakeup.rs b/src/input/jobs/wakeup.rs index 070ec39b..85563fa7 100644 --- a/src/input/jobs/wakeup.rs +++ b/src/input/jobs/wakeup.rs @@ -13,6 +13,12 @@ impl WakeUp { let inner = Arc::new(Mutex::new(inner)); Ok(Self(inner)) } + pub fn tomorrow(&self) -> Option<(u8,u8)> { + self.0.lock().unwrap().tomorrow + } + pub fn usually(&self) -> Option<(u8,u8)> { + self.0.lock().unwrap().usually + } pub async fn reset(&self) -> Result<(), Error> { self.0.lock().unwrap().reset().await } diff --git a/src/input/web_api/commands.rs b/src/input/web_api/commands.rs index bd0d7527..72d12544 100644 --- a/src/input/web_api/commands.rs +++ b/src/input/web_api/commands.rs @@ -1,14 +1,39 @@ use actix_web::web::Data; use actix_web_httpauth::extractors::basic::BasicAuth; - +use actix_web::http::Method; +use actix_web::FromRequest; +use actix_web::web::Bytes; use actix_web::HttpResponse; use super::*; use crate::controller::State as TargetState; use crate::controller::{Command, Event}; -///////////////////// lamp commands /////////////////////////////// +pub async fn tomorrow(state: Data, auth: BasicAuth, req: HttpRequest, body: Bytes) -> HttpResponse { + if !authenticated(auth) { + return make_auth_error(); + } + match *req.method() { + Method::GET => { + let tomorrow = state.wakeup.tomorrow(); + let bytes = bincode::serialize(&tomorrow).unwrap(); + HttpResponse::Ok().body(bytes) + } + Method::POST => { + match bincode::deserialize(&body) { + Ok((hour,min)) => { + state.wakeup.set_tomorrow(hour, min).await; //TODO handle result of this + HttpResponse::Ok().finish() + } + Err(_) => HttpResponse::BadRequest().body("invalid encoding"), + } + } + _ => HttpResponse::BadRequest().finish(), + } +} + +///////////////////// lamp commands /////////////////////////////// pub fn toggle(state: Data, auth: BasicAuth) -> HttpResponse { if authenticated(auth) { state diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index 30c0d4be..79ae3615 100755 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -172,6 +172,8 @@ pub fn start_webserver( .service(web::resource("/commands/lamps/dimmest").to(commands::dimmest)) .service(web::resource("/commands/lamps/dim").to(commands::dim)) .service(web::resource("/commands/lightloop").to(commands::lightloop)) + .service(web::resource("/alarm/tomorrow").to(commands::tomorrow)) + // .service(web::resource("/alarm/usually").to(commands::usually)) .service(web::resource(&format!("/{}", &state.bot_token)).to(bot::handle_webhook)) .service( web::resource(&format!("/{}", ha_key)).route(web::post().to(handle_sensor)), From 9cfcf5efbb9c465275d724f266fdfaa21c911c71 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Sat, 20 Feb 2021 13:42:35 +0100 Subject: [PATCH 061/687] fixed Utc used instead of local timezone --- src/input/jobs.rs | 4 ++-- src/input/jobs/wakeup.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/input/jobs.rs b/src/input/jobs.rs index 197f4b95..2ffa16b7 100644 --- a/src/input/jobs.rs +++ b/src/input/jobs.rs @@ -109,7 +109,7 @@ fn waker( Err(Disconnected) => return, Err(Timeout) => { // time to sound the alarm - sound_alarm(&mut alarm_list, &event_tx, current_alarm); + sound_alarm(&event_tx, current_alarm); alarm_list.remove_alarm(id).unwrap(); continue; //get next alarm } @@ -128,7 +128,7 @@ fn waker( } } -fn sound_alarm(list: &mut JobList, event_tx: &crossbeam_channel::Sender, job: Job) { +fn sound_alarm(event_tx: &crossbeam_channel::Sender, job: Job) { match job.action { Action::SendEvent(ev) => event_tx.send(ev).unwrap(), Action::SendCommand(cmd) => event_tx.send(Event::Command(cmd)).unwrap(), diff --git a/src/input/jobs/wakeup.rs b/src/input/jobs/wakeup.rs index 85563fa7..f1f07ed9 100644 --- a/src/input/jobs/wakeup.rs +++ b/src/input/jobs/wakeup.rs @@ -111,15 +111,15 @@ fn wakeup_job(hour: u8, min: u8) -> Job { fn to_datetime(hour: u8, min: u8) -> DateTime { let (hour, min) = (hour as u32, min as u32); - let now = Utc::now(); + let now = Local::now(); let alarm = now .with_hour(hour).unwrap() .with_minute(min).unwrap(); if alarm < now { let tomorrow = now.date().succ(); - tomorrow.and_hms(hour, min, 0) + tomorrow.and_hms(hour, min, 0).into() } else { - alarm + alarm.into() } } From 97f4ca045b9906ca8c4bddf29e32e94a9438ab7c Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Sun, 21 Feb 2021 15:26:55 +0100 Subject: [PATCH 062/687] adds api endpoints for set_alarm --- Cargo.lock | 102 +++++++++++++++++++++++++++++++- Cargo.toml | 4 +- src/input/bot/set_alarm.rs | 5 +- src/input/bot/youtube_dl.rs | 1 - src/input/jobs.rs | 9 ++- src/input/jobs/wakeup.rs | 21 +++++-- src/input/web_api/commands.rs | 24 -------- src/input/web_api/mod.rs | 1 + src/input/web_api/server/mod.rs | 6 +- 9 files changed, 133 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 22e03c29..e49d3d08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,8 +44,10 @@ dependencies = [ "serde_yaml", "sled", "smallvec 0.6.13", + "smol", "structopt", "telegram-bot", + "thiserror", ] [[package]] @@ -546,6 +548,17 @@ dependencies = [ "vec-arena", ] +[[package]] +name = "async-fs" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b3ca4f8ff117c37c278a2f7415ce9be55560b846b5bc4412aaa5d29c1c3dae2" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + [[package]] name = "async-global-executor" version = "1.4.3" @@ -579,6 +592,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "async-lock" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1996609732bde4a9988bc42125f55f2af5f3c36370e27c778d5191a4a1b63bfb" +dependencies = [ + "event-listener", +] + [[package]] name = "async-mutex" version = "1.4.0" @@ -588,6 +610,34 @@ dependencies = [ "event-listener", ] +[[package]] +name = "async-net" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06de475c85affe184648202401d7622afb32f0f74e02192857d0201a16defbe5" +dependencies = [ + "async-io", + "blocking", + "fastrand", + "futures-lite", +] + +[[package]] +name = "async-process" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef37b86e2fa961bae5a4d212708ea0154f904ce31d1a4a7f47e1bbc33a0c040b" +dependencies = [ + "async-io", + "blocking", + "cfg-if 1.0.0", + "event-listener", + "futures-lite", + "once_cell", + "signal-hook", + "winapi 0.3.9", +] + [[package]] name = "async-std" version = "1.7.0" @@ -3400,11 +3450,21 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" +[[package]] +name = "signal-hook" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7f3f92a1da3d6b1d32245d0cbcbbab0cfc45996d8df619c42bccfa6d2bbb5f" +dependencies = [ + "libc", + "signal-hook-registry", +] + [[package]] name = "signal-hook-registry" -version = "1.2.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce32ea0c6c56d5eacaeb814fbed9960547021d3edd010ded1425f180536b20ab" +checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6" dependencies = [ "libc", ] @@ -3452,6 +3512,24 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252" +[[package]] +name = "smol" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cf3b5351f3e783c1d79ab5fc604eeed8b8ae9abd36b166e8b87a089efd85e4" +dependencies = [ + "async-channel", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-net", + "async-process", + "blocking", + "futures-lite", + "once_cell", +] + [[package]] name = "socket2" version = "0.3.16" @@ -3628,6 +3706,26 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thiserror" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.7", + "syn 1.0.48", +] + [[package]] name = "thread_local" version = "1.0.1" diff --git a/Cargo.toml b/Cargo.toml index 0432301c..7a8b4763 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ live_server = [] [dependencies] futures = "0.3" +smol = "1.2" async-std = "1" async-trait = "0.1" @@ -37,6 +38,7 @@ serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.8" bincode = "1.3.1" +thiserror = "1.0" log = "0.4" fern = { version = "0.5.6", features = ["colored"] } @@ -44,7 +46,6 @@ sensor_value = { git = "https://github.com/dskleingeld/sensor_central.git", bran gpio-cdev = { git = "https://github.com/rust-embedded/gpio-cdev", branch = "master" } nix = "0.17" -#tokio = "0.1.15" ring = "0.16" linux-embedded-hal = "0.2" @@ -72,4 +73,3 @@ retry = "0.5" telegram-bot = {version = "0.7", default-features = false, features = ["rustls"]} serde_json = "1.0" regex = "1" -#id3 = "0.5.0" diff --git a/src/input/bot/set_alarm.rs b/src/input/bot/set_alarm.rs index 39321c0f..cb30cc16 100644 --- a/src/input/bot/set_alarm.rs +++ b/src/input/bot/set_alarm.rs @@ -13,6 +13,7 @@ pub enum Error { InvalidMinuteArgument, WrongTimeFormat, NoAlarmId, + BackendError, } pub async fn handle<'a>( @@ -43,7 +44,7 @@ pub async fn add_tomorrow<'a>( ) -> Result<(), Error> { let (hour, min, text) = parse_args(chat_id, token, args, state)?; - state.wakeup.set_tomorrow(hour as u8, min as u8).await; + state.wakeup.set_tomorrow(hour as u8, min as u8).await.map_err(|_| Error::BackendError)?; send_text(chat_id, token, text) .await .map_err(|_| Error::CouldNotRespond)?; @@ -59,7 +60,7 @@ pub async fn add_usually<'a>( ) -> Result<(), Error> { let (hour, min, text) = parse_args(chat_id, token, args, state)?; - state.wakeup.set_usually(hour as u8, min as u8).await; + state.wakeup.set_usually(hour as u8, min as u8).await.map_err(|_| Error::BackendError)?; send_text(chat_id, token, text) .await .map_err(|_| Error::CouldNotRespond)?; diff --git a/src/input/bot/youtube_dl.rs b/src/input/bot/youtube_dl.rs index 38a91cff..7e24892c 100644 --- a/src/input/bot/youtube_dl.rs +++ b/src/input/bot/youtube_dl.rs @@ -1,5 +1,4 @@ use async_trait::async_trait; -use telegram_bot::types::callback_query::CallbackQuery; use telegram_bot::types::refs::{ChatId, MessageId}; use super::send_text; diff --git a/src/input/jobs.rs b/src/input/jobs.rs index 2ffa16b7..c60a1596 100644 --- a/src/input/jobs.rs +++ b/src/input/jobs.rs @@ -9,7 +9,6 @@ use sled; use crate::controller::Command; use crate::controller::Event; -use crate::errors::Error; mod wakeup; pub use wakeup::WakeUp; @@ -20,6 +19,14 @@ pub enum Action { SendCommand(Command), } +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Could store/edit job on disk")] + DbError(#[from] sled::Error), + #[error("Could not inform waker about new job")] + CommError(#[from] crossbeam_channel::SendError<()>), +} + impl From for Action { fn from(event: Event) -> Self { Action::SendEvent(event) diff --git a/src/input/jobs/wakeup.rs b/src/input/jobs/wakeup.rs index f1f07ed9..490b56e7 100644 --- a/src/input/jobs/wakeup.rs +++ b/src/input/jobs/wakeup.rs @@ -1,10 +1,20 @@ use super::{Jobs, Job, Action}; -use crate::errors::Error; +// use crate::errors::Error; use crate::controller::Event; use std::time::Duration; use std::sync::{Arc, Mutex}; use chrono::{Utc, Local, DateTime, Timelike}; +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Error modifying wakeup alarms: {0}")] + DbError(#[from] sled::Error), + #[error("Could not create/edit wakeup job")] + JobError(#[from] super::Error), + + +} + #[derive(Clone)] pub struct WakeUp(Arc>); impl WakeUp { @@ -19,8 +29,8 @@ impl WakeUp { pub fn usually(&self) -> Option<(u8,u8)> { self.0.lock().unwrap().usually } - pub async fn reset(&self) -> Result<(), Error> { - self.0.lock().unwrap().reset().await + pub fn reset(&self) -> Result<(), Error> { + self.0.lock().unwrap().reset() } pub async fn set_tomorrow(&self, hour: u8, min: u8) -> Result<(), Error> { self.0.lock().unwrap().set_tomorrow(hour, min).await @@ -78,10 +88,11 @@ impl Inner { Ok(()) } - pub async fn reset(&mut self) -> Result<(),Error> { + pub fn reset(&mut self) -> Result<(),Error> { if let Some((hour,min)) = self.usually { let job = wakeup_job(hour, min); - self.add_new_job(job).await?; + let add = self.add_new_job(job); + smol::block_on(add)?; } Ok(()) } diff --git a/src/input/web_api/commands.rs b/src/input/web_api/commands.rs index 72d12544..1c5a4422 100644 --- a/src/input/web_api/commands.rs +++ b/src/input/web_api/commands.rs @@ -9,30 +9,6 @@ use super::*; use crate::controller::State as TargetState; use crate::controller::{Command, Event}; -pub async fn tomorrow(state: Data, auth: BasicAuth, req: HttpRequest, body: Bytes) -> HttpResponse { - if !authenticated(auth) { - return make_auth_error(); - } - - match *req.method() { - Method::GET => { - let tomorrow = state.wakeup.tomorrow(); - let bytes = bincode::serialize(&tomorrow).unwrap(); - HttpResponse::Ok().body(bytes) - } - Method::POST => { - match bincode::deserialize(&body) { - Ok((hour,min)) => { - state.wakeup.set_tomorrow(hour, min).await; //TODO handle result of this - HttpResponse::Ok().finish() - } - Err(_) => HttpResponse::BadRequest().body("invalid encoding"), - } - } - _ => HttpResponse::BadRequest().finish(), - } -} - ///////////////////// lamp commands /////////////////////////////// pub fn toggle(state: Data, auth: BasicAuth) -> HttpResponse { if authenticated(auth) { diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index 64bfaab8..d0b83cff 100755 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -6,6 +6,7 @@ use actix_web::http::StatusCode; use actix_web::web::{Data, Form}; use actix_web::{HttpRequest, HttpResponse}; +mod wakeup; mod alarms; mod commands; mod logins; diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index 79ae3615..5539d1f8 100755 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -26,7 +26,7 @@ pub mod database; pub mod login; pub mod login_redirect; -use super::{alarms, commands, music}; +use super::{alarms, wakeup, commands, music}; pub use database::PasswordDatabase; pub use login::{login_get_and_check, login_page, logout, make_random_cookie_key}; pub use login_redirect::CheckLogin; @@ -172,8 +172,8 @@ pub fn start_webserver( .service(web::resource("/commands/lamps/dimmest").to(commands::dimmest)) .service(web::resource("/commands/lamps/dim").to(commands::dim)) .service(web::resource("/commands/lightloop").to(commands::lightloop)) - .service(web::resource("/alarm/tomorrow").to(commands::tomorrow)) - // .service(web::resource("/alarm/usually").to(commands::usually)) + .service(web::resource("/alarm/tomorrow").to(wakeup::tomorrow)) + .service(web::resource("/alarm/usually").to(wakeup::usually)) .service(web::resource(&format!("/{}", &state.bot_token)).to(bot::handle_webhook)) .service( web::resource(&format!("/{}", ha_key)).route(web::post().to(handle_sensor)), From 2507ec488acbc4bf283a7764353ee723f47d6ddf Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Mon, 22 Feb 2021 03:26:36 +0100 Subject: [PATCH 063/687] fix wakeup not being stored in db + missing api endpoint files --- src/input/jobs.rs | 13 ++++++-- src/input/jobs/wakeup.rs | 30 +++++++++-------- src/input/web_api/wakeup.rs | 64 +++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 15 deletions(-) create mode 100644 src/input/web_api/wakeup.rs diff --git a/src/input/jobs.rs b/src/input/jobs.rs index c60a1596..36ef4fc6 100644 --- a/src/input/jobs.rs +++ b/src/input/jobs.rs @@ -171,13 +171,15 @@ impl Jobs { self.waker_tx.send(())?; //signal waker to update its next alarm Ok(removed_alarm) } + pub fn get(&self, id: u64) -> Result, Error> { + self.list.get_alarm(id) + } pub fn list(&self) -> Vec<(u64, Job)> { - //self.alarm_list.iter().keys().map(|k| DateTime::::from_utc(NaiveDateTime::from_timestamp(k, 0), Utc);) let start: &[u8] = &[0]; let alarms = self.list.db.range(start..); - let mut list = Vec::new(); //TODO placeholder + let mut list = Vec::new(); for (key, alarm) in alarms.filter_map(Result::ok) { let alarm = bincode::deserialize(&alarm).unwrap(); let key = key.as_ref().read_u64::().unwrap(); @@ -188,6 +190,13 @@ impl Jobs { } impl JobList { + pub fn get_alarm(&self, id: u64) -> Result, Error> { + Ok(self + .db + .get(id.to_be_bytes())? + .map(|k| bincode::deserialize::(&k).unwrap())) + } + // we decrease the time till the alarm until there is a place in the database // as only one alarm can fire at the time, after an alarm gets a timeslot it is never changed /// return the key for the alarm diff --git a/src/input/jobs/wakeup.rs b/src/input/jobs/wakeup.rs index 490b56e7..2be61394 100644 --- a/src/input/jobs/wakeup.rs +++ b/src/input/jobs/wakeup.rs @@ -51,18 +51,18 @@ struct Inner { impl Inner { pub fn setup(db: sled::Db, jobs: Jobs) -> Result { let db = db.open_tree("wakeup")?; - let tomorrow = db - .get("tomorrow") - .unwrap() - .map(|b| bincode::deserialize(&b).unwrap()); let usually = db - .get("usually") - .unwrap() + .get("usually")? .map(|b| bincode::deserialize(&b).unwrap()); let job_id = db - .get("job_id") - .unwrap() + .get("job_id")? .map(|b| bincode::deserialize(&b).unwrap()); + let tomorrow = job_id.as_ref() + .map(|id| jobs.get(*id).ok()) + .flatten().flatten() + .map(|job| job.time.into()) + .map(|t: DateTime| (t.hour() as u8, t.minute() as u8)) + .filter(|tomorrow| Some(*tomorrow) != usually); Ok(Self { db, @@ -73,18 +73,21 @@ impl Inner { }) } - fn remove_existing_job(&self) { - if let Some(job_id) = self.job_id { - self.jobs.remove_alarm(job_id).unwrap(); + fn register_new_job(&mut self, id: u64) -> Result<(), Error> { + self.job_id = Some(id); + let bytes = bincode::serialize(&id).unwrap(); + if let Some(bytes) = self.db.insert("job_id", bytes)? { + let old_job_id = bincode::deserialize(&bytes).unwrap(); + self.jobs.remove_alarm(old_job_id)?; } + Ok(()) } async fn add_new_job(&mut self, job: Job) -> Result<(),Error> { let id = self.jobs .add_alarm(job) .await?; - self.remove_existing_job(); - self.job_id = Some(id); + self.register_new_job(id)?; Ok(()) } @@ -94,6 +97,7 @@ impl Inner { let add = self.add_new_job(job); smol::block_on(add)?; } + self.tomorrow = None; Ok(()) } diff --git a/src/input/web_api/wakeup.rs b/src/input/web_api/wakeup.rs new file mode 100644 index 00000000..3764ea81 --- /dev/null +++ b/src/input/web_api/wakeup.rs @@ -0,0 +1,64 @@ +use actix_web::web::Data; +use actix_web_httpauth::extractors::basic::BasicAuth; +use actix_web::http::Method; +use actix_web::FromRequest; +use actix_web::web::Bytes; +use actix_web::HttpResponse; + +use super::*; +use crate::input::jobs::WakeUp; + +async fn set_tomorrow(wakeup: &WakeUp, body: Bytes) -> Result { + let (hour,min) = bincode::deserialize(&body).map_err(|_| ())?; + wakeup.set_tomorrow(hour, min).await.map_err(|_| ())?; + Ok(HttpResponse::Ok().finish()) +} + +pub async fn tomorrow(state: Data, auth: BasicAuth, req: HttpRequest, body: Bytes) -> HttpResponse { + if !authenticated(auth) { + return make_auth_error(); + } + + match *req.method() { + Method::GET => { + let tomorrow = state.wakeup.tomorrow(); + let bytes = bincode::serialize(&tomorrow).unwrap(); + HttpResponse::Ok().body(bytes) + } + Method::POST => { + match set_tomorrow(&state.wakeup, body).await { + Ok(resp) => resp, + Err(_) => HttpResponse::BadRequest().finish() + } + } + _ => HttpResponse::BadRequest().finish(), + } +} + +async fn set_usually(wakeup: &WakeUp, body: Bytes) -> Result { + let (hour,min) = bincode::deserialize(&body).map_err(|_| ())?; + wakeup.set_usually(hour, min).await.map_err(|_| ())?; + Ok(HttpResponse::Ok().finish()) +} + +pub async fn usually(state: Data, auth: BasicAuth, req: HttpRequest, body: Bytes) -> HttpResponse { + if !authenticated(auth) { + return make_auth_error(); + } + + match *req.method() { + Method::GET => { + let usually = state.wakeup.usually(); + let bytes = bincode::serialize(&usually).unwrap(); + HttpResponse::Ok().body(bytes) + } + Method::POST => { + match set_usually(&state.wakeup, body).await { + Ok(resp) => resp, + Err(_) => HttpResponse::BadRequest().finish() + } + } + _ => HttpResponse::BadRequest().finish(), + } +} + From 96eed320f25f80bbb36be86ba86f3fce7cc5f478 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Tue, 23 Feb 2021 02:40:03 +0100 Subject: [PATCH 064/687] web api unresponsive now works for unsetting alarm + error handeling reworked --- src/controller/environment/mod.rs | 2 +- src/controller/mod.rs | 2 +- src/controller/state/wakeup.rs | 10 +-- src/controller/system/lamps/mod.rs | 4 +- src/errors.rs | 114 ++++++----------------------- src/input/bot/set_alarm.rs | 12 +-- src/input/jobs.rs | 2 +- src/input/jobs/wakeup.rs | 65 ++++++++++------ src/input/web_api/alarms.rs | 7 +- src/input/web_api/commands.rs | 3 - src/input/web_api/wakeup.rs | 10 +-- 11 files changed, 86 insertions(+), 145 deletions(-) diff --git a/src/controller/environment/mod.rs b/src/controller/environment/mod.rs index 1a12dcc1..4375a2f0 100755 --- a/src/controller/environment/mod.rs +++ b/src/controller/environment/mod.rs @@ -9,7 +9,7 @@ pub struct Environment { } impl Environment { - pub fn update(&self, s: SensorValue) {} + pub fn update(&self, _: SensorValue) {} } impl std::default::Default for Environment { diff --git a/src/controller/mod.rs b/src/controller/mod.rs index 032f220a..47d3b284 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -151,7 +151,7 @@ fn handle_event( (Event::Command(cmd), _) => handle_cmd(cmd, mods, system), (Event::Update, _) => state.update(mods, system, env)?, (Event::WakeUp, _) => { - system.wakeup.reset(); + system.wakeup.reset()?; Some(State::WakeUp) } (Event::Test, _) => { diff --git a/src/controller/state/wakeup.rs b/src/controller/state/wakeup.rs index 88277230..282fb150 100755 --- a/src/controller/state/wakeup.rs +++ b/src/controller/state/wakeup.rs @@ -29,11 +29,11 @@ impl WakeUp { fn setup_playlist() -> Result<(), Error> { let mpd = &mut retry(Fixed::from_millis(100), || { mpd::Client::connect("127.0.0.1:6600") - })?; + }).unwrap();//?; dbg!(); retry(Fixed::from_millis(100).take(3), || { system::mpd_control::save_current_playlist(mpd) - })?; + }).unwrap();//?; dbg!(); retry(Fixed::from_millis(100).take(3), || { system::mpd_control::add_from_playlist( @@ -42,7 +42,7 @@ impl WakeUp { chrono::Duration::seconds(3 * 60), chrono::Duration::seconds(5 * 60), ) - })?; + }).unwrap();//?; dbg!(); retry(Fixed::from_millis(100).take(3), || { system::mpd_control::add_from_playlist( @@ -51,7 +51,7 @@ impl WakeUp { chrono::Duration::seconds(10 * 60), chrono::Duration::seconds(11 * 60), ) - })?; + }).unwrap();//?; retry(Fixed::from_millis(100).take(3), || { system::mpd_control::add_from_playlist( mpd, @@ -59,7 +59,7 @@ impl WakeUp { chrono::Duration::seconds(30 * 60), chrono::Duration::seconds(60 * 60), ) - })?; + }).unwrap();//?; Ok(()) } } diff --git a/src/controller/system/lamps/mod.rs b/src/controller/system/lamps/mod.rs index 8cb0d6d9..bb7e3eda 100755 --- a/src/controller/system/lamps/mod.rs +++ b/src/controller/system/lamps/mod.rs @@ -123,7 +123,7 @@ fn get_bridge_and_status() -> Result<(Bridge, BTreeMap { - login = register(&ip)?; + login = register(&ip).map_err(|_| Error::UnTracked)?; update_ip_or_login = true; } Err(e) => { @@ -134,7 +134,7 @@ fn get_bridge_and_status() -> Result<(Bridge, BTreeMap), - DataBase(sled::Error), - Download(reqwest::Error), - Lamps(philipshue::errors::HueError), - Mpd(mpd::error::Error), + #[error("Io error")] + IO(#[from] std::io::Error), + #[error("Could not parse yaml")] + YamlParsing(#[from] serde_yaml::Error), + #[error("Channel send error")] + Channel(#[from] crossbeam_channel::SendError<()>), + #[error("Database error")] + DataBase(#[from] sled::Error), + #[error("Could not download youtube")] + Download(#[from] reqwest::Error), + #[error("Error contacting hue")] + Lamps(#[from] philipshue::errors::HueError), + #[error("Error contacting mpd")] + Mpd(#[from] mpd::error::Error), + #[error("TODO")] RetryLogic(String), + #[error("Could not download youtube movie")] YoutubeDownloader(youtube_downloader::Error), + #[error("Problem handeling web requests")] WebServerError(server::Error), + #[error("Wakeup system")] + WakeUp(#[from] crate::input::jobs::wakeup::Error), + #[error("untracked error")] UnTracked, } -impl From for Error { - fn from(err: server::Error) -> Self { - Error::WebServerError(err) - } -} - -impl From for Error { - fn from(err: youtube_downloader::Error) -> Self { - Error::YoutubeDownloader(err) - } -} - -impl From for Error { - fn from(error: serde_yaml::Error) -> Self { - Error::YamlParsing(error) - } -} -impl From for Error { - fn from(error: std::io::Error) -> Self { - Error::IO(error) - } -} - -impl From> for Error { - fn from(error: crossbeam_channel::SendError<()>) -> Self { - Error::Channel(error) - } -} - -impl From for Error { - fn from(error: reqwest::Error) -> Self { - Error::Download(error) - } -} - -impl From> for Error { - fn from(error: retry::Error) -> Self { - match error { - retry::Error::Operation { - error, - total_delay: _total_delay, - tries: _tries, - } => error, - retry::Error::Internal(error_str) => Error::RetryLogic(error_str), - } - } -} - -impl From> for Error { - fn from(error: retry::Error) -> Self { - match error { - retry::Error::Operation { - error, - total_delay: _total_delay, - tries: _tries, - } => Error::Mpd(error), - retry::Error::Internal(error_str) => Error::RetryLogic(error_str), - } - } -} - -impl From for Error { - fn from(error: sled::Error) -> Self { - Error::DataBase(error) - } -} - -impl From<()> for Error { - fn from(_error: ()) -> Self { - Error::UnTracked - } -} - -impl From for Error { - fn from(error: philipshue::errors::HueError) -> Self { - Error::Lamps(error) - } -} - -impl From for Error { - fn from(error: mpd::error::Error) -> Self { - Error::Mpd(error) - } -} - pub fn setup_logging(verbosity: u8) -> Result<(), fern::InitError> { let mut base_config = fern::Dispatch::new(); let colors = ColoredLevelConfig::new() diff --git a/src/input/bot/set_alarm.rs b/src/input/bot/set_alarm.rs index cb30cc16..511a74d4 100644 --- a/src/input/bot/set_alarm.rs +++ b/src/input/bot/set_alarm.rs @@ -44,7 +44,8 @@ pub async fn add_tomorrow<'a>( ) -> Result<(), Error> { let (hour, min, text) = parse_args(chat_id, token, args, state)?; - state.wakeup.set_tomorrow(hour as u8, min as u8).await.map_err(|_| Error::BackendError)?; + let time = Some((hour as u8, min as u8)); + state.wakeup.set_tomorrow(time).await.map_err(|_| Error::BackendError)?; send_text(chat_id, token, text) .await .map_err(|_| Error::CouldNotRespond)?; @@ -60,7 +61,8 @@ pub async fn add_usually<'a>( ) -> Result<(), Error> { let (hour, min, text) = parse_args(chat_id, token, args, state)?; - state.wakeup.set_usually(hour as u8, min as u8).await.map_err(|_| Error::BackendError)?; + let time = Some((hour as u8, min as u8)); + state.wakeup.set_usually(time).await.map_err(|_| Error::BackendError)?; send_text(chat_id, token, text) .await .map_err(|_| Error::CouldNotRespond)?; @@ -69,10 +71,10 @@ pub async fn add_usually<'a>( } fn parse_args<'a>( - chat_id: ChatId, - token: &str, + _: ChatId, + _: &str, mut args: std::str::SplitWhitespace<'a>, - state: &State, + _: &State, ) -> Result<(u8, u8, String), Error> { let time = args.next().ok_or(Error::NoTimeArgument)?; diff --git a/src/input/jobs.rs b/src/input/jobs.rs index 36ef4fc6..d3072679 100644 --- a/src/input/jobs.rs +++ b/src/input/jobs.rs @@ -10,7 +10,7 @@ use sled; use crate::controller::Command; use crate::controller::Event; -mod wakeup; +pub mod wakeup; pub use wakeup::WakeUp; #[derive(Serialize, Deserialize, Debug)] diff --git a/src/input/jobs/wakeup.rs b/src/input/jobs/wakeup.rs index 2be61394..4756caaa 100644 --- a/src/input/jobs/wakeup.rs +++ b/src/input/jobs/wakeup.rs @@ -1,5 +1,4 @@ use super::{Jobs, Job, Action}; -// use crate::errors::Error; use crate::controller::Event; use std::time::Duration; use std::sync::{Arc, Mutex}; @@ -11,8 +10,6 @@ pub enum Error { DbError(#[from] sled::Error), #[error("Could not create/edit wakeup job")] JobError(#[from] super::Error), - - } #[derive(Clone)] @@ -32,18 +29,19 @@ impl WakeUp { pub fn reset(&self) -> Result<(), Error> { self.0.lock().unwrap().reset() } - pub async fn set_tomorrow(&self, hour: u8, min: u8) -> Result<(), Error> { - self.0.lock().unwrap().set_tomorrow(hour, min).await + pub async fn set_tomorrow(&self, time: Time) -> Result<(), Error> { + self.0.lock().unwrap().set_tomorrow(time).await } - pub async fn set_usually(&self, hour: u8, min: u8) -> Result<(), Error> { - self.0.lock().unwrap().set_usually(hour, min).await + pub async fn set_usually(&self, time: Time) -> Result<(), Error> { + self.0.lock().unwrap().set_usually(time).await } } +type Time = Option<(u8, u8)>; struct Inner { db: sled::Tree, - pub tomorrow: Option<(u8, u8)>, - pub usually: Option<(u8, u8)>, + pub tomorrow: Time, + pub usually: Time, job_id: Option, jobs: Jobs, } @@ -73,7 +71,7 @@ impl Inner { }) } - fn register_new_job(&mut self, id: u64) -> Result<(), Error> { + fn save_job_id(&mut self, id: u64) -> Result<(), Error> { self.job_id = Some(id); let bytes = bincode::serialize(&id).unwrap(); if let Some(bytes) = self.db.insert("job_id", bytes)? { @@ -83,40 +81,61 @@ impl Inner { Ok(()) } - async fn add_new_job(&mut self, job: Job) -> Result<(),Error> { + async fn replace_current(&mut self, job: Job) -> Result<(),Error> { let id = self.jobs .add_alarm(job) .await?; - self.register_new_job(id)?; + self.save_job_id(id)?; Ok(()) } + async fn remove_current(&mut self) -> Result<(), Error> { + self.jobs.remove_alarm(self.job_id.unwrap())?; + self.job_id = None; + Ok(()) + } + + /// reset the alarm, if their is a usual alarm + /// time we set that, otherwise remove all pub fn reset(&mut self) -> Result<(),Error> { if let Some((hour,min)) = self.usually { - let job = wakeup_job(hour, min); - let add = self.add_new_job(job); + let job = job_from(hour, min); + let add = self.replace_current(job); smol::block_on(add)?; + } else { + let remove = self.remove_current(); + smol::block_on(remove)?; } self.tomorrow = None; Ok(()) } - pub async fn set_tomorrow(&mut self, hour: u8, min: u8) -> Result<(),Error> { - let job = wakeup_job(hour, min); - self.tomorrow = Some((hour,min)); - self.add_new_job(job).await?; + pub async fn set_tomorrow(&mut self, time: Time) -> Result<(),Error> { + match time { + None => self.reset()?, + Some((hour, min)) => { + let job = job_from(hour, min); + self.replace_current(job).await?; + } + } + self.tomorrow = time; Ok(()) } - pub async fn set_usually(&mut self, hour: u8, min: u8) -> Result<(), Error> { - let job = wakeup_job(hour, min); - self.usually = Some((hour,min)); - self.add_new_job(job).await?; + pub async fn set_usually(&mut self, time: Time) -> Result<(), Error> { + match time { + None => self.reset()?, + Some((hour, min)) => { + let job = job_from(hour, min); + self.replace_current(job).await?; + } + } + self.usually = time; Ok(()) } } -fn wakeup_job(hour: u8, min: u8) -> Job { +fn job_from(hour: u8, min: u8) -> Job { Job { time: to_datetime(hour,min), action: Action::SendEvent(Event::WakeUp), diff --git a/src/input/web_api/alarms.rs b/src/input/web_api/alarms.rs index 01590e24..ef977230 100644 --- a/src/input/web_api/alarms.rs +++ b/src/input/web_api/alarms.rs @@ -1,10 +1,7 @@ use chrono::{DateTime, NaiveDateTime, Utc, Timelike}; use serde::Deserialize; -use std::time::Duration; use super::*; -use crate::controller::Event; -use crate::input::jobs::Job; #[derive(Deserialize, Debug)] pub struct AlarmDataMinFrom { @@ -12,7 +9,6 @@ pub struct AlarmDataMinFrom { } pub fn set_alarm_minutes_from_now( - req: HttpRequest, params: Form, state: Data, auth: BasicAuth, @@ -54,7 +50,8 @@ pub async fn set_alarm_unix_timestamp( if time > Utc::now() { let hour = time.time().hour() as u8; let min = time.time().minute() as u8; - if state.wakeup.set_tomorrow(hour, min).await.is_ok() { + let time = Some((hour,min)); + if state.wakeup.set_tomorrow(time).await.is_ok() { dbg!("done setting alarm"); HttpResponse::Ok().finish() } else { diff --git a/src/input/web_api/commands.rs b/src/input/web_api/commands.rs index 1c5a4422..e76cb816 100644 --- a/src/input/web_api/commands.rs +++ b/src/input/web_api/commands.rs @@ -1,8 +1,5 @@ use actix_web::web::Data; use actix_web_httpauth::extractors::basic::BasicAuth; -use actix_web::http::Method; -use actix_web::FromRequest; -use actix_web::web::Bytes; use actix_web::HttpResponse; use super::*; diff --git a/src/input/web_api/wakeup.rs b/src/input/web_api/wakeup.rs index 3764ea81..d82fc7e0 100644 --- a/src/input/web_api/wakeup.rs +++ b/src/input/web_api/wakeup.rs @@ -1,7 +1,6 @@ use actix_web::web::Data; use actix_web_httpauth::extractors::basic::BasicAuth; use actix_web::http::Method; -use actix_web::FromRequest; use actix_web::web::Bytes; use actix_web::HttpResponse; @@ -9,8 +8,8 @@ use super::*; use crate::input::jobs::WakeUp; async fn set_tomorrow(wakeup: &WakeUp, body: Bytes) -> Result { - let (hour,min) = bincode::deserialize(&body).map_err(|_| ())?; - wakeup.set_tomorrow(hour, min).await.map_err(|_| ())?; + let time = bincode::deserialize(&body).map_err(|_| ())?; + wakeup.set_tomorrow(time).await.map_err(|_| ())?; Ok(HttpResponse::Ok().finish()) } @@ -36,8 +35,8 @@ pub async fn tomorrow(state: Data, auth: BasicAuth, req: HttpRequest, bod } async fn set_usually(wakeup: &WakeUp, body: Bytes) -> Result { - let (hour,min) = bincode::deserialize(&body).map_err(|_| ())?; - wakeup.set_usually(hour, min).await.map_err(|_| ())?; + let time = bincode::deserialize(&body).map_err(|_| ())?; + wakeup.set_usually(time).await.map_err(|_| ())?; Ok(HttpResponse::Ok().finish()) } @@ -61,4 +60,3 @@ pub async fn usually(state: Data, auth: BasicAuth, req: HttpRequest, body _ => HttpResponse::BadRequest().finish(), } } - From 8eeabd2290c06770926a56d6b0746bff6b314b1c Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Tue, 23 Feb 2021 04:23:16 +0100 Subject: [PATCH 065/687] improves error handeling of wakeup state, fixes mpd volume bugs in wakeup state --- Cargo.lock | 975 +++++++++++++++------------ Cargo.toml | 2 +- src/controller/mod.rs | 2 +- src/controller/state/mod.rs | 2 +- src/controller/state/wakeup.rs | 50 +- src/controller/system/mpd_control.rs | 7 +- src/errors.rs | 6 +- 7 files changed, 595 insertions(+), 449 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e49d3d08..131bac5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,11 +22,11 @@ dependencies = [ "crossbeam-channel 0.3.9", "dirs", "fern", - "futures 0.3.8", + "futures 0.3.12", "gpio-cdev", "hex", "linux-embedded-hal", - "log 0.4.11", + "log 0.4.14", "mpd", "nix 0.17.0", "num 0.2.1", @@ -34,7 +34,7 @@ dependencies = [ "philipshue", "rand 0.6.5", "regex", - "reqwest 0.10.8", + "reqwest 0.10.10", "retry", "ring", "rustls 0.16.0", @@ -43,7 +43,7 @@ dependencies = [ "serde_json", "serde_yaml", "sled", - "smallvec 0.6.13", + "smallvec 0.6.14", "smol", "structopt", "telegram-bot", @@ -64,9 +64,9 @@ dependencies = [ "fnv", "futures 0.1.30", "libc", - "log 0.4.11", + "log 0.4.14", "parking_lot 0.7.1", - "smallvec 0.6.13", + "smallvec 0.6.14", "tokio 0.1.22", "tokio-codec", "tokio-executor", @@ -90,8 +90,8 @@ dependencies = [ "bytes 0.5.6", "futures-core", "futures-sink", - "log 0.4.11", - "tokio 0.2.23", + "log 0.4.14", + "tokio 0.2.25", "tokio-util 0.2.0", ] @@ -105,9 +105,9 @@ dependencies = [ "bytes 0.5.6", "futures-core", "futures-sink", - "log 0.4.11", + "log 0.4.14", "pin-project 0.4.27", - "tokio 0.2.23", + "tokio 0.2.25", "tokio-util 0.3.1", ] @@ -123,9 +123,9 @@ dependencies = [ "actix-utils 1.0.6", "derive_more", "either", - "futures 0.3.8", - "http 0.2.1", - "log 0.4.11", + "futures 0.3.12", + "http 0.2.3", + "log 0.4.14", "rustls 0.16.0", "tokio-rustls 0.12.3", "trust-dns-proto 0.18.0-alpha.2", @@ -147,7 +147,7 @@ dependencies = [ "derive_more", "futures-core", "futures-util", - "log 0.4.11", + "log 0.4.14", "mime 0.3.16", "mime_guess 2.0.3", "percent-encoding 2.1.0", @@ -183,12 +183,12 @@ dependencies = [ "futures-util", "fxhash", "h2 0.2.7", - "http 0.2.1", + "http 0.2.3", "httparse", "indexmap", "language-tags", "lazy_static", - "log 0.4.11", + "log 0.4.14", "mime 0.3.16", "percent-encoding 2.1.0", "pin-project 0.4.27", @@ -211,7 +211,7 @@ checksum = "2a379b0639c293292d71defb8cc1f94c87b7705c904adf044338ad392df77c7a" dependencies = [ "actix-service", "actix-web", - "futures 0.3.8", + "futures 0.3.12", "serde", "serde_json", "time", @@ -219,12 +219,12 @@ dependencies = [ [[package]] name = "actix-macros" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a60f9ba7c4e6df97f3aacb14bb5c0cd7d98a49dcbaed0d7f292912ad9a6a3ed2" +checksum = "b4ca8ce00b267af8ccebbd647de0d61e0674b6e61185cc7a592ff88772bed655" dependencies = [ - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", ] [[package]] @@ -236,7 +236,7 @@ dependencies = [ "actix", "bytes 0.4.12", "futures 0.1.30", - "log 0.4.11", + "log 0.4.14", "mio", "net2", "num_cpus", @@ -254,13 +254,13 @@ dependencies = [ [[package]] name = "actix-router" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd1f7dbda1645bf7da33554db60891755f6c01c1b2169e2f4c492098d30c235" +checksum = "2ad299af73649e1fc893e333ccf86f377751eb95ff875d095131574c6f43452c" dependencies = [ "bytestring", - "http 0.2.1", - "log 0.4.11", + "http 0.2.3", + "log 0.4.14", "regex", "serde", ] @@ -276,8 +276,8 @@ dependencies = [ "copyless", "futures-channel", "futures-util", - "smallvec 1.4.2", - "tokio 0.2.23", + "smallvec 1.6.1", + "tokio 0.2.25", ] [[package]] @@ -292,7 +292,7 @@ dependencies = [ "actix-utils 2.0.0", "futures-channel", "futures-util", - "log 0.4.11", + "log 0.4.14", "mio", "mio-uds", "num_cpus", @@ -320,7 +320,7 @@ dependencies = [ "actix-rt", "actix-server", "actix-service", - "log 0.4.11", + "log 0.4.14", "socket2", ] @@ -333,9 +333,9 @@ dependencies = [ "derive_more", "futures-channel", "lazy_static", - "log 0.4.11", + "log 0.4.14", "num_cpus", - "parking_lot 0.11.0", + "parking_lot 0.11.1", "threadpool", ] @@ -351,8 +351,8 @@ dependencies = [ "actix-utils 1.0.6", "derive_more", "either", - "futures 0.3.8", - "log 0.4.11", + "futures 0.3.12", + "log 0.4.14", "rustls 0.16.0", "tokio-rustls 0.12.3", "webpki", @@ -371,8 +371,8 @@ dependencies = [ "bitflags 1.2.1", "bytes 0.5.6", "either", - "futures 0.3.8", - "log 0.4.11", + "futures 0.3.12", + "log 0.4.14", "pin-project 0.4.27", "slab", ] @@ -392,7 +392,7 @@ dependencies = [ "futures-channel", "futures-sink", "futures-util", - "log 0.4.11", + "log 0.4.14", "pin-project 0.4.27", "slab", ] @@ -419,9 +419,9 @@ dependencies = [ "bytes 0.5.6", "derive_more", "encoding_rs", - "futures 0.3.8", + "futures 0.3.12", "fxhash", - "log 0.4.11", + "log 0.4.14", "mime 0.3.16", "net2", "pin-project 0.4.27", @@ -431,7 +431,7 @@ dependencies = [ "serde_json", "serde_urlencoded 0.6.1", "time", - "url 2.2.0", + "url 2.2.1", ] [[package]] @@ -441,8 +441,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a71bf475cbe07281d0b3696abb48212db118e7e23219f13596ce865235ff5766" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", ] [[package]] @@ -471,9 +471,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423" +checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7" dependencies = [ "gimli", ] @@ -525,9 +525,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "async-channel" -version = "1.5.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59740d83946db6a5af71ae25ddf9562c2b176b2ca42cf99a455f09f4a220d6b9" +checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" dependencies = [ "concurrent-queue", "event-listener", @@ -561,12 +561,15 @@ dependencies = [ [[package]] name = "async-global-executor" -version = "1.4.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73079b49cd26b8fd5a15f68fc7707fc78698dc2a3d61430f2a7a9430230dfa04" +checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6" dependencies = [ + "async-channel", "async-executor", "async-io", + "async-mutex", + "blocking", "futures-lite", "num_cpus", "once_cell", @@ -574,15 +577,15 @@ dependencies = [ [[package]] name = "async-io" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a0b2bb8ae20fede194e779150fe283f65a4a08461b496de546ec366b174ad9" +checksum = "9315f8f07556761c3e48fec2e6b276004acf426e6dc068b2c2251854d65ee0fd" dependencies = [ "concurrent-queue", "fastrand", "futures-lite", "libc", - "log 0.4.11", + "log 0.4.14", "nb-connect", "once_cell", "parking", @@ -640,26 +643,26 @@ dependencies = [ [[package]] name = "async-std" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7e82538bc65a25dbdff70e4c5439d52f068048ab97cdea0acd73f131594caa1" +checksum = "d9f06685bad74e0570f5213741bea82158279a4103d988e57bfada11ad230341" dependencies = [ + "async-channel", "async-global-executor", "async-io", - "async-mutex", - "blocking", - "crossbeam-utils 0.8.0", + "async-lock", + "crossbeam-utils 0.8.2", "futures-channel", "futures-core", "futures-io", "futures-lite", "gloo-timers", "kv-log-macro", - "log 0.4.11", + "log 0.4.14", "memchr", "num_cpus", "once_cell", - "pin-project-lite", + "pin-project-lite 0.2.4", "pin-utils", "slab", "wasm-bindgen-futures", @@ -673,13 +676,13 @@ checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" [[package]] name = "async-trait" -version = "0.1.41" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b246867b8b3b6ae56035f1eb1ed557c1d8eae97f0d53696138a50fa0e3a3b8c0" +checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", ] [[package]] @@ -725,7 +728,7 @@ dependencies = [ "bytes 0.5.6", "derive_more", "futures-core", - "log 0.4.11", + "log 0.4.14", "mime 0.3.16", "percent-encoding 2.1.0", "rand 0.7.3", @@ -737,9 +740,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.54" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2baad346b2d4e94a24347adeee9c7a93f412ee94b9cc26e5b59dea23848e9f28" +checksum = "9d117600f438b1707d4e4ae15d3595657288f8235a0eb593e80ecc98ab34e1bc" dependencies = [ "addr2line", "cfg-if 1.0.0", @@ -770,6 +773,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + [[package]] name = "bincode" version = "1.3.1" @@ -803,7 +812,7 @@ name = "bitspec" version = "1.0.0" source = "git+https://github.com/dskleingeld/bitspec?branch=bool-fields#65e92b1ad3d3900a634cc6828785ed4054c83985" dependencies = [ - "log 0.4.11", + "log 0.4.14", "num 0.3.1", "rand 0.5.6", "serde", @@ -874,15 +883,15 @@ checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" [[package]] name = "bumpalo" -version = "3.4.0" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" +checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" [[package]] name = "byteorder" -version = "1.3.4" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" [[package]] name = "bytes" @@ -901,13 +910,19 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" +[[package]] +name = "bytes" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" + [[package]] name = "bytestring" -version = "0.1.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7c05fa5172da78a62d9949d662d2ac89d4cc7355d7b49adee5163f1fb3f363" +checksum = "90706ba19e97b90786e19dc0d5e2abd80008d99d4c0c5d1ad0b5e72cec7c494d" dependencies = [ - "bytes 0.5.6", + "bytes 1.0.1", ] [[package]] @@ -927,9 +942,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.62" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1770ced377336a88a67c473594ccc14eca6f4559217c34f64aac8f83d641b40" +checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" [[package]] name = "cfg-if" @@ -991,15 +1006,6 @@ dependencies = [ "bitflags 1.2.1", ] -[[package]] -name = "cloudabi" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467" -dependencies = [ - "bitflags 1.2.1", -] - [[package]] name = "colored" version = "1.9.3" @@ -1020,12 +1026,6 @@ dependencies = [ "cache-padded", ] -[[package]] -name = "const_fn" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab" - [[package]] name = "constant_time_eq" version = "0.1.5" @@ -1051,7 +1051,7 @@ dependencies = [ "cookie", "failure", "idna 0.1.5", - "log 0.4.11", + "log 0.4.14", "publicsuffix", "serde", "serde_json", @@ -1107,7 +1107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.0", + "crossbeam-utils 0.8.2", ] [[package]] @@ -1128,8 +1128,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" dependencies = [ "cfg-if 1.0.0", - "crossbeam-epoch 0.9.0", - "crossbeam-utils 0.8.0", + "crossbeam-epoch 0.9.2", + "crossbeam-utils 0.8.2", ] [[package]] @@ -1142,7 +1142,7 @@ dependencies = [ "cfg-if 0.1.10", "crossbeam-utils 0.6.6", "lazy_static", - "memoffset", + "memoffset 0.5.6", "scopeguard 1.1.0", ] @@ -1157,21 +1157,21 @@ dependencies = [ "crossbeam-utils 0.7.2", "lazy_static", "maybe-uninit", - "memoffset", + "memoffset 0.5.6", "scopeguard 1.1.0", ] [[package]] name = "crossbeam-epoch" -version = "0.9.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0f606a85340376eef0d6d8fec399e6d4a544d648386c6645eb6d0653b27d9f" +checksum = "d60ab4a8dba064f2fbb5aa270c28da5cf4bbd0e72dae1140a6b0353a779dbe00" dependencies = [ "cfg-if 1.0.0", - "const_fn", - "crossbeam-utils 0.8.0", + "crossbeam-utils 0.8.2", "lazy_static", - "memoffset", + "loom", + "memoffset 0.6.1", "scopeguard 1.1.0", ] @@ -1209,14 +1209,14 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec91540d98355f690a86367e566ecad2e9e579f230230eb7c21398372be73ea5" +checksum = "bae8f328835f8f5a6ceb6a7842a7f2d0c03692adb5c889347235d59194731fe3" dependencies = [ "autocfg 1.0.1", "cfg-if 1.0.0", - "const_fn", "lazy_static", + "loom", ] [[package]] @@ -1228,6 +1228,16 @@ dependencies = [ "sct", ] +[[package]] +name = "ctor" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8f45d9ad417bcef4817d614a501ab55cdd96a6fdb24f49aab89a54acfd66b19" +dependencies = [ + "quote 1.0.9", + "syn 1.0.60", +] + [[package]] name = "derive_more" version = "0.99.11" @@ -1235,8 +1245,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", ] [[package]] @@ -1262,9 +1272,9 @@ dependencies = [ [[package]] name = "dtoa" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b" +checksum = "88d7ed2934d741c6b37e33e3832298e8850b53fd2d2bea03873375596c7cea4e" [[package]] name = "either" @@ -1284,9 +1294,9 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.26" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "801bbab217d7f79c0062f4f7205b5d4427c6d1a7bd7aafdd1475f7c59d62b283" +checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" dependencies = [ "cfg-if 1.0.0", ] @@ -1299,8 +1309,8 @@ checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595" dependencies = [ "heck", "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", ] [[package]] @@ -1353,8 +1363,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", "synstructure", ] @@ -1375,14 +1385,14 @@ checksum = "e69ab0d5aca163e388c3a49d284fed6c3d0810700e77c5ae2756a50ec1a4daaa" dependencies = [ "chrono", "colored", - "log 0.4.11", + "log 0.4.14", ] [[package]] name = "flate2" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129" +checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" dependencies = [ "cfg-if 1.0.0", "crc32fast", @@ -1398,9 +1408,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" dependencies = [ "matches", "percent-encoding 2.1.0", @@ -1446,9 +1456,9 @@ checksum = "4c7e4c2612746b0df8fed4ce0c69156021b704c9aefa360311c04e6e9e002eed" [[package]] name = "futures" -version = "0.3.8" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b3b0c040a1fe6529d30b3c5944b280c7f0dcb2930d2c3062bca967b602583d0" +checksum = "da9052a1a50244d8d5aa9bf55cbc2fb6f357c86cc52e46c62ed390a7180cf150" dependencies = [ "futures-channel", "futures-core", @@ -1461,9 +1471,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.8" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b7109687aa4e177ef6fe84553af6280ef2778bdb7783ba44c9dc3399110fe64" +checksum = "f2d31b7ec7efab6eefc7c57233bb10b847986139d88cc2f5a02a1ae6871a1846" dependencies = [ "futures-core", "futures-sink", @@ -1471,9 +1481,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.8" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748" +checksum = "79e5145dde8da7d1b3892dad07a9c98fc04bc39892b1ecc9692cf53e2b780a65" [[package]] name = "futures-cpupool" @@ -1487,9 +1497,9 @@ dependencies = [ [[package]] name = "futures-executor" -version = "0.3.8" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4caa2b2b68b880003057c1dd49f1ed937e38f22fcf6c212188a121f08cf40a65" +checksum = "e9e59fdc009a4b3096bf94f740a0f2424c082521f20a9b08c5c07c48d90fd9b9" dependencies = [ "futures-core", "futures-task", @@ -1498,57 +1508,57 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.8" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611834ce18aaa1bd13c4b374f5d653e1027cf99b6b502584ff8c9a64413b30bb" +checksum = "28be053525281ad8259d47e4de5de657b25e7bac113458555bb4b70bc6870500" [[package]] name = "futures-lite" -version = "1.11.2" +version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6c079abfac3ab269e2927ec048dabc89d009ebfdda6b8ee86624f30c689658" +checksum = "b4481d0cd0de1d204a4fa55e7d45f07b1d958abcb06714b3446438e2eff695fb" dependencies = [ "fastrand", "futures-core", "futures-io", "memchr", "parking", - "pin-project-lite", + "pin-project-lite 0.2.4", "waker-fn", ] [[package]] name = "futures-macro" -version = "0.3.8" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77408a692f1f97bcc61dc001d752e00643408fbc922e4d634c655df50d595556" +checksum = "c287d25add322d9f9abdcdc5927ca398917996600182178774032e9f8258fedd" dependencies = [ "proc-macro-hack", "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", ] [[package]] name = "futures-sink" -version = "0.3.8" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f878195a49cee50e006b02b93cf7e0a95a38ac7b776b4c4d9cc1207cd20fcb3d" +checksum = "caf5c69029bda2e743fddd0582d1083951d65cc9539aebf8812f36c3491342d6" [[package]] name = "futures-task" -version = "0.3.8" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c554eb5bf48b2426c4771ab68c6b14468b6e76cc90996f528c3338d761a4d0d" +checksum = "13de07eb8ea81ae445aca7b69f5f7bf15d7bf4912d8ca37d6645c77ae8a58d86" dependencies = [ "once_cell", ] [[package]] name = "futures-util" -version = "0.3.8" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d304cff4a7b99cfb7986f7d43fbe93d175e72e704a8860787cc95e9ffd85cbd2" +checksum = "632a8cd0f2a4b3fdea1657f08bde063848c3bd00f9bbf6e256b8be78802e624b" dependencies = [ "futures-channel", "futures-core", @@ -1557,7 +1567,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project 1.0.1", + "pin-project-lite 0.2.4", "pin-utils", "proc-macro-hack", "proc-macro-nested", @@ -1573,17 +1583,41 @@ dependencies = [ "byteorder", ] +[[package]] +name = "generator" +version = "0.6.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9fed24fd1e18827652b4d55652899a1e9da8e54d91624dc3437a5bc3a9f9a9c" +dependencies = [ + "cc", + "libc", + "log 0.4.14", + "rustversion", + "winapi 0.3.9", +] + [[package]] name = "getrandom" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] +[[package]] +name = "getrandom" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", +] + [[package]] name = "gimli" version = "0.23.0" @@ -1606,7 +1640,7 @@ dependencies = [ [[package]] name = "gpio-cdev" version = "0.4.0" -source = "git+https://github.com/rust-embedded/gpio-cdev?branch=master#a8c1c10f3b5f5d76ef34e4581fb0c621865b364b" +source = "git+https://github.com/rust-embedded/gpio-cdev?branch=master#246f5baaf1c64a6e0cb8dd651fd1625aa7d10815" dependencies = [ "bitflags 1.2.1", "libc", @@ -1625,7 +1659,7 @@ dependencies = [ "futures 0.1.30", "http 0.1.21", "indexmap", - "log 0.4.11", + "log 0.4.14", "slab", "string", "tokio-io", @@ -1642,10 +1676,10 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http 0.2.1", + "http 0.2.3", "indexmap", "slab", - "tokio 0.2.23", + "tokio 0.2.25", "tokio-util 0.3.1", "tracing", "tracing-futures", @@ -1668,18 +1702,18 @@ checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" [[package]] name = "heck" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac" dependencies = [ "unicode-segmentation", ] [[package]] name = "hermit-abi" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" dependencies = [ "libc", ] @@ -1720,11 +1754,11 @@ dependencies = [ [[package]] name = "http" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" +checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747" dependencies = [ - "bytes 0.5.6", + "bytes 1.0.1", "fnv", "itoa", ] @@ -1748,14 +1782,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" dependencies = [ "bytes 0.5.6", - "http 0.2.1", + "http 0.2.3", ] [[package]] name = "httparse" -version = "1.3.4" +version = "1.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" +checksum = "615caabe2c3160b313d52ccc905335f4ed5f10881dd63dc5699d47e90be85691" [[package]] name = "httpdate" @@ -1765,9 +1799,9 @@ checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" [[package]] name = "hyper" -version = "0.12.35" +version = "0.12.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" +checksum = "5c843caf6296fc1f93444735205af9ed4e109a539005abb2564ae1d6fad34c52" dependencies = [ "bytes 0.4.12", "futures 0.1.30", @@ -1778,7 +1812,7 @@ dependencies = [ "httparse", "iovec", "itoa", - "log 0.4.11", + "log 0.4.14", "net2", "rustc_version 0.2.3", "time", @@ -1795,24 +1829,24 @@ dependencies = [ [[package]] name = "hyper" -version = "0.13.9" +version = "0.13.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ad767baac13b44d4529fcf58ba2cd0995e36e7b435bc5b039de6f47e880dbf" +checksum = "8a6f157065790a3ed2f88679250419b5cdd96e714a0d65f7797fd337186e96bb" dependencies = [ "bytes 0.5.6", "futures-channel", "futures-core", "futures-util", "h2 0.2.7", - "http 0.2.1", + "http 0.2.3", "http-body 0.3.1", "httparse", "httpdate", "itoa", - "pin-project 1.0.1", + "pin-project 1.0.5", "socket2", - "tokio 0.2.23", - "tower-service 0.3.0", + "tokio 0.2.25", + "tower-service 0.3.1", "tracing", "want 0.3.0", ] @@ -1826,7 +1860,7 @@ dependencies = [ "bytes 0.4.12", "ct-logs", "futures 0.1.30", - "hyper 0.12.35", + "hyper 0.12.36", "rustls 0.16.0", "tokio-io", "tokio-rustls 0.10.3", @@ -1843,10 +1877,10 @@ dependencies = [ "bytes 0.5.6", "ct-logs", "futures-util", - "hyper 0.13.9", + "hyper 0.13.10", "rustls 0.16.0", "rustls-native-certs", - "tokio 0.2.23", + "tokio 0.2.25", "tokio-rustls 0.12.3", "webpki", ] @@ -1859,10 +1893,10 @@ checksum = "37743cc83e8ee85eacfce90f2f4102030d9ff0a95244098d781e9bee4a90abb6" dependencies = [ "bytes 0.5.6", "futures-util", - "hyper 0.13.9", - "log 0.4.11", + "hyper 0.13.10", + "log 0.4.14", "rustls 0.18.1", - "tokio 0.2.23", + "tokio 0.2.25", "tokio-rustls 0.14.1", "webpki", ] @@ -1892,9 +1926,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" +checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21" dependencies = [ "matches", "unicode-bidi", @@ -1903,9 +1937,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2" +checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" dependencies = [ "autocfg 1.0.1", "hashbrown 0.9.1", @@ -1913,9 +1947,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb1fc4429a33e1f80d41dc9fea4d108a88bec1de8053878898ae448a0b52f613" +checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" dependencies = [ "cfg-if 1.0.0", ] @@ -1962,15 +1996,15 @@ checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" [[package]] name = "itoa" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" +checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" [[package]] name = "js-sys" -version = "0.3.45" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8" +checksum = "5cfb73131c35423a367daf8cbd24100af0d077668c8c2943f0e7dd775fef0f65" dependencies = [ "wasm-bindgen", ] @@ -1991,7 +2025,7 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" dependencies = [ - "log 0.4.11", + "log 0.4.14", ] [[package]] @@ -2008,15 +2042,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.80" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614" +checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" [[package]] name = "linked-hash-map" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" +checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" [[package]] name = "linux-embedded-hal" @@ -2052,9 +2086,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c" +checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" dependencies = [ "scopeguard 1.1.0", ] @@ -2065,16 +2099,28 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" dependencies = [ - "log 0.4.11", + "log 0.4.14", ] [[package]] name = "log" -version = "0.4.11" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", + "value-bag", +] + +[[package]] +name = "loom" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d44c73b4636e497b4917eb21c33539efa3816741a2d3ff26c6316f1b529481a4" +dependencies = [ + "cfg-if 1.0.0", + "generator", + "scoped-tls", ] [[package]] @@ -2119,6 +2165,15 @@ dependencies = [ "autocfg 1.0.1", ] +[[package]] +name = "memoffset" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" +dependencies = [ + "autocfg 1.0.1", +] + [[package]] name = "mime" version = "0.2.6" @@ -2168,9 +2223,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.22" +version = "0.6.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" dependencies = [ "cfg-if 0.1.10", "fuchsia-zircon", @@ -2178,7 +2233,7 @@ dependencies = [ "iovec", "kernel32-sys", "libc", - "log 0.4.11", + "log 0.4.14", "miow", "net2", "slab", @@ -2198,9 +2253,9 @@ dependencies = [ [[package]] name = "miow" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" dependencies = [ "kernel32-sys", "net2", @@ -2225,7 +2280,7 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "136eed74cadb9edd2651ffba732b19a450316b680e4f48d6c79e905799e19d01" dependencies = [ - "log 0.4.11", + "log 0.4.14", "mime 0.2.6", "mime_guess 1.8.8", "rand 0.6.5", @@ -2249,19 +2304,19 @@ checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" [[package]] name = "nb-connect" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8123a81538e457d44b933a02faf885d3fe8408806b23fa700e8f01c6c3a98998" +checksum = "670361df1bc2399ee1ff50406a0d422587dd3bb0da596e1978fe8e05dabddf4f" dependencies = [ "libc", - "winapi 0.3.9", + "socket2", ] [[package]] name = "net2" -version = "0.2.35" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853" +checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" dependencies = [ "cfg-if 0.1.10", "libc", @@ -2459,15 +2514,15 @@ dependencies = [ [[package]] name = "object" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" +checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" [[package]] name = "once_cell" -version = "1.5.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" +checksum = "4ad167a2f54e832b82dbe003a046280dceffe5227b5f79e08e363a29638cfddd" [[package]] name = "openssl-probe" @@ -2477,9 +2532,9 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "ordered-float" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3741934be594d77de1c8461ebcbbe866f585ea616a9753aa78f2bdc69f0e4579" +checksum = "3305af35278dd29f46fcdd139e0b1fbfae2153f0e5928b39b035542dd31e37b7" dependencies = [ "num-traits", ] @@ -2510,7 +2565,7 @@ dependencies = [ "historian", "lazy_static", "libc", - "log 0.4.11", + "log 0.4.14", "rayon", "serde", ] @@ -2554,13 +2609,13 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733" +checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" dependencies = [ "instant", - "lock_api 0.4.1", - "parking_lot_core 0.8.0", + "lock_api 0.4.2", + "parking_lot_core 0.8.3", ] [[package]] @@ -2572,7 +2627,7 @@ dependencies = [ "libc", "rand 0.6.5", "rustc_version 0.2.3", - "smallvec 0.6.13", + "smallvec 0.6.14", "winapi 0.3.9", ] @@ -2583,11 +2638,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" dependencies = [ "cfg-if 0.1.10", - "cloudabi 0.0.3", + "cloudabi", "libc", - "redox_syscall", + "redox_syscall 0.1.57", "rustc_version 0.2.3", - "smallvec 0.6.13", + "smallvec 0.6.14", "winapi 0.3.9", ] @@ -2598,25 +2653,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" dependencies = [ "cfg-if 0.1.10", - "cloudabi 0.0.3", + "cloudabi", "libc", - "redox_syscall", - "smallvec 1.4.2", + "redox_syscall 0.1.57", + "smallvec 1.6.1", "winapi 0.3.9", ] [[package]] name = "parking_lot_core" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" +checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" dependencies = [ - "cfg-if 0.1.10", - "cloudabi 0.1.0", + "cfg-if 1.0.0", "instant", "libc", - "redox_syscall", - "smallvec 1.4.2", + "redox_syscall 0.2.5", + "smallvec 1.6.1", "winapi 0.3.9", ] @@ -2703,11 +2757,11 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.1" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee41d838744f60d959d7074e3afb6b35c7456d0f61cad38a24e35e6553f73841" +checksum = "96fa8ebb90271c4477f144354485b8068bd8f6b78b428b01ba892ca26caf0b63" dependencies = [ - "pin-project-internal 1.0.1", + "pin-project-internal 1.0.5", ] [[package]] @@ -2717,19 +2771,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", ] [[package]] name = "pin-project-internal" -version = "1.0.1" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a4ffa594b66bff340084d4081df649a7dc049ac8d7fc458d8e628bfbbb2f86" +checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", ] [[package]] @@ -2738,6 +2792,12 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b" +[[package]] +name = "pin-project-lite" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827" + [[package]] name = "pin-utils" version = "0.1.0" @@ -2752,7 +2812,7 @@ checksum = "a2a7bc6b2a29e632e45451c941832803a18cce6781db04de8a04696cdca8bde4" dependencies = [ "cfg-if 0.1.10", "libc", - "log 0.4.11", + "log 0.4.14", "wepoll-sys", "winapi 0.3.9", ] @@ -2771,8 +2831,8 @@ checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", "version_check 0.9.2", ] @@ -2783,7 +2843,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", + "quote 1.0.9", "version_check 0.9.2", ] @@ -2795,9 +2855,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro-nested" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a" +checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" @@ -2824,10 +2884,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bbaa49075179162b49acac1c6aa45fb4dafb5f13cf6794276d77bc7fd95757b" dependencies = [ "error-chain 0.12.4", - "idna 0.2.0", + "idna 0.2.2", "lazy_static", "regex", - "url 2.2.0", + "url 2.2.1", ] [[package]] @@ -2847,9 +2907,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ "proc-macro2 1.0.24", ] @@ -2860,7 +2920,7 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" dependencies = [ - "cloudabi 0.0.3", + "cloudabi", "fuchsia-cprng", "libc", "rand_core 0.3.1", @@ -2892,13 +2952,25 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom", + "getrandom 0.1.16", "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", "rand_hc 0.2.0", ] +[[package]] +name = "rand" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +dependencies = [ + "libc", + "rand_chacha 0.3.0", + "rand_core 0.6.2", + "rand_hc 0.3.0", +] + [[package]] name = "rand_chacha" version = "0.1.1" @@ -2919,6 +2991,16 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_chacha" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.2", +] + [[package]] name = "rand_core" version = "0.3.1" @@ -2940,7 +3022,16 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom", + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +dependencies = [ + "getrandom 0.2.2", ] [[package]] @@ -2961,6 +3052,15 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_hc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +dependencies = [ + "rand_core 0.6.2", +] + [[package]] name = "rand_isaac" version = "0.1.1" @@ -2987,7 +3087,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" dependencies = [ - "cloudabi 0.0.3", + "cloudabi", "fuchsia-cprng", "libc", "rand_core 0.4.2", @@ -3034,7 +3134,7 @@ checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" dependencies = [ "crossbeam-channel 0.5.0", "crossbeam-deque 0.8.0", - "crossbeam-utils 0.8.0", + "crossbeam-utils 0.8.2", "lazy_static", "num_cpus", ] @@ -3054,22 +3154,31 @@ version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +[[package]] +name = "redox_syscall" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" +dependencies = [ + "bitflags 1.2.1", +] + [[package]] name = "redox_users" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" dependencies = [ - "getrandom", - "redox_syscall", + "getrandom 0.1.16", + "redox_syscall 0.1.57", "rust-argon2", ] [[package]] name = "regex" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" +checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" dependencies = [ "aho-corasick", "memchr", @@ -3079,9 +3188,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.21" +version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" +checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" [[package]] name = "remove_dir_all" @@ -3106,9 +3215,9 @@ dependencies = [ "flate2", "futures 0.1.30", "http 0.1.21", - "hyper 0.12.35", + "hyper 0.12.36", "hyper-rustls 0.17.1", - "log 0.4.11", + "log 0.4.14", "mime 0.3.16", "mime_guess 2.0.3", "rustls 0.16.0", @@ -3130,37 +3239,37 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.10.8" +version = "0.10.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9eaa17ac5d7b838b7503d118fa16ad88f440498bf9ffe5424e621f93190d61e" +checksum = "0718f81a8e14c4dbb3b34cf23dc6aaf9ab8a0dfec160c534b3dbca1aaa21f47c" dependencies = [ - "base64 0.12.3", + "base64 0.13.0", "bytes 0.5.6", "encoding_rs", "futures-core", "futures-util", - "http 0.2.1", + "http 0.2.3", "http-body 0.3.1", - "hyper 0.13.9", + "hyper 0.13.10", "hyper-rustls 0.21.0", "ipnet", "js-sys", "lazy_static", - "log 0.4.11", + "log 0.4.14", "mime 0.3.16", "mime_guess 2.0.3", "percent-encoding 2.1.0", - "pin-project-lite", + "pin-project-lite 0.2.4", "rustls 0.18.1", "serde", - "serde_urlencoded 0.6.1", - "tokio 0.2.23", + "serde_urlencoded 0.7.0", + "tokio 0.2.25", "tokio-rustls 0.14.1", - "url 2.2.0", + "url 2.2.1", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.19.0", + "webpki-roots 0.20.0", "winreg 0.7.0", ] @@ -3176,18 +3285,18 @@ dependencies = [ [[package]] name = "retry" -version = "0.5.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ac83b31b3831aa4b07608db4170f6555ab12942197037c38570dc4c5ba5028" +checksum = "c15ef4789108d066d7fd85dcec330eab9b8e51244275922a9b7161afc4f46dda" dependencies = [ - "rand 0.6.5", + "rand 0.7.3", ] [[package]] name = "ring" -version = "0.16.15" +version = "0.16.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "952cd6b98c85bbc30efa1ba5783b8abf12fec8b3287ffa52605b9432313e34e4" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" dependencies = [ "cc", "libc", @@ -3200,14 +3309,14 @@ dependencies = [ [[package]] name = "rust-argon2" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dab61250775933275e84053ac235621dfb739556d5c54a2f2e9313b7cf43a19" +checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" dependencies = [ - "base64 0.12.3", + "base64 0.13.0", "blake2b_simd", "constant_time_eq", - "crossbeam-utils 0.7.2", + "crossbeam-utils 0.8.2", ] [[package]] @@ -3247,7 +3356,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" dependencies = [ "base64 0.10.1", - "log 0.4.11", + "log 0.4.14", "ring", "sct", "webpki", @@ -3260,7 +3369,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81" dependencies = [ "base64 0.12.3", - "log 0.4.11", + "log 0.4.14", "ring", "sct", "webpki", @@ -3278,6 +3387,12 @@ dependencies = [ "security-framework", ] +[[package]] +name = "rustversion" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd" + [[package]] name = "ryu" version = "1.0.5" @@ -3294,6 +3409,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + [[package]] name = "scopeguard" version = "0.3.3" @@ -3361,7 +3482,7 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "sensor_value" version = "0.1.0" -source = "git+https://github.com/dskleingeld/sensor_central.git?branch=boolean-fields#1768323c876411071d6db297c34986eaf0aaaccf" +source = "git+https://github.com/dskleingeld/sensor_central.git?branch=boolean-fields#ad5d48c43c827f421f573bf57e216a3f4440a0c9" dependencies = [ "bitspec", "serde", @@ -3369,9 +3490,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.117" +version = "1.0.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a" +checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae" dependencies = [ "serde_derive", ] @@ -3388,20 +3509,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.117" +version = "1.0.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e" +checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", ] [[package]] name = "serde_json" -version = "1.0.59" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95" +checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486" dependencies = [ "itoa", "ryu", @@ -3429,14 +3550,26 @@ dependencies = [ "dtoa", "itoa", "serde", - "url 2.2.0", + "url 2.2.1", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", ] [[package]] name = "serde_yaml" -version = "0.8.14" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7baae0a99f1a324984bcdc5f0718384c1f69775f1c7eec8b859b71b443e3fd7" +checksum = "15654ed4ab61726bf918a39cb8d98a2e2995b002387807fa6ba58fdf7f59bb23" dependencies = [ "dtoa", "linked-hash-map", @@ -3493,24 +3626,24 @@ dependencies = [ "fs2", "fxhash", "libc", - "log 0.4.11", + "log 0.4.14", "parking_lot 0.10.2", ] [[package]] name = "smallvec" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" +checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" dependencies = [ "maybe-uninit", ] [[package]] name = "smallvec" -version = "1.4.2" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252" +checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "smol" @@ -3532,13 +3665,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.3.16" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd8b795c389288baa5f355489c65e71fd48a02104600d15c4cfbc561e9e429d" +checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", - "redox_syscall", "winapi 0.3.9", ] @@ -3582,9 +3714,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.20" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126d630294ec449fae0b16f964e35bf3c74f940da9dca17ee9b905f7b3112eb8" +checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c" dependencies = [ "clap", "lazy_static", @@ -3593,15 +3725,15 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e51c492f9e23a220534971ff5afc14037289de430e3c83f9daf6a1b6ae91e8" +checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90" dependencies = [ "heck", "proc-macro-error", "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", ] [[package]] @@ -3617,12 +3749,12 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.48" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac" +checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", + "quote 1.0.9", "unicode-xid 0.2.1", ] @@ -3633,8 +3765,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", "unicode-xid 0.2.1", ] @@ -3654,12 +3786,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb29fb11ef40c839c1c6b4e9c2ec4f357f9f674491e9df5a8c94f8cc2005f860" dependencies = [ "bytes 0.5.6", - "futures 0.3.8", - "hyper 0.13.9", + "futures 0.3.12", + "hyper 0.13.10", "hyper-rustls 0.19.1", "multipart", "telegram-bot-raw", - "tokio 0.2.23", + "tokio 0.2.25", "tracing", "tracing-futures", ] @@ -3679,14 +3811,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", - "rand 0.7.3", - "redox_syscall", + "rand 0.8.3", + "redox_syscall 0.2.5", "remove_dir_all", "winapi 0.3.9", ] @@ -3722,17 +3854,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", ] [[package]] name = "thread_local" -version = "1.0.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" dependencies = [ - "lazy_static", + "once_cell", ] [[package]] @@ -3757,9 +3889,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.0.1" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b78a366903f506d2ad52ca8dc552102ffdd3e937ba8a227f024dc1d1eae28575" +checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023" dependencies = [ "tinyvec_macros", ] @@ -3796,9 +3928,9 @@ dependencies = [ [[package]] name = "tokio" -version = "0.2.23" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6d7ad61edd59bfcc7e80dababf0f4aed2e6d5e0ba1659356ae889752dfc12ff" +checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092" dependencies = [ "bytes 0.5.6", "fnv", @@ -3809,7 +3941,7 @@ dependencies = [ "memchr", "mio", "mio-uds", - "pin-project-lite", + "pin-project-lite 0.1.11", "signal-hook-registry", "slab", "winapi 0.3.9", @@ -3876,7 +4008,7 @@ checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" dependencies = [ "bytes 0.4.12", "futures 0.1.30", - "log 0.4.11", + "log 0.4.14", ] [[package]] @@ -3888,7 +4020,7 @@ dependencies = [ "crossbeam-utils 0.7.2", "futures 0.1.30", "lazy_static", - "log 0.4.11", + "log 0.4.14", "mio", "num_cpus", "parking_lot 0.9.0", @@ -3920,7 +4052,7 @@ checksum = "3068d891551949b37681724d6b73666787cc63fa8e255c812a41d2513aff9775" dependencies = [ "futures-core", "rustls 0.16.0", - "tokio 0.2.23", + "tokio 0.2.25", "webpki", ] @@ -3932,7 +4064,7 @@ checksum = "e12831b255bcfa39dc0436b01e19fea231a37db570686c06ee72c423479f889a" dependencies = [ "futures-core", "rustls 0.18.1", - "tokio 0.2.23", + "tokio 0.2.25", "webpki", ] @@ -3988,7 +4120,7 @@ dependencies = [ "crossbeam-utils 0.7.2", "futures 0.1.30", "lazy_static", - "log 0.4.11", + "log 0.4.14", "num_cpus", "slab", "tokio-executor", @@ -4014,7 +4146,7 @@ checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" dependencies = [ "bytes 0.4.12", "futures 0.1.30", - "log 0.4.11", + "log 0.4.14", "mio", "tokio-codec", "tokio-io", @@ -4031,7 +4163,7 @@ dependencies = [ "futures 0.1.30", "iovec", "libc", - "log 0.4.11", + "log 0.4.14", "mio", "mio-uds", "tokio-codec", @@ -4048,9 +4180,9 @@ dependencies = [ "bytes 0.5.6", "futures-core", "futures-sink", - "log 0.4.11", - "pin-project-lite", - "tokio 0.2.23", + "log 0.4.14", + "pin-project-lite 0.1.11", + "tokio 0.2.25", ] [[package]] @@ -4062,9 +4194,9 @@ dependencies = [ "bytes 0.5.6", "futures-core", "futures-sink", - "log 0.4.11", - "pin-project-lite", - "tokio 0.2.23", + "log 0.4.14", + "pin-project-lite 0.1.11", + "tokio 0.2.25", ] [[package]] @@ -4078,32 +4210,32 @@ dependencies = [ [[package]] name = "tower-service" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.21" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0987850db3733619253fe60e17cb59b82d37c7e6c0236bb81e4d6b87c879f27" +checksum = "f77d3842f76ca899ff2dbcf231c5c65813dea431301d6eb686279c15c4464f12" dependencies = [ - "cfg-if 0.1.10", - "log 0.4.11", - "pin-project-lite", + "cfg-if 1.0.0", + "log 0.4.14", + "pin-project-lite 0.2.4", "tracing-attributes", "tracing-core", ] [[package]] name = "tracing-attributes" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada" +checksum = "a8a9bd1db7706f2373a190b0d067146caa39350c486f3d455b0e33b431f94c07" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", ] [[package]] @@ -4117,11 +4249,11 @@ dependencies = [ [[package]] name = "tracing-futures" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ - "pin-project 0.4.27", + "pin-project 1.0.5", "tracing", ] @@ -4136,9 +4268,9 @@ dependencies = [ "futures 0.1.30", "idna 0.1.5", "lazy_static", - "log 0.4.11", + "log 0.4.14", "rand 0.5.6", - "smallvec 0.6.13", + "smallvec 0.6.14", "socket2", "tokio-executor", "tokio-io", @@ -4160,9 +4292,9 @@ dependencies = [ "futures 0.1.30", "idna 0.1.5", "lazy_static", - "log 0.4.11", + "log 0.4.14", "rand 0.5.6", - "smallvec 0.6.13", + "smallvec 0.6.14", "socket2", "tokio-executor", "tokio-io", @@ -4182,15 +4314,15 @@ dependencies = [ "async-trait", "enum-as-inner", "failure", - "futures 0.3.8", - "idna 0.2.0", + "futures 0.3.12", + "idna 0.2.2", "lazy_static", - "log 0.4.11", + "log 0.4.14", "rand 0.7.3", - "smallvec 1.4.2", + "smallvec 1.6.1", "socket2", - "tokio 0.2.23", - "url 2.2.0", + "tokio 0.2.25", + "url 2.2.1", ] [[package]] @@ -4204,10 +4336,10 @@ dependencies = [ "futures 0.1.30", "ipconfig 0.1.9", "lazy_static", - "log 0.4.11", + "log 0.4.14", "lru-cache", "resolv-conf", - "smallvec 0.6.13", + "smallvec 0.6.14", "tokio 0.1.22", "trust-dns-proto 0.6.3", ] @@ -4220,14 +4352,14 @@ checksum = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f" dependencies = [ "cfg-if 0.1.10", "failure", - "futures 0.3.8", + "futures 0.3.12", "ipconfig 0.2.2", "lazy_static", - "log 0.4.11", + "log 0.4.14", "lru-cache", "resolv-conf", - "smallvec 1.4.2", - "tokio 0.2.23", + "smallvec 1.6.1", + "tokio 0.2.25", "trust-dns-proto 0.18.0-alpha.2", ] @@ -4275,18 +4407,18 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.14" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f98e67a4d84f730d343392f9bfff7d21e3fca562b9cb7a43b768350beeddc6" +checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" +checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" [[package]] name = "unicode-width" @@ -4325,12 +4457,12 @@ dependencies = [ [[package]] name = "url" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e" +checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b" dependencies = [ "form_urlencoded", - "idna 0.2.0", + "idna 0.2.2", "matches", "percent-encoding 2.1.0", ] @@ -4361,8 +4493,8 @@ checksum = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae" dependencies = [ "nom", "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", ] [[package]] @@ -4375,6 +4507,15 @@ dependencies = [ "v_escape", ] +[[package]] +name = "value-bag" +version = "1.0.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b676010e055c99033117c2343b33a40a30b91fecd6c49055ac9cd2d6c305ab1" +dependencies = [ + "ctor", +] + [[package]] name = "vec-arena" version = "1.0.0" @@ -4418,7 +4559,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" dependencies = [ "futures 0.1.30", - "log 0.4.11", + "log 0.4.14", "try-lock", ] @@ -4428,7 +4569,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" dependencies = [ - "log 0.4.11", + "log 0.4.14", "try-lock", ] @@ -4446,11 +4587,11 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" -version = "0.2.68" +version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" +checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "serde", "serde_json", "wasm-bindgen-macro", @@ -4458,26 +4599,26 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.68" +version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68" +checksum = "7bc45447f0d4573f3d65720f636bbcc3dd6ce920ed704670118650bcd47764c7" dependencies = [ "bumpalo", "lazy_static", - "log 0.4.11", + "log 0.4.14", "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.18" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da" +checksum = "3de431a2910c86679c34283a33f66f4e4abd7e0aec27b6669060148872aadf94" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -4485,38 +4626,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.68" +version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" +checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c" dependencies = [ - "quote 1.0.7", + "quote 1.0.9", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.68" +version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" +checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.48", + "quote 1.0.9", + "syn 1.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.68" +version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" +checksum = "dd4945e4943ae02d15c13962b38a5b1e81eadd4b71214eee75af64a4d6a4fd64" [[package]] name = "web-sys" -version = "0.3.45" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d" +checksum = "c40dc691fc48003eba817c38da7113c15698142da971298003cac3ef175680b3" dependencies = [ "js-sys", "wasm-bindgen", @@ -4524,9 +4665,9 @@ dependencies = [ [[package]] name = "webpki" -version = "0.21.3" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab146130f5f790d45f82aeeb09e55a256573373ec64409fc19a6fb82fb1032ae" +checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" dependencies = [ "ring", "untrusted", @@ -4543,9 +4684,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8eff4b7516a57307f9349c64bf34caa34b940b66fed4b2fb3136cb7386e5739" +checksum = "0f20dea7535251981a9670857150d571846545088359b28e4951d350bdaf179f" dependencies = [ "webpki", ] @@ -4644,9 +4785,9 @@ dependencies = [ [[package]] name = "yaml-rust" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] diff --git a/Cargo.toml b/Cargo.toml index 7a8b4763..95b7385c 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,7 +68,7 @@ reqwest = {version = "0.10", default-features = false, features = ["rustls-tls"] mpd = "0.0.12" dirs = "2" rand = "0.6" -retry = "0.5" +retry = "1" telegram-bot = {version = "0.7", default-features = false, features = ["rustls"]} serde_json = "1.0" diff --git a/src/controller/mod.rs b/src/controller/mod.rs index 47d3b284..6e07b22a 100755 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -19,7 +19,7 @@ use crate::input::jobs::WakeUp; use crate::input::mpd_status::MpdStatus; pub use commands::Command; use sensor_value::{Button, Press, SensorValue}; -pub use state::State; +pub use state::{State, WakeUpStateError}; #[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub enum Event { diff --git a/src/controller/state/mod.rs b/src/controller/state/mod.rs index 9cdbcd4d..f7819f28 100755 --- a/src/controller/state/mod.rs +++ b/src/controller/state/mod.rs @@ -16,7 +16,7 @@ pub use off::Off; pub use quiet::Quiet; pub use silent::Silent; pub use sleep::Sleep; -pub use wakeup::WakeUp; +pub use wakeup::{WakeUp, WakeUpStateError}; #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub enum State { diff --git a/src/controller/state/wakeup.rs b/src/controller/state/wakeup.rs index 282fb150..837a218e 100755 --- a/src/controller/state/wakeup.rs +++ b/src/controller/state/wakeup.rs @@ -1,9 +1,9 @@ use super::super::{Environment, Modifications, System}; use super::{RoomState, State}; use crate::controller::system; -use crate::errors::Error; use retry::{delay::Fixed, retry}; +use crate::errors::Error; use std::time::{Duration, Instant}; const UPDATE_PERIOD: u64 = 5; @@ -19,6 +19,13 @@ const MAX_VOLUME: i8 = 40; const MIN_VOLUME: i8 = 10; const VOL_PER_SECOND: f32 = (MAX_VOLUME - MIN_VOLUME) as f32 / (WAKEUP_DURATION - MUSIC_ON) as f32; +#[derive(thiserror::Error, Debug)] +pub enum WakeUpStateError { + #[error("could not setup playlist even after retries: {0}")] + SetupPlaylist(retry::Error), + +} + #[derive(Clone, Copy)] pub struct WakeUp { start: Instant, @@ -29,12 +36,12 @@ impl WakeUp { fn setup_playlist() -> Result<(), Error> { let mpd = &mut retry(Fixed::from_millis(100), || { mpd::Client::connect("127.0.0.1:6600") - }).unwrap();//?; - dbg!(); + }).map_err(WakeUpStateError::SetupPlaylist)?; + retry(Fixed::from_millis(100).take(3), || { system::mpd_control::save_current_playlist(mpd) - }).unwrap();//?; - dbg!(); + }).map_err(WakeUpStateError::SetupPlaylist)?; + retry(Fixed::from_millis(100).take(3), || { system::mpd_control::add_from_playlist( mpd, @@ -42,8 +49,8 @@ impl WakeUp { chrono::Duration::seconds(3 * 60), chrono::Duration::seconds(5 * 60), ) - }).unwrap();//?; - dbg!(); + }).map_err(WakeUpStateError::SetupPlaylist)?; + retry(Fixed::from_millis(100).take(3), || { system::mpd_control::add_from_playlist( mpd, @@ -51,7 +58,8 @@ impl WakeUp { chrono::Duration::seconds(10 * 60), chrono::Duration::seconds(11 * 60), ) - }).unwrap();//?; + }).map_err(WakeUpStateError::SetupPlaylist)?; + retry(Fixed::from_millis(100).take(3), || { system::mpd_control::add_from_playlist( mpd, @@ -59,7 +67,7 @@ impl WakeUp { chrono::Duration::seconds(30 * 60), chrono::Duration::seconds(60 * 60), ) - }).unwrap();//?; + }).map_err(WakeUpStateError::SetupPlaylist)?; Ok(()) } } @@ -97,29 +105,27 @@ impl RoomState for WakeUp { return Ok(Some(State::Normal)); } + // do nothing to the lighting if the user changed it if !mods.lighting { - // if lighting controls have not been modified externally since start if sys.lights.numb_on() < 3 { sys.lights.all_on()?; } let bri = (BRI_PER_SECOND * (elapsed as f32)) as u8; let ct = CT_BEGIN - (CT_PER_SECOND * (elapsed as f32)) as u16; - sys.lights.set_all_ct(bri, ct)?; //TODO map to terror error + sys.lights.set_all_ct(dbg!(bri), ct)?; } + // do nothing to mpd if the user changed an mpd setting if !mods.mpd { - // if mpd controls have not been modified externally since start - if !self.playing { - if elapsed > MUSIC_ON { - mpd::Client::connect("127.0.0.1:6600") - .and_then(|ref mut c| c.volume(MIN_VOLUME).and_then(|_| c.play())); - //only play if the volume was set correctly - } - } else { - mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| { - c.volume((VOL_PER_SECOND * (elapsed - MUSIC_ON) as f32) as i8) - }); + if !self.playing && elapsed > MUSIC_ON { + let mut client = mpd::Client::connect("127.0.0.1:6600")?; + client.volume(dbg!(MIN_VOLUME))?; + client.play()?; + } else if elapsed > MUSIC_ON { + let since_music_on = elapsed.saturating_sub(MUSIC_ON); + let mut client = mpd::Client::connect("127.0.0.1:6600")?; + client.volume(dbg!(dbg!(VOL_PER_SECOND) * dbg!(since_music_on) as f32) as i8)?; } } diff --git a/src/controller/system/mpd_control.rs b/src/controller/system/mpd_control.rs index fd200b42..4d0e3a75 100755 --- a/src/controller/system/mpd_control.rs +++ b/src/controller/system/mpd_control.rs @@ -9,7 +9,7 @@ pub fn add_from_playlist( name: &str, minimal_play_time: Duration, maximal_play_time: Duration, -) -> Result<(), Error> { +) -> Result<(), mpd::error::Error> { let mut rng = rand::thread_rng(); let songs = mpd.playlist(name); @@ -104,11 +104,8 @@ pub fn pause() -> Result<(), Error> { Ok(()) } -pub fn save_current_playlist(mpd: &mut mpd::Client) -> Result<(), Error> { - dbg!(); +pub fn save_current_playlist(mpd: &mut mpd::Client) -> Result<(), mpd::error::Error> { mpd.pl_remove("temp")?; - dbg!(); mpd.save("temp")?; - dbg!(); Ok(()) } diff --git a/src/errors.rs b/src/errors.rs index f3826fc0..b3961558 100755 --- a/src/errors.rs +++ b/src/errors.rs @@ -25,8 +25,10 @@ pub enum Error { YoutubeDownloader(youtube_downloader::Error), #[error("Problem handeling web requests")] WebServerError(server::Error), - #[error("Wakeup system")] - WakeUp(#[from] crate::input::jobs::wakeup::Error), + #[error("Error in the wakeup alarm system")] + SetWakeUp(#[from] crate::input::jobs::wakeup::Error), + #[error("Error in wakeup state")] + WakeUpState(#[from] crate::controller::WakeUpStateError), #[error("untracked error")] UnTracked, } From 3495592ad8166b076c0d237c54395e2cb048d5c3 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Tue, 23 Feb 2021 12:14:38 +0100 Subject: [PATCH 066/687] fixed winter/summer time issue in alarm time --- src/controller/state/wakeup.rs | 7 +++---- src/input/jobs/wakeup.rs | 17 ++++++++++------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/controller/state/wakeup.rs b/src/controller/state/wakeup.rs index 837a218e..5ab50c75 100755 --- a/src/controller/state/wakeup.rs +++ b/src/controller/state/wakeup.rs @@ -42,6 +42,8 @@ impl WakeUp { system::mpd_control::save_current_playlist(mpd) }).map_err(WakeUpStateError::SetupPlaylist)?; + // note if playlist does not exist we do not + // report an error retry(Fixed::from_millis(100).take(3), || { system::mpd_control::add_from_playlist( mpd, @@ -84,6 +86,7 @@ impl WakeUp { Self::setup_playlist()?; sys.lights.set_all_ct(0, CT_BEGIN)?; + sys.lights.all_on()?; Ok(Box::new(Self { start: Instant::now(), @@ -107,10 +110,6 @@ impl RoomState for WakeUp { // do nothing to the lighting if the user changed it if !mods.lighting { - if sys.lights.numb_on() < 3 { - sys.lights.all_on()?; - } - let bri = (BRI_PER_SECOND * (elapsed as f32)) as u8; let ct = CT_BEGIN - (CT_PER_SECOND * (elapsed as f32)) as u16; sys.lights.set_all_ct(dbg!(bri), ct)?; diff --git a/src/input/jobs/wakeup.rs b/src/input/jobs/wakeup.rs index 4756caaa..499de586 100644 --- a/src/input/jobs/wakeup.rs +++ b/src/input/jobs/wakeup.rs @@ -55,11 +55,13 @@ impl Inner { let job_id = db .get("job_id")? .map(|b| bincode::deserialize(&b).unwrap()); - let tomorrow = job_id.as_ref() + let next_alarm = job_id.as_ref() .map(|id| jobs.get(*id).ok()) .flatten().flatten() .map(|job| job.time.into()) - .map(|t: DateTime| (t.hour() as u8, t.minute() as u8)) + .map(|t: DateTime| t) + .map(|t| (t.hour() as u8, t.minute() as u8)); + let tomorrow = next_alarm .filter(|tomorrow| Some(*tomorrow) != usually); Ok(Self { @@ -71,6 +73,7 @@ impl Inner { }) } + /// stores a new job fn save_job_id(&mut self, id: u64) -> Result<(), Error> { self.job_id = Some(id); let bytes = bincode::serialize(&id).unwrap(); @@ -146,14 +149,14 @@ fn job_from(hour: u8, min: u8) -> Job { fn to_datetime(hour: u8, min: u8) -> DateTime { let (hour, min) = (hour as u32, min as u32); let now = Local::now(); - let alarm = now - .with_hour(hour).unwrap() - .with_minute(min).unwrap(); + let today = now.date(); + let alarm = today.and_hms(hour,min, 0); if alarm < now { let tomorrow = now.date().succ(); - tomorrow.and_hms(hour, min, 0).into() + tomorrow.and_hms(hour, min, 0) + .with_timezone(&Utc) } else { - alarm.into() + alarm.with_timezone(&Utc) } } From c380130aaf0e1d666a3444749aa2ae5f99756176 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Tue, 9 Mar 2021 21:48:39 +0100 Subject: [PATCH 067/687] removes alarm from web api, finishes port from bot alarm to wakeupsystem --- src/controller/state/wakeup.rs | 14 ++-- src/input/bot/mod.rs | 2 +- src/input/bot/set_alarm.rs | 132 ++++++++++++++++---------------- src/input/jobs.rs | 7 +- src/input/jobs/wakeup.rs | 44 ++++++++--- src/input/web_api/alarms.rs | 88 --------------------- src/input/web_api/mod.rs | 1 - src/input/web_api/server/mod.rs | 4 +- src/input/web_api/wakeup.rs | 2 +- 9 files changed, 112 insertions(+), 182 deletions(-) delete mode 100644 src/input/web_api/alarms.rs diff --git a/src/controller/state/wakeup.rs b/src/controller/state/wakeup.rs index 5ab50c75..11bbea3a 100755 --- a/src/controller/state/wakeup.rs +++ b/src/controller/state/wakeup.rs @@ -15,9 +15,9 @@ const CT_PER_SECOND: f32 = ((CT_BEGIN - CT_END) as f32) / (WAKEUP_DURATION as f3 const BRI_PER_SECOND: f32 = 254. / (WAKEUP_DURATION as f32); //in seconds const MUSIC_ON: u64 = 60 * 5; -const MAX_VOLUME: i8 = 40; -const MIN_VOLUME: i8 = 10; -const VOL_PER_SECOND: f32 = (MAX_VOLUME - MIN_VOLUME) as f32 / (WAKEUP_DURATION - MUSIC_ON) as f32; +const MAX_VOLUME: f32 = 20.; +const MIN_VOLUME: f32 = 3.; +const VOL_PER_SECOND: f32 = (MAX_VOLUME - MIN_VOLUME) / (WAKEUP_DURATION - MUSIC_ON) as f32; #[derive(thiserror::Error, Debug)] pub enum WakeUpStateError { @@ -76,7 +76,7 @@ impl WakeUp { impl WakeUp { pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { - dbg!("starting wakeup state"); + log::info!("starting wakeup state"); sys.update_period = Duration::from_secs(UPDATE_PERIOD); sys.next_update = Instant::now() + sys.update_period; @@ -119,12 +119,14 @@ impl RoomState for WakeUp { if !mods.mpd { if !self.playing && elapsed > MUSIC_ON { let mut client = mpd::Client::connect("127.0.0.1:6600")?; - client.volume(dbg!(MIN_VOLUME))?; + client.volume(dbg!(MIN_VOLUME) as i8)?; client.play()?; + self.playing = true; } else if elapsed > MUSIC_ON { let since_music_on = elapsed.saturating_sub(MUSIC_ON); let mut client = mpd::Client::connect("127.0.0.1:6600")?; - client.volume(dbg!(dbg!(VOL_PER_SECOND) * dbg!(since_music_on) as f32) as i8)?; + let volume = MIN_VOLUME + VOL_PER_SECOND * (since_music_on as f32); + client.volume(volume as i8)?; } } diff --git a/src/input/bot/mod.rs b/src/input/bot/mod.rs index d79e0617..e79c9940 100644 --- a/src/input/bot/mod.rs +++ b/src/input/bot/mod.rs @@ -92,7 +92,7 @@ async fn handle_command( "/test" => { send_text(chat_id, token, "hi").await?; } - "/alarm" => { + "/wakeup" => { set_alarm::handle(chat_id, token, split, state).await?; } &_ => { diff --git a/src/input/bot/set_alarm.rs b/src/input/bot/set_alarm.rs index 511a74d4..8d35046f 100644 --- a/src/input/bot/set_alarm.rs +++ b/src/input/bot/set_alarm.rs @@ -5,14 +5,12 @@ use telegram_bot::types::refs::ChatId; #[derive(Debug)] pub enum Error { - NoArguments, InvalidOption, CouldNotRespond, NoTimeArgument, InvalidHourArgument, InvalidMinuteArgument, WrongTimeFormat, - NoAlarmId, BackendError, } @@ -22,62 +20,88 @@ pub async fn handle<'a>( mut args: std::str::SplitWhitespace<'a>, state: &State, ) -> Result<(), Error> { - let command = args.next().ok_or(Error::NoArguments)?; - dbg!(command); + let command = args.next(); match command { - "list" => list_alarm(chat_id, token, state).await?, - "tomorrow" => add_tomorrow(chat_id, token, args, state).await?, - "usually" => add_usually(chat_id, token, args, state).await?, - "remove" => remove_alarm(chat_id, token, args, state).await?, - &_ => Err(Error::InvalidOption)?, + None => print_current(chat_id, token, state).await?, + Some("tomorrow") => add_tomorrow(chat_id, token, args, state).await?, + Some("usually") => add_usually(chat_id, token, args, state).await?, + Some("help") => help(chat_id, token).await?, + _ => Err(Error::InvalidOption)?, } Ok(()) } -pub async fn add_tomorrow<'a>( +async fn help( + chat_id: ChatId, + token: &str, +) -> Result<(), Error> { + + let text = String::from("Check, Set and remove alarms + * use 'tomorrow' followed by a time to set the alarm only for tomorrow + * use 'usually' followed by a time to set the alarm for all other days + * format a time as hh:mm or - to unset + * without any arguments this displays the tomorrow and usually times"); + + send_text(chat_id, token, text) + .await + .map_err(|_| Error::CouldNotRespond)?; + Ok(()) +} + +async fn add_tomorrow<'a>( chat_id: ChatId, token: &str, args: std::str::SplitWhitespace<'a>, state: &State, ) -> Result<(), Error> { - let (hour, min, text) = parse_args(chat_id, token, args, state)?; + let Parsed { time, status } = parse_args(chat_id, token, args, state)?; - let time = Some((hour as u8, min as u8)); state.wakeup.set_tomorrow(time).await.map_err(|_| Error::BackendError)?; - send_text(chat_id, token, text) + send_text(chat_id, token, status) .await .map_err(|_| Error::CouldNotRespond)?; Ok(()) } -pub async fn add_usually<'a>( +async fn add_usually<'a>( chat_id: ChatId, token: &str, args: std::str::SplitWhitespace<'a>, state: &State, ) -> Result<(), Error> { - let (hour, min, text) = parse_args(chat_id, token, args, state)?; + let Parsed { time, status } = parse_args(chat_id, token, args, state)?; - let time = Some((hour as u8, min as u8)); state.wakeup.set_usually(time).await.map_err(|_| Error::BackendError)?; - send_text(chat_id, token, text) + send_text(chat_id, token, status) .await .map_err(|_| Error::CouldNotRespond)?; Ok(()) } +struct Parsed { + time: Option<(u8,u8)>, + status: String, +} + fn parse_args<'a>( _: ChatId, _: &str, mut args: std::str::SplitWhitespace<'a>, _: &State, -) -> Result<(u8, u8, String), Error> { +) -> Result { let time = args.next().ok_or(Error::NoTimeArgument)?; + if time == "-" { + return Ok(Parsed { + time: None, + status: String::from("Alarm unset"), + }) + } + //assumes hh:mm let mut time = time.split(':'); let hour = time @@ -110,65 +134,37 @@ fn parse_args<'a>( let till_alarm = alarm-now; - let text = format!( + let status = format!( "set alarm for over {} hours and {} minutes from now", till_alarm.num_hours(), till_alarm.num_minutes() % 60 ); - Ok((hour as u8, min as u8, text)) -} - -pub async fn list_alarm(chat_id: ChatId, token: &str, state: &State) -> Result<(), Error> { - let alarms = state.jobs.list(); - let mut list = String::with_capacity(alarms.len() * 100); - - for (id, alarm) in alarms.into_iter() { - list.push_str(&format!( - "{:x}, {}, {:?}, {:?}", - id, - &alarm.time.with_timezone(&Local).to_rfc2822(), - &alarm.action, - &alarm.expiration, - )); - list.push_str("\n"); - } - if list.is_empty() { - list.push_str("no alarms set"); - } - - send_text(chat_id, token, list) - .await //.unwrap(); - .map_err(|_| Error::CouldNotRespond)?; - Ok(()) + Ok(Parsed { + time: Some((hour as u8, min as u8)), + status}) } -pub async fn remove_alarm<'a>( - chat_id: ChatId, - token: &str, - mut args: std::str::SplitWhitespace<'a>, - state: &State, -) -> Result<(), Error> { - let to_remove = dbg!(args.next()).ok_or(Error::NoAlarmId)?; - let to_remove = u64::from_str_radix(to_remove, 16).unwrap(); - - let removed = state.jobs.remove_alarm(to_remove).unwrap(); //TODO //FIXME - //.map_err(|_| Error::CouldNotRemove)?; - - let text = if let Some(alarm) = removed { - format!( - "removed alarm {:x}: {}, {:?}, {:?}", - to_remove, - &alarm.time.with_timezone(&Local).to_rfc2822(), - &alarm.action, - &alarm.expiration, - ) - } else { - String::from("Alarm does not exist, no alarm removed") +pub async fn print_current(chat_id: ChatId, token: &str, state: &State) -> Result<(), Error> { + let tomorrow = state.wakeup.tomorrow(); + let usually = state.wakeup.usually(); + + let msg = match (tomorrow, usually) { + (Some(tomorrow), Some(usually)) => + format!("alarm tomorrow: {:02}:{:02}\nusually: {:02}:{:02}", + tomorrow.0, tomorrow.1, + usually.0, usually.1), + (Some(tomorrow), None) => + format!("alarm tomorrow: {:02}:{:02}, usually no alarm", + tomorrow.0, tomorrow.1), + (None, Some(usually)) => + format!("alarm tomorrow as usual: {:02}:{:02}", + usually.0, usually.1), + (None, None) => String::from("No alarm set"), }; - send_text(chat_id, token, text) - .await //.unwrap(); + send_text(chat_id, token, msg) + .await .map_err(|_| Error::CouldNotRespond)?; Ok(()) } diff --git a/src/input/jobs.rs b/src/input/jobs.rs index d3072679..d7171d03 100644 --- a/src/input/jobs.rs +++ b/src/input/jobs.rs @@ -221,11 +221,14 @@ impl JobList { self.db.flush_async().await?; Ok(timestamp) } + pub fn remove_alarm(&self, to_remove: u64) -> Result, Error> { - Ok(self + let old_alarm = self .db .remove(to_remove.to_be_bytes())? - .map(|k| bincode::deserialize::(&k).unwrap())) + .map(|k| bincode::deserialize::(&k).unwrap()); + self.db.flush()?; + Ok(old_alarm) } /// calculate time to the earliest alarm, remove it from the list if the current time is later diff --git a/src/input/jobs/wakeup.rs b/src/input/jobs/wakeup.rs index 499de586..4c317510 100644 --- a/src/input/jobs/wakeup.rs +++ b/src/input/jobs/wakeup.rs @@ -4,6 +4,11 @@ use std::time::Duration; use std::sync::{Arc, Mutex}; use chrono::{Utc, Local, DateTime, Timelike}; +// TODO FIXME multiple things left to do: +// - usually and tomorrow are not written to db +// - setting usually none goes wrong if tomorrow is not none +// - recheck set tomorrow and set usually carefull + #[derive(Debug, thiserror::Error)] pub enum Error { #[error("Error modifying wakeup alarms: {0}")] @@ -27,13 +32,19 @@ impl WakeUp { self.0.lock().unwrap().usually } pub fn reset(&self) -> Result<(), Error> { - self.0.lock().unwrap().reset() + self.0.lock().unwrap().reset()?; + log::info!("alarm system reset correctly"); + Ok(()) } pub async fn set_tomorrow(&self, time: Time) -> Result<(), Error> { - self.0.lock().unwrap().set_tomorrow(time).await + self.0.lock().unwrap().set_tomorrow(time).await?; + log::info!("alarm tomorrow set to: time"); + Ok(()) } pub async fn set_usually(&self, time: Time) -> Result<(), Error> { - self.0.lock().unwrap().set_usually(time).await + self.0.lock().unwrap().set_usually(time).await?; + log::info!("alarm usually set to: time"); + Ok(()) } } @@ -84,7 +95,13 @@ impl Inner { Ok(()) } - async fn replace_current(&mut self, job: Job) -> Result<(),Error> { + fn save_usually(&mut self, usually: &Time) -> Result<(), Error> { + let bytes = bincode::serialize(dbg!(usually)).unwrap(); + self.db.insert("usually", bytes)?; + Ok(()) + } + + async fn replace_job(&mut self, job: Job) -> Result<(),Error> { let id = self.jobs .add_alarm(job) .await?; @@ -92,7 +109,7 @@ impl Inner { Ok(()) } - async fn remove_current(&mut self) -> Result<(), Error> { + fn remove_job(&mut self) -> Result<(), Error> { self.jobs.remove_alarm(self.job_id.unwrap())?; self.job_id = None; Ok(()) @@ -103,11 +120,8 @@ impl Inner { pub fn reset(&mut self) -> Result<(),Error> { if let Some((hour,min)) = self.usually { let job = job_from(hour, min); - let add = self.replace_current(job); + let add = self.replace_job(job); smol::block_on(add)?; - } else { - let remove = self.remove_current(); - smol::block_on(remove)?; } self.tomorrow = None; Ok(()) @@ -118,7 +132,7 @@ impl Inner { None => self.reset()?, Some((hour, min)) => { let job = job_from(hour, min); - self.replace_current(job).await?; + self.replace_job(job).await?; } } self.tomorrow = time; @@ -127,10 +141,16 @@ impl Inner { pub async fn set_usually(&mut self, time: Time) -> Result<(), Error> { match time { - None => self.reset()?, Some((hour, min)) => { + self.save_usually(&time)?; let job = job_from(hour, min); - self.replace_current(job).await?; + self.replace_job(job).await?; + } + None => { + self.db.remove("usually")?; + if self.tomorrow.is_none() { + self.remove_job()?; + } } } self.usually = time; diff --git a/src/input/web_api/alarms.rs b/src/input/web_api/alarms.rs deleted file mode 100644 index ef977230..00000000 --- a/src/input/web_api/alarms.rs +++ /dev/null @@ -1,88 +0,0 @@ -use chrono::{DateTime, NaiveDateTime, Utc, Timelike}; -use serde::Deserialize; - -use super::*; - -#[derive(Deserialize, Debug)] -pub struct AlarmDataMinFrom { - min_till_alarm: String, -} - -pub fn set_alarm_minutes_from_now( - params: Form, - state: Data, - auth: BasicAuth, -) -> HttpResponse { - if authenticated(auth) { - //Code to parse alarm time - dbg!(¶ms); - - if let Ok(minutes) = params.min_till_alarm.parse() { - let time = Utc::now() + chrono::Duration::minutes(minutes); - - //state.alarms.add_alarm(time).unwrap(); - HttpResponse::Ok().finish() - } else { - make_error(StatusCode::INTERNAL_SERVER_ERROR) - } - } else { - make_auth_error() - } -} - -#[derive(Deserialize, Debug)] -pub struct AlarmDataUnixTS { - timestamp: String, -} - -pub async fn set_alarm_unix_timestamp( - params: Form, - state: Data, -) -> HttpResponse { - //Code to parse alarm time - dbg!(¶ms); - - if let Ok(ts) = params.timestamp.parse() { - let time = DateTime::::from_utc(NaiveDateTime::from_timestamp(ts, 0), Utc); - dbg!(time); - dbg!(Utc::now()); - - if time > Utc::now() { - let hour = time.time().hour() as u8; - let min = time.time().minute() as u8; - let time = Some((hour,min)); - if state.wakeup.set_tomorrow(time).await.is_ok() { - dbg!("done setting alarm"); - HttpResponse::Ok().finish() - } else { - dbg!(); - make_error(StatusCode::INTERNAL_SERVER_ERROR) - } - } else { - dbg!(); - make_error(StatusCode::UNPROCESSABLE_ENTITY) - } - } else { - dbg!(); - make_error(StatusCode::INTERNAL_SERVER_ERROR) - } -} - -pub fn list_alarms(state: Data) -> HttpResponse { - //Code to parse alarm time - - let alarms = state.jobs.list(); - let mut list = String::with_capacity(alarms.len() * 100); - for (id, alarm) in alarms { - list.push_str(&format!( - "{:x}, {}, {:?}, {:?}", - id, - &alarm.time.to_rfc2822(), - &alarm.action, - &alarm.expiration, - )); - list.push_str("\n"); - } - dbg!(&list); - HttpResponse::Ok().body(list) -} diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index d0b83cff..8735d89a 100755 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -7,7 +7,6 @@ use actix_web::web::{Data, Form}; use actix_web::{HttpRequest, HttpResponse}; mod wakeup; -mod alarms; mod commands; mod logins; mod music; diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index 5539d1f8..7ae25328 100755 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -26,7 +26,7 @@ pub mod database; pub mod login; pub mod login_redirect; -use super::{alarms, wakeup, commands, music}; +use super::{wakeup, commands, music}; pub use database::PasswordDatabase; pub use login::{login_get_and_check, login_page, logout, make_random_cookie_key}; pub use login_redirect::CheckLogin; @@ -184,8 +184,6 @@ pub fn start_webserver( .service(web::resource("").to(index)) .service(web::resource("logout/").to(logout)) .service(web::resource("add_song").to(music::add_song_from_url)) - .service(web::resource("set_alarm").to(alarms::set_alarm_unix_timestamp)) - .service(web::resource("list_alarms").to(alarms::list_alarms)) //for all other urls we try to resolve to static files in the "web" dir .service(axtix_fs::Files::new("", "./web/")), ) diff --git a/src/input/web_api/wakeup.rs b/src/input/web_api/wakeup.rs index d82fc7e0..ead45207 100644 --- a/src/input/web_api/wakeup.rs +++ b/src/input/web_api/wakeup.rs @@ -47,7 +47,7 @@ pub async fn usually(state: Data, auth: BasicAuth, req: HttpRequest, body match *req.method() { Method::GET => { - let usually = state.wakeup.usually(); + let usually = dbg!(state.wakeup.usually()); let bytes = bincode::serialize(&usually).unwrap(); HttpResponse::Ok().body(bytes) } From eb4b22460b3c18c14bf8876e0e341529b370171b Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Wed, 10 Mar 2021 01:56:50 +0100 Subject: [PATCH 068/687] Solves two critical bugs in wakeup database. - A new entries where not always flushed to disk before returning, now any call to set usually or set tomorrow is guarenteed tha t the data has been written to disk. - B while loading from disk deserializing went wrong because it tried to deserialize to (u8,u8) instead of Option<(u8,u8)>. This was hidden as the type for deserializing was inferred and deserializing was done within a map over an Option of bytes. --- Cargo.lock | 389 +++++++++++++++--------------------- Cargo.toml | 4 +- src/input/jobs/wakeup.rs | 17 +- src/input/web_api/wakeup.rs | 2 +- src/main.rs | 2 +- 5 files changed, 170 insertions(+), 244 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 131bac5f..caee97f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,7 +22,7 @@ dependencies = [ "crossbeam-channel 0.3.9", "dirs", "fern", - "futures 0.3.12", + "futures 0.3.13", "gpio-cdev", "hex", "linux-embedded-hal", @@ -62,7 +62,7 @@ dependencies = [ "crossbeam-channel 0.3.9", "failure", "fnv", - "futures 0.1.30", + "futures 0.1.31", "libc", "log 0.4.14", "parking_lot 0.7.1", @@ -123,7 +123,7 @@ dependencies = [ "actix-utils 1.0.6", "derive_more", "either", - "futures 0.3.12", + "futures 0.3.13", "http 0.2.3", "log 0.4.14", "rustls 0.16.0", @@ -211,7 +211,7 @@ checksum = "2a379b0639c293292d71defb8cc1f94c87b7705c904adf044338ad392df77c7a" dependencies = [ "actix-service", "actix-web", - "futures 0.3.12", + "futures 0.3.13", "serde", "serde_json", "time", @@ -224,7 +224,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ca8ce00b267af8ccebbd647de0d61e0674b6e61185cc7a592ff88772bed655" dependencies = [ "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -235,7 +235,7 @@ checksum = "8bebfbe6629e0131730746718c9e032b58f02c6ce06ed7c982b9fef6c8545acd" dependencies = [ "actix", "bytes 0.4.12", - "futures 0.1.30", + "futures 0.1.31", "log 0.4.14", "mio", "net2", @@ -351,7 +351,7 @@ dependencies = [ "actix-utils 1.0.6", "derive_more", "either", - "futures 0.3.12", + "futures 0.3.13", "log 0.4.14", "rustls 0.16.0", "tokio-rustls 0.12.3", @@ -371,7 +371,7 @@ dependencies = [ "bitflags 1.2.1", "bytes 0.5.6", "either", - "futures 0.3.12", + "futures 0.3.13", "log 0.4.14", "pin-project 0.4.27", "slab", @@ -419,7 +419,7 @@ dependencies = [ "bytes 0.5.6", "derive_more", "encoding_rs", - "futures 0.3.12", + "futures 0.3.13", "fxhash", "log 0.4.14", "mime 0.3.16", @@ -442,7 +442,7 @@ checksum = "a71bf475cbe07281d0b3696abb48212db118e7e23219f13596ce865235ff5766" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -480,9 +480,9 @@ dependencies = [ [[package]] name = "adler" -version = "0.2.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" @@ -651,7 +651,7 @@ dependencies = [ "async-global-executor", "async-io", "async-lock", - "crossbeam-utils 0.8.2", + "crossbeam-utils 0.8.3", "futures-channel", "futures-core", "futures-io", @@ -662,7 +662,7 @@ dependencies = [ "memchr", "num_cpus", "once_cell", - "pin-project-lite 0.2.4", + "pin-project-lite 0.2.6", "pin-utils", "slab", "wasm-bindgen-futures", @@ -676,13 +676,13 @@ checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" [[package]] name = "async-trait" -version = "0.1.42" +version = "0.1.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d" +checksum = "36ea56748e10732c49404c153638a15ec3d6211ec5ff35d9bb20e13b93576adf" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -781,9 +781,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bincode" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d" +checksum = "d175dfa69e619905c4c3cdb7c3c203fa3bdd5d51184e3afdb2742c0280493772" dependencies = [ "byteorder", "serde", @@ -889,9 +889,9 @@ checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" [[package]] name = "byteorder" -version = "1.4.2" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" [[package]] name = "bytes" @@ -1107,7 +1107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.2", + "crossbeam-utils 0.8.3", ] [[package]] @@ -1128,8 +1128,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" dependencies = [ "cfg-if 1.0.0", - "crossbeam-epoch 0.9.2", - "crossbeam-utils 0.8.2", + "crossbeam-epoch 0.9.3", + "crossbeam-utils 0.8.3", ] [[package]] @@ -1163,14 +1163,13 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d60ab4a8dba064f2fbb5aa270c28da5cf4bbd0e72dae1140a6b0353a779dbe00" +checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.2", + "crossbeam-utils 0.8.3", "lazy_static", - "loom", "memoffset 0.6.1", "scopeguard 1.1.0", ] @@ -1209,14 +1208,13 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae8f328835f8f5a6ceb6a7842a7f2d0c03692adb5c889347235d59194731fe3" +checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" dependencies = [ "autocfg 1.0.1", "cfg-if 1.0.0", "lazy_static", - "loom", ] [[package]] @@ -1235,7 +1233,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8f45d9ad417bcef4817d614a501ab55cdd96a6fdb24f49aab89a54acfd66b19" dependencies = [ "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -1246,7 +1244,7 @@ checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -1310,7 +1308,7 @@ dependencies = [ "heck", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -1331,15 +1329,6 @@ dependencies = [ "backtrace", ] -[[package]] -name = "error-chain" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" -dependencies = [ - "version_check 0.9.2", -] - [[package]] name = "event-listener" version = "2.5.1" @@ -1364,7 +1353,7 @@ checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", "synstructure", ] @@ -1450,15 +1439,15 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futures" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7e4c2612746b0df8fed4ce0c69156021b704c9aefa360311c04e6e9e002eed" +checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9052a1a50244d8d5aa9bf55cbc2fb6f357c86cc52e46c62ed390a7180cf150" +checksum = "7f55667319111d593ba876406af7c409c0ebb44dc4be6132a783ccf163ea14c1" dependencies = [ "futures-channel", "futures-core", @@ -1471,9 +1460,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2d31b7ec7efab6eefc7c57233bb10b847986139d88cc2f5a02a1ae6871a1846" +checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939" dependencies = [ "futures-core", "futures-sink", @@ -1481,9 +1470,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e5145dde8da7d1b3892dad07a9c98fc04bc39892b1ecc9692cf53e2b780a65" +checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94" [[package]] name = "futures-cpupool" @@ -1491,15 +1480,15 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" dependencies = [ - "futures 0.1.30", + "futures 0.1.31", "num_cpus", ] [[package]] name = "futures-executor" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e59fdc009a4b3096bf94f740a0f2424c082521f20a9b08c5c07c48d90fd9b9" +checksum = "891a4b7b96d84d5940084b2a37632dd65deeae662c114ceaa2c879629c9c0ad1" dependencies = [ "futures-core", "futures-task", @@ -1508,9 +1497,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28be053525281ad8259d47e4de5de657b25e7bac113458555bb4b70bc6870500" +checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59" [[package]] name = "futures-lite" @@ -1523,42 +1512,39 @@ dependencies = [ "futures-io", "memchr", "parking", - "pin-project-lite 0.2.4", + "pin-project-lite 0.2.6", "waker-fn", ] [[package]] name = "futures-macro" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c287d25add322d9f9abdcdc5927ca398917996600182178774032e9f8258fedd" +checksum = "ea405816a5139fb39af82c2beb921d52143f556038378d6db21183a5c37fbfb7" dependencies = [ "proc-macro-hack", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] name = "futures-sink" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf5c69029bda2e743fddd0582d1083951d65cc9539aebf8812f36c3491342d6" +checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3" [[package]] name = "futures-task" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13de07eb8ea81ae445aca7b69f5f7bf15d7bf4912d8ca37d6645c77ae8a58d86" -dependencies = [ - "once_cell", -] +checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80" [[package]] name = "futures-util" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632a8cd0f2a4b3fdea1657f08bde063848c3bd00f9bbf6e256b8be78802e624b" +checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1" dependencies = [ "futures-channel", "futures-core", @@ -1567,7 +1553,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.4", + "pin-project-lite 0.2.6", "pin-utils", "proc-macro-hack", "proc-macro-nested", @@ -1583,19 +1569,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "generator" -version = "0.6.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9fed24fd1e18827652b4d55652899a1e9da8e54d91624dc3437a5bc3a9f9a9c" -dependencies = [ - "cc", - "libc", - "log 0.4.14", - "rustversion", - "winapi 0.3.9", -] - [[package]] name = "getrandom" version = "0.1.16" @@ -1656,7 +1629,7 @@ dependencies = [ "byteorder", "bytes 0.4.12", "fnv", - "futures 0.1.30", + "futures 0.1.31", "http 0.1.21", "indexmap", "log 0.4.14", @@ -1720,9 +1693,9 @@ dependencies = [ [[package]] name = "hex" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "historian" @@ -1770,7 +1743,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" dependencies = [ "bytes 0.4.12", - "futures 0.1.30", + "futures 0.1.31", "http 0.1.21", "tokio-buf", ] @@ -1804,7 +1777,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c843caf6296fc1f93444735205af9ed4e109a539005abb2564ae1d6fad34c52" dependencies = [ "bytes 0.4.12", - "futures 0.1.30", + "futures 0.1.31", "futures-cpupool", "h2 0.1.26", "http 0.1.21", @@ -1859,7 +1832,7 @@ checksum = "719d85c7df4a7f309a77d145340a063ea929dcb2e025bae46a80345cffec2952" dependencies = [ "bytes 0.4.12", "ct-logs", - "futures 0.1.30", + "futures 0.1.31", "hyper 0.12.36", "rustls 0.16.0", "tokio-io", @@ -1937,9 +1910,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.6.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" +checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" dependencies = [ "autocfg 1.0.1", "hashbrown 0.9.1", @@ -2002,9 +1975,9 @@ checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" [[package]] name = "js-sys" -version = "0.3.47" +version = "0.3.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cfb73131c35423a367daf8cbd24100af0d077668c8c2943f0e7dd775fef0f65" +checksum = "dc9f84f9b115ce7843d60706df1422a916680bfdfcbdb0447c5614ff9d7e4d78" dependencies = [ "wasm-bindgen", ] @@ -2042,9 +2015,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.86" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" +checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a" [[package]] name = "linked-hash-map" @@ -2112,17 +2085,6 @@ dependencies = [ "value-bag", ] -[[package]] -name = "loom" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d44c73b4636e497b4917eb21c33539efa3816741a2d3ff26c6316f1b529481a4" -dependencies = [ - "cfg-if 1.0.0", - "generator", - "scoped-tls", -] - [[package]] name = "lru-cache" version = "0.1.2" @@ -2213,9 +2175,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" dependencies = [ "adler", "autocfg 1.0.1", @@ -2399,7 +2361,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" dependencies = [ - "num-bigint 0.3.1", + "num-bigint 0.3.2", "num-complex 0.3.1", "num-integer", "num-iter", @@ -2420,9 +2382,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e9a41747ae4633fce5adffb4d2e81ffc5e89593cb19917f8fb2cc5ff76507bf" +checksum = "7d0a3d5e207573f948a9e5376662aa743a2ea13f7c50a554d7af443a73fbfeba" dependencies = [ "autocfg 1.0.1", "num-integer", @@ -2488,7 +2450,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" dependencies = [ "autocfg 1.0.1", - "num-bigint 0.3.1", + "num-bigint 0.3.2", "num-integer", "num-traits", ] @@ -2520,9 +2482,9 @@ checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" [[package]] name = "once_cell" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad167a2f54e832b82dbe003a046280dceffe5227b5f79e08e363a29638cfddd" +checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" [[package]] name = "openssl-probe" @@ -2559,7 +2521,7 @@ dependencies = [ "crossbeam-epoch 0.7.2", "crossbeam-utils 0.6.6", "fs2", - "futures 0.1.30", + "futures 0.1.31", "fxhash", "hashbrown 0.3.1", "historian", @@ -2597,16 +2559,6 @@ dependencies = [ "rustc_version 0.2.3", ] -[[package]] -name = "parking_lot" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" -dependencies = [ - "lock_api 0.3.4", - "parking_lot_core 0.7.2", -] - [[package]] name = "parking_lot" version = "0.11.1" @@ -2646,20 +2598,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "parking_lot_core" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" -dependencies = [ - "cfg-if 0.1.10", - "cloudabi", - "libc", - "redox_syscall 0.1.57", - "smallvec 1.6.1", - "winapi 0.3.9", -] - [[package]] name = "parking_lot_core" version = "0.8.3" @@ -2772,7 +2710,7 @@ checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -2783,20 +2721,20 @@ checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] name = "pin-project-lite" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b" +checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827" +checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" [[package]] name = "pin-utils" @@ -2832,7 +2770,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", "version_check 0.9.2", ] @@ -2879,14 +2817,11 @@ dependencies = [ [[package]] name = "publicsuffix" -version = "1.5.4" +version = "1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bbaa49075179162b49acac1c6aa45fb4dafb5f13cf6794276d77bc7fd95757b" +checksum = "95b4ce31ff0a27d93c8de1849cf58162283752f065a90d508f1105fa6c9a213f" dependencies = [ - "error-chain 0.12.4", "idna 0.2.2", - "lazy_static", - "regex", "url 2.2.1", ] @@ -3134,7 +3069,7 @@ checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" dependencies = [ "crossbeam-channel 0.5.0", "crossbeam-deque 0.8.0", - "crossbeam-utils 0.8.2", + "crossbeam-utils 0.8.3", "lazy_static", "num_cpus", ] @@ -3213,7 +3148,7 @@ dependencies = [ "cookie_store", "encoding_rs", "flate2", - "futures 0.1.30", + "futures 0.1.31", "http 0.1.21", "hyper 0.12.36", "hyper-rustls 0.17.1", @@ -3259,7 +3194,7 @@ dependencies = [ "mime 0.3.16", "mime_guess 2.0.3", "percent-encoding 2.1.0", - "pin-project-lite 0.2.4", + "pin-project-lite 0.2.6", "rustls 0.18.1", "serde", "serde_urlencoded 0.7.0", @@ -3316,7 +3251,7 @@ dependencies = [ "base64 0.13.0", "blake2b_simd", "constant_time_eq", - "crossbeam-utils 0.8.2", + "crossbeam-utils 0.8.3", ] [[package]] @@ -3387,12 +3322,6 @@ dependencies = [ "security-framework", ] -[[package]] -name = "rustversion" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd" - [[package]] name = "ryu" version = "1.0.5" @@ -3409,12 +3338,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "scoped-tls" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" - [[package]] name = "scopeguard" version = "0.3.3" @@ -3490,9 +3413,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.123" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae" +checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f" dependencies = [ "serde_derive", ] @@ -3509,20 +3432,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.123" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31" +checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] name = "serde_json" -version = "1.0.62" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486" +checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" dependencies = [ "itoa", "ryu", @@ -3616,18 +3539,18 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "sled" -version = "0.30.3" +version = "0.34.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb8c32cb0e34e67ad74fae1a77f4635d0cc7ffc873088a0136f3c4849336d71" +checksum = "1d0132f3e393bcb7390c60bb45769498cf4550bcb7a21d7f95c02b69f6362cdc" dependencies = [ "crc32fast", - "crossbeam-epoch 0.8.2", - "crossbeam-utils 0.7.2", + "crossbeam-epoch 0.9.3", + "crossbeam-utils 0.8.3", "fs2", "fxhash", "libc", "log 0.4.14", - "parking_lot 0.10.2", + "parking_lot 0.11.1", ] [[package]] @@ -3733,7 +3656,7 @@ dependencies = [ "proc-macro-error", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -3749,9 +3672,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.60" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" +checksum = "8fd9bc7ccc2688b3344c2f48b9b546648b25ce0b20fc717ee7fa7981a8ca9717" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", @@ -3766,7 +3689,7 @@ checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", "unicode-xid 0.2.1", ] @@ -3786,7 +3709,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb29fb11ef40c839c1c6b4e9c2ec4f357f9f674491e9df5a8c94f8cc2005f860" dependencies = [ "bytes 0.5.6", - "futures 0.3.12", + "futures 0.3.13", "hyper 0.13.10", "hyper-rustls 0.19.1", "multipart", @@ -3855,7 +3778,7 @@ checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -3909,7 +3832,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" dependencies = [ "bytes 0.4.12", - "futures 0.1.30", + "futures 0.1.31", "mio", "num_cpus", "tokio-codec", @@ -3941,7 +3864,7 @@ dependencies = [ "memchr", "mio", "mio-uds", - "pin-project-lite 0.1.11", + "pin-project-lite 0.1.12", "signal-hook-registry", "slab", "winapi 0.3.9", @@ -3955,7 +3878,7 @@ checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" dependencies = [ "bytes 0.4.12", "either", - "futures 0.1.30", + "futures 0.1.31", ] [[package]] @@ -3965,7 +3888,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" dependencies = [ "bytes 0.4.12", - "futures 0.1.30", + "futures 0.1.31", "tokio-io", ] @@ -3975,7 +3898,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" dependencies = [ - "futures 0.1.30", + "futures 0.1.31", "tokio-executor", ] @@ -3986,7 +3909,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" dependencies = [ "crossbeam-utils 0.7.2", - "futures 0.1.30", + "futures 0.1.31", ] [[package]] @@ -3995,7 +3918,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" dependencies = [ - "futures 0.1.30", + "futures 0.1.31", "tokio-io", "tokio-threadpool", ] @@ -4007,7 +3930,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" dependencies = [ "bytes 0.4.12", - "futures 0.1.30", + "futures 0.1.31", "log 0.4.14", ] @@ -4018,7 +3941,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" dependencies = [ "crossbeam-utils 0.7.2", - "futures 0.1.30", + "futures 0.1.31", "lazy_static", "log 0.4.14", "mio", @@ -4037,7 +3960,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d7cf08f990090abd6c6a73cab46fed62f85e8aef8b99e4b918a9f4a637f0676" dependencies = [ "bytes 0.4.12", - "futures 0.1.30", + "futures 0.1.31", "iovec", "rustls 0.16.0", "tokio-io", @@ -4074,7 +3997,7 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0c34c6e548f101053321cba3da7cbb87a610b85555884c41b07da2eb91aff12" dependencies = [ - "futures 0.1.30", + "futures 0.1.31", "libc", "mio", "mio-uds", @@ -4092,7 +4015,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" dependencies = [ "fnv", - "futures 0.1.30", + "futures 0.1.31", ] [[package]] @@ -4102,7 +4025,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" dependencies = [ "bytes 0.4.12", - "futures 0.1.30", + "futures 0.1.31", "iovec", "mio", "tokio-io", @@ -4118,7 +4041,7 @@ dependencies = [ "crossbeam-deque 0.7.3", "crossbeam-queue", "crossbeam-utils 0.7.2", - "futures 0.1.30", + "futures 0.1.31", "lazy_static", "log 0.4.14", "num_cpus", @@ -4133,7 +4056,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" dependencies = [ "crossbeam-utils 0.7.2", - "futures 0.1.30", + "futures 0.1.31", "slab", "tokio-executor", ] @@ -4145,7 +4068,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" dependencies = [ "bytes 0.4.12", - "futures 0.1.30", + "futures 0.1.31", "log 0.4.14", "mio", "tokio-codec", @@ -4160,7 +4083,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0" dependencies = [ "bytes 0.4.12", - "futures 0.1.30", + "futures 0.1.31", "iovec", "libc", "log 0.4.14", @@ -4181,7 +4104,7 @@ dependencies = [ "futures-core", "futures-sink", "log 0.4.14", - "pin-project-lite 0.1.11", + "pin-project-lite 0.1.12", "tokio 0.2.25", ] @@ -4195,7 +4118,7 @@ dependencies = [ "futures-core", "futures-sink", "log 0.4.14", - "pin-project-lite 0.1.11", + "pin-project-lite 0.1.12", "tokio 0.2.25", ] @@ -4205,7 +4128,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b32f72af77f1bfe3d3d4da8516a238ebe7039b51dd8637a09841ac7f16d2c987" dependencies = [ - "futures 0.1.30", + "futures 0.1.31", ] [[package]] @@ -4216,13 +4139,13 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f77d3842f76ca899ff2dbcf231c5c65813dea431301d6eb686279c15c4464f12" +checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f" dependencies = [ "cfg-if 1.0.0", "log 0.4.14", - "pin-project-lite 0.2.4", + "pin-project-lite 0.2.6", "tracing-attributes", "tracing-core", ] @@ -4235,7 +4158,7 @@ checksum = "a8a9bd1db7706f2373a190b0d067146caa39350c486f3d455b0e33b431f94c07" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -4265,7 +4188,7 @@ checksum = "0838272e89f1c693b4df38dc353412e389cf548ceed6f9fd1af5a8d6e0e7cf74" dependencies = [ "byteorder", "failure", - "futures 0.1.30", + "futures 0.1.31", "idna 0.1.5", "lazy_static", "log 0.4.14", @@ -4289,7 +4212,7 @@ checksum = "09144f0992b0870fa8d2972cc069cbf1e3c0fda64d1f3d45c4d68d0e0b52ad4e" dependencies = [ "byteorder", "failure", - "futures 0.1.30", + "futures 0.1.31", "idna 0.1.5", "lazy_static", "log 0.4.14", @@ -4314,7 +4237,7 @@ dependencies = [ "async-trait", "enum-as-inner", "failure", - "futures 0.3.12", + "futures 0.3.13", "idna 0.2.2", "lazy_static", "log 0.4.14", @@ -4333,7 +4256,7 @@ checksum = "8a9f877f7a1ad821ab350505e1f1b146a4960402991787191d6d8cab2ce2de2c" dependencies = [ "cfg-if 0.1.10", "failure", - "futures 0.1.30", + "futures 0.1.31", "ipconfig 0.1.9", "lazy_static", "log 0.4.14", @@ -4352,7 +4275,7 @@ checksum = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f" dependencies = [ "cfg-if 0.1.10", "failure", - "futures 0.3.12", + "futures 0.3.13", "ipconfig 0.2.2", "lazy_static", "log 0.4.14", @@ -4494,7 +4417,7 @@ dependencies = [ "nom", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -4558,7 +4481,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" dependencies = [ - "futures 0.1.30", + "futures 0.1.31", "log 0.4.14", "try-lock", ] @@ -4587,9 +4510,9 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" -version = "0.2.70" +version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be" +checksum = "7ee1280240b7c461d6a0071313e08f34a60b0365f14260362e5a2b17d1d31aa7" dependencies = [ "cfg-if 1.0.0", "serde", @@ -4599,24 +4522,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.70" +version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bc45447f0d4573f3d65720f636bbcc3dd6ce920ed704670118650bcd47764c7" +checksum = "5b7d8b6942b8bb3a9b0e73fc79b98095a27de6fa247615e59d096754a3bc2aa8" dependencies = [ "bumpalo", "lazy_static", "log 0.4.14", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3de431a2910c86679c34283a33f66f4e4abd7e0aec27b6669060148872aadf94" +checksum = "8e67a5806118af01f0d9045915676b22aaebecf4178ae7021bc171dab0b897ab" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -4626,9 +4549,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.70" +version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c" +checksum = "e5ac38da8ef716661f0f36c0d8320b89028efe10c7c0afde65baffb496ce0d3b" dependencies = [ "quote 1.0.9", "wasm-bindgen-macro-support", @@ -4636,28 +4559,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.70" +version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385" +checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.70" +version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4945e4943ae02d15c13962b38a5b1e81eadd4b71214eee75af64a4d6a4fd64" +checksum = "7d6f8ec44822dd71f5f221a5847fb34acd9060535c1211b70a05844c0f6383b1" [[package]] name = "web-sys" -version = "0.3.47" +version = "0.3.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c40dc691fc48003eba817c38da7113c15698142da971298003cac3ef175680b3" +checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index 95b7385c..87064246 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ philipshue = { git = "https://github.com/dskleingeld/philipshue", branch = "mast structopt = "0.3" serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.8" -bincode = "1.3.1" +bincode = "1.3" thiserror = "1.0" log = "0.4" @@ -61,7 +61,7 @@ hex = "0.4.2" crossbeam-channel = "0.3" -sled = "0.30" +sled = "0.34" pagecache = "0.17" reqwest = {version = "0.10", default-features = false, features = ["rustls-tls"]} diff --git a/src/input/jobs/wakeup.rs b/src/input/jobs/wakeup.rs index 4c317510..3e620fc8 100644 --- a/src/input/jobs/wakeup.rs +++ b/src/input/jobs/wakeup.rs @@ -60,15 +60,17 @@ struct Inner { impl Inner { pub fn setup(db: sled::Db, jobs: Jobs) -> Result { let db = db.open_tree("wakeup")?; + let usually = db .get("usually")? - .map(|b| bincode::deserialize(&b).unwrap()); + .map(|b| bincode::deserialize(&b).unwrap()) + .flatten(); // we want bincode to deserialize to Option<(u8,u8)> not (u8,u8) let job_id = db .get("job_id")? .map(|b| bincode::deserialize(&b).unwrap()); let next_alarm = job_id.as_ref() - .map(|id| jobs.get(*id).ok()) - .flatten().flatten() + .map(|id| jobs.get(*id).unwrap()) + .flatten() .map(|job| job.time.into()) .map(|t: DateTime| t) .map(|t| (t.hour() as u8, t.minute() as u8)); @@ -92,12 +94,14 @@ impl Inner { let old_job_id = bincode::deserialize(&bytes).unwrap(); self.jobs.remove_alarm(old_job_id)?; } + self.db.flush().unwrap(); Ok(()) } fn save_usually(&mut self, usually: &Time) -> Result<(), Error> { - let bytes = bincode::serialize(dbg!(usually)).unwrap(); + let bytes = bincode::serialize(usually).unwrap(); self.db.insert("usually", bytes)?; + self.db.flush()?; Ok(()) } @@ -140,14 +144,13 @@ impl Inner { } pub async fn set_usually(&mut self, time: Time) -> Result<(), Error> { + self.save_usually(&time)?; match time { Some((hour, min)) => { - self.save_usually(&time)?; let job = job_from(hour, min); self.replace_job(job).await?; } - None => { - self.db.remove("usually")?; + None => if self.job_id.is_some() { if self.tomorrow.is_none() { self.remove_job()?; } diff --git a/src/input/web_api/wakeup.rs b/src/input/web_api/wakeup.rs index ead45207..d82fc7e0 100644 --- a/src/input/web_api/wakeup.rs +++ b/src/input/web_api/wakeup.rs @@ -47,7 +47,7 @@ pub async fn usually(state: Data, auth: BasicAuth, req: HttpRequest, body match *req.method() { Method::GET => { - let usually = dbg!(state.wakeup.usually()); + let usually = state.wakeup.usually(); let bytes = bincode::serialize(&usually).unwrap(); HttpResponse::Ok().body(bytes) } diff --git a/src/main.rs b/src/main.rs index 7d38a1e8..0a0337d5 100755 --- a/src/main.rs +++ b/src/main.rs @@ -38,7 +38,7 @@ struct Opt { #[actix_rt::main] async fn main() { let opt = Opt::from_args(); - errors::setup_logging(1).unwrap(); + errors::setup_logging(2).unwrap(); let db = sled::Config::default() //651ms .path("database") From 43deda21e87b30409d93a716ca47b7b967d8de9f Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Fri, 12 Mar 2021 09:13:57 +0100 Subject: [PATCH 069/687] adjusted light command to also turn on lamps solving the issue where they turn on at full brightness --- src/controller/state/wakeup.rs | 7 +++---- src/controller/system/lamps/mod.rs | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/controller/state/wakeup.rs b/src/controller/state/wakeup.rs index 11bbea3a..8cfba628 100755 --- a/src/controller/state/wakeup.rs +++ b/src/controller/state/wakeup.rs @@ -85,8 +85,7 @@ impl WakeUp { mods.mpd = false; Self::setup_playlist()?; - sys.lights.set_all_ct(0, CT_BEGIN)?; - sys.lights.all_on()?; + sys.lights.set_all_on_ct(0, CT_BEGIN)?; Ok(Box::new(Self { start: Instant::now(), @@ -112,14 +111,14 @@ impl RoomState for WakeUp { if !mods.lighting { let bri = (BRI_PER_SECOND * (elapsed as f32)) as u8; let ct = CT_BEGIN - (CT_PER_SECOND * (elapsed as f32)) as u16; - sys.lights.set_all_ct(dbg!(bri), ct)?; + sys.lights.set_all_on_ct(bri, ct)?; } // do nothing to mpd if the user changed an mpd setting if !mods.mpd { if !self.playing && elapsed > MUSIC_ON { let mut client = mpd::Client::connect("127.0.0.1:6600")?; - client.volume(dbg!(MIN_VOLUME) as i8)?; + client.volume(MIN_VOLUME as i8)?; client.play()?; self.playing = true; } else if elapsed > MUSIC_ON { diff --git a/src/controller/system/lamps/mod.rs b/src/controller/system/lamps/mod.rs index bb7e3eda..b96c557c 100755 --- a/src/controller/system/lamps/mod.rs +++ b/src/controller/system/lamps/mod.rs @@ -246,6 +246,22 @@ impl Lighting { Ok(()) } + pub fn set_all_on_ct(&mut self, bri: u8, ct: u16) -> Result<(), Error> { + let command = LightCommand::default(); + //let command = command.on(); + let command = command.with_bri(bri); + let command = command.with_ct(ct); + let command = command.on(); + self.bridge.set_group_state(0, &command)?; + self.lamps.values_mut().for_each(|lamp| { + lamp.bri = bri; + lamp.ct = Some(ct); + lamp.on = true + }); + + Ok(()) + } + //how to deal with errors? pub fn set_all_ct(&mut self, bri: u8, ct: u16) -> Result<(), Error> { let command = LightCommand::default(); From c614a51e1496762804343334922aa03acd6549a4 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Mon, 28 Jun 2021 18:07:01 +0200 Subject: [PATCH 070/687] switches to http + removes tls code, now expected to use this behind a reverse tls terminating proxy --- src/errors.rs | 3 -- src/input/web_api/mod.rs | 1 - src/input/web_api/server/mod.rs | 70 ++------------------------------- src/main.rs | 20 +++++----- 4 files changed, 13 insertions(+), 81 deletions(-) diff --git a/src/errors.rs b/src/errors.rs index b3961558..f10b0dee 100755 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,6 +1,5 @@ use fern::colors::{Color, ColoredLevelConfig}; -use crate::input::web_api::server; use crate::input::youtube_downloader; #[derive(thiserror::Error, Debug)] @@ -23,8 +22,6 @@ pub enum Error { RetryLogic(String), #[error("Could not download youtube movie")] YoutubeDownloader(youtube_downloader::Error), - #[error("Problem handeling web requests")] - WebServerError(server::Error), #[error("Error in the wakeup alarm system")] SetWakeUp(#[from] crate::input::jobs::wakeup::Error), #[error("Error in wakeup state")] diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index 8735d89a..77624c55 100755 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -3,7 +3,6 @@ use actix_web_httpauth::headers::www_authenticate::basic::Basic; use actix_web_httpauth::headers::www_authenticate::WwwAuthenticate; use actix_web::http::StatusCode; -use actix_web::web::{Data, Form}; use actix_web::{HttpRequest, HttpResponse}; mod wakeup; diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index 7ae25328..62aaf8c5 100755 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -1,5 +1,3 @@ -use rustls::internal::pemfile::{certs, pkcs8_private_keys}; -use rustls::{NoClientAuth, ServerConfig}; use sensor_value::SensorValue; use telegram_bot::types::refs::UserId; @@ -12,9 +10,6 @@ use actix_web::HttpResponse; use actix_web::{web, App, HttpServer, Responder}; use std::collections::HashMap; -use std::fs; -use std::io::BufReader; -use std::path::{Path, PathBuf}; use std::sync::{atomic::AtomicUsize, Arc, Mutex, RwLock}; use std::thread; @@ -74,72 +69,16 @@ impl State { } } -#[derive(Debug)] -pub enum Error { - NoKeyFound, - NoCertFound, -} - -fn get_key_and_cert(domain: &str, dir: &Path) -> Result<(PathBuf, PathBuf), Error> { - let mut cert_path = Err(Error::NoCertFound); - let mut key_path = Err(Error::NoKeyFound); - let domain = domain.replace(".", "_"); - for path in fs::read_dir(dir) - .unwrap() - .filter_map(Result::ok) - .map(|entry| entry.path()) - { - if let Some(stem) = path.file_stem().map(|s| s.to_str()).flatten() { - if !stem.contains(&domain) { - continue; - } - if let Some(ext) = path.extension().map(|s| s.to_str()).flatten() { - match ext { - "key" => key_path = Ok(path), - "crt" => cert_path = Ok(path), - _ => continue, - } - } - } - } - - Ok((key_path?, cert_path?)) -} - -pub fn make_tls_config(domain: &str, key_dir: &Path) -> Result { - //find cert and key - let (key_path, cert_path) = get_key_and_cert(domain, key_dir)?; - - let mut tls_config = ServerConfig::new(NoClientAuth::new()); - let cert_file = &mut BufReader::new( - fs::File::open(&cert_path) - .expect(&format!("could not open certificate file: {:?}", cert_path)), - ); - let key_file = &mut BufReader::new( - fs::File::open(&key_path).expect(&format!("could not open key file: {:?}", key_path)), - ); - - let cert_chain = certs(cert_file).unwrap(); - let mut key = pkcs8_private_keys(key_file).unwrap(); - - tls_config - .set_single_cert(cert_chain, key.pop().unwrap()) - .unwrap(); - Ok(tls_config) -} - pub async fn index(_req: HttpRequest) -> impl Responder { "Hello world!" } pub fn start_webserver( - key_dir: &Path, state: State, port: u16, domain: String, ha_key: String, -) -> Result { - let tls_config = make_tls_config(&domain, key_dir)?; +) -> actix_web::dev::Server { let cookie_key = make_random_cookie_key(); let (tx, rx) = crossbeam_channel::unbounded(); @@ -188,20 +127,17 @@ pub fn start_webserver( .service(axtix_fs::Files::new("", "./web/")), ) }) - .bind_rustls(&format!("0.0.0.0:{}", port), tls_config) + .bind(&format!("127.0.0.1:{}", port)) // SEC: disallow connections from the outside .unwrap() - //.bind("0.0.0.0:8080").unwrap() //without tcp use with debugging (note: https -> http, wss -> ws) .shutdown_timeout(5) // shut down 5 seconds after getting the signal to shut down .run(); let _ = tx.send(web_server.clone()); sys.run() - //let mut rt = Runtime::new().unwrap(); - //rt.block_on(web_server).unwrap(); }); let web_handle = rx.recv().unwrap(); - Ok(web_handle) + web_handle } pub fn handle_sensor(body: Bytes, state: Data) -> HttpResponse { diff --git a/src/main.rs b/src/main.rs index 0a0337d5..686b53fe 100755 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,6 @@ extern crate log; use sled; -use std::path::PathBuf; use structopt::StructOpt; mod controller; @@ -17,20 +16,23 @@ mod errors; #[derive(StructOpt)] #[structopt(name = "homeautomation")] struct Opt { - #[structopt(short = "p", long = "port", default_value = "8080")] + /// port to bind to and listen for traffic + #[structopt(short = "p", long = "port", default_value = "433")] port: u16, - #[structopt(short = "e", long = "external-port")] - external_port: Option, + /// port to which telegram bot traffic should be send + #[structopt(short = "e", long = "external-port", default_value = "433")] + external_port: u16, + /// telegram bot token #[structopt(short = "t", long = "token")] token: String, + /// domain to which telegram bot traffic should be send #[structopt(short = "d", long = "domain")] domain: String, #[structopt(short = "a", long = "admin-password")] password: String, - #[structopt(short = "k", long = "keys", default_value = "keys")] - key_dir: PathBuf, #[structopt(short = "i", long = "allowed-telegram-ids")] valid_ids: Vec, + /// secret url part on which sensor data is recieved #[structopt(short = "h", long = "ha-key")] ha_key: String, } @@ -77,18 +79,16 @@ async fn main() { //start the webserver let _web_handle = server::start_webserver( - &opt.key_dir, state, opt.port, opt.domain.clone(), opt.ha_key.clone(), - ) - .unwrap(); + ); bot::set_webhook( &opt.domain, &opt.token, - opt.external_port.unwrap_or_else(|| opt.port), + opt.external_port, ) .await .unwrap(); From b8ded76006604c0cc063408add4728c5651d7e77 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Mon, 28 Jun 2021 23:33:17 +0200 Subject: [PATCH 071/687] remove exec bit --- .gitignore | 0 Cargo.toml | 0 src/controller/commands.rs | 0 src/controller/environment/mod.rs | 0 src/controller/mod.rs | 0 src/controller/state/lightloop.rs | 0 src/controller/state/mod.rs | 0 src/controller/state/normal.rs | 0 src/controller/state/silent.rs | 2 +- src/controller/state/wakeup.rs | 0 src/controller/system/computer.rs | 0 src/controller/system/lamps/mod.rs | 0 src/controller/system/mod.rs | 0 src/controller/system/mpd_control.rs | 0 src/errors.rs | 0 src/input/mod.rs | 0 src/input/mpd_status.rs | 0 src/input/web_api/mod.rs | 0 src/input/web_api/server/database.rs | 0 src/input/web_api/server/login.rs | 0 src/input/web_api/server/login_redirect.rs | 0 src/input/web_api/server/mod.rs | 0 src/input/youtube_downloader.rs | 0 src/main.rs | 0 24 files changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 .gitignore mode change 100755 => 100644 Cargo.toml mode change 100755 => 100644 src/controller/commands.rs mode change 100755 => 100644 src/controller/environment/mod.rs mode change 100755 => 100644 src/controller/mod.rs mode change 100755 => 100644 src/controller/state/lightloop.rs mode change 100755 => 100644 src/controller/state/mod.rs mode change 100755 => 100644 src/controller/state/normal.rs mode change 100755 => 100644 src/controller/state/wakeup.rs mode change 100755 => 100644 src/controller/system/computer.rs mode change 100755 => 100644 src/controller/system/lamps/mod.rs mode change 100755 => 100644 src/controller/system/mod.rs mode change 100755 => 100644 src/controller/system/mpd_control.rs mode change 100755 => 100644 src/errors.rs mode change 100755 => 100644 src/input/mod.rs mode change 100755 => 100644 src/input/mpd_status.rs mode change 100755 => 100644 src/input/web_api/mod.rs mode change 100755 => 100644 src/input/web_api/server/database.rs mode change 100755 => 100644 src/input/web_api/server/login.rs mode change 100755 => 100644 src/input/web_api/server/login_redirect.rs mode change 100755 => 100644 src/input/web_api/server/mod.rs mode change 100755 => 100644 src/input/youtube_downloader.rs mode change 100755 => 100644 src/main.rs diff --git a/.gitignore b/.gitignore old mode 100755 new mode 100644 diff --git a/Cargo.toml b/Cargo.toml old mode 100755 new mode 100644 diff --git a/src/controller/commands.rs b/src/controller/commands.rs old mode 100755 new mode 100644 diff --git a/src/controller/environment/mod.rs b/src/controller/environment/mod.rs old mode 100755 new mode 100644 diff --git a/src/controller/mod.rs b/src/controller/mod.rs old mode 100755 new mode 100644 diff --git a/src/controller/state/lightloop.rs b/src/controller/state/lightloop.rs old mode 100755 new mode 100644 diff --git a/src/controller/state/mod.rs b/src/controller/state/mod.rs old mode 100755 new mode 100644 diff --git a/src/controller/state/normal.rs b/src/controller/state/normal.rs old mode 100755 new mode 100644 diff --git a/src/controller/state/silent.rs b/src/controller/state/silent.rs index 03bb4d21..47e3b6fd 100644 --- a/src/controller/state/silent.rs +++ b/src/controller/state/silent.rs @@ -20,7 +20,7 @@ impl Silent { mpd::pause()?; sys.lights.single_off(2)?; - let command = LightCommand::default().on().with_bri(1).with_ct(2000); + let command = LightCommand::default().on().with_bri(77).with_ct(2000); for lamp_id in &[1, 8, 5, 4, 6] { sys.lights.bridge.set_light_state(*lamp_id, &command)?; diff --git a/src/controller/state/wakeup.rs b/src/controller/state/wakeup.rs old mode 100755 new mode 100644 diff --git a/src/controller/system/computer.rs b/src/controller/system/computer.rs old mode 100755 new mode 100644 diff --git a/src/controller/system/lamps/mod.rs b/src/controller/system/lamps/mod.rs old mode 100755 new mode 100644 diff --git a/src/controller/system/mod.rs b/src/controller/system/mod.rs old mode 100755 new mode 100644 diff --git a/src/controller/system/mpd_control.rs b/src/controller/system/mpd_control.rs old mode 100755 new mode 100644 diff --git a/src/errors.rs b/src/errors.rs old mode 100755 new mode 100644 diff --git a/src/input/mod.rs b/src/input/mod.rs old mode 100755 new mode 100644 diff --git a/src/input/mpd_status.rs b/src/input/mpd_status.rs old mode 100755 new mode 100644 diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs old mode 100755 new mode 100644 diff --git a/src/input/web_api/server/database.rs b/src/input/web_api/server/database.rs old mode 100755 new mode 100644 diff --git a/src/input/web_api/server/login.rs b/src/input/web_api/server/login.rs old mode 100755 new mode 100644 diff --git a/src/input/web_api/server/login_redirect.rs b/src/input/web_api/server/login_redirect.rs old mode 100755 new mode 100644 diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs old mode 100755 new mode 100644 diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs old mode 100755 new mode 100644 diff --git a/src/main.rs b/src/main.rs old mode 100755 new mode 100644 From dcdbcd8b82da6aa34b17ca38cd21d39edfb4d3ee Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Tue, 29 Jun 2021 16:07:11 +0200 Subject: [PATCH 072/687] changes deploy scripts to work with new server setup --- .gitignore | 1 - deploy.sh | 18 ++++++++++++++++++ deploy_optimized.sh | 3 +++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100755 deploy.sh create mode 100755 deploy_optimized.sh diff --git a/.gitignore b/.gitignore index 41422ce1..4e3fa2e2 100644 --- a/.gitignore +++ b/.gitignore @@ -73,4 +73,3 @@ userdb.hm ##################### target/ src/input/web_api/logins.rs -deploy_optimized.sh diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 00000000..3b8661c7 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -e + +BUILD_ARG=$1 +SERVER="sgc" # ssh config name or full adress + +cross build --target=armv7-unknown-linux-gnueabihf $BUILD_ARG --features "sensors_connected live_server" +rsync -vh --progress \ + target/armv7-unknown-linux-gnueabihf/debug/HomeAutomation \ + $SERVER:/tmp/ + +cmds=" +sudo mv /tmp/HomeAutomation /home/ha/homeAutomation +sudo chown ha:ha /home/ha/homeAutomation +sudo systemctl restart ha.service +" + +ssh -t sgc "$cmds" diff --git a/deploy_optimized.sh b/deploy_optimized.sh new file mode 100755 index 00000000..942ecbe4 --- /dev/null +++ b/deploy_optimized.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +source deploy "--release" From 0f36d7a36358d8251d1e094433bd131c983d2be5 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Tue, 29 Jun 2021 16:17:42 +0200 Subject: [PATCH 073/687] fixes arch in deploy --- deploy.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy.sh b/deploy.sh index 3b8661c7..2ad84558 100755 --- a/deploy.sh +++ b/deploy.sh @@ -4,9 +4,9 @@ set -e BUILD_ARG=$1 SERVER="sgc" # ssh config name or full adress -cross build --target=armv7-unknown-linux-gnueabihf $BUILD_ARG --features "sensors_connected live_server" +cross build --target=aarch64-unknown-linux-gnu $BUILD_ARG --features "sensors_connected live_server" rsync -vh --progress \ - target/armv7-unknown-linux-gnueabihf/debug/HomeAutomation \ + target/aarch64-unknown-linux-gnu/debug/HomeAutomation \ $SERVER:/tmp/ cmds=" From 266f3e88d80536e14564c6c76fa0e1bfb984607e Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Thu, 1 Jul 2021 23:35:01 +0200 Subject: [PATCH 074/687] port fixes update deps --- Cargo.lock | 789 ++++++++++++++++++++++--------------------- Cargo.toml | 2 +- src/input/bot/mod.rs | 2 +- src/main.rs | 4 +- 4 files changed, 403 insertions(+), 394 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index caee97f4..f1a75fff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,7 +22,7 @@ dependencies = [ "crossbeam-channel 0.3.9", "dirs", "fern", - "futures 0.3.13", + "futures 0.3.15", "gpio-cdev", "hex", "linux-embedded-hal", @@ -106,7 +106,7 @@ dependencies = [ "futures-core", "futures-sink", "log 0.4.14", - "pin-project 0.4.27", + "pin-project 0.4.28", "tokio 0.2.25", "tokio-util 0.3.1", ] @@ -123,8 +123,8 @@ dependencies = [ "actix-utils 1.0.6", "derive_more", "either", - "futures 0.3.13", - "http 0.2.3", + "futures 0.3.15", + "http 0.2.4", "log 0.4.14", "rustls 0.16.0", "tokio-rustls 0.12.3", @@ -183,7 +183,7 @@ dependencies = [ "futures-util", "fxhash", "h2 0.2.7", - "http 0.2.3", + "http 0.2.4", "httparse", "indexmap", "language-tags", @@ -191,7 +191,7 @@ dependencies = [ "log 0.4.14", "mime 0.3.16", "percent-encoding 2.1.0", - "pin-project 0.4.27", + "pin-project 0.4.28", "rand 0.7.3", "regex", "ring", @@ -211,7 +211,7 @@ checksum = "2a379b0639c293292d71defb8cc1f94c87b7705c904adf044338ad392df77c7a" dependencies = [ "actix-service", "actix-web", - "futures 0.3.13", + "futures 0.3.15", "serde", "serde_json", "time", @@ -224,7 +224,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ca8ce00b267af8ccebbd647de0d61e0674b6e61185cc7a592ff88772bed655" dependencies = [ "quote 1.0.9", - "syn 1.0.63", + "syn 1.0.73", ] [[package]] @@ -259,7 +259,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ad299af73649e1fc893e333ccf86f377751eb95ff875d095131574c6f43452c" dependencies = [ "bytestring", - "http 0.2.3", + "http 0.2.4", "log 0.4.14", "regex", "serde", @@ -297,7 +297,7 @@ dependencies = [ "mio-uds", "num_cpus", "slab", - "socket2", + "socket2 0.3.19", ] [[package]] @@ -307,7 +307,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0052435d581b5be835d11f4eb3bce417c8af18d87ddf8ace99f8e67e595882bb" dependencies = [ "futures-util", - "pin-project 0.4.27", + "pin-project 0.4.28", ] [[package]] @@ -321,7 +321,7 @@ dependencies = [ "actix-server", "actix-service", "log 0.4.14", - "socket2", + "socket2 0.3.19", ] [[package]] @@ -351,7 +351,7 @@ dependencies = [ "actix-utils 1.0.6", "derive_more", "either", - "futures 0.3.13", + "futures 0.3.15", "log 0.4.14", "rustls 0.16.0", "tokio-rustls 0.12.3", @@ -371,9 +371,9 @@ dependencies = [ "bitflags 1.2.1", "bytes 0.5.6", "either", - "futures 0.3.13", + "futures 0.3.15", "log 0.4.14", - "pin-project 0.4.27", + "pin-project 0.4.28", "slab", ] @@ -393,7 +393,7 @@ dependencies = [ "futures-sink", "futures-util", "log 0.4.14", - "pin-project 0.4.27", + "pin-project 0.4.28", "slab", ] @@ -419,19 +419,19 @@ dependencies = [ "bytes 0.5.6", "derive_more", "encoding_rs", - "futures 0.3.13", + "futures 0.3.15", "fxhash", "log 0.4.14", "mime 0.3.16", "net2", - "pin-project 0.4.27", + "pin-project 0.4.28", "regex", "rustls 0.16.0", "serde", "serde_json", "serde_urlencoded 0.6.1", "time", - "url 2.2.1", + "url 2.2.2", ] [[package]] @@ -440,9 +440,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a71bf475cbe07281d0b3696abb48212db118e7e23219f13596ce865235ff5766" dependencies = [ - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "syn 1.0.63", + "syn 1.0.73", ] [[package]] @@ -471,9 +471,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.14.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7" +checksum = "e7a2e47a1fbe209ee101dd6d61285226744c6c8d3c21c8dc878ba6cb9f467f3a" dependencies = [ "gimli", ] @@ -486,9 +486,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "0.7.15" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" dependencies = [ "memchr", ] @@ -502,12 +502,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "arrayref" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" - [[package]] name = "arrayvec" version = "0.4.12" @@ -517,12 +511,6 @@ dependencies = [ "nodrop", ] -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "async-channel" version = "1.6.1" @@ -536,16 +524,16 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb877970c7b440ead138f6321a3b5395d6061183af779340b65e20c0fede9146" +checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" dependencies = [ "async-task", "concurrent-queue", "fastrand", "futures-lite", "once_cell", - "vec-arena", + "slab", ] [[package]] @@ -577,29 +565,29 @@ dependencies = [ [[package]] name = "async-io" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9315f8f07556761c3e48fec2e6b276004acf426e6dc068b2c2251854d65ee0fd" +checksum = "4bbfd5cf2794b1e908ea8457e6c45f8f8f1f6ec5f74617bf4662623f47503c3b" dependencies = [ "concurrent-queue", "fastrand", "futures-lite", "libc", "log 0.4.14", - "nb-connect", "once_cell", "parking", "polling", - "vec-arena", + "slab", + "socket2 0.4.0", "waker-fn", "winapi 0.3.9", ] [[package]] name = "async-lock" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1996609732bde4a9988bc42125f55f2af5f3c36370e27c778d5191a4a1b63bfb" +checksum = "e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b" dependencies = [ "event-listener", ] @@ -615,9 +603,9 @@ dependencies = [ [[package]] name = "async-net" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06de475c85affe184648202401d7622afb32f0f74e02192857d0201a16defbe5" +checksum = "69b0a74e7f70af3c8cf1aa539edbd044795706659ac52b78a71dc1a205ecefdf" dependencies = [ "async-io", "blocking", @@ -627,15 +615,16 @@ dependencies = [ [[package]] name = "async-process" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef37b86e2fa961bae5a4d212708ea0154f904ce31d1a4a7f47e1bbc33a0c040b" +checksum = "a8f38756dd9ac84671c428afbf7c9f7495feff9ec5b0710f17100098e5b354ac" dependencies = [ "async-io", "blocking", "cfg-if 1.0.0", "event-listener", "futures-lite", + "libc", "once_cell", "signal-hook", "winapi 0.3.9", @@ -651,7 +640,7 @@ dependencies = [ "async-global-executor", "async-io", "async-lock", - "crossbeam-utils 0.8.3", + "crossbeam-utils 0.8.5", "futures-channel", "futures-core", "futures-io", @@ -662,7 +651,7 @@ dependencies = [ "memchr", "num_cpus", "once_cell", - "pin-project-lite 0.2.6", + "pin-project-lite 0.2.7", "pin-utils", "slab", "wasm-bindgen-futures", @@ -676,13 +665,13 @@ checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" [[package]] name = "async-trait" -version = "0.1.48" +version = "0.1.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36ea56748e10732c49404c153638a15ec3d6211ec5ff35d9bb20e13b93576adf" +checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722" dependencies = [ - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "syn 1.0.63", + "syn 1.0.73", ] [[package]] @@ -740,11 +729,12 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.56" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d117600f438b1707d4e4ae15d3595657288f8235a0eb593e80ecc98ab34e1bc" +checksum = "b7815ea54e4d821e791162e078acbebfd6d8c8939cd559c9335dceb1c8ca7282" dependencies = [ "addr2line", + "cc", "cfg-if 1.0.0", "libc", "miniz_oxide", @@ -781,11 +771,10 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bincode" -version = "1.3.2" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d175dfa69e619905c4c3cdb7c3c203fa3bdd5d51184e3afdb2742c0280493772" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" dependencies = [ - "byteorder", "serde", ] @@ -821,17 +810,6 @@ dependencies = [ "text_io", ] -[[package]] -name = "blake2b_simd" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" -dependencies = [ - "arrayref", - "arrayvec 0.5.2", - "constant_time_eq", -] - [[package]] name = "blocking" version = "1.0.2" @@ -883,15 +861,15 @@ checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" [[package]] name = "bumpalo" -version = "3.6.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" +checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" [[package]] name = "byteorder" -version = "1.3.4" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" @@ -933,18 +911,18 @@ checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" [[package]] name = "cast" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" +checksum = "57cdfa5d50aad6cb4d44dcab6101a7f79925bd59d82ca42f38a9856a28865374" dependencies = [ - "rustc_version 0.2.3", + "rustc_version 0.3.3", ] [[package]] name = "cc" -version = "1.0.67" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" +checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" [[package]] name = "cfg-if" @@ -1027,10 +1005,10 @@ dependencies = [ ] [[package]] -name = "constant_time_eq" -version = "0.1.5" +name = "convert_case" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "cookie" @@ -1102,12 +1080,12 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" +checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.3", + "crossbeam-utils 0.8.5", ] [[package]] @@ -1128,8 +1106,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" dependencies = [ "cfg-if 1.0.0", - "crossbeam-epoch 0.9.3", - "crossbeam-utils 0.8.3", + "crossbeam-epoch 0.9.5", + "crossbeam-utils 0.8.5", ] [[package]] @@ -1138,7 +1116,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" dependencies = [ - "arrayvec 0.4.12", + "arrayvec", "cfg-if 0.1.10", "crossbeam-utils 0.6.6", "lazy_static", @@ -1163,14 +1141,14 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12" +checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.3", + "crossbeam-utils 0.8.5", "lazy_static", - "memoffset 0.6.1", + "memoffset 0.6.4", "scopeguard 1.1.0", ] @@ -1208,11 +1186,10 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" +checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" dependencies = [ - "autocfg 1.0.1", "cfg-if 1.0.0", "lazy_static", ] @@ -1228,23 +1205,24 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8f45d9ad417bcef4817d614a501ab55cdd96a6fdb24f49aab89a54acfd66b19" +checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d" dependencies = [ "quote 1.0.9", - "syn 1.0.63", + "syn 1.0.73", ] [[package]] name = "derive_more" -version = "0.99.11" +version = "0.99.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c" +checksum = "5cc7b9cef1e351660e5443924e4f43ab25fbbed3e9a5f052df3677deb4d6b320" dependencies = [ - "proc-macro2 1.0.24", + "convert_case", + "proc-macro2 1.0.27", "quote 1.0.9", - "syn 1.0.63", + "syn 1.0.73", ] [[package]] @@ -1259,9 +1237,9 @@ dependencies = [ [[package]] name = "dirs-sys" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" dependencies = [ "libc", "redox_users", @@ -1270,9 +1248,9 @@ dependencies = [ [[package]] name = "dtoa" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d7ed2934d741c6b37e33e3832298e8850b53fd2d2bea03873375596c7cea4e" +checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" [[package]] name = "either" @@ -1282,9 +1260,9 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "embedded-hal" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa998ce59ec9765d15216393af37a58961ddcefb14c753b4816ba2191d865fcb" +checksum = "db184d3fa27bc7a2344250394c0264144dfe0bc81a4401801dcb964b8dd172ad" dependencies = [ "nb 0.1.3", "void", @@ -1306,9 +1284,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595" dependencies = [ "heck", - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "syn 1.0.63", + "syn 1.0.73", ] [[package]] @@ -1351,17 +1329,17 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "syn 1.0.63", + "syn 1.0.73", "synstructure", ] [[package]] name = "fastrand" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca5faf057445ce5c9d4329e382b2ce7ca38550ef3b73a5348362d5f24e0c7fe3" +checksum = "77b705829d1e87f762c2df6da140b26af5839e1033aa84aa5f56bb688e4e1bdb" dependencies = [ "instant", ] @@ -1445,9 +1423,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f55667319111d593ba876406af7c409c0ebb44dc4be6132a783ccf163ea14c1" +checksum = "0e7e43a803dae2fa37c1f6a8fe121e1f7bf9548b4dfc0522a42f34145dadfc27" dependencies = [ "futures-channel", "futures-core", @@ -1460,9 +1438,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939" +checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2" dependencies = [ "futures-core", "futures-sink", @@ -1470,9 +1448,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94" +checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1" [[package]] name = "futures-cpupool" @@ -1486,9 +1464,9 @@ dependencies = [ [[package]] name = "futures-executor" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891a4b7b96d84d5940084b2a37632dd65deeae662c114ceaa2c879629c9c0ad1" +checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79" dependencies = [ "futures-core", "futures-task", @@ -1497,55 +1475,57 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59" +checksum = "acc499defb3b348f8d8f3f66415835a9131856ff7714bf10dadfc4ec4bdb29a1" [[package]] name = "futures-lite" -version = "1.11.3" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4481d0cd0de1d204a4fa55e7d45f07b1d958abcb06714b3446438e2eff695fb" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" dependencies = [ "fastrand", "futures-core", "futures-io", "memchr", "parking", - "pin-project-lite 0.2.6", + "pin-project-lite 0.2.7", "waker-fn", ] [[package]] name = "futures-macro" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea405816a5139fb39af82c2beb921d52143f556038378d6db21183a5c37fbfb7" +checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121" dependencies = [ + "autocfg 1.0.1", "proc-macro-hack", - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "syn 1.0.63", + "syn 1.0.73", ] [[package]] name = "futures-sink" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3" +checksum = "a57bead0ceff0d6dde8f465ecd96c9338121bb7717d3e7b108059531870c4282" [[package]] name = "futures-task" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80" +checksum = "8a16bef9fc1a4dddb5bee51c989e3fbba26569cbb0e31f5b303c184e3dd33dae" [[package]] name = "futures-util" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1" +checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967" dependencies = [ + "autocfg 1.0.1", "futures-channel", "futures-core", "futures-io", @@ -1553,7 +1533,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.6", + "pin-project-lite 0.2.7", "pin-utils", "proc-macro-hack", "proc-macro-nested", @@ -1582,9 +1562,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if 1.0.0", "libc", @@ -1593,9 +1573,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" +checksum = "0e4075386626662786ddb0ec9081e7c7eeb1ba31951f447ca780ef9f5d568189" [[package]] name = "gloo-timers" @@ -1613,11 +1593,11 @@ dependencies = [ [[package]] name = "gpio-cdev" version = "0.4.0" -source = "git+https://github.com/rust-embedded/gpio-cdev?branch=master#246f5baaf1c64a6e0cb8dd651fd1625aa7d10815" +source = "git+https://github.com/rust-embedded/gpio-cdev?branch=master#48a39488db2196b6ed15337a7f6712db0880ba93" dependencies = [ "bitflags 1.2.1", "libc", - "nix 0.14.1", + "nix 0.20.0", ] [[package]] @@ -1649,7 +1629,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http 0.2.3", + "http 0.2.4", "indexmap", "slab", "tokio 0.2.25", @@ -1669,24 +1649,24 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.9.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" [[package]] name = "heck" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" dependencies = [ "unicode-segmentation", ] [[package]] name = "hermit-abi" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ "libc", ] @@ -1699,9 +1679,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "historian" -version = "4.0.3" +version = "4.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f653416eb756b69642a1f1498817970fafe409998a849622c27cc5b1b7df989c" +checksum = "cae74efdb3c09c2dfbba9351363eebae2ac129f8e07dba620747b80324917657" [[package]] name = "hostname" @@ -1727,9 +1707,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747" +checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" dependencies = [ "bytes 1.0.1", "fnv", @@ -1755,14 +1735,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" dependencies = [ "bytes 0.5.6", - "http 0.2.3", + "http 0.2.4", ] [[package]] name = "httparse" -version = "1.3.5" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "615caabe2c3160b313d52ccc905335f4ed5f10881dd63dc5699d47e90be85691" +checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68" [[package]] name = "httpdate" @@ -1811,13 +1791,13 @@ dependencies = [ "futures-core", "futures-util", "h2 0.2.7", - "http 0.2.3", + "http 0.2.4", "http-body 0.3.1", "httparse", "httpdate", "itoa", - "pin-project 1.0.5", - "socket2", + "pin-project 1.0.7", + "socket2 0.3.19", "tokio 0.2.25", "tower-service 0.3.1", "tracing", @@ -1899,9 +1879,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" dependencies = [ "matches", "unicode-bidi", @@ -1910,12 +1890,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.6.2" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" +checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" dependencies = [ "autocfg 1.0.1", - "hashbrown 0.9.1", + "hashbrown 0.11.2", ] [[package]] @@ -1943,7 +1923,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08f7eadeaf4b52700de180d147c4805f199854600b36faa963d91114827b2ffc" dependencies = [ "error-chain 0.8.1", - "socket2", + "socket2 0.3.19", "widestring 0.2.2", "winapi 0.3.9", "winreg 0.5.1", @@ -1955,7 +1935,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" dependencies = [ - "socket2", + "socket2 0.3.19", "widestring 0.4.3", "winapi 0.3.9", "winreg 0.6.2", @@ -1963,9 +1943,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" +checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" [[package]] name = "itoa" @@ -1975,9 +1955,9 @@ checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" [[package]] name = "js-sys" -version = "0.3.48" +version = "0.3.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc9f84f9b115ce7843d60706df1422a916680bfdfcbdb0447c5614ff9d7e4d78" +checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" dependencies = [ "wasm-bindgen", ] @@ -2015,9 +1995,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.88" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a" +checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" [[package]] name = "linked-hash-map" @@ -2059,9 +2039,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" +checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" dependencies = [ "scopeguard 1.1.0", ] @@ -2114,9 +2094,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.3.4" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" +checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" [[package]] name = "memoffset" @@ -2129,9 +2109,9 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.6.1" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" +checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" dependencies = [ "autocfg 1.0.1", ] @@ -2264,16 +2244,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" -[[package]] -name = "nb-connect" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670361df1bc2399ee1ff50406a0d422587dd3bb0da596e1978fe8e05dabddf4f" -dependencies = [ - "libc", - "socket2", -] - [[package]] name = "net2" version = "0.2.37" @@ -2325,6 +2295,18 @@ dependencies = [ "void", ] +[[package]] +name = "nix" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" +dependencies = [ + "bitflags 1.2.1", + "cc", + "cfg-if 1.0.0", + "libc", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -2476,21 +2458,24 @@ dependencies = [ [[package]] name = "object" -version = "0.23.0" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" +checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7" +dependencies = [ + "memchr", +] [[package]] name = "once_cell" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "openssl-probe" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" +checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" [[package]] name = "ordered-float" @@ -2566,7 +2551,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" dependencies = [ "instant", - "lock_api 0.4.2", + "lock_api 0.4.4", "parking_lot_core 0.8.3", ] @@ -2607,7 +2592,7 @@ dependencies = [ "cfg-if 1.0.0", "instant", "libc", - "redox_syscall 0.2.5", + "redox_syscall 0.2.9", "smallvec 1.6.1", "winapi 0.3.9", ] @@ -2633,6 +2618,15 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +[[package]] +name = "pest" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +dependencies = [ + "ucd-trie", +] + [[package]] name = "phf" version = "0.7.24" @@ -2686,42 +2680,42 @@ dependencies = [ [[package]] name = "pin-project" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffbc8e94b38ea3d2d8ba92aea2983b503cd75d0888d75b86bb37970b5698e15" +checksum = "918192b5c59119d51e0cd221f4d49dde9112824ba717369e903c97d076083d0f" dependencies = [ - "pin-project-internal 0.4.27", + "pin-project-internal 0.4.28", ] [[package]] name = "pin-project" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96fa8ebb90271c4477f144354485b8068bd8f6b78b428b01ba892ca26caf0b63" +checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4" dependencies = [ - "pin-project-internal 1.0.5", + "pin-project-internal 1.0.7", ] [[package]] name = "pin-project-internal" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895" +checksum = "3be26700300be6d9d23264c73211d8190e755b6b5ca7a1b28230025511b52a5e" dependencies = [ - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "syn 1.0.63", + "syn 1.0.73", ] [[package]] name = "pin-project-internal" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b" +checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f" dependencies = [ - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "syn 1.0.63", + "syn 1.0.73", ] [[package]] @@ -2732,9 +2726,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" +checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" [[package]] name = "pin-utils" @@ -2744,14 +2738,14 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "polling" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a7bc6b2a29e632e45451c941832803a18cce6781db04de8a04696cdca8bde4" +checksum = "92341d779fa34ea8437ef4d82d440d5e1ce3f3ff7f824aa64424cd481f9a1f25" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", "log 0.4.14", - "wepoll-sys", + "wepoll-ffi", "winapi 0.3.9", ] @@ -2768,10 +2762,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "syn 1.0.63", - "version_check 0.9.2", + "syn 1.0.73", + "version_check 0.9.3", ] [[package]] @@ -2780,9 +2774,9 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "version_check 0.9.2", + "version_check 0.9.3", ] [[package]] @@ -2808,11 +2802,11 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.24" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" dependencies = [ - "unicode-xid 0.2.1", + "unicode-xid 0.2.2", ] [[package]] @@ -2821,8 +2815,8 @@ version = "1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95b4ce31ff0a27d93c8de1849cf58162283752f065a90d508f1105fa6c9a213f" dependencies = [ - "idna 0.2.2", - "url 2.2.1", + "idna 0.2.3", + "url 2.2.2", ] [[package]] @@ -2846,7 +2840,7 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", ] [[package]] @@ -2896,14 +2890,14 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" dependencies = [ "libc", - "rand_chacha 0.3.0", - "rand_core 0.6.2", - "rand_hc 0.3.0", + "rand_chacha 0.3.1", + "rand_core 0.6.3", + "rand_hc 0.3.1", ] [[package]] @@ -2928,12 +2922,12 @@ dependencies = [ [[package]] name = "rand_chacha" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.2", + "rand_core 0.6.3", ] [[package]] @@ -2962,11 +2956,11 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.2", + "getrandom 0.2.3", ] [[package]] @@ -2989,11 +2983,11 @@ dependencies = [ [[package]] name = "rand_hc" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" dependencies = [ - "rand_core 0.6.2", + "rand_core 0.6.3", ] [[package]] @@ -3051,9 +3045,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" +checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" dependencies = [ "autocfg 1.0.1", "crossbeam-deque 0.8.0", @@ -3063,13 +3057,13 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.9.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" +checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" dependencies = [ - "crossbeam-channel 0.5.0", + "crossbeam-channel 0.5.1", "crossbeam-deque 0.8.0", - "crossbeam-utils 0.8.3", + "crossbeam-utils 0.8.5", "lazy_static", "num_cpus", ] @@ -3091,41 +3085,39 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" -version = "0.2.5" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" +checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" dependencies = [ "bitflags 1.2.1", ] [[package]] name = "redox_users" -version = "0.3.5" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ - "getrandom 0.1.16", - "redox_syscall 0.1.57", - "rust-argon2", + "getrandom 0.2.3", + "redox_syscall 0.2.9", ] [[package]] name = "regex" -version = "1.4.3" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" dependencies = [ "aho-corasick", "memchr", "regex-syntax", - "thread_local", ] [[package]] name = "regex-syntax" -version = "0.6.22" +version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "remove_dir_all" @@ -3183,7 +3175,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "http 0.2.3", + "http 0.2.4", "http-body 0.3.1", "hyper 0.13.10", "hyper-rustls 0.21.0", @@ -3194,13 +3186,13 @@ dependencies = [ "mime 0.3.16", "mime_guess 2.0.3", "percent-encoding 2.1.0", - "pin-project-lite 0.2.6", + "pin-project-lite 0.2.7", "rustls 0.18.1", "serde", "serde_urlencoded 0.7.0", "tokio 0.2.25", "tokio-rustls 0.14.1", - "url 2.2.1", + "url 2.2.2", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -3220,9 +3212,9 @@ dependencies = [ [[package]] name = "retry" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c15ef4789108d066d7fd85dcec330eab9b8e51244275922a9b7161afc4f46dda" +checksum = "d0ee4a654b43dd7e3768be7a1c0fc20e90f0a84b72a60ffb6c11e1cae2545c2e" dependencies = [ "rand 0.7.3", ] @@ -3242,23 +3234,11 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "rust-argon2" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" -dependencies = [ - "base64 0.13.0", - "blake2b_simd", - "constant_time_eq", - "crossbeam-utils 0.8.3", -] - [[package]] name = "rustc-demangle" -version = "0.1.18" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" +checksum = "dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49" [[package]] name = "rustc-serialize" @@ -3284,6 +3264,15 @@ dependencies = [ "semver 0.9.0", ] +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + [[package]] name = "rustls" version = "0.16.0" @@ -3352,9 +3341,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "sct" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" +checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" dependencies = [ "ring", "untrusted", @@ -3393,7 +3382,16 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ - "semver-parser", + "semver-parser 0.7.0", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser 0.10.2", ] [[package]] @@ -3402,10 +3400,19 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + [[package]] name = "sensor_value" version = "0.1.0" -source = "git+https://github.com/dskleingeld/sensor_central.git?branch=boolean-fields#ad5d48c43c827f421f573bf57e216a3f4440a0c9" +source = "git+https://github.com/dskleingeld/sensor_central.git?branch=main#eb9beee9e43682be52d078188d572c7b0fad9a0f" dependencies = [ "bitspec", "serde", @@ -3413,9 +3420,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.124" +version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f" +checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" dependencies = [ "serde_derive", ] @@ -3432,13 +3439,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.124" +version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b" +checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" dependencies = [ - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "syn 1.0.63", + "syn 1.0.73", ] [[package]] @@ -3473,7 +3480,7 @@ dependencies = [ "dtoa", "itoa", "serde", - "url 2.2.1", + "url 2.2.2", ] [[package]] @@ -3508,9 +3515,9 @@ checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" [[package]] name = "signal-hook" -version = "0.3.6" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7f3f92a1da3d6b1d32245d0cbcbbab0cfc45996d8df619c42bccfa6d2bbb5f" +checksum = "470c5a6397076fae0094aaf06a08e6ba6f37acb77d3b1b91ea92b4d6c8650c39" dependencies = [ "libc", "signal-hook-registry", @@ -3518,9 +3525,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" dependencies = [ "libc", ] @@ -3533,9 +3540,9 @@ checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" [[package]] name = "slab" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" [[package]] name = "sled" @@ -3544,8 +3551,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d0132f3e393bcb7390c60bb45769498cf4550bcb7a21d7f95c02b69f6362cdc" dependencies = [ "crc32fast", - "crossbeam-epoch 0.9.3", - "crossbeam-utils 0.8.3", + "crossbeam-epoch 0.9.5", + "crossbeam-utils 0.8.5", "fs2", "fxhash", "libc", @@ -3597,6 +3604,16 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "socket2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2" +dependencies = [ + "libc", + "winapi 0.3.9", +] + [[package]] name = "spidev" version = "0.3.0" @@ -3654,9 +3671,9 @@ checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "syn 1.0.63", + "syn 1.0.73", ] [[package]] @@ -3672,13 +3689,13 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.63" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd9bc7ccc2688b3344c2f48b9b546648b25ce0b20fc717ee7fa7981a8ca9717" +checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" dependencies = [ - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "unicode-xid 0.2.1", + "unicode-xid 0.2.2", ] [[package]] @@ -3687,10 +3704,10 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "syn 1.0.63", - "unicode-xid 0.2.1", + "syn 1.0.73", + "unicode-xid 0.2.2", ] [[package]] @@ -3709,7 +3726,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb29fb11ef40c839c1c6b4e9c2ec4f357f9f674491e9df5a8c94f8cc2005f860" dependencies = [ "bytes 0.5.6", - "futures 0.3.13", + "futures 0.3.15", "hyper 0.13.10", "hyper-rustls 0.19.1", "multipart", @@ -3740,8 +3757,8 @@ checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ "cfg-if 1.0.0", "libc", - "rand 0.8.3", - "redox_syscall 0.2.5", + "rand 0.8.4", + "redox_syscall 0.2.9", "remove_dir_all", "winapi 0.3.9", ] @@ -3763,31 +3780,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d" dependencies = [ - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "syn 1.0.63", -] - -[[package]] -name = "thread_local" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" -dependencies = [ - "once_cell", + "syn 1.0.73", ] [[package]] @@ -3812,9 +3820,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023" +checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" dependencies = [ "tinyvec_macros", ] @@ -4139,33 +4147,33 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f" +checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d" dependencies = [ "cfg-if 1.0.0", "log 0.4.14", - "pin-project-lite 0.2.6", + "pin-project-lite 0.2.7", "tracing-attributes", "tracing-core", ] [[package]] name = "tracing-attributes" -version = "0.1.13" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a9bd1db7706f2373a190b0d067146caa39350c486f3d455b0e33b431f94c07" +checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2" dependencies = [ - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "syn 1.0.63", + "syn 1.0.73", ] [[package]] name = "tracing-core" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f" +checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052" dependencies = [ "lazy_static", ] @@ -4176,7 +4184,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ - "pin-project 1.0.5", + "pin-project 1.0.7", "tracing", ] @@ -4194,7 +4202,7 @@ dependencies = [ "log 0.4.14", "rand 0.5.6", "smallvec 0.6.14", - "socket2", + "socket2 0.3.19", "tokio-executor", "tokio-io", "tokio-reactor", @@ -4218,7 +4226,7 @@ dependencies = [ "log 0.4.14", "rand 0.5.6", "smallvec 0.6.14", - "socket2", + "socket2 0.3.19", "tokio-executor", "tokio-io", "tokio-reactor", @@ -4237,15 +4245,15 @@ dependencies = [ "async-trait", "enum-as-inner", "failure", - "futures 0.3.13", - "idna 0.2.2", + "futures 0.3.15", + "idna 0.2.3", "lazy_static", "log 0.4.14", "rand 0.7.3", "smallvec 1.6.1", - "socket2", + "socket2 0.3.19", "tokio 0.2.25", - "url 2.2.1", + "url 2.2.2", ] [[package]] @@ -4275,7 +4283,7 @@ checksum = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f" dependencies = [ "cfg-if 0.1.10", "failure", - "futures 0.3.13", + "futures 0.3.15", "ipconfig 0.2.2", "lazy_static", "log 0.4.14", @@ -4301,6 +4309,12 @@ dependencies = [ "cfg-if 0.1.10", ] +[[package]] +name = "ucd-trie" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" + [[package]] name = "unicase" version = "1.4.2" @@ -4316,23 +4330,23 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" dependencies = [ - "version_check 0.9.2", + "version_check 0.9.3", ] [[package]] name = "unicode-bidi" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" dependencies = [ "matches", ] [[package]] name = "unicode-normalization" -version = "0.1.17" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" dependencies = [ "tinyvec", ] @@ -4357,9 +4371,9 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "untrusted" @@ -4380,12 +4394,12 @@ dependencies = [ [[package]] name = "url" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b" +checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" dependencies = [ "form_urlencoded", - "idna 0.2.2", + "idna 0.2.3", "matches", "percent-encoding 2.1.0", ] @@ -4415,9 +4429,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae" dependencies = [ "nom", - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "syn 1.0.63", + "syn 1.0.73", ] [[package]] @@ -4432,19 +4446,14 @@ dependencies = [ [[package]] name = "value-bag" -version = "1.0.0-alpha.6" +version = "1.0.0-alpha.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b676010e055c99033117c2343b33a40a30b91fecd6c49055ac9cd2d6c305ab1" +checksum = "dd320e1520f94261153e96f7534476ad869c14022aee1e59af7c778075d840ae" dependencies = [ "ctor", + "version_check 0.9.3", ] -[[package]] -name = "vec-arena" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eafc1b9b2dfc6f5529177b62cf806484db55b32dc7c9658a118e11bbeb33061d" - [[package]] name = "vec_map" version = "0.8.2" @@ -4459,9 +4468,9 @@ checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" [[package]] name = "version_check" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" [[package]] name = "void" @@ -4510,9 +4519,9 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" -version = "0.2.71" +version = "0.2.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee1280240b7c461d6a0071313e08f34a60b0365f14260362e5a2b17d1d31aa7" +checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" dependencies = [ "cfg-if 1.0.0", "serde", @@ -4522,24 +4531,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.71" +version = "0.2.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b7d8b6942b8bb3a9b0e73fc79b98095a27de6fa247615e59d096754a3bc2aa8" +checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" dependencies = [ "bumpalo", "lazy_static", "log 0.4.14", - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "syn 1.0.63", + "syn 1.0.73", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.21" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e67a5806118af01f0d9045915676b22aaebecf4178ae7021bc171dab0b897ab" +checksum = "5fba7978c679d53ce2d0ac80c8c175840feb849a161664365d1287b41f2e67f1" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -4549,9 +4558,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.71" +version = "0.2.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ac38da8ef716661f0f36c0d8320b89028efe10c7c0afde65baffb496ce0d3b" +checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" dependencies = [ "quote 1.0.9", "wasm-bindgen-macro-support", @@ -4559,28 +4568,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.71" +version = "0.2.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e" +checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" dependencies = [ - "proc-macro2 1.0.24", + "proc-macro2 1.0.27", "quote 1.0.9", - "syn 1.0.63", + "syn 1.0.73", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.71" +version = "0.2.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d6f8ec44822dd71f5f221a5847fb34acd9060535c1211b70a05844c0f6383b1" +checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" [[package]] name = "web-sys" -version = "0.3.48" +version = "0.3.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b" +checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582" dependencies = [ "js-sys", "wasm-bindgen", @@ -4615,10 +4624,10 @@ dependencies = [ ] [[package]] -name = "wepoll-sys" -version = "3.0.1" +name = "wepoll-ffi" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb14dea929042224824779fbc82d9fab8d2e6d3cbc0ac404de8edf489e77ff" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" dependencies = [ "cc", ] diff --git a/Cargo.toml b/Cargo.toml index 87064246..48f1cb70 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ thiserror = "1.0" log = "0.4" fern = { version = "0.5.6", features = ["colored"] } -sensor_value = { git = "https://github.com/dskleingeld/sensor_central.git", branch = "boolean-fields" } +sensor_value = { git = "https://github.com/dskleingeld/sensor_central.git", branch = "main" } gpio-cdev = { git = "https://github.com/rust-embedded/gpio-cdev", branch = "master" } nix = "0.17" diff --git a/src/input/bot/mod.rs b/src/input/bot/mod.rs index e79c9940..efa6b54c 100644 --- a/src/input/bot/mod.rs +++ b/src/input/bot/mod.rs @@ -225,13 +225,13 @@ pub async fn send_text>( //Ports currently supported for Webhooks: 443, 80, 88, 8443. pub async fn set_webhook(domain: &str, token: &str, port: u16) -> Result<(), Error> { let url = format!("https://api.telegram.org/bot{}/setWebhook", token); - let webhook_url = format!("{}:{}/{}", domain, port, token); let params = [("url", &webhook_url)]; let client = reqwest::Client::new(); let res = client.post(url.as_str()).form(¶ms).send().await?; if res.status() != reqwest::StatusCode::OK { + error!("could not set webhook: {:?}", res); Err(Error::CouldNotSetWebhook) } else { info!("set webhook to: {}", webhook_url); diff --git a/src/main.rs b/src/main.rs index 686b53fe..c8d14ffa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,10 +17,10 @@ mod errors; #[structopt(name = "homeautomation")] struct Opt { /// port to bind to and listen for traffic - #[structopt(short = "p", long = "port", default_value = "433")] + #[structopt(short = "p", long = "port", default_value = "443")] port: u16, /// port to which telegram bot traffic should be send - #[structopt(short = "e", long = "external-port", default_value = "433")] + #[structopt(short = "e", long = "external-port", default_value = "443")] external_port: u16, /// telegram bot token #[structopt(short = "t", long = "token")] From 897551dc03875605b17a5433f0e7475fde520280 Mon Sep 17 00:00:00 2001 From: dskleingeld <11743287+dskleingeld@users.noreply.github.com> Date: Thu, 8 Jul 2021 02:59:12 +0200 Subject: [PATCH 075/687] make sure lights respond even if playlist not present --- src/controller/state/wakeup.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/controller/state/wakeup.rs b/src/controller/state/wakeup.rs index 8cfba628..bf3021e4 100644 --- a/src/controller/state/wakeup.rs +++ b/src/controller/state/wakeup.rs @@ -84,7 +84,9 @@ impl WakeUp { mods.lighting = false; mods.mpd = false; - Self::setup_playlist()?; + if let Err(e) = Self::setup_playlist() { + log::error!("could not set up playlist: {}", e); + } sys.lights.set_all_on_ct(0, CT_BEGIN)?; Ok(Box::new(Self { From be4386d43635635e53f8381d8adeb5698fa57978 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 25 Nov 2022 13:14:13 +0100 Subject: [PATCH 076/687] remove quiet state, compiled time env for command api login --- src/controller/mod.rs | 1 - src/controller/state/mod.rs | 2 -- src/input/bot/mod.rs | 4 ++-- src/input/web_api/mod.rs | 13 ++----------- 4 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/controller/mod.rs b/src/controller/mod.rs index 6e07b22a..f01134f4 100644 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -231,7 +231,6 @@ fn change_state( State::WakeUp => state::WakeUp::setup(mods, system), State::Sleep => state::Sleep::setup(mods, system), State::Silent => state::Silent::setup(mods, system), - State::Quiet => state::Quiet::setup(mods, system), State::Off => state::Off::setup(mods, system), }; diff --git a/src/controller/state/mod.rs b/src/controller/state/mod.rs index f7819f28..fb6e671a 100644 --- a/src/controller/state/mod.rs +++ b/src/controller/state/mod.rs @@ -5,7 +5,6 @@ use serde::{Deserialize, Serialize}; mod lightloop; mod normal; mod off; -mod quiet; mod silent; mod sleep; mod wakeup; @@ -13,7 +12,6 @@ mod wakeup; pub use lightloop::LightLoop; pub use normal::Normal; pub use off::Off; -pub use quiet::Quiet; pub use silent::Silent; pub use sleep::Sleep; pub use wakeup::{WakeUp, WakeUpStateError}; diff --git a/src/input/bot/mod.rs b/src/input/bot/mod.rs index efa6b54c..9f3ddc17 100644 --- a/src/input/bot/mod.rs +++ b/src/input/bot/mod.rs @@ -226,7 +226,7 @@ pub async fn send_text>( pub async fn set_webhook(domain: &str, token: &str, port: u16) -> Result<(), Error> { let url = format!("https://api.telegram.org/bot{}/setWebhook", token); - let params = [("url", &webhook_url)]; + let params = [("url", &url)]; let client = reqwest::Client::new(); let res = client.post(url.as_str()).form(¶ms).send().await?; @@ -234,7 +234,7 @@ pub async fn set_webhook(domain: &str, token: &str, port: u16) -> Result<(), Err error!("could not set webhook: {:?}", res); Err(Error::CouldNotSetWebhook) } else { - info!("set webhook to: {}", webhook_url); + info!("set webhook to: {}", url); Ok(()) } } diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index 77624c55..e8fb641e 100644 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -7,7 +7,6 @@ use actix_web::{HttpRequest, HttpResponse}; mod wakeup; mod commands; -mod logins; mod music; pub mod server; @@ -15,16 +14,8 @@ use server::State; fn authenticated(auth: BasicAuth) -> bool { let username = auth.user_id(); - if let Some(password) = auth.password() { - logins::LIST - .iter() - .filter(|x| x.username == username) - .filter(|x| x.password == password) - .next() - .is_some() - } else { - false - } + let password = auth.password() ; + username == env!("CMD_API_USERNAME") && password == env!("COMMAND_API_PASSWORD") } fn make_auth_error() -> HttpResponse { From b9e6262033c275d2eb292d99b153eb18af71b7a4 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 27 Nov 2022 23:50:35 +0100 Subject: [PATCH 077/687] fixed type and compile errors --- Cargo.lock | 1484 ++++++++++++++++++-------------- src/controller/mod.rs | 4 +- src/controller/state/mod.rs | 1 - src/controller/state/normal.rs | 10 +- src/input/bot/set_alarm.rs | 5 +- src/input/jobs/wakeup.rs | 12 +- src/input/web_api/mod.rs | 6 +- 7 files changed, 853 insertions(+), 669 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f1a75fff..d6c39478 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "HomeAutomation" version = "0.1.0" @@ -22,11 +24,11 @@ dependencies = [ "crossbeam-channel 0.3.9", "dirs", "fern", - "futures 0.3.15", + "futures 0.3.25", "gpio-cdev", "hex", "linux-embedded-hal", - "log 0.4.14", + "log 0.4.17", "mpd", "nix 0.17.0", "num 0.2.1", @@ -57,14 +59,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c616db5fa4b0c40702fb75201c2af7f8aa8f3a2e2c1dda3b0655772aa949666" dependencies = [ "actix_derive", - "bitflags 1.2.1", + "bitflags 1.3.2", "bytes 0.4.12", "crossbeam-channel 0.3.9", "failure", "fnv", "futures 0.1.31", "libc", - "log 0.4.14", + "log 0.4.17", "parking_lot 0.7.1", "smallvec 0.6.14", "tokio 0.1.22", @@ -86,11 +88,11 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09e55f0a5c2ca15795035d90c46bd0e73a5123b72f68f12596d6ba5282051380" dependencies = [ - "bitflags 1.2.1", + "bitflags 1.3.2", "bytes 0.5.6", "futures-core", "futures-sink", - "log 0.4.14", + "log 0.4.17", "tokio 0.2.25", "tokio-util 0.2.0", ] @@ -101,12 +103,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78d1833b3838dbe990df0f1f87baf640cf6146e898166afe401839d1b001e570" dependencies = [ - "bitflags 1.2.1", + "bitflags 1.3.2", "bytes 0.5.6", "futures-core", "futures-sink", - "log 0.4.14", - "pin-project 0.4.28", + "log 0.4.17", + "pin-project 0.4.30", "tokio 0.2.25", "tokio-util 0.3.1", ] @@ -123,9 +125,9 @@ dependencies = [ "actix-utils 1.0.6", "derive_more", "either", - "futures 0.3.15", - "http 0.2.4", - "log 0.4.14", + "futures 0.3.25", + "http 0.2.8", + "log 0.4.17", "rustls 0.16.0", "tokio-rustls 0.12.3", "trust-dns-proto 0.18.0-alpha.2", @@ -142,15 +144,15 @@ dependencies = [ "actix-http", "actix-service", "actix-web", - "bitflags 1.2.1", + "bitflags 1.3.2", "bytes 0.5.6", "derive_more", "futures-core", "futures-util", - "log 0.4.14", + "log 0.4.17", "mime 0.3.16", - "mime_guess 2.0.3", - "percent-encoding 2.1.0", + "mime_guess 2.0.4", + "percent-encoding 2.2.0", "v_htmlescape", ] @@ -168,7 +170,7 @@ dependencies = [ "actix-tls", "actix-utils 1.0.6", "base64 0.11.0", - "bitflags 1.2.1", + "bitflags 1.3.2", "brotli2", "bytes 0.5.6", "chrono", @@ -183,15 +185,15 @@ dependencies = [ "futures-util", "fxhash", "h2 0.2.7", - "http 0.2.4", + "http 0.2.8", "httparse", "indexmap", "language-tags", "lazy_static", - "log 0.4.14", + "log 0.4.17", "mime 0.3.16", - "percent-encoding 2.1.0", - "pin-project 0.4.28", + "percent-encoding 2.2.0", + "pin-project 0.4.30", "rand 0.7.3", "regex", "ring", @@ -211,7 +213,7 @@ checksum = "2a379b0639c293292d71defb8cc1f94c87b7705c904adf044338ad392df77c7a" dependencies = [ "actix-service", "actix-web", - "futures 0.3.15", + "futures 0.3.25", "serde", "serde_json", "time", @@ -223,8 +225,8 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ca8ce00b267af8ccebbd647de0d61e0674b6e61185cc7a592ff88772bed655" dependencies = [ - "quote 1.0.9", - "syn 1.0.73", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -236,7 +238,7 @@ dependencies = [ "actix", "bytes 0.4.12", "futures 0.1.31", - "log 0.4.14", + "log 0.4.17", "mio", "net2", "num_cpus", @@ -259,8 +261,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ad299af73649e1fc893e333ccf86f377751eb95ff875d095131574c6f43452c" dependencies = [ "bytestring", - "http 0.2.4", - "log 0.4.14", + "http 0.2.8", + "log 0.4.17", "regex", "serde", ] @@ -276,7 +278,7 @@ dependencies = [ "copyless", "futures-channel", "futures-util", - "smallvec 1.6.1", + "smallvec 1.10.0", "tokio 0.2.25", ] @@ -292,7 +294,7 @@ dependencies = [ "actix-utils 2.0.0", "futures-channel", "futures-util", - "log 0.4.14", + "log 0.4.17", "mio", "mio-uds", "num_cpus", @@ -307,7 +309,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0052435d581b5be835d11f4eb3bce417c8af18d87ddf8ace99f8e67e595882bb" dependencies = [ "futures-util", - "pin-project 0.4.28", + "pin-project 0.4.30", ] [[package]] @@ -320,7 +322,7 @@ dependencies = [ "actix-rt", "actix-server", "actix-service", - "log 0.4.14", + "log 0.4.17", "socket2 0.3.19", ] @@ -333,9 +335,9 @@ dependencies = [ "derive_more", "futures-channel", "lazy_static", - "log 0.4.14", + "log 0.4.17", "num_cpus", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "threadpool", ] @@ -351,8 +353,8 @@ dependencies = [ "actix-utils 1.0.6", "derive_more", "either", - "futures 0.3.15", - "log 0.4.14", + "futures 0.3.25", + "log 0.4.17", "rustls 0.16.0", "tokio-rustls 0.12.3", "webpki", @@ -368,12 +370,12 @@ dependencies = [ "actix-codec 0.2.0", "actix-rt", "actix-service", - "bitflags 1.2.1", + "bitflags 1.3.2", "bytes 0.5.6", "either", - "futures 0.3.15", - "log 0.4.14", - "pin-project 0.4.28", + "futures 0.3.25", + "log 0.4.17", + "pin-project 0.4.30", "slab", ] @@ -386,14 +388,14 @@ dependencies = [ "actix-codec 0.3.0", "actix-rt", "actix-service", - "bitflags 1.2.1", + "bitflags 1.3.2", "bytes 0.5.6", "either", "futures-channel", "futures-sink", "futures-util", - "log 0.4.14", - "pin-project 0.4.28", + "log 0.4.17", + "pin-project 0.4.30", "slab", ] @@ -419,19 +421,19 @@ dependencies = [ "bytes 0.5.6", "derive_more", "encoding_rs", - "futures 0.3.15", + "futures 0.3.25", "fxhash", - "log 0.4.14", + "log 0.4.17", "mime 0.3.16", "net2", - "pin-project 0.4.28", + "pin-project 0.4.30", "regex", "rustls 0.16.0", "serde", "serde_json", "serde_urlencoded 0.6.1", "time", - "url 2.2.2", + "url 2.3.1", ] [[package]] @@ -440,9 +442,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a71bf475cbe07281d0b3696abb48212db118e7e23219f13596ce865235ff5766" dependencies = [ - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -471,9 +473,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.15.2" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a2e47a1fbe209ee101dd6d61285226744c6c8d3c21c8dc878ba6cb9f467f3a" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" dependencies = [ "gimli", ] @@ -486,18 +488,27 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "ansi_term" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ "winapi 0.3.9", ] @@ -513,113 +524,106 @@ dependencies = [ [[package]] name = "async-channel" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" +checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28" dependencies = [ - "concurrent-queue", + "concurrent-queue 1.2.4", "event-listener", "futures-core", ] [[package]] name = "async-executor" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" dependencies = [ + "async-lock", "async-task", - "concurrent-queue", + "concurrent-queue 2.0.0", "fastrand", "futures-lite", - "once_cell", "slab", ] [[package]] name = "async-fs" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b3ca4f8ff117c37c278a2f7415ce9be55560b846b5bc4412aaa5d29c1c3dae2" +checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" dependencies = [ "async-lock", + "autocfg 1.1.0", "blocking", "futures-lite", ] [[package]] name = "async-global-executor" -version = "2.0.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6" +checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" dependencies = [ "async-channel", "async-executor", "async-io", - "async-mutex", + "async-lock", "blocking", "futures-lite", - "num_cpus", "once_cell", ] [[package]] name = "async-io" -version = "1.4.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bbfd5cf2794b1e908ea8457e6c45f8f8f1f6ec5f74617bf4662623f47503c3b" +checksum = "e8121296a9f05be7f34aa4196b1747243b3b62e048bb7906f644f3fbfc490cf7" dependencies = [ - "concurrent-queue", - "fastrand", + "async-lock", + "autocfg 1.1.0", + "concurrent-queue 1.2.4", "futures-lite", "libc", - "log 0.4.14", - "once_cell", + "log 0.4.17", "parking", "polling", "slab", - "socket2 0.4.0", + "socket2 0.4.7", "waker-fn", "winapi 0.3.9", ] [[package]] name = "async-lock" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-mutex" -version = "1.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" dependencies = [ "event-listener", + "futures-lite", ] [[package]] name = "async-net" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b0a74e7f70af3c8cf1aa539edbd044795706659ac52b78a71dc1a205ecefdf" +checksum = "4051e67316bc7eff608fe723df5d32ed639946adcd69e07df41fd42a7b411f1f" dependencies = [ "async-io", + "autocfg 1.1.0", "blocking", - "fastrand", "futures-lite", ] [[package]] name = "async-process" -version = "1.1.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f38756dd9ac84671c428afbf7c9f7495feff9ec5b0710f17100098e5b354ac" +checksum = "02111fd8655a613c25069ea89fc8d9bb89331fa77486eb3bc059ee757cfa481c" dependencies = [ "async-io", + "autocfg 1.1.0", "blocking", "cfg-if 1.0.0", "event-listener", @@ -632,26 +636,25 @@ dependencies = [ [[package]] name = "async-std" -version = "1.9.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f06685bad74e0570f5213741bea82158279a4103d988e57bfada11ad230341" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" dependencies = [ "async-channel", "async-global-executor", "async-io", "async-lock", - "crossbeam-utils 0.8.5", + "crossbeam-utils 0.8.14", "futures-channel", "futures-core", "futures-io", "futures-lite", "gloo-timers", "kv-log-macro", - "log 0.4.14", + "log 0.4.17", "memchr", - "num_cpus", "once_cell", - "pin-project-lite 0.2.7", + "pin-project-lite 0.2.9", "pin-utils", "slab", "wasm-bindgen-futures", @@ -659,19 +662,19 @@ dependencies = [ [[package]] name = "async-task" -version = "4.0.3" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" +checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" [[package]] name = "async-trait" -version = "0.1.50" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722" +checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" dependencies = [ - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -693,15 +696,18 @@ dependencies = [ [[package]] name = "autocfg" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" +dependencies = [ + "autocfg 1.1.0", +] [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "awc" @@ -717,9 +723,9 @@ dependencies = [ "bytes 0.5.6", "derive_more", "futures-core", - "log 0.4.14", + "log 0.4.17", "mime 0.3.16", - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", "rand 0.7.3", "rustls 0.16.0", "serde", @@ -729,15 +735,15 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.60" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7815ea54e4d821e791162e078acbebfd6d8c8939cd559c9335dceb1c8ca7282" +checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" dependencies = [ "addr2line", "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide", + "miniz_oxide 0.5.4", "object", "rustc-demangle", ] @@ -765,9 +771,9 @@ checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" [[package]] name = "base64" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "bincode" @@ -792,16 +798,16 @@ checksum = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitspec" version = "1.0.0" source = "git+https://github.com/dskleingeld/bitspec?branch=bool-fields#65e92b1ad3d3900a634cc6828785ed4054c83985" dependencies = [ - "log 0.4.14", + "log 0.4.17", "num 0.3.1", "rand 0.5.6", "serde", @@ -812,9 +818,9 @@ dependencies = [ [[package]] name = "blocking" -version = "1.0.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e170dbede1f740736619b776d7251cb1b9095c435c34d8ca9f57fcd2f335e9" +checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc" dependencies = [ "async-channel", "async-task", @@ -861,9 +867,9 @@ checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" [[package]] name = "bumpalo" -version = "3.7.0" +version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "byteorder" @@ -890,39 +896,39 @@ checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" [[package]] name = "bytes" -version = "1.0.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" [[package]] name = "bytestring" -version = "1.0.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90706ba19e97b90786e19dc0d5e2abd80008d99d4c0c5d1ad0b5e72cec7c494d" +checksum = "f7f83e57d9154148e355404702e2694463241880b939570d7c97c014da7a69a1" dependencies = [ - "bytes 1.0.1", + "bytes 1.3.0", ] [[package]] name = "cache-padded" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" +checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" [[package]] name = "cast" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57cdfa5d50aad6cb4d44dcab6101a7f79925bd59d82ca42f38a9856a28865374" +checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" dependencies = [ - "rustc_version 0.3.3", + "rustc_version 0.4.0", ] [[package]] name = "cc" -version = "1.0.68" +version = "1.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" +checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" [[package]] name = "cfg-if" @@ -938,15 +944,17 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ - "libc", + "iana-time-zone", + "js-sys", "num-integer", "num-traits", "serde", "time", + "wasm-bindgen", "winapi 0.3.9", ] @@ -962,13 +970,13 @@ dependencies = [ [[package]] name = "clap" -version = "2.33.3" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "ansi_term", "atty", - "bitflags 1.2.1", + "bitflags 1.3.2", "strsim", "textwrap", "unicode-width", @@ -981,7 +989,17 @@ version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" dependencies = [ - "bitflags 1.2.1", + "bitflags 1.3.2", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", ] [[package]] @@ -997,13 +1015,22 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "1.2.2" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" +checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" dependencies = [ "cache-padded", ] +[[package]] +name = "concurrent-queue" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7bef69dc86e3c610e4e7aed41035e2a7ed12e72dd7530f61327a6579a4390b" +dependencies = [ + "crossbeam-utils 0.8.14", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -1029,7 +1056,7 @@ dependencies = [ "cookie", "failure", "idna 0.1.5", - "log 0.4.14", + "log 0.4.17", "publicsuffix", "serde", "serde_json", @@ -1050,7 +1077,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" dependencies = [ - "core-foundation-sys", + "core-foundation-sys 0.6.2", "libc", ] @@ -1060,11 +1087,17 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + [[package]] name = "crc32fast" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if 1.0.0", ] @@ -1080,19 +1113,19 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.1" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.5", + "crossbeam-utils 0.8.14", ] [[package]] name = "crossbeam-deque" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" +checksum = "c20ff29ded3204c5106278a81a38f4b482636ed4fa1e6cfbeef193291beb29ed" dependencies = [ "crossbeam-epoch 0.8.2", "crossbeam-utils 0.7.2", @@ -1101,13 +1134,13 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if 1.0.0", - "crossbeam-epoch 0.9.5", - "crossbeam-utils 0.8.5", + "crossbeam-epoch 0.9.13", + "crossbeam-utils 0.8.14", ] [[package]] @@ -1130,7 +1163,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "cfg-if 0.1.10", "crossbeam-utils 0.7.2", "lazy_static", @@ -1141,14 +1174,14 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.5" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ + "autocfg 1.1.0", "cfg-if 1.0.0", - "crossbeam-utils 0.8.5", - "lazy_static", - "memoffset 0.6.4", + "crossbeam-utils 0.8.14", + "memoffset 0.7.1", "scopeguard 1.1.0", ] @@ -1179,19 +1212,18 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "cfg-if 0.1.10", "lazy_static", ] [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ "cfg-if 1.0.0", - "lazy_static", ] [[package]] @@ -1205,24 +1237,69 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.20" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ - "quote 1.0.9", - "syn 1.0.73", + "quote 1.0.21", + "syn 1.0.103", +] + +[[package]] +name = "cxx" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2 1.0.47", + "quote 1.0.21", + "scratch", + "syn 1.0.103", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470" +dependencies = [ + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "derive_more" -version = "0.99.14" +version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc7b9cef1e351660e5443924e4f43ab25fbbed3e9a5f052df3677deb4d6b320" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "convert_case", - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", + "proc-macro2 1.0.47", + "quote 1.0.21", + "rustc_version 0.4.0", + "syn 1.0.103", ] [[package]] @@ -1237,9 +1314,9 @@ dependencies = [ [[package]] name = "dirs-sys" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", @@ -1254,15 +1331,15 @@ checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" [[package]] name = "either" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "embedded-hal" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db184d3fa27bc7a2344250394c0264144dfe0bc81a4401801dcb964b8dd172ad" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" dependencies = [ "nb 0.1.3", "void", @@ -1270,23 +1347,23 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.28" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "enum-as-inner" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595" +checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4" dependencies = [ - "heck", - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", + "heck 0.4.0", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -1309,9 +1386,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.1" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "failure" @@ -1329,17 +1406,17 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", "synstructure", ] [[package]] name = "fastrand" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77b705829d1e87f762c2df6da140b26af5839e1033aa84aa5f56bb688e4e1bdb" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] @@ -1352,19 +1429,17 @@ checksum = "e69ab0d5aca163e388c3a49d284fed6c3d0810700e77c5ae2756a50ec1a4daaa" dependencies = [ "chrono", "colored", - "log 0.4.14", + "log 0.4.17", ] [[package]] name = "flate2" -version = "1.0.20" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ - "cfg-if 1.0.0", "crc32fast", - "libc", - "miniz_oxide", + "miniz_oxide 0.6.2", ] [[package]] @@ -1375,12 +1450,11 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", - "percent-encoding 2.1.0", + "percent-encoding 2.2.0", ] [[package]] @@ -1405,7 +1479,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" dependencies = [ - "bitflags 1.2.1", + "bitflags 1.3.2", "fuchsia-zircon-sys", ] @@ -1423,9 +1497,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.15" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7e43a803dae2fa37c1f6a8fe121e1f7bf9548b4dfc0522a42f34145dadfc27" +checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" dependencies = [ "futures-channel", "futures-core", @@ -1438,9 +1512,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.15" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" dependencies = [ "futures-core", "futures-sink", @@ -1448,9 +1522,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.15" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" [[package]] name = "futures-cpupool" @@ -1464,9 +1538,9 @@ dependencies = [ [[package]] name = "futures-executor" -version = "0.3.15" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79" +checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" dependencies = [ "futures-core", "futures-task", @@ -1475,9 +1549,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.15" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acc499defb3b348f8d8f3f66415835a9131856ff7714bf10dadfc4ec4bdb29a1" +checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" [[package]] name = "futures-lite" @@ -1490,42 +1564,39 @@ dependencies = [ "futures-io", "memchr", "parking", - "pin-project-lite 0.2.7", + "pin-project-lite 0.2.9", "waker-fn", ] [[package]] name = "futures-macro" -version = "0.3.15" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121" +checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ - "autocfg 1.0.1", - "proc-macro-hack", - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "futures-sink" -version = "0.3.15" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a57bead0ceff0d6dde8f465ecd96c9338121bb7717d3e7b108059531870c4282" +checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" [[package]] name = "futures-task" -version = "0.3.15" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a16bef9fc1a4dddb5bee51c989e3fbba26569cbb0e31f5b303c184e3dd33dae" +checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" [[package]] name = "futures-util" -version = "0.3.15" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967" +checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" dependencies = [ - "autocfg 1.0.1", "futures-channel", "futures-core", "futures-io", @@ -1533,10 +1604,8 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.7", + "pin-project-lite 0.2.9", "pin-utils", - "proc-macro-hack", - "proc-macro-nested", "slab", ] @@ -1562,42 +1631,41 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi 0.10.0+wasi-snapshot-preview1", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] name = "gimli" -version = "0.24.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4075386626662786ddb0ec9081e7c7eeb1ba31951f447ca780ef9f5d568189" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" [[package]] name = "gloo-timers" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f" +checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" dependencies = [ "futures-channel", "futures-core", "js-sys", "wasm-bindgen", - "web-sys", ] [[package]] name = "gpio-cdev" -version = "0.4.0" -source = "git+https://github.com/rust-embedded/gpio-cdev?branch=master#48a39488db2196b6ed15337a7f6712db0880ba93" +version = "0.5.1" +source = "git+https://github.com/rust-embedded/gpio-cdev?branch=master#2c7ef82343e1331cc2805dc682afb3a699d0da7d" dependencies = [ - "bitflags 1.2.1", + "bitflags 1.3.2", "libc", - "nix 0.20.0", + "nix 0.23.1", ] [[package]] @@ -1612,7 +1680,7 @@ dependencies = [ "futures 0.1.31", "http 0.1.21", "indexmap", - "log 0.4.14", + "log 0.4.17", "slab", "string", "tokio-io", @@ -1629,7 +1697,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http 0.2.4", + "http 0.2.8", "indexmap", "slab", "tokio 0.2.25", @@ -1649,9 +1717,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "heck" @@ -1662,6 +1730,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1702,18 +1776,18 @@ checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" dependencies = [ "bytes 0.4.12", "fnv", - "itoa", + "itoa 0.4.8", ] [[package]] name = "http" -version = "0.2.4" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ - "bytes 1.0.1", + "bytes 1.3.0", "fnv", - "itoa", + "itoa 1.0.4", ] [[package]] @@ -1735,14 +1809,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" dependencies = [ "bytes 0.5.6", - "http 0.2.4", + "http 0.2.8", ] [[package]] name = "httparse" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" @@ -1764,8 +1838,8 @@ dependencies = [ "http-body 0.1.0", "httparse", "iovec", - "itoa", - "log 0.4.14", + "itoa 0.4.8", + "log 0.4.17", "net2", "rustc_version 0.2.3", "time", @@ -1791,15 +1865,15 @@ dependencies = [ "futures-core", "futures-util", "h2 0.2.7", - "http 0.2.4", + "http 0.2.8", "http-body 0.3.1", "httparse", "httpdate", - "itoa", - "pin-project 1.0.7", + "itoa 0.4.8", + "pin-project 1.0.12", "socket2 0.3.19", "tokio 0.2.25", - "tower-service 0.3.1", + "tower-service 0.3.2", "tracing", "want 0.3.0", ] @@ -1847,7 +1921,7 @@ dependencies = [ "bytes 0.5.6", "futures-util", "hyper 0.13.10", - "log 0.4.14", + "log 0.4.17", "rustls 0.18.1", "tokio 0.2.25", "tokio-rustls 0.14.1", @@ -1860,12 +1934,36 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c0eb3d9b6b02dc2508ee23439170004e44344bab9d53a490eb1f64c885b5003" dependencies = [ - "bitflags 1.2.1", + "bitflags 1.3.2", "byteorder", "libc", "nix 0.14.1", ] +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys 0.8.3", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi 0.3.9", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "idna" version = "0.1.5" @@ -1888,21 +1986,31 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "indexmap" -version = "1.7.0" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ - "autocfg 1.0.1", - "hashbrown 0.11.2", + "autocfg 1.1.0", + "hashbrown 0.12.3", ] [[package]] name = "instant" -version = "0.1.9" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if 1.0.0", ] @@ -1943,21 +2051,27 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.3.1" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" +checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745" [[package]] name = "itoa" -version = "0.4.7" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "js-sys" -version = "0.3.51" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -1978,7 +2092,7 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" dependencies = [ - "log 0.4.14", + "log 0.4.17", ] [[package]] @@ -1995,15 +2109,24 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.97" +version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" + +[[package]] +name = "link-cplusplus" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +dependencies = [ + "cc", +] [[package]] name = "linked-hash-map" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-embedded-hal" @@ -2039,10 +2162,11 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.4" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ + "autocfg 1.1.0", "scopeguard 1.1.0", ] @@ -2052,14 +2176,14 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" dependencies = [ - "log 0.4.14", + "log 0.4.17", ] [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if 1.0.0", "value-bag", @@ -2082,9 +2206,9 @@ checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" [[package]] name = "matches" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "maybe-uninit" @@ -2094,9 +2218,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" @@ -2104,16 +2228,25 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", ] [[package]] name = "memoffset" -version = "0.6.4" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg 1.1.0", +] + +[[package]] +name = "memoffset" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", ] [[package]] @@ -2145,9 +2278,9 @@ dependencies = [ [[package]] name = "mime_guess" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" dependencies = [ "mime 0.3.16", "unicase 2.6.0", @@ -2155,12 +2288,20 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.4.4" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" +dependencies = [ + "adler", +] + +[[package]] +name = "miniz_oxide" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" dependencies = [ "adler", - "autocfg 1.0.1", ] [[package]] @@ -2175,7 +2316,7 @@ dependencies = [ "iovec", "kernel32-sys", "libc", - "log 0.4.14", + "log 0.4.17", "miow", "net2", "slab", @@ -2222,7 +2363,7 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "136eed74cadb9edd2651ffba732b19a450316b680e4f48d6c79e905799e19d01" dependencies = [ - "log 0.4.14", + "log 0.4.17", "mime 0.2.6", "mime_guess 1.8.8", "rand 0.6.5", @@ -2246,9 +2387,9 @@ checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" [[package]] name = "net2" -version = "0.2.37" +version = "0.2.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" +checksum = "74d0df99cfcd2530b2e694f6e17e7f37b8e26bb23983ac530c0c97408837c631" dependencies = [ "cfg-if 0.1.10", "libc", @@ -2275,7 +2416,7 @@ version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" dependencies = [ - "bitflags 1.2.1", + "bitflags 1.3.2", "cc", "cfg-if 0.1.10", "libc", @@ -2288,7 +2429,7 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" dependencies = [ - "bitflags 1.2.1", + "bitflags 1.3.2", "cc", "cfg-if 0.1.10", "libc", @@ -2297,14 +2438,15 @@ dependencies = [ [[package]] name = "nix" -version = "0.20.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" +checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" dependencies = [ - "bitflags 1.2.1", + "bitflags 1.3.2", "cc", "cfg-if 1.0.0", "libc", + "memoffset 0.6.5", ] [[package]] @@ -2343,7 +2485,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" dependencies = [ - "num-bigint 0.3.2", + "num-bigint 0.3.3", "num-complex 0.3.1", "num-integer", "num-iter", @@ -2357,18 +2499,18 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-integer", "num-traits", ] [[package]] name = "num-bigint" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d0a3d5e207573f948a9e5376662aa743a2ea13f7c50a554d7af443a73fbfeba" +checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-integer", "num-traits", ] @@ -2379,7 +2521,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-traits", ] @@ -2394,21 +2536,21 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-integer", "num-traits", ] @@ -2419,7 +2561,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-bigint 0.2.6", "num-integer", "num-traits", @@ -2431,26 +2573,26 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" dependencies = [ - "autocfg 1.0.1", - "num-bigint 0.3.2", + "autocfg 1.1.0", + "num-bigint 0.3.3", "num-integer", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", ] [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" dependencies = [ "hermit-abi", "libc", @@ -2458,24 +2600,24 @@ dependencies = [ [[package]] name = "object" -version = "0.25.3" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.8.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] name = "openssl-probe" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "ordered-float" @@ -2512,7 +2654,7 @@ dependencies = [ "historian", "lazy_static", "libc", - "log 0.4.14", + "log 0.4.17", "rayon", "serde", ] @@ -2546,13 +2688,13 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", - "lock_api 0.4.4", - "parking_lot_core 0.8.3", + "lock_api 0.4.9", + "parking_lot_core 0.8.5", ] [[package]] @@ -2585,15 +2727,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ "cfg-if 1.0.0", "instant", "libc", - "redox_syscall 0.2.9", - "smallvec 1.6.1", + "redox_syscall 0.2.16", + "smallvec 1.10.0", "winapi 0.3.9", ] @@ -2614,18 +2756,9 @@ checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" - -[[package]] -name = "pest" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" -dependencies = [ - "ucd-trie", -] +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "phf" @@ -2680,42 +2813,42 @@ dependencies = [ [[package]] name = "pin-project" -version = "0.4.28" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "918192b5c59119d51e0cd221f4d49dde9112824ba717369e903c97d076083d0f" +checksum = "3ef0f924a5ee7ea9cbcea77529dba45f8a9ba9f622419fe3386ca581a3ae9d5a" dependencies = [ - "pin-project-internal 0.4.28", + "pin-project-internal 0.4.30", ] [[package]] name = "pin-project" -version = "1.0.7" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ - "pin-project-internal 1.0.7", + "pin-project-internal 1.0.12", ] [[package]] name = "pin-project-internal" -version = "0.4.28" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be26700300be6d9d23264c73211d8190e755b6b5ca7a1b28230025511b52a5e" +checksum = "851c8d0ce9bebe43790dedfc86614c23494ac9f423dd618d3a61fc693eafe61e" dependencies = [ - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "pin-project-internal" -version = "1.0.7" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -2726,9 +2859,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -2738,22 +2871,23 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "polling" -version = "2.1.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92341d779fa34ea8437ef4d82d440d5e1ce3f3ff7f824aa64424cd481f9a1f25" +checksum = "ab4609a838d88b73d8238967b60dd115cc08d38e2bbaf51ee1e4b695f89122e2" dependencies = [ + "autocfg 1.1.0", "cfg-if 1.0.0", "libc", - "log 0.4.14", + "log 0.4.17", "wepoll-ffi", "winapi 0.3.9", ] [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro-error" @@ -2762,10 +2896,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", - "version_check 0.9.3", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", + "version_check 0.9.4", ] [[package]] @@ -2774,23 +2908,11 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.27", - "quote 1.0.9", - "version_check 0.9.3", + "proc-macro2 1.0.47", + "quote 1.0.21", + "version_check 0.9.4", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - -[[package]] -name = "proc-macro-nested" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" - [[package]] name = "proc-macro2" version = "0.4.30" @@ -2802,11 +2924,11 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.27" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ - "unicode-xid 0.2.2", + "unicode-ident", ] [[package]] @@ -2816,7 +2938,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95b4ce31ff0a27d93c8de1849cf58162283752f065a90d508f1105fa6c9a213f" dependencies = [ "idna 0.2.3", - "url 2.2.2", + "url 2.3.1", ] [[package]] @@ -2836,11 +2958,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.9" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ - "proc-macro2 1.0.27", + "proc-macro2 1.0.47", ] [[package]] @@ -2862,7 +2984,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" dependencies = [ - "autocfg 0.1.7", + "autocfg 0.1.8", "libc", "rand_chacha 0.1.1", "rand_core 0.4.2", @@ -2890,14 +3012,13 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", - "rand_core 0.6.3", - "rand_hc 0.3.1", + "rand_core 0.6.4", ] [[package]] @@ -2906,7 +3027,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" dependencies = [ - "autocfg 0.1.7", + "autocfg 0.1.8", "rand_core 0.3.1", ] @@ -2927,7 +3048,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -2956,11 +3077,11 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.8", ] [[package]] @@ -2981,15 +3102,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core 0.6.3", -] - [[package]] name = "rand_isaac" version = "0.1.1" @@ -3030,7 +3142,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" dependencies = [ - "autocfg 0.1.7", + "autocfg 0.1.8", "rand_core 0.4.2", ] @@ -3045,26 +3157,24 @@ dependencies = [ [[package]] name = "rayon" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" +checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b" dependencies = [ - "autocfg 1.0.1", - "crossbeam-deque 0.8.0", + "crossbeam-deque 0.8.2", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.1" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" +checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" dependencies = [ - "crossbeam-channel 0.5.1", - "crossbeam-deque 0.8.0", - "crossbeam-utils 0.8.5", - "lazy_static", + "crossbeam-channel 0.5.6", + "crossbeam-deque 0.8.2", + "crossbeam-utils 0.8.14", "num_cpus", ] @@ -3085,28 +3195,29 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" -version = "0.2.9" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags 1.2.1", + "bitflags 1.3.2", ] [[package]] name = "redox_users" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.3", - "redox_syscall 0.2.9", + "getrandom 0.2.8", + "redox_syscall 0.2.16", + "thiserror", ] [[package]] name = "regex" -version = "1.5.4" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" dependencies = [ "aho-corasick", "memchr", @@ -3115,9 +3226,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -3144,9 +3255,9 @@ dependencies = [ "http 0.1.21", "hyper 0.12.36", "hyper-rustls 0.17.1", - "log 0.4.14", + "log 0.4.17", "mime 0.3.16", - "mime_guess 2.0.3", + "mime_guess 2.0.4", "rustls 0.16.0", "serde", "serde_json", @@ -3170,29 +3281,29 @@ version = "0.10.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0718f81a8e14c4dbb3b34cf23dc6aaf9ab8a0dfec160c534b3dbca1aaa21f47c" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bytes 0.5.6", "encoding_rs", "futures-core", "futures-util", - "http 0.2.4", + "http 0.2.8", "http-body 0.3.1", "hyper 0.13.10", "hyper-rustls 0.21.0", "ipnet", "js-sys", "lazy_static", - "log 0.4.14", + "log 0.4.17", "mime 0.3.16", - "mime_guess 2.0.3", - "percent-encoding 2.1.0", - "pin-project-lite 0.2.7", + "mime_guess 2.0.4", + "percent-encoding 2.2.0", + "pin-project-lite 0.2.9", "rustls 0.18.1", "serde", - "serde_urlencoded 0.7.0", + "serde_urlencoded 0.7.1", "tokio 0.2.25", "tokio-rustls 0.14.1", - "url 2.2.2", + "url 2.3.1", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -3212,11 +3323,11 @@ dependencies = [ [[package]] name = "retry" -version = "1.2.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ee4a654b43dd7e3768be7a1c0fc20e90f0a84b72a60ffb6c11e1cae2545c2e" +checksum = "ac95c60a949a63fd2822f4964939662d8f2c16c4fa0624fd954bc6e703b9a3f6" dependencies = [ - "rand 0.7.3", + "rand 0.8.5", ] [[package]] @@ -3236,9 +3347,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] name = "rustc-serialize" @@ -3266,11 +3377,11 @@ dependencies = [ [[package]] name = "rustc_version" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 0.11.0", + "semver 1.0.14", ] [[package]] @@ -3280,7 +3391,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" dependencies = [ "base64 0.10.1", - "log 0.4.14", + "log 0.4.17", "ring", "sct", "webpki", @@ -3293,7 +3404,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81" dependencies = [ "base64 0.12.3", - "log 0.4.14", + "log 0.4.17", "ring", "sct", "webpki", @@ -3313,18 +3424,18 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.5" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "schannel" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ "lazy_static", - "winapi 0.3.9", + "windows-sys", ] [[package]] @@ -3339,6 +3450,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" + [[package]] name = "sct" version = "0.6.1" @@ -3356,7 +3473,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df" dependencies = [ "core-foundation", - "core-foundation-sys", + "core-foundation-sys 0.6.2", "libc", "security-framework-sys", ] @@ -3367,7 +3484,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" dependencies = [ - "core-foundation-sys", + "core-foundation-sys 0.6.2", ] [[package]] @@ -3382,17 +3499,14 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ - "semver-parser 0.7.0", + "semver-parser", ] [[package]] name = "semver" -version = "0.11.0" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser 0.10.2", -] +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" [[package]] name = "semver-parser" @@ -3400,19 +3514,10 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] - [[package]] name = "sensor_value" version = "0.1.0" -source = "git+https://github.com/dskleingeld/sensor_central.git?branch=main#eb9beee9e43682be52d078188d572c7b0fad9a0f" +source = "git+https://github.com/dskleingeld/sensor_central.git?branch=main#4b5eb3209adf84aeb9fb0d983eac9c91324c50ab" dependencies = [ "bitspec", "serde", @@ -3420,9 +3525,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.126" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" dependencies = [ "serde_derive", ] @@ -3439,22 +3544,22 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.126" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" +checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "serde_json" -version = "1.0.64" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" dependencies = [ - "itoa", + "itoa 1.0.4", "ryu", "serde", ] @@ -3466,7 +3571,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" dependencies = [ "dtoa", - "itoa", + "itoa 0.4.8", "serde", "url 1.7.2", ] @@ -3478,46 +3583,55 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" dependencies = [ "dtoa", - "itoa", + "itoa 0.4.8", "serde", - "url 2.2.2", + "url 2.3.1", ] [[package]] name = "serde_urlencoded" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa", + "itoa 1.0.4", "ryu", "serde", ] [[package]] name = "serde_yaml" -version = "0.8.17" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15654ed4ab61726bf918a39cb8d98a2e2995b002387807fa6ba58fdf7f59bb23" +checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ - "dtoa", - "linked-hash-map", + "indexmap", + "ryu", "serde", "yaml-rust", ] [[package]] name = "sha1" -version = "0.6.0" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +dependencies = [ + "sha1_smol", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" [[package]] name = "signal-hook" -version = "0.3.9" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "470c5a6397076fae0094aaf06a08e6ba6f37acb77d3b1b91ea92b4d6c8650c39" +checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" dependencies = [ "libc", "signal-hook-registry", @@ -3540,24 +3654,27 @@ checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" [[package]] name = "slab" -version = "0.4.3" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg 1.1.0", +] [[package]] name = "sled" -version = "0.34.6" +version = "0.34.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d0132f3e393bcb7390c60bb45769498cf4550bcb7a21d7f95c02b69f6362cdc" +checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" dependencies = [ "crc32fast", - "crossbeam-epoch 0.9.5", - "crossbeam-utils 0.8.5", + "crossbeam-epoch 0.9.13", + "crossbeam-utils 0.8.14", "fs2", "fxhash", "libc", - "log 0.4.14", - "parking_lot 0.11.1", + "log 0.4.17", + "parking_lot 0.11.2", ] [[package]] @@ -3571,9 +3688,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.6.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "smol" @@ -3606,9 +3723,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.0" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi 0.3.9", @@ -3654,9 +3771,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c" +checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" dependencies = [ "clap", "lazy_static", @@ -3665,15 +3782,15 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.14" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro-error", - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -3689,25 +3806,25 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.73" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ - "proc-macro2 1.0.27", - "quote 1.0.9", - "unicode-xid 0.2.2", + "proc-macro2 1.0.47", + "quote 1.0.21", + "unicode-ident", ] [[package]] name = "synstructure" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", - "unicode-xid 0.2.2", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", + "unicode-xid 0.2.4", ] [[package]] @@ -3726,7 +3843,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb29fb11ef40c839c1c6b4e9c2ec4f357f9f674491e9df5a8c94f8cc2005f860" dependencies = [ "bytes 0.5.6", - "futures 0.3.15", + "futures 0.3.25", "hyper 0.13.10", "hyper-rustls 0.19.1", "multipart", @@ -3751,23 +3868,32 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ "cfg-if 1.0.0", + "fastrand", "libc", - "rand 0.8.4", - "redox_syscall 0.2.9", + "redox_syscall 0.2.16", "remove_dir_all", "winapi 0.3.9", ] +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + [[package]] name = "text_io" -version = "0.1.8" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cb170b4f47dc48835fbc56259c12d8963e542b05a24be2e3a1f5a6c320fd2d4" +checksum = "d5f0c8eb2ad70c12a6a69508f499b3051c924f4b1cfeae85bfad96e6bc5bba46" [[package]] name = "textwrap" @@ -3780,22 +3906,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.25" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.25" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -3820,9 +3946,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.2.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -3939,7 +4065,7 @@ checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" dependencies = [ "bytes 0.4.12", "futures 0.1.31", - "log 0.4.14", + "log 0.4.17", ] [[package]] @@ -3951,7 +4077,7 @@ dependencies = [ "crossbeam-utils 0.7.2", "futures 0.1.31", "lazy_static", - "log 0.4.14", + "log 0.4.17", "mio", "num_cpus", "parking_lot 0.9.0", @@ -4046,12 +4172,12 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" dependencies = [ - "crossbeam-deque 0.7.3", + "crossbeam-deque 0.7.4", "crossbeam-queue", "crossbeam-utils 0.7.2", "futures 0.1.31", "lazy_static", - "log 0.4.14", + "log 0.4.17", "num_cpus", "slab", "tokio-executor", @@ -4077,7 +4203,7 @@ checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" dependencies = [ "bytes 0.4.12", "futures 0.1.31", - "log 0.4.14", + "log 0.4.17", "mio", "tokio-codec", "tokio-io", @@ -4094,7 +4220,7 @@ dependencies = [ "futures 0.1.31", "iovec", "libc", - "log 0.4.14", + "log 0.4.17", "mio", "mio-uds", "tokio-codec", @@ -4111,7 +4237,7 @@ dependencies = [ "bytes 0.5.6", "futures-core", "futures-sink", - "log 0.4.14", + "log 0.4.17", "pin-project-lite 0.1.12", "tokio 0.2.25", ] @@ -4125,7 +4251,7 @@ dependencies = [ "bytes 0.5.6", "futures-core", "futures-sink", - "log 0.4.14", + "log 0.4.17", "pin-project-lite 0.1.12", "tokio 0.2.25", ] @@ -4141,41 +4267,41 @@ dependencies = [ [[package]] name = "tower-service" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.26" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if 1.0.0", - "log 0.4.14", - "pin-project-lite 0.2.7", + "log 0.4.17", + "pin-project-lite 0.2.9", "tracing-attributes", "tracing-core", ] [[package]] name = "tracing-attributes" -version = "0.1.15" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] name = "tracing-core" -version = "0.1.18" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ - "lazy_static", + "once_cell", ] [[package]] @@ -4184,7 +4310,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ - "pin-project 1.0.7", + "pin-project 1.0.12", "tracing", ] @@ -4199,7 +4325,7 @@ dependencies = [ "futures 0.1.31", "idna 0.1.5", "lazy_static", - "log 0.4.14", + "log 0.4.17", "rand 0.5.6", "smallvec 0.6.14", "socket2 0.3.19", @@ -4223,7 +4349,7 @@ dependencies = [ "futures 0.1.31", "idna 0.1.5", "lazy_static", - "log 0.4.14", + "log 0.4.17", "rand 0.5.6", "smallvec 0.6.14", "socket2 0.3.19", @@ -4245,15 +4371,15 @@ dependencies = [ "async-trait", "enum-as-inner", "failure", - "futures 0.3.15", + "futures 0.3.25", "idna 0.2.3", "lazy_static", - "log 0.4.14", + "log 0.4.17", "rand 0.7.3", - "smallvec 1.6.1", + "smallvec 1.10.0", "socket2 0.3.19", "tokio 0.2.25", - "url 2.2.2", + "url 2.3.1", ] [[package]] @@ -4267,7 +4393,7 @@ dependencies = [ "futures 0.1.31", "ipconfig 0.1.9", "lazy_static", - "log 0.4.14", + "log 0.4.17", "lru-cache", "resolv-conf", "smallvec 0.6.14", @@ -4283,13 +4409,13 @@ checksum = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f" dependencies = [ "cfg-if 0.1.10", "failure", - "futures 0.3.15", + "futures 0.3.25", "ipconfig 0.2.2", "lazy_static", - "log 0.4.14", + "log 0.4.17", "lru-cache", "resolv-conf", - "smallvec 1.6.1", + "smallvec 1.10.0", "tokio 0.2.25", "trust-dns-proto 0.18.0-alpha.2", ] @@ -4309,12 +4435,6 @@ dependencies = [ "cfg-if 0.1.10", ] -[[package]] -name = "ucd-trie" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" - [[package]] name = "unicase" version = "1.4.2" @@ -4330,38 +4450,41 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" dependencies = [ - "version_check 0.9.3", + "version_check 0.9.4", ] [[package]] name = "unicode-bidi" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" -dependencies = [ - "matches", -] +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-ident" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-normalization" -version = "0.1.19" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.7.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" [[package]] name = "unicode-width" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unicode-xid" @@ -4371,9 +4494,9 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "untrusted" @@ -4394,14 +4517,13 @@ dependencies = [ [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", - "idna 0.2.3", - "matches", - "percent-encoding 2.1.0", + "idna 0.3.0", + "percent-encoding 2.2.0", ] [[package]] @@ -4429,9 +4551,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae" dependencies = [ "nom", - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", ] [[package]] @@ -4446,12 +4568,12 @@ dependencies = [ [[package]] name = "value-bag" -version = "1.0.0-alpha.7" +version = "1.0.0-alpha.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd320e1520f94261153e96f7534476ad869c14022aee1e59af7c778075d840ae" +checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" dependencies = [ "ctor", - "version_check 0.9.3", + "version_check 0.9.4", ] [[package]] @@ -4468,9 +4590,9 @@ checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "void" @@ -4491,7 +4613,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" dependencies = [ "futures 0.1.31", - "log 0.4.14", + "log 0.4.17", "try-lock", ] @@ -4501,7 +4623,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" dependencies = [ - "log 0.4.14", + "log 0.4.17", "try-lock", ] @@ -4517,11 +4639,17 @@ version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" -version = "0.2.74" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if 1.0.0", "serde", @@ -4531,24 +4659,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.74" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", - "lazy_static", - "log 0.4.14", - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", + "log 0.4.17", + "once_cell", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.24" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fba7978c679d53ce2d0ac80c8c175840feb849a161664365d1287b41f2e67f1" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -4558,38 +4686,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.74" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ - "quote 1.0.9", + "quote 1.0.21", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.74" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.74" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "web-sys" -version = "0.3.51" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", @@ -4672,12 +4800,64 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + [[package]] name = "winreg" version = "0.5.1" diff --git a/src/controller/mod.rs b/src/controller/mod.rs index f01134f4..a5944cf8 100644 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -188,13 +188,13 @@ fn handle_buttonpress( if press.duration < LONG_PRESS { // millisec match press.button { - Button::LampLeft => Some(State::Quiet), + Button::LampLeft => None, Button::LampMid => Some(State::Silent), Button::LampRight => Some(State::Off), Button::DeskLeftMost => Some(State::Sleep), Button::DeskLeft => Some(State::Normal), - Button::DeskRight => Some(State::Quiet), + Button::DeskRight => None, Button::DeskRightMost => Some(State::Off), Button::DeskTop => handle_cmd(Command::MpdIncreaseVolume, mods, system), diff --git a/src/controller/state/mod.rs b/src/controller/state/mod.rs index fb6e671a..79765dc5 100644 --- a/src/controller/state/mod.rs +++ b/src/controller/state/mod.rs @@ -23,7 +23,6 @@ pub enum State { WakeUp, Sleep, Silent, - Quiet, Off, } diff --git a/src/controller/state/normal.rs b/src/controller/state/normal.rs index 12c4e85d..fb727067 100644 --- a/src/controller/state/normal.rs +++ b/src/controller/state/normal.rs @@ -6,12 +6,16 @@ use chrono::{Local, NaiveTime}; use std::time::{Duration, Instant}; fn update_lights(sys: &mut System) -> Result<(), Error> { + fn hour(h: u8) -> NaiveTime { + NaiveTime::from_hms_opt(h as u32, 0, 0).unwrap() + } + let now = Local::now(); - if now.time() > NaiveTime::from_hms(22, 0, 0) || now.time() < NaiveTime::from_hms(6, 0, 0) { + if now.time() > hour(22) || now.time() < hour(6) { sys.lights.set_all_ct(220, 500)?; - } else if now.time() > NaiveTime::from_hms(17, 0, 0) { + } else if now.time() > hour(17) { sys.lights.set_all_ct(254, 320)?; - } else if now.time() >= NaiveTime::from_hms(6, 0, 0) { + } else if now.time() >= hour(6) { sys.lights.set_all_ct(254, 240)?; }; Ok(()) diff --git a/src/input/bot/set_alarm.rs b/src/input/bot/set_alarm.rs index 8d35046f..6f2744f5 100644 --- a/src/input/bot/set_alarm.rs +++ b/src/input/bot/set_alarm.rs @@ -93,6 +93,7 @@ fn parse_args<'a>( mut args: std::str::SplitWhitespace<'a>, _: &State, ) -> Result { + use chrono::TimeZone; let time = args.next().ok_or(Error::NoTimeArgument)?; if time == "-" { @@ -128,8 +129,8 @@ fn parse_args<'a>( .with_minute(min).unwrap(); if alarm < now { - let tomorrow = now.date().succ(); - alarm = tomorrow.and_hms(hour, min, 0); + let alarm = now.date_naive().succ_opt().unwrap() + .and_hms_opt(hour, min, 0).unwrap().and_local_timezone(Local).unwrap(); } let till_alarm = alarm-now; diff --git a/src/input/jobs/wakeup.rs b/src/input/jobs/wakeup.rs index 3e620fc8..902d6759 100644 --- a/src/input/jobs/wakeup.rs +++ b/src/input/jobs/wakeup.rs @@ -172,14 +172,14 @@ fn job_from(hour: u8, min: u8) -> Job { fn to_datetime(hour: u8, min: u8) -> DateTime { let (hour, min) = (hour as u32, min as u32); let now = Local::now(); - let today = now.date(); - let alarm = today.and_hms(hour,min, 0); + let today = now.date_naive(); + let alarm = today.and_hms_opt(hour,min, 0).unwrap(); - if alarm < now { - let tomorrow = now.date().succ(); - tomorrow.and_hms(hour, min, 0) + if alarm < now.naive_local() { + let tomorrow = now.date_naive().succ_opt().unwrap(); + tomorrow.and_hms_opt(hour, min, 0).unwrap().and_local_timezone(Local).unwrap() .with_timezone(&Utc) } else { - alarm.with_timezone(&Utc) + alarm.and_local_timezone(Local).unwrap().with_timezone(&Utc) } } diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index e8fb641e..5717434d 100644 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -5,16 +5,16 @@ use actix_web_httpauth::headers::www_authenticate::WwwAuthenticate; use actix_web::http::StatusCode; use actix_web::{HttpRequest, HttpResponse}; -mod wakeup; mod commands; mod music; +mod wakeup; pub mod server; use server::State; fn authenticated(auth: BasicAuth) -> bool { - let username = auth.user_id(); - let password = auth.password() ; + let username = auth.user_id() else { return false }; + let Some(password) = auth.password() else { return false }; username == env!("CMD_API_USERNAME") && password == env!("COMMAND_API_PASSWORD") } From 61f3120b06ad0dc85f39c6e803410e72bbfc038e Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 27 Nov 2022 23:59:09 +0100 Subject: [PATCH 078/687] upgrades some deps --- Cargo.lock | 101 +++++++++++++++++++++++++++++++++++++++++------------ Cargo.toml | 8 ++--- 2 files changed, 83 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d6c39478..c39674c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -576,13 +576,13 @@ dependencies = [ [[package]] name = "async-io" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8121296a9f05be7f34aa4196b1747243b3b62e048bb7906f644f3fbfc490cf7" +checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" dependencies = [ "async-lock", "autocfg 1.1.0", - "concurrent-queue 1.2.4", + "concurrent-queue 2.0.0", "futures-lite", "libc", "log 0.4.17", @@ -591,7 +591,7 @@ dependencies = [ "slab", "socket2 0.4.7", "waker-fn", - "winapi 0.3.9", + "windows-sys 0.42.0", ] [[package]] @@ -618,20 +618,20 @@ dependencies = [ [[package]] name = "async-process" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02111fd8655a613c25069ea89fc8d9bb89331fa77486eb3bc059ee757cfa481c" +checksum = "6381ead98388605d0d9ff86371043b5aa922a3905824244de40dc263a14fcba4" dependencies = [ "async-io", + "async-lock", "autocfg 1.1.0", "blocking", "cfg-if 1.0.0", "event-listener", "futures-lite", "libc", - "once_cell", "signal-hook", - "winapi 0.3.9", + "windows-sys 0.42.0", ] [[package]] @@ -818,16 +818,16 @@ dependencies = [ [[package]] name = "blocking" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc" +checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8" dependencies = [ "async-channel", + "async-lock", "async-task", "atomic-waker", "fastrand", "futures-lite", - "once_cell", ] [[package]] @@ -2871,16 +2871,16 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "polling" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4609a838d88b73d8238967b60dd115cc08d38e2bbaf51ee1e4b695f89122e2" +checksum = "9f7d73f1eaed1ca1fb37b54dcc9b38e3b17d6c7b8ecb7abfffcac8d0351f17d4" dependencies = [ "autocfg 1.1.0", "cfg-if 1.0.0", "libc", "log 0.4.17", "wepoll-ffi", - "winapi 0.3.9", + "windows-sys 0.42.0", ] [[package]] @@ -3435,7 +3435,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ "lazy_static", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -3935,9 +3935,9 @@ dependencies = [ [[package]] name = "time" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", @@ -4821,43 +4821,100 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", +] + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + [[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + [[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + [[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + [[package]] name = "winreg" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index 48f1cb70..0c828eff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,7 @@ bincode = "1.3" thiserror = "1.0" log = "0.4" -fern = { version = "0.5.6", features = ["colored"] } +fern = { version = "0.5.9", features = ["colored"] } sensor_value = { git = "https://github.com/dskleingeld/sensor_central.git", branch = "main" } gpio-cdev = { git = "https://github.com/rust-embedded/gpio-cdev", branch = "master" } @@ -53,11 +53,11 @@ bme280 = "0.1" smallvec = "0.6" chrono = { version = "0.4", features = ["serde"] } -chrono-tz = "0.5.1" +chrono-tz = "0.5.3" bytes = "0.4" -byteorder = "1.3" +byteorder = "1.4" num = { version = "0.2"} -hex = "0.4.2" +hex = "0.4.3" crossbeam-channel = "0.3" From 42c914efdc213bfa2e68ae2863f475f7c04f908f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 30 Nov 2022 17:14:54 +0100 Subject: [PATCH 079/687] Command API now uses password database instead of environment variable or hardcoded credentials --- src/controller/state/wakeup.rs | 20 +++++---- src/input/bot/set_alarm.rs | 73 +++++++++++++++++++-------------- src/input/jobs/wakeup.rs | 56 +++++++++++++------------ src/input/web_api/commands.rs | 16 ++++---- src/input/web_api/mod.rs | 14 +++++-- src/input/web_api/server/mod.rs | 2 +- src/input/web_api/wakeup.rs | 42 +++++++++++-------- src/main.rs | 18 +++----- 8 files changed, 131 insertions(+), 110 deletions(-) diff --git a/src/controller/state/wakeup.rs b/src/controller/state/wakeup.rs index bf3021e4..4502b85c 100644 --- a/src/controller/state/wakeup.rs +++ b/src/controller/state/wakeup.rs @@ -23,7 +23,6 @@ const VOL_PER_SECOND: f32 = (MAX_VOLUME - MIN_VOLUME) / (WAKEUP_DURATION - MUSIC pub enum WakeUpStateError { #[error("could not setup playlist even after retries: {0}")] SetupPlaylist(retry::Error), - } #[derive(Clone, Copy)] @@ -36,13 +35,15 @@ impl WakeUp { fn setup_playlist() -> Result<(), Error> { let mpd = &mut retry(Fixed::from_millis(100), || { mpd::Client::connect("127.0.0.1:6600") - }).map_err(WakeUpStateError::SetupPlaylist)?; + }) + .map_err(WakeUpStateError::SetupPlaylist)?; retry(Fixed::from_millis(100).take(3), || { system::mpd_control::save_current_playlist(mpd) - }).map_err(WakeUpStateError::SetupPlaylist)?; + }) + .map_err(WakeUpStateError::SetupPlaylist)?; - // note if playlist does not exist we do not + // note if playlist does not exist we do not // report an error retry(Fixed::from_millis(100).take(3), || { system::mpd_control::add_from_playlist( @@ -51,7 +52,8 @@ impl WakeUp { chrono::Duration::seconds(3 * 60), chrono::Duration::seconds(5 * 60), ) - }).map_err(WakeUpStateError::SetupPlaylist)?; + }) + .map_err(WakeUpStateError::SetupPlaylist)?; retry(Fixed::from_millis(100).take(3), || { system::mpd_control::add_from_playlist( @@ -60,7 +62,8 @@ impl WakeUp { chrono::Duration::seconds(10 * 60), chrono::Duration::seconds(11 * 60), ) - }).map_err(WakeUpStateError::SetupPlaylist)?; + }) + .map_err(WakeUpStateError::SetupPlaylist)?; retry(Fixed::from_millis(100).take(3), || { system::mpd_control::add_from_playlist( @@ -69,7 +72,8 @@ impl WakeUp { chrono::Duration::seconds(30 * 60), chrono::Duration::seconds(60 * 60), ) - }).map_err(WakeUpStateError::SetupPlaylist)?; + }) + .map_err(WakeUpStateError::SetupPlaylist)?; Ok(()) } } @@ -126,7 +130,7 @@ impl RoomState for WakeUp { } else if elapsed > MUSIC_ON { let since_music_on = elapsed.saturating_sub(MUSIC_ON); let mut client = mpd::Client::connect("127.0.0.1:6600")?; - let volume = MIN_VOLUME + VOL_PER_SECOND * (since_music_on as f32); + let volume = MIN_VOLUME + VOL_PER_SECOND * (since_music_on as f32); client.volume(volume as i8)?; } } diff --git a/src/input/bot/set_alarm.rs b/src/input/bot/set_alarm.rs index 6f2744f5..4fe49a09 100644 --- a/src/input/bot/set_alarm.rs +++ b/src/input/bot/set_alarm.rs @@ -33,16 +33,14 @@ pub async fn handle<'a>( Ok(()) } -async fn help( - chat_id: ChatId, - token: &str, -) -> Result<(), Error> { - - let text = String::from("Check, Set and remove alarms +async fn help(chat_id: ChatId, token: &str) -> Result<(), Error> { + let text = String::from( + "Check, Set and remove alarms * use 'tomorrow' followed by a time to set the alarm only for tomorrow * use 'usually' followed by a time to set the alarm for all other days * format a time as hh:mm or - to unset - * without any arguments this displays the tomorrow and usually times"); + * without any arguments this displays the tomorrow and usually times", + ); send_text(chat_id, token, text) .await @@ -58,7 +56,11 @@ async fn add_tomorrow<'a>( ) -> Result<(), Error> { let Parsed { time, status } = parse_args(chat_id, token, args, state)?; - state.wakeup.set_tomorrow(time).await.map_err(|_| Error::BackendError)?; + state + .wakeup + .set_tomorrow(time) + .await + .map_err(|_| Error::BackendError)?; send_text(chat_id, token, status) .await .map_err(|_| Error::CouldNotRespond)?; @@ -74,7 +76,11 @@ async fn add_usually<'a>( ) -> Result<(), Error> { let Parsed { time, status } = parse_args(chat_id, token, args, state)?; - state.wakeup.set_usually(time).await.map_err(|_| Error::BackendError)?; + state + .wakeup + .set_usually(time) + .await + .map_err(|_| Error::BackendError)?; send_text(chat_id, token, status) .await .map_err(|_| Error::CouldNotRespond)?; @@ -83,7 +89,7 @@ async fn add_usually<'a>( } struct Parsed { - time: Option<(u8,u8)>, + time: Option<(u8, u8)>, status: String, } @@ -93,14 +99,13 @@ fn parse_args<'a>( mut args: std::str::SplitWhitespace<'a>, _: &State, ) -> Result { - use chrono::TimeZone; let time = args.next().ok_or(Error::NoTimeArgument)?; if time == "-" { return Ok(Parsed { time: None, status: String::from("Alarm unset"), - }) + }); } //assumes hh:mm @@ -124,16 +129,20 @@ fn parse_args<'a>( } let now = Local::now(); - let mut alarm = now - .with_hour(hour).unwrap() - .with_minute(min).unwrap(); + let mut alarm = now.with_hour(hour).unwrap().with_minute(min).unwrap(); if alarm < now { - let alarm = now.date_naive().succ_opt().unwrap() - .and_hms_opt(hour, min, 0).unwrap().and_local_timezone(Local).unwrap(); + alarm = now + .date_naive() + .succ_opt() + .unwrap() + .and_hms_opt(hour, min, 0) + .unwrap() + .and_local_timezone(Local) + .unwrap(); } - let till_alarm = alarm-now; + let till_alarm = alarm - now; let status = format!( "set alarm for over {} hours and {} minutes from now", @@ -141,9 +150,10 @@ fn parse_args<'a>( till_alarm.num_minutes() % 60 ); - Ok(Parsed { - time: Some((hour as u8, min as u8)), - status}) + Ok(Parsed { + time: Some((hour as u8, min as u8)), + status, + }) } pub async fn print_current(chat_id: ChatId, token: &str, state: &State) -> Result<(), Error> { @@ -151,16 +161,17 @@ pub async fn print_current(chat_id: ChatId, token: &str, state: &State) -> Resul let usually = state.wakeup.usually(); let msg = match (tomorrow, usually) { - (Some(tomorrow), Some(usually)) => - format!("alarm tomorrow: {:02}:{:02}\nusually: {:02}:{:02}", - tomorrow.0, tomorrow.1, - usually.0, usually.1), - (Some(tomorrow), None) => - format!("alarm tomorrow: {:02}:{:02}, usually no alarm", - tomorrow.0, tomorrow.1), - (None, Some(usually)) => - format!("alarm tomorrow as usual: {:02}:{:02}", - usually.0, usually.1), + (Some(tomorrow), Some(usually)) => format!( + "alarm tomorrow: {:02}:{:02}\nusually: {:02}:{:02}", + tomorrow.0, tomorrow.1, usually.0, usually.1 + ), + (Some(tomorrow), None) => format!( + "alarm tomorrow: {:02}:{:02}, usually no alarm", + tomorrow.0, tomorrow.1 + ), + (None, Some(usually)) => { + format!("alarm tomorrow as usual: {:02}:{:02}", usually.0, usually.1) + } (None, None) => String::from("No alarm set"), }; diff --git a/src/input/jobs/wakeup.rs b/src/input/jobs/wakeup.rs index 902d6759..7af368f3 100644 --- a/src/input/jobs/wakeup.rs +++ b/src/input/jobs/wakeup.rs @@ -1,12 +1,12 @@ -use super::{Jobs, Job, Action}; +use super::{Action, Job, Jobs}; use crate::controller::Event; -use std::time::Duration; +use chrono::{DateTime, Local, Timelike, Utc}; use std::sync::{Arc, Mutex}; -use chrono::{Utc, Local, DateTime, Timelike}; +use std::time::Duration; // TODO FIXME multiple things left to do: // - usually and tomorrow are not written to db -// - setting usually none goes wrong if tomorrow is not none +// - setting usually none goes wrong if tomorrow is not none // - recheck set tomorrow and set usually carefull #[derive(Debug, thiserror::Error)] @@ -18,17 +18,17 @@ pub enum Error { } #[derive(Clone)] -pub struct WakeUp(Arc>); +pub struct WakeUp(Arc>); impl WakeUp { pub fn setup(db: sled::Db, jobs: Jobs) -> Result { let inner = Inner::setup(db, jobs)?; let inner = Arc::new(Mutex::new(inner)); Ok(Self(inner)) } - pub fn tomorrow(&self) -> Option<(u8,u8)> { + pub fn tomorrow(&self) -> Option<(u8, u8)> { self.0.lock().unwrap().tomorrow } - pub fn usually(&self) -> Option<(u8,u8)> { + pub fn usually(&self) -> Option<(u8, u8)> { self.0.lock().unwrap().usually } pub fn reset(&self) -> Result<(), Error> { @@ -65,17 +65,15 @@ impl Inner { .get("usually")? .map(|b| bincode::deserialize(&b).unwrap()) .flatten(); // we want bincode to deserialize to Option<(u8,u8)> not (u8,u8) - let job_id = db - .get("job_id")? - .map(|b| bincode::deserialize(&b).unwrap()); - let next_alarm = job_id.as_ref() + let job_id = db.get("job_id")?.map(|b| bincode::deserialize(&b).unwrap()); + let next_alarm = job_id + .as_ref() .map(|id| jobs.get(*id).unwrap()) .flatten() .map(|job| job.time.into()) .map(|t: DateTime| t) .map(|t| (t.hour() as u8, t.minute() as u8)); - let tomorrow = next_alarm - .filter(|tomorrow| Some(*tomorrow) != usually); + let tomorrow = next_alarm.filter(|tomorrow| Some(*tomorrow) != usually); Ok(Self { db, @@ -105,10 +103,8 @@ impl Inner { Ok(()) } - async fn replace_job(&mut self, job: Job) -> Result<(),Error> { - let id = self.jobs - .add_alarm(job) - .await?; + async fn replace_job(&mut self, job: Job) -> Result<(), Error> { + let id = self.jobs.add_alarm(job).await?; self.save_job_id(id)?; Ok(()) } @@ -121,8 +117,8 @@ impl Inner { /// reset the alarm, if their is a usual alarm /// time we set that, otherwise remove all - pub fn reset(&mut self) -> Result<(),Error> { - if let Some((hour,min)) = self.usually { + pub fn reset(&mut self) -> Result<(), Error> { + if let Some((hour, min)) = self.usually { let job = job_from(hour, min); let add = self.replace_job(job); smol::block_on(add)?; @@ -131,7 +127,7 @@ impl Inner { Ok(()) } - pub async fn set_tomorrow(&mut self, time: Time) -> Result<(),Error> { + pub async fn set_tomorrow(&mut self, time: Time) -> Result<(), Error> { match time { None => self.reset()?, Some((hour, min)) => { @@ -150,9 +146,11 @@ impl Inner { let job = job_from(hour, min); self.replace_job(job).await?; } - None => if self.job_id.is_some() { - if self.tomorrow.is_none() { - self.remove_job()?; + None => { + if self.job_id.is_some() { + if self.tomorrow.is_none() { + self.remove_job()?; + } } } } @@ -163,9 +161,9 @@ impl Inner { fn job_from(hour: u8, min: u8) -> Job { Job { - time: to_datetime(hour,min), + time: to_datetime(hour, min), action: Action::SendEvent(Event::WakeUp), - expiration: Some(Duration::from_secs(3*60*60)), + expiration: Some(Duration::from_secs(3 * 60 * 60)), } } @@ -173,11 +171,15 @@ fn to_datetime(hour: u8, min: u8) -> DateTime { let (hour, min) = (hour as u32, min as u32); let now = Local::now(); let today = now.date_naive(); - let alarm = today.and_hms_opt(hour,min, 0).unwrap(); + let alarm = today.and_hms_opt(hour, min, 0).unwrap(); if alarm < now.naive_local() { let tomorrow = now.date_naive().succ_opt().unwrap(); - tomorrow.and_hms_opt(hour, min, 0).unwrap().and_local_timezone(Local).unwrap() + tomorrow + .and_hms_opt(hour, min, 0) + .unwrap() + .and_local_timezone(Local) + .unwrap() .with_timezone(&Utc) } else { alarm.and_local_timezone(Local).unwrap().with_timezone(&Utc) diff --git a/src/input/web_api/commands.rs b/src/input/web_api/commands.rs index e76cb816..ecad490e 100644 --- a/src/input/web_api/commands.rs +++ b/src/input/web_api/commands.rs @@ -1,6 +1,6 @@ use actix_web::web::Data; -use actix_web_httpauth::extractors::basic::BasicAuth; use actix_web::HttpResponse; +use actix_web_httpauth::extractors::basic::BasicAuth; use super::*; use crate::controller::State as TargetState; @@ -8,7 +8,7 @@ use crate::controller::{Command, Event}; ///////////////////// lamp commands /////////////////////////////// pub fn toggle(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { + if authenticated(auth, &state.passw_db) { state .controller_addr .send(Event::Command(Command::LampsToggle)) @@ -20,7 +20,7 @@ pub fn toggle(state: Data, auth: BasicAuth) -> HttpResponse { } pub fn dim(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { + if authenticated(auth, &state.passw_db) { state .controller_addr .send(Event::Command(Command::LampsDim)) @@ -32,7 +32,7 @@ pub fn dim(state: Data, auth: BasicAuth) -> HttpResponse { } pub fn dimmest(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { + if authenticated(auth, &state.passw_db) { state .controller_addr .send(Event::Command(Command::LampsDimmest)) @@ -44,7 +44,7 @@ pub fn dimmest(state: Data, auth: BasicAuth) -> HttpResponse { } pub fn normal(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { + if authenticated(auth, &state.passw_db) { state .controller_addr .send(Event::Command(Command::LampsDay)) @@ -56,7 +56,7 @@ pub fn normal(state: Data, auth: BasicAuth) -> HttpResponse { } pub fn evening(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { + if authenticated(auth, &state.passw_db) { state .controller_addr .send(Event::Command(Command::LampsEvening)) @@ -68,7 +68,7 @@ pub fn evening(state: Data, auth: BasicAuth) -> HttpResponse { } pub fn night(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { + if authenticated(auth, &state.passw_db) { state .controller_addr .send(Event::Command(Command::LampsNight)) @@ -82,7 +82,7 @@ pub fn night(state: Data, auth: BasicAuth) -> HttpResponse { //////////////////////// go to state commands ///////////////////////////////// pub fn lightloop(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth) { + if authenticated(auth, &state.passw_db) { state .controller_addr .send(Event::Command(Command::ChangeState(TargetState::LightLoop))) diff --git a/src/input/web_api/mod.rs b/src/input/web_api/mod.rs index 5717434d..d8542340 100644 --- a/src/input/web_api/mod.rs +++ b/src/input/web_api/mod.rs @@ -5,6 +5,8 @@ use actix_web_httpauth::headers::www_authenticate::WwwAuthenticate; use actix_web::http::StatusCode; use actix_web::{HttpRequest, HttpResponse}; +use crate::PasswordDatabase; + mod commands; mod music; mod wakeup; @@ -12,10 +14,14 @@ mod wakeup; pub mod server; use server::State; -fn authenticated(auth: BasicAuth) -> bool { - let username = auth.user_id() else { return false }; - let Some(password) = auth.password() else { return false }; - username == env!("CMD_API_USERNAME") && password == env!("COMMAND_API_PASSWORD") +fn authenticated(auth: BasicAuth, pass_db: &PasswordDatabase) -> bool { + let username = auth.user_id(); + let Some(password) = auth.password() else { + return false; + }; + pass_db + .verify_password(username.as_bytes(), password.as_bytes()) + .is_ok() } fn make_auth_error() -> HttpResponse { diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index 62aaf8c5..01022f2b 100644 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -21,7 +21,7 @@ pub mod database; pub mod login; pub mod login_redirect; -use super::{wakeup, commands, music}; +use super::{commands, music, wakeup}; pub use database::PasswordDatabase; pub use login::{login_get_and_check, login_page, logout, make_random_cookie_key}; pub use login_redirect::CheckLogin; diff --git a/src/input/web_api/wakeup.rs b/src/input/web_api/wakeup.rs index d82fc7e0..d6b2730b 100644 --- a/src/input/web_api/wakeup.rs +++ b/src/input/web_api/wakeup.rs @@ -1,8 +1,8 @@ -use actix_web::web::Data; -use actix_web_httpauth::extractors::basic::BasicAuth; use actix_web::http::Method; use actix_web::web::Bytes; +use actix_web::web::Data; use actix_web::HttpResponse; +use actix_web_httpauth::extractors::basic::BasicAuth; use super::*; use crate::input::jobs::WakeUp; @@ -13,8 +13,13 @@ async fn set_tomorrow(wakeup: &WakeUp, body: Bytes) -> Result Ok(HttpResponse::Ok().finish()) } -pub async fn tomorrow(state: Data, auth: BasicAuth, req: HttpRequest, body: Bytes) -> HttpResponse { - if !authenticated(auth) { +pub async fn tomorrow( + state: Data, + auth: BasicAuth, + req: HttpRequest, + body: Bytes, +) -> HttpResponse { + if !authenticated(auth, &state.passw_db) { return make_auth_error(); } @@ -24,12 +29,10 @@ pub async fn tomorrow(state: Data, auth: BasicAuth, req: HttpRequest, bod let bytes = bincode::serialize(&tomorrow).unwrap(); HttpResponse::Ok().body(bytes) } - Method::POST => { - match set_tomorrow(&state.wakeup, body).await { - Ok(resp) => resp, - Err(_) => HttpResponse::BadRequest().finish() - } - } + Method::POST => match set_tomorrow(&state.wakeup, body).await { + Ok(resp) => resp, + Err(_) => HttpResponse::BadRequest().finish(), + }, _ => HttpResponse::BadRequest().finish(), } } @@ -40,8 +43,13 @@ async fn set_usually(wakeup: &WakeUp, body: Bytes) -> Result { Ok(HttpResponse::Ok().finish()) } -pub async fn usually(state: Data, auth: BasicAuth, req: HttpRequest, body: Bytes) -> HttpResponse { - if !authenticated(auth) { +pub async fn usually( + state: Data, + auth: BasicAuth, + req: HttpRequest, + body: Bytes, +) -> HttpResponse { + if !authenticated(auth, &state.passw_db) { return make_auth_error(); } @@ -51,12 +59,10 @@ pub async fn usually(state: Data, auth: BasicAuth, req: HttpRequest, body let bytes = bincode::serialize(&usually).unwrap(); HttpResponse::Ok().body(bytes) } - Method::POST => { - match set_usually(&state.wakeup, body).await { - Ok(resp) => resp, - Err(_) => HttpResponse::BadRequest().finish() - } - } + Method::POST => match set_usually(&state.wakeup, body).await { + Ok(resp) => resp, + Err(_) => HttpResponse::BadRequest().finish(), + }, _ => HttpResponse::BadRequest().finish(), } } diff --git a/src/main.rs b/src/main.rs index c8d14ffa..3fb4a7f6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -78,20 +78,12 @@ async fn main() { ); //start the webserver - let _web_handle = server::start_webserver( - state, - opt.port, - opt.domain.clone(), - opt.ha_key.clone(), - ); + let _web_handle = + server::start_webserver(state, opt.port, opt.domain.clone(), opt.ha_key.clone()); - bot::set_webhook( - &opt.domain, - &opt.token, - opt.external_port, - ) - .await - .unwrap(); + bot::set_webhook(&opt.domain, &opt.token, opt.external_port) + .await + .unwrap(); loop { std::thread::park(); From fcacc16a960a2aa64e98fb2e5e5c86225cf157de Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 9 Mar 2024 00:04:13 +0100 Subject: [PATCH 080/687] trims down the abilities and improves whats left --- Cargo.lock | 2192 ++++------------- Cargo.toml | 42 +- src/controller/commands.rs | 1 + src/controller/environment/mod.rs | 18 +- src/controller/mod.rs | 9 +- src/controller/state/lightloop.rs | 5 +- src/controller/state/normal.rs | 16 +- src/controller/state/off.rs | 2 +- src/controller/state/silent.rs | 9 +- src/controller/state/sleep.rs | 6 +- src/controller/state/wakeup.rs | 24 +- src/controller/system/lamps/bridge_connect.rs | 118 + .../lamps/eventually_consistent_bridge.rs | 150 ++ src/controller/system/lamps/lamp.rs | 55 + src/controller/system/lamps/mod.rs | 394 +-- src/controller/system/mod.rs | 2 +- src/controller/system/mpd_control.rs | 11 +- src/errors.rs | 64 +- src/input/api.rs | 26 + src/input/bot/mod.rs | 240 -- src/input/bot/set_alarm.rs | 182 -- src/input/bot/youtube_dl.rs | 136 - src/input/jobs.rs | 4 +- src/input/jobs/wakeup.rs | 13 +- src/input/mod.rs | 6 +- src/input/web_api/server/mod.rs | 1 - src/input/youtube_downloader.rs | 691 ------ src/main.rs | 88 +- 28 files changed, 1082 insertions(+), 3423 deletions(-) create mode 100644 src/controller/system/lamps/bridge_connect.rs create mode 100644 src/controller/system/lamps/eventually_consistent_bridge.rs create mode 100644 src/controller/system/lamps/lamp.rs create mode 100644 src/input/api.rs delete mode 100644 src/input/bot/mod.rs delete mode 100644 src/input/bot/set_alarm.rs delete mode 100644 src/input/bot/youtube_dl.rs delete mode 100644 src/input/youtube_downloader.rs diff --git a/Cargo.lock b/Cargo.lock index c39674c7..e05d80b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,475 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "HomeAutomation" -version = "0.1.0" -dependencies = [ - "actix-files", - "actix-identity", - "actix-net", - "actix-rt", - "actix-service", - "actix-web", - "actix-web-httpauth", - "async-std", - "async-trait", - "bincode", - "bme280", - "byteorder", - "bytes 0.4.12", - "chrono", - "chrono-tz", - "crossbeam-channel 0.3.9", - "dirs", - "fern", - "futures 0.3.25", - "gpio-cdev", - "hex", - "linux-embedded-hal", - "log 0.4.17", - "mpd", - "nix 0.17.0", - "num 0.2.1", - "pagecache", - "philipshue", - "rand 0.6.5", - "regex", - "reqwest 0.10.10", - "retry", - "ring", - "rustls 0.16.0", - "sensor_value", - "serde", - "serde_json", - "serde_yaml", - "sled", - "smallvec 0.6.14", - "smol", - "structopt", - "telegram-bot", - "thiserror", -] - -[[package]] -name = "actix" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c616db5fa4b0c40702fb75201c2af7f8aa8f3a2e2c1dda3b0655772aa949666" -dependencies = [ - "actix_derive", - "bitflags 1.3.2", - "bytes 0.4.12", - "crossbeam-channel 0.3.9", - "failure", - "fnv", - "futures 0.1.31", - "libc", - "log 0.4.17", - "parking_lot 0.7.1", - "smallvec 0.6.14", - "tokio 0.1.22", - "tokio-codec", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "tokio-signal", - "tokio-tcp", - "tokio-timer", - "trust-dns-proto 0.5.0", - "trust-dns-resolver 0.10.3", - "uuid", -] - -[[package]] -name = "actix-codec" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09e55f0a5c2ca15795035d90c46bd0e73a5123b72f68f12596d6ba5282051380" -dependencies = [ - "bitflags 1.3.2", - "bytes 0.5.6", - "futures-core", - "futures-sink", - "log 0.4.17", - "tokio 0.2.25", - "tokio-util 0.2.0", -] - -[[package]] -name = "actix-codec" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78d1833b3838dbe990df0f1f87baf640cf6146e898166afe401839d1b001e570" -dependencies = [ - "bitflags 1.3.2", - "bytes 0.5.6", - "futures-core", - "futures-sink", - "log 0.4.17", - "pin-project 0.4.30", - "tokio 0.2.25", - "tokio-util 0.3.1", -] - -[[package]] -name = "actix-connect" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95cc9569221e9802bf4c377f6c18b90ef10227d787611decf79fd47d2a8e76c" -dependencies = [ - "actix-codec 0.2.0", - "actix-rt", - "actix-service", - "actix-utils 1.0.6", - "derive_more", - "either", - "futures 0.3.25", - "http 0.2.8", - "log 0.4.17", - "rustls 0.16.0", - "tokio-rustls 0.12.3", - "trust-dns-proto 0.18.0-alpha.2", - "trust-dns-resolver 0.18.0-alpha.2", - "webpki", -] - -[[package]] -name = "actix-files" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193b22cb1f7b4ff12a4eb2415d6d19e47e44ea93e05930b30d05375ea29d3529" -dependencies = [ - "actix-http", - "actix-service", - "actix-web", - "bitflags 1.3.2", - "bytes 0.5.6", - "derive_more", - "futures-core", - "futures-util", - "log 0.4.17", - "mime 0.3.16", - "mime_guess 2.0.4", - "percent-encoding 2.2.0", - "v_htmlescape", -] - -[[package]] -name = "actix-http" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c16664cc4fdea8030837ad5a845eb231fb93fc3c5c171edfefb52fad92ce9019" -dependencies = [ - "actix-codec 0.2.0", - "actix-connect", - "actix-rt", - "actix-service", - "actix-threadpool", - "actix-tls", - "actix-utils 1.0.6", - "base64 0.11.0", - "bitflags 1.3.2", - "brotli2", - "bytes 0.5.6", - "chrono", - "copyless", - "derive_more", - "either", - "encoding_rs", - "failure", - "flate2", - "futures-channel", - "futures-core", - "futures-util", - "fxhash", - "h2 0.2.7", - "http 0.2.8", - "httparse", - "indexmap", - "language-tags", - "lazy_static", - "log 0.4.17", - "mime 0.3.16", - "percent-encoding 2.2.0", - "pin-project 0.4.30", - "rand 0.7.3", - "regex", - "ring", - "serde", - "serde_json", - "serde_urlencoded 0.6.1", - "sha1", - "slab", - "time", -] - -[[package]] -name = "actix-identity" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a379b0639c293292d71defb8cc1f94c87b7705c904adf044338ad392df77c7a" -dependencies = [ - "actix-service", - "actix-web", - "futures 0.3.25", - "serde", - "serde_json", - "time", -] - -[[package]] -name = "actix-macros" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ca8ce00b267af8ccebbd647de0d61e0674b6e61185cc7a592ff88772bed655" -dependencies = [ - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "actix-net" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bebfbe6629e0131730746718c9e032b58f02c6ce06ed7c982b9fef6c8545acd" -dependencies = [ - "actix", - "bytes 0.4.12", - "futures 0.1.31", - "log 0.4.17", - "mio", - "net2", - "num_cpus", - "slab", - "tokio 0.1.22", - "tokio-codec", - "tokio-current-thread", - "tokio-io", - "tokio-reactor", - "tokio-tcp", - "tokio-timer", - "tower-service 0.1.0", - "trust-dns-resolver 0.10.3", -] - -[[package]] -name = "actix-router" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ad299af73649e1fc893e333ccf86f377751eb95ff875d095131574c6f43452c" -dependencies = [ - "bytestring", - "http 0.2.8", - "log 0.4.17", - "regex", - "serde", -] - -[[package]] -name = "actix-rt" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143fcc2912e0d1de2bcf4e2f720d2a60c28652ab4179685a1ee159e0fb3db227" -dependencies = [ - "actix-macros", - "actix-threadpool", - "copyless", - "futures-channel", - "futures-util", - "smallvec 1.10.0", - "tokio 0.2.25", -] - -[[package]] -name = "actix-server" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45407e6e672ca24784baa667c5d32ef109ccdd8d5e0b5ebb9ef8a67f4dfb708e" -dependencies = [ - "actix-codec 0.3.0", - "actix-rt", - "actix-service", - "actix-utils 2.0.0", - "futures-channel", - "futures-util", - "log 0.4.17", - "mio", - "mio-uds", - "num_cpus", - "slab", - "socket2 0.3.19", -] - -[[package]] -name = "actix-service" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0052435d581b5be835d11f4eb3bce417c8af18d87ddf8ace99f8e67e595882bb" -dependencies = [ - "futures-util", - "pin-project 0.4.30", -] - -[[package]] -name = "actix-testing" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47239ca38799ab74ee6a8a94d1ce857014b2ac36f242f70f3f75a66f691e791c" -dependencies = [ - "actix-macros", - "actix-rt", - "actix-server", - "actix-service", - "log 0.4.17", - "socket2 0.3.19", -] - -[[package]] -name = "actix-threadpool" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d209f04d002854b9afd3743032a27b066158817965bf5d036824d19ac2cc0e30" -dependencies = [ - "derive_more", - "futures-channel", - "lazy_static", - "log 0.4.17", - "num_cpus", - "parking_lot 0.11.2", - "threadpool", -] - -[[package]] -name = "actix-tls" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e5b4faaf105e9a6d389c606c298dcdb033061b00d532af9df56ff3a54995a8" -dependencies = [ - "actix-codec 0.2.0", - "actix-rt", - "actix-service", - "actix-utils 1.0.6", - "derive_more", - "either", - "futures 0.3.25", - "log 0.4.17", - "rustls 0.16.0", - "tokio-rustls 0.12.3", - "webpki", - "webpki-roots 0.17.0", -] - -[[package]] -name = "actix-utils" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcf8f5631bf01adec2267808f00e228b761c60c0584cc9fa0b5364f41d147f4e" -dependencies = [ - "actix-codec 0.2.0", - "actix-rt", - "actix-service", - "bitflags 1.3.2", - "bytes 0.5.6", - "either", - "futures 0.3.25", - "log 0.4.17", - "pin-project 0.4.30", - "slab", -] - -[[package]] -name = "actix-utils" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9022dec56632d1d7979e59af14f0597a28a830a9c1c7fec8b2327eb9f16b5a" -dependencies = [ - "actix-codec 0.3.0", - "actix-rt", - "actix-service", - "bitflags 1.3.2", - "bytes 0.5.6", - "either", - "futures-channel", - "futures-sink", - "futures-util", - "log 0.4.17", - "pin-project 0.4.30", - "slab", -] - -[[package]] -name = "actix-web" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3158e822461040822f0dbf1735b9c2ce1f95f93b651d7a7aded00b1efbb1f635" -dependencies = [ - "actix-codec 0.2.0", - "actix-http", - "actix-macros", - "actix-router", - "actix-rt", - "actix-server", - "actix-service", - "actix-testing", - "actix-threadpool", - "actix-tls", - "actix-utils 1.0.6", - "actix-web-codegen", - "awc", - "bytes 0.5.6", - "derive_more", - "encoding_rs", - "futures 0.3.25", - "fxhash", - "log 0.4.17", - "mime 0.3.16", - "net2", - "pin-project 0.4.30", - "regex", - "rustls 0.16.0", - "serde", - "serde_json", - "serde_urlencoded 0.6.1", - "time", - "url 2.3.1", -] - -[[package]] -name = "actix-web-codegen" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a71bf475cbe07281d0b3696abb48212db118e7e23219f13596ce865235ff5766" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "actix-web-httpauth" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea25b3a3e113d04ae74bfbc3ba617f6254437dbd03576d9b479e8e8df894285" -dependencies = [ - "actix-service", - "actix-web", - "base64 0.12.3", - "bytes 0.5.6", - "futures-util", -] - -[[package]] -name = "actix_derive" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4300e9431455322ae393d43a2ba1ef96b8080573c0fc23b196219efedfb6ba69" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.44", -] - [[package]] name = "addr2line" version = "0.17.0" @@ -513,176 +44,17 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "arrayvec" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -dependencies = [ - "nodrop", -] - -[[package]] -name = "async-channel" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28" -dependencies = [ - "concurrent-queue 1.2.4", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-executor" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" -dependencies = [ - "async-lock", - "async-task", - "concurrent-queue 2.0.0", - "fastrand", - "futures-lite", - "slab", -] - -[[package]] -name = "async-fs" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" -dependencies = [ - "async-lock", - "autocfg 1.1.0", - "blocking", - "futures-lite", -] - -[[package]] -name = "async-global-executor" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" -dependencies = [ - "async-channel", - "async-executor", - "async-io", - "async-lock", - "blocking", - "futures-lite", - "once_cell", -] - -[[package]] -name = "async-io" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" -dependencies = [ - "async-lock", - "autocfg 1.1.0", - "concurrent-queue 2.0.0", - "futures-lite", - "libc", - "log 0.4.17", - "parking", - "polling", - "slab", - "socket2 0.4.7", - "waker-fn", - "windows-sys 0.42.0", -] - -[[package]] -name = "async-lock" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" -dependencies = [ - "event-listener", - "futures-lite", -] - -[[package]] -name = "async-net" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4051e67316bc7eff608fe723df5d32ed639946adcd69e07df41fd42a7b411f1f" -dependencies = [ - "async-io", - "autocfg 1.1.0", - "blocking", - "futures-lite", -] - -[[package]] -name = "async-process" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6381ead98388605d0d9ff86371043b5aa922a3905824244de40dc263a14fcba4" -dependencies = [ - "async-io", - "async-lock", - "autocfg 1.1.0", - "blocking", - "cfg-if 1.0.0", - "event-listener", - "futures-lite", - "libc", - "signal-hook", - "windows-sys 0.42.0", -] - -[[package]] -name = "async-std" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" -dependencies = [ - "async-channel", - "async-global-executor", - "async-io", - "async-lock", - "crossbeam-utils 0.8.14", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers", - "kv-log-macro", - "log 0.4.17", - "memchr", - "once_cell", - "pin-project-lite 0.2.9", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - -[[package]] -name = "async-task" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" - [[package]] name = "async-trait" -version = "0.1.58" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2", + "quote", + "syn 2.0.48", ] -[[package]] -name = "atomic-waker" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" - [[package]] name = "atty" version = "0.2.14" @@ -710,27 +82,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] -name = "awc" -version = "1.0.1" +name = "axum" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7601d4d1d7ef2335d6597a41b5fe069f6ab799b85f53565ab390e7b7065aac5" +checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e" dependencies = [ - "actix-codec 0.2.0", - "actix-http", - "actix-rt", - "actix-service", - "base64 0.11.0", - "bytes 0.5.6", - "derive_more", - "futures-core", - "log 0.4.17", + "async-trait", + "axum-core", + "bytes 1.3.0", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.2.0", + "hyper-util", + "itoa 1.0.10", + "matchit", + "memchr", "mime 0.3.16", "percent-encoding 2.2.0", - "rand 0.7.3", - "rustls 0.16.0", + "pin-project-lite 0.2.13", + "rustversion", "serde", "serde_json", - "serde_urlencoded 0.6.1", + "serde_path_to_error", + "serde_urlencoded 0.7.1", + "sync_wrapper", + "tokio 1.35.1", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +dependencies = [ + "async-trait", + "bytes 1.3.0", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "mime 0.3.16", + "pin-project-lite 0.2.13", + "rustversion", + "sync_wrapper", + "tower-layer", + "tower-service", + "tracing", ] [[package]] @@ -757,12 +160,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "base64" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" - [[package]] name = "base64" version = "0.12.3" @@ -816,20 +213,6 @@ dependencies = [ "text_io", ] -[[package]] -name = "blocking" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8" -dependencies = [ - "async-channel", - "async-lock", - "async-task", - "atomic-waker", - "fastrand", - "futures-lite", -] - [[package]] name = "bme280" version = "0.1.2" @@ -839,26 +222,6 @@ dependencies = [ "embedded-hal", ] -[[package]] -name = "brotli-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "brotli2" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" -dependencies = [ - "brotli-sys", - "libc", -] - [[package]] name = "bufstream" version = "0.1.4" @@ -900,21 +263,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" -[[package]] -name = "bytestring" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7f83e57d9154148e355404702e2694463241880b939570d7c97c014da7a69a1" -dependencies = [ - "bytes 1.3.0", -] - -[[package]] -name = "cache-padded" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" - [[package]] name = "cast" version = "0.2.7" @@ -1010,32 +358,8 @@ checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59" dependencies = [ "atty", "lazy_static", - "winapi 0.3.9", -] - -[[package]] -name = "concurrent-queue" -version = "1.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" -dependencies = [ - "cache-padded", -] - -[[package]] -name = "concurrent-queue" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7bef69dc86e3c610e4e7aed41035e2a7ed12e72dd7530f61327a6579a4390b" -dependencies = [ - "crossbeam-utils 0.8.14", -] - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + "winapi 0.3.9", +] [[package]] name = "cookie" @@ -1065,12 +389,6 @@ dependencies = [ "url 1.7.2", ] -[[package]] -name = "copyless" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" - [[package]] name = "core-foundation" version = "0.6.4" @@ -1111,16 +429,6 @@ dependencies = [ "crossbeam-utils 0.6.6", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.14", -] - [[package]] name = "crossbeam-deque" version = "0.7.4" @@ -1132,31 +440,6 @@ dependencies = [ "maybe-uninit", ] -[[package]] -name = "crossbeam-deque" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-epoch 0.9.13", - "crossbeam-utils 0.8.14", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" -dependencies = [ - "arrayvec", - "cfg-if 0.1.10", - "crossbeam-utils 0.6.6", - "lazy_static", - "memoffset 0.5.6", - "scopeguard 1.1.0", -] - [[package]] name = "crossbeam-epoch" version = "0.8.2" @@ -1169,7 +452,7 @@ dependencies = [ "lazy_static", "maybe-uninit", "memoffset 0.5.6", - "scopeguard 1.1.0", + "scopeguard", ] [[package]] @@ -1182,7 +465,7 @@ dependencies = [ "cfg-if 1.0.0", "crossbeam-utils 0.8.14", "memoffset 0.7.1", - "scopeguard 1.1.0", + "scopeguard", ] [[package]] @@ -1235,16 +518,6 @@ dependencies = [ "sct", ] -[[package]] -name = "ctor" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" -dependencies = [ - "quote 1.0.21", - "syn 1.0.103", -] - [[package]] name = "cxx" version = "1.0.82" @@ -1266,8 +539,8 @@ dependencies = [ "cc", "codespan-reporting", "once_cell", - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2", + "quote", "scratch", "syn 1.0.103", ] @@ -1284,21 +557,8 @@ version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "convert_case", - "proc-macro2 1.0.47", - "quote 1.0.21", - "rustc_version 0.4.0", + "proc-macro2", + "quote", "syn 1.0.103", ] @@ -1355,25 +615,10 @@ dependencies = [ ] [[package]] -name = "enum-as-inner" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4" -dependencies = [ - "heck 0.4.0", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "error-chain" -version = "0.8.1" +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" -dependencies = [ - "backtrace", -] +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "error-chain" @@ -1384,12 +629,6 @@ dependencies = [ "backtrace", ] -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - [[package]] name = "failure" version = "0.1.8" @@ -1406,8 +645,8 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2", + "quote", "syn 1.0.103", "synstructure", ] @@ -1512,9 +751,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.25" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1522,9 +761,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-cpupool" @@ -1549,53 +788,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.25" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" - -[[package]] -name = "futures-lite" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite 0.2.9", - "waker-fn", -] +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.25" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2", + "quote", + "syn 2.0.48", ] [[package]] name = "futures-sink" -version = "0.3.25" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.25" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.25" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -1604,7 +828,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "pin-utils", "slab", ] @@ -1618,17 +842,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.8" @@ -1646,28 +859,6 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" -[[package]] -name = "gloo-timers" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "gpio-cdev" -version = "0.5.1" -source = "git+https://github.com/rust-embedded/gpio-cdev?branch=master#2c7ef82343e1331cc2805dc682afb3a699d0da7d" -dependencies = [ - "bitflags 1.3.2", - "libc", - "nix 0.23.1", -] - [[package]] name = "h2" version = "0.1.26" @@ -1679,7 +870,7 @@ dependencies = [ "fnv", "futures 0.1.31", "http 0.1.21", - "indexmap", + "indexmap 1.9.2", "log 0.4.17", "slab", "string", @@ -1698,7 +889,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.8", - "indexmap", + "indexmap 1.9.2", "slab", "tokio 0.2.25", "tokio-util 0.3.1", @@ -1707,12 +898,63 @@ dependencies = [ ] [[package]] -name = "hashbrown" -version = "0.3.1" +name = "h2" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29fba9abe4742d586dfd0c06ae4f7e73a1c2d86b856933509b269d82cdf06e18" +checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943" +dependencies = [ + "bytes 1.3.0", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 1.1.0", + "indexmap 2.2.5", + "slab", + "tokio 1.35.1", + "tokio-util 0.7.10", + "tracing", +] + +[[package]] +name = "ha" +version = "0.1.0" dependencies = [ + "axum", + "bincode", + "bme280", + "byteorder", + "bytes 0.4.12", + "chrono", + "chrono-tz", + "crossbeam-channel", + "dirs", + "fern", + "futures 0.3.25", + "futures-util", + "hex", + "linux-embedded-hal", + "log-panics", + "mpd", + "num 0.2.1", + "philipshue", + "rand 0.6.5", + "regex", + "reqwest 0.10.10", + "retry", + "sensor_value", "serde", + "serde_json", + "serde_yaml", + "sled", + "smallvec 0.6.14", + "structopt", + "telegram-bot", + "thiserror", + "tokio 1.35.1", + "tracing", + "tracing-journald", + "tracing-subscriber", ] [[package]] @@ -1721,6 +963,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + [[package]] name = "heck" version = "0.3.3" @@ -1730,12 +978,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "heck" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" - [[package]] name = "hermit-abi" version = "0.1.19" @@ -1751,23 +993,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "historian" -version = "4.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cae74efdb3c09c2dfbba9351363eebae2ac129f8e07dba620747b80324917657" - -[[package]] -name = "hostname" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" -dependencies = [ - "libc", - "match_cfg", - "winapi 0.3.9", -] - [[package]] name = "http" version = "0.1.21" @@ -1787,7 +1012,18 @@ checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes 1.3.0", "fnv", - "itoa 1.0.4", + "itoa 1.0.10", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes 1.3.0", + "fnv", + "itoa 1.0.10", ] [[package]] @@ -1812,6 +1048,29 @@ dependencies = [ "http 0.2.8", ] +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes 1.3.0", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" +dependencies = [ + "bytes 1.3.0", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "pin-project-lite 0.2.13", +] + [[package]] name = "httparse" version = "1.8.0" @@ -1824,6 +1083,12 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + [[package]] name = "hyper" version = "0.12.36" @@ -1868,16 +1133,36 @@ dependencies = [ "http 0.2.8", "http-body 0.3.1", "httparse", - "httpdate", + "httpdate 0.3.2", "itoa 0.4.8", - "pin-project 1.0.12", + "pin-project", "socket2 0.3.19", "tokio 0.2.25", - "tower-service 0.3.2", + "tower-service", "tracing", "want 0.3.0", ] +[[package]] +name = "hyper" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +dependencies = [ + "bytes 1.3.0", + "futures-channel", + "futures-util", + "h2 0.4.2", + "http 1.1.0", + "http-body 1.0.0", + "httparse", + "httpdate 1.0.3", + "itoa 1.0.10", + "pin-project-lite 0.2.13", + "smallvec 1.13.1", + "tokio 1.35.1", +] + [[package]] name = "hyper-rustls" version = "0.17.1" @@ -1928,6 +1213,22 @@ dependencies = [ "webpki", ] +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes 1.3.0", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.2.0", + "pin-project-lite 0.2.13", + "socket2 0.5.5", + "tokio 1.35.1", +] + [[package]] name = "i2cdev" version = "0.4.4" @@ -2006,6 +1307,16 @@ dependencies = [ "hashbrown 0.12.3", ] +[[package]] +name = "indexmap" +version = "2.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", +] + [[package]] name = "instant" version = "0.1.12" @@ -2024,31 +1335,6 @@ dependencies = [ "libc", ] -[[package]] -name = "ipconfig" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f7eadeaf4b52700de180d147c4805f199854600b36faa963d91114827b2ffc" -dependencies = [ - "error-chain 0.8.1", - "socket2 0.3.19", - "widestring 0.2.2", - "winapi 0.3.9", - "winreg 0.5.1", -] - -[[package]] -name = "ipconfig" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" -dependencies = [ - "socket2 0.3.19", - "widestring 0.4.3", - "winapi 0.3.9", - "winreg 0.6.2", -] - [[package]] name = "ipnet" version = "2.5.1" @@ -2063,9 +1349,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.4" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" @@ -2082,24 +1368,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log 0.4.17", -] - -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" + "winapi 0.2.8", + "winapi-build", +] [[package]] name = "lazy_static" @@ -2109,9 +1380,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.137" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "link-cplusplus" @@ -2141,23 +1412,13 @@ dependencies = [ "sysfs_gpio", ] -[[package]] -name = "lock_api" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -dependencies = [ - "owning_ref", - "scopeguard 0.3.3", -] - [[package]] name = "lock_api" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" dependencies = [ - "scopeguard 1.1.0", + "scopeguard", ] [[package]] @@ -2167,7 +1428,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg 1.1.0", - "scopeguard 1.1.0", + "scopeguard", ] [[package]] @@ -2186,23 +1447,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if 1.0.0", - "value-bag", ] [[package]] -name = "lru-cache" -version = "0.1.2" +name = "log-panics" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +checksum = "68f9dd8546191c1850ecf67d22f5ff00a935b890d0e84713159a55495cc2ac5f" dependencies = [ - "linked-hash-map", + "log 0.4.17", ] [[package]] -name = "match_cfg" +name = "matchers" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] [[package]] name = "matches" @@ -2210,6 +1473,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + [[package]] name = "maybe-uninit" version = "2.0.0" @@ -2231,15 +1500,6 @@ dependencies = [ "autocfg 1.1.0", ] -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg 1.1.0", -] - [[package]] name = "memoffset" version = "0.7.1" @@ -2324,14 +1584,14 @@ dependencies = [ ] [[package]] -name = "mio-uds" -version = "0.6.8" +name = "mio" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ - "iovec", "libc", - "mio", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.48.0", ] [[package]] @@ -2348,13 +1608,11 @@ dependencies = [ [[package]] name = "mpd" -version = "0.0.12" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a20784da57fa01bf7910a5da686d9f39ff37feaa774856b71f050e4331bf82" +checksum = "2e12cace5746cb0aa78faa6cd2caec9f9c01882fc0e6b54d34685a2d3303ea34" dependencies = [ "bufstream", - "rustc-serialize", - "time", ] [[package]] @@ -2424,45 +1682,13 @@ dependencies = [ ] [[package]] -name = "nix" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" -dependencies = [ - "bitflags 1.3.2", - "cc", - "cfg-if 0.1.10", - "libc", - "void", -] - -[[package]] -name = "nix" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" -dependencies = [ - "bitflags 1.3.2", - "cc", - "cfg-if 1.0.0", - "libc", - "memoffset 0.6.5", -] - -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - -[[package]] -name = "nom" -version = "4.2.3" +name = "nu-ansi-term" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ - "memchr", - "version_check 0.1.5", + "overload", + "winapi 0.3.9", ] [[package]] @@ -2609,9 +1835,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.16.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl-probe" @@ -2629,51 +1855,10 @@ dependencies = [ ] [[package]] -name = "owning_ref" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce" -dependencies = [ - "stable_deref_trait", -] - -[[package]] -name = "pagecache" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74a701d13e2f3ee32a50be43321da8f712cf1e6e9ff0e2be66ab7f5c6598a16a" -dependencies = [ - "bincode", - "crc32fast", - "crossbeam-epoch 0.7.2", - "crossbeam-utils 0.6.6", - "fs2", - "futures 0.1.31", - "fxhash", - "hashbrown 0.3.1", - "historian", - "lazy_static", - "libc", - "log 0.4.17", - "rayon", - "serde", -] - -[[package]] -name = "parking" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" - -[[package]] -name = "parking_lot" -version = "0.7.1" +name = "overload" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" -dependencies = [ - "lock_api 0.1.5", - "parking_lot_core 0.4.0", -] +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parking_lot" @@ -2698,16 +1883,13 @@ dependencies = [ ] [[package]] -name = "parking_lot_core" -version = "0.4.0" +name = "parking_lot" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ - "libc", - "rand 0.6.5", - "rustc_version 0.2.3", - "smallvec 0.6.14", - "winapi 0.3.9", + "lock_api 0.4.9", + "parking_lot_core 0.9.9", ] [[package]] @@ -2735,10 +1917,23 @@ dependencies = [ "instant", "libc", "redox_syscall 0.2.16", - "smallvec 1.10.0", + "smallvec 1.13.1", "winapi 0.3.9", ] +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall 0.4.1", + "smallvec 1.13.1", + "windows-targets", +] + [[package]] name = "parse-zoneinfo" version = "0.3.0" @@ -2804,40 +1999,20 @@ name = "philipshue" version = "0.3.2" source = "git+https://github.com/dskleingeld/philipshue?branch=master#c52c7fa306a78c3432f5619bb4de75ccd55fb19f" dependencies = [ - "error-chain 0.11.0", + "error-chain", "reqwest 0.9.24", "serde", "serde_derive", "serde_json", ] -[[package]] -name = "pin-project" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef0f924a5ee7ea9cbcea77529dba45f8a9ba9f622419fe3386ca581a3ae9d5a" -dependencies = [ - "pin-project-internal 0.4.30", -] - [[package]] name = "pin-project" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ - "pin-project-internal 1.0.12", -] - -[[package]] -name = "pin-project-internal" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "851c8d0ce9bebe43790dedfc86614c23494ac9f423dd618d3a61fc693eafe61e" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "pin-project-internal", ] [[package]] @@ -2846,8 +2021,8 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2", + "quote", "syn 1.0.103", ] @@ -2859,9 +2034,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -2869,20 +2044,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "polling" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7d73f1eaed1ca1fb37b54dcc9b38e3b17d6c7b8ecb7abfffcac8d0351f17d4" -dependencies = [ - "autocfg 1.1.0", - "cfg-if 1.0.0", - "libc", - "log 0.4.17", - "wepoll-ffi", - "windows-sys 0.42.0", -] - [[package]] name = "ppv-lite86" version = "0.2.17" @@ -2896,8 +2057,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2", + "quote", "syn 1.0.103", "version_check 0.9.4", ] @@ -2908,25 +2069,16 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2", + "quote", "version_check 0.9.4", ] [[package]] name = "proc-macro2" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -dependencies = [ - "unicode-xid 0.1.0", -] - -[[package]] -name = "proc-macro2" -version = "1.0.47" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -2941,28 +2093,13 @@ dependencies = [ "url 2.3.1", ] -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quote" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -dependencies = [ - "proc-macro2 0.4.30", -] - [[package]] name = "quote" -version = "1.0.21" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ - "proc-macro2 1.0.47", + "proc-macro2", ] [[package]] @@ -2988,7 +2125,7 @@ dependencies = [ "libc", "rand_chacha 0.1.1", "rand_core 0.4.2", - "rand_hc 0.1.0", + "rand_hc", "rand_isaac", "rand_jitter", "rand_os", @@ -2997,19 +2134,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc 0.2.0", -] - [[package]] name = "rand" version = "0.8.5" @@ -3031,16 +2155,6 @@ dependencies = [ "rand_core 0.3.1", ] -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - [[package]] name = "rand_chacha" version = "0.3.1" @@ -3066,22 +2180,13 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.8", + "getrandom", ] [[package]] @@ -3093,15 +2198,6 @@ dependencies = [ "rand_core 0.3.1", ] -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - [[package]] name = "rand_isaac" version = "0.1.1" @@ -3155,29 +2251,6 @@ dependencies = [ "rand_core 0.3.1", ] -[[package]] -name = "rayon" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b" -dependencies = [ - "crossbeam-deque 0.8.2", - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" -dependencies = [ - "crossbeam-channel 0.5.6", - "crossbeam-deque 0.8.2", - "crossbeam-utils 0.8.14", - "num_cpus", -] - [[package]] name = "rdrand" version = "0.4.0" @@ -3202,13 +2275,22 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_users" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.8", + "getrandom", "redox_syscall 0.2.16", "thiserror", ] @@ -3224,6 +2306,15 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + [[package]] name = "regex-syntax" version = "0.6.28" @@ -3297,7 +2388,7 @@ dependencies = [ "mime 0.3.16", "mime_guess 2.0.4", "percent-encoding 2.2.0", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "rustls 0.18.1", "serde", "serde_urlencoded 0.7.1", @@ -3311,16 +2402,6 @@ dependencies = [ "winreg 0.7.0", ] -[[package]] -name = "resolv-conf" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11834e137f3b14e309437a8276714eed3a80d1ef894869e510f2c0c0b98b9f4a" -dependencies = [ - "hostname", - "quick-error", -] - [[package]] name = "retry" version = "1.3.1" @@ -3351,12 +2432,6 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" -[[package]] -name = "rustc-serialize" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" - [[package]] name = "rustc_version" version = "0.1.7" @@ -3422,6 +2497,12 @@ dependencies = [ "security-framework", ] +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "ryu" version = "1.0.11" @@ -3438,12 +2519,6 @@ dependencies = [ "windows-sys 0.36.1", ] -[[package]] -name = "scopeguard" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" - [[package]] name = "scopeguard" version = "1.1.0" @@ -3525,9 +2600,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.147" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] @@ -3544,13 +2619,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.147" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2", + "quote", + "syn 2.0.48", ] [[package]] @@ -3559,33 +2634,31 @@ version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" dependencies = [ - "itoa 1.0.4", + "itoa 1.0.10", "ryu", "serde", ] [[package]] -name = "serde_urlencoded" -version = "0.5.5" +name = "serde_path_to_error" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" +checksum = "ebd154a240de39fdebcf5775d2675c204d7c13cf39a4c697be6493c8e734337c" dependencies = [ - "dtoa", - "itoa 0.4.8", + "itoa 1.0.10", "serde", - "url 1.7.2", ] [[package]] name = "serde_urlencoded" -version = "0.6.1" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" +checksum = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" dependencies = [ "dtoa", "itoa 0.4.8", "serde", - "url 2.3.1", + "url 1.7.2", ] [[package]] @@ -3595,7 +2668,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.4", + "itoa 1.0.10", "ryu", "serde", ] @@ -3606,35 +2679,19 @@ version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ - "indexmap", + "indexmap 1.9.2", "ryu", "serde", "yaml-rust", ] [[package]] -name = "sha1" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" -dependencies = [ - "sha1_smol", -] - -[[package]] -name = "sha1_smol" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" - -[[package]] -name = "signal-hook" -version = "0.3.14" +name = "sharded-slab" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ - "libc", - "signal-hook-registry", + "lazy_static", ] [[package]] @@ -3683,32 +2740,14 @@ version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" dependencies = [ - "maybe-uninit", -] - -[[package]] -name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + "maybe-uninit", +] [[package]] -name = "smol" -version = "1.2.5" +name = "smallvec" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cf3b5351f3e783c1d79ab5fc604eeed8b8ae9abd36b166e8b87a089efd85e4" -dependencies = [ - "async-channel", - "async-executor", - "async-fs", - "async-io", - "async-lock", - "async-net", - "async-process", - "blocking", - "futures-lite", - "once_cell", -] +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "socket2" @@ -3723,12 +2762,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.7" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", - "winapi 0.3.9", + "windows-sys 0.48.0", ] [[package]] @@ -3748,12 +2787,6 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - [[package]] name = "string" version = "0.2.1" @@ -3786,45 +2819,51 @@ version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck 0.3.3", + "heck", "proc-macro-error", - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2", + "quote", "syn 1.0.103", ] [[package]] name = "syn" -version = "0.15.44" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "unicode-xid 0.1.0", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] name = "syn" -version = "1.0.103" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2", + "quote", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "synstructure" version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2", + "quote", "syn 1.0.103", - "unicode-xid 0.2.4", + "unicode-xid", ] [[package]] @@ -3919,18 +2958,19 @@ version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2", + "quote", "syn 1.0.103", ] [[package]] -name = "threadpool" -version = "1.8.1" +name = "thread_local" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ - "num_cpus", + "cfg-if 1.0.0", + "once_cell", ] [[package]] @@ -3967,20 +3007,15 @@ checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" dependencies = [ "bytes 0.4.12", "futures 0.1.31", - "mio", + "mio 0.6.23", "num_cpus", - "tokio-codec", "tokio-current-thread", "tokio-executor", - "tokio-fs", "tokio-io", "tokio-reactor", - "tokio-sync", "tokio-tcp", "tokio-threadpool", "tokio-timer", - "tokio-udp", - "tokio-uds", ] [[package]] @@ -3994,36 +3029,40 @@ dependencies = [ "futures-core", "iovec", "lazy_static", - "libc", "memchr", - "mio", - "mio-uds", + "mio 0.6.23", "pin-project-lite 0.1.12", - "signal-hook-registry", "slab", - "winapi 0.3.9", ] [[package]] -name = "tokio-buf" -version = "0.1.1" +name = "tokio" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" +checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ - "bytes 0.4.12", - "either", - "futures 0.1.31", + "backtrace", + "bytes 1.3.0", + "libc", + "mio 0.8.10", + "num_cpus", + "parking_lot 0.12.1", + "pin-project-lite 0.2.13", + "signal-hook-registry", + "socket2 0.5.5", + "tokio-macros", + "windows-sys 0.48.0", ] [[package]] -name = "tokio-codec" -version = "0.1.2" +name = "tokio-buf" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" +checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" dependencies = [ "bytes 0.4.12", + "either", "futures 0.1.31", - "tokio-io", ] [[package]] @@ -4046,17 +3085,6 @@ dependencies = [ "futures 0.1.31", ] -[[package]] -name = "tokio-fs" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" -dependencies = [ - "futures 0.1.31", - "tokio-io", - "tokio-threadpool", -] - [[package]] name = "tokio-io" version = "0.1.13" @@ -4068,6 +3096,17 @@ dependencies = [ "log 0.4.17", ] +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "tokio-reactor" version = "0.1.12" @@ -4078,7 +3117,7 @@ dependencies = [ "futures 0.1.31", "lazy_static", "log 0.4.17", - "mio", + "mio 0.6.23", "num_cpus", "parking_lot 0.9.0", "slab", @@ -4125,23 +3164,6 @@ dependencies = [ "webpki", ] -[[package]] -name = "tokio-signal" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c34c6e548f101053321cba3da7cbb87a610b85555884c41b07da2eb91aff12" -dependencies = [ - "futures 0.1.31", - "libc", - "mio", - "mio-uds", - "signal-hook-registry", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "winapi 0.3.9", -] - [[package]] name = "tokio-sync" version = "0.1.8" @@ -4161,7 +3183,7 @@ dependencies = [ "bytes 0.4.12", "futures 0.1.31", "iovec", - "mio", + "mio 0.6.23", "tokio-io", "tokio-reactor", ] @@ -4172,7 +3194,7 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" dependencies = [ - "crossbeam-deque 0.7.4", + "crossbeam-deque", "crossbeam-queue", "crossbeam-utils 0.7.2", "futures 0.1.31", @@ -4195,44 +3217,11 @@ dependencies = [ "tokio-executor", ] -[[package]] -name = "tokio-udp" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "log 0.4.17", - "mio", - "tokio-codec", - "tokio-io", - "tokio-reactor", -] - -[[package]] -name = "tokio-uds" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "iovec", - "libc", - "log 0.4.17", - "mio", - "mio-uds", - "tokio-codec", - "tokio-io", - "tokio-reactor", -] - [[package]] name = "tokio-util" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" +checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" dependencies = [ "bytes 0.5.6", "futures-core", @@ -4244,27 +3233,40 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.3.1" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ - "bytes 0.5.6", + "bytes 1.3.0", "futures-core", "futures-sink", - "log 0.4.17", - "pin-project-lite 0.1.12", - "tokio 0.2.25", + "pin-project-lite 0.2.13", + "tokio 1.35.1", + "tracing", ] [[package]] -name = "tower-service" -version = "0.1.0" +name = "tower" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b32f72af77f1bfe3d3d4da8516a238ebe7039b51dd8637a09841ac7f16d2c987" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ - "futures 0.1.31", + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite 0.2.13", + "tokio 1.35.1", + "tower-layer", + "tower-service", + "tracing", ] +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -4273,35 +3275,35 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if 1.0.0", "log 0.4.17", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "tracing-attributes", "tracing-core", ] [[package]] name = "tracing-attributes" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2", + "quote", + "syn 2.0.48", ] [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", + "valuable", ] [[package]] @@ -4310,114 +3312,48 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ - "pin-project 1.0.12", + "pin-project", "tracing", ] [[package]] -name = "trust-dns-proto" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0838272e89f1c693b4df38dc353412e389cf548ceed6f9fd1af5a8d6e0e7cf74" -dependencies = [ - "byteorder", - "failure", - "futures 0.1.31", - "idna 0.1.5", - "lazy_static", - "log 0.4.17", - "rand 0.5.6", - "smallvec 0.6.14", - "socket2 0.3.19", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "tokio-tcp", - "tokio-timer", - "tokio-udp", - "url 1.7.2", -] - -[[package]] -name = "trust-dns-proto" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09144f0992b0870fa8d2972cc069cbf1e3c0fda64d1f3d45c4d68d0e0b52ad4e" -dependencies = [ - "byteorder", - "failure", - "futures 0.1.31", - "idna 0.1.5", - "lazy_static", - "log 0.4.17", - "rand 0.5.6", - "smallvec 0.6.14", - "socket2 0.3.19", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "tokio-tcp", - "tokio-timer", - "tokio-udp", - "url 1.7.2", -] - -[[package]] -name = "trust-dns-proto" -version = "0.18.0-alpha.2" +name = "tracing-journald" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a7f3a2ab8a919f5eca52a468866a67ed7d3efa265d48a652a9a3452272b413f" +checksum = "ba316a74e8fc3c3896a850dba2375928a9fa171b085ecddfc7c054d39970f3fd" dependencies = [ - "async-trait", - "enum-as-inner", - "failure", - "futures 0.3.25", - "idna 0.2.3", - "lazy_static", - "log 0.4.17", - "rand 0.7.3", - "smallvec 1.10.0", - "socket2 0.3.19", - "tokio 0.2.25", - "url 2.3.1", + "libc", + "tracing-core", + "tracing-subscriber", ] [[package]] -name = "trust-dns-resolver" -version = "0.10.3" +name = "tracing-log" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9f877f7a1ad821ab350505e1f1b146a4960402991787191d6d8cab2ce2de2c" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "cfg-if 0.1.10", - "failure", - "futures 0.1.31", - "ipconfig 0.1.9", - "lazy_static", "log 0.4.17", - "lru-cache", - "resolv-conf", - "smallvec 0.6.14", - "tokio 0.1.22", - "trust-dns-proto 0.6.3", + "once_cell", + "tracing-core", ] [[package]] -name = "trust-dns-resolver" -version = "0.18.0-alpha.2" +name = "tracing-subscriber" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ - "cfg-if 0.1.10", - "failure", - "futures 0.3.25", - "ipconfig 0.2.2", - "lazy_static", - "log 0.4.17", - "lru-cache", - "resolv-conf", - "smallvec 1.10.0", - "tokio 0.2.25", - "trust-dns-proto 0.18.0-alpha.2", + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec 1.13.1", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", ] [[package]] @@ -4486,12 +3422,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" - [[package]] name = "unicode-xid" version = "0.2.4" @@ -4536,45 +3466,10 @@ dependencies = [ ] [[package]] -name = "v_escape" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "660b101c07b5d0863deb9e7fb3138777e858d6d2a79f9e6049a27d1cc77c6da6" -dependencies = [ - "v_escape_derive", -] - -[[package]] -name = "v_escape_derive" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae" -dependencies = [ - "nom", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "v_htmlescape" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33e939c0d8cf047514fb6ba7d5aac78bc56677a6938b2ee67000b91f2e97e41" -dependencies = [ - "cfg-if 0.1.10", - "v_escape", -] - -[[package]] -name = "value-bag" -version = "1.0.0-alpha.9" +name = "valuable" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" -dependencies = [ - "ctor", - "version_check 0.9.4", -] +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "vec_map" @@ -4600,12 +3495,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - [[package]] name = "want" version = "0.2.0" @@ -4627,12 +3516,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" @@ -4666,8 +3549,8 @@ dependencies = [ "bumpalo", "log 0.4.17", "once_cell", - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2", + "quote", "syn 1.0.103", "wasm-bindgen-shared", ] @@ -4690,7 +3573,7 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ - "quote 1.0.21", + "quote", "wasm-bindgen-macro-support", ] @@ -4700,8 +3583,8 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2", + "quote", "syn 1.0.103", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -4751,27 +3634,6 @@ dependencies = [ "webpki", ] -[[package]] -name = "wepoll-ffi" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" -dependencies = [ - "cc", -] - -[[package]] -name = "widestring" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" - -[[package]] -name = "widestring" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" - [[package]] name = "winapi" version = "0.2.8" @@ -4830,24 +3692,33 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.0", + "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" @@ -4857,9 +3728,9 @@ checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" [[package]] name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" @@ -4869,9 +3740,9 @@ checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" [[package]] name = "windows_i686_gnu" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" @@ -4881,9 +3752,9 @@ checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" [[package]] name = "windows_i686_msvc" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" @@ -4893,15 +3764,15 @@ checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" [[package]] name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" @@ -4911,18 +3782,9 @@ checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" [[package]] name = "windows_x86_64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" - -[[package]] -name = "winreg" -version = "0.5.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27a759395c1195c4cc5cda607ef6f8f6498f64e78f7900f5de0a127a424704a" -dependencies = [ - "winapi 0.3.9", -] +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winreg" diff --git a/Cargo.toml b/Cargo.toml index 0c828eff..54e19046 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [package] -name = "HomeAutomation" +name = "ha" version = "0.1.0" authors = ["David Kleingeld "] -edition = "2018" +edition = "2021" [features] default = [] @@ -15,18 +15,16 @@ live_server = [] [dependencies] futures = "0.3" -smol = "1.2" -async-std = "1" -async-trait = "0.1" +tokio = { version = "1", features = ["full"] } -actix-web = { version = "2", features = ["rustls"] } -actix-net = "0.2" -actix-identity = "0.2" -actix-files = "0.2" -actix-rt = "1" -actix-service = "1.0" -actix-web-httpauth = "0.4" -rustls = "0.16" +# actix-web = { version = "4", features = ["rustls"] } +# actix-net = "0.2" +# actix-identity = "0.2" +# actix-files = "0.2" +# actix-rt = "1" +# actix-service = "1.0" +# actix-web-httpauth = "0.4" +# rustls = "0.16" philipshue = { git = "https://github.com/dskleingeld/philipshue", branch = "master" } # for local dev purpose we use below targets @@ -39,15 +37,11 @@ serde_yaml = "0.8" bincode = "1.3" thiserror = "1.0" -log = "0.4" fern = { version = "0.5.9", features = ["colored"] } sensor_value = { git = "https://github.com/dskleingeld/sensor_central.git", branch = "main" } -gpio-cdev = { git = "https://github.com/rust-embedded/gpio-cdev", branch = "master" } -nix = "0.17" - -ring = "0.16" - +# nix = "0.17" +# ring = "0.16" linux-embedded-hal = "0.2" bme280 = "0.1" @@ -62,10 +56,10 @@ hex = "0.4.3" crossbeam-channel = "0.3" sled = "0.34" -pagecache = "0.17" +# pagecache = "0.17" reqwest = {version = "0.10", default-features = false, features = ["rustls-tls"]} -mpd = "0.0.12" +mpd = "0.1" dirs = "2" rand = "0.6" retry = "1" @@ -73,3 +67,9 @@ retry = "1" telegram-bot = {version = "0.7", default-features = false, features = ["rustls"]} serde_json = "1.0" regex = "1" +futures-util = "0.3.30" +tracing = "0.1.40" +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +tracing-journald = "0.3.0" +log-panics = "2.1.0" +axum = "0.7.4" diff --git a/src/controller/commands.rs b/src/controller/commands.rs index 98355ad6..a2332ab1 100644 --- a/src/controller/commands.rs +++ b/src/controller/commands.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use tracing::{warn, error}; use super::{Modifications, System}; use crate::controller::state::*; diff --git a/src/controller/environment/mod.rs b/src/controller/environment/mod.rs index 4375a2f0..ba64cc4b 100644 --- a/src/controller/environment/mod.rs +++ b/src/controller/environment/mod.rs @@ -1,11 +1,15 @@ +/// will store a short history of the last sensor values +/// useful for debouncing events (someone passing in front +/// light sensor vs a cloud) + use sensor_value::SensorValue; -struct History { - last_values: Vec, -} +// struct History { +// last_values: Vec, +// } pub struct Environment { - light: History, + // light: History, } impl Environment { @@ -15,9 +19,9 @@ impl Environment { impl std::default::Default for Environment { fn default() -> Self { Environment { - light: History { - last_values: Vec::new(), - }, + // light: History { + // last_values: Vec::new(), + // }, } } } diff --git a/src/controller/mod.rs b/src/controller/mod.rs index a5944cf8..ebdfe92a 100644 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -2,8 +2,9 @@ use crossbeam_channel::RecvTimeoutError::*; use serde::{Deserialize, Serialize}; use std::thread; use std::time::{Duration, Instant}; +use tracing::error; -mod system; +pub mod system; use system::Lighting; mod environment; @@ -79,7 +80,7 @@ pub fn start( let mut system = System { update_period: Duration::from_secs(5), next_update: Instant::now() + Duration::from_secs(5), - lights: Lighting::init()?, + lights: Lighting::start_init(), mpd: mpd_status, wakeup, }; @@ -144,7 +145,7 @@ fn handle_event( let next_state = match (event, current_state) { //specific test code for normal state (Event::Test, State::Normal) => { - dbg!("a test happend while in normal state"); + dbg!("a test happened while in normal state"); None } //general code that is the same for all functions, unless specific handlers exist above @@ -155,7 +156,7 @@ fn handle_event( Some(State::WakeUp) } (Event::Test, _) => { - dbg!("a test happend"); + dbg!("a test happened"); None } diff --git a/src/controller/state/lightloop.rs b/src/controller/state/lightloop.rs index dd31e92e..e8ef5fc8 100644 --- a/src/controller/state/lightloop.rs +++ b/src/controller/state/lightloop.rs @@ -12,7 +12,7 @@ impl LightLoop { pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { dbg!("making everything rdy for the lightloop state"); - sys.lights.set_all_ct(0, 200)?; + let _ignore_err = sys.lights.set_all_ct(0, 200); mods.lighting = false; sys.update_period = Duration::from_millis(500); @@ -34,8 +34,7 @@ impl RoomState for LightLoop { Ok(Some(State::Normal)) } else { if !mods.lighting { - dbg!(self.counter); - sys.lights.set_all_ct(self.counter, 200)?; + let _ignore_err = sys.lights.set_all_ct(self.counter, 200); self.counter -= 1; } Ok(None) diff --git a/src/controller/state/normal.rs b/src/controller/state/normal.rs index fb727067..e4bcfcb5 100644 --- a/src/controller/state/normal.rs +++ b/src/controller/state/normal.rs @@ -5,20 +5,19 @@ use crate::errors::Error; use chrono::{Local, NaiveTime}; use std::time::{Duration, Instant}; -fn update_lights(sys: &mut System) -> Result<(), Error> { +fn update_lights(sys: &mut System) { fn hour(h: u8) -> NaiveTime { NaiveTime::from_hms_opt(h as u32, 0, 0).unwrap() } let now = Local::now(); if now.time() > hour(22) || now.time() < hour(6) { - sys.lights.set_all_ct(220, 500)?; + let _ignore_err = sys.lights.set_all_ct(220, 500); } else if now.time() > hour(17) { - sys.lights.set_all_ct(254, 320)?; + let _ignore_err = sys.lights.set_all_ct(254, 320); } else if now.time() >= hour(6) { - sys.lights.set_all_ct(254, 240)?; + let _ignore_err = sys.lights.set_all_ct(254, 240); }; - Ok(()) } #[derive(Default, Clone, Copy)] @@ -26,13 +25,12 @@ pub struct Normal {} impl Normal { pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { - dbg!("making everything rdy for the normal state"); mods.reset(); sys.update_period = Duration::from_secs(5); sys.next_update = Instant::now() + sys.update_period; - update_lights(sys)?; - sys.lights.all_on()?; + update_lights(sys); + let _ignore_err = sys.lights.all_on(); Ok(Box::new(Self::default())) } @@ -47,7 +45,7 @@ impl RoomState for Normal { ) -> Result, Error> { //dbg!("updating normal state"); if !mods.lighting { - update_lights(sys)? + update_lights(sys) } Ok(None) } diff --git a/src/controller/state/off.rs b/src/controller/state/off.rs index b296cc38..212177ec 100644 --- a/src/controller/state/off.rs +++ b/src/controller/state/off.rs @@ -10,7 +10,7 @@ impl Off { pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { mods.reset(); mpd::pause()?; - sys.lights.all_off()?; + let _ignore_err = sys.lights.all_off(); Ok(Box::new(Off {})) } } diff --git a/src/controller/state/silent.rs b/src/controller/state/silent.rs index 47e3b6fd..c1fa01b9 100644 --- a/src/controller/state/silent.rs +++ b/src/controller/state/silent.rs @@ -3,7 +3,6 @@ use super::{RoomState, State}; use crate::controller::system::mpd_control as mpd; use crate::errors::Error; -use philipshue::hue::LightCommand; use std::time::{Duration, Instant}; #[derive(Clone, Copy)] @@ -19,12 +18,10 @@ impl Silent { mpd::pause()?; - sys.lights.single_off(2)?; - let command = LightCommand::default().on().with_bri(77).with_ct(2000); - + let _ignore_err = sys.lights.single_off(2); for lamp_id in &[1, 8, 5, 4, 6] { - sys.lights.bridge.set_light_state(*lamp_id, &command)?; - sys.lights.lamps.get_mut(lamp_id).unwrap().on = true; + let _ignore_err = sys.lights.single_on(*lamp_id); + let _ignore_err = sys.lights.set_ct(*lamp_id, 77, 2000); } Ok(Box::new(Silent {})) diff --git a/src/controller/state/sleep.rs b/src/controller/state/sleep.rs index 993ab682..5a4e2e31 100644 --- a/src/controller/state/sleep.rs +++ b/src/controller/state/sleep.rs @@ -19,8 +19,8 @@ impl Sleep { sys.next_update = Instant::now() + sys.update_period; const RED: (f32, f32, f32) = (1f32, 0f32, 0f32); - sys.lights.set_all_rgb(0, RED)?; - sys.lights.all_on()?; + let _ignore_err = sys.lights.set_all_rgb(0, RED); + let _ignore_err = sys.lights.all_on(); Ok(Box::new(Sleep { start: Instant::now(), @@ -39,7 +39,7 @@ impl RoomState for Sleep { const MUSIC_OFF: Duration = Duration::from_secs(120); if self.start.elapsed() >= LIGHTS_OFF && !mods.lighting { - sys.lights.all_off()?; + let _ignore_err = sys.lights.all_off(); } if self.start.elapsed() >= MUSIC_OFF && !mods.mpd { mpd::pause()?; diff --git a/src/controller/state/wakeup.rs b/src/controller/state/wakeup.rs index 4502b85c..ab101360 100644 --- a/src/controller/state/wakeup.rs +++ b/src/controller/state/wakeup.rs @@ -2,6 +2,7 @@ use super::super::{Environment, Modifications, System}; use super::{RoomState, State}; use crate::controller::system; use retry::{delay::Fixed, retry}; +use tracing::{error, info}; use crate::errors::Error; use std::time::{Duration, Instant}; @@ -49,8 +50,8 @@ impl WakeUp { system::mpd_control::add_from_playlist( mpd, "calm", - chrono::Duration::seconds(3 * 60), - chrono::Duration::seconds(5 * 60), + Duration::from_secs(3 * 60), + Duration::from_secs(5 * 60), ) }) .map_err(WakeUpStateError::SetupPlaylist)?; @@ -59,8 +60,8 @@ impl WakeUp { system::mpd_control::add_from_playlist( mpd, "energetic", - chrono::Duration::seconds(10 * 60), - chrono::Duration::seconds(11 * 60), + Duration::from_secs(10 * 60), + Duration::from_secs(11 * 60), ) }) .map_err(WakeUpStateError::SetupPlaylist)?; @@ -69,8 +70,8 @@ impl WakeUp { system::mpd_control::add_from_playlist( mpd, "active", - chrono::Duration::seconds(30 * 60), - chrono::Duration::seconds(60 * 60), + Duration::from_secs(30 * 60), + Duration::from_secs(60 * 60), ) }) .map_err(WakeUpStateError::SetupPlaylist)?; @@ -78,9 +79,12 @@ impl WakeUp { } } +/* TODO: Hardware backup alarm that triggers if any of this failed + * */ + impl WakeUp { pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { - log::info!("starting wakeup state"); + info!("starting wakeup state"); sys.update_period = Duration::from_secs(UPDATE_PERIOD); sys.next_update = Instant::now() + sys.update_period; @@ -89,9 +93,9 @@ impl WakeUp { mods.mpd = false; if let Err(e) = Self::setup_playlist() { - log::error!("could not set up playlist: {}", e); + error!("could not set up playlist: {}", e); } - sys.lights.set_all_on_ct(0, CT_BEGIN)?; + let _ignore_err = sys.lights.set_all_ct(1, CT_BEGIN); Ok(Box::new(Self { start: Instant::now(), @@ -117,7 +121,7 @@ impl RoomState for WakeUp { if !mods.lighting { let bri = (BRI_PER_SECOND * (elapsed as f32)) as u8; let ct = CT_BEGIN - (CT_PER_SECOND * (elapsed as f32)) as u16; - sys.lights.set_all_on_ct(bri, ct)?; + let _ignore_err = sys.lights.set_all_ct(bri, ct); } // do nothing to mpd if the user changed an mpd setting diff --git a/src/controller/system/lamps/bridge_connect.rs b/src/controller/system/lamps/bridge_connect.rs new file mode 100644 index 00000000..b56873d6 --- /dev/null +++ b/src/controller/system/lamps/bridge_connect.rs @@ -0,0 +1,118 @@ +use philipshue::bridge; +use philipshue::bridge::Bridge; +use philipshue::errors::{BridgeError::LinkButtonNotPressed, HueError, HueErrorKind}; +use tracing::{info, error}; + +use super::Error; +use std::collections::BTreeMap; +use std::fs::File; +use std::path::Path; +use std::thread; +use std::time::Duration; + +#[derive(Debug, thiserror::Error)] +pub enum RegisterError { + #[error("Something went wrong registering the user inside the hue library")] + HueError(philipshue::errors::HueError), + #[error("Link button was not pressed within 25 seconds")] + Timedout, +} + +fn register(ip: &str) -> Result { + for _ in 0..5 { + //try 5 times to connect + match bridge::register_user(ip, "homeAutomationSys") { + Ok(received_login) => { + println!("Success, linked to bridge"); + info!("User registered: {}, on IP: {}", &received_login, ip); + return Ok(received_login); + } + Err(HueError( + HueErrorKind::BridgeError { + error: LinkButtonNotPressed, + .. + }, + _, + )) => { + println!("Please, press the link on the bridge. Retrying in 5 seconds"); + thread::sleep(Duration::from_secs(5)); + } + Err(e) => { + println!("Unexpected error occurred: {}", e); + return Err(RegisterError::HueError(e)); + } + } + } + return Err(RegisterError::Timedout); +} + +fn find_bridge_ip() -> Result { + let mut discovered = bridge::discover().map_err(Error::Discovery)?; + if discovered.len() == 0 { + error!("No bridge found!"); + return Err(Error::NoBridgeFound); + } else if discovered.len() > 1 { + error!( + "Found multiple hue bridges: {:?}, continuing with first one in list", + discovered + ); + } + + Ok(discovered.pop().unwrap().into_ip()) +} + +fn saved_bridge_info() -> Result<(String, String), ()> { + let path = Path::new("hueBridgeLogin"); + match File::open(&path) { + Err(e) => error!("find ip and login file, error: {}", e), + Ok(f) => match serde_yaml::from_reader(f) { + Ok((ip, login)) => return Ok((ip, login)), + Err(_) => error!("could not read ip and login from file"), + }, + } + Err(()) +} + +#[derive(Debug, thiserror::Error)] +pub enum SaveBridgeError { + #[error("Could not create file {path:?} to store bridge logins in: {err}")] + CreatingFile { + path: &'static Path, + err: std::io::Error, + }, + #[error("Error writing bridge logins to file: {0}")] + Writing(serde_yaml::Error), +} +fn update_saved_bridge_info(bridge_ip: &str, login: &str) -> Result<(), SaveBridgeError> { + let path = Path::new("hueBridgeLogin"); + let file = File::create(&path).map_err(|err| SaveBridgeError::CreatingFile { err, path })?; + serde_yaml::to_writer(file, &(bridge_ip, login)).map_err(SaveBridgeError::Writing) +} + +pub fn get_bridge_and_status() -> Result<(Bridge, BTreeMap), Error> { + let Ok((ip, login)) = saved_bridge_info() else { + let ip = find_bridge_ip()?; + let login = register(&ip)?; + update_saved_bridge_info(&ip, &login)?; + + let bridge = Bridge::new(&ip, &login); + let lights_info = bridge.get_all_lights().map_err(Error::GettingLights)?; + return Ok((bridge, lights_info)); + }; + + let bridge = Bridge::new(&ip, &login); + let res = bridge.get_all_lights(); + + match res { + Ok(lights_info) => Ok((bridge, lights_info)), + Err(_) => { + let ip = find_bridge_ip()?; + let login = register(&ip)?; + update_saved_bridge_info(&ip, &login)?; + + let bridge = Bridge::new(&ip, &login); + let lights_info = bridge.get_all_lights().map_err(Error::GettingLights)?; + Ok((bridge, lights_info)) + } + } +} diff --git a/src/controller/system/lamps/eventually_consistent_bridge.rs b/src/controller/system/lamps/eventually_consistent_bridge.rs new file mode 100644 index 00000000..a8e9b1f3 --- /dev/null +++ b/src/controller/system/lamps/eventually_consistent_bridge.rs @@ -0,0 +1,150 @@ +use super::{bridge_connect, lamp::Lamp}; +use super::{ApplyChangeError, State}; +use crate::errors::Error; +use futures_util::stream::Peekable; +use futures_util::{FutureExt, Stream, StreamExt}; +use philipshue::LightCommand; +use std::collections::HashMap; +use std::pin::Pin; +use std::time::Duration; +use tokio::select; +use tokio::sync::oneshot; +use tracing::error; + +use philipshue::bridge::Bridge; + +pub(crate) type LampId = usize; +pub(crate) enum Change { + AllOff, + AllOn, + Off { lamp_id: LampId }, + On { lamp_id: LampId }, + CtBri { lamp_id: LampId, bri: u8, ct: u16 }, + AllCtBri { bri: u8, ct: u16 }, + AllXY { bri: u8, xy: (f32, f32) }, +} + +pub(crate) struct CachedBridge { + pub(crate) bridge: Bridge, + pub(crate) needed_state: State, + pub(crate) known_state: State, +} + +impl CachedBridge { + pub(crate) fn try_init() -> Result { + let (bridge, lights_info) = bridge_connect::get_bridge_and_status()?; + let state: HashMap = lights_info + .iter() + .map(|(id, light)| (*id, Lamp::from(&light.state))) + .collect(); + + Ok(Self { + bridge, + needed_state: state.clone(), + known_state: state, + }) + } + + pub(crate) fn apply_changes(&mut self) -> Result<(), Error> { + for (id, lamp) in self.known_state.iter_mut() { + let Some(needed) = self.needed_state.get(id) else { + continue; + }; + + if lamp != needed { + self.bridge + .set_light_state( + *id, + &LightCommand::default() + .with_xy(needed.xy.unwrap()) + .with_bri(needed.bri), + ) + .unwrap(); + } + } + + Ok(()) + } + pub(crate) fn prep_change(&mut self, change: &Change) { + match change { + Change::AllOff => { + self.needed_state + .values_mut() + .for_each(|lamp| lamp.on = false); + } + Change::AllOn => { + self.needed_state + .values_mut() + .for_each(|lamp| lamp.on = true); + } + Change::Off { lamp_id } => { + if let Some(lamp) = self.needed_state.get_mut(&lamp_id) { + lamp.on = true; + } else { + error!("no lamp with id: {lamp_id} exists"); + } + } + Change::On { lamp_id } => { + if let Some(lamp) = self.needed_state.get_mut(&lamp_id) { + lamp.on = false; + } else { + error!("no lamp with id: {lamp_id} exists"); + } + } + Change::CtBri { lamp_id, bri, ct } => { + if let Some(lamp) = self.needed_state.get_mut(lamp_id) { + lamp.bri = *bri; + lamp.ct = Some(*ct); + } + } + Change::AllCtBri { bri, ct } => { + self.needed_state.values_mut().for_each(|lamp| { + lamp.bri = *bri; + lamp.ct = Some(*ct); + }); + } + Change::AllXY { bri, xy } => { + self.needed_state.values_mut().for_each(|lamp| { + lamp.bri = *bri; + lamp.xy = Some(*xy); + }); + } + } + } +} + +pub(crate) async fn process_lamp_changes( + stream: &mut Pin<&mut Peekable>, + mut bridge: CachedBridge, +) -> Error +where + S: Stream>, Change)>, +{ + loop { + let mut to_answer = Vec::new(); + // process backlog + loop { + let Some((_, change)) = stream.as_mut().peek_mut().now_or_never().flatten() else { + let change_appears = stream.as_mut().peek_mut(); + let not_instant = tokio::time::sleep(Duration::from_millis(50)); + select! { + _ = change_appears => continue, + _ = not_instant => break, + + } + }; + bridge.prep_change(change); + // remove the now processed item from the stream and store its + // answer tx + let (tx, _) = stream.as_mut().next().await.expect("just peeked"); + to_answer.push(tx); + } + + if let Err(e) = bridge.apply_changes() { + for tx in to_answer { + let _ignore_canceld_requester = tx.send(Err(ApplyChangeError)); + } + return e; + } + } +} diff --git a/src/controller/system/lamps/lamp.rs b/src/controller/system/lamps/lamp.rs new file mode 100644 index 00000000..18823774 --- /dev/null +++ b/src/controller/system/lamps/lamp.rs @@ -0,0 +1,55 @@ +//adaptation from philipshue LightState that adds some +//values and removes unused +#[derive(Debug, Clone, PartialEq)] +pub struct Lamp { + pub on: bool, + pub bri: u8, + pub hue: Option, + pub sat: Option, + pub xy: Option<(f32, f32)>, + pub ct: Option, + pub reachable: bool, +} + +impl From<&philipshue::hue::LightState> for Lamp { + fn from(state: &philipshue::hue::LightState) -> Self { + Lamp { + on: state.on, + bri: state.bri, + hue: state.hue, + sat: state.sat, + xy: state.xy, + ct: state.ct, + reachable: state.reachable, + } + } +} + +fn gamma_correct(mut x: f32) -> f32 { + if x > 0.04045 { + x = (x + 0.055) / (1f32 + 0.055); + x.powf(2.4) + } else { + x / 12.92 + } +} + +//r,g,b between 0 and one +//https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d +pub fn xy_from_rgb(rgb: (f32, f32, f32)) -> (f32, f32) { + let (r, g, b) = rgb; + let r = gamma_correct(r); + let g = gamma_correct(g); + let b = gamma_correct(b); + + let xyz_x = r * 0.649926 + g * 0.103455 + b * 0.197109; + let xyz_y = r * 0.234327 + g * 0.743075 + b * 0.022598; + let xyz_z = g * 0.053077 + b * 1.035763; + + let hue_x = xyz_x / (xyz_x + xyz_y + xyz_z); + let hue_y = xyz_y / (xyz_x + xyz_y + xyz_z); + + //TODO color gamut triangle stuff for finding closest valid value + + (hue_x, hue_y) +} diff --git a/src/controller/system/lamps/mod.rs b/src/controller/system/lamps/mod.rs index b96c557c..86e4eeda 100644 --- a/src/controller/system/lamps/mod.rs +++ b/src/controller/system/lamps/mod.rs @@ -1,342 +1,116 @@ extern crate philipshue; extern crate serde_yaml; -use philipshue::bridge; -use philipshue::bridge::Bridge; -use philipshue::errors::{ - BridgeError::{DeviceIsUnreachable, LinkButtonNotPressed}, - HueError, HueErrorKind, -}; -use philipshue::hue::LightCommand; +use futures_util::{pin_mut, stream, StreamExt}; +use tokio::sync::{mpsc, oneshot}; +use tracing::error; -use crate::errors::Error; -use std::collections::{BTreeMap, HashMap}; -use std::fs::File; -use std::path::Path; -use std::thread; +use std::collections::HashMap; use std::time::Duration; -fn register(ip: &str) -> Result { - for _ in 0..5 { - //try 5 times to connect - match bridge::register_user(ip, "homeAutomationSys") { - Ok(recieved_login) => { - println!("Success, linked to brige"); - info!("User registered: {}, on IP: {}", &recieved_login, ip); - return Ok(recieved_login); +use self::bridge_connect::SaveBridgeError; +use self::eventually_consistent_bridge::Change; + +mod bridge_connect; +mod eventually_consistent_bridge; +mod lamp; + +type State = HashMap; + +async fn manage_bridge( + rx: mpsc::UnboundedReceiver<(oneshot::Sender>, Change)>, +) { + let stream = stream::unfold(rx, |mut rx| async move { + let yielded = rx.recv().await; + yielded.map(|item| (item, rx)) + }); + + let stream = stream.peekable(); + pin_mut!(stream); + loop { + let error = match eventually_consistent_bridge::CachedBridge::try_init() { + Ok(bridge) => { + eventually_consistent_bridge::process_lamp_changes(&mut stream, bridge).await } - Err(HueError( - HueErrorKind::BridgeError { - error: LinkButtonNotPressed, - .. - }, - _, - )) => { - println!("Please, press the link on the bridge. Retrying in 5 seconds"); - thread::sleep(Duration::from_secs(5)); - } - Err(e) => { - println!("Unexpected error occured: {}", e); - return Err(()); - } - } - } - return Err(()); -} - -fn find_bridge_ip() -> Result { - let mut discovered = bridge::discover()?; - if discovered.len() == 0 { - error!("No bridge found!"); - return Err(Error::Lamps(HueError::from_kind(HueErrorKind::Msg( - "no bridge found".into(), - )))); - } else if discovered.len() > 1 { - error!( - "Found multiple hue bridges: {:?}, continueing with first one in list", - discovered - ); - } - - Ok(discovered.pop().unwrap().into_ip()) -} - -fn saved_bridge_info() -> Result<(String, String), ()> { - let path = Path::new("hueBridgeLogin"); - match File::open(&path) { - Err(e) => error!("find ip and login file, error: {}", e), - Ok(f) => match serde_yaml::from_reader(f) { - Ok((ip, login)) => return Ok((ip, login)), - Err(_) => error!("could not read ip and login from file"), - }, - } - Err(()) -} - -fn update_saved_bridge_info(bridge_ip: &str, login: &str) -> Result<(), ()> { - let path = Path::new("hueBridgeLogin"); - match File::create(&path) { - Ok(f) => { - if let Err(e) = serde_yaml::to_writer(f, &(bridge_ip, login)) { - error!("could not write ip and login from file, error: {}", e); - } else { - return Ok(()); - } - } - Err(e) => { - error!("cant open ip and login file, error: {}", e); - } - } - Err(()) -} - -fn get_bridge_and_status() -> Result<(Bridge, BTreeMap), Error> { - if let Ok((mut ip, mut login)) = saved_bridge_info() { - let mut update_ip_or_login = false; - loop { - let bridge = Bridge::new(&ip, &login); - match bridge.get_all_lights() { - Ok(lights_info) => { - if update_ip_or_login { - if update_saved_bridge_info(&ip, &login).is_err() { - error!("Could not save new bridge ip and login, next run will fail without user intervention") - } - } - return Ok((bridge, lights_info)); - } - //cant find bridge on given ip - Err(HueError( - HueErrorKind::BridgeError { - error: DeviceIsUnreachable, - .. - }, - _, - )) => { - ip = find_bridge_ip()?; - update_ip_or_login = true; - } - //cant register as button was not pressed in time - Err(HueError( - HueErrorKind::BridgeError { - error: LinkButtonNotPressed, - .. - }, - _, - )) => { - login = register(&ip).map_err(|_| Error::UnTracked)?; - update_ip_or_login = true; - } - Err(e) => { - error!("Unexpected error occured: {:?}", e); - return Err(e.into()); - } - } - } - } else { - let ip = find_bridge_ip()?; - let login = register(&ip).map_err(|_| Error::UnTracked)?; - if update_saved_bridge_info(&ip, &login).is_err() { - error!("Could not save new bridge ip and login, next run will fail without user intervention") + Err(e) => e, }; - let bridge = Bridge::new(&ip, &login); - let lights_info = bridge.get_all_lights()?; - return Ok((bridge, lights_info)); + error!("could not connect to bridge: {error:?}"); + tokio::time::sleep(Duration::from_secs(5)).await; } } -//adaptation from philipshue LightState that adds some -//values and removes unused -#[derive(Debug)] -pub struct Lamp { - pub on: bool, - pub bri: u8, - pub hue: Option, - pub sat: Option, - pub xy: Option<(f32, f32)>, - pub ct: Option, - pub reachable: bool, +pub struct Lighting { + _manage_bridge: tokio::task::JoinHandle<()>, + tx: mpsc::UnboundedSender<(oneshot::Sender>, Change)>, } -pub struct Lighting { - pub bridge: Bridge, - //local cache of current state (used for toggle) - pub lamps: HashMap, +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Could not get lights from bridge")] + GettingLights(philipshue::errors::HueError), + #[error("Could not find the bridge via upnp")] + NoBridgeFound, + #[error("Error while trying to discover the bridge")] + Discovery(philipshue::errors::HueError), + #[error("Failed to register on bridge")] + Register(#[from] bridge_connect::RegisterError), + #[error("Something went wrong saving bridge account to disk: {0}")] + SavingBridgeAccount(#[from] SaveBridgeError), } -impl From<&philipshue::hue::LightState> for Lamp { - fn from(state: &philipshue::hue::LightState) -> Self { - Lamp { - on: state.on, - bri: state.bri, - hue: state.hue, - sat: state.sat, - xy: state.xy, - ct: state.ct, - reachable: state.reachable, +#[derive(Debug, thiserror::Error)] +#[error("Could not apply changes to lighting system. Will simulate this and further changes then automatically apply the simulation outcome once the issue is resolved")] +pub struct ApplyChangeError; + +macro_rules! light_fn { + ($name:ident, $change:ident$(; $($arg:ident: $type:ty),+)?) => { + pub fn $name(&mut self, $($($arg: $type),+)?) -> Result<(), ApplyChangeError> { + // todo use oneshot to get error back from other side + let (tx, rx) = tokio::sync::oneshot::channel(); + self.tx.send((tx, Change::$change$({$($arg),+})?)).expect("managed_bridge should channel should never drop as managed bridge task should never end"); + let res = rx.blocking_recv().expect("managed_bridge should not crash and thus not drop the receive end of the channel"); + res } - } + }; } impl Lighting { - pub fn init() -> Result { - let (bridge, lights_info) = get_bridge_and_status()?; - let lamps: HashMap = lights_info - .iter() - .map(|(id, light)| (*id, Lamp::from(&light.state))) - .collect(); - - Ok(Self { bridge, lamps }) - } - - #[allow(unused)] - pub fn print_info(&self) { - dbg!(&self.lamps); - } - - pub fn numb_on(&self) -> u8 { - self.lamps.values().map(|lamp| lamp.on as u8).sum() - } - - //how to deal with errors? - pub fn toggle(&mut self) -> Result<(), Error> { - let numb_on: u8 = self.numb_on(); - let numb_off = self.lamps.len() as u8 - numb_on; - - //group ID 0 is a special group containing all lights known to the bridge - if numb_on > numb_off { - let command = LightCommand::off(LightCommand::default()); - self.bridge.set_group_state(0, &command)?; - self.lamps.values_mut().for_each(|lamp| lamp.on = false); - } else { - let command = LightCommand::on(LightCommand::default()); - self.bridge.set_group_state(0, &command)?; - self.lamps.values_mut().for_each(|lamp| lamp.on = true); + pub fn start_init() -> Self { + let (tx, rx) = mpsc::unbounded_channel(); + let manage_bridge = manage_bridge(rx); + let manage_bridge = tokio::task::spawn(manage_bridge); + Self { + _manage_bridge: manage_bridge, + tx, } - - Ok(()) - } - - pub fn all_off(&mut self) -> Result<(), Error> { - let command = LightCommand::off(LightCommand::default()); - self.bridge.set_group_state(0, &command)?; - self.lamps.values_mut().for_each(|lamp| lamp.on = false); - Ok(()) - } - - pub fn all_on(&mut self) -> Result<(), Error> { - let command = LightCommand::on(LightCommand::default()); - self.bridge.set_group_state(0, &command)?; - self.lamps.values_mut().for_each(|lamp| lamp.on = false); - Ok(()) - } - - pub fn single_off(&mut self, lamp_id: usize) -> Result<(), Error> { - let command = LightCommand::off(LightCommand::default()); - self.bridge.set_light_state(lamp_id, &command)?; - self.lamps.get_mut(&lamp_id).unwrap().on = true; - Ok(()) - } - - #[allow(dead_code)] - pub fn single_on(&mut self, lamp_id: usize) -> Result<(), Error> { - let command = LightCommand::on(LightCommand::default()); - self.bridge.set_light_state(lamp_id, &command)?; - self.lamps.get_mut(&lamp_id).unwrap().on = true; - Ok(()) - } - - pub fn set_all_on_ct(&mut self, bri: u8, ct: u16) -> Result<(), Error> { - let command = LightCommand::default(); - //let command = command.on(); - let command = command.with_bri(bri); - let command = command.with_ct(ct); - let command = command.on(); - self.bridge.set_group_state(0, &command)?; - self.lamps.values_mut().for_each(|lamp| { - lamp.bri = bri; - lamp.ct = Some(ct); - lamp.on = true - }); - - Ok(()) } //how to deal with errors? - pub fn set_all_ct(&mut self, bri: u8, ct: u16) -> Result<(), Error> { - let command = LightCommand::default(); - //let command = command.on(); - let command = command.with_bri(bri); - let command = command.with_ct(ct); - self.bridge.set_group_state(0, &command)?; - self.lamps.values_mut().for_each(|lamp| { - lamp.bri = bri; - lamp.ct = Some(ct); - lamp.on = true - }); - + pub fn toggle(&mut self) -> Result<(), Error> { + error!("not implemented"); Ok(()) } - #[allow(dead_code)] - pub fn set_all_xy(&mut self, bri: u8, xy: (f32, f32)) -> Result<(), Error> { - let command = LightCommand::default(); - let command = command.on(); - let command = command.with_bri(bri); - let command = command.with_xy(xy); - self.bridge.set_group_state(0, &command)?; - self.lamps.values_mut().for_each(|lamp| { - lamp.bri = bri; - lamp.xy = Some(xy); - lamp.on = true - }); + light_fn! {all_off, AllOff} + light_fn! {all_on, AllOn} + light_fn! {single_off, Off; lamp_id: usize} + light_fn! {single_on, On; lamp_id: usize} - Ok(()) - } + light_fn! {set_ct, CtBri; lamp_id: usize, bri: u8, ct: u16 } + light_fn! {set_all_ct, AllCtBri; bri: u8, ct: u16 } + light_fn! {set_all_xy, AllXY; bri: u8, xy: (f32, f32) } - pub fn set_all_rgb(&mut self, bri: u8, rgb: (f32, f32, f32)) -> Result<(), Error> { - let xy = xy_from_rgb(rgb); + pub fn set_all_rgb(&mut self, bri: u8, rgb: (f32, f32, f32)) -> Result<(), ApplyChangeError> { + let xy = lamp::xy_from_rgb(rgb); + let (tx, rx) = tokio::sync::oneshot::channel(); + self.tx + .send((tx, Change::AllXY { bri, xy })) + .expect("manage_bridge should never return"); - let command = LightCommand::default(); - let command = command.on(); - let command = command.with_bri(bri); - let command = command.with_xy(xy); - self.bridge.set_group_state(0, &command)?; - self.lamps.values_mut().for_each(|lamp| { - lamp.bri = bri; - lamp.xy = Some(xy); - lamp.on = true - }); - - Ok(()) - } -} - -fn gamma_correct(mut x: f32) -> f32 { - if x > 0.04045 { - x = (x + 0.055) / (1f32 + 0.055); - x.powf(2.4) - } else { - x / 12.92 + let res = rx.blocking_recv().expect( + "managed_bridge should not crash and thus not drop the receive end of the channel", + ); + res } } - -//r,g,b between 0 and one -//https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d -fn xy_from_rgb(rgb: (f32, f32, f32)) -> (f32, f32) { - let (r, g, b) = rgb; - let r = gamma_correct(r); - let g = gamma_correct(g); - let b = gamma_correct(b); - - let xyz_x = r * 0.649926 + g * 0.103455 + b * 0.197109; - let xyz_y = r * 0.234327 + g * 0.743075 + b * 0.022598; - let xyz_z = g * 0.053077 + b * 1.035763; - - let hue_x = xyz_x / (xyz_x + xyz_y + xyz_z); - let hue_y = xyz_y / (xyz_x + xyz_y + xyz_z); - - //TODO color gamut triangle stuff for finding closest valid value - - (hue_x, hue_y) -} diff --git a/src/controller/system/mod.rs b/src/controller/system/mod.rs index ff31482d..d8fec9b2 100644 --- a/src/controller/system/mod.rs +++ b/src/controller/system/mod.rs @@ -1,3 +1,3 @@ -mod lamps; +pub mod lamps; pub mod mpd_control; pub use lamps::Lighting; diff --git a/src/controller/system/mpd_control.rs b/src/controller/system/mpd_control.rs index 4d0e3a75..8289f26b 100644 --- a/src/controller/system/mpd_control.rs +++ b/src/controller/system/mpd_control.rs @@ -1,6 +1,7 @@ use crate::errors::Error; -use chrono::Duration; +use std::time::Duration; use rand::Rng; +use tracing::warn; use crate::input::mpd_status::MpdStatus; @@ -28,7 +29,7 @@ pub fn add_from_playlist( }, }; - let mut time = Duration::seconds(0); + let mut time = Duration::from_secs(0); //add random songs until the playtime is larger then the minimum while time < minimal_play_time && songs.len() > 1 { let idx = rng.gen_range(0, songs.len() - 1); @@ -69,12 +70,6 @@ pub fn decrease_volume(mpd_status: &mut MpdStatus) -> Result<(), Error> { Ok(()) } -pub fn set_volume(volume: i8) -> Result<(), Error> { - let mut client = mpd::Client::connect("127.0.0.1:6600")?; - client.volume(volume)?; - Ok(()) -} - pub fn next_song() -> Result<(), Error> { let mut client = mpd::Client::connect("127.0.0.1:6600")?; client.next()?; diff --git a/src/errors.rs b/src/errors.rs index f10b0dee..7312dc5d 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,7 +1,3 @@ -use fern::colors::{Color, ColoredLevelConfig}; - -use crate::input::youtube_downloader; - #[derive(thiserror::Error, Debug)] pub enum Error { #[error("Io error")] @@ -14,68 +10,12 @@ pub enum Error { DataBase(#[from] sled::Error), #[error("Could not download youtube")] Download(#[from] reqwest::Error), - #[error("Error contacting hue")] - Lamps(#[from] philipshue::errors::HueError), + #[error("Error while adjusting lighting: {0}")] + Lamps(#[from] crate::controller::system::lamps::Error), #[error("Error contacting mpd")] Mpd(#[from] mpd::error::Error), - #[error("TODO")] - RetryLogic(String), - #[error("Could not download youtube movie")] - YoutubeDownloader(youtube_downloader::Error), #[error("Error in the wakeup alarm system")] SetWakeUp(#[from] crate::input::jobs::wakeup::Error), #[error("Error in wakeup state")] WakeUpState(#[from] crate::controller::WakeUpStateError), - #[error("untracked error")] - UnTracked, -} - -pub fn setup_logging(verbosity: u8) -> Result<(), fern::InitError> { - let mut base_config = fern::Dispatch::new(); - let colors = ColoredLevelConfig::new() - .info(Color::Green) - .debug(Color::Yellow) - .warn(Color::Magenta); - - base_config = match verbosity { - 0 => base_config.level(log::LevelFilter::Error), - 1 => base_config.level(log::LevelFilter::Warn), - 2 => base_config - .level(log::LevelFilter::Info) - .level_for("actix-web", log::LevelFilter::Warn), - 3 => base_config.level(log::LevelFilter::Trace), - 4 => base_config.level(log::LevelFilter::Error), - _4_or_more => base_config.level(log::LevelFilter::Warn), - }; - - // Separate file config so we can include year, month and day in file logs - let file_config = fern::Dispatch::new() - .format(|out, message, record| { - out.finish(format_args!( - "{}[{}][{}] {}", - chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"), - record.target(), - record.level(), - message - )) - }) - .chain(fern::log_file("program.log")?); - - let stdout_config = fern::Dispatch::new() - .format(move |out, message, record| { - out.finish(format_args!( - "[{}][{}][{}] {}", - chrono::Local::now().format("%H:%M"), - record.target(), - colors.color(record.level()), - message - )) - }) - .chain(std::io::stdout()); - - base_config - .chain(file_config) - .chain(stdout_config) - .apply()?; - Ok(()) } diff --git a/src/input/api.rs b/src/input/api.rs new file mode 100644 index 00000000..bb9d92f8 --- /dev/null +++ b/src/input/api.rs @@ -0,0 +1,26 @@ +use axum::Router; +use axum::body::Bytes; +use axum::routing::{get, post}; + +use crate::errors::Error; + +use super::jobs::WakeUp; + +async fn usually(wakeup: WakeUp) -> Bytes { +} + +async fn setup(wakeup: WakeUp) -> Result<(), Error> { + let app = Router::new() + .route("/alarm/usually", get(usually)) + // .route("/alarm/tomorrow", get(tomorrow)) + // .route("/alarm/usually", post(usually)) + // .route("/alarm/tomorrow", post(tomorrow)) + .with_state(wakeup); + + // https is done at the loadbalancer + let listener = tokio::net::TcpListener::bind("127.0.0.1:80") + .await + .unwrap(); + tracing::debug!("listening on {}", listener.local_addr().unwrap()); + axum::serve(listener, app).await.unwrap(); +} diff --git a/src/input/bot/mod.rs b/src/input/bot/mod.rs deleted file mode 100644 index 9f3ddc17..00000000 --- a/src/input/bot/mod.rs +++ /dev/null @@ -1,240 +0,0 @@ -use actix_web::http::StatusCode; -use actix_web::web::{Bytes, Data, HttpResponse}; - -use log::{error, info, warn}; -use reqwest; -use serde_json; - -use telegram_bot::types::callback_query::CallbackQuery; -use telegram_bot::types::message::Message; -use telegram_bot::types::message::MessageKind; -use telegram_bot::types::refs::{ChatId, MessageId, UserId}; -use telegram_bot::types::update::Update; -use telegram_bot::types::update::UpdateKind; - -use crate::input::web_api::server::State; -use crate::input::youtube_downloader::{self, FeedbackChannel}; - -pub mod youtube_dl; -use youtube_dl::TelegramFeedback; -mod set_alarm; - -#[derive(Debug)] -pub enum Error { - HttpClientError(reqwest::Error), - CouldNotSetWebhook, - InvalidServerResponse(reqwest::Response), - UnhandledUpdateKind, - UnknownCommand(String), - SongDownloadError(youtube_downloader::Error), - Unauthorized(ChatId), - SetAlarmError(set_alarm::Error), -} - -impl From for Error { - fn from(error: reqwest::Error) -> Self { - Error::HttpClientError(error) - } -} - -impl From for Error { - fn from(e: youtube_downloader::Error) -> Self { - Error::SongDownloadError(e) - } -} - -impl From for Error { - fn from(err: set_alarm::Error) -> Self { - Error::SetAlarmError(err) - } -} - -fn to_string_and_ids(message: Message) -> Result<(String, ChatId, UserId, MessageId), Error> { - let chat_id = message.chat.id(); - let user_id = message.from.id; - let message_id = message.id; - - if let MessageKind::Text { data, entities: _ } = message.kind { - return Ok((data, chat_id, user_id, message_id)); - } else { - warn!("unhandled message kind"); - return Err(Error::UnhandledUpdateKind); - } -} - -async fn handle_command( - text: String, - chat_id: ChatId, - message_id: MessageId, - userid: UserId, - state: &State, -) -> Result<(), Error> { - if !state.valid_ids.contains(&userid) { - return Err(Error::Unauthorized(chat_id)); - } - - let token = &state.bot_token; - if text.contains("https://") || text.contains("http://") { - let fb = TelegramFeedback { - chat_id, - message_id, - }; - state - .youtube_dl - .add_song_to_queue(text, FeedbackChannel::Telegram(fb)) - .await?; - return Ok(()); - } - - let mut split = text.split_whitespace(); - let command = split.next().unwrap(); - match command { - "/test" => { - send_text(chat_id, token, "hi").await?; - } - "/wakeup" => { - set_alarm::handle(chat_id, token, split, state).await?; - } - &_ => { - warn!("no known command or alias: {:?}", &command); - Err(Error::UnknownCommand(command.to_owned()))?; - } - } - - return Ok(()); -} - -async fn handle_callback(callback: CallbackQuery, state: &State) { - if !state.valid_ids.contains(&callback.from.id) { - warn!("Unauthorized callback, userid: {}", callback.from.id); - return; //no need for error handling, just drop callback - } - - if callback.data.is_none() { - debug!("no data in callback"); - return; //not allowed, drop callback - } - let data = callback.data.as_ref().unwrap(); - let header = data.split_terminator(":").next(); - let res = match header { - Some("ytdl") => youtube_dl::handle_callback(data, state).await, - _ => { - warn!( - "unhandled callback, data: {}\nfull_callback: {:?}", - data, callback - ); - Ok(()) //user need not be warned as user is dev - } - }; - if let Err(e) = res { - error!("ran into error handling callback: {:?}", e); - } -} - -const INT_ERR_TEXT: &str = "apologies, an internal error happend this has been reported and will be fixed as soon as possible"; -const UNHANDLED: &str = "sorry I can not understand your input"; -async fn handle_error(error: Error, chat_id: ChatId, token: &str) { - let error_message = match error { - Error::UnknownCommand(input) => format!("Unknown command: {}", input), - Error::HttpClientError(err) => { - error!("Internal error in http client: {}", err); - String::from(INT_ERR_TEXT) - } - Error::InvalidServerResponse(resp) => { - error!("Incorrect bot api response {:?}", resp); - String::from(INT_ERR_TEXT) - } - Error::SongDownloadError(e) => { - error!("song download error {:?}", e); - String::from("Could not download song due to critical internal error") - } - Error::SetAlarmError(e) => { - error!("could not set alarm {:?}", e); - String::from("Could not set alarm") - } - Error::Unauthorized(chat_id) => format!( - "You are not authorized to use this bot, if you \ - believe this is a mistake ask for your telegram chat id \ - {} to be added", - chat_id - ), - - Error::UnhandledUpdateKind => String::from(UNHANDLED), - Error::CouldNotSetWebhook => unreachable!(), - }; - if let Err(error) = send_text(chat_id, token, error_message).await { - error!("Could not send text reply to user: {:?}", error); - } -} - -async fn handle(update: Update, state: State) { - //TODO change to ref - let token = &state.bot_token; - match update.kind { - UpdateKind::Message(messg) => { - if let Ok((text, chat_id, user_id, message_id)) = to_string_and_ids(messg) { - if let Err(error) = handle_command(text, chat_id, message_id, user_id, &state).await - { - handle_error(error, chat_id, token).await; - } - } - } - UpdateKind::CallbackQuery(callback) => { - //let chat_id = callback.message.chat.id(); - handle_callback(callback, &state).await; - } - _ => { - warn!("unhandled update from telegram: {:?}", update); - } - } -} - -pub async fn handle_webhook(state: Data, raw_update: Bytes) -> HttpResponse { - let update: Update = serde_json::from_slice(&raw_update.to_vec()).unwrap(); - let state_cpy = state.get_ref().clone(); - handle(update, state_cpy).await; - - HttpResponse::Ok().status(StatusCode::OK).body("{}") -} - -pub async fn send_text>( - chat_id: ChatId, - token: &str, - text: T, -) -> Result<(), Error> { - //add as arg generic ToChatRef (should get from Update) - //TODO create a SendMessage, serialise it (use member function serialize) - //then use the HttpRequest fields, (url, method, and body) to send to telegram - let url = format!("https://api.telegram.org/bot{}/sendMessage", token); - let form = reqwest::multipart::Form::new() - .text("chat_id", chat_id.to_string()) - .text("text", text.into()); - - let client = reqwest::Client::new(); - let resp = client.post(&url).multipart(form).send().await?; - //https://stackoverflow.com/questions/57540455/error-blockingclientinfuturecontext-when-trying-to-make-a-request-from-within - - if resp.status() != reqwest::StatusCode::OK { - Err(Error::InvalidServerResponse(resp)) - } else { - info!("send message"); - Ok(()) - } -} - -//Ports currently supported for Webhooks: 443, 80, 88, 8443. -pub async fn set_webhook(domain: &str, token: &str, port: u16) -> Result<(), Error> { - let url = format!("https://api.telegram.org/bot{}/setWebhook", token); - - let params = [("url", &url)]; - let client = reqwest::Client::new(); - let res = client.post(url.as_str()).form(¶ms).send().await?; - - if res.status() != reqwest::StatusCode::OK { - error!("could not set webhook: {:?}", res); - Err(Error::CouldNotSetWebhook) - } else { - info!("set webhook to: {}", url); - Ok(()) - } -} diff --git a/src/input/bot/set_alarm.rs b/src/input/bot/set_alarm.rs deleted file mode 100644 index 4fe49a09..00000000 --- a/src/input/bot/set_alarm.rs +++ /dev/null @@ -1,182 +0,0 @@ -use super::send_text; -use crate::input::web_api::server::State; -use chrono::{Local, Timelike}; -use telegram_bot::types::refs::ChatId; - -#[derive(Debug)] -pub enum Error { - InvalidOption, - CouldNotRespond, - NoTimeArgument, - InvalidHourArgument, - InvalidMinuteArgument, - WrongTimeFormat, - BackendError, -} - -pub async fn handle<'a>( - chat_id: ChatId, - token: &str, - mut args: std::str::SplitWhitespace<'a>, - state: &State, -) -> Result<(), Error> { - let command = args.next(); - - match command { - None => print_current(chat_id, token, state).await?, - Some("tomorrow") => add_tomorrow(chat_id, token, args, state).await?, - Some("usually") => add_usually(chat_id, token, args, state).await?, - Some("help") => help(chat_id, token).await?, - _ => Err(Error::InvalidOption)?, - } - - Ok(()) -} - -async fn help(chat_id: ChatId, token: &str) -> Result<(), Error> { - let text = String::from( - "Check, Set and remove alarms - * use 'tomorrow' followed by a time to set the alarm only for tomorrow - * use 'usually' followed by a time to set the alarm for all other days - * format a time as hh:mm or - to unset - * without any arguments this displays the tomorrow and usually times", - ); - - send_text(chat_id, token, text) - .await - .map_err(|_| Error::CouldNotRespond)?; - Ok(()) -} - -async fn add_tomorrow<'a>( - chat_id: ChatId, - token: &str, - args: std::str::SplitWhitespace<'a>, - state: &State, -) -> Result<(), Error> { - let Parsed { time, status } = parse_args(chat_id, token, args, state)?; - - state - .wakeup - .set_tomorrow(time) - .await - .map_err(|_| Error::BackendError)?; - send_text(chat_id, token, status) - .await - .map_err(|_| Error::CouldNotRespond)?; - - Ok(()) -} - -async fn add_usually<'a>( - chat_id: ChatId, - token: &str, - args: std::str::SplitWhitespace<'a>, - state: &State, -) -> Result<(), Error> { - let Parsed { time, status } = parse_args(chat_id, token, args, state)?; - - state - .wakeup - .set_usually(time) - .await - .map_err(|_| Error::BackendError)?; - send_text(chat_id, token, status) - .await - .map_err(|_| Error::CouldNotRespond)?; - - Ok(()) -} - -struct Parsed { - time: Option<(u8, u8)>, - status: String, -} - -fn parse_args<'a>( - _: ChatId, - _: &str, - mut args: std::str::SplitWhitespace<'a>, - _: &State, -) -> Result { - let time = args.next().ok_or(Error::NoTimeArgument)?; - - if time == "-" { - return Ok(Parsed { - time: None, - status: String::from("Alarm unset"), - }); - } - - //assumes hh:mm - let mut time = time.split(':'); - let hour = time - .next() - .ok_or(Error::WrongTimeFormat)? - .parse::() - .map_err(|_| Error::InvalidHourArgument)?; - let min = time - .next() - .ok_or(Error::WrongTimeFormat)? - .parse::() - .map_err(|_| Error::InvalidHourArgument)?; - - if hour > 24 { - return Err(Error::InvalidHourArgument); - } - if min > 60 { - return Err(Error::InvalidMinuteArgument); - } - - let now = Local::now(); - let mut alarm = now.with_hour(hour).unwrap().with_minute(min).unwrap(); - - if alarm < now { - alarm = now - .date_naive() - .succ_opt() - .unwrap() - .and_hms_opt(hour, min, 0) - .unwrap() - .and_local_timezone(Local) - .unwrap(); - } - - let till_alarm = alarm - now; - - let status = format!( - "set alarm for over {} hours and {} minutes from now", - till_alarm.num_hours(), - till_alarm.num_minutes() % 60 - ); - - Ok(Parsed { - time: Some((hour as u8, min as u8)), - status, - }) -} - -pub async fn print_current(chat_id: ChatId, token: &str, state: &State) -> Result<(), Error> { - let tomorrow = state.wakeup.tomorrow(); - let usually = state.wakeup.usually(); - - let msg = match (tomorrow, usually) { - (Some(tomorrow), Some(usually)) => format!( - "alarm tomorrow: {:02}:{:02}\nusually: {:02}:{:02}", - tomorrow.0, tomorrow.1, usually.0, usually.1 - ), - (Some(tomorrow), None) => format!( - "alarm tomorrow: {:02}:{:02}, usually no alarm", - tomorrow.0, tomorrow.1 - ), - (None, Some(usually)) => { - format!("alarm tomorrow as usual: {:02}:{:02}", usually.0, usually.1) - } - (None, None) => String::from("No alarm set"), - }; - - send_text(chat_id, token, msg) - .await - .map_err(|_| Error::CouldNotRespond)?; - Ok(()) -} diff --git a/src/input/bot/youtube_dl.rs b/src/input/bot/youtube_dl.rs deleted file mode 100644 index 7e24892c..00000000 --- a/src/input/bot/youtube_dl.rs +++ /dev/null @@ -1,136 +0,0 @@ -use async_trait::async_trait; -use telegram_bot::types::refs::{ChatId, MessageId}; - -use super::send_text; -use super::Error as BotError; -use crate::input::web_api::server::State; -use crate::input::youtube_downloader::{self, Feedback, JobStatus, MetaGuess}; - -#[derive(Debug, Clone)] -pub struct TelegramFeedback { - pub chat_id: ChatId, - pub message_id: MessageId, -} - -//present options: -// Swap -// None -// Ok -// Lookup -impl TelegramFeedback { - async fn ask_name_artist( - &self, - token: &str, - mut meta: MetaGuess, - id: u64, - ) -> Result<(), BotError> { - dbg!(); - let keyboard_json = format!( - "[\ - [{{\"text\":\"swap\", \"callback_data\":\"ytdl:swap:{id}\"}}],\ - [{{\"text\":\"no\", \"callback_data\":\"ytdl:no:{id}\"}}],\ - [{{\"text\":\"ok\", \"callback_data\":\"ytdl:ok:{id}\"}}],\ - [{{\"text\":\"lookup\", \"callback_data\":\"ytdl:lookup:{id}\"}}]\ - ]", - id = id - ); - let reply_markup = format!("{{\"inline_keyboard\":{} }}", keyboard_json); - meta.title - .retain(|c| c.is_ascii_alphanumeric() || c.is_ascii_whitespace() || c == '-'); - meta.artist - .retain(|c| c.is_ascii_alphanumeric() || c.is_ascii_whitespace() || c == '-'); - let text = format!( - "is _{}_ the title and _{}_ the artist?", - meta.title, meta.artist - ); - //TODO: should always base this on metadata guess, should make that a - //seperate type - - dbg!(&text); - dbg!(&reply_markup); - let url = format!("https://api.telegram.org/bot{}/sendMessage", token); - let form = reqwest::multipart::Form::new() - .text("chat_id", self.chat_id.to_string()) - .text("text", text) - .text("parse_mode", "Markdown") - .text("reply_to_message_id", self.message_id.to_string()) - .text("reply_markup", reply_markup); - - dbg!(); - let client = reqwest::Client::new(); - let resp = client.post(&url).multipart(form).send().await?; - //https://stackoverflow.com/questions/57540455/error-blockingclientinfuturecontext-when-trying-to-make-a-request-from-within - - if resp.status() != reqwest::StatusCode::OK { - error!("telegram gave invalid response: {:?}", resp); - Err(BotError::InvalidServerResponse(resp)) - } else { - dbg!("send message"); - Ok(()) - } - } -} - -#[async_trait] -impl Feedback for TelegramFeedback { - //errors during feedback must be handled within feedback channel - async fn feedback(&self, status: JobStatus, token: &str) { - let res: Result<(), BotError> = match status { - JobStatus::Finished => send_text(self.chat_id, token, "finished").await, - JobStatus::Downloaded => send_text(self.chat_id, token, "done downloading").await, - JobStatus::Queued(meta_data, id) => self - .ask_name_artist(token, meta_data, id) - .await - .map_err(|e| e.into()), - JobStatus::Error => send_text(self.chat_id, token, "ran into error").await, - }; - - if let Err(e) = res { - error!("ran into error within feedback function: {:?}", e); - } - } -} - -#[derive(Debug)] -pub enum Error { - ParseError(std::num::ParseIntError), - YoutubeDlError(youtube_downloader::Error), - NotEnoughData, -} - -impl From for Error { - fn from(err: std::num::ParseIntError) -> Error { - Error::ParseError(err) - } -} - -impl From for Error { - fn from(err: youtube_downloader::Error) -> Error { - Error::YoutubeDlError(err) - } -} - -pub async fn handle_callback(callback_data: &str, state: &State) -> Result<(), Error> { - let mut split = callback_data.split_terminator(":").skip(1); - let command = split.next(); - match command { - Some("swap") => { - let id = split.next().ok_or(Error::NotEnoughData)?.parse()?; - state.youtube_dl.swap_meta(id).await? //artist an title swapped - } - Some("ok") => { - let id = split.next().ok_or(Error::NotEnoughData)?.parse()?; - dbg!("handling callback"); - state.youtube_dl.meta_ok(id).await? - } - Some("no") => { - let id = split.next().ok_or(Error::NotEnoughData)?.parse()?; - state.youtube_dl.no_meta(id).await? - } - Some("lookup") => todo!(), - _ => { - error!("cant handle youtube_dl callback command: {:?}", command); - } - } - Ok(()) -} diff --git a/src/input/jobs.rs b/src/input/jobs.rs index d7171d03..de36e7dc 100644 --- a/src/input/jobs.rs +++ b/src/input/jobs.rs @@ -1,4 +1,6 @@ use crossbeam_channel; +use tracing::error; +use tracing::info; use std::ops::Sub; use std::thread; @@ -206,7 +208,7 @@ impl JobList { let alarm = bincode::serialize(&to_add).unwrap(); //create alarm entry if there is no alarm at this timestamp yet - //if there is already an alarm schedualed, postpone this one until there is a spot free + //if there is already an alarm scheduled, postpone this one until there is a spot free //self.db.cas(&[1], None as Option<&[u8]>, Some(&[10]) //TODO check how this works and expand sled documentation for fail cases while let Err(_old_event) = self.db.compare_and_swap( diff --git a/src/input/jobs/wakeup.rs b/src/input/jobs/wakeup.rs index 7af368f3..37b60b77 100644 --- a/src/input/jobs/wakeup.rs +++ b/src/input/jobs/wakeup.rs @@ -1,13 +1,15 @@ use super::{Action, Job, Jobs}; use crate::controller::Event; use chrono::{DateTime, Local, Timelike, Utc}; +use tokio::runtime::Runtime; +use tracing::info; use std::sync::{Arc, Mutex}; use std::time::Duration; // TODO FIXME multiple things left to do: // - usually and tomorrow are not written to db // - setting usually none goes wrong if tomorrow is not none -// - recheck set tomorrow and set usually carefull +// - recheck set tomorrow and set usually #[derive(Debug, thiserror::Error)] pub enum Error { @@ -33,17 +35,17 @@ impl WakeUp { } pub fn reset(&self) -> Result<(), Error> { self.0.lock().unwrap().reset()?; - log::info!("alarm system reset correctly"); + info!("alarm system reset correctly"); Ok(()) } pub async fn set_tomorrow(&self, time: Time) -> Result<(), Error> { self.0.lock().unwrap().set_tomorrow(time).await?; - log::info!("alarm tomorrow set to: time"); + info!("alarm tomorrow set to: time"); Ok(()) } pub async fn set_usually(&self, time: Time) -> Result<(), Error> { self.0.lock().unwrap().set_usually(time).await?; - log::info!("alarm usually set to: time"); + info!("alarm usually set to: time"); Ok(()) } } @@ -121,7 +123,8 @@ impl Inner { if let Some((hour, min)) = self.usually { let job = job_from(hour, min); let add = self.replace_job(job); - smol::block_on(add)?; + let rt = Runtime::new().unwrap(); + rt.block_on(add)?; } self.tomorrow = None; Ok(()) diff --git a/src/input/mod.rs b/src/input/mod.rs index d7240b7e..729474cc 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -1,8 +1,4 @@ -pub mod bot; pub mod jobs; +pub mod api; pub mod mpd_status; -pub mod web_api; -pub mod youtube_downloader; - pub use mpd_status::MpdStatus; -pub use youtube_downloader::YoutubeDownloader; diff --git a/src/input/web_api/server/mod.rs b/src/input/web_api/server/mod.rs index 01022f2b..c31c7012 100644 --- a/src/input/web_api/server/mod.rs +++ b/src/input/web_api/server/mod.rs @@ -47,7 +47,6 @@ impl State { controller_tx: crossbeam_channel::Sender, jobs: input::jobs::Jobs, wakeup: input::jobs::WakeUp, - youtube_dl: input::YoutubeDownloader, bot_token: String, valid_ids: Vec, ) -> Self { diff --git a/src/input/youtube_downloader.rs b/src/input/youtube_downloader.rs deleted file mode 100644 index 49d5f3f1..00000000 --- a/src/input/youtube_downloader.rs +++ /dev/null @@ -1,691 +0,0 @@ -use std::fs; -use std::io::Write; -use std::os::unix::fs::OpenOptionsExt; -use std::process::Command; -use std::thread; - -use std::path::{Path, PathBuf}; -use std::time::Duration; - -use actix_rt; -use async_std::task; -use async_trait::async_trait; -use bincode; -use regex::Regex; -use reqwest::IntoUrl; -use serde::{Deserialize, Serialize}; -use sled::Batch; -use std::ffi::OsStr; -//use id3; - -use crate::input::bot::youtube_dl::TelegramFeedback; - -const DIR: &str = "temp"; -const YOUTUBE_DL_LOC: &str = "temp/youtube-dl"; -const MUSIC_TEMP: &str = "temp/music"; -const MUSIC_DIR: &str = "/home/pi/Music"; - -#[derive(Debug)] -pub enum Error { - CouldNotDownloadExecutable(reqwest::Error), - CouldNotStoreExecutable(std::io::Error), - CouldNotDownloadSong(std::process::Output), - CouldNotUpdateMpd(mpd::error::Error), - #[allow(dead_code)] - CouldNotCreateTempDir(std::io::Error), - #[allow(dead_code)] - UnexpectedYoutubeDlStdOut(String), - #[allow(dead_code)] - UnsupportedSource(String), - CanNoLongerUpdateMeta, - #[allow(dead_code)] - CanNotSwapArtistWithEmptyTitle, - #[allow(dead_code)] - IDWasDeleted, -} - -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - match self { - Error::CouldNotDownloadExecutable(e) => { - write!(f, "Could not download executable, cause {}", e) - } - Error::CouldNotStoreExecutable(e) => { - write!(f, "Could not store executable, cause: {}", e) - } - Error::CouldNotDownloadSong(e) => write!( - f, - "Could not download song, cause: {}", - String::from_utf8(e.stderr.clone()).unwrap() - ), - Error::CouldNotUpdateMpd(e) => write!(f, "Could not update mpd, cause: {}", e), - Error::CouldNotCreateTempDir(e) => { - write!(f, "Could not create temp directory, cause: {}", e) - } - Error::UnexpectedYoutubeDlStdOut(s) => write!( - f, - "Could not understand output of youtube-dl, output was: {}", - s - ), - Error::UnsupportedSource(s) => write!(f, "Could not find something to download: {}", s), - Error::CanNoLongerUpdateMeta => write!( - f, - "Can no longer update metadata, was already done some time ago" - ), - Error::CanNotSwapArtistWithEmptyTitle => write!( - f, - "Can not swap artist and title as the current artist \ - is empty and the title can not be empty. Not writing metadata" - ), - Error::IDWasDeleted => write!(f, "Internal error, file not in database"), - } - } -} - -impl From for Error { - fn from(err: reqwest::Error) -> Self { - Error::CouldNotDownloadExecutable(err) - } -} -impl From for Error { - fn from(err: std::io::Error) -> Self { - Error::CouldNotStoreExecutable(err) - } -} -impl From for Error { - fn from(err: mpd::error::Error) -> Self { - Error::CouldNotUpdateMpd(err) - } -} - -#[async_trait] -pub trait Feedback { - async fn feedback(&self, status: JobStatus, token: &str); -} - -#[derive(Debug, Clone)] -pub enum FeedbackChannel { - Telegram(TelegramFeedback), - None, - //future expand with ... signal? -} - -#[derive(Debug)] -pub enum JobStatus { - Finished, - Downloaded, - Queued(MetaGuess, u64), - Error, -} - -impl FeedbackChannel { - async fn send(self, status: JobStatus, token: &str) { - match self { - Self::Telegram(tel) => tel.feedback(status, token).await, - Self::None => (), - } - } -} - -struct Job { - id: u64, - url: String, - feedback: FeedbackChannel, -} - -async fn download_youtube_dl(url: U) -> Result<(), Error> { - let mut dest = fs::OpenOptions::new() - .create(true) - .write(true) - .mode(0o770) - .open(YOUTUBE_DL_LOC)?; - - let response = reqwest::get(url).await?.bytes().await?; - dbg!(&response.len()); - dest.write(&response)?; - Ok(()) -} - -#[derive(Clone)] -pub struct YoutubeDownloader { - url_tx: crossbeam_channel::Sender, - db: sled::Db, - token: String, -} - -#[derive(Serialize, Deserialize, Default, Debug)] -pub struct MetaData { - pub artist: String, - pub title: String, - pub source_url: String, -} - -#[derive(Serialize, Deserialize, Default, Debug, Clone)] -pub struct MetaGuess { - pub artist: String, - pub title: String, - pub source_url: String, -} - -/*impl MetaData { - fn to_tag(&self) -> id3::Tag { - let mut tag = id3::Tag::new(); - tag.set_artist(&self.artist); - tag.set_title(&self.title); - //tag.set_text("source: ",&self.source_url); - tag - } -}*/ - -// in the future queued an downloaded can be expanded -// with a MetaGuess -#[derive(Serialize, Deserialize)] -enum Status { - Queued(MetaGuess), //can go to Downloaded or ConfirmedMeta - Downloaded(MetaGuess), // can go to Metawritten (as soon as there is meta we write it to file) - MetaConfirmed(MetaData), //can go to MetaWritten (as soon as download is complete meta written to file) - MetaWritten((PathBuf, MetaData)), //can only tranfrom to WritingMeta -} - -fn split(to_split_on: &str) -> (&str, &str) { - //try splitting on title - let new_title; - let new_artist; - - let in_quotes = Regex::new(r#"(.*)\s*(?:'|")\s*(.*)\s*(?:'|")\s*(.*)"#).unwrap(); - if to_split_on.contains("-") { - let mut split = to_split_on.splitn(2, "-"); - new_title = split.next().unwrap(); - new_artist = split.next().unwrap(); - } else if to_split_on.contains(":") { - let mut split = to_split_on.splitn(2, ":"); - new_title = split.next().unwrap(); - new_artist = split.next().unwrap(); - } else if to_split_on.contains("|") { - let mut split = to_split_on.splitn(2, "|"); - new_title = split.next().unwrap(); - new_artist = split.next().unwrap(); - } else if let Some(caps) = in_quotes.captures(to_split_on) { - dbg!(&caps); - let len_before = caps.get(1).unwrap().as_str().len(); - let len_after = caps.get(3).unwrap().as_str().len(); - if len_before > len_after { - new_title = caps.get(1).unwrap().as_str(); - new_artist = caps.get(2).unwrap().as_str(); - } else { - new_title = caps.get(2).unwrap().as_str(); - new_artist = caps.get(3).unwrap().as_str(); - } - } else { - new_title = to_split_on; - new_artist = "unknown"; - } - - (new_title.trim(), new_artist.trim()) -} - -fn guess_meta(url: &str) -> Result { - let full_path = Path::new(YOUTUBE_DL_LOC); - let output = Command::new(full_path) - //.arg("--verbose") //for debugging - .arg("--geo-bypass") - .arg("--no-playlist") - .arg("--ignore-config") - .arg("--get-filename") - .arg("--max-filesize") - .arg("50m") - .arg("--audio-format") - .arg("m4a") - .arg("--audio-quality") - .arg("257") - .arg("--format") - .arg("bestaudio[acodec=opus]/bestaudio/best") - .arg("--output") - .arg("%(title)s") - .arg(url) - .output()?; - - let stdout = String::from_utf8(output.stdout).unwrap(); - dbg!(&stdout); - let (title, artist) = split(&stdout); - - Ok(MetaGuess { - artist: artist.to_owned(), - title: title.to_owned(), - source_url: url.to_owned(), - }) -} - -fn download_file(output_arg: &String, url: &str) -> std::io::Result { - let full_path = Path::new(YOUTUBE_DL_LOC); - Command::new(full_path) - //.arg("--verbose") //for debugging - .arg("--geo-bypass") - .arg("--no-playlist") - .arg("--ignore-config") - .arg("--max-filesize") - .arg("50m") - //.arg("--embed-thumbnail") //dependency can not be installed - .arg("--write-thumbnail") - .arg("--audio-format") - .arg("m4a") - .arg("--audio-quality") - .arg("257") - .arg("--postprocessor-args") //seems to take along time - .arg("-ar 44100") - .arg("--extract-audio") - .arg("--format") - .arg("bestaudio[acodec=opus]/bestaudio/best") - .arg("--output") - .arg(&output_arg) - .arg(url) - .output() -} - -async fn download_song(url: &str, id: u64) -> Result<(), Error> { - let temp_dir = std::path::PathBuf::from(MUSIC_TEMP); - if !temp_dir.exists() { - fs::create_dir(&temp_dir).map_err(|e| Error::CouldNotCreateTempDir(e))?; - } - - let mut output_arg = String::from(temp_dir.to_str().unwrap()); - output_arg.push_str(&format!("/{}.%(ext)s", id)); - - let output = download_file(&output_arg, url)?; - dbg!(&output); - - dbg!(output.stderr.starts_with(b"ERROR:")); - if !output.status.success() || output.stderr.starts_with(b"ERROR:") { - dbg!("UPDATING YOUTUBE_DL"); - let since_last_updated = fs::metadata(YOUTUBE_DL_LOC) - .unwrap() - .created() - .unwrap() - .elapsed() - .unwrap_or(Duration::from_secs(0)); - - // updating youtube-dl wont do anything return error - dbg!(since_last_updated); - if since_last_updated < Duration::from_secs(60 * 60 * 24) { - dbg!("not updating youtube_dl, has been recently tried already"); - return Err(Error::CouldNotDownloadSong(output)); - } - - download_youtube_dl("https://yt-dl.org/downloads/latest/youtube-dl").await?; - let output = download_file(&output_arg, url)?; - if !output.status.success() { - return Err(Error::CouldNotDownloadSong(output)); - } - } - Ok(()) -} - -fn ffmpeg_set_meta(input: &Path, output: &Path, artist: &str, title: &str) { - let input = fs::canonicalize(input).unwrap(); - dbg!(&input); - dbg!(&output); - - let output = Command::new("ffmpeg") - .args(&[OsStr::new("-i"), input.as_os_str()]) - .args(&["-metadata", &format!("artist={}", artist)]) - .args(&["-metadata", &format!("title={}", title)]) - .args(&["-codec", "copy"]) - .arg(output.as_os_str()) - .output() - .expect("ffmpeg write metadata"); - - dbg!(output); - //ffmpeg -i InputFile -metadata key=value -codec copy OutputFile -} - -fn write_metadata(id: u64, meta: &MetaData) -> Result { - let mut old_path = PathBuf::from(MUSIC_TEMP); - old_path.push(id.to_string()); - old_path.set_extension("m4a"); - - let mut new_path = PathBuf::from(MUSIC_DIR); - new_path.push(&meta.artist); - if !new_path.exists() { - fs::create_dir(&new_path)?; - } - new_path.push(&meta.title); - new_path.set_extension("m4a"); - - ffmpeg_set_meta(&old_path, &new_path, &meta.artist, &meta.title); - fs::remove_file(old_path).unwrap(); - mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| c.rescan())?; - Ok(new_path) -} - -fn update_metadata(old_path: &Path, meta: &MetaData) -> Result { - let mut new_path = PathBuf::from(MUSIC_DIR); - new_path.push(&meta.artist); - if !new_path.exists() { - fs::create_dir(&new_path)?; - } - new_path.push(&meta.title); - new_path.set_extension("m4a"); - - ffmpeg_set_meta(&old_path, &new_path, &meta.artist, &meta.title); - - fs::remove_file(old_path).unwrap(); - //delete if parent dir is now empty - if let Some(dir) = old_path.parent() { - if dir.read_dir().unwrap().count() == 0 { - fs::remove_dir(dir).unwrap(); - } - } - - mpd::Client::connect("127.0.0.1:6600").and_then(|mut c| c.rescan())?; - Ok(new_path) -} - -async fn handle_job(job: Job, token: String, db: sled::Tree) -> Result<(), Error> { - let status = match download_song(&job.url, job.id).await { - Ok(_) => { - aquire_db_mutex(&db, job.id).await; - let db_status = db - .get(&status_key(job.id)) - .unwrap() - .ok_or(Error::CanNoLongerUpdateMeta)?; - let db_status = bincode::deserialize(&db_status.to_vec()).unwrap(); - let (new_db_status, job_status) = match db_status { - Status::Queued(meta_guess) => { - (Status::Downloaded(meta_guess), JobStatus::Downloaded) - } - Status::MetaConfirmed(meta) => { - let new_path = write_metadata(job.id, &meta)?; //write meta - (Status::MetaWritten((new_path, meta)), JobStatus::Finished) - } - Status::Downloaded(_) => panic!("file should not yet be download!"), - Status::MetaWritten((_, _)) => panic!("file should not yet be download!"), - }; - - let mut batch = Batch::default(); - batch.insert( - &status_key(job.id), - bincode::serialize(&new_db_status).unwrap(), - ); - batch.insert( - //unlock file lock - &db_mutex_key(job.id), - bincode::serialize(&false).unwrap(), - ); - db.apply_batch(batch).unwrap(); - job_status - } - Err(error) => { - error!("warn error during song download: {:?}", error); - //TODO remove from database - JobStatus::Error - } - }; - job.feedback.send(status, &token).await; - Ok(()) -} - -fn song_downloader(url_rx: crossbeam_channel::Receiver, token: String, db: sled::Tree) { - let mut rt = actix_rt::Runtime::new().unwrap(); - - loop { - match url_rx.recv() { - Ok(job) => { - if let Err(e) = rt.block_on(handle_job(job, token.clone(), db.clone())) { - error!("could not handle download job: {:?}", e); - } - } - // Err means YoutubeDownloader - // was dropped and this thread should stop - Err(_) => return, - } - } -} - -async fn aquire_db_mutex(db: &sled::Tree, id: u64) { - while let Err(_is_locked) = db - .compare_and_swap( - &db_mutex_key(id), - Some(bincode::serialize(&false).unwrap()), - Some(bincode::serialize(&true).unwrap()), - ) - .unwrap() - { - task::sleep(Duration::from_millis(10)).await; - dbg!("blocking on mutex aquisition"); - } -} - -fn db_mutex_key(id: u64) -> [u8; 9] { - let mut a = [0; 9]; - a[..8].clone_from_slice(&id.to_be_bytes()); - return a; -} -fn status_key(id: u64) -> [u8; 9] { - let mut a = [1; 9]; - a[..8].clone_from_slice(&id.to_be_bytes()); - return a; -} - -impl YoutubeDownloader { - pub async fn init( - token: String, - db: sled::Db, - ) -> Result<(Self, thread::JoinHandle<()>), Error> { - let youtube_db = db.open_tree("youtube_dl").unwrap(); - let full_path = Path::new(YOUTUBE_DL_LOC); - let dir_path = Path::new(DIR); - - if !full_path.exists() { - if !dir_path.exists() { - fs::create_dir(dir_path)?; - } - download_youtube_dl("https://yt-dl.org/downloads/latest/youtube-dl").await?; - } - - let (url_tx, url_rx) = crossbeam_channel::bounded(10); - let local_token = token.clone(); - let downloader_thread = - thread::spawn(move || song_downloader(url_rx, local_token, youtube_db)); - - Ok((Self { url_tx, db, token }, downloader_thread)) - } - - //TODO use youtube downloader to stream audio from youtube!!! - - /// checks if a song can be downloaded, if so sends the command to start download to - /// a seperate thread - pub async fn add_song_to_queue( - &self, - url: String, - feedback: FeedbackChannel, - ) -> Result<(), Error> { - //get metadata guess from youtube-dl - let meta_guess = guess_meta(&url)?; - let id = self.db.generate_id().unwrap(); - let db = self.db.open_tree("youtube_dl").unwrap(); - - let db_entry = Status::Queued(meta_guess.clone()); - let mut batch = Batch::default(); - batch.insert(&status_key(id), bincode::serialize(&db_entry).unwrap()); - batch.insert(&db_mutex_key(id), bincode::serialize(&false).unwrap()); - db.apply_batch(batch).unwrap(); - - let job = Job { - id, - url: url, - feedback: feedback.clone(), - }; - self.url_tx.try_send(job).unwrap(); - feedback - .send(JobStatus::Queued(meta_guess, id), &self.token) - .await; - dbg!(); - Ok(()) - } - - pub async fn meta_ok(&self, id: u64) -> Result<(), Error> { - let db = self.db.open_tree("youtube_dl").unwrap(); - - aquire_db_mutex(&db, id).await; - let job_status = db - .get(&status_key(id)) - .unwrap() - .ok_or(Error::CanNoLongerUpdateMeta)?; - let job_status = bincode::deserialize(&job_status.to_vec()).unwrap(); - let new_status = match job_status { - Status::Queued(meta_guess) => { - let new_meta = MetaData { - title: meta_guess.title, - artist: meta_guess.artist, - source_url: meta_guess.source_url, - }; - Status::MetaConfirmed(new_meta) - } - Status::MetaConfirmed(meta) => Status::MetaConfirmed(meta), - Status::Downloaded(meta_guess) => { - let new_meta = MetaData { - title: meta_guess.title, - artist: meta_guess.artist, - source_url: meta_guess.source_url, - }; - let new_path = write_metadata(id, &new_meta)?; - Status::MetaWritten((new_path, new_meta)) - } - Status::MetaWritten(i) => Status::MetaWritten(i), - }; - - let mut batch = Batch::default(); - batch.insert(&status_key(id), bincode::serialize(&new_status).unwrap()); - batch.insert( - //unlock file lock - &db_mutex_key(id), - bincode::serialize(&false).unwrap(), - ); - db.apply_batch(batch).unwrap(); - Ok(()) - } - - pub async fn swap_meta(&self, id: u64) -> Result<(), Error> { - let db = self.db.open_tree("youtube_dl").unwrap(); - - aquire_db_mutex(&db, id).await; - let job_status = db - .get(&status_key(id)) - .unwrap() - .ok_or(Error::CanNoLongerUpdateMeta)?; - let job_status = bincode::deserialize(&job_status.to_vec()).unwrap(); - let new_status = match job_status { - Status::Queued(meta_guess) => { - let new_meta = MetaData { - title: meta_guess.artist, - artist: meta_guess.title, - source_url: meta_guess.source_url, - }; - Status::MetaConfirmed(new_meta) - } - Status::MetaConfirmed(mut meta) => { - meta.title = meta.artist.clone(); - meta.artist = meta.title.clone(); - Status::MetaConfirmed(meta) - } - Status::Downloaded(meta_guess) => { - let new_meta = MetaData { - title: meta_guess.artist, - artist: meta_guess.title, - source_url: meta_guess.source_url, - }; - let new_path = write_metadata(id, &new_meta)?; - Status::MetaWritten((new_path, new_meta)) - } - Status::MetaWritten((path, mut meta)) => { - meta.artist = meta.title.clone(); - meta.title = meta.artist.clone(); - let new_path = update_metadata(&path, &meta)?; - Status::MetaWritten((new_path, meta)) - } - }; - - let mut batch = Batch::default(); - batch.insert(&status_key(id), bincode::serialize(&new_status).unwrap()); - batch.insert( - //unlock file lock - &db_mutex_key(id), - bincode::serialize(&false).unwrap(), - ); - db.apply_batch(batch).unwrap(); - Ok(()) - } - - pub async fn no_meta(&self, id: u64) -> Result<(), Error> { - let db = self.db.open_tree("youtube_dl").unwrap(); - - aquire_db_mutex(&db, id).await; - let job_status = db - .get(&status_key(id)) - .unwrap() - .ok_or(Error::CanNoLongerUpdateMeta)?; - let job_status = bincode::deserialize(&job_status.to_vec()).unwrap(); - let new_status = match job_status { - Status::Queued(meta) => { - let new_meta = MetaData { - title: format!("{} {}", meta.title, meta.artist), - artist: "".to_owned(), - source_url: meta.source_url, - }; - Status::MetaConfirmed(new_meta) - } - Status::MetaConfirmed(mut meta) => { - meta.title = format!("{} {}", meta.title, meta.artist); - meta.artist = "".to_owned(); - Status::MetaConfirmed(meta) - } - Status::Downloaded(meta) => { - let new_meta = MetaData { - title: format!("{} {}", meta.title, meta.artist), - artist: "".to_owned(), - source_url: meta.source_url, - }; - let new_path = write_metadata(id, &new_meta)?; - Status::MetaWritten((new_path, new_meta)) - } - Status::MetaWritten((path, mut meta)) => { - meta.title = format!("{} {}", meta.title, meta.artist); - meta.artist = "".to_owned(); - let new_path = update_metadata(&path, &meta)?; - Status::MetaWritten((new_path, meta)) - } - }; - - let mut batch = Batch::default(); - batch.insert(&status_key(id), bincode::serialize(&new_status).unwrap()); - batch.insert( - //unlock file lock - &db_mutex_key(id), - bincode::serialize(&false).unwrap(), - ); - db.apply_batch(batch).unwrap(); - - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - /*#[test] - fn test_parse_stdout(){ - - let test_case = String::from("[youtube] 1MZu2pD3QPY: Downloading webpage\n[youtube] 1MZu2pD3QPY: Downloading video info webpage\n[youtube] Downloading just video 1MZu2pD3QPY because of --no-playlist\n[download] Destination: /home/pi/Music/youtube/Trevor Jones - Promentory (The Last of the Mohicans).webm\n\r[download] 0.0% of 6.03MiB at 527.45KiB/s ETA 00:12\r[download] 0.0% of 6.03MiB at 1.06MiB/s ETA 00:05\r[download] 0.1% of 6.03MiB at 1.90MiB/s ETA 00:03\r[download] 0.2% of 6.03MiB at 3.33MiB/s ETA 00:01\r[download] 0.5% of 6.03MiB at 4.79MiB/s ETA 00:01\r[download] 1.0% of 6.03MiB at 6.59MiB/s ETA 00:00\r[download] 2.1% of 6.03MiB at 7.89MiB/s ETA 00:00\r[download] 4.1% of 6.03MiB at 9.44MiB/s ETA 00:00\r[download] 8.3% of 6.03MiB at 10.43MiB/s ETA 00:00\r[download] 16.6% of 6.03MiB at 10.76MiB/s ETA 00:00\r[download] 33.1% of 6.03MiB at 10.06MiB/s ETA 00:00\r[download] 66.3% of 6.03MiB at 10.36MiB/s ETA 00:00\r[download] 100.0% of 6.03MiB at 10.33MiB/s ETA 00:00\r[download] 100% of 6.03MiB in 00:00\n[fromtitle] parsed artist: Trevor Jones\n[fromtitle] parsed title: Promentory (The Last of the Mohicans)\n[ffmpeg] Destination: /home/pi/Music/youtube/Trevor Jones - Promentory (The Last of the Mohicans).m4a\nDeleting original file /home/pi/Music/youtube/Trevor Jones - Promentory (The Last of the Mohicans).webm (pass -k to keep)\n[ffmpeg] Adding metadata to \'/home/pi/Music/youtube/Trevor Jones - Promentory (The Last of the Mohicans).m4a\'\n"); - let test_case = test_case.into_bytes(); - let test_case_awnser = "Trevor Jones - Promentory (The Last of the Mohicans)"; - assert_eq!(parse_stdout(test_case).unwrap(), test_case_awnser); - }*/ - - #[test] - fn test_split() { - let (artist, title) = split("Merlin 4 Soundtrack \"The Burial\" 04"); - assert_eq!(artist, "Merlin 4 Soundtrack"); - assert_eq!(title, "The Burial"); - } -} diff --git a/src/main.rs b/src/main.rs index 3fb4a7f6..72409a57 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,46 +1,24 @@ -#[macro_use] -extern crate log; - use sled; use structopt::StructOpt; +use tracing::warn; mod controller; -mod input; -use input::bot; -use input::web_api::server; -use input::web_api::server::{PasswordDatabase, State}; - mod errors; +mod input; #[derive(StructOpt)] #[structopt(name = "homeautomation")] struct Opt { - /// port to bind to and listen for traffic - #[structopt(short = "p", long = "port", default_value = "443")] - port: u16, - /// port to which telegram bot traffic should be send - #[structopt(short = "e", long = "external-port", default_value = "443")] - external_port: u16, - /// telegram bot token - #[structopt(short = "t", long = "token")] - token: String, - /// domain to which telegram bot traffic should be send - #[structopt(short = "d", long = "domain")] - domain: String, - #[structopt(short = "a", long = "admin-password")] - password: String, - #[structopt(short = "i", long = "allowed-telegram-ids")] - valid_ids: Vec, - /// secret url part on which sensor data is recieved + /// secret url part on which sensor data is received #[structopt(short = "h", long = "ha-key")] ha_key: String, } -#[actix_rt::main] +#[tokio::main] async fn main() { let opt = Opt::from_args(); - errors::setup_logging(2).unwrap(); + setup_tracing(); let db = sled::Config::default() //651ms .path("database") @@ -49,43 +27,49 @@ async fn main() { .open() .unwrap(); - let mut passw_db = PasswordDatabase::from_db(&db).unwrap(); - passw_db.add_admin(&opt.password).unwrap(); - let (controller_tx, controller_rx) = crossbeam_channel::unbounded(); let (joblist, _waker_thread) = input::jobs::Jobs::setup(controller_tx.clone(), db.clone()).unwrap(); let wakeup = input::jobs::WakeUp::setup(db.clone(), joblist.clone()).unwrap(); - let (youtube_dl, _downloader_thread) = - input::YoutubeDownloader::init(opt.token.clone(), db.clone()) - .await - .unwrap(); let (mpd_status, _mpd_watcher_thread, _updater_tx) = input::MpdStatus::start_updating().unwrap(); let _controller_thread = controller::start(controller_rx, mpd_status.clone(), wakeup.clone()).unwrap(); - - let state = State::new( - passw_db, - controller_tx.clone(), - joblist, - wakeup, - youtube_dl, - opt.token.clone(), - opt.valid_ids.clone(), - ); - - //start the webserver - let _web_handle = - server::start_webserver(state, opt.port, opt.domain.clone(), opt.ha_key.clone()); - - bot::set_webhook(&opt.domain, &opt.token, opt.external_port) - .await - .unwrap(); + let _webserver = input::api::setup(wakeup.clone()).unwrap(); loop { std::thread::park(); } } + +pub fn setup_tracing() { + use tracing_subscriber::filter; + use tracing_subscriber::fmt; + use tracing_subscriber::prelude::*; + + let filter = filter::EnvFilter::builder() + .with_regex(true) + .try_from_env() + .unwrap_or_else(|_| { + filter::EnvFilter::builder() + .parse("HomeAutomation=debug,info") + .unwrap() + }); + + let fmt = fmt::layer() + .pretty() + .with_line_number(true) + .with_test_writer(); + + let registry = tracing_subscriber::registry().with(filter).with(fmt); + match tracing_journald::layer() { + Ok(journal) => registry.with(journal).init(), + Err(err) => { + warn!("Failed to init journald logging, error: {err}"); + registry.init() + } + }; + log_panics::init(); +} From ac354ad8d91c43ab6cef0253a84378b1ccdc1460 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 12 Mar 2024 02:05:24 +0100 Subject: [PATCH 081/687] re-add alarm api --- Cargo.lock | 1494 +++++------------ Cargo.toml | 82 +- LICENSE.md | 21 - crates/protocol/Cargo.toml | 12 + crates/protocol/src/lib.rs | 14 + crates/system/Cargo.toml | 54 + deploy.sh => crates/system/deploy.sh | 0 .../system/deploy_optimized.sh | 0 .../system/src}/controller/commands.rs | 0 .../system/src}/controller/environment/mod.rs | 0 {src => crates/system/src}/controller/mod.rs | 4 +- .../system/src}/controller/state/lightloop.rs | 0 .../system/src}/controller/state/mod.rs | 0 .../system/src}/controller/state/normal.rs | 0 .../system/src}/controller/state/off.rs | 0 .../system/src}/controller/state/silent.rs | 0 .../system/src}/controller/state/sleep.rs | 0 .../system/src}/controller/state/wakeup.rs | 0 .../system/src}/controller/system/computer.rs | 0 .../controller/system/lamps/bridge_connect.rs | 0 .../lamps/eventually_consistent_bridge.rs | 0 .../src}/controller/system/lamps/lamp.rs | 0 .../src}/controller/system/lamps/mod.rs | 0 .../system/src}/controller/system/mod.rs | 0 .../src}/controller/system/mpd_control.rs | 0 {src => crates/system/src}/errors.rs | 0 crates/system/src/input/api.rs | 86 + {src => crates/system/src}/input/jobs.rs | 0 .../system/src}/input/jobs/wakeup.rs | 17 +- {src => crates/system/src}/input/mod.rs | 0 .../system/src}/input/mpd_status.rs | 5 +- .../system/src}/input/web_api/commands.rs | 0 .../system/src}/input/web_api/mod.rs | 0 .../system/src}/input/web_api/music.rs | 0 .../src}/input/web_api/server/database.rs | 0 .../system/src}/input/web_api/server/login.rs | 0 .../input/web_api/server/login_redirect.rs | 0 .../system/src}/input/web_api/server/mod.rs | 0 .../web_api/server/static_webpages/login.css | 0 .../web_api/server/static_webpages/login.html | 0 .../system/src}/input/web_api/wakeup.rs | 0 {src => crates/system/src}/main.rs | 39 +- {web => crates/system/web}/add_song.html | 0 {web => crates/system/web}/graph.html | 0 {web => crates/system/web}/graphDebug.html | 0 {web => crates/system/web}/login.css | 0 {web => crates/system/web}/login.html | 0 {web => crates/system/web}/plot.js | 0 {web => crates/system/web}/plot_debug.js | 0 {web => crates/system/web}/set_alarm.html | 0 {web => crates/system/web}/test.html | 0 {web => crates/system/web}/test_decode.html | 0 .../system/web}/test_graph_updates.html | 0 .../system/web}/test_ws_interface.html | 0 {web => crates/system/web}/websocket.html | 0 .../system/web}/websocket_getData.html | 0 .../system/web}/websocket_getData2.html | 0 deny.toml | 196 --- src/input/api.rs | 26 - 59 files changed, 663 insertions(+), 1387 deletions(-) delete mode 100644 LICENSE.md create mode 100644 crates/protocol/Cargo.toml create mode 100644 crates/protocol/src/lib.rs create mode 100644 crates/system/Cargo.toml rename deploy.sh => crates/system/deploy.sh (100%) rename deploy_optimized.sh => crates/system/deploy_optimized.sh (100%) rename {src => crates/system/src}/controller/commands.rs (100%) rename {src => crates/system/src}/controller/environment/mod.rs (100%) rename {src => crates/system/src}/controller/mod.rs (98%) rename {src => crates/system/src}/controller/state/lightloop.rs (100%) rename {src => crates/system/src}/controller/state/mod.rs (100%) rename {src => crates/system/src}/controller/state/normal.rs (100%) rename {src => crates/system/src}/controller/state/off.rs (100%) rename {src => crates/system/src}/controller/state/silent.rs (100%) rename {src => crates/system/src}/controller/state/sleep.rs (100%) rename {src => crates/system/src}/controller/state/wakeup.rs (100%) rename {src => crates/system/src}/controller/system/computer.rs (100%) rename {src => crates/system/src}/controller/system/lamps/bridge_connect.rs (100%) rename {src => crates/system/src}/controller/system/lamps/eventually_consistent_bridge.rs (100%) rename {src => crates/system/src}/controller/system/lamps/lamp.rs (100%) rename {src => crates/system/src}/controller/system/lamps/mod.rs (100%) rename {src => crates/system/src}/controller/system/mod.rs (100%) rename {src => crates/system/src}/controller/system/mpd_control.rs (100%) rename {src => crates/system/src}/errors.rs (100%) create mode 100644 crates/system/src/input/api.rs rename {src => crates/system/src}/input/jobs.rs (100%) rename {src => crates/system/src}/input/jobs/wakeup.rs (93%) rename {src => crates/system/src}/input/mod.rs (100%) rename {src => crates/system/src}/input/mpd_status.rs (90%) rename {src => crates/system/src}/input/web_api/commands.rs (100%) rename {src => crates/system/src}/input/web_api/mod.rs (100%) rename {src => crates/system/src}/input/web_api/music.rs (100%) rename {src => crates/system/src}/input/web_api/server/database.rs (100%) rename {src => crates/system/src}/input/web_api/server/login.rs (100%) rename {src => crates/system/src}/input/web_api/server/login_redirect.rs (100%) rename {src => crates/system/src}/input/web_api/server/mod.rs (100%) rename {src => crates/system/src}/input/web_api/server/static_webpages/login.css (100%) rename {src => crates/system/src}/input/web_api/server/static_webpages/login.html (100%) rename {src => crates/system/src}/input/web_api/wakeup.rs (100%) rename {src => crates/system/src}/main.rs (64%) rename {web => crates/system/web}/add_song.html (100%) rename {web => crates/system/web}/graph.html (100%) rename {web => crates/system/web}/graphDebug.html (100%) rename {web => crates/system/web}/login.css (100%) rename {web => crates/system/web}/login.html (100%) rename {web => crates/system/web}/plot.js (100%) rename {web => crates/system/web}/plot_debug.js (100%) rename {web => crates/system/web}/set_alarm.html (100%) rename {web => crates/system/web}/test.html (100%) rename {web => crates/system/web}/test_decode.html (100%) rename {web => crates/system/web}/test_graph_updates.html (100%) rename {web => crates/system/web}/test_ws_interface.html (100%) rename {web => crates/system/web}/websocket.html (100%) rename {web => crates/system/web}/websocket_getData.html (100%) rename {web => crates/system/web}/websocket_getData2.html (100%) delete mode 100644 deny.toml delete mode 100644 src/input/api.rs diff --git a/Cargo.lock b/Cargo.lock index e05d80b3..4016c6e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.17.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -19,13 +19,19 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -36,34 +42,62 @@ dependencies = [ ] [[package]] -name = "ansi_term" -version = "0.12.1" +name = "anstream" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" dependencies = [ - "winapi 0.3.9", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", ] [[package]] -name = "async-trait" -version = "0.1.77" +name = "anstyle" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", + "utf8parse", ] [[package]] -name = "atty" -version = "0.2.14" +name = "anstyle-query" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ - "hermit-abi", - "libc", - "winapi 0.3.9", + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-trait" +version = "0.1.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", ] [[package]] @@ -89,7 +123,7 @@ checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e" dependencies = [ "async-trait", "axum-core", - "bytes 1.3.0", + "bytes 1.5.0", "futures-util", "http 1.1.0", "http-body 1.0.0", @@ -99,8 +133,8 @@ dependencies = [ "itoa 1.0.10", "matchit", "memchr", - "mime 0.3.16", - "percent-encoding 2.2.0", + "mime", + "percent-encoding 2.3.1", "pin-project-lite 0.2.13", "rustversion", "serde", @@ -108,7 +142,7 @@ dependencies = [ "serde_path_to_error", "serde_urlencoded 0.7.1", "sync_wrapper", - "tokio 1.35.1", + "tokio 1.36.0", "tower", "tower-layer", "tower-service", @@ -122,12 +156,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" dependencies = [ "async-trait", - "bytes 1.3.0", + "bytes 1.5.0", "futures-util", "http 1.1.0", "http-body 1.0.0", "http-body-util", - "mime 0.3.16", + "mime", "pin-project-lite 0.2.13", "rustversion", "sync_wrapper", @@ -136,17 +170,29 @@ dependencies = [ "tracing", ] +[[package]] +name = "axum-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "backtrace" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide 0.5.4", + "miniz_oxide", "object", "rustc-demangle", ] @@ -181,18 +227,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bitflags" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" - -[[package]] -name = "bitflags" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" - [[package]] name = "bitflags" version = "1.3.2" @@ -204,7 +238,7 @@ name = "bitspec" version = "1.0.0" source = "git+https://github.com/dskleingeld/bitspec?branch=bool-fields#65e92b1ad3d3900a634cc6828785ed4054c83985" dependencies = [ - "log 0.4.17", + "log", "num 0.3.1", "rand 0.5.6", "serde", @@ -213,15 +247,6 @@ dependencies = [ "text_io", ] -[[package]] -name = "bme280" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d48076b7293afafab5ff93e3db57435c567f1fc72755c27d377f7e96ea66678d" -dependencies = [ - "embedded-hal", -] - [[package]] name = "bufstream" version = "0.1.4" @@ -230,15 +255,15 @@ checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" @@ -259,24 +284,15 @@ checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" [[package]] name = "bytes" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" - -[[package]] -name = "cast" -version = "0.2.7" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" -dependencies = [ - "rustc_version 0.4.0", -] +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cc" -version = "1.0.77" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" [[package]] name = "cfg-if" @@ -292,75 +308,74 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.23" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" dependencies = [ + "android-tzdata", "iana-time-zone", "js-sys", - "num-integer", "num-traits", "serde", - "time", "wasm-bindgen", - "winapi 0.3.9", + "windows-targets 0.52.4", ] [[package]] -name = "chrono-tz" -version = "0.5.3" +name = "clap" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2554a3155fec064362507487171dcc4edc3df60cb10f3a1fb10ed8094822b120" +checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651" dependencies = [ - "chrono", - "parse-zoneinfo", + "clap_builder", + "clap_derive", ] [[package]] -name = "clap" -version = "2.34.0" +name = "clap_builder" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ - "ansi_term", - "atty", - "bitflags 1.3.2", + "anstream", + "anstyle", + "clap_lex", "strsim", - "textwrap", - "unicode-width", - "vec_map", ] [[package]] -name = "cloudabi" -version = "0.0.3" +name = "clap_derive" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" dependencies = [ - "bitflags 1.3.2", + "heck", + "proc-macro2", + "quote", + "syn 2.0.52", ] [[package]] -name = "codespan-reporting" -version = "0.11.1" +name = "clap_lex" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] -name = "colored" -version = "1.9.3" +name = "cloudabi" +version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" dependencies = [ - "atty", - "lazy_static", - "winapi 0.3.9", + "bitflags", ] +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "cookie" version = "0.12.0" @@ -380,7 +395,7 @@ dependencies = [ "cookie", "failure", "idna 0.1.5", - "log 0.4.17", + "log", "publicsuffix", "serde", "serde_json", @@ -389,33 +404,17 @@ dependencies = [ "url 1.7.2", ] -[[package]] -name = "core-foundation" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" -dependencies = [ - "core-foundation-sys 0.6.2", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" - [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if 1.0.0", ] @@ -451,21 +450,17 @@ dependencies = [ "crossbeam-utils 0.7.2", "lazy_static", "maybe-uninit", - "memoffset 0.5.6", + "memoffset", "scopeguard", ] [[package]] name = "crossbeam-epoch" -version = "0.9.13" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg 1.1.0", - "cfg-if 1.0.0", - "crossbeam-utils 0.8.14", - "memoffset 0.7.1", - "scopeguard", + "crossbeam-utils 0.8.19", ] [[package]] @@ -502,12 +497,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.14" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "ct-logs" @@ -518,71 +510,6 @@ dependencies = [ "sct", ] -[[package]] -name = "cxx" -version = "1.0.82" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453" -dependencies = [ - "cc", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", -] - -[[package]] -name = "cxx-build" -version = "1.0.82" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0" -dependencies = [ - "cc", - "codespan-reporting", - "once_cell", - "proc-macro2", - "quote", - "scratch", - "syn 1.0.103", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.82" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.82" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.103", -] - -[[package]] -name = "dirs" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" -dependencies = [ - "cfg-if 0.1.10", - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi 0.3.9", -] - [[package]] name = "dtoa" version = "0.4.8" @@ -591,25 +518,15 @@ checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" [[package]] name = "either" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" - -[[package]] -name = "embedded-hal" -version = "0.2.7" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" -dependencies = [ - "nb 0.1.3", - "void", -] +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "encoding_rs" -version = "0.8.31" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if 1.0.0", ] @@ -647,38 +564,18 @@ checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn 1.0.109", "synstructure", ] -[[package]] -name = "fastrand" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" -dependencies = [ - "instant", -] - -[[package]] -name = "fern" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e69ab0d5aca163e388c3a49d284fed6c3d0810700e77c5ae2756a50ec1a4daaa" -dependencies = [ - "chrono", - "colored", - "log 0.4.17", -] - [[package]] name = "flate2" -version = "1.0.25" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", - "miniz_oxide 0.6.2", + "miniz_oxide", ] [[package]] @@ -689,11 +586,11 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ - "percent-encoding 2.2.0", + "percent-encoding 2.3.1", ] [[package]] @@ -718,7 +615,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" dependencies = [ - "bitflags 1.3.2", + "bitflags", "fuchsia-zircon-sys", ] @@ -736,9 +633,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.25" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -777,9 +674,9 @@ dependencies = [ [[package]] name = "futures-executor" -version = "0.3.25" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -800,7 +697,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] @@ -844,9 +741,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if 1.0.0", "libc", @@ -855,9 +752,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.2" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "h2" @@ -870,8 +767,8 @@ dependencies = [ "fnv", "futures 0.1.31", "http 0.1.21", - "indexmap 1.9.2", - "log 0.4.17", + "indexmap 1.9.3", + "log", "slab", "string", "tokio-io", @@ -888,8 +785,8 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http 0.2.8", - "indexmap 1.9.2", + "http 0.2.12", + "indexmap 1.9.3", "slab", "tokio 0.2.25", "tokio-util 0.3.1", @@ -903,7 +800,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943" dependencies = [ - "bytes 1.3.0", + "bytes 1.5.0", "fnv", "futures-core", "futures-sink", @@ -911,7 +808,7 @@ dependencies = [ "http 1.1.0", "indexmap 2.2.5", "slab", - "tokio 1.35.1", + "tokio 1.36.0", "tokio-util 0.7.10", "tracing", ] @@ -921,37 +818,29 @@ name = "ha" version = "0.1.0" dependencies = [ "axum", + "axum-macros", "bincode", - "bme280", "byteorder", "bytes 0.4.12", "chrono", - "chrono-tz", + "clap", "crossbeam-channel", - "dirs", - "fern", - "futures 0.3.25", + "futures 0.3.30", "futures-util", - "hex", - "linux-embedded-hal", "log-panics", "mpd", "num 0.2.1", "philipshue", + "protocol", "rand 0.6.5", - "regex", "reqwest 0.10.10", "retry", "sensor_value", "serde", - "serde_json", "serde_yaml", "sled", - "smallvec 0.6.14", - "structopt", - "telegram-bot", "thiserror", - "tokio 1.35.1", + "tokio 1.36.0", "tracing", "tracing-journald", "tracing-subscriber", @@ -971,27 +860,15 @@ checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "heck" -version = "0.3.3" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hex" -version = "0.4.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "http" @@ -1006,11 +883,11 @@ dependencies = [ [[package]] name = "http" -version = "0.2.8" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "bytes 1.3.0", + "bytes 1.5.0", "fnv", "itoa 1.0.10", ] @@ -1021,7 +898,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ - "bytes 1.3.0", + "bytes 1.5.0", "fnv", "itoa 1.0.10", ] @@ -1045,7 +922,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" dependencies = [ "bytes 0.5.6", - "http 0.2.8", + "http 0.2.12", ] [[package]] @@ -1054,18 +931,18 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ - "bytes 1.3.0", + "bytes 1.5.0", "http 1.1.0", ] [[package]] name = "http-body-util" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" dependencies = [ - "bytes 1.3.0", - "futures-util", + "bytes 1.5.0", + "futures-core", "http 1.1.0", "http-body 1.0.0", "pin-project-lite 0.2.13", @@ -1104,9 +981,9 @@ dependencies = [ "httparse", "iovec", "itoa 0.4.8", - "log 0.4.17", + "log", "net2", - "rustc_version 0.2.3", + "rustc_version", "time", "tokio 0.1.22", "tokio-buf", @@ -1130,7 +1007,7 @@ dependencies = [ "futures-core", "futures-util", "h2 0.2.7", - "http 0.2.8", + "http 0.2.12", "http-body 0.3.1", "httparse", "httpdate 0.3.2", @@ -1140,7 +1017,7 @@ dependencies = [ "tokio 0.2.25", "tower-service", "tracing", - "want 0.3.0", + "want 0.3.1", ] [[package]] @@ -1149,7 +1026,7 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" dependencies = [ - "bytes 1.3.0", + "bytes 1.5.0", "futures-channel", "futures-util", "h2 0.4.2", @@ -1160,7 +1037,7 @@ dependencies = [ "itoa 1.0.10", "pin-project-lite 0.2.13", "smallvec 1.13.1", - "tokio 1.35.1", + "tokio 1.36.0", ] [[package]] @@ -1180,23 +1057,6 @@ dependencies = [ "webpki-roots 0.17.0", ] -[[package]] -name = "hyper-rustls" -version = "0.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ea6215c7314d450ee45970ab8b3851ab447a0e6bafdd19e31b20a42dbb7faf" -dependencies = [ - "bytes 0.5.6", - "ct-logs", - "futures-util", - "hyper 0.13.10", - "rustls 0.16.0", - "rustls-native-certs", - "tokio 0.2.25", - "tokio-rustls 0.12.3", - "webpki", -] - [[package]] name = "hyper-rustls" version = "0.21.0" @@ -1206,7 +1066,7 @@ dependencies = [ "bytes 0.5.6", "futures-util", "hyper 0.13.10", - "log 0.4.17", + "log", "rustls 0.18.1", "tokio 0.2.25", "tokio-rustls 0.14.1", @@ -1219,50 +1079,37 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" dependencies = [ - "bytes 1.3.0", + "bytes 1.5.0", "futures-util", "http 1.1.0", "http-body 1.0.0", "hyper 1.2.0", "pin-project-lite 0.2.13", - "socket2 0.5.5", - "tokio 1.35.1", -] - -[[package]] -name = "i2cdev" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0eb3d9b6b02dc2508ee23439170004e44344bab9d53a490eb1f64c885b5003" -dependencies = [ - "bitflags 1.3.2", - "byteorder", - "libc", - "nix 0.14.1", + "socket2 0.5.6", + "tokio 1.36.0", ] [[package]] name = "iana-time-zone" -version = "0.1.53" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", - "core-foundation-sys 0.8.3", + "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "winapi 0.3.9", + "windows-core", ] [[package]] name = "iana-time-zone-haiku" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ - "cxx", - "cxx-build", + "cc", ] [[package]] @@ -1289,9 +1136,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.3.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1299,9 +1146,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg 1.1.0", "hashbrown 0.12.3", @@ -1337,9 +1184,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.5.1" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "itoa" @@ -1355,9 +1202,9 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1380,18 +1227,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.152" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" - -[[package]] -name = "link-cplusplus" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" -dependencies = [ - "cc", -] +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "linked-hash-map" @@ -1399,19 +1237,6 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" -[[package]] -name = "linux-embedded-hal" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "795096c0eecb0622afb591c3e1a97b1ba046688a7689957b70b8eee9cac8fb84" -dependencies = [ - "cast", - "embedded-hal", - "i2cdev", - "spidev", - "sysfs_gpio", -] - [[package]] name = "lock_api" version = "0.3.4" @@ -1423,9 +1248,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg 1.1.0", "scopeguard", @@ -1433,21 +1258,9 @@ dependencies = [ [[package]] name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -dependencies = [ - "log 0.4.17", -] - -[[package]] -name = "log" -version = "0.4.17" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "log-panics" @@ -1455,7 +1268,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68f9dd8546191c1850ecf67d22f5ff00a935b890d0e84713159a55495cc2ac5f" dependencies = [ - "log 0.4.17", + "log", ] [[package]] @@ -1464,14 +1277,14 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] name = "matches" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "matchit" @@ -1487,9 +1300,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memoffset" @@ -1500,41 +1313,11 @@ dependencies = [ "autocfg 1.1.0", ] -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg 1.1.0", -] - [[package]] name = "mime" -version = "0.2.6" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -dependencies = [ - "log 0.3.9", -] - -[[package]] -name = "mime" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" - -[[package]] -name = "mime_guess" -version = "1.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216929a5ee4dd316b1702eedf5e74548c123d370f47841ceaac38ca154690ca3" -dependencies = [ - "mime 0.2.6", - "phf", - "phf_codegen", - "unicase 1.4.2", -] +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" @@ -1542,24 +1325,15 @@ version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" dependencies = [ - "mime 0.3.16", - "unicase 2.6.0", + "mime", + "unicase", ] [[package]] name = "miniz_oxide" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" -dependencies = [ - "adler", -] - -[[package]] -name = "miniz_oxide" -version = "0.6.2" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] @@ -1576,7 +1350,7 @@ dependencies = [ "iovec", "kernel32-sys", "libc", - "log 0.4.17", + "log", "miow", "net2", "slab", @@ -1585,9 +1359,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", @@ -1615,72 +1389,17 @@ dependencies = [ "bufstream", ] -[[package]] -name = "multipart" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136eed74cadb9edd2651ffba732b19a450316b680e4f48d6c79e905799e19d01" -dependencies = [ - "log 0.4.17", - "mime 0.2.6", - "mime_guess 1.8.8", - "rand 0.6.5", - "tempfile", -] - -[[package]] -name = "nb" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" -dependencies = [ - "nb 1.0.0", -] - -[[package]] -name = "nb" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" - [[package]] name = "net2" -version = "0.2.38" +version = "0.2.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d0df99cfcd2530b2e694f6e17e7f37b8e26bb23983ac530c0c97408837c631" +checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" dependencies = [ "cfg-if 0.1.10", "libc", "winapi 0.3.9", ] -[[package]] -name = "nix" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a7bb1da2be7da3cbffda73fc681d509ffd9e665af478d2bee1907cee0bc64b2" -dependencies = [ - "bitflags 0.4.0", - "cfg-if 0.1.10", - "libc", - "rustc_version 0.1.7", - "semver 0.1.20", - "void", -] - -[[package]] -name = "nix" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" -dependencies = [ - "bitflags 1.3.2", - "cc", - "cfg-if 0.1.10", - "libc", - "void", -] - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1762,19 +1481,18 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg 1.1.0", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" dependencies = [ "autocfg 1.1.0", "num-integer", @@ -1807,18 +1525,18 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg 1.1.0", ] [[package]] name = "num_cpus" -version = "1.14.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", @@ -1826,9 +1544,9 @@ dependencies = [ [[package]] name = "object" -version = "0.29.0" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -1839,21 +1557,6 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "ordered-float" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3305af35278dd29f46fcdd139e0b1fbfae2153f0e5928b39b035542dd31e37b7" -dependencies = [ - "num-traits", -] - [[package]] name = "overload" version = "0.1.1" @@ -1867,8 +1570,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" dependencies = [ "lock_api 0.3.4", - "parking_lot_core 0.6.2", - "rustc_version 0.2.3", + "parking_lot_core 0.6.3", + "rustc_version", ] [[package]] @@ -1878,8 +1581,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", - "lock_api 0.4.9", - "parking_lot_core 0.8.5", + "lock_api 0.4.11", + "parking_lot_core 0.8.6", ] [[package]] @@ -1888,30 +1591,30 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ - "lock_api 0.4.9", + "lock_api 0.4.11", "parking_lot_core 0.9.9", ] [[package]] name = "parking_lot_core" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" +checksum = "bda66b810a62be75176a80873726630147a5ca780cd33921e0b5709033e66b0a" dependencies = [ "cfg-if 0.1.10", "cloudabi", "libc", "redox_syscall 0.1.57", - "rustc_version 0.2.3", + "rustc_version", "smallvec 0.6.14", "winapi 0.3.9", ] [[package]] name = "parking_lot_core" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ "cfg-if 1.0.0", "instant", @@ -1931,16 +1634,7 @@ dependencies = [ "libc", "redox_syscall 0.4.1", "smallvec 1.13.1", - "windows-targets", -] - -[[package]] -name = "parse-zoneinfo" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" -dependencies = [ - "regex", + "windows-targets 0.48.5", ] [[package]] @@ -1951,53 +1645,14 @@ checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" [[package]] name = "percent-encoding" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" - -[[package]] -name = "phf" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" -dependencies = [ - "phf_shared", -] - -[[package]] -name = "phf_codegen" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" -dependencies = [ - "phf_generator", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" -dependencies = [ - "phf_shared", - "rand 0.6.5", -] - -[[package]] -name = "phf_shared" -version = "0.7.24" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" -dependencies = [ - "siphasher", - "unicase 1.4.2", -] +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "philipshue" version = "0.3.2" -source = "git+https://github.com/dskleingeld/philipshue?branch=master#c52c7fa306a78c3432f5619bb4de75ccd55fb19f" +source = "git+https://github.com/dvdsk/philipshue?branch=master#c52c7fa306a78c3432f5619bb4de75ccd55fb19f" dependencies = [ "error-chain", "reqwest 0.9.24", @@ -2008,22 +1663,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.12" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.12" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn 2.0.52", ] [[package]] @@ -2050,37 +1705,20 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.103", - "version_check 0.9.4", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check 0.9.4", -] - [[package]] name = "proc-macro2" version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ - "unicode-ident", + "unicode-ident", +] + +[[package]] +name = "protocol" +version = "0.1.0" +dependencies = [ + "serde", ] [[package]] @@ -2090,7 +1728,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95b4ce31ff0a27d93c8de1849cf58162283752f065a90d508f1105fa6c9a213f" dependencies = [ "idna 0.2.3", - "url 2.3.1", + "url 2.5.0", ] [[package]] @@ -2272,7 +1910,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags 1.3.2", + "bitflags", ] [[package]] @@ -2281,29 +1919,19 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_users" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" -dependencies = [ - "getrandom", - "redox_syscall 0.2.16", - "thiserror", + "bitflags", ] [[package]] name = "regex" -version = "1.7.0" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-automata 0.4.6", + "regex-syntax 0.8.2", ] [[package]] @@ -2312,23 +1940,31 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "regex-syntax", + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.2", ] [[package]] name = "regex-syntax" -version = "0.6.28" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] -name = "remove_dir_all" -version = "0.5.3" +name = "regex-syntax" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi 0.3.9", -] +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" @@ -2346,9 +1982,9 @@ dependencies = [ "http 0.1.21", "hyper 0.12.36", "hyper-rustls 0.17.1", - "log 0.4.17", - "mime 0.3.16", - "mime_guess 2.0.4", + "log", + "mime", + "mime_guess", "rustls 0.16.0", "serde", "serde_json", @@ -2377,24 +2013,24 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "http 0.2.8", + "http 0.2.12", "http-body 0.3.1", "hyper 0.13.10", "hyper-rustls 0.21.0", "ipnet", "js-sys", "lazy_static", - "log 0.4.17", - "mime 0.3.16", - "mime_guess 2.0.4", - "percent-encoding 2.2.0", + "log", + "mime", + "mime_guess", + "percent-encoding 2.3.1", "pin-project-lite 0.2.13", "rustls 0.18.1", "serde", "serde_urlencoded 0.7.1", "tokio 0.2.25", "tokio-rustls 0.14.1", - "url 2.3.1", + "url 2.5.0", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -2428,18 +2064,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" - -[[package]] -name = "rustc_version" -version = "0.1.7" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" -dependencies = [ - "semver 0.1.20", -] +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustc_version" @@ -2447,16 +2074,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver 0.9.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver 1.0.14", + "semver", ] [[package]] @@ -2466,7 +2084,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" dependencies = [ "base64 0.10.1", - "log 0.4.17", + "log", "ring", "sct", "webpki", @@ -2479,24 +2097,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81" dependencies = [ "base64 0.12.3", - "log 0.4.17", + "log", "ring", "sct", "webpki", ] -[[package]] -name = "rustls-native-certs" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51ffebdbb48c14f84eba0b715197d673aff1dd22cc1007ca647e28483bbcc307" -dependencies = [ - "openssl-probe", - "rustls 0.16.0", - "schannel", - "security-framework", -] - [[package]] name = "rustversion" version = "1.0.14" @@ -2505,31 +2111,15 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" - -[[package]] -name = "schannel" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" -dependencies = [ - "lazy_static", - "windows-sys 0.36.1", -] +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "scratch" -version = "1.0.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sct" @@ -2541,33 +2131,6 @@ dependencies = [ "untrusted", ] -[[package]] -name = "security-framework" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df" -dependencies = [ - "core-foundation", - "core-foundation-sys 0.6.2", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" -dependencies = [ - "core-foundation-sys 0.6.2", -] - -[[package]] -name = "semver" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" - [[package]] name = "semver" version = "0.9.0" @@ -2577,12 +2140,6 @@ dependencies = [ "semver-parser", ] -[[package]] -name = "semver" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" - [[package]] name = "semver-parser" version = "0.7.0" @@ -2592,7 +2149,7 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "sensor_value" version = "0.1.0" -source = "git+https://github.com/dskleingeld/sensor_central.git?branch=main#4b5eb3209adf84aeb9fb0d983eac9c91324c50ab" +source = "git+https://github.com/dskleingeld/sensor_central.git?branch=main#59407b7944e4a196d29c7d127751b3c2b06f3fb3" dependencies = [ "bitspec", "serde", @@ -2600,39 +2157,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] -[[package]] -name = "serde-value" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a663f873dedc4eac1a559d4c6bc0d0b2c34dc5ac4702e105014b8281489e44f" -dependencies = [ - "ordered-float", - "serde", -] - [[package]] name = "serde_derive" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] name = "serde_json" -version = "1.0.89" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa 1.0.10", "ryu", @@ -2641,9 +2188,9 @@ dependencies = [ [[package]] name = "serde_path_to_error" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd154a240de39fdebcf5775d2675c204d7c13cf39a4c697be6493c8e734337c" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" dependencies = [ "itoa 1.0.10", "serde", @@ -2679,7 +2226,7 @@ version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ - "indexmap 1.9.2", + "indexmap 1.9.3", "ryu", "serde", "yaml-rust", @@ -2696,24 +2243,18 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] -[[package]] -name = "siphasher" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" - [[package]] name = "slab" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg 1.1.0", ] @@ -2725,12 +2266,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" dependencies = [ "crc32fast", - "crossbeam-epoch 0.9.13", - "crossbeam-utils 0.8.14", + "crossbeam-epoch 0.9.18", + "crossbeam-utils 0.8.19", "fs2", "fxhash", "libc", - "log 0.4.17", + "log", "parking_lot 0.11.2", ] @@ -2762,23 +2303,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" -dependencies = [ - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "spidev" -version = "0.3.0" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba01d3ef92a37e898fecac76cd3e1b33c999395e2d70787608d9678c4293e04" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ - "bitflags 0.3.3", "libc", - "nix 0.6.0", + "windows-sys 0.52.0", ] [[package]] @@ -2798,39 +2328,15 @@ dependencies = [ [[package]] name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "structopt" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.103", -] +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" [[package]] name = "syn" -version = "1.0.103" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", @@ -2839,9 +2345,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -2862,105 +2368,34 @@ checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn 1.0.109", "unicode-xid", ] -[[package]] -name = "sysfs_gpio" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24961a55846623d8e4f6cec38718945116fed8d6970336a7110710a07aa9b5d1" -dependencies = [ - "nix 0.14.1", -] - -[[package]] -name = "telegram-bot" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb29fb11ef40c839c1c6b4e9c2ec4f357f9f674491e9df5a8c94f8cc2005f860" -dependencies = [ - "bytes 0.5.6", - "futures 0.3.25", - "hyper 0.13.10", - "hyper-rustls 0.19.1", - "multipart", - "telegram-bot-raw", - "tokio 0.2.25", - "tracing", - "tracing-futures", -] - -[[package]] -name = "telegram-bot-raw" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add65834bee405351f092b18a4647cae05d1c40699570054eadc6d4035d9692c" -dependencies = [ - "bytes 0.5.6", - "serde", - "serde-value", - "serde_derive", - "serde_json", -] - -[[package]] -name = "tempfile" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" -dependencies = [ - "cfg-if 1.0.0", - "fastrand", - "libc", - "redox_syscall 0.2.16", - "remove_dir_all", - "winapi 0.3.9", -] - -[[package]] -name = "termcolor" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" -dependencies = [ - "winapi-util", -] - [[package]] name = "text_io" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f0c8eb2ad70c12a6a69508f499b3051c924f4b1cfeae85bfad96e6bc5bba46" -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "thiserror" -version = "1.0.37" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.37" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn 2.0.52", ] [[package]] @@ -2995,9 +2430,9 @@ dependencies = [ [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" @@ -3037,19 +2472,19 @@ dependencies = [ [[package]] name = "tokio" -version = "1.35.1" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", - "bytes 1.3.0", + "bytes 1.5.0", "libc", - "mio 0.8.10", + "mio 0.8.11", "num_cpus", "parking_lot 0.12.1", "pin-project-lite 0.2.13", "signal-hook-registry", - "socket2 0.5.5", + "socket2 0.5.6", "tokio-macros", "windows-sys 0.48.0", ] @@ -3093,7 +2528,7 @@ checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" dependencies = [ "bytes 0.4.12", "futures 0.1.31", - "log 0.4.17", + "log", ] [[package]] @@ -3104,7 +2539,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] @@ -3116,7 +2551,7 @@ dependencies = [ "crossbeam-utils 0.7.2", "futures 0.1.31", "lazy_static", - "log 0.4.17", + "log", "mio 0.6.23", "num_cpus", "parking_lot 0.9.0", @@ -3140,18 +2575,6 @@ dependencies = [ "webpki", ] -[[package]] -name = "tokio-rustls" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3068d891551949b37681724d6b73666787cc63fa8e255c812a41d2513aff9775" -dependencies = [ - "futures-core", - "rustls 0.16.0", - "tokio 0.2.25", - "webpki", -] - [[package]] name = "tokio-rustls" version = "0.14.1" @@ -3199,7 +2622,7 @@ dependencies = [ "crossbeam-utils 0.7.2", "futures 0.1.31", "lazy_static", - "log 0.4.17", + "log", "num_cpus", "slab", "tokio-executor", @@ -3226,7 +2649,7 @@ dependencies = [ "bytes 0.5.6", "futures-core", "futures-sink", - "log 0.4.17", + "log", "pin-project-lite 0.1.12", "tokio 0.2.25", ] @@ -3237,11 +2660,11 @@ version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ - "bytes 1.3.0", + "bytes 1.5.0", "futures-core", "futures-sink", "pin-project-lite 0.2.13", - "tokio 1.35.1", + "tokio 1.36.0", "tracing", ] @@ -3255,7 +2678,7 @@ dependencies = [ "futures-util", "pin-project", "pin-project-lite 0.2.13", - "tokio 1.35.1", + "tokio 1.36.0", "tower-layer", "tower-service", "tracing", @@ -3279,7 +2702,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "log 0.4.17", + "log", "pin-project-lite 0.2.13", "tracing-attributes", "tracing-core", @@ -3293,7 +2716,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] @@ -3333,7 +2756,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "log 0.4.17", + "log", "once_cell", "tracing-core", ] @@ -3358,9 +2781,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "try_from" @@ -3373,55 +2796,34 @@ dependencies = [ [[package]] name = "unicase" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -dependencies = [ - "version_check 0.1.5", -] - -[[package]] -name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ - "version_check 0.9.4", + "version_check", ] [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" - -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - [[package]] name = "unicode-xid" version = "0.2.4" @@ -3447,15 +2849,21 @@ dependencies = [ [[package]] name = "url" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna 0.3.0", - "percent-encoding 2.2.0", + "idna 0.5.0", + "percent-encoding 2.3.1", ] +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "uuid" version = "0.7.4" @@ -3471,30 +2879,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" - [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - [[package]] name = "want" version = "0.2.0" @@ -3502,17 +2892,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" dependencies = [ "futures 0.1.31", - "log 0.4.17", + "log", "try-lock", ] [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log 0.4.17", "try-lock", ] @@ -3530,9 +2919,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if 1.0.0", "serde", @@ -3542,24 +2931,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", - "log 0.4.17", + "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.103", + "syn 2.0.52", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.33" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -3569,9 +2958,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3579,28 +2968,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 1.0.103", + "syn 2.0.52", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.60" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -3662,15 +3051,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -3678,16 +3058,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-sys" -version = "0.36.1" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", + "windows-targets 0.52.4", ] [[package]] @@ -3696,7 +3072,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.4", ] [[package]] @@ -3705,15 +3090,30 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", + "windows_aarch64_gnullvm 0.48.5", "windows_aarch64_msvc 0.48.5", "windows_i686_gnu 0.48.5", "windows_i686_msvc 0.48.5", "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm", + "windows_x86_64_gnullvm 0.48.5", "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -3721,10 +3121,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" +name = "windows_aarch64_gnullvm" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" @@ -3733,10 +3133,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] -name = "windows_i686_gnu" -version = "0.36.1" +name = "windows_aarch64_msvc" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -3745,10 +3145,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] -name = "windows_i686_msvc" -version = "0.36.1" +name = "windows_i686_gnu" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -3757,10 +3157,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] -name = "windows_x86_64_gnu" -version = "0.36.1" +name = "windows_i686_msvc" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -3768,6 +3168,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -3775,10 +3181,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] -name = "windows_x86_64_msvc" -version = "0.36.1" +name = "windows_x86_64_gnullvm" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" @@ -3786,6 +3192,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + [[package]] name = "winreg" version = "0.6.2" diff --git a/Cargo.toml b/Cargo.toml index 54e19046..a15fcb1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,75 +1,9 @@ -[package] -name = "ha" -version = "0.1.0" -authors = ["David Kleingeld "] -edition = "2021" - -[features] -default = [] - -# Enable code that expects sensor hardware to be present. Will stop execution -# if hardware is not present, -# on by default for testing use cargo flag: --no-default-features -sensors_connected = [] -live_server = [] - -[dependencies] -futures = "0.3" -tokio = { version = "1", features = ["full"] } - -# actix-web = { version = "4", features = ["rustls"] } -# actix-net = "0.2" -# actix-identity = "0.2" -# actix-files = "0.2" -# actix-rt = "1" -# actix-service = "1.0" -# actix-web-httpauth = "0.4" -# rustls = "0.16" - -philipshue = { git = "https://github.com/dskleingeld/philipshue", branch = "master" } -# for local dev purpose we use below targets -# philipshue = { path = "../philipshue"} -# secure-ble = { path = "../home_sensors/ble/central"} - -structopt = "0.3" -serde = { version = "1.0", features = ["derive"] } -serde_yaml = "0.8" -bincode = "1.3" +[workspace] +resolver = "2" +members = ["crates/*"] -thiserror = "1.0" -fern = { version = "0.5.9", features = ["colored"] } - -sensor_value = { git = "https://github.com/dskleingeld/sensor_central.git", branch = "main" } -# nix = "0.17" -# ring = "0.16" -linux-embedded-hal = "0.2" -bme280 = "0.1" - -smallvec = "0.6" -chrono = { version = "0.4", features = ["serde"] } -chrono-tz = "0.5.3" -bytes = "0.4" -byteorder = "1.4" -num = { version = "0.2"} -hex = "0.4.3" - -crossbeam-channel = "0.3" - -sled = "0.34" -# pagecache = "0.17" -reqwest = {version = "0.10", default-features = false, features = ["rustls-tls"]} - -mpd = "0.1" -dirs = "2" -rand = "0.6" -retry = "1" - -telegram-bot = {version = "0.7", default-features = false, features = ["rustls"]} -serde_json = "1.0" -regex = "1" -futures-util = "0.3.30" -tracing = "0.1.40" -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -tracing-journald = "0.3.0" -log-panics = "2.1.0" -axum = "0.7.4" +[workspace.package] +rust-version = "1.70" +edition = "2021" +license = "GPLv3" +authors = ["David Kleingeld & Eva van Houten"] diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 1550c40a..00000000 --- a/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 David Kleingeld - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml new file mode 100644 index 00000000..8286eb8b --- /dev/null +++ b/crates/protocol/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "protocol" +version = "0.1.0" +rust-version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde = { version = "1.0.197", features = ["derive"] } diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs new file mode 100644 index 00000000..559e65cb --- /dev/null +++ b/crates/protocol/src/lib.rs @@ -0,0 +1,14 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub enum Button { +} + +impl Button { + fn encode(&self) -> Vec { + todo!() + } + fn dencode(bytes: impl AsRef<[u8]>) -> Result { + todo!() + } +} diff --git a/crates/system/Cargo.toml b/crates/system/Cargo.toml new file mode 100644 index 00000000..415ca4b6 --- /dev/null +++ b/crates/system/Cargo.toml @@ -0,0 +1,54 @@ +[package] +name = "ha" +version = "0.1.0" +authors = ["David Kleingeld "] +edition = "2021" + +[features] +default = [] + +# Enable code that expects sensor hardware to be present. Will stop execution +# if hardware is not present, +# on by default for testing use cargo flag: --no-default-features +sensors_connected = [] +live_server = [] + +[dependencies] +protocol = { path = "../protocol" } + +futures = "0.3" +tokio = { version = "1", features = ["full"] } +axum = "0.7.4" +axum-macros = "0.4.1" + +philipshue = { git = "https://github.com/dvdsk/philipshue", branch = "master" } + +serde = { version = "1.0", features = ["derive"] } +serde_yaml = "0.8" +bincode = "1.3" + +thiserror = "1.0" + +sensor_value = { git = "https://github.com/dskleingeld/sensor_central.git", branch = "main" } + +chrono = { version = "0.4", features = ["serde"] } +bytes = "0.4" +byteorder = "1.4" +num = { version = "0.2"} + +crossbeam-channel = "0.3" + +sled = "0.34" +# pagecache = "0.17" +reqwest = {version = "0.10", default-features = false, features = ["rustls-tls"]} + +mpd = "0.1" +rand = "0.6" +retry = "1" + +futures-util = "0.3.30" +tracing = "0.1.40" +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +tracing-journald = "0.3.0" +log-panics = "2.1.0" +clap = { version = "4.5.2", features = ["derive"] } diff --git a/deploy.sh b/crates/system/deploy.sh similarity index 100% rename from deploy.sh rename to crates/system/deploy.sh diff --git a/deploy_optimized.sh b/crates/system/deploy_optimized.sh similarity index 100% rename from deploy_optimized.sh rename to crates/system/deploy_optimized.sh diff --git a/src/controller/commands.rs b/crates/system/src/controller/commands.rs similarity index 100% rename from src/controller/commands.rs rename to crates/system/src/controller/commands.rs diff --git a/src/controller/environment/mod.rs b/crates/system/src/controller/environment/mod.rs similarity index 100% rename from src/controller/environment/mod.rs rename to crates/system/src/controller/environment/mod.rs diff --git a/src/controller/mod.rs b/crates/system/src/controller/mod.rs similarity index 98% rename from src/controller/mod.rs rename to crates/system/src/controller/mod.rs index ebdfe92a..7b8c6245 100644 --- a/src/controller/mod.rs +++ b/crates/system/src/controller/mod.rs @@ -73,7 +73,7 @@ fn saturating_duration_till(target: std::time::Instant) -> std::time::Duration { } pub fn start( - rx: crossbeam_channel::Receiver, + event_rx: crossbeam_channel::Receiver, mpd_status: MpdStatus, wakeup: WakeUp, ) -> Result, Error> { @@ -96,7 +96,7 @@ pub fn start( loop { //wait for next update or an incoming event let time_till_update = saturating_duration_till(system.next_update); - let event = match rx.recv_timeout(time_till_update) { + let event = match event_rx.recv_timeout(time_till_update) { Ok(event) => event, Err(Timeout) => { system.next_update = Instant::now() + system.update_period; diff --git a/src/controller/state/lightloop.rs b/crates/system/src/controller/state/lightloop.rs similarity index 100% rename from src/controller/state/lightloop.rs rename to crates/system/src/controller/state/lightloop.rs diff --git a/src/controller/state/mod.rs b/crates/system/src/controller/state/mod.rs similarity index 100% rename from src/controller/state/mod.rs rename to crates/system/src/controller/state/mod.rs diff --git a/src/controller/state/normal.rs b/crates/system/src/controller/state/normal.rs similarity index 100% rename from src/controller/state/normal.rs rename to crates/system/src/controller/state/normal.rs diff --git a/src/controller/state/off.rs b/crates/system/src/controller/state/off.rs similarity index 100% rename from src/controller/state/off.rs rename to crates/system/src/controller/state/off.rs diff --git a/src/controller/state/silent.rs b/crates/system/src/controller/state/silent.rs similarity index 100% rename from src/controller/state/silent.rs rename to crates/system/src/controller/state/silent.rs diff --git a/src/controller/state/sleep.rs b/crates/system/src/controller/state/sleep.rs similarity index 100% rename from src/controller/state/sleep.rs rename to crates/system/src/controller/state/sleep.rs diff --git a/src/controller/state/wakeup.rs b/crates/system/src/controller/state/wakeup.rs similarity index 100% rename from src/controller/state/wakeup.rs rename to crates/system/src/controller/state/wakeup.rs diff --git a/src/controller/system/computer.rs b/crates/system/src/controller/system/computer.rs similarity index 100% rename from src/controller/system/computer.rs rename to crates/system/src/controller/system/computer.rs diff --git a/src/controller/system/lamps/bridge_connect.rs b/crates/system/src/controller/system/lamps/bridge_connect.rs similarity index 100% rename from src/controller/system/lamps/bridge_connect.rs rename to crates/system/src/controller/system/lamps/bridge_connect.rs diff --git a/src/controller/system/lamps/eventually_consistent_bridge.rs b/crates/system/src/controller/system/lamps/eventually_consistent_bridge.rs similarity index 100% rename from src/controller/system/lamps/eventually_consistent_bridge.rs rename to crates/system/src/controller/system/lamps/eventually_consistent_bridge.rs diff --git a/src/controller/system/lamps/lamp.rs b/crates/system/src/controller/system/lamps/lamp.rs similarity index 100% rename from src/controller/system/lamps/lamp.rs rename to crates/system/src/controller/system/lamps/lamp.rs diff --git a/src/controller/system/lamps/mod.rs b/crates/system/src/controller/system/lamps/mod.rs similarity index 100% rename from src/controller/system/lamps/mod.rs rename to crates/system/src/controller/system/lamps/mod.rs diff --git a/src/controller/system/mod.rs b/crates/system/src/controller/system/mod.rs similarity index 100% rename from src/controller/system/mod.rs rename to crates/system/src/controller/system/mod.rs diff --git a/src/controller/system/mpd_control.rs b/crates/system/src/controller/system/mpd_control.rs similarity index 100% rename from src/controller/system/mpd_control.rs rename to crates/system/src/controller/system/mpd_control.rs diff --git a/src/errors.rs b/crates/system/src/errors.rs similarity index 100% rename from src/errors.rs rename to crates/system/src/errors.rs diff --git a/crates/system/src/input/api.rs b/crates/system/src/input/api.rs new file mode 100644 index 00000000..f78f8d23 --- /dev/null +++ b/crates/system/src/input/api.rs @@ -0,0 +1,86 @@ +use axum::body::Bytes; +use axum::extract::State as aState; +use axum::http::StatusCode; +use axum::routing::{get, post}; +use axum::Router; + +use crate::controller::Event; + +use super::jobs::WakeUp; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Could not bind to port {port} on 127.0.0.1, error: {err}")] + Binding { err: std::io::Error, port: u16 }, + #[error("Can not run server, io error: {0:?}")] + Serving(std::io::Error), +} + +/// sends back bincode serialized +async fn usually(aState(state): aState) -> Vec { + let usually = state.wakeup.usually().await; + let usually = bincode::serialize(&usually).expect("Should be serializable"); + usually +} + +/// sends back bincode serialized +async fn tomorrow(aState(state): aState) -> Vec { + let usually = state.wakeup.tomorrow().await; + let usually = bincode::serialize(&usually).expect("Should be serializable"); + usually +} + +async fn set_usually(aState(state): aState, body: Bytes) -> StatusCode { + let time: Option<(u8, u8)> = bincode::deserialize(&body[..]) + .map_err(|_| "Could not deserialize into time") + .unwrap(); + let _ignore = state.wakeup + .set_usually(time) + .await + .map_err(|_| "Could not save new alarm time") + .unwrap(); + + StatusCode::OK +} + +async fn set_tomorrow(aState(state): aState, body: Bytes) -> StatusCode { + let time: Option<(u8, u8)> = bincode::deserialize(&body[..]) + .map_err(|_| "Could not deserialize into time") + .unwrap(); + let _ignore = state.wakeup + .set_tomorrow(time) + .await + .map_err(|_| "Could not save new alarm time") + .unwrap(); + + StatusCode::OK +} + +async fn button(aState(state): aState) { + state.event_tx.send(todo!()).unwrap(); +} + +#[derive(Clone)] +pub struct State { + wakeup: WakeUp, + event_tx: crossbeam_channel::Sender, +} + +pub async fn setup( + wakeup: WakeUp, + event_tx: crossbeam_channel::Sender, + port: u16, +) -> Result<(), Error> { + let app = Router::new() + .route("/alarm/usually", get(usually).post(set_usually)) + .route("/alarm/tomorrow", get(tomorrow).post(set_tomorrow)) + .route("/event/button", post(button)) + .with_state(State{wakeup, event_tx}); + + // https is done at the loadbalancer + let listener = tokio::net::TcpListener::bind(format!("127.0.0.1:{port}")) + .await + .map_err(|err| Error::Binding { err, port })?; + tracing::debug!("listening on {}", listener.local_addr().unwrap()); + axum::serve(listener, app).await.map_err(Error::Serving) +} diff --git a/src/input/jobs.rs b/crates/system/src/input/jobs.rs similarity index 100% rename from src/input/jobs.rs rename to crates/system/src/input/jobs.rs diff --git a/src/input/jobs/wakeup.rs b/crates/system/src/input/jobs/wakeup.rs similarity index 93% rename from src/input/jobs/wakeup.rs rename to crates/system/src/input/jobs/wakeup.rs index 37b60b77..b71c6244 100644 --- a/src/input/jobs/wakeup.rs +++ b/crates/system/src/input/jobs/wakeup.rs @@ -3,7 +3,8 @@ use crate::controller::Event; use chrono::{DateTime, Local, Timelike, Utc}; use tokio::runtime::Runtime; use tracing::info; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; +use tokio::sync::Mutex; use std::time::Duration; // TODO FIXME multiple things left to do: @@ -27,24 +28,24 @@ impl WakeUp { let inner = Arc::new(Mutex::new(inner)); Ok(Self(inner)) } - pub fn tomorrow(&self) -> Option<(u8, u8)> { - self.0.lock().unwrap().tomorrow + pub async fn tomorrow(&self) -> Option<(u8, u8)> { + self.0.lock().await.tomorrow } - pub fn usually(&self) -> Option<(u8, u8)> { - self.0.lock().unwrap().usually + pub async fn usually(&self) -> Option<(u8, u8)> { + self.0.lock().await.usually } pub fn reset(&self) -> Result<(), Error> { - self.0.lock().unwrap().reset()?; + self.0.blocking_lock().reset()?; info!("alarm system reset correctly"); Ok(()) } pub async fn set_tomorrow(&self, time: Time) -> Result<(), Error> { - self.0.lock().unwrap().set_tomorrow(time).await?; + self.0.lock().await.set_tomorrow(time).await?; info!("alarm tomorrow set to: time"); Ok(()) } pub async fn set_usually(&self, time: Time) -> Result<(), Error> { - self.0.lock().unwrap().set_usually(time).await?; + self.0.lock().await.set_usually(time).await?; info!("alarm usually set to: time"); Ok(()) } diff --git a/src/input/mod.rs b/crates/system/src/input/mod.rs similarity index 100% rename from src/input/mod.rs rename to crates/system/src/input/mod.rs diff --git a/src/input/mpd_status.rs b/crates/system/src/input/mpd_status.rs similarity index 90% rename from src/input/mpd_status.rs rename to crates/system/src/input/mpd_status.rs index 963b5205..8cac7e25 100644 --- a/src/input/mpd_status.rs +++ b/crates/system/src/input/mpd_status.rs @@ -1,6 +1,7 @@ use crate::errors::Error; use crossbeam_channel::{Receiver, Sender}; use mpd::{idle::Idle, idle::Subsystem, Client}; +use std::net::{IpAddr, SocketAddr}; use std::sync::{Arc, RwLock}; use std::thread; @@ -50,8 +51,8 @@ impl MpdStatus { client.volume(status.volume).unwrap(); }*/ - pub fn start_updating() -> Result<(Self, thread::JoinHandle<()>, Sender<()>), Error> { - let mut client = mpd::Client::connect("127.0.0.1:6600")?; + pub fn start_updating(mpd_ip: IpAddr) -> Result<(Self, thread::JoinHandle<()>, Sender<()>), Error> { + let mut client = mpd::Client::connect(SocketAddr::new(mpd_ip, 6600))?; let status = client.status()?; let mpd_status = Self { diff --git a/src/input/web_api/commands.rs b/crates/system/src/input/web_api/commands.rs similarity index 100% rename from src/input/web_api/commands.rs rename to crates/system/src/input/web_api/commands.rs diff --git a/src/input/web_api/mod.rs b/crates/system/src/input/web_api/mod.rs similarity index 100% rename from src/input/web_api/mod.rs rename to crates/system/src/input/web_api/mod.rs diff --git a/src/input/web_api/music.rs b/crates/system/src/input/web_api/music.rs similarity index 100% rename from src/input/web_api/music.rs rename to crates/system/src/input/web_api/music.rs diff --git a/src/input/web_api/server/database.rs b/crates/system/src/input/web_api/server/database.rs similarity index 100% rename from src/input/web_api/server/database.rs rename to crates/system/src/input/web_api/server/database.rs diff --git a/src/input/web_api/server/login.rs b/crates/system/src/input/web_api/server/login.rs similarity index 100% rename from src/input/web_api/server/login.rs rename to crates/system/src/input/web_api/server/login.rs diff --git a/src/input/web_api/server/login_redirect.rs b/crates/system/src/input/web_api/server/login_redirect.rs similarity index 100% rename from src/input/web_api/server/login_redirect.rs rename to crates/system/src/input/web_api/server/login_redirect.rs diff --git a/src/input/web_api/server/mod.rs b/crates/system/src/input/web_api/server/mod.rs similarity index 100% rename from src/input/web_api/server/mod.rs rename to crates/system/src/input/web_api/server/mod.rs diff --git a/src/input/web_api/server/static_webpages/login.css b/crates/system/src/input/web_api/server/static_webpages/login.css similarity index 100% rename from src/input/web_api/server/static_webpages/login.css rename to crates/system/src/input/web_api/server/static_webpages/login.css diff --git a/src/input/web_api/server/static_webpages/login.html b/crates/system/src/input/web_api/server/static_webpages/login.html similarity index 100% rename from src/input/web_api/server/static_webpages/login.html rename to crates/system/src/input/web_api/server/static_webpages/login.html diff --git a/src/input/web_api/wakeup.rs b/crates/system/src/input/web_api/wakeup.rs similarity index 100% rename from src/input/web_api/wakeup.rs rename to crates/system/src/input/web_api/wakeup.rs diff --git a/src/main.rs b/crates/system/src/main.rs similarity index 64% rename from src/main.rs rename to crates/system/src/main.rs index 72409a57..90088dad 100644 --- a/src/main.rs +++ b/crates/system/src/main.rs @@ -1,5 +1,7 @@ +use std::net::IpAddr; + +use clap::Parser; use sled; -use structopt::StructOpt; use tracing::warn; mod controller; @@ -7,18 +9,26 @@ mod controller; mod errors; mod input; -#[derive(StructOpt)] -#[structopt(name = "homeautomation")] +#[derive(Parser)] +#[command(version, about, long_about=None)] struct Opt { /// secret url part on which sensor data is received - #[structopt(short = "h", long = "ha-key")] - ha_key: String, + #[clap(short, long)] + key: String, + + /// ip address for mpd server + #[clap(short, long)] + mpd_ip: IpAddr, + + /// http api listens on this port at 127.0.0.1 use + /// a loadbalancer/reverse proxy to get traffic to this + #[clap(short, long)] + port: u16, } #[tokio::main] async fn main() { - let opt = Opt::from_args(); - setup_tracing(); + let opt = Opt::parse(); let db = sled::Config::default() //651ms .path("database") @@ -27,21 +37,16 @@ async fn main() { .open() .unwrap(); - let (controller_tx, controller_rx) = crossbeam_channel::unbounded(); + let (event_tx, event_rx) = crossbeam_channel::unbounded(); - let (joblist, _waker_thread) = - input::jobs::Jobs::setup(controller_tx.clone(), db.clone()).unwrap(); + let (joblist, _waker_thread) = input::jobs::Jobs::setup(event_tx.clone(), db.clone()).unwrap(); let wakeup = input::jobs::WakeUp::setup(db.clone(), joblist.clone()).unwrap(); let (mpd_status, _mpd_watcher_thread, _updater_tx) = - input::MpdStatus::start_updating().unwrap(); + input::MpdStatus::start_updating(opt.mpd_ip).unwrap(); let _controller_thread = - controller::start(controller_rx, mpd_status.clone(), wakeup.clone()).unwrap(); - let _webserver = input::api::setup(wakeup.clone()).unwrap(); - - loop { - std::thread::park(); - } + controller::start(event_rx, mpd_status.clone(), wakeup.clone()).unwrap(); + let webserver = input::api::setup(wakeup.clone(), event_tx, opt.port).await; } pub fn setup_tracing() { diff --git a/web/add_song.html b/crates/system/web/add_song.html similarity index 100% rename from web/add_song.html rename to crates/system/web/add_song.html diff --git a/web/graph.html b/crates/system/web/graph.html similarity index 100% rename from web/graph.html rename to crates/system/web/graph.html diff --git a/web/graphDebug.html b/crates/system/web/graphDebug.html similarity index 100% rename from web/graphDebug.html rename to crates/system/web/graphDebug.html diff --git a/web/login.css b/crates/system/web/login.css similarity index 100% rename from web/login.css rename to crates/system/web/login.css diff --git a/web/login.html b/crates/system/web/login.html similarity index 100% rename from web/login.html rename to crates/system/web/login.html diff --git a/web/plot.js b/crates/system/web/plot.js similarity index 100% rename from web/plot.js rename to crates/system/web/plot.js diff --git a/web/plot_debug.js b/crates/system/web/plot_debug.js similarity index 100% rename from web/plot_debug.js rename to crates/system/web/plot_debug.js diff --git a/web/set_alarm.html b/crates/system/web/set_alarm.html similarity index 100% rename from web/set_alarm.html rename to crates/system/web/set_alarm.html diff --git a/web/test.html b/crates/system/web/test.html similarity index 100% rename from web/test.html rename to crates/system/web/test.html diff --git a/web/test_decode.html b/crates/system/web/test_decode.html similarity index 100% rename from web/test_decode.html rename to crates/system/web/test_decode.html diff --git a/web/test_graph_updates.html b/crates/system/web/test_graph_updates.html similarity index 100% rename from web/test_graph_updates.html rename to crates/system/web/test_graph_updates.html diff --git a/web/test_ws_interface.html b/crates/system/web/test_ws_interface.html similarity index 100% rename from web/test_ws_interface.html rename to crates/system/web/test_ws_interface.html diff --git a/web/websocket.html b/crates/system/web/websocket.html similarity index 100% rename from web/websocket.html rename to crates/system/web/websocket.html diff --git a/web/websocket_getData.html b/crates/system/web/websocket_getData.html similarity index 100% rename from web/websocket_getData.html rename to crates/system/web/websocket_getData.html diff --git a/web/websocket_getData2.html b/crates/system/web/websocket_getData2.html similarity index 100% rename from web/websocket_getData2.html rename to crates/system/web/websocket_getData2.html diff --git a/deny.toml b/deny.toml deleted file mode 100644 index acfbfb39..00000000 --- a/deny.toml +++ /dev/null @@ -1,196 +0,0 @@ -# This template contains all of the possible sections and their default values - -# Note that all fields that take a lint level have these possible values: -# * deny - An error will be produced and the check will fail -# * warn - A warning will be produced, but the check will not fail -# * allow - No warning or error will be produced, though in some cases a note -# will be - -# The values provided in this template are the default values that will be used -# when any section or field is not specified in your own configuration - -# If 1 or more target triples (and optionally, target_features) are specified, -# only the specified targets will be checked when running `cargo deny check`. -# This means, if a particular package is only ever used as a target specific -# dependency, such as, for example, the `nix` crate only being used via the -# `target_family = "unix"` configuration, that only having windows targets in -# this list would mean the nix crate, as well as any of its exclusive -# dependencies not shared by any other crates, would be ignored, as the target -# list here is effectively saying which targets you are building for. -targets = [ - # The triple can be any string, but only the target triples built in to - # rustc (as of 1.40) can be checked against actual config expressions - #{ triple = "x86_64-unknown-linux-musl" }, - # You can also specify which target_features you promise are enabled for a - # particular target. target_features are currently not validated against - # the actual valid features supported by the target architecture. - #{ triple = "wasm32-unknown-unknown", features = ["atomics"] }, -] - -# This section is considered when running `cargo deny check advisories` -# More documentation for the advisories section can be found here: -# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html -[advisories] -# The path where the advisory database is cloned/fetched into -db-path = "~/.cargo/advisory-db" -# The url of the advisory database to use -db-url = "https://github.com/rustsec/advisory-db" -# The lint level for security vulnerabilities -vulnerability = "deny" -# The lint level for unmaintained crates -unmaintained = "warn" -# The lint level for crates that have been yanked from their source registry -yanked = "warn" -# The lint level for crates with security notices. Note that as of -# 2019-12-17 there are no security notice advisories in -# https://github.com/rustsec/advisory-db -notice = "warn" -# A list of advisory IDs to ignore. Note that ignored advisories will still -# output a note when they are encountered. -ignore = [ - #"RUSTSEC-0000-0000", -] -# Threshold for security vulnerabilities, any vulnerability with a CVSS score -# lower than the range specified will be ignored. Note that ignored advisories -# will still output a note when they are encountered. -# * None - CVSS Score 0.0 -# * Low - CVSS Score 0.1 - 3.9 -# * Medium - CVSS Score 4.0 - 6.9 -# * High - CVSS Score 7.0 - 8.9 -# * Critical - CVSS Score 9.0 - 10.0 -#severity-threshold = - -# This section is considered when running `cargo deny check licenses` -# More documentation for the licenses section can be found here: -# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html -[licenses] -# The lint level for crates which do not have a detectable license -unlicensed = "deny" -# List of explictly allowed licenses -# See https://spdx.org/licenses/ for list of possible licenses -# [possible values: any SPDX 3.7 short identifier (+ optional exception)]. -allow = [ - "CC0-1.0", - "MIT", - "Apache-2.0", - "Apache-2.0 WITH LLVM-exception", - "BSD-2-Clause", #similar to MIT - "BSD-3-Clause", - "Zlib", - #"ring", - "MPL-2.0", #do not change mpl licenced source or you have to change your licence to MPL - "ISC", -] -# List of explictly disallowed licenses -# See https://spdx.org/licenses/ for list of possible licenses -# [possible values: any SPDX 3.7 short identifier (+ optional exception)]. -deny = [ - #"Nokia", -] -# Lint level for licenses considered copyleft -copyleft = "warn" -# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses -# * both - The license will be approved if it is both OSI-approved *AND* FSF -# * either - The license will be approved if it is either OSI-approved *OR* FSF -# * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF -# * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved -# * neither - This predicate is ignored and the default lint level is used -allow-osi-fsf-free = "neither" -# Lint level used when no other predicates are matched -# 1. License isn't in the allow or deny lists -# 2. License isn't copyleft -# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither" -default = "deny" -# The confidence threshold for detecting a license from license text. -# The higher the value, the more closely the license text must be to the -# canonical license text of a valid SPDX license file. -# [possible values: any between 0.0 and 1.0]. -confidence-threshold = 0.8 -# Allow 1 or more licenses on a per-crate basis, so that particular licenses -# aren't accepted for every possible crate as with the normal allow list -exceptions = [ - # Each entry is the crate and version constraint, and its specific allow - # list - #{ allow = ["Zlib"], name = "adler32", version = "*" }, -] - -# Some crates don't have (easily) machine readable licensing information, -# adding a clarification entry for it allows you to manually specify the -# licensing information -#[[licenses.clarify]] -# The name of the crate the clarification applies to -#name = "ring" -# THe optional version constraint for the crate -#version = "*" -# The SPDX expression for the license requirements of the crate -#expression = "MIT AND ISC AND OpenSSL" -# One or more files in the crate's source used as the "source of truth" for -# the license expression. If the contents match, the clarification will be used -# when running the license check, otherwise the clarification will be ignored -# and the crate will be checked normally, which may produce warnings or errors -# depending on the rest of your configuration -#license-files = [ - # Each entry is a crate relative path, and the (opaque) hash of its contents - #{ path = "LICENSE", hash = 0xbd0eed23 } -#] - -[licenses.private] -# If true, ignores workspace crates that aren't published, or are only -# published to private registries -ignore = false -# One or more private registries that you might publish crates to, if a crate -# is only published to private registries, and ignore is true, the crate will -# not have its license(s) checked -registries = [ - #"https://sekretz.com/registry -] - -# This section is considered when running `cargo deny check bans`. -# More documentation about the 'bans' section can be found here: -# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html -[bans] -# Lint level for when multiple versions of the same crate are detected -multiple-versions = "warn" -# The graph highlighting used when creating dotgraphs for crates -# with multiple versions -# * lowest-version - The path to the lowest versioned duplicate is highlighted -# * simplest-path - The path to the version with the fewest edges is highlighted -# * all - Both lowest-version and simplest-path are used -highlight = "all" -# List of crates that are allowed. Use with care! -allow = [ - #{ name = "ansi_term", version = "=0.11.0" }, -] -# List of crates to deny -deny = [ - # Each entry the name of a crate and a version range. If version is - # not specified, all versions will be matched. - #{ name = "ansi_term", version = "=0.11.0" }, -] -# Certain crates/versions that will be skipped when doing duplicate detection. -skip = [ - #{ name = "ansi_term", version = "=0.11.0" }, -] -# Similarly to `skip` allows you to skip certain crates during duplicate -# detection. Unlike skip, it also includes the entire tree of transitive -# dependencies starting at the specified crate, up to a certain depth, which is -# by default infinite -skip-tree = [ - #{ name = "ansi_term", version = "=0.11.0", depth = 20 }, -] - -# This section is considered when running `cargo deny check sources`. -# More documentation about the 'sources' section can be found here: -# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html -[sources] -# Lint level for what to happen when a crate from a crate registry that is not -# in the allow list is encountered -unknown-registry = "warn" -# Lint level for what to happen when a crate from a git repository that is not -# in the allow list is encountered -unknown-git = "warn" -# List of URLs for allowed crate registries. Defaults to the crates.io index -# if not specified. If it is specified but empty, no registries are allowed. -allow-registry = ["https://github.com/rust-lang/crates.io-index"] -# List of URLs for allowed Git repositories -allow-git = [] diff --git a/src/input/api.rs b/src/input/api.rs deleted file mode 100644 index bb9d92f8..00000000 --- a/src/input/api.rs +++ /dev/null @@ -1,26 +0,0 @@ -use axum::Router; -use axum::body::Bytes; -use axum::routing::{get, post}; - -use crate::errors::Error; - -use super::jobs::WakeUp; - -async fn usually(wakeup: WakeUp) -> Bytes { -} - -async fn setup(wakeup: WakeUp) -> Result<(), Error> { - let app = Router::new() - .route("/alarm/usually", get(usually)) - // .route("/alarm/tomorrow", get(tomorrow)) - // .route("/alarm/usually", post(usually)) - // .route("/alarm/tomorrow", post(tomorrow)) - .with_state(wakeup); - - // https is done at the loadbalancer - let listener = tokio::net::TcpListener::bind("127.0.0.1:80") - .await - .unwrap(); - tracing::debug!("listening on {}", listener.local_addr().unwrap()); - axum::serve(listener, app).await.unwrap(); -} From 2c48ecb6bc8e1af80d6c9acf0e7da7260dce6150 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 12 Mar 2024 02:15:04 +0100 Subject: [PATCH 082/687] update all deps to latest versions --- Cargo.lock | 457 +++++++++--------- Cargo.toml | 1 + crates/system/Cargo.toml | 23 +- .../src/controller/system/mpd_control.rs | 2 +- 4 files changed, 254 insertions(+), 229 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4016c6e7..4734a8dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -135,7 +135,7 @@ dependencies = [ "memchr", "mime", "percent-encoding 2.3.1", - "pin-project-lite 0.2.13", + "pin-project-lite", "rustversion", "serde", "serde_json", @@ -162,7 +162,7 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "mime", - "pin-project-lite 0.2.13", + "pin-project-lite", "rustversion", "sync_wrapper", "tower-layer", @@ -208,15 +208,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.12.3" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "bincode" @@ -233,6 +227,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + [[package]] name = "bitspec" version = "1.0.0" @@ -243,7 +243,7 @@ dependencies = [ "rand 0.5.6", "serde", "serde_derive", - "serde_yaml", + "serde_yaml 0.8.26", "text_io", ] @@ -276,12 +276,6 @@ dependencies = [ "iovec", ] -[[package]] -name = "bytes" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" - [[package]] name = "bytes" version = "1.5.0" @@ -367,7 +361,7 @@ version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -404,6 +398,16 @@ dependencies = [ "url 1.7.2", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.6" @@ -421,11 +425,11 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.3.9" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" dependencies = [ - "crossbeam-utils 0.6.6", + "crossbeam-utils 0.8.19", ] [[package]] @@ -474,16 +478,6 @@ dependencies = [ "maybe-uninit", ] -[[package]] -name = "crossbeam-utils" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" -dependencies = [ - "cfg-if 0.1.10", - "lazy_static", -] - [[package]] name = "crossbeam-utils" version = "0.7.2" @@ -507,7 +501,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d3686f5fa27dbc1d76c751300376e167c5a43387f44bb451fd1c24776e49113" dependencies = [ - "sct", + "sct 0.6.1", ] [[package]] @@ -615,7 +609,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" dependencies = [ - "bitflags", + "bitflags 1.3.2", "fuchsia-zircon-sys", ] @@ -725,7 +719,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.13", + "pin-project-lite", "pin-utils", "slab", ] @@ -776,22 +770,21 @@ dependencies = [ [[package]] name = "h2" -version = "0.2.7" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" dependencies = [ - "bytes 0.5.6", + "bytes 1.5.0", "fnv", "futures-core", "futures-sink", "futures-util", "http 0.2.12", - "indexmap 1.9.3", + "indexmap 2.2.5", "slab", - "tokio 0.2.25", - "tokio-util 0.3.1", + "tokio 1.36.0", + "tokio-util", "tracing", - "tracing-futures", ] [[package]] @@ -809,7 +802,7 @@ dependencies = [ "indexmap 2.2.5", "slab", "tokio 1.36.0", - "tokio-util 0.7.10", + "tokio-util", "tracing", ] @@ -821,7 +814,7 @@ dependencies = [ "axum-macros", "bincode", "byteorder", - "bytes 0.4.12", + "bytes 1.5.0", "chrono", "clap", "crossbeam-channel", @@ -829,15 +822,15 @@ dependencies = [ "futures-util", "log-panics", "mpd", - "num 0.2.1", + "num 0.4.1", "philipshue", "protocol", - "rand 0.6.5", - "reqwest 0.10.10", + "rand 0.8.5", + "reqwest 0.11.25", "retry", "sensor_value", "serde", - "serde_yaml", + "serde_yaml 0.9.32", "sled", "thiserror", "tokio 1.36.0", @@ -917,12 +910,13 @@ dependencies = [ [[package]] name = "http-body" -version = "0.3.1" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ - "bytes 0.5.6", + "bytes 1.5.0", "http 0.2.12", + "pin-project-lite", ] [[package]] @@ -945,7 +939,7 @@ dependencies = [ "futures-core", "http 1.1.0", "http-body 1.0.0", - "pin-project-lite 0.2.13", + "pin-project-lite", ] [[package]] @@ -954,12 +948,6 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" -[[package]] -name = "httpdate" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" - [[package]] name = "httpdate" version = "1.0.3" @@ -998,23 +986,23 @@ dependencies = [ [[package]] name = "hyper" -version = "0.13.10" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a6f157065790a3ed2f88679250419b5cdd96e714a0d65f7797fd337186e96bb" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ - "bytes 0.5.6", + "bytes 1.5.0", "futures-channel", "futures-core", "futures-util", - "h2 0.2.7", + "h2 0.3.24", "http 0.2.12", - "http-body 0.3.1", + "http-body 0.4.6", "httparse", - "httpdate 0.3.2", - "itoa 0.4.8", - "pin-project", - "socket2 0.3.19", - "tokio 0.2.25", + "httpdate", + "itoa 1.0.10", + "pin-project-lite", + "socket2", + "tokio 1.36.0", "tower-service", "tracing", "want 0.3.1", @@ -1033,9 +1021,9 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "httparse", - "httpdate 1.0.3", + "httpdate", "itoa 1.0.10", - "pin-project-lite 0.2.13", + "pin-project-lite", "smallvec 1.13.1", "tokio 1.36.0", ] @@ -1059,18 +1047,16 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37743cc83e8ee85eacfce90f2f4102030d9ff0a95244098d781e9bee4a90abb6" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ - "bytes 0.5.6", "futures-util", - "hyper 0.13.10", - "log", - "rustls 0.18.1", - "tokio 0.2.25", - "tokio-rustls 0.14.1", - "webpki", + "http 0.2.12", + "hyper 0.14.28", + "rustls 0.21.10", + "tokio 1.36.0", + "tokio-rustls 0.24.1", ] [[package]] @@ -1084,8 +1070,8 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "hyper 1.2.0", - "pin-project-lite 0.2.13", - "socket2 0.5.6", + "pin-project-lite", + "socket2", "tokio 1.36.0", ] @@ -1412,37 +1398,37 @@ dependencies = [ [[package]] name = "num" -version = "0.2.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" +checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" dependencies = [ - "num-bigint 0.2.6", - "num-complex 0.2.4", + "num-bigint 0.3.3", + "num-complex 0.3.1", "num-integer", "num-iter", - "num-rational 0.2.4", + "num-rational 0.3.2", "num-traits", ] [[package]] name = "num" -version = "0.3.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" dependencies = [ - "num-bigint 0.3.3", - "num-complex 0.3.1", + "num-bigint 0.4.4", + "num-complex 0.4.5", "num-integer", "num-iter", - "num-rational 0.3.2", + "num-rational 0.4.1", "num-traits", ] [[package]] name = "num-bigint" -version = "0.2.6" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" dependencies = [ "autocfg 1.1.0", "num-integer", @@ -1451,9 +1437,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.3.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ "autocfg 1.1.0", "num-integer", @@ -1462,19 +1448,18 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.2.4" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" dependencies = [ - "autocfg 1.1.0", "num-traits", ] [[package]] name = "num-complex" -version = "0.3.1" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" dependencies = [ "num-traits", ] @@ -1501,24 +1486,24 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.2.4" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" dependencies = [ "autocfg 1.1.0", - "num-bigint 0.2.6", + "num-bigint 0.3.3", "num-integer", "num-traits", ] [[package]] name = "num-rational" -version = "0.3.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg 1.1.0", - "num-bigint 0.3.3", + "num-bigint 0.4.4", "num-integer", "num-traits", ] @@ -1681,12 +1666,6 @@ dependencies = [ "syn 2.0.52", ] -[[package]] -name = "pin-project-lite" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" - [[package]] name = "pin-project-lite" version = "0.2.13" @@ -1910,7 +1889,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1919,7 +1898,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -2004,45 +1983,50 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.10.10" +version = "0.11.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0718f81a8e14c4dbb3b34cf23dc6aaf9ab8a0dfec160c534b3dbca1aaa21f47c" +checksum = "0eea5a9eb898d3783f17c6407670e3592fd174cb81a10e51d4c37f49450b9946" dependencies = [ - "base64 0.13.1", - "bytes 0.5.6", + "base64 0.21.7", + "bytes 1.5.0", "encoding_rs", "futures-core", "futures-util", + "h2 0.3.24", "http 0.2.12", - "http-body 0.3.1", - "hyper 0.13.10", - "hyper-rustls 0.21.0", + "http-body 0.4.6", + "hyper 0.14.28", + "hyper-rustls 0.24.2", "ipnet", "js-sys", - "lazy_static", "log", "mime", - "mime_guess", + "once_cell", "percent-encoding 2.3.1", - "pin-project-lite 0.2.13", - "rustls 0.18.1", + "pin-project-lite", + "rustls 0.21.10", + "rustls-pemfile", "serde", + "serde_json", "serde_urlencoded 0.7.1", - "tokio 0.2.25", - "tokio-rustls 0.14.1", + "sync_wrapper", + "system-configuration", + "tokio 1.36.0", + "tokio-rustls 0.24.1", + "tower-service", "url 2.5.0", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.20.0", - "winreg 0.7.0", + "webpki-roots 0.25.4", + "winreg 0.50.0", ] [[package]] name = "retry" -version = "1.3.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac95c60a949a63fd2822f4964939662d8f2c16c4fa0624fd954bc6e703b9a3f6" +checksum = "9166d72162de3575f950507683fac47e30f6f2c3836b71b7fbc61aa517c9c5f4" dependencies = [ "rand 0.8.5", ] @@ -2056,12 +2040,27 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", - "untrusted", + "spin 0.5.2", + "untrusted 0.7.1", "web-sys", "winapi 0.3.9", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if 1.0.0", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -2085,22 +2084,40 @@ checksum = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" dependencies = [ "base64 0.10.1", "log", - "ring", - "sct", + "ring 0.16.20", + "sct 0.6.1", "webpki", ] [[package]] name = "rustls" -version = "0.18.1" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ - "base64 0.12.3", "log", - "ring", - "sct", - "webpki", + "ring 0.17.8", + "rustls-webpki", + "sct 0.7.1", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] @@ -2127,8 +2144,18 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", +] + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] @@ -2149,7 +2176,7 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "sensor_value" version = "0.1.0" -source = "git+https://github.com/dskleingeld/sensor_central.git?branch=main#59407b7944e4a196d29c7d127751b3c2b06f3fb3" +source = "git+https://github.com/dvdsk/sensor_central.git?branch=main#59407b7944e4a196d29c7d127751b3c2b06f3fb3" dependencies = [ "bitspec", "serde", @@ -2232,6 +2259,19 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "serde_yaml" +version = "0.9.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" +dependencies = [ + "indexmap 2.2.5", + "itoa 1.0.10", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -2290,17 +2330,6 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" -[[package]] -name = "socket2" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "winapi 0.3.9", -] - [[package]] name = "socket2" version = "0.5.6" @@ -2317,6 +2346,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "string" version = "0.2.1" @@ -2372,6 +2407,27 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "system-configuration" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bc6ee10a9b4fcf576e9b0819d95ec16f4d2c02d39fd83ac1c8789785c4a42" +dependencies = [ + "bitflags 2.4.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "text_io" version = "0.1.12" @@ -2453,23 +2509,6 @@ dependencies = [ "tokio-timer", ] -[[package]] -name = "tokio" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092" -dependencies = [ - "bytes 0.5.6", - "fnv", - "futures-core", - "iovec", - "lazy_static", - "memchr", - "mio 0.6.23", - "pin-project-lite 0.1.12", - "slab", -] - [[package]] name = "tokio" version = "1.36.0" @@ -2482,9 +2521,9 @@ dependencies = [ "mio 0.8.11", "num_cpus", "parking_lot 0.12.1", - "pin-project-lite 0.2.13", + "pin-project-lite", "signal-hook-registry", - "socket2 0.5.6", + "socket2", "tokio-macros", "windows-sys 0.48.0", ] @@ -2577,14 +2616,12 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.14.1" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12831b255bcfa39dc0436b01e19fea231a37db570686c06ee72c423479f889a" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "futures-core", - "rustls 0.18.1", - "tokio 0.2.25", - "webpki", + "rustls 0.21.10", + "tokio 1.36.0", ] [[package]] @@ -2640,20 +2677,6 @@ dependencies = [ "tokio-executor", ] -[[package]] -name = "tokio-util" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" -dependencies = [ - "bytes 0.5.6", - "futures-core", - "futures-sink", - "log", - "pin-project-lite 0.1.12", - "tokio 0.2.25", -] - [[package]] name = "tokio-util" version = "0.7.10" @@ -2663,7 +2686,7 @@ dependencies = [ "bytes 1.5.0", "futures-core", "futures-sink", - "pin-project-lite 0.2.13", + "pin-project-lite", "tokio 1.36.0", "tracing", ] @@ -2677,7 +2700,7 @@ dependencies = [ "futures-core", "futures-util", "pin-project", - "pin-project-lite 0.2.13", + "pin-project-lite", "tokio 1.36.0", "tower-layer", "tower-service", @@ -2703,7 +2726,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "log", - "pin-project-lite 0.2.13", + "pin-project-lite", "tracing-attributes", "tracing-core", ] @@ -2729,16 +2752,6 @@ dependencies = [ "valuable", ] -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", -] - [[package]] name = "tracing-journald" version = "0.3.0" @@ -2830,12 +2843,24 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "unsafe-libyaml" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" + [[package]] name = "untrusted" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "1.7.2" @@ -2924,8 +2949,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if 1.0.0", - "serde", - "serde_json", "wasm-bindgen-macro", ] @@ -3001,8 +3024,8 @@ version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", ] [[package]] @@ -3016,12 +3039,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.20.0" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f20dea7535251981a9670857150d571846545088359b28e4951d350bdaf179f" -dependencies = [ - "webpki", -] +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "winapi" @@ -3209,11 +3229,12 @@ dependencies = [ [[package]] name = "winreg" -version = "0.7.0" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "winapi 0.3.9", + "cfg-if 1.0.0", + "windows-sys 0.48.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index a15fcb1d..e01ff38d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] resolver = "2" members = ["crates/*"] +rust-version = "1.76" [workspace.package] rust-version = "1.70" diff --git a/crates/system/Cargo.toml b/crates/system/Cargo.toml index 415ca4b6..8f5e1e77 100644 --- a/crates/system/Cargo.toml +++ b/crates/system/Cargo.toml @@ -1,8 +1,10 @@ [package] name = "ha" version = "0.1.0" -authors = ["David Kleingeld "] -edition = "2021" +rust-version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true [features] default = [] @@ -24,27 +26,28 @@ axum-macros = "0.4.1" philipshue = { git = "https://github.com/dvdsk/philipshue", branch = "master" } serde = { version = "1.0", features = ["derive"] } -serde_yaml = "0.8" +serde_yaml = "0.9" bincode = "1.3" thiserror = "1.0" -sensor_value = { git = "https://github.com/dskleingeld/sensor_central.git", branch = "main" } +# todo deprecate in favor of protocol lib +sensor_value = { git = "https://github.com/dvdsk/sensor_central.git", branch = "main" } chrono = { version = "0.4", features = ["serde"] } -bytes = "0.4" +bytes = "1.5" byteorder = "1.4" -num = { version = "0.2"} +num = { version = "0.4"} -crossbeam-channel = "0.3" +crossbeam-channel = "0.5" sled = "0.34" # pagecache = "0.17" -reqwest = {version = "0.10", default-features = false, features = ["rustls-tls"]} +reqwest = {version = "0.11", default-features = false, features = ["rustls-tls"]} mpd = "0.1" -rand = "0.6" -retry = "1" +rand = "0.8" +retry = "2" futures-util = "0.3.30" tracing = "0.1.40" diff --git a/crates/system/src/controller/system/mpd_control.rs b/crates/system/src/controller/system/mpd_control.rs index 8289f26b..e5294d06 100644 --- a/crates/system/src/controller/system/mpd_control.rs +++ b/crates/system/src/controller/system/mpd_control.rs @@ -32,7 +32,7 @@ pub fn add_from_playlist( let mut time = Duration::from_secs(0); //add random songs until the playtime is larger then the minimum while time < minimal_play_time && songs.len() > 1 { - let idx = rng.gen_range(0, songs.len() - 1); + let idx = rng.gen_range(0..(songs.len() - 1)); let song = songs.remove(idx); if let Some(duration) = song.duration { if time + duration < maximal_play_time { From c250d2f173dae6e97d64222bf4426e871a267a60 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 26 Apr 2024 11:01:50 +0200 Subject: [PATCH 083/687] reorganises control system --- Cargo.lock | 382 ++++++++++++------ crates/{system => brain}/Cargo.toml | 6 +- crates/{system => brain}/deploy.sh | 0 crates/{system => brain}/deploy_optimized.sh | 0 .../src/controller/environment/mod.rs | 5 +- crates/brain/src/controller/mod.rs | 45 +++ crates/brain/src/controller/rooms.rs | 1 + .../src/controller/rooms/large_bedroom.rs | 102 +++++ crates/{system => brain}/src/errors.rs | 4 +- crates/{system => brain}/src/input/api.rs | 27 +- crates/{system => brain}/src/input/jobs.rs | 36 +- .../src/input/jobs/wakeup.rs | 2 +- crates/{system => brain}/src/input/mod.rs | 0 .../{system => brain}/src/input/mpd_status.rs | 0 .../src/input/web_api/commands.rs | 0 .../src/input/web_api/mod.rs | 0 .../src/input/web_api/music.rs | 0 .../src/input/web_api/server/database.rs | 0 .../src/input/web_api/server/login.rs | 0 .../input/web_api/server/login_redirect.rs | 0 .../src/input/web_api/server/mod.rs | 0 .../web_api/server/static_webpages/login.css | 0 .../web_api/server/static_webpages/login.html | 0 .../src/input/web_api/wakeup.rs | 0 crates/{system => brain}/src/main.rs | 28 +- crates/brain/src/system.rs | 24 ++ .../src}/system/computer.rs | 0 .../src}/system/lamps/bridge_connect.rs | 0 .../lamps/eventually_consistent_bridge.rs | 68 +++- .../src}/system/lamps/lamp.rs | 0 .../src}/system/lamps/mod.rs | 20 +- .../src}/system/mpd_control.rs | 4 + crates/{system => brain}/web/add_song.html | 0 crates/{system => brain}/web/graph.html | 0 crates/{system => brain}/web/graphDebug.html | 0 crates/{system => brain}/web/login.css | 0 crates/{system => brain}/web/login.html | 0 crates/{system => brain}/web/plot.js | 0 crates/{system => brain}/web/plot_debug.js | 0 crates/{system => brain}/web/set_alarm.html | 4 +- crates/{system => brain}/web/test.html | 0 crates/{system => brain}/web/test_decode.html | 0 .../web/test_graph_updates.html | 0 .../web/test_ws_interface.html | 0 crates/{system => brain}/web/websocket.html | 0 .../web/websocket_getData.html | 0 .../web/websocket_getData2.html | 0 crates/protocol/Cargo.toml | 9 +- crates/protocol/src/large_bedroom.rs | 15 + crates/protocol/src/lib.rs | 170 +++++++- crates/system/src/controller/commands.rs | 90 ----- crates/system/src/controller/mod.rs | 245 ----------- .../system/src/controller/state/lightloop.rs | 49 --- crates/system/src/controller/state/mod.rs | 38 -- crates/system/src/controller/state/normal.rs | 59 --- crates/system/src/controller/state/off.rs | 34 -- crates/system/src/controller/state/silent.rs | 47 --- crates/system/src/controller/state/sleep.rs | 57 --- crates/system/src/controller/state/wakeup.rs | 151 ------- crates/system/src/controller/system/mod.rs | 3 - 60 files changed, 758 insertions(+), 967 deletions(-) rename crates/{system => brain}/Cargo.toml (87%) rename crates/{system => brain}/deploy.sh (100%) rename crates/{system => brain}/deploy_optimized.sh (100%) rename crates/{system => brain}/src/controller/environment/mod.rs (83%) create mode 100644 crates/brain/src/controller/mod.rs create mode 100644 crates/brain/src/controller/rooms.rs create mode 100644 crates/brain/src/controller/rooms/large_bedroom.rs rename crates/{system => brain}/src/errors.rs (80%) rename crates/{system => brain}/src/input/api.rs (78%) rename crates/{system => brain}/src/input/jobs.rs (91%) rename crates/{system => brain}/src/input/jobs/wakeup.rs (98%) rename crates/{system => brain}/src/input/mod.rs (100%) rename crates/{system => brain}/src/input/mpd_status.rs (100%) rename crates/{system => brain}/src/input/web_api/commands.rs (100%) rename crates/{system => brain}/src/input/web_api/mod.rs (100%) rename crates/{system => brain}/src/input/web_api/music.rs (100%) rename crates/{system => brain}/src/input/web_api/server/database.rs (100%) rename crates/{system => brain}/src/input/web_api/server/login.rs (100%) rename crates/{system => brain}/src/input/web_api/server/login_redirect.rs (100%) rename crates/{system => brain}/src/input/web_api/server/mod.rs (100%) rename crates/{system => brain}/src/input/web_api/server/static_webpages/login.css (100%) rename crates/{system => brain}/src/input/web_api/server/static_webpages/login.html (100%) rename crates/{system => brain}/src/input/web_api/wakeup.rs (100%) rename crates/{system => brain}/src/main.rs (69%) create mode 100644 crates/brain/src/system.rs rename crates/{system/src/controller => brain/src}/system/computer.rs (100%) rename crates/{system/src/controller => brain/src}/system/lamps/bridge_connect.rs (100%) rename crates/{system/src/controller => brain/src}/system/lamps/eventually_consistent_bridge.rs (68%) rename crates/{system/src/controller => brain/src}/system/lamps/lamp.rs (100%) rename crates/{system/src/controller => brain/src}/system/lamps/mod.rs (88%) rename crates/{system/src/controller => brain/src}/system/mpd_control.rs (97%) rename crates/{system => brain}/web/add_song.html (100%) rename crates/{system => brain}/web/graph.html (100%) rename crates/{system => brain}/web/graphDebug.html (100%) rename crates/{system => brain}/web/login.css (100%) rename crates/{system => brain}/web/login.html (100%) rename crates/{system => brain}/web/plot.js (100%) rename crates/{system => brain}/web/plot_debug.js (100%) rename crates/{system => brain}/web/set_alarm.html (98%) rename crates/{system => brain}/web/test.html (100%) rename crates/{system => brain}/web/test_decode.html (100%) rename crates/{system => brain}/web/test_graph_updates.html (100%) rename crates/{system => brain}/web/test_ws_interface.html (100%) rename crates/{system => brain}/web/websocket.html (100%) rename crates/{system => brain}/web/websocket_getData.html (100%) rename crates/{system => brain}/web/websocket_getData2.html (100%) create mode 100644 crates/protocol/src/large_bedroom.rs delete mode 100644 crates/system/src/controller/commands.rs delete mode 100644 crates/system/src/controller/mod.rs delete mode 100644 crates/system/src/controller/state/lightloop.rs delete mode 100644 crates/system/src/controller/state/mod.rs delete mode 100644 crates/system/src/controller/state/normal.rs delete mode 100644 crates/system/src/controller/state/off.rs delete mode 100644 crates/system/src/controller/state/silent.rs delete mode 100644 crates/system/src/controller/state/sleep.rs delete mode 100644 crates/system/src/controller/state/wakeup.rs delete mode 100644 crates/system/src/controller/system/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 4734a8dc..a2218c3c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -100,6 +100,15 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + [[package]] name = "autocfg" version = "0.1.8" @@ -234,17 +243,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] -name = "bitspec" -version = "1.0.0" -source = "git+https://github.com/dskleingeld/bitspec?branch=bool-fields#65e92b1ad3d3900a634cc6828785ed4054c83985" +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ - "log", - "num 0.3.1", - "rand 0.5.6", - "serde", - "serde_derive", - "serde_yaml 0.8.26", - "text_io", + "funty", + "radium", + "tap", + "wyz", ] [[package]] @@ -364,19 +371,45 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + [[package]] name = "colorchoice" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "const_format" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "cookie" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" dependencies = [ - "time", + "time 0.1.45", "url 1.7.2", ] @@ -393,7 +426,7 @@ dependencies = [ "publicsuffix", "serde", "serde_json", - "time", + "time 0.1.45", "try_from", "url 1.7.2", ] @@ -423,6 +456,12 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + [[package]] name = "crossbeam-channel" version = "0.5.12" @@ -504,6 +543,15 @@ dependencies = [ "sct 0.6.1", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "dtoa" version = "0.4.8" @@ -516,6 +564,12 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + [[package]] name = "encoding_rs" version = "0.8.33" @@ -619,6 +673,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures" version = "0.1.31" @@ -650,6 +710,19 @@ dependencies = [ "futures-sink", ] +[[package]] +name = "futures-concurrency" +version = "7.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b590a729e1cbaf9ae3ec294143ea034d93cbb1de01c884d04bcd0af8b613d02" +dependencies = [ + "bitvec", + "futures-core", + "pin-project", + "slab", + "smallvec 1.13.1", +] + [[package]] name = "futures-core" version = "0.3.30" @@ -819,26 +892,46 @@ dependencies = [ "clap", "crossbeam-channel", "futures 0.3.30", + "futures-concurrency", "futures-util", "log-panics", "mpd", - "num 0.4.1", + "num", "philipshue", "protocol", "rand 0.8.5", "reqwest 0.11.25", "retry", - "sensor_value", "serde", - "serde_yaml 0.9.32", + "serde_yaml", "sled", + "strum", "thiserror", + "time 0.3.36", "tokio 1.36.0", "tracing", "tracing-journald", "tracing-subscriber", ] +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -851,6 +944,31 @@ version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version 0.4.0", + "serde", + "spin 0.9.8", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32 0.3.1", + "serde", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.4.1" @@ -971,8 +1089,8 @@ dependencies = [ "itoa 0.4.8", "log", "net2", - "rustc_version", - "time", + "rustc_version 0.2.3", + "time 0.1.45", "tokio 0.1.22", "tokio-buf", "tokio-executor", @@ -1217,12 +1335,6 @@ version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - [[package]] name = "lock_api" version = "0.3.4" @@ -1396,42 +1508,17 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "num" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" -dependencies = [ - "num-bigint 0.3.3", - "num-complex 0.3.1", - "num-integer", - "num-iter", - "num-rational 0.3.2", - "num-traits", -] - [[package]] name = "num" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" dependencies = [ - "num-bigint 0.4.4", - "num-complex 0.4.5", + "num-bigint", + "num-complex", "num-integer", "num-iter", - "num-rational 0.4.1", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" -dependencies = [ - "autocfg 1.1.0", - "num-integer", + "num-rational", "num-traits", ] @@ -1448,21 +1535,18 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.3.1" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" dependencies = [ "num-traits", ] [[package]] -name = "num-complex" -version = "0.4.5" +name = "num-conv" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" -dependencies = [ - "num-traits", -] +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-integer" @@ -1484,18 +1568,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-rational" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" -dependencies = [ - "autocfg 1.1.0", - "num-bigint 0.3.3", - "num-integer", - "num-traits", -] - [[package]] name = "num-rational" version = "0.4.1" @@ -1503,7 +1575,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg 1.1.0", - "num-bigint 0.4.4", + "num-bigint", "num-integer", "num-traits", ] @@ -1527,6 +1599,15 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "object" version = "0.32.2" @@ -1556,7 +1637,7 @@ checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" dependencies = [ "lock_api 0.3.4", "parking_lot_core 0.6.3", - "rustc_version", + "rustc_version 0.2.3", ] [[package]] @@ -1590,7 +1671,7 @@ dependencies = [ "cloudabi", "libc", "redox_syscall 0.1.57", - "rustc_version", + "rustc_version 0.2.3", "smallvec 0.6.14", "winapi 0.3.9", ] @@ -1678,6 +1759,37 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "postcard" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +dependencies = [ + "cobs", + "const_format", + "embedded-io", + "heapless 0.7.17", + "postcard-derive", + "serde", +] + +[[package]] +name = "postcard-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4b01218787dd4420daf63875163a787a78294ad48a24e9f6fa8c6507759a79" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1697,7 +1809,10 @@ dependencies = [ name = "protocol" version = "0.1.0" dependencies = [ + "heapless 0.8.0", + "postcard", "serde", + "strum", ] [[package]] @@ -1720,17 +1835,10 @@ dependencies = [ ] [[package]] -name = "rand" -version = "0.5.6" +name = "radium" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "winapi 0.3.9", -] +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" @@ -1968,7 +2076,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded 0.5.5", - "time", + "time 0.1.45", "tokio 0.1.22", "tokio-executor", "tokio-io", @@ -2073,7 +2181,16 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver", + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.22", ] [[package]] @@ -2167,21 +2284,18 @@ dependencies = [ "semver-parser", ] +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + [[package]] name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -[[package]] -name = "sensor_value" -version = "0.1.0" -source = "git+https://github.com/dvdsk/sensor_central.git?branch=main#59407b7944e4a196d29c7d127751b3c2b06f3fb3" -dependencies = [ - "bitspec", - "serde", -] - [[package]] name = "serde" version = "1.0.197" @@ -2247,18 +2361,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_yaml" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" -dependencies = [ - "indexmap 1.9.3", - "ryu", - "serde", - "yaml-rust", -] - [[package]] name = "serde_yaml" version = "0.9.32" @@ -2351,6 +2453,15 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api 0.4.11", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "string" @@ -2367,6 +2478,28 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +[[package]] +name = "strum" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.52", +] + [[package]] name = "syn" version = "1.0.109" @@ -2429,10 +2562,10 @@ dependencies = [ ] [[package]] -name = "text_io" -version = "0.1.12" +name = "tap" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f0c8eb2ad70c12a6a69508f499b3051c924f4b1cfeae85bfad96e6bc5bba46" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "thiserror" @@ -2475,6 +2608,27 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "libc", + "num-conv", + "num_threads", + "powerfmt", + "serde", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + [[package]] name = "tinyvec" version = "1.6.0" @@ -3248,10 +3402,10 @@ dependencies = [ ] [[package]] -name = "yaml-rust" -version = "0.4.5" +name = "wyz" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" dependencies = [ - "linked-hash-map", + "tap", ] diff --git a/crates/system/Cargo.toml b/crates/brain/Cargo.toml similarity index 87% rename from crates/system/Cargo.toml rename to crates/brain/Cargo.toml index 8f5e1e77..6cd2ecdf 100644 --- a/crates/system/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -31,9 +31,6 @@ bincode = "1.3" thiserror = "1.0" -# todo deprecate in favor of protocol lib -sensor_value = { git = "https://github.com/dvdsk/sensor_central.git", branch = "main" } - chrono = { version = "0.4", features = ["serde"] } bytes = "1.5" byteorder = "1.4" @@ -55,3 +52,6 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } tracing-journald = "0.3.0" log-panics = "2.1.0" clap = { version = "4.5.2", features = ["derive"] } +futures-concurrency = "7.5.0" +time = { version = "0.3.36", features = ["local-offset"] } +strum = { version = "0.26.2", default-features = false, features = ["derive"] } diff --git a/crates/system/deploy.sh b/crates/brain/deploy.sh similarity index 100% rename from crates/system/deploy.sh rename to crates/brain/deploy.sh diff --git a/crates/system/deploy_optimized.sh b/crates/brain/deploy_optimized.sh similarity index 100% rename from crates/system/deploy_optimized.sh rename to crates/brain/deploy_optimized.sh diff --git a/crates/system/src/controller/environment/mod.rs b/crates/brain/src/controller/environment/mod.rs similarity index 83% rename from crates/system/src/controller/environment/mod.rs rename to crates/brain/src/controller/environment/mod.rs index ba64cc4b..83880539 100644 --- a/crates/system/src/controller/environment/mod.rs +++ b/crates/brain/src/controller/environment/mod.rs @@ -1,8 +1,7 @@ /// will store a short history of the last sensor values -/// useful for debouncing events (someone passing in front +/// useful for debouncing events (someone passing in front /// light sensor vs a cloud) - -use sensor_value::SensorValue; +use protocol::SensorValue; // struct History { // last_values: Vec, diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs new file mode 100644 index 00000000..a25896f6 --- /dev/null +++ b/crates/brain/src/controller/mod.rs @@ -0,0 +1,45 @@ +mod rooms; + +use crate::system::System; +pub use protocol::SensorValue; +use tokio::sync::broadcast; +use tokio::task::JoinSet; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Event { + Sensor(SensorValue), +} + +struct RestrictedSystem { + allowed_lights: Vec<&'static str>, + system: System, +} + +impl RestrictedSystem { + fn all_lamps_ct(&mut self, ct: u16, bri: u8) { + for name in &self.allowed_lights { + self.system.lights.set_ct(name, bri, ct).unwrap(); + } + } +} + +pub fn start(event_tx: broadcast::Sender, system: System) -> JoinSet<()> { + let mut tasks = JoinSet::new(); + + let restricted = RestrictedSystem { + system, + allowed_lights: vec![ + "large_bedroom:cabinet", + "large_bedroom:ceiling", + "large_bedroom:desk", + ], + }; + tasks.spawn(rooms::large_bedroom::run( + event_tx.subscribe(), + event_tx, + restricted, + )); + + tasks +} + diff --git a/crates/brain/src/controller/rooms.rs b/crates/brain/src/controller/rooms.rs new file mode 100644 index 00000000..e47ef5f4 --- /dev/null +++ b/crates/brain/src/controller/rooms.rs @@ -0,0 +1 @@ +pub mod large_bedroom; diff --git a/crates/brain/src/controller/rooms/large_bedroom.rs b/crates/brain/src/controller/rooms/large_bedroom.rs new file mode 100644 index 00000000..e2f6fc54 --- /dev/null +++ b/crates/brain/src/controller/rooms/large_bedroom.rs @@ -0,0 +1,102 @@ +use std::time::Duration; + +use futures_concurrency::future::Race; +use futures_util::FutureExt; +use protocol::{Button, SensorValue}; +use time::OffsetDateTime; +use tokio::sync::broadcast; +use tokio::time::{sleep_until, Instant}; +use tracing::warn; + +use crate::controller::{Event, RestrictedSystem}; +use crate::system::System; + +enum State { + Sleep, + Wakeup, + Normal, + Away, +} + +const INTERVAL: Duration = Duration::from_secs(5); + +trait RecvFiltered { + async fn recv_filter_mapped(&mut self, filter_map: impl Fn(Event) -> Option) -> T; +} + +impl RecvFiltered for broadcast::Receiver { + async fn recv_filter_mapped(&mut self, filter_map: impl Fn(Event) -> Option) -> T { + loop { + let event = self.recv().await.unwrap(); + if let Some(relevant) = filter_map(event) { + return relevant; + } + } + } +} + +#[derive(Debug)] +enum RelevantEvent { + DeskButton(protocol::large_bedroom::DeskButton), +} + +fn filter(event: Event) -> Option { + match event { + Event::Sensor(SensorValue::ButtonPress(Button::LargeBedroomDesk(desk))) => { + Some(RelevantEvent::DeskButton(desk)) + } + _ => None, + } +} + +pub async fn run( + mut event_rx: broadcast::Receiver, + // todo if state change message everyone using this + event_tx: broadcast::Sender, + mut system: RestrictedSystem, +) { + enum Res { + Event(RelevantEvent), + ShouldUpdate, + } + + let state = State::Normal; + let mut next_update = Instant::now() + INTERVAL; + loop { + let get_event = event_rx.recv_filter_mapped(filter).map(Res::Event); + let tick = sleep_until(next_update).map(|_| Res::ShouldUpdate); + + let res = (get_event, tick).race().await; + match res { + Res::Event(e) => handle_event(e), + Res::ShouldUpdate => { + update(&mut system); + next_update = Instant::now() + INTERVAL; + } + } + } +} + +fn update(system: &mut RestrictedSystem) { + let (new_ct, new_bri) = optimal_ct_bri(); + system.all_lamps_ct(new_ct, new_bri); +} + +fn optimal_ct_bri() -> (u16, u8) { + let now = OffsetDateTime::now_local().expect("Timezone not found"); + match now.hour() { + 0..=5 | 22.. => (500, 220), + 17..=21 => (320, u8::MAX), + 6..=16 => (254, u8::MAX), + } +} + +fn handle_event(e: RelevantEvent) { + use protocol::large_bedroom::DeskButton as D; + use RelevantEvent as R; + + match e { + R::DeskButton(D::OneOfFour(p)) if p.is_long() => todo!(), + unhandled => warn!("Unhandled button: {unhandled:?}"), + } +} diff --git a/crates/system/src/errors.rs b/crates/brain/src/errors.rs similarity index 80% rename from crates/system/src/errors.rs rename to crates/brain/src/errors.rs index 7312dc5d..07d2aff3 100644 --- a/crates/system/src/errors.rs +++ b/crates/brain/src/errors.rs @@ -11,11 +11,9 @@ pub enum Error { #[error("Could not download youtube")] Download(#[from] reqwest::Error), #[error("Error while adjusting lighting: {0}")] - Lamps(#[from] crate::controller::system::lamps::Error), + Lamps(#[from] crate::system::lamps::Error), #[error("Error contacting mpd")] Mpd(#[from] mpd::error::Error), #[error("Error in the wakeup alarm system")] SetWakeUp(#[from] crate::input::jobs::wakeup::Error), - #[error("Error in wakeup state")] - WakeUpState(#[from] crate::controller::WakeUpStateError), } diff --git a/crates/system/src/input/api.rs b/crates/brain/src/input/api.rs similarity index 78% rename from crates/system/src/input/api.rs rename to crates/brain/src/input/api.rs index f78f8d23..a2a74cec 100644 --- a/crates/system/src/input/api.rs +++ b/crates/brain/src/input/api.rs @@ -3,6 +3,8 @@ use axum::extract::State as aState; use axum::http::StatusCode; use axum::routing::{get, post}; use axum::Router; +use tokio::sync::broadcast; +use tracing::warn; use crate::controller::Event; @@ -34,7 +36,8 @@ async fn set_usually(aState(state): aState, body: Bytes) -> StatusCode { let time: Option<(u8, u8)> = bincode::deserialize(&body[..]) .map_err(|_| "Could not deserialize into time") .unwrap(); - let _ignore = state.wakeup + let _ignore = state + .wakeup .set_usually(time) .await .map_err(|_| "Could not save new alarm time") @@ -47,7 +50,8 @@ async fn set_tomorrow(aState(state): aState, body: Bytes) -> StatusCode { let time: Option<(u8, u8)> = bincode::deserialize(&body[..]) .map_err(|_| "Could not deserialize into time") .unwrap(); - let _ignore = state.wakeup + let _ignore = state + .wakeup .set_tomorrow(time) .await .map_err(|_| "Could not save new alarm time") @@ -56,26 +60,33 @@ async fn set_tomorrow(aState(state): aState, body: Bytes) -> StatusCode { StatusCode::OK } -async fn button(aState(state): aState) { - state.event_tx.send(todo!()).unwrap(); +async fn sensor_event(aState(state): aState, body: Bytes) { + let value = match protocol::SensorValue::decode(&body[..]) { + Ok(value) => value, + Err(e) => { + warn!("Failed to decode received body: {e}"); + return; + } + }; + state.event_tx.send(Event::Sensor(value)).unwrap(); } #[derive(Clone)] pub struct State { wakeup: WakeUp, - event_tx: crossbeam_channel::Sender, + event_tx: broadcast::Sender, } pub async fn setup( wakeup: WakeUp, - event_tx: crossbeam_channel::Sender, + event_tx: broadcast::Sender, port: u16, ) -> Result<(), Error> { let app = Router::new() .route("/alarm/usually", get(usually).post(set_usually)) .route("/alarm/tomorrow", get(tomorrow).post(set_tomorrow)) - .route("/event/button", post(button)) - .with_state(State{wakeup, event_tx}); + .route("/event", post(sensor_event)) + .with_state(State { wakeup, event_tx }); // https is done at the loadbalancer let listener = tokio::net::TcpListener::bind(format!("127.0.0.1:{port}")) diff --git a/crates/system/src/input/jobs.rs b/crates/brain/src/input/jobs.rs similarity index 91% rename from crates/system/src/input/jobs.rs rename to crates/brain/src/input/jobs.rs index de36e7dc..f54e3a38 100644 --- a/crates/system/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -1,4 +1,5 @@ use crossbeam_channel; +use tokio::sync::broadcast; use tracing::error; use tracing::info; use std::ops::Sub; @@ -9,7 +10,6 @@ use chrono::{self, DateTime, Utc}; use serde::{Deserialize, Serialize}; use sled; -use crate::controller::Command; use crate::controller::Event; pub mod wakeup; @@ -17,8 +17,7 @@ pub use wakeup::WakeUp; #[derive(Serialize, Deserialize, Debug)] pub enum Action { - SendEvent(Event), - SendCommand(Command), + // SendEvent(Event), } #[derive(thiserror::Error, Debug)] @@ -29,17 +28,6 @@ pub enum Error { CommError(#[from] crossbeam_channel::SendError<()>), } -impl From for Action { - fn from(event: Event) -> Self { - Action::SendEvent(event) - } -} -impl From for Action { - fn from(command: Command) -> Self { - Action::SendCommand(command) - } -} - #[derive(Serialize, Deserialize, Debug)] pub struct Job { pub time: DateTime, @@ -78,21 +66,21 @@ impl Sub> for &Job { } } -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct Jobs { waker_tx: crossbeam_channel::Sender<()>, list: JobList, } -#[derive(Clone)] -pub struct JobList { +#[derive(Debug, Clone)] +struct JobList { db: sled::Tree, } use crossbeam_channel::RecvTimeoutError::*; fn waker( mut alarm_list: JobList, - event_tx: crossbeam_channel::Sender, + event_tx: broadcast::Sender, waker_rx: crossbeam_channel::Receiver<()>, ) { loop { @@ -137,16 +125,16 @@ fn waker( } } -fn sound_alarm(event_tx: &crossbeam_channel::Sender, job: Job) { - match job.action { - Action::SendEvent(ev) => event_tx.send(ev).unwrap(), - Action::SendCommand(cmd) => event_tx.send(Event::Command(cmd)).unwrap(), - } +fn sound_alarm(event_tx: &broadcast::Sender, job: Job) { + todo!(); + // match job.action { + // Action::SendEvent(ev) => event_tx.send(ev).unwrap(), + // }; } impl Jobs { pub fn setup( - event_tx: crossbeam_channel::Sender, + event_tx: broadcast::Sender, db: sled::Db, ) -> Result<(Self, thread::JoinHandle<()>), Error> { let list = JobList { diff --git a/crates/system/src/input/jobs/wakeup.rs b/crates/brain/src/input/jobs/wakeup.rs similarity index 98% rename from crates/system/src/input/jobs/wakeup.rs rename to crates/brain/src/input/jobs/wakeup.rs index b71c6244..bc957cd6 100644 --- a/crates/system/src/input/jobs/wakeup.rs +++ b/crates/brain/src/input/jobs/wakeup.rs @@ -166,7 +166,7 @@ impl Inner { fn job_from(hour: u8, min: u8) -> Job { Job { time: to_datetime(hour, min), - action: Action::SendEvent(Event::WakeUp), + action: todo!(), //Action::SendEvent(Event::WakeUp), expiration: Some(Duration::from_secs(3 * 60 * 60)), } } diff --git a/crates/system/src/input/mod.rs b/crates/brain/src/input/mod.rs similarity index 100% rename from crates/system/src/input/mod.rs rename to crates/brain/src/input/mod.rs diff --git a/crates/system/src/input/mpd_status.rs b/crates/brain/src/input/mpd_status.rs similarity index 100% rename from crates/system/src/input/mpd_status.rs rename to crates/brain/src/input/mpd_status.rs diff --git a/crates/system/src/input/web_api/commands.rs b/crates/brain/src/input/web_api/commands.rs similarity index 100% rename from crates/system/src/input/web_api/commands.rs rename to crates/brain/src/input/web_api/commands.rs diff --git a/crates/system/src/input/web_api/mod.rs b/crates/brain/src/input/web_api/mod.rs similarity index 100% rename from crates/system/src/input/web_api/mod.rs rename to crates/brain/src/input/web_api/mod.rs diff --git a/crates/system/src/input/web_api/music.rs b/crates/brain/src/input/web_api/music.rs similarity index 100% rename from crates/system/src/input/web_api/music.rs rename to crates/brain/src/input/web_api/music.rs diff --git a/crates/system/src/input/web_api/server/database.rs b/crates/brain/src/input/web_api/server/database.rs similarity index 100% rename from crates/system/src/input/web_api/server/database.rs rename to crates/brain/src/input/web_api/server/database.rs diff --git a/crates/system/src/input/web_api/server/login.rs b/crates/brain/src/input/web_api/server/login.rs similarity index 100% rename from crates/system/src/input/web_api/server/login.rs rename to crates/brain/src/input/web_api/server/login.rs diff --git a/crates/system/src/input/web_api/server/login_redirect.rs b/crates/brain/src/input/web_api/server/login_redirect.rs similarity index 100% rename from crates/system/src/input/web_api/server/login_redirect.rs rename to crates/brain/src/input/web_api/server/login_redirect.rs diff --git a/crates/system/src/input/web_api/server/mod.rs b/crates/brain/src/input/web_api/server/mod.rs similarity index 100% rename from crates/system/src/input/web_api/server/mod.rs rename to crates/brain/src/input/web_api/server/mod.rs diff --git a/crates/system/src/input/web_api/server/static_webpages/login.css b/crates/brain/src/input/web_api/server/static_webpages/login.css similarity index 100% rename from crates/system/src/input/web_api/server/static_webpages/login.css rename to crates/brain/src/input/web_api/server/static_webpages/login.css diff --git a/crates/system/src/input/web_api/server/static_webpages/login.html b/crates/brain/src/input/web_api/server/static_webpages/login.html similarity index 100% rename from crates/system/src/input/web_api/server/static_webpages/login.html rename to crates/brain/src/input/web_api/server/static_webpages/login.html diff --git a/crates/system/src/input/web_api/wakeup.rs b/crates/brain/src/input/web_api/wakeup.rs similarity index 100% rename from crates/system/src/input/web_api/wakeup.rs rename to crates/brain/src/input/web_api/wakeup.rs diff --git a/crates/system/src/main.rs b/crates/brain/src/main.rs similarity index 69% rename from crates/system/src/main.rs rename to crates/brain/src/main.rs index 90088dad..a44092c9 100644 --- a/crates/system/src/main.rs +++ b/crates/brain/src/main.rs @@ -1,10 +1,13 @@ use std::net::IpAddr; use clap::Parser; +use input::jobs::Jobs; use sled; +use tokio::sync::broadcast; use tracing::warn; mod controller; +mod system; mod errors; mod input; @@ -27,26 +30,29 @@ struct Opt { } #[tokio::main] -async fn main() { +async fn main() -> Result<(), Box> { + setup_tracing(); let opt = Opt::parse(); let db = sled::Config::default() //651ms .path("database") .flush_every_ms(None) //do not flush to disk unless explicitly asked .cache_capacity(1024 * 1024 * 32) //32 mb cache - .open() - .unwrap(); + .open()?; - let (event_tx, event_rx) = crossbeam_channel::unbounded(); + let (event_tx, _event_rx) = broadcast::channel(250); - let (joblist, _waker_thread) = input::jobs::Jobs::setup(event_tx.clone(), db.clone()).unwrap(); - let wakeup = input::jobs::WakeUp::setup(db.clone(), joblist.clone()).unwrap(); - let (mpd_status, _mpd_watcher_thread, _updater_tx) = - input::MpdStatus::start_updating(opt.mpd_ip).unwrap(); + let (jobs, _waker_thread) = input::jobs::Jobs::setup(event_tx.clone(), db.clone())?; + let wakeup = input::jobs::WakeUp::setup(db.clone(), jobs.clone())?; + // let (_mpd_status, _mpd_watcher_thread, _updater_tx) = + // input::MpdStatus::start_updating(opt.mpd_ip)?; - let _controller_thread = - controller::start(event_rx, mpd_status.clone(), wakeup.clone()).unwrap(); - let webserver = input::api::setup(wakeup.clone(), event_tx, opt.port).await; + let system = system::System::init(jobs); + controller::start(event_tx.clone(), system); + input::api::setup(wakeup.clone(), event_tx, opt.port).await?; + + std::future::pending::<()>().await; + Ok(()) } pub fn setup_tracing() { diff --git a/crates/brain/src/system.rs b/crates/brain/src/system.rs new file mode 100644 index 00000000..59ffe0bf --- /dev/null +++ b/crates/brain/src/system.rs @@ -0,0 +1,24 @@ +pub mod lamps; +pub mod mpd_control; + +pub use lamps::Lighting; +pub use mpd_control::Mpd; + +use crate::input::jobs::Jobs; + +#[derive(Debug, Clone)] +pub struct System { + pub jobs: Jobs, + pub lights: Lighting, + pub mpd: Mpd, +} + +impl System { + pub fn init(jobs: Jobs) -> Self { + Self { + jobs, + lights: Lighting::start_init(), + mpd: Mpd, + } + } +} diff --git a/crates/system/src/controller/system/computer.rs b/crates/brain/src/system/computer.rs similarity index 100% rename from crates/system/src/controller/system/computer.rs rename to crates/brain/src/system/computer.rs diff --git a/crates/system/src/controller/system/lamps/bridge_connect.rs b/crates/brain/src/system/lamps/bridge_connect.rs similarity index 100% rename from crates/system/src/controller/system/lamps/bridge_connect.rs rename to crates/brain/src/system/lamps/bridge_connect.rs diff --git a/crates/system/src/controller/system/lamps/eventually_consistent_bridge.rs b/crates/brain/src/system/lamps/eventually_consistent_bridge.rs similarity index 68% rename from crates/system/src/controller/system/lamps/eventually_consistent_bridge.rs rename to crates/brain/src/system/lamps/eventually_consistent_bridge.rs index a8e9b1f3..d3efa8ff 100644 --- a/crates/system/src/controller/system/lamps/eventually_consistent_bridge.rs +++ b/crates/brain/src/system/lamps/eventually_consistent_bridge.rs @@ -13,21 +13,42 @@ use tracing::error; use philipshue::bridge::Bridge; -pub(crate) type LampId = usize; pub(crate) enum Change { AllOff, AllOn, - Off { lamp_id: LampId }, - On { lamp_id: LampId }, - CtBri { lamp_id: LampId, bri: u8, ct: u16 }, - AllCtBri { bri: u8, ct: u16 }, - AllXY { bri: u8, xy: (f32, f32) }, + Off { + name: &'static str, + }, + On { + name: &'static str, + }, + CtBri { + name: &'static str, + bri: u8, + ct: u16, + }, + XyBri { + name: &'static str, + bri: u8, + xy: (f32, f32), + }, + AllCtBri { + bri: u8, + ct: u16, + }, + AllXY { + bri: u8, + xy: (f32, f32), + }, } +type LampId = usize; pub(crate) struct CachedBridge { pub(crate) bridge: Bridge, pub(crate) needed_state: State, pub(crate) known_state: State, + // get names using: curl 192.168.1.11/api//lights | jq | grep '"name": "' + lookup: HashMap, } impl CachedBridge { @@ -37,11 +58,16 @@ impl CachedBridge { .iter() .map(|(id, light)| (*id, Lamp::from(&light.state))) .collect(); + let lookup = lights_info + .into_iter() + .map(|(id, light)| (light.name, id)) + .collect(); Ok(Self { bridge, needed_state: state.clone(), known_state: state, + lookup, }) } @@ -77,26 +103,48 @@ impl CachedBridge { .values_mut() .for_each(|lamp| lamp.on = true); } - Change::Off { lamp_id } => { - if let Some(lamp) = self.needed_state.get_mut(&lamp_id) { + Change::Off { name } => { + let Some(lamp_id) = self.lookup.get(*name) else { + error!("no lamp with name: {name} in lookup table, was recently (re)named?"); + return; + }; + if let Some(lamp) = self.needed_state.get_mut(lamp_id) { lamp.on = true; } else { error!("no lamp with id: {lamp_id} exists"); } } - Change::On { lamp_id } => { + Change::On { name } => { + let Some(lamp_id) = self.lookup.get(*name) else { + error!("no lamp with name: {name} in lookup table, was recently (re)named?"); + return; + }; if let Some(lamp) = self.needed_state.get_mut(&lamp_id) { lamp.on = false; } else { error!("no lamp with id: {lamp_id} exists"); } } - Change::CtBri { lamp_id, bri, ct } => { + Change::CtBri { name, bri, ct } => { + let Some(lamp_id) = self.lookup.get(*name) else { + error!("no lamp with name: {name} in lookup table, was recently (re)named?"); + return; + }; if let Some(lamp) = self.needed_state.get_mut(lamp_id) { lamp.bri = *bri; lamp.ct = Some(*ct); } } + Change::XyBri { name, bri, xy } => { + let Some(lamp_id) = self.lookup.get(*name) else { + error!("no lamp with name: {name} in lookup table, was recently (re)named?"); + return; + }; + if let Some(lamp) = self.needed_state.get_mut(lamp_id) { + lamp.bri = *bri; + lamp.xy = Some(*xy); + } + } Change::AllCtBri { bri, ct } => { self.needed_state.values_mut().for_each(|lamp| { lamp.bri = *bri; diff --git a/crates/system/src/controller/system/lamps/lamp.rs b/crates/brain/src/system/lamps/lamp.rs similarity index 100% rename from crates/system/src/controller/system/lamps/lamp.rs rename to crates/brain/src/system/lamps/lamp.rs diff --git a/crates/system/src/controller/system/lamps/mod.rs b/crates/brain/src/system/lamps/mod.rs similarity index 88% rename from crates/system/src/controller/system/lamps/mod.rs rename to crates/brain/src/system/lamps/mod.rs index 86e4eeda..94f78c64 100644 --- a/crates/system/src/controller/system/lamps/mod.rs +++ b/crates/brain/src/system/lamps/mod.rs @@ -25,6 +25,7 @@ async fn manage_bridge( yielded.map(|item| (item, rx)) }); + let mut prev_error = String::new(); let stream = stream.peekable(); pin_mut!(stream); loop { @@ -35,13 +36,16 @@ async fn manage_bridge( Err(e) => e, }; - error!("could not connect to bridge: {error:?}"); + if prev_error != error.to_string() { + error!("could not connect to bridge: {error:?}"); + prev_error = error.to_string(); + } tokio::time::sleep(Duration::from_secs(5)).await; } } +#[derive(Debug, Clone)] pub struct Lighting { - _manage_bridge: tokio::task::JoinHandle<()>, tx: mpsc::UnboundedSender<(oneshot::Sender>, Change)>, } @@ -80,10 +84,7 @@ impl Lighting { let (tx, rx) = mpsc::unbounded_channel(); let manage_bridge = manage_bridge(rx); let manage_bridge = tokio::task::spawn(manage_bridge); - Self { - _manage_bridge: manage_bridge, - tx, - } + Self { tx } } //how to deal with errors? @@ -94,10 +95,11 @@ impl Lighting { light_fn! {all_off, AllOff} light_fn! {all_on, AllOn} - light_fn! {single_off, Off; lamp_id: usize} - light_fn! {single_on, On; lamp_id: usize} + light_fn! {single_off, Off; name: &'static str} + light_fn! {single_on, On; name: &'static str} - light_fn! {set_ct, CtBri; lamp_id: usize, bri: u8, ct: u16 } + light_fn! {set_ct, CtBri; name: &'static str, bri: u8, ct: u16 } + light_fn! {set_xy, XyBri; name: &'static str, bri: u8, xy: (f32, f32)} light_fn! {set_all_ct, AllCtBri; bri: u8, ct: u16 } light_fn! {set_all_xy, AllXY; bri: u8, xy: (f32, f32) } diff --git a/crates/system/src/controller/system/mpd_control.rs b/crates/brain/src/system/mpd_control.rs similarity index 97% rename from crates/system/src/controller/system/mpd_control.rs rename to crates/brain/src/system/mpd_control.rs index e5294d06..7e0f7db0 100644 --- a/crates/system/src/controller/system/mpd_control.rs +++ b/crates/brain/src/system/mpd_control.rs @@ -5,6 +5,10 @@ use tracing::warn; use crate::input::mpd_status::MpdStatus; +// TODO make this stuff obj oriented +#[derive(Debug, Clone)] +pub struct Mpd; + pub fn add_from_playlist( mpd: &mut mpd::Client, name: &str, diff --git a/crates/system/web/add_song.html b/crates/brain/web/add_song.html similarity index 100% rename from crates/system/web/add_song.html rename to crates/brain/web/add_song.html diff --git a/crates/system/web/graph.html b/crates/brain/web/graph.html similarity index 100% rename from crates/system/web/graph.html rename to crates/brain/web/graph.html diff --git a/crates/system/web/graphDebug.html b/crates/brain/web/graphDebug.html similarity index 100% rename from crates/system/web/graphDebug.html rename to crates/brain/web/graphDebug.html diff --git a/crates/system/web/login.css b/crates/brain/web/login.css similarity index 100% rename from crates/system/web/login.css rename to crates/brain/web/login.css diff --git a/crates/system/web/login.html b/crates/brain/web/login.html similarity index 100% rename from crates/system/web/login.html rename to crates/brain/web/login.html diff --git a/crates/system/web/plot.js b/crates/brain/web/plot.js similarity index 100% rename from crates/system/web/plot.js rename to crates/brain/web/plot.js diff --git a/crates/system/web/plot_debug.js b/crates/brain/web/plot_debug.js similarity index 100% rename from crates/system/web/plot_debug.js rename to crates/brain/web/plot_debug.js diff --git a/crates/system/web/set_alarm.html b/crates/brain/web/set_alarm.html similarity index 98% rename from crates/system/web/set_alarm.html rename to crates/brain/web/set_alarm.html index 9d5ec2c1..b2ea2404 100755 --- a/crates/system/web/set_alarm.html +++ b/crates/brain/web/set_alarm.html @@ -28,7 +28,7 @@ function display_alarm_success() { - document.write("alarm set succesfully"); + document.write("alarm set successfully"); } function display_alarm_fail() { document.write("alarm set failed!!!!"); @@ -100,4 +100,4 @@ - \ No newline at end of file + diff --git a/crates/system/web/test.html b/crates/brain/web/test.html similarity index 100% rename from crates/system/web/test.html rename to crates/brain/web/test.html diff --git a/crates/system/web/test_decode.html b/crates/brain/web/test_decode.html similarity index 100% rename from crates/system/web/test_decode.html rename to crates/brain/web/test_decode.html diff --git a/crates/system/web/test_graph_updates.html b/crates/brain/web/test_graph_updates.html similarity index 100% rename from crates/system/web/test_graph_updates.html rename to crates/brain/web/test_graph_updates.html diff --git a/crates/system/web/test_ws_interface.html b/crates/brain/web/test_ws_interface.html similarity index 100% rename from crates/system/web/test_ws_interface.html rename to crates/brain/web/test_ws_interface.html diff --git a/crates/system/web/websocket.html b/crates/brain/web/websocket.html similarity index 100% rename from crates/system/web/websocket.html rename to crates/brain/web/websocket.html diff --git a/crates/system/web/websocket_getData.html b/crates/brain/web/websocket_getData.html similarity index 100% rename from crates/system/web/websocket_getData.html rename to crates/brain/web/websocket_getData.html diff --git a/crates/system/web/websocket_getData2.html b/crates/brain/web/websocket_getData2.html similarity index 100% rename from crates/system/web/websocket_getData2.html rename to crates/brain/web/websocket_getData2.html diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index 8286eb8b..7eb58e7e 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -9,4 +9,11 @@ authors.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -serde = { version = "1.0.197", features = ["derive"] } +serde = { version = "1.0", features = ["derive"], default-features = false } +postcard = { version = "1.0", features = ["experimental-derive"] } +heapless = { version = "0.8.0", features = ["serde"] } +strum = { version = "0.26.2", default-features = false } + +[features] +default = ["alloc"] +alloc = ["postcard/alloc", "serde/std"] diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs new file mode 100644 index 00000000..b4529bf4 --- /dev/null +++ b/crates/protocol/src/large_bedroom.rs @@ -0,0 +1,15 @@ +use crate::button_enum; + +// No these are not borg, these are buttons on a string of cat5. +// They are numbered starting at the farthest from the end +button_enum! { + DeskButton { + OneOfFour, + TwoOfFour, + ThreeOfFour, + FourOfFour, + OneOfThree, + TwoOfThree, + ThirdOfThree, + } +} diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 559e65cb..9a73241d 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -1,14 +1,174 @@ +#[cfg_attr(not(feature = "alloc"), no_std)] +pub mod large_bedroom; + +use postcard::experimental::max_size::MaxSize as _; use serde::{Deserialize, Serialize}; -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +/// turns an enum of empty variants into one with [`Press`](crate::Press) inside each variant also +/// adds a method `press(&self)` that returns an instance of [`Press`](crate::Press). It can be +/// used to quickly find out if a button event is a long or short press. +/// +/// Example: +/// +/// button_enum! { +/// DeskButton { +/// OneOfFour, +/// TwoOfFour, +/// } +/// } +/// +macro_rules! button_enum { + ($name:ident {$($variant:ident,)*}) => { + #[derive( + Clone, + Copy, + Debug, + serde::Serialize, + serde::Deserialize, + PartialEq, + Eq, + postcard::experimental::max_size::MaxSize + )] + pub enum $name { + $($variant(crate::Press),)* + } + + impl $name { + pub fn press(&self) -> crate::Press { + match self { + $(Self::$variant(d) => *d,)* + } + } + } + }; +} +pub(crate) use button_enum; + +// Duration of the press in milliseconds +#[derive( + Clone, + Copy, + Debug, + Serialize, + Deserialize, + PartialEq, + Eq, + postcard::experimental::max_size::MaxSize, +)] +pub struct Press(u16); + +impl Press { + pub fn is_long(&self) -> bool { + if self.0 > 300 { + true + } else { + false + } + } +} + +#[derive( + Clone, + Copy, + Debug, + Serialize, + Deserialize, + PartialEq, + Eq, + postcard::experimental::max_size::MaxSize, +)] pub enum Button { + LargeBedroomDesk(large_bedroom::DeskButton), } impl Button { - fn encode(&self) -> Vec { - todo!() + pub fn press(&self) -> Press { + match self { + Button::LargeBedroomDesk(b) => b.press(), + } + } +} + +#[derive( + Clone, + Copy, + Debug, + Serialize, + Deserialize, + PartialEq, + Eq, + postcard::experimental::max_size::MaxSize, +)] +pub enum SensorValue { + ButtonPress(Button), + #[cfg(test)] + Test, +} + +impl SensorValue { + // #[cfg(feature = "alloc")] + // pub fn encode(&self) -> Vec { + // postcard::to_allocvec(self).expect("Encoding should not fail") + // } + // // todo encode for on an embedded sys + // + // pub fn decode(bytes: impl AsRef<[u8]>) -> Result { + // postcard::from_bytes(bytes.as_ref()) + // } + // + pub fn version() -> u8 { + 0u8 + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SensorMessage { + values: heapless::Vec, + version: u8, +} + +impl SensorMessage { + /// the 2x is the max overhead from COBS encoding the encoded data + /// +2 is for the version + /// +4 covers the length of the heapless list + pub const ENCODED_SIZE: usize = 2 * (MAX_ITEMS * SensorValue::POSTCARD_MAX_SIZE + 2 + 4); + + #[cfg(feature = "alloc")] + pub fn encode(&self) -> Vec { + postcard::to_allocvec_cobs(self).expect("Encoding should not fail") + } + + /// Buffer should be at least Self::ENCODED_SIZE long. The returned slice contains + /// the serialized data. It can be shorter then the input buffer. + pub fn encode_slice<'a, const N: usize>(&self, buf: &'a mut [u8]) -> &'a mut [u8] { + postcard::to_slice_cobs(self, buf).expect("Encoding should not fail") + } + + pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { + postcard::from_bytes_cobs(bytes.as_mut()) } - fn dencode(bytes: impl AsRef<[u8]>) -> Result { - todo!() + + pub fn version() -> u8 { + 0u8 + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn decode_from_different_max_items() { + let mut values = heapless::Vec::new(); + values.push(SensorValue::Test).unwrap(); + let mut bytes = SensorMessage::<1> { + values: values.clone(), + version: 0u8, + } + .encode(); + + let decoded: SensorMessage<100> = SensorMessage::<100>::decode(&mut bytes).unwrap(); + + assert_eq!(decoded.values.to_vec(), values.to_vec()); } } diff --git a/crates/system/src/controller/commands.rs b/crates/system/src/controller/commands.rs deleted file mode 100644 index a2332ab1..00000000 --- a/crates/system/src/controller/commands.rs +++ /dev/null @@ -1,90 +0,0 @@ -use serde::{Deserialize, Serialize}; -use tracing::{warn, error}; - -use super::{Modifications, System}; -use crate::controller::state::*; -use crate::controller::system::mpd_control; - -#[derive(Copy, Clone, Debug, Serialize, Deserialize)] -pub enum Command { - None, - - LampsToggle, - LampsDim, - LampsDimmest, - LampsEvening, - LampsNight, - LampsDay, - - MpdPause, - MpdDecreaseVolume, - MpdIncreaseVolume, - MpdNextSong, - MpdPrevSong, - - GoToLinux, - GoToWindows, - - Test, //prints a test message - - ChangeState(State), -} - -//TODO handle error on command -pub fn handle_cmd(cmd: Command, mods: &mut Modifications, sys: &mut System) -> Option { - println!("handled a command"); - match cmd { - Command::ChangeState(target_state) => { - return Some(target_state); - } - //Command::PauseMpd => {unimplemented!(); state}, - Command::LampsToggle => { - sys.lights.toggle().unwrap(); - mods.lighting = true - } - Command::LampsDim => { - sys.lights.set_all_ct(50, 500).unwrap(); - mods.lighting = true - } - Command::LampsDimmest => { - sys.lights.set_all_ct(1, 500).unwrap(); - mods.lighting = true - } - Command::LampsEvening => { - sys.lights.set_all_ct(254, 320).unwrap(); - mods.lighting = true - } - Command::LampsNight => { - sys.lights.set_all_ct(220, 500).unwrap(); - mods.lighting = true - } - Command::LampsDay => { - sys.lights.set_all_ct(254, 240).unwrap(); - mods.lighting = true - } - - Command::GoToLinux => println!("should go to linux"), - Command::GoToWindows => println!("should go to windows"), - - Command::MpdPause => { - mpd_control::toggle_playback(&mut sys.mpd).unwrap(); - mods.mpd = true - } - Command::MpdDecreaseVolume => { - mpd_control::decrease_volume(&mut sys.mpd).unwrap(); - mods.mpd = true - } - Command::MpdIncreaseVolume => { - if let mpd::State::Play = sys.mpd.is_playing() { - mpd_control::increase_volume(&mut sys.mpd).unwrap(); - mods.mpd = true - } - } - Command::MpdNextSong => mpd_control::next_song().unwrap(), - Command::MpdPrevSong => mpd_control::prev_song().unwrap(), - - Command::Test => warn!("The Test command was just send"), - Command::None => error!("None command was issued, this should not happen"), - } - None -} diff --git a/crates/system/src/controller/mod.rs b/crates/system/src/controller/mod.rs deleted file mode 100644 index 7b8c6245..00000000 --- a/crates/system/src/controller/mod.rs +++ /dev/null @@ -1,245 +0,0 @@ -use crossbeam_channel::RecvTimeoutError::*; -use serde::{Deserialize, Serialize}; -use std::thread; -use std::time::{Duration, Instant}; -use tracing::error; - -pub mod system; -use system::Lighting; - -mod environment; -use environment::Environment; - -mod state; -use state::RoomState; -mod commands; -use commands::handle_cmd; - -use crate::errors::Error; -use crate::input::jobs::WakeUp; -use crate::input::mpd_status::MpdStatus; -pub use commands::Command; -use sensor_value::{Button, Press, SensorValue}; -pub use state::{State, WakeUpStateError}; - -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] -pub enum Event { - Update, - WakeUp, - Test, - Command(Command), - Sensor(SensorValue), -} - -pub struct Modifications { - //change name to: alteration, deviation, overrides or something else? - lighting: bool, - mpd: bool, - //Desk, - //Alarm, -} - -impl Modifications { - fn reset(&mut self) { - self.lighting = false; - self.mpd = false; - } -} - -impl Default for Modifications { - fn default() -> Self { - Modifications { - lighting: false, - mpd: false, - } - } -} - -pub struct System { - update_period: Duration, - next_update: Instant, - lights: Lighting, - mpd: MpdStatus, - wakeup: WakeUp, -} - -fn saturating_duration_till(target: std::time::Instant) -> std::time::Duration { - let now = Instant::now(); - if now < target { - target - now - } else { - Duration::from_secs(0) - } -} - -pub fn start( - event_rx: crossbeam_channel::Receiver, - mpd_status: MpdStatus, - wakeup: WakeUp, -) -> Result, Error> { - let mut system = System { - update_period: Duration::from_secs(5), - next_update: Instant::now() + Duration::from_secs(5), - lights: Lighting::start_init(), - mpd: mpd_status, - wakeup, - }; - - let handle = thread::spawn(move || { - let mut mods = Modifications::default(); - let mut env = Environment::default(); - // TODO guess best init state from statefile or lamps+mpd+time - - let mut state: Box = state::Normal::setup(&mut mods, &mut system).unwrap(); //initial state - let mut current_state = State::Normal; - - loop { - //wait for next update or an incoming event - let time_till_update = saturating_duration_till(system.next_update); - let event = match event_rx.recv_timeout(time_till_update) { - Ok(event) => event, - Err(Timeout) => { - system.next_update = Instant::now() + system.update_period; - Event::Update - } - Err(Disconnected) => return, - }; - - let res = handle_event( - event, - current_state, - &mut mods, - &mut system, - &mut env, - &mut state, - ); - match res { - Err(e) => error!("Ran into an error handling an event: {:?}", e), - Ok(Some(target_state)) => { - //should switch to another state - if let Ok(new_state) = change_state(target_state, &mut mods, &mut system) { - state = new_state; - current_state = target_state; - } //if state setup ran into an error we do not switch state - } - _ => (), - } - - if let Event::Sensor(s) = event { - env.update(s); - } - } - }); - Ok(handle) -} - -fn handle_event( - event: Event, - current_state: State, - mods: &mut Modifications, - system: &mut System, - env: &mut Environment, - state: &mut Box, -) -> Result, Error> { - //state changes may not return errors - let next_state = match (event, current_state) { - //specific test code for normal state - (Event::Test, State::Normal) => { - dbg!("a test happened while in normal state"); - None - } - //general code that is the same for all functions, unless specific handlers exist above - (Event::Command(cmd), _) => handle_cmd(cmd, mods, system), - (Event::Update, _) => state.update(mods, system, env)?, - (Event::WakeUp, _) => { - system.wakeup.reset()?; - Some(State::WakeUp) - } - (Event::Test, _) => { - dbg!("a test happened"); - None - } - - (Event::Sensor(s), _) => handle_sensor(s, mods, system), - }; - Ok(next_state) -} - -fn handle_sensor( - value: SensorValue, - mods: &mut Modifications, - system: &mut System, -) -> Option { - match value { - SensorValue::ButtonPress(press) => handle_buttonpress(press, mods, system), - // SensorValue::BathroomHum(b) => {dbg!(b); None} - // SensorValue::BathroomTemp(t) => {dbg!(t); None} - // SensorValue::MovementShower => {dbg!(b); None} - // SensorValue::MovementToilet => {dbg!(b); None} - _ => None, // for now we ignore the other sensor data - } -} - -fn handle_buttonpress( - press: Press, - mods: &mut Modifications, - system: &mut System, -) -> Option { - const LONG_PRESS: u16 = 500; //ms - if press.duration < LONG_PRESS { - // millisec - match press.button { - Button::LampLeft => None, - Button::LampMid => Some(State::Silent), - Button::LampRight => Some(State::Off), - - Button::DeskLeftMost => Some(State::Sleep), - Button::DeskLeft => Some(State::Normal), - Button::DeskRight => None, - Button::DeskRightMost => Some(State::Off), - - Button::DeskTop => handle_cmd(Command::MpdIncreaseVolume, mods, system), - Button::DeskMid => handle_cmd(Command::MpdPause, mods, system), - Button::DeskBottom => handle_cmd(Command::MpdDecreaseVolume, mods, system), - } - } else { - let cmd = match press.button { - Button::LampLeft => Command::LampsDim, - Button::LampMid => Command::LampsDimmest, - Button::LampRight => Command::LampsToggle, - - Button::DeskLeftMost => Command::LampsNight, - Button::DeskLeft => Command::LampsEvening, - Button::DeskRight => Command::LampsDay, - Button::DeskRightMost => Command::LampsToggle, - - Button::DeskTop => Command::MpdIncreaseVolume, - Button::DeskMid => Command::MpdPause, - Button::DeskBottom => Command::MpdDecreaseVolume, - }; - handle_cmd(cmd, mods, system) - } -} - -fn change_state( - next_state: State, - mods: &mut Modifications, - system: &mut System, -) -> Result, Error> { - let res = match &next_state { - State::Normal => state::Normal::setup(mods, system), - State::LightLoop => state::LightLoop::setup(mods, system), - State::WakeUp => state::WakeUp::setup(mods, system), - State::Sleep => state::Sleep::setup(mods, system), - State::Silent => state::Silent::setup(mods, system), - State::Off => state::Off::setup(mods, system), - }; - - if let Err(ref e) = &res { - error!( - "ran into error trying to switch to state: {:?}, error: {:?}", - next_state, e - ); - } - res -} diff --git a/crates/system/src/controller/state/lightloop.rs b/crates/system/src/controller/state/lightloop.rs deleted file mode 100644 index e8ef5fc8..00000000 --- a/crates/system/src/controller/state/lightloop.rs +++ /dev/null @@ -1,49 +0,0 @@ -use super::super::{Environment, Modifications, System}; -use super::{RoomState, State}; -use crate::errors::Error; -use std::time::{Duration, Instant}; - -#[derive(Default, Clone, Copy)] -pub struct LightLoop { - counter: u8, -} - -impl LightLoop { - pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { - dbg!("making everything rdy for the lightloop state"); - - let _ignore_err = sys.lights.set_all_ct(0, 200); - mods.lighting = false; - - sys.update_period = Duration::from_millis(500); - sys.next_update = Instant::now() + sys.update_period; - - Ok(Box::new(Self { counter: 100 })) - } -} - -impl RoomState for LightLoop { - fn update( - &mut self, - mods: &mut Modifications, - sys: &mut System, - _env: &mut Environment, - ) -> Result, Error> { - dbg!("updating lightloop state"); - if self.counter == 0 { - Ok(Some(State::Normal)) - } else { - if !mods.lighting { - let _ignore_err = sys.lights.set_all_ct(self.counter, 200); - self.counter -= 1; - } - Ok(None) - } - } - fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> { - Ok(()) - } - fn state(&self) -> State { - State::LightLoop - } -} diff --git a/crates/system/src/controller/state/mod.rs b/crates/system/src/controller/state/mod.rs deleted file mode 100644 index 79765dc5..00000000 --- a/crates/system/src/controller/state/mod.rs +++ /dev/null @@ -1,38 +0,0 @@ -use super::{Environment, Modifications, System}; -use crate::errors::Error; -use serde::{Deserialize, Serialize}; - -mod lightloop; -mod normal; -mod off; -mod silent; -mod sleep; -mod wakeup; - -pub use lightloop::LightLoop; -pub use normal::Normal; -pub use off::Off; -pub use silent::Silent; -pub use sleep::Sleep; -pub use wakeup::{WakeUp, WakeUpStateError}; - -#[derive(Copy, Clone, Debug, Serialize, Deserialize)] -pub enum State { - Normal, - LightLoop, - WakeUp, - Sleep, - Silent, - Off, -} - -pub trait RoomState { - fn update( - &mut self, - mods: &mut Modifications, - system: &mut System, - env: &mut Environment, - ) -> Result, Error>; - fn breakdown(&self, mods: &mut Modifications, system: &mut System) -> Result<(), Error>; - fn state(&self) -> State; -} diff --git a/crates/system/src/controller/state/normal.rs b/crates/system/src/controller/state/normal.rs deleted file mode 100644 index e4bcfcb5..00000000 --- a/crates/system/src/controller/state/normal.rs +++ /dev/null @@ -1,59 +0,0 @@ -use super::super::{Environment, Modifications, System}; -use super::{RoomState, State}; -use crate::errors::Error; - -use chrono::{Local, NaiveTime}; -use std::time::{Duration, Instant}; - -fn update_lights(sys: &mut System) { - fn hour(h: u8) -> NaiveTime { - NaiveTime::from_hms_opt(h as u32, 0, 0).unwrap() - } - - let now = Local::now(); - if now.time() > hour(22) || now.time() < hour(6) { - let _ignore_err = sys.lights.set_all_ct(220, 500); - } else if now.time() > hour(17) { - let _ignore_err = sys.lights.set_all_ct(254, 320); - } else if now.time() >= hour(6) { - let _ignore_err = sys.lights.set_all_ct(254, 240); - }; -} - -#[derive(Default, Clone, Copy)] -pub struct Normal {} - -impl Normal { - pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { - mods.reset(); - - sys.update_period = Duration::from_secs(5); - sys.next_update = Instant::now() + sys.update_period; - update_lights(sys); - let _ignore_err = sys.lights.all_on(); - - Ok(Box::new(Self::default())) - } -} - -impl RoomState for Normal { - fn update( - &mut self, - mods: &mut Modifications, - sys: &mut System, - _env: &mut Environment, - ) -> Result, Error> { - //dbg!("updating normal state"); - if !mods.lighting { - update_lights(sys) - } - Ok(None) - } - - fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> { - Ok(()) - } - fn state(&self) -> State { - State::Normal - } -} diff --git a/crates/system/src/controller/state/off.rs b/crates/system/src/controller/state/off.rs deleted file mode 100644 index 212177ec..00000000 --- a/crates/system/src/controller/state/off.rs +++ /dev/null @@ -1,34 +0,0 @@ -use super::super::{Environment, Modifications, System}; -use super::{RoomState, State}; -use crate::controller::system::mpd_control as mpd; -use crate::errors::Error; - -#[derive(Clone, Copy)] -pub struct Off {} - -impl Off { - pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { - mods.reset(); - mpd::pause()?; - let _ignore_err = sys.lights.all_off(); - Ok(Box::new(Off {})) - } -} - -impl RoomState for Off { - fn update( - &mut self, - _: &mut Modifications, - _: &mut System, - _env: &mut Environment, - ) -> Result, Error> { - Ok(None) - } - - fn breakdown(&self, _: &mut Modifications, _sys: &mut System) -> Result<(), Error> { - Ok(()) - } - fn state(&self) -> State { - State::Off - } -} diff --git a/crates/system/src/controller/state/silent.rs b/crates/system/src/controller/state/silent.rs deleted file mode 100644 index c1fa01b9..00000000 --- a/crates/system/src/controller/state/silent.rs +++ /dev/null @@ -1,47 +0,0 @@ -use super::super::{Environment, Modifications, System}; -use super::{RoomState, State}; -use crate::controller::system::mpd_control as mpd; -use crate::errors::Error; - -use std::time::{Duration, Instant}; - -#[derive(Clone, Copy)] -pub struct Silent {} - -impl Silent { - pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { - dbg!("entering silent mode"); - mods.reset(); - - sys.update_period = Duration::from_secs(60); - sys.next_update = Instant::now() + sys.update_period; - - mpd::pause()?; - - let _ignore_err = sys.lights.single_off(2); - for lamp_id in &[1, 8, 5, 4, 6] { - let _ignore_err = sys.lights.single_on(*lamp_id); - let _ignore_err = sys.lights.set_ct(*lamp_id, 77, 2000); - } - - Ok(Box::new(Silent {})) - } -} - -impl RoomState for Silent { - fn update( - &mut self, - _: &mut Modifications, - _: &mut System, - _env: &mut Environment, - ) -> Result, Error> { - Ok(None) - } - - fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> { - Ok(()) - } - fn state(&self) -> State { - State::Silent - } -} diff --git a/crates/system/src/controller/state/sleep.rs b/crates/system/src/controller/state/sleep.rs deleted file mode 100644 index 5a4e2e31..00000000 --- a/crates/system/src/controller/state/sleep.rs +++ /dev/null @@ -1,57 +0,0 @@ -use super::super::{Environment, Modifications, System}; -use super::{RoomState, State}; -use crate::controller::system::mpd_control as mpd; -use crate::errors::Error; - -use std::time::{Duration, Instant}; - -#[derive(Clone, Copy)] -pub struct Sleep { - start: Instant, -} - -impl Sleep { - pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { - dbg!("entering sleep mode"); - mods.reset(); - - sys.update_period = Duration::from_secs(60); - sys.next_update = Instant::now() + sys.update_period; - - const RED: (f32, f32, f32) = (1f32, 0f32, 0f32); - let _ignore_err = sys.lights.set_all_rgb(0, RED); - let _ignore_err = sys.lights.all_on(); - - Ok(Box::new(Sleep { - start: Instant::now(), - })) - } -} - -impl RoomState for Sleep { - fn update( - &mut self, - mods: &mut Modifications, - sys: &mut System, - _env: &mut Environment, - ) -> Result, Error> { - const LIGHTS_OFF: Duration = Duration::from_secs(60); - const MUSIC_OFF: Duration = Duration::from_secs(120); - - if self.start.elapsed() >= LIGHTS_OFF && !mods.lighting { - let _ignore_err = sys.lights.all_off(); - } - if self.start.elapsed() >= MUSIC_OFF && !mods.mpd { - mpd::pause()?; - } - - Ok(None) - } - - fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> { - Ok(()) - } - fn state(&self) -> State { - State::LightLoop - } -} diff --git a/crates/system/src/controller/state/wakeup.rs b/crates/system/src/controller/state/wakeup.rs deleted file mode 100644 index ab101360..00000000 --- a/crates/system/src/controller/state/wakeup.rs +++ /dev/null @@ -1,151 +0,0 @@ -use super::super::{Environment, Modifications, System}; -use super::{RoomState, State}; -use crate::controller::system; -use retry::{delay::Fixed, retry}; -use tracing::{error, info}; - -use crate::errors::Error; -use std::time::{Duration, Instant}; - -const UPDATE_PERIOD: u64 = 5; -const WAKEUP_DURATION: u64 = 60 * 15; //in seconds - -const CT_BEGIN: u16 = 500; -const CT_END: u16 = 280; -const CT_PER_SECOND: f32 = ((CT_BEGIN - CT_END) as f32) / (WAKEUP_DURATION as f32); -const BRI_PER_SECOND: f32 = 254. / (WAKEUP_DURATION as f32); //in seconds - -const MUSIC_ON: u64 = 60 * 5; -const MAX_VOLUME: f32 = 20.; -const MIN_VOLUME: f32 = 3.; -const VOL_PER_SECOND: f32 = (MAX_VOLUME - MIN_VOLUME) / (WAKEUP_DURATION - MUSIC_ON) as f32; - -#[derive(thiserror::Error, Debug)] -pub enum WakeUpStateError { - #[error("could not setup playlist even after retries: {0}")] - SetupPlaylist(retry::Error), -} - -#[derive(Clone, Copy)] -pub struct WakeUp { - start: Instant, - playing: bool, -} - -impl WakeUp { - fn setup_playlist() -> Result<(), Error> { - let mpd = &mut retry(Fixed::from_millis(100), || { - mpd::Client::connect("127.0.0.1:6600") - }) - .map_err(WakeUpStateError::SetupPlaylist)?; - - retry(Fixed::from_millis(100).take(3), || { - system::mpd_control::save_current_playlist(mpd) - }) - .map_err(WakeUpStateError::SetupPlaylist)?; - - // note if playlist does not exist we do not - // report an error - retry(Fixed::from_millis(100).take(3), || { - system::mpd_control::add_from_playlist( - mpd, - "calm", - Duration::from_secs(3 * 60), - Duration::from_secs(5 * 60), - ) - }) - .map_err(WakeUpStateError::SetupPlaylist)?; - - retry(Fixed::from_millis(100).take(3), || { - system::mpd_control::add_from_playlist( - mpd, - "energetic", - Duration::from_secs(10 * 60), - Duration::from_secs(11 * 60), - ) - }) - .map_err(WakeUpStateError::SetupPlaylist)?; - - retry(Fixed::from_millis(100).take(3), || { - system::mpd_control::add_from_playlist( - mpd, - "active", - Duration::from_secs(30 * 60), - Duration::from_secs(60 * 60), - ) - }) - .map_err(WakeUpStateError::SetupPlaylist)?; - Ok(()) - } -} - -/* TODO: Hardware backup alarm that triggers if any of this failed - * */ - -impl WakeUp { - pub fn setup(mods: &mut Modifications, sys: &mut System) -> Result, Error> { - info!("starting wakeup state"); - sys.update_period = Duration::from_secs(UPDATE_PERIOD); - sys.next_update = Instant::now() + sys.update_period; - - // reset modifications on entering state - mods.lighting = false; - mods.mpd = false; - - if let Err(e) = Self::setup_playlist() { - error!("could not set up playlist: {}", e); - } - let _ignore_err = sys.lights.set_all_ct(1, CT_BEGIN); - - Ok(Box::new(Self { - start: Instant::now(), - playing: false, - })) - } -} - -impl RoomState for WakeUp { - fn update( - &mut self, - mods: &mut Modifications, - sys: &mut System, - _env: &mut Environment, - ) -> Result, Error> { - let elapsed = self.start.elapsed().as_secs(); - - if elapsed > WAKEUP_DURATION { - return Ok(Some(State::Normal)); - } - - // do nothing to the lighting if the user changed it - if !mods.lighting { - let bri = (BRI_PER_SECOND * (elapsed as f32)) as u8; - let ct = CT_BEGIN - (CT_PER_SECOND * (elapsed as f32)) as u16; - let _ignore_err = sys.lights.set_all_ct(bri, ct); - } - - // do nothing to mpd if the user changed an mpd setting - if !mods.mpd { - if !self.playing && elapsed > MUSIC_ON { - let mut client = mpd::Client::connect("127.0.0.1:6600")?; - client.volume(MIN_VOLUME as i8)?; - client.play()?; - self.playing = true; - } else if elapsed > MUSIC_ON { - let since_music_on = elapsed.saturating_sub(MUSIC_ON); - let mut client = mpd::Client::connect("127.0.0.1:6600")?; - let volume = MIN_VOLUME + VOL_PER_SECOND * (since_music_on as f32); - client.volume(volume as i8)?; - } - } - - Ok(None) - } - - fn breakdown(&self, _: &mut Modifications, _: &mut System) -> Result<(), Error> { - Ok(()) - } - fn state(&self) -> State { - State::WakeUp - } -} diff --git a/crates/system/src/controller/system/mod.rs b/crates/system/src/controller/system/mod.rs deleted file mode 100644 index d8fec9b2..00000000 --- a/crates/system/src/controller/system/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod lamps; -pub mod mpd_control; -pub use lamps::Lighting; From f88f552394925d2cb99db70cf4386f3994b80c7a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 27 Apr 2024 10:47:51 +0200 Subject: [PATCH 084/687] adds two rooms to control system --- crates/brain/Cargo.toml | 2 +- crates/brain/src/controller/mod.rs | 28 +- crates/brain/src/controller/rooms.rs | 2 + crates/brain/src/controller/rooms/kitchen.rs | 100 +++++++ .../src/controller/rooms/large_bedroom.rs | 18 +- .../src/controller/rooms/small_bedroom.rs | 101 +++++++ crates/brain/src/input/api.rs | 10 +- crates/brain/src/input/jobs/wakeup.rs | 3 +- crates/brain/src/input/mod.rs | 4 +- crates/brain/src/main.rs | 1 - crates/brain/src/system.rs | 8 +- crates/protocol/Cargo.lock | 264 ++++++++++++++++++ crates/protocol/Cargo.toml | 1 - crates/protocol/src/large_bedroom.rs | 68 +++++ crates/protocol/src/lib.rs | 40 +-- 15 files changed, 589 insertions(+), 61 deletions(-) create mode 100644 crates/brain/src/controller/rooms/kitchen.rs create mode 100644 crates/brain/src/controller/rooms/small_bedroom.rs create mode 100644 crates/protocol/Cargo.lock diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 6cd2ecdf..b5d30a2b 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -16,7 +16,7 @@ sensors_connected = [] live_server = [] [dependencies] -protocol = { path = "../protocol" } +protocol = { path = "../protocol", features = ["alloc"] } futures = "0.3" tokio = { version = "1", features = ["full"] } diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index a25896f6..bd317b8a 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -27,7 +27,7 @@ pub fn start(event_tx: broadcast::Sender, system: System) -> JoinSet<()> let mut tasks = JoinSet::new(); let restricted = RestrictedSystem { - system, + system: system.clone(), allowed_lights: vec![ "large_bedroom:cabinet", "large_bedroom:ceiling", @@ -35,6 +35,32 @@ pub fn start(event_tx: broadcast::Sender, system: System) -> JoinSet<()> ], }; tasks.spawn(rooms::large_bedroom::run( + event_tx.clone().subscribe(), + event_tx.clone(), + restricted, + )); + + let restricted = RestrictedSystem { + system: system.clone(), + allowed_lights: vec![ + "small_bedroom:ceiling", + ], + }; + tasks.spawn(rooms::small_bedroom::run( + event_tx.clone().subscribe(), + event_tx.clone(), + restricted, + )); + + let restricted = RestrictedSystem { + system: system.clone(), + allowed_lights: vec![ + "kitchen:ceiling", + "kitchen:hood_left", + "kitchen:hood_right", + ], + }; + tasks.spawn(rooms::kitchen::run( event_tx.subscribe(), event_tx, restricted, diff --git a/crates/brain/src/controller/rooms.rs b/crates/brain/src/controller/rooms.rs index e47ef5f4..b45791b7 100644 --- a/crates/brain/src/controller/rooms.rs +++ b/crates/brain/src/controller/rooms.rs @@ -1 +1,3 @@ pub mod large_bedroom; +pub mod small_bedroom; +pub mod kitchen; diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs new file mode 100644 index 00000000..7aa19659 --- /dev/null +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -0,0 +1,100 @@ +use std::time::Duration; + +use futures_concurrency::future::Race; +use futures_util::FutureExt; +use time::OffsetDateTime; +use tokio::sync::broadcast; +use tokio::time::{sleep_until, Instant}; +use tracing::warn; + +use crate::controller::{Event, RestrictedSystem}; + +enum State { + // Sleep, + // Wakeup, + Normal, + // Away, +} + +const INTERVAL: Duration = Duration::from_secs(5); + +trait RecvFiltered { + async fn recv_filter_mapped(&mut self, filter_map: impl Fn(Event) -> Option) -> T; +} + +impl RecvFiltered for broadcast::Receiver { + async fn recv_filter_mapped(&mut self, filter_map: impl Fn(Event) -> Option) -> T { + loop { + let event = self.recv().await.unwrap(); + if let Some(relevant) = filter_map(event) { + return relevant; + } + } + } +} + +#[derive(Debug)] +enum RelevantEvent { + DeskButton(protocol::large_bedroom::DeskButton), +} + +fn filter(event: Event) -> Option { + match event { + // Event::Sensor(SensorValue::ButtonPress(Button::LargeBedroomDesk(desk))) => { + // Some(RelevantEvent::DeskButton(desk)) + // } + _ => None, + } +} + +pub async fn run( + mut event_rx: broadcast::Receiver, + // todo if state change message everyone using this + event_tx: broadcast::Sender, + mut system: RestrictedSystem, +) { + enum Res { + Event(RelevantEvent), + ShouldUpdate, + } + + let state = State::Normal; + let mut next_update = Instant::now() + INTERVAL; + loop { + let get_event = event_rx.recv_filter_mapped(filter).map(Res::Event); + let tick = sleep_until(next_update).map(|_| Res::ShouldUpdate); + + let res = (get_event, tick).race().await; + match res { + Res::Event(e) => handle_event(e), + Res::ShouldUpdate => { + update(&mut system); + next_update = Instant::now() + INTERVAL; + } + } + } +} + +fn update(system: &mut RestrictedSystem) { + let (new_ct, new_bri) = optimal_ct_bri(); + system.all_lamps_ct(new_ct, new_bri); +} + +fn optimal_ct_bri() -> (u16, u8) { + let now = OffsetDateTime::now_local().expect("Timezone not found"); + match now.hour() { + 0..=5 | 22.. => (500, 220), + 17..=21 => (320, u8::MAX), + 6..=16 => (254, u8::MAX), + } +} + +fn handle_event(e: RelevantEvent) { + use protocol::large_bedroom::DeskButton as D; + use RelevantEvent as R; + + match e { + R::DeskButton(D::OneOfFour(p)) if p.is_long() => todo!(), + unhandled => warn!("Unhandled button: {unhandled:?}"), + } +} diff --git a/crates/brain/src/controller/rooms/large_bedroom.rs b/crates/brain/src/controller/rooms/large_bedroom.rs index e2f6fc54..80503c92 100644 --- a/crates/brain/src/controller/rooms/large_bedroom.rs +++ b/crates/brain/src/controller/rooms/large_bedroom.rs @@ -2,20 +2,18 @@ use std::time::Duration; use futures_concurrency::future::Race; use futures_util::FutureExt; -use protocol::{Button, SensorValue}; use time::OffsetDateTime; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; use tracing::warn; use crate::controller::{Event, RestrictedSystem}; -use crate::system::System; enum State { - Sleep, - Wakeup, + // Sleep, + // Wakeup, Normal, - Away, + // Away, } const INTERVAL: Duration = Duration::from_secs(5); @@ -42,9 +40,9 @@ enum RelevantEvent { fn filter(event: Event) -> Option { match event { - Event::Sensor(SensorValue::ButtonPress(Button::LargeBedroomDesk(desk))) => { - Some(RelevantEvent::DeskButton(desk)) - } + // Event::Sensor(SensorValue::ButtonPress(Button::LargeBedroomDesk(desk))) => { + // Some(RelevantEvent::DeskButton(desk)) + // } _ => None, } } @@ -52,7 +50,7 @@ fn filter(event: Event) -> Option { pub async fn run( mut event_rx: broadcast::Receiver, // todo if state change message everyone using this - event_tx: broadcast::Sender, + _event_tx: broadcast::Sender, mut system: RestrictedSystem, ) { enum Res { @@ -60,7 +58,7 @@ pub async fn run( ShouldUpdate, } - let state = State::Normal; + let _state = State::Normal; let mut next_update = Instant::now() + INTERVAL; loop { let get_event = event_rx.recv_filter_mapped(filter).map(Res::Event); diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs new file mode 100644 index 00000000..9723588e --- /dev/null +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -0,0 +1,101 @@ +use std::time::Duration; + +use futures_concurrency::future::Race; +use futures_util::FutureExt; +use time::OffsetDateTime; +use tokio::sync::broadcast; +use tokio::time::{sleep_until, Instant}; +use tracing::warn; + +use crate::controller::{Event, RestrictedSystem}; + +enum State { + Sleep, + Wakeup, + Normal, + Away, +} + +const INTERVAL: Duration = Duration::from_secs(5); + +trait RecvFiltered { + async fn recv_filter_mapped(&mut self, filter_map: impl Fn(Event) -> Option) -> T; +} + +impl RecvFiltered for broadcast::Receiver { + async fn recv_filter_mapped(&mut self, filter_map: impl Fn(Event) -> Option) -> T { + loop { + let event = self.recv().await.unwrap(); + if let Some(relevant) = filter_map(event) { + return relevant; + } + } + } +} + +#[derive(Debug)] +enum RelevantEvent { + DeskButton(protocol::large_bedroom::DeskButton), +} + +fn filter(event: Event) -> Option { + match event { + // Event::Sensor(SensorValue::ButtonPress(Button::LargeBedroomDesk(desk))) => { + // Some(RelevantEvent::DeskButton(desk)) + // } + _ => None, + } +} + +pub async fn run( + mut event_rx: broadcast::Receiver, + // todo if state change message everyone using this + event_tx: broadcast::Sender, + mut system: RestrictedSystem, +) { + enum Res { + Event(RelevantEvent), + ShouldUpdate, + } + + let state = State::Normal; + let mut next_update = Instant::now() + INTERVAL; + loop { + let get_event = event_rx.recv_filter_mapped(filter).map(Res::Event); + let tick = sleep_until(next_update).map(|_| Res::ShouldUpdate); + + let res = (get_event, tick).race().await; + match res { + Res::Event(e) => handle_event(e), + Res::ShouldUpdate => { + update(&mut system); + next_update = Instant::now() + INTERVAL; + } + } + } +} + +fn update(system: &mut RestrictedSystem) { + let (new_ct, new_bri) = optimal_ct_bri(); + system.all_lamps_ct(new_ct, new_bri); +} + +fn optimal_ct_bri() -> (u16, u8) { + let now = OffsetDateTime::now_local().expect("Timezone not found"); + match now.hour() { + 0..=8 | 22.. => (500, 180), + 9..=16 => (270, u8::MAX), + 17..=19 => (300, u8::MAX), + 20..=21 => (400, 220), + } +} + +fn handle_event(e: RelevantEvent) { + use protocol::large_bedroom::DeskButton as D; + use RelevantEvent as R; + + match e { + R::DeskButton(D::OneOfFour(p)) if p.is_long() => todo!(), + unhandled => warn!("Unhandled button: {unhandled:?}"), + } +} diff --git a/crates/brain/src/input/api.rs b/crates/brain/src/input/api.rs index a2a74cec..3750c504 100644 --- a/crates/brain/src/input/api.rs +++ b/crates/brain/src/input/api.rs @@ -61,14 +61,18 @@ async fn set_tomorrow(aState(state): aState, body: Bytes) -> StatusCode { } async fn sensor_event(aState(state): aState, body: Bytes) { - let value = match protocol::SensorValue::decode(&body[..]) { - Ok(value) => value, + let mut bytes = body[..].to_vec(); + let msg: protocol::SensorMessage<20> = match protocol::SensorMessage::decode(&mut bytes) { + Ok(msg) => msg, Err(e) => { warn!("Failed to decode received body: {e}"); return; } }; - state.event_tx.send(Event::Sensor(value)).unwrap(); + // in future convert from older protocol here + for value in msg.values { + state.event_tx.send(Event::Sensor(value)).unwrap(); + } } #[derive(Clone)] diff --git a/crates/brain/src/input/jobs/wakeup.rs b/crates/brain/src/input/jobs/wakeup.rs index bc957cd6..c1e67811 100644 --- a/crates/brain/src/input/jobs/wakeup.rs +++ b/crates/brain/src/input/jobs/wakeup.rs @@ -1,5 +1,4 @@ -use super::{Action, Job, Jobs}; -use crate::controller::Event; +use super::{Job, Jobs}; use chrono::{DateTime, Local, Timelike, Utc}; use tokio::runtime::Runtime; use tracing::info; diff --git a/crates/brain/src/input/mod.rs b/crates/brain/src/input/mod.rs index 729474cc..e2b5e971 100644 --- a/crates/brain/src/input/mod.rs +++ b/crates/brain/src/input/mod.rs @@ -1,4 +1,4 @@ pub mod jobs; pub mod api; -pub mod mpd_status; -pub use mpd_status::MpdStatus; +// pub mod mpd_status; +// pub use mpd_status::MpdStatus; diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index a44092c9..c3d9a78b 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -1,7 +1,6 @@ use std::net::IpAddr; use clap::Parser; -use input::jobs::Jobs; use sled; use tokio::sync::broadcast; use tracing::warn; diff --git a/crates/brain/src/system.rs b/crates/brain/src/system.rs index 59ffe0bf..d72f7634 100644 --- a/crates/brain/src/system.rs +++ b/crates/brain/src/system.rs @@ -1,8 +1,8 @@ pub mod lamps; -pub mod mpd_control; +// pub mod mpd_control; pub use lamps::Lighting; -pub use mpd_control::Mpd; +// pub use mpd_control::Mpd; use crate::input::jobs::Jobs; @@ -10,7 +10,7 @@ use crate::input::jobs::Jobs; pub struct System { pub jobs: Jobs, pub lights: Lighting, - pub mpd: Mpd, + // pub mpd: Mpd, } impl System { @@ -18,7 +18,7 @@ impl System { Self { jobs, lights: Lighting::start_init(), - mpd: Mpd, + // mpd: Mpd, } } } diff --git a/crates/protocol/Cargo.lock b/crates/protocol/Cargo.lock new file mode 100644 index 00000000..7096c465 --- /dev/null +++ b/crates/protocol/Cargo.lock @@ -0,0 +1,264 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "autocfg" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + +[[package]] +name = "const_format" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version", + "serde", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32 0.3.1", + "serde", + "stable_deref_trait", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "postcard" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +dependencies = [ + "cobs", + "const_format", + "embedded-io", + "heapless 0.7.17", + "postcard-derive", + "serde", +] + +[[package]] +name = "postcard-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4b01218787dd4420daf63875163a787a78294ad48a24e9f6fa8c6507759a79" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "proc-macro2" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "protocol" +version = "0.1.0" +dependencies = [ + "heapless 0.8.0", + "postcard", + "serde", + "strum", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + +[[package]] +name = "serde" +version = "1.0.198" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.198" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strum" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index 7eb58e7e..1d55aeea 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -15,5 +15,4 @@ heapless = { version = "0.8.0", features = ["serde"] } strum = { version = "0.26.2", default-features = false } [features] -default = ["alloc"] alloc = ["postcard/alloc", "serde/std"] diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index b4529bf4..64353911 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -1,3 +1,6 @@ +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + use crate::button_enum; // No these are not borg, these are buttons on a string of cat5. @@ -13,3 +16,68 @@ button_enum! { ThirdOfThree, } } + +// No these are not borg, these are buttons on a string of cat5. +// They are numbered starting at the farthest from the end +button_enum! { + BedButton { + OneOfFour, + TwoOfFour, + ThreeOfFour, + FourOfFour, + OneOfThree, + TwoOfThree, + ThirdOfThree, + } +} + +#[derive( + Clone, + Copy, + Debug, + Serialize, + Deserialize, + PartialEq, + Eq, + MaxSize, +)] +pub enum LargeBedroom { + Bed(Bed), + Desk(Desk), +} + +#[derive( + Clone, + Copy, + Debug, + Serialize, + Deserialize, + PartialEq, + Eq, + MaxSize, +)] +pub enum Desk { + Button(DeskButton), +} + +#[derive( + Clone, + Copy, + Debug, + Serialize, + Deserialize, + PartialEq, + Eq, + MaxSize, +)] +pub enum Bed { + /// lux divided by 100 + Brightness(u32), + /// celsius divided by 100 + Temperature(u16), + /// relative percentage divided by 100 + Humidity(u16), + /// parts per million + Co2(u16), + Button, +} diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 9a73241d..0ffea5bd 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -1,4 +1,4 @@ -#[cfg_attr(not(feature = "alloc"), no_std)] +#![cfg_attr(not(feature = "alloc"), no_std)] pub mod large_bedroom; use postcard::experimental::max_size::MaxSize as _; @@ -67,28 +67,6 @@ impl Press { } } -#[derive( - Clone, - Copy, - Debug, - Serialize, - Deserialize, - PartialEq, - Eq, - postcard::experimental::max_size::MaxSize, -)] -pub enum Button { - LargeBedroomDesk(large_bedroom::DeskButton), -} - -impl Button { - pub fn press(&self) -> Press { - match self { - Button::LargeBedroomDesk(b) => b.press(), - } - } -} - #[derive( Clone, Copy, @@ -100,22 +78,12 @@ impl Button { postcard::experimental::max_size::MaxSize, )] pub enum SensorValue { - ButtonPress(Button), + LargeBedroom(large_bedroom::LargeBedroom), #[cfg(test)] Test, } impl SensorValue { - // #[cfg(feature = "alloc")] - // pub fn encode(&self) -> Vec { - // postcard::to_allocvec(self).expect("Encoding should not fail") - // } - // // todo encode for on an embedded sys - // - // pub fn decode(bytes: impl AsRef<[u8]>) -> Result { - // postcard::from_bytes(bytes.as_ref()) - // } - // pub fn version() -> u8 { 0u8 } @@ -123,8 +91,8 @@ impl SensorValue { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SensorMessage { - values: heapless::Vec, - version: u8, + pub values: heapless::Vec, + pub version: u8, } impl SensorMessage { From db2cac596bd418ca5196931635e9d15edf33046d Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 1 May 2024 12:17:01 +0200 Subject: [PATCH 085/687] adds Errors to Sensor enum and provides functions to make those errors ergonomic --- crates/protocol/Cargo.toml | 13 +++- crates/protocol/src/extended_errors.rs | 84 ++++++++++++++++++++++ crates/protocol/src/large_bedroom.rs | 98 +++++++++++--------------- crates/protocol/src/lib.rs | 97 +++++++++++++------------ crates/protocol/src/small_bedroom.rs | 23 ++++++ 5 files changed, 213 insertions(+), 102 deletions(-) create mode 100644 crates/protocol/src/extended_errors.rs create mode 100644 crates/protocol/src/small_bedroom.rs diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index 1d55aeea..e52a6114 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -13,6 +13,17 @@ serde = { version = "1.0", features = ["derive"], default-features = false } postcard = { version = "1.0", features = ["experimental-derive"] } heapless = { version = "0.8.0", features = ["serde"] } strum = { version = "0.26.2", default-features = false } +thiserror = { version = "1.0", optional = true } +defmt = "0.3.6" + +# sensors, we need these to be able to display/receive their errors +sht31 = { version = "0.3.0", git = "https://github.com/dvdsk/SHT31-rs", features = ["serde", "postcard"]} +bosch-bme680 = { version = "1.0.2", git = "https://github.com/dvdsk/async-bosch-bme680", features = ["serde", "postcard"] } +max44009 = { version = "0.2", git = "https://github.com/dvdsk/max44009-rs", features = ["serde", "postcard"] } + +# needed for bme680 error I2C type +embassy-stm32 = { version = "0.1.0", features = ["stm32f401cc"] } +embassy-embedded-hal = "0.1.0" [features] -alloc = ["postcard/alloc", "serde/std"] +alloc = ["postcard/alloc", "serde/std", "sht31/thiserror", "bosch-bme680/thiserror"] diff --git a/crates/protocol/src/extended_errors.rs b/crates/protocol/src/extended_errors.rs new file mode 100644 index 00000000..d4ac89b6 --- /dev/null +++ b/crates/protocol/src/extended_errors.rs @@ -0,0 +1,84 @@ +use bosch_bme680::BmeError; +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] +#[cfg_attr(feature = "thiserror", derive(thiserror::Error))] +pub enum I2cError { + #[cfg_attr(feature = "thiserror", error("Bus error"))] + Bus, + #[cfg_attr(feature = "thiserror", error("Arbitration lost"))] + Arbitration, + #[cfg_attr( + feature = "thiserror", + error("ACK not received (either to the address or to a data byte)") + )] + Nack, + #[cfg_attr(feature = "thiserror", error("Timeout"))] + Timeout, + #[cfg_attr(feature = "thiserror", error("CRC error"))] + Crc, + #[cfg_attr(feature = "thiserror", error("Overrun error"))] + Overrun, + #[cfg_attr(feature = "thiserror", error("Zero-length transfers are not allowed"))] + ZeroLengthTransfer, + #[cfg_attr( + feature = "thiserror", + error("Configuration of the inner I2C bus failed.") + )] + Config, +} +impl From> + for I2cError +{ + fn from( + value: embassy_embedded_hal::shared_bus::I2cDeviceError, + ) -> Self { + use embassy_embedded_hal::shared_bus::I2cDeviceError; + use embassy_stm32::i2c::Error; + + match value { + I2cDeviceError::I2c(Error::Bus) => Self::Bus, + I2cDeviceError::I2c(Error::Arbitration) => Self::Arbitration, + I2cDeviceError::I2c(Error::Nack) => Self::Nack, + I2cDeviceError::I2c(Error::Timeout) => Self::Timeout, + I2cDeviceError::I2c(Error::Crc) => Self::Crc, + I2cDeviceError::I2c(Error::Overrun) => Self::Overrun, + I2cDeviceError::I2c(Error::ZeroLengthTransfer) => Self::ZeroLengthTransfer, + I2cDeviceError::Config => Self::Config, + } + } +} + +pub trait ConcreteErrorType { + type Concrete; + fn map_to_concrete(self) -> Self::Concrete; +} + +impl ConcreteErrorType for BmeError +where + E: Into + core::fmt::Debug, +{ + type Concrete = BmeError; + fn map_to_concrete(self) -> Self::Concrete { + match self { + BmeError::WriteError(i2c) => BmeError::WriteError(i2c.into()), + BmeError::WriteReadError(i2c) => BmeError::WriteReadError(i2c.into()), + BmeError::UnexpectedChipId(id) => BmeError::UnexpectedChipId(id), + BmeError::MeasuringTimeOut => BmeError::MeasuringTimeOut, + } + } +} + +impl ConcreteErrorType for max44009::Error +where + E: Into + core::fmt::Debug + defmt::Format, +{ + type Concrete = max44009::Error; + fn map_to_concrete(self) -> Self::Concrete { + match self { + max44009::Error::I2C(i2c) => max44009::Error::I2C(i2c.into()), + max44009::Error::OperationNotAvailable => max44009::Error::OperationNotAvailable, + } + } +} diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index 64353911..ea45a54a 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -2,10 +2,11 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; use crate::button_enum; +use crate::extended_errors::I2cError; -// No these are not borg, these are buttons on a string of cat5. -// They are numbered starting at the farthest from the end button_enum! { + /// No these are not borg, these are buttons on a string of cat5. + /// They are numbered starting at the farthest from the end DeskButton { OneOfFour, TwoOfFour, @@ -17,67 +18,50 @@ button_enum! { } } -// No these are not borg, these are buttons on a string of cat5. -// They are numbered starting at the farthest from the end button_enum! { + /// All button are on the headboard of the bed. As seen from the foot of the + /// bed it looks like this: + /// + /// LR----------------------------| + /// |--------------|--------------| + /// |-----------321|123-----------| + /// |654-----------|-----------456| + /// + /// Legend: + /// L: TopLeft, R: TopRight, 1: MiddleInner, 2: MiddleCenter, 3: MiddleOuter, + /// 4: OuterInner, 5: OuterCenter, 6: OuterOuter BedButton { - OneOfFour, - TwoOfFour, - ThreeOfFour, - FourOfFour, - OneOfThree, - TwoOfThree, - ThirdOfThree, + TopLeft, + TopRight, + MiddleInner, + MiddleCenter, + MiddleOuter, + LowerInner, + LowerCenter, + LowerOuter, } } -#[derive( - Clone, - Copy, - Debug, - Serialize, - Deserialize, - PartialEq, - Eq, - MaxSize, -)] +#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] pub enum LargeBedroom { - Bed(Bed), - Desk(Desk), -} - -#[derive( - Clone, - Copy, - Debug, - Serialize, - Deserialize, - PartialEq, - Eq, - MaxSize, -)] -pub enum Desk { - Button(DeskButton), -} - -#[derive( - Clone, - Copy, - Debug, - Serialize, - Deserialize, - PartialEq, - Eq, - MaxSize, -)] -pub enum Bed { - /// lux divided by 100 - Brightness(u32), - /// celsius divided by 100 - Temperature(u16), - /// relative percentage divided by 100 - Humidity(u16), + Brightness(f32), + Temperature(f32), + Humidity(f32), + GassResistance(f32), // in Ohm + Pressure(f32), /// parts per million Co2(u16), - Button, + /// weight on the left side of the bed + WeightLeft(u32), + /// weight on the right side of the bed + WeightRight(u32), + DeskButton(DeskButton), + BedButton(BedButton), +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] +pub enum Error { + Sht31(sht31::error::SHTError), + Bme680(bosch_bme680::BmeError), + Max44(max44009::Error) } diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 0ffea5bd..96dcc7b9 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -1,9 +1,13 @@ #![cfg_attr(not(feature = "alloc"), no_std)] -pub mod large_bedroom; -use postcard::experimental::max_size::MaxSize as _; +use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; +pub mod large_bedroom; +pub mod small_bedroom; + +pub mod extended_errors; + /// turns an enum of empty variants into one with [`Press`](crate::Press) inside each variant also /// adds a method `press(&self)` that returns an instance of [`Press`](crate::Press). It can be /// used to quickly find out if a button event is a long or short press. @@ -18,17 +22,19 @@ use serde::{Deserialize, Serialize}; /// } /// macro_rules! button_enum { - ($name:ident {$($variant:ident,)*}) => { + ( + $(#[$outer:meta])* + $name:ident {$($variant:ident,)*}) => { #[derive( Clone, Copy, Debug, serde::Serialize, serde::Deserialize, - PartialEq, - Eq, + defmt::Format, postcard::experimental::max_size::MaxSize )] + $(#[$outer])* // docs pub enum $name { $($variant(crate::Press),)* } @@ -51,11 +57,10 @@ pub(crate) use button_enum; Debug, Serialize, Deserialize, - PartialEq, - Eq, postcard::experimental::max_size::MaxSize, + defmt::Format, )] -pub struct Press(u16); +pub struct Press(pub u16); impl Press { pub fn is_long(&self) -> bool { @@ -67,23 +72,16 @@ impl Press { } } -#[derive( - Clone, - Copy, - Debug, - Serialize, - Deserialize, - PartialEq, - Eq, - postcard::experimental::max_size::MaxSize, -)] -pub enum SensorValue { +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] +pub enum Sensor { + LargeBedroomError(large_bedroom::Error), LargeBedroom(large_bedroom::LargeBedroom), + SmallBedroom(small_bedroom::SmallBedroom), #[cfg(test)] Test, } -impl SensorValue { +impl Sensor { pub fn version() -> u8 { 0u8 } @@ -91,7 +89,7 @@ impl SensorValue { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SensorMessage { - pub values: heapless::Vec, + pub values: heapless::Vec, pub version: u8, } @@ -99,7 +97,18 @@ impl SensorMessage { /// the 2x is the max overhead from COBS encoding the encoded data /// +2 is for the version /// +4 covers the length of the heapless list - pub const ENCODED_SIZE: usize = 2 * (MAX_ITEMS * SensorValue::POSTCARD_MAX_SIZE + 2 + 4); + pub const ENCODED_SIZE: usize = 2 * (MAX_ITEMS * Sensor::POSTCARD_MAX_SIZE + 2 + 4); + + pub fn new() -> Self { + Self { + values: heapless::Vec::new(), + version: 0, + } + } + + pub fn space_left(&self) -> bool { + self.values.len() < self.values.capacity() + } #[cfg(feature = "alloc")] pub fn encode(&self) -> Vec { @@ -108,7 +117,7 @@ impl SensorMessage { /// Buffer should be at least Self::ENCODED_SIZE long. The returned slice contains /// the serialized data. It can be shorter then the input buffer. - pub fn encode_slice<'a, const N: usize>(&self, buf: &'a mut [u8]) -> &'a mut [u8] { + pub fn encode_slice<'a>(&self, buf: &'a mut [u8]) -> &'a mut [u8] { postcard::to_slice_cobs(self, buf).expect("Encoding should not fail") } @@ -116,27 +125,27 @@ impl SensorMessage { postcard::from_bytes_cobs(bytes.as_mut()) } - pub fn version() -> u8 { - 0u8 + pub fn version(&self) -> u8 { + self.version } } -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn decode_from_different_max_items() { - let mut values = heapless::Vec::new(); - values.push(SensorValue::Test).unwrap(); - let mut bytes = SensorMessage::<1> { - values: values.clone(), - version: 0u8, - } - .encode(); - - let decoded: SensorMessage<100> = SensorMessage::<100>::decode(&mut bytes).unwrap(); - - assert_eq!(decoded.values.to_vec(), values.to_vec()); - } -} +// #[cfg(test)] +// mod test { +// use super::*; +// +// #[test] +// fn decode_from_different_max_items() { +// let mut values = heapless::Vec::new(); +// values.push(Sensor::Test).unwrap(); +// let mut bytes = SensorMessage::<1> { +// values: values.clone(), +// version: 0u8, +// } +// .encode(); +// +// let decoded: SensorMessage<100> = SensorMessage::<100>::decode(&mut bytes).unwrap(); +// +// assert_eq!(decoded.values.to_vec(), values.to_vec()); +// } +// } diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs new file mode 100644 index 00000000..216dda9e --- /dev/null +++ b/crates/protocol/src/small_bedroom.rs @@ -0,0 +1,23 @@ +use serde::{Deserialize, Serialize}; +use postcard::experimental::max_size::MaxSize; + +crate::button_enum! { + /// +-----------------------------------------+ + /// | TopLeft | TopMiddle | TopRight | + /// +-----------------------------------------+ + /// | BottomLeft | BottomMiddle | BottomRight | + /// +-----------------------------------------+ + ButtonPanel { + TopLeft, + TopMiddle, + TopRight, + BottomLeft, + BottomMiddle, + BOttomRight, + } +} + +#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] +pub enum SmallBedroom { + Desk(ButtonPanel), +} From cd6fc5c94d057eea1e6e6df3fe04cd0ab3e12f06 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 2 May 2024 16:12:27 +0200 Subject: [PATCH 086/687] error remapping fn's now traits --- crates/protocol/src/extended_errors.rs | 7 ++++--- crates/protocol/src/large_bedroom.rs | 18 ++++++++++++++++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/crates/protocol/src/extended_errors.rs b/crates/protocol/src/extended_errors.rs index d4ac89b6..a4041a2b 100644 --- a/crates/protocol/src/extended_errors.rs +++ b/crates/protocol/src/extended_errors.rs @@ -28,6 +28,7 @@ pub enum I2cError { )] Config, } + impl From> for I2cError { @@ -52,7 +53,7 @@ impl From Self::Concrete; + fn strip_generics(self) -> Self::Concrete; } impl ConcreteErrorType for BmeError @@ -60,7 +61,7 @@ where E: Into + core::fmt::Debug, { type Concrete = BmeError; - fn map_to_concrete(self) -> Self::Concrete { + fn strip_generics(self) -> Self::Concrete { match self { BmeError::WriteError(i2c) => BmeError::WriteError(i2c.into()), BmeError::WriteReadError(i2c) => BmeError::WriteReadError(i2c.into()), @@ -75,7 +76,7 @@ where E: Into + core::fmt::Debug + defmt::Format, { type Concrete = max44009::Error; - fn map_to_concrete(self) -> Self::Concrete { + fn strip_generics(self) -> Self::Concrete { match self { max44009::Error::I2C(i2c) => max44009::Error::I2C(i2c.into()), max44009::Error::OperationNotAvailable => max44009::Error::OperationNotAvailable, diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index ea45a54a..ea0b24c5 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -60,8 +60,22 @@ pub enum LargeBedroom { } #[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] -pub enum Error { +pub enum SensorError { Sht31(sht31::error::SHTError), Bme680(bosch_bme680::BmeError), - Max44(max44009::Error) + Max44(max44009::Error), +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] +pub enum Device { + Sht31, + Bme680, + Max44, +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] +pub enum Error { + Running(SensorError), + Setup(SensorError), + SetupTimedOut(Device), } From 6f67fa4551163d5331d06d51bc9ec1ce5b86a9ae Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 24 May 2024 21:17:22 +0200 Subject: [PATCH 087/687] rework protocol and controllers --- .gitignore | 1 + Cargo.lock | 1402 ++++++++++++----- Cargo.toml | 1 - crates/brain/Cargo.toml | 21 +- crates/brain/deploy.sh | 18 - crates/brain/deploy_optimized.sh | 3 - crates/brain/src/controller/mod.rs | 65 +- crates/brain/src/controller/rooms/kitchen.rs | 45 +- .../src/controller/rooms/large_bedroom.rs | 52 +- .../src/controller/rooms/small_bedroom.rs | 41 +- crates/brain/src/input/api.rs | 2 +- crates/brain/src/input/jobs.rs | 50 +- crates/brain/src/input/jobs/wakeup.rs | 40 +- crates/brain/src/main.rs | 15 +- .../lamps/eventually_consistent_bridge.rs | 105 +- crates/brain/src/system/lamps/lamp.rs | 18 + crates/brain/src/system/lamps/mod.rs | 13 +- crates/protocol/Cargo.toml | 12 +- crates/protocol/src/downcast_err.rs | 105 ++ .../i2c.rs} | 63 +- .../protocol/src/downcast_err/rpi_button.rs | 36 + crates/protocol/src/downcast_err/uart.rs | 40 + crates/protocol/src/large_bedroom.rs | 104 +- crates/protocol/src/large_bedroom/bed.rs | 172 ++ crates/protocol/src/large_bedroom/desk.rs | 101 ++ crates/protocol/src/lib.rs | 63 +- deploy.sh | 23 + deploy_optimized.sh | 3 + 28 files changed, 1895 insertions(+), 719 deletions(-) delete mode 100755 crates/brain/deploy.sh delete mode 100755 crates/brain/deploy_optimized.sh create mode 100644 crates/protocol/src/downcast_err.rs rename crates/protocol/src/{extended_errors.rs => downcast_err/i2c.rs} (51%) create mode 100644 crates/protocol/src/downcast_err/rpi_button.rs create mode 100644 crates/protocol/src/downcast_err/uart.rs create mode 100644 crates/protocol/src/large_bedroom/bed.rs create mode 100644 crates/protocol/src/large_bedroom/desk.rs create mode 100755 deploy.sh create mode 100755 deploy_optimized.sh diff --git a/.gitignore b/.gitignore index 4e3fa2e2..e6d2e70d 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,4 @@ userdb.hm ##################### target/ src/input/web_api/logins.rs +database/ diff --git a/Cargo.lock b/Cargo.lock index a2218c3c..aca3fffe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -43,47 +43,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -91,13 +92,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.65", ] [[package]] @@ -115,31 +116,31 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e" +checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", "axum-core", - "bytes 1.5.0", + "bytes 1.6.0", "futures-util", "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-util", - "itoa 1.0.10", + "itoa 1.0.11", "matchit", "memchr", "mime", @@ -150,8 +151,8 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded 0.7.1", - "sync_wrapper", - "tokio 1.36.0", + "sync_wrapper 1.0.1", + "tokio 1.37.0", "tower", "tower-layer", "tower-service", @@ -165,7 +166,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" dependencies = [ "async-trait", - "bytes 1.5.0", + "bytes 1.6.0", "futures-util", "http 1.1.0", "http-body 1.0.0", @@ -173,7 +174,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper", + "sync_wrapper 0.1.2", "tower-layer", "tower-service", "tracing", @@ -185,17 +186,17 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.65", ] [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -206,6 +207,15 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + [[package]] name = "base64" version = "0.10.1" @@ -230,6 +240,24 @@ dependencies = [ "serde", ] +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "bitfield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" + [[package]] name = "bitflags" version = "1.3.2" @@ -238,9 +266,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bitvec" @@ -254,6 +282,66 @@ dependencies = [ "wyz", ] +[[package]] +name = "bme280" +version = "0.5.1" +source = "git+https://github.com/dvdsk/bme280-rs#4999b005d26a16312acb3dbc64b72658df49a16d" +dependencies = [ + "defmt", + "embedded-hal 1.0.0", + "maybe-async-cfg", + "postcard", + "serde", +] + +[[package]] +name = "bosch-bme680" +version = "1.0.2" +source = "git+https://github.com/dvdsk/async-bosch-bme680#455d5d3194f137d9e0403779badc645e1bad7a05" +dependencies = [ + "bitfield 0.14.0", + "defmt", + "embedded-hal 1.0.0", + "embedded-hal-async", + "postcard", + "serde", + "thiserror", +] + +[[package]] +name = "brain" +version = "0.1.0" +dependencies = [ + "axum", + "axum-macros", + "bincode", + "byteorder", + "bytes 1.6.0", + "chrono", + "clap", + "crossbeam-channel", + "futures 0.3.30", + "futures-concurrency", + "futures-util", + "log-panics", + "mpd", + "philipshue", + "protocol", + "rand 0.8.5", + "reqwest 0.11.27", + "serde", + "serde_yaml", + "sled", + "strum", + "thiserror", + "time 0.3.36", + "tokio 1.37.0", + "tracing", + "tracing-journald", + "tracing-subscriber", + "tz-rs", +] + [[package]] name = "bufstream" version = "0.1.4" @@ -262,9 +350,21 @@ checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bxcan" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ac3d0c0a542d0ab5521211f873f62706a7136df415676f676d347e5a41dd80" +dependencies = [ + "bitflags 1.3.2", + "embedded-hal 0.2.7", + "nb 1.1.0", + "vcell", +] [[package]] name = "byteorder" @@ -285,15 +385,21 @@ dependencies = [ [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cast" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.90" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" [[package]] name = "cfg-if" @@ -307,11 +413,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "chrono" -version = "0.4.35" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", @@ -319,14 +431,14 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] name = "clap" -version = "4.5.2" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", @@ -346,14 +458,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.65", ] [[package]] @@ -379,9 +491,15 @@ checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "const_fn" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "373e9fafaa20882876db20562275ff58d50e0caa2590077fe7ce7bef90211d0d" [[package]] name = "const_format" @@ -447,11 +565,58 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal", + "bitfield 0.13.2", + "embedded-hal 0.2.7", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if 1.0.0", ] @@ -464,11 +629,11 @@ checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" [[package]] name = "crossbeam-channel" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ - "crossbeam-utils 0.8.19", + "crossbeam-utils 0.8.20", ] [[package]] @@ -488,7 +653,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", "cfg-if 0.1.10", "crossbeam-utils 0.7.2", "lazy_static", @@ -503,7 +668,7 @@ version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "crossbeam-utils 0.8.19", + "crossbeam-utils 0.8.20", ] [[package]] @@ -523,16 +688,16 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", "cfg-if 0.1.10", "lazy_static", ] [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "ct-logs" @@ -543,6 +708,38 @@ dependencies = [ "sct 0.6.1", ] +[[package]] +name = "defmt" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb" +dependencies = [ + "defmt-parser", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "defmt-parser" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" +dependencies = [ + "thiserror", +] + [[package]] name = "deranged" version = "0.3.11" @@ -552,6 +749,15 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "document-features" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +dependencies = [ + "litrs", +] + [[package]] name = "dtoa" version = "0.4.8" @@ -560,9 +766,178 @@ checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" [[package]] name = "either" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" + +[[package]] +name = "embassy-embedded-hal" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca4a9380d03e61063067b8239f67d2fa9f108ede7c46b4273804f6b79e59a1d" +dependencies = [ + "embassy-futures", + "embassy-sync", + "embassy-time", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-storage", + "embedded-storage-async", + "nb 1.1.0", +] + +[[package]] +name = "embassy-futures" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f878075b9794c1e4ac788c95b728f26aa6366d32eeb10c7051389f898f7d067" + +[[package]] +name = "embassy-hal-internal" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0ec47cf8bab914018d4bd2b4f0aaeb46e4f52ab1e7985df88aeef2c6eda5aed" +dependencies = [ + "cortex-m", + "critical-section", + "num-traits", +] + +[[package]] +name = "embassy-net-driver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d" + +[[package]] +name = "embassy-stm32" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32bc0257b5ade13a1b93e8b9949268f44d57e8ce03e599ef1c5a62024a0fbff9" +dependencies = [ + "bit_field", + "bxcan", + "cfg-if 1.0.0", + "cortex-m", + "cortex-m-rt", + "critical-section", + "document-features", + "embassy-embedded-hal", + "embassy-futures", + "embassy-hal-internal", + "embassy-net-driver", + "embassy-sync", + "embassy-usb-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-nb", + "embedded-io 0.6.1", + "embedded-io-async", + "embedded-storage", + "embedded-storage-async", + "futures 0.3.30", + "nb 1.1.0", + "proc-macro2", + "quote", + "rand_core 0.6.4", + "sdio-host", + "stm32-fmc", + "stm32-metapac", + "vcell", +] + +[[package]] +name = "embassy-sync" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd938f25c0798db4280fcd8026bf4c2f48789aebf8f77b6e5cf8a7693ba114ec" +dependencies = [ + "cfg-if 1.0.0", + "critical-section", + "embedded-io-async", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c844070d9f80dc66ee739299183312baee2e1cdeb6e90b4ea2af44f4676da5" +dependencies = [ + "cfg-if 1.0.0", + "critical-section", + "document-features", + "embassy-time-driver", + "embassy-time-queue-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time-driver" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e0c214077aaa9206958b16411c157961fb7990d4ea628120a78d1a5a28aed24" +dependencies = [ + "document-features", +] + +[[package]] +name = "embassy-time-queue-driver" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1177859559ebf42cd24ae7ba8fe6ee707489b01d0bf471f8827b7b12dcb0bc0" + +[[package]] +name = "embassy-usb-driver" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fc247028eae04174b6635104a35b1ed336aabef4654f5e87a8f32327d231970" + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "defmt", + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" +dependencies = [ + "embedded-hal 1.0.0", + "nb 1.1.0", +] [[package]] name = "embedded-io" @@ -570,11 +945,45 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-io-async" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" +dependencies = [ + "defmt", + "embedded-io 0.6.1", +] + +[[package]] +name = "embedded-storage" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" + +[[package]] +name = "embedded-storage-async" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc" +dependencies = [ + "embedded-storage", +] + [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if 1.0.0", ] @@ -616,11 +1025,20 @@ dependencies = [ "synstructure", ] +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "miniz_oxide", @@ -712,15 +1130,16 @@ dependencies = [ [[package]] name = "futures-concurrency" -version = "7.5.0" +version = "7.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b590a729e1cbaf9ae3ec294143ea034d93cbb1de01c884d04bcd0af8b613d02" +checksum = "51ee14e256b9143bfafbf2fddeede6f396650bacf95d06fc1b3f2b503df129a0" dependencies = [ "bitvec", "futures-core", + "futures-lite", "pin-project", "slab", - "smallvec 1.13.1", + "smallvec 1.13.2", ] [[package]] @@ -756,6 +1175,21 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + [[package]] name = "futures-macro" version = "0.3.30" @@ -764,7 +1198,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.65", ] [[package]] @@ -808,9 +1242,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if 1.0.0", "libc", @@ -843,77 +1277,23 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ - "bytes 1.5.0", + "bytes 1.6.0", "fnv", "futures-core", "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.2.5", + "indexmap 2.2.6", "slab", - "tokio 1.36.0", + "tokio 1.37.0", "tokio-util", "tracing", ] -[[package]] -name = "h2" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943" -dependencies = [ - "bytes 1.5.0", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 1.1.0", - "indexmap 2.2.5", - "slab", - "tokio 1.36.0", - "tokio-util", - "tracing", -] - -[[package]] -name = "ha" -version = "0.1.0" -dependencies = [ - "axum", - "axum-macros", - "bincode", - "byteorder", - "bytes 1.5.0", - "chrono", - "clap", - "crossbeam-channel", - "futures 0.3.30", - "futures-concurrency", - "futures-util", - "log-panics", - "mpd", - "num", - "philipshue", - "protocol", - "rand 0.8.5", - "reqwest 0.11.25", - "retry", - "serde", - "serde_yaml", - "sled", - "strum", - "thiserror", - "time 0.3.36", - "tokio 1.36.0", - "tracing", - "tracing-journald", - "tracing-subscriber", -] - [[package]] name = "hash32" version = "0.2.1" @@ -940,9 +1320,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "heapless" @@ -975,6 +1355,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -998,9 +1384,9 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "bytes 1.5.0", + "bytes 1.6.0", "fnv", - "itoa 1.0.10", + "itoa 1.0.11", ] [[package]] @@ -1009,9 +1395,9 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ - "bytes 1.5.0", + "bytes 1.6.0", "fnv", - "itoa 1.0.10", + "itoa 1.0.11", ] [[package]] @@ -1032,7 +1418,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ - "bytes 1.5.0", + "bytes 1.6.0", "http 0.2.12", "pin-project-lite", ] @@ -1043,7 +1429,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ - "bytes 1.5.0", + "bytes 1.6.0", "http 1.1.0", ] @@ -1053,7 +1439,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" dependencies = [ - "bytes 1.5.0", + "bytes 1.6.0", "futures-core", "http 1.1.0", "http-body 1.0.0", @@ -1108,19 +1494,19 @@ version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ - "bytes 1.5.0", + "bytes 1.6.0", "futures-channel", "futures-core", "futures-util", - "h2 0.3.24", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "httparse", "httpdate", - "itoa 1.0.10", + "itoa 1.0.11", "pin-project-lite", "socket2", - "tokio 1.36.0", + "tokio 1.37.0", "tower-service", "tracing", "want 0.3.1", @@ -1128,22 +1514,21 @@ dependencies = [ [[package]] name = "hyper" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ - "bytes 1.5.0", + "bytes 1.6.0", "futures-channel", "futures-util", - "h2 0.4.2", "http 1.1.0", "http-body 1.0.0", "httparse", "httpdate", - "itoa 1.0.10", + "itoa 1.0.11", "pin-project-lite", - "smallvec 1.13.1", - "tokio 1.36.0", + "smallvec 1.13.2", + "tokio 1.37.0", ] [[package]] @@ -1172,8 +1557,8 @@ dependencies = [ "futures-util", "http 0.2.12", "hyper 0.14.28", - "rustls 0.21.10", - "tokio 1.36.0", + "rustls 0.21.12", + "tokio 1.37.0", "tokio-rustls 0.24.1", ] @@ -1183,14 +1568,26 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" dependencies = [ - "bytes 1.5.0", + "bytes 1.6.0", "futures-util", "http 1.1.0", "http-body 1.0.0", - "hyper 1.2.0", + "hyper 1.3.1", "pin-project-lite", "socket2", - "tokio 1.36.0", + "tokio 1.37.0", +] + +[[package]] +name = "i2cdev" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597f56d08cebc0fb3e67d49f48124f49e1c7ac297a21d60bc90a28b9482fb35c" +dependencies = [ + "bitflags 2.5.0", + "byteorder", + "libc", + "nix 0.26.4", ] [[package]] @@ -1254,27 +1651,37 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", "hashbrown 0.12.3", ] [[package]] name = "indexmap" -version = "2.2.5" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "io-kit-sys" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b" dependencies = [ - "cfg-if 1.0.0", + "core-foundation-sys", + "mach2", ] [[package]] @@ -1292,6 +1699,12 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itoa" version = "0.4.8" @@ -1300,9 +1713,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" @@ -1331,9 +1744,30 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "linux-embedded-hal" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d566b726e1b6810f66c6f1c769889248439c27f06a59df2881a735454cfa02" +dependencies = [ + "cast", + "embedded-hal 1.0.0", + "embedded-hal-nb", + "i2cdev", + "nb 1.1.0", + "nix 0.27.1", + "serialport", +] + +[[package]] +name = "litrs" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" [[package]] name = "lock_api" @@ -1346,11 +1780,11 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", "scopeguard", ] @@ -1369,6 +1803,15 @@ dependencies = [ "log", ] +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + [[package]] name = "matchers" version = "0.1.0" @@ -1390,6 +1833,31 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +[[package]] +name = "max44009" +version = "0.2.0" +source = "git+https://github.com/dvdsk/max44009-rs#7b7df2e3173476c250fca3eb242f0dd366857599" +dependencies = [ + "defmt", + "embedded-hal-async", + "postcard", + "serde", + "thiserror", +] + +[[package]] +name = "maybe-async-cfg" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21fb8fac02158b9b529eb692491895d8459dbac939f3bc6e32159969646ffe55" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "pulldown-cmark", + "quote", + "syn 1.0.109", +] + [[package]] name = "maybe-uninit" version = "2.0.0" @@ -1398,9 +1866,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "memoffset" @@ -1408,7 +1876,20 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", +] + +[[package]] +name = "mhzx" +version = "0.3.0" +source = "git+https://github.com/dvdsk/mhzx#08f6e7adb4ec98749fa84f24f8ff9e0e3c83d164" +dependencies = [ + "defmt", + "embedded-io-async", + "heapless 0.8.0", + "postcard", + "serde", + "thiserror", ] [[package]] @@ -1429,9 +1910,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] @@ -1487,6 +1968,21 @@ dependencies = [ "bufstream", ] +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + [[package]] name = "net2" version = "0.2.39" @@ -1499,47 +1995,47 @@ dependencies = [ ] [[package]] -name = "nu-ansi-term" -version = "0.46.0" +name = "nix" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ - "overload", - "winapi 0.3.9", + "bitflags 1.3.2", + "cfg-if 1.0.0", + "libc", ] [[package]] -name = "num" -version = "0.4.1" +name = "nix" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", + "bitflags 2.5.0", + "cfg-if 1.0.0", + "libc", ] [[package]] -name = "num-bigint" -version = "0.4.4" +name = "nix" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ - "autocfg 1.1.0", - "num-integer", - "num-traits", + "bitflags 2.5.0", + "cfg-if 1.0.0", + "cfg_aliases", + "libc", ] [[package]] -name = "num-complex" -version = "0.4.5" +name = "nu-ansi-term" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ - "num-traits", + "overload", + "winapi 0.3.9", ] [[package]] @@ -1548,45 +2044,13 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" -dependencies = [ - "autocfg 1.1.0", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg 1.1.0", - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", ] [[package]] @@ -1599,15 +2063,6 @@ dependencies = [ "libc", ] -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - [[package]] name = "object" version = "0.32.2" @@ -1629,6 +2084,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + [[package]] name = "parking_lot" version = "0.9.0" @@ -1647,18 +2108,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", - "lock_api 0.4.11", + "lock_api 0.4.12", "parking_lot_core 0.8.6", ] [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" dependencies = [ - "lock_api 0.4.11", - "parking_lot_core 0.9.9", + "lock_api 0.4.12", + "parking_lot_core 0.9.10", ] [[package]] @@ -1686,21 +2147,21 @@ dependencies = [ "instant", "libc", "redox_syscall 0.2.16", - "smallvec 1.13.1", + "smallvec 1.13.2", "winapi 0.3.9", ] [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.4.1", - "smallvec 1.13.1", - "windows-targets 0.48.5", + "redox_syscall 0.5.1", + "smallvec 1.13.2", + "windows-targets 0.52.5", ] [[package]] @@ -1744,14 +2205,14 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.65", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -1767,7 +2228,7 @@ checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" dependencies = [ "cobs", "const_format", - "embedded-io", + "embedded-io 0.4.0", "heapless 0.7.17", "postcard-derive", "serde", @@ -1796,11 +2257,35 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" dependencies = [ "unicode-ident", ] @@ -1809,10 +2294,23 @@ dependencies = [ name = "protocol" version = "0.1.0" dependencies = [ + "bme280", + "bosch-bme680", + "defmt", + "embassy-embedded-hal", + "embassy-stm32", + "embedded-hal 1.0.0", "heapless 0.8.0", + "linux-embedded-hal", + "max44009", + "mhzx", + "nix 0.28.0", "postcard", "serde", + "sht31", + "sps30-async", "strum", + "thiserror", ] [[package]] @@ -1825,11 +2323,22 @@ dependencies = [ "url 2.5.0", ] +[[package]] +name = "pulldown-cmark" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" +dependencies = [ + "bitflags 2.5.0", + "memchr", + "unicase", +] + [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -2002,23 +2511,23 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", ] [[package]] name = "regex" -version = "1.10.3" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", "regex-automata 0.4.6", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -2038,7 +2547,7 @@ checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -2049,9 +2558,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" @@ -2091,16 +2600,16 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.25" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eea5a9eb898d3783f17c6407670e3592fd174cb81a10e51d4c37f49450b9946" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64 0.21.7", - "bytes 1.5.0", + "bytes 1.6.0", "encoding_rs", "futures-core", "futures-util", - "h2 0.3.24", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.28", @@ -2112,14 +2621,14 @@ dependencies = [ "once_cell", "percent-encoding 2.3.1", "pin-project-lite", - "rustls 0.21.10", + "rustls 0.21.12", "rustls-pemfile", "serde", "serde_json", "serde_urlencoded 0.7.1", - "sync_wrapper", + "sync_wrapper 0.1.2", "system-configuration", - "tokio 1.36.0", + "tokio 1.37.0", "tokio-rustls 0.24.1", "tower-service", "url 2.5.0", @@ -2130,15 +2639,6 @@ dependencies = [ "winreg 0.50.0", ] -[[package]] -name = "retry" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9166d72162de3575f950507683fac47e30f6f2c3836b71b7fbc61aa517c9c5f4" -dependencies = [ - "rand 0.8.5", -] - [[package]] name = "ring" version = "0.16.20" @@ -2171,9 +2671,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" @@ -2190,7 +2690,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.22", + "semver 1.0.23", ] [[package]] @@ -2208,9 +2708,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring 0.17.8", @@ -2239,15 +2739,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "scopeguard" @@ -2275,6 +2775,12 @@ dependencies = [ "untrusted 0.9.0", ] +[[package]] +name = "sdio-host" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93c025f9cfe4c388c328ece47d11a54a823da3b5ad0370b22d95ad47137f85a" + [[package]] name = "semver" version = "0.9.0" @@ -2286,9 +2792,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "semver-parser" @@ -2298,31 +2804,31 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.65", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ - "itoa 1.0.10", + "itoa 1.0.11", "ryu", "serde", ] @@ -2333,7 +2839,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" dependencies = [ - "itoa 1.0.10", + "itoa 1.0.11", "serde", ] @@ -2356,24 +2862,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.10", + "itoa 1.0.11", "ryu", "serde", ] [[package]] name = "serde_yaml" -version = "0.9.32" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.2.5", - "itoa 1.0.10", + "indexmap 2.2.6", + "itoa 1.0.11", "ryu", "serde", "unsafe-libyaml", ] +[[package]] +name = "serialport" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5a15d0be940df84846264b09b51b10b931fb2f275becb80934e3568a016828" +dependencies = [ + "bitflags 2.5.0", + "cfg-if 1.0.0", + "core-foundation-sys", + "io-kit-sys", + "mach2", + "nix 0.26.4", + "regex", + "scopeguard", + "unescaper", + "winapi 0.3.9", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -2383,11 +2907,24 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "sht31" +version = "0.3.1" +source = "git+https://github.com/dvdsk/SHT31-rs#a7b6bd94fb137e16bf326eff5fb591624369a2cf" +dependencies = [ + "crc", + "defmt", + "embedded-hal-async", + "postcard", + "serde", + "thiserror", +] + [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -2398,7 +2935,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", ] [[package]] @@ -2409,7 +2946,7 @@ checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" dependencies = [ "crc32fast", "crossbeam-epoch 0.9.18", - "crossbeam-utils 0.8.19", + "crossbeam-utils 0.8.20", "fs2", "fxhash", "libc", @@ -2428,15 +2965,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -2454,7 +2991,21 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" dependencies = [ - "lock_api 0.4.11", + "lock_api 0.4.12", +] + +[[package]] +name = "sps30-async" +version = "0.2.0" +source = "git+https://github.com/dvdsk/sps30-async#a5e81ec034727442c048acea2e8eb07fe4be78e4" +dependencies = [ + "defmt", + "embedded-hal-async", + "embedded-io-async", + "heapless 0.8.0", + "postcard", + "serde", + "thiserror", ] [[package]] @@ -2463,6 +3014,25 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "stm32-fmc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830ed60f33e6194ecb377f5d6ab765dc0e37e7b65e765f1fa87df13336658d63" +dependencies = [ + "embedded-hal 0.2.7", +] + +[[package]] +name = "stm32-metapac" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deabea56a8821dcea05d0109f3ab3135f31eb572444e5da203d06149c594c8c6" +dependencies = [ + "cortex-m", + "cortex-m-rt", +] + [[package]] name = "string" version = "0.2.1" @@ -2474,9 +3044,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" @@ -2493,11 +3063,11 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", - "syn 2.0.52", + "syn 2.0.65", ] [[package]] @@ -2513,9 +3083,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.52" +version = "2.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" dependencies = [ "proc-macro2", "quote", @@ -2528,6 +3098,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + [[package]] name = "synstructure" version = "0.12.6" @@ -2542,20 +3118,20 @@ dependencies = [ [[package]] name = "system-configuration" -version = "0.6.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bc6ee10a9b4fcf576e9b0819d95ec16f4d2c02d39fd83ac1c8789785c4a42" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ - "bitflags 2.4.2", + "bitflags 1.3.2", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.6.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" dependencies = [ "core-foundation-sys", "libc", @@ -2569,22 +3145,22 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.65", ] [[package]] @@ -2615,12 +3191,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", - "libc", "num-conv", - "num_threads", "powerfmt", "serde", "time-core", + "time-macros", ] [[package]] @@ -2629,6 +3204,16 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -2665,16 +3250,16 @@ dependencies = [ [[package]] name = "tokio" -version = "1.36.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", - "bytes 1.5.0", + "bytes 1.6.0", "libc", "mio 0.8.11", "num_cpus", - "parking_lot 0.12.1", + "parking_lot 0.12.2", "pin-project-lite", "signal-hook-registry", "socket2", @@ -2732,7 +3317,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.65", ] [[package]] @@ -2774,8 +3359,8 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.10", - "tokio 1.36.0", + "rustls 0.21.12", + "tokio 1.37.0", ] [[package]] @@ -2833,16 +3418,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ - "bytes 1.5.0", + "bytes 1.6.0", "futures-core", "futures-sink", "pin-project-lite", - "tokio 1.36.0", - "tracing", + "tokio 1.37.0", ] [[package]] @@ -2855,7 +3439,7 @@ dependencies = [ "futures-util", "pin-project", "pin-project-lite", - "tokio 1.36.0", + "tokio 1.37.0", "tower-layer", "tower-service", "tracing", @@ -2893,7 +3477,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.65", ] [[package]] @@ -2939,7 +3523,7 @@ dependencies = [ "once_cell", "regex", "sharded-slab", - "smallvec 1.13.1", + "smallvec 1.13.2", "thread_local", "tracing", "tracing-core", @@ -2961,6 +3545,24 @@ dependencies = [ "cfg-if 0.1.10", ] +[[package]] +name = "tz-rs" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33851b15c848fad2cf4b105c6bb66eb9512b6f6c44a4b13f57c53c73c707e2b4" +dependencies = [ + "const_fn", +] + +[[package]] +name = "unescaper" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0adf6ad32eb5b3cadff915f7b770faaac8f7ff0476633aa29eb0d9584d889d34" +dependencies = [ + "thiserror", +] + [[package]] name = "unicase" version = "2.7.0" @@ -2999,9 +3601,9 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "unsafe-libyaml" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "untrusted" @@ -3058,12 +3660,39 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] + +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + [[package]] name = "want" version = "0.2.0" @@ -3117,7 +3746,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.65", "wasm-bindgen-shared", ] @@ -3151,7 +3780,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.65", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3237,7 +3866,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -3255,7 +3884,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -3275,17 +3904,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -3296,9 +3926,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -3308,9 +3938,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -3320,9 +3950,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -3332,9 +3968,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -3344,9 +3980,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -3356,9 +3992,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -3368,9 +4004,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winreg" diff --git a/Cargo.toml b/Cargo.toml index e01ff38d..a15fcb1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,6 @@ [workspace] resolver = "2" members = ["crates/*"] -rust-version = "1.76" [workspace.package] rust-version = "1.70" diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index b5d30a2b..0a441867 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -1,22 +1,13 @@ [package] -name = "ha" +name = "brain" version = "0.1.0" rust-version.workspace = true edition.workspace = true license.workspace = true authors.workspace = true -[features] -default = [] - -# Enable code that expects sensor hardware to be present. Will stop execution -# if hardware is not present, -# on by default for testing use cargo flag: --no-default-features -sensors_connected = [] -live_server = [] - [dependencies] -protocol = { path = "../protocol", features = ["alloc"] } +protocol = { path = "../protocol" } futures = "0.3" tokio = { version = "1", features = ["full"] } @@ -34,24 +25,22 @@ thiserror = "1.0" chrono = { version = "0.4", features = ["serde"] } bytes = "1.5" byteorder = "1.4" -num = { version = "0.4"} crossbeam-channel = "0.5" sled = "0.34" -# pagecache = "0.17" reqwest = {version = "0.11", default-features = false, features = ["rustls-tls"]} mpd = "0.1" rand = "0.8" -retry = "2" futures-util = "0.3.30" tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } tracing-journald = "0.3.0" log-panics = "2.1.0" -clap = { version = "4.5.2", features = ["derive"] } +clap = { version = "4.5.4", features = ["derive"] } futures-concurrency = "7.5.0" -time = { version = "0.3.36", features = ["local-offset"] } +time = { version = "0.3.36", features = ["macros"] } strum = { version = "0.26.2", default-features = false, features = ["derive"] } +tz-rs = "0.6.14" diff --git a/crates/brain/deploy.sh b/crates/brain/deploy.sh deleted file mode 100755 index 2ad84558..00000000 --- a/crates/brain/deploy.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash -set -e - -BUILD_ARG=$1 -SERVER="sgc" # ssh config name or full adress - -cross build --target=aarch64-unknown-linux-gnu $BUILD_ARG --features "sensors_connected live_server" -rsync -vh --progress \ - target/aarch64-unknown-linux-gnu/debug/HomeAutomation \ - $SERVER:/tmp/ - -cmds=" -sudo mv /tmp/HomeAutomation /home/ha/homeAutomation -sudo chown ha:ha /home/ha/homeAutomation -sudo systemctl restart ha.service -" - -ssh -t sgc "$cmds" diff --git a/crates/brain/deploy_optimized.sh b/crates/brain/deploy_optimized.sh deleted file mode 100755 index 942ecbe4..00000000 --- a/crates/brain/deploy_optimized.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -source deploy "--release" diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index bd317b8a..2e975561 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -1,13 +1,31 @@ mod rooms; use crate::system::System; -pub use protocol::SensorValue; +pub use protocol::Reading; +use serde::{Deserialize, Serialize}; +use time::{OffsetDateTime, UtcOffset}; use tokio::sync::broadcast; use tokio::task::JoinSet; -#[derive(Clone, Debug, PartialEq, Eq)] +// now_local works some of the time only... this replaces it with....... +// horrible hard coded time stuff. Chrono does provide reliable now_local +// however it has disadvantages (unsound + other flaws) +pub fn local_now() -> OffsetDateTime { + let utc = OffsetDateTime::now_utc(); + let offset = tz::TimeZone::local() + .unwrap() + .find_current_local_time_type() + .unwrap() + .ut_offset(); + + let offset = UtcOffset::from_whole_seconds(offset).unwrap(); + utc.to_offset(offset) +} + +#[derive(Clone, Debug, Serialize, Deserialize)] pub enum Event { - Sensor(SensorValue), + Sensor(Reading), + WakeUp, } struct RestrictedSystem { @@ -16,15 +34,21 @@ struct RestrictedSystem { } impl RestrictedSystem { - fn all_lamps_ct(&mut self, ct: u16, bri: u8) { + async fn all_lamps_ct(&mut self, ct: u16, bri: u8) { for name in &self.allowed_lights { - self.system.lights.set_ct(name, bri, ct).unwrap(); + self.system.lights.set_ct(name, bri, ct).await.unwrap(); } } } -pub fn start(event_tx: broadcast::Sender, system: System) -> JoinSet<()> { +pub fn start( + subscribed: [broadcast::Receiver; 3], + sender: broadcast::Sender, + system: System, +) -> JoinSet<()> { + tracing::info!("starting"); let mut tasks = JoinSet::new(); + let [rx1, rx2, rx3] = subscribed; let restricted = RestrictedSystem { system: system.clone(), @@ -32,40 +56,27 @@ pub fn start(event_tx: broadcast::Sender, system: System) -> JoinSet<()> "large_bedroom:cabinet", "large_bedroom:ceiling", "large_bedroom:desk", + "large_bedroom:wardrobe", + "large_bedroom:bed", ], }; - tasks.spawn(rooms::large_bedroom::run( - event_tx.clone().subscribe(), - event_tx.clone(), - restricted, - )); + tasks.spawn(rooms::large_bedroom::run(rx1, sender.clone(), restricted)); let restricted = RestrictedSystem { system: system.clone(), allowed_lights: vec![ "small_bedroom:ceiling", + "small_bedroom:bureau", + "small_bedroom:piano", ], }; - tasks.spawn(rooms::small_bedroom::run( - event_tx.clone().subscribe(), - event_tx.clone(), - restricted, - )); + tasks.spawn(rooms::small_bedroom::run(rx2, sender.clone(), restricted)); let restricted = RestrictedSystem { system: system.clone(), - allowed_lights: vec![ - "kitchen:ceiling", - "kitchen:hood_left", - "kitchen:hood_right", - ], + allowed_lights: vec!["kitchen:ceiling", "kitchen:hood_left", "kitchen:hood_right"], }; - tasks.spawn(rooms::kitchen::run( - event_tx.subscribe(), - event_tx, - restricted, - )); + tasks.spawn(rooms::kitchen::run(rx3, sender, restricted)); tasks } - diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index 7aa19659..08ce5199 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -2,12 +2,11 @@ use std::time::Duration; use futures_concurrency::future::Race; use futures_util::FutureExt; -use time::OffsetDateTime; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; -use tracing::warn; +use tracing::{instrument, warn}; -use crate::controller::{Event, RestrictedSystem}; +use crate::controller::{local_now, Event, RestrictedSystem}; enum State { // Sleep, @@ -35,7 +34,7 @@ impl RecvFiltered for broadcast::Receiver { #[derive(Debug)] enum RelevantEvent { - DeskButton(protocol::large_bedroom::DeskButton), + // DeskButton(protocol::large_bedroom::DeskButton), } fn filter(event: Event) -> Option { @@ -66,35 +65,37 @@ pub async fn run( let res = (get_event, tick).race().await; match res { - Res::Event(e) => handle_event(e), + Res::Event(_) => (), // handle_event(e), Res::ShouldUpdate => { - update(&mut system); - next_update = Instant::now() + INTERVAL; + update(&mut system).await; + next_update = Instant::now() + Duration::from_secs(60); } } } } -fn update(system: &mut RestrictedSystem) { +async fn update(system: &mut RestrictedSystem) { let (new_ct, new_bri) = optimal_ct_bri(); - system.all_lamps_ct(new_ct, new_bri); + system.all_lamps_ct(new_ct, new_bri).await; + tracing::info!("updated lamps"); } fn optimal_ct_bri() -> (u16, u8) { - let now = OffsetDateTime::now_local().expect("Timezone not found"); + let now = local_now(); match now.hour() { - 0..=5 | 22.. => (500, 220), - 17..=21 => (320, u8::MAX), - 6..=16 => (254, u8::MAX), + 0..=8 | 22.. => (500, 180), + 9..=16 => (270, u8::MAX), + 17..=19 => (300, u8::MAX), + 20..=21 => (400, 210), } } -fn handle_event(e: RelevantEvent) { - use protocol::large_bedroom::DeskButton as D; - use RelevantEvent as R; - - match e { - R::DeskButton(D::OneOfFour(p)) if p.is_long() => todo!(), - unhandled => warn!("Unhandled button: {unhandled:?}"), - } -} +// fn handle_event(e: RelevantEvent) { +// use protocol::large_bedroom::DeskButton as D; +// use RelevantEvent as R; +// +// match e { +// R::DeskButton(D::OneOfFour(p)) if p.is_long() => todo!(), +// unhandled => warn!("Unhandled button: {unhandled:?}"), +// } +// } diff --git a/crates/brain/src/controller/rooms/large_bedroom.rs b/crates/brain/src/controller/rooms/large_bedroom.rs index 80503c92..3c2486d5 100644 --- a/crates/brain/src/controller/rooms/large_bedroom.rs +++ b/crates/brain/src/controller/rooms/large_bedroom.rs @@ -2,12 +2,11 @@ use std::time::Duration; use futures_concurrency::future::Race; use futures_util::FutureExt; -use time::OffsetDateTime; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; use tracing::warn; -use crate::controller::{Event, RestrictedSystem}; +use crate::controller::{local_now, Event, RestrictedSystem}; enum State { // Sleep, @@ -35,16 +34,30 @@ impl RecvFiltered for broadcast::Receiver { #[derive(Debug)] enum RelevantEvent { - DeskButton(protocol::large_bedroom::DeskButton), + WakeUp, + WeightLeft(u32), + WeightRight(u32), + Brightness(f32), // millilux + DeskButton(protocol::large_bedroom::desk::Button), + BedButton(protocol::large_bedroom::bed::Button), } fn filter(event: Event) -> Option { - match event { - // Event::Sensor(SensorValue::ButtonPress(Button::LargeBedroomDesk(desk))) => { - // Some(RelevantEvent::DeskButton(desk)) - // } - _ => None, - } + use protocol::large_bedroom::bed::Reading as B; + use protocol::large_bedroom::desk::Reading as D; + use protocol::large_bedroom::Reading as R; + use protocol::Reading::LargeBedroom as LB; + use Event::{Sensor, WakeUp}; + + Some(match event { + WakeUp => RelevantEvent::WakeUp, + Sensor(LB(R::Desk(D::Button(b)))) => RelevantEvent::DeskButton(b), + Sensor(LB(R::Bed(B::Button(b)))) => RelevantEvent::BedButton(b), + Sensor(LB(R::Bed(B::Brightness(l)))) => RelevantEvent::Brightness(l), + Sensor(LB(R::Bed(B::WeightLeft(w)))) => RelevantEvent::WeightLeft(w), + Sensor(LB(R::Bed(B::WeightRight(w)))) => RelevantEvent::WeightRight(w), + _ => return None, + }) } pub async fn run( @@ -68,33 +81,34 @@ pub async fn run( match res { Res::Event(e) => handle_event(e), Res::ShouldUpdate => { - update(&mut system); + update(&mut system).await; next_update = Instant::now() + INTERVAL; } } } } -fn update(system: &mut RestrictedSystem) { +async fn update(system: &mut RestrictedSystem) { let (new_ct, new_bri) = optimal_ct_bri(); - system.all_lamps_ct(new_ct, new_bri); + system.all_lamps_ct(new_ct, new_bri).await; } fn optimal_ct_bri() -> (u16, u8) { - let now = OffsetDateTime::now_local().expect("Timezone not found"); + let now = local_now(); match now.hour() { - 0..=5 | 22.. => (500, 220), - 17..=21 => (320, u8::MAX), + 0..=5 | 22.. => (500, 170), 6..=16 => (254, u8::MAX), + 17..=19 => (320, u8::MAX), + 20..=21 => (320, 220), } } fn handle_event(e: RelevantEvent) { - use protocol::large_bedroom::DeskButton as D; - use RelevantEvent as R; + // use protocol::large_bedroom::DeskButton; + // use RelevantEvent as R; match e { - R::DeskButton(D::OneOfFour(p)) if p.is_long() => todo!(), - unhandled => warn!("Unhandled button: {unhandled:?}"), + // R::DeskButton(DeskButton::OneOfFour(p)) if p.is_long() => (), + unhandled => warn!("Unhandled relevant event: {unhandled:?}"), } } diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 9723588e..28714274 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -2,12 +2,11 @@ use std::time::Duration; use futures_concurrency::future::Race; use futures_util::FutureExt; -use time::OffsetDateTime; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; use tracing::warn; -use crate::controller::{Event, RestrictedSystem}; +use crate::controller::{local_now, Event, RestrictedSystem}; enum State { Sleep, @@ -35,7 +34,7 @@ impl RecvFiltered for broadcast::Receiver { #[derive(Debug)] enum RelevantEvent { - DeskButton(protocol::large_bedroom::DeskButton), + // DeskButton(protocol::large_bedroom::DeskButton), } fn filter(event: Event) -> Option { @@ -50,7 +49,7 @@ fn filter(event: Event) -> Option { pub async fn run( mut event_rx: broadcast::Receiver, // todo if state change message everyone using this - event_tx: broadcast::Sender, + _event_tx: broadcast::Sender, mut system: RestrictedSystem, ) { enum Res { @@ -66,36 +65,36 @@ pub async fn run( let res = (get_event, tick).race().await; match res { - Res::Event(e) => handle_event(e), + Res::Event(_) => (), //handle_event(e), Res::ShouldUpdate => { - update(&mut system); + update(&mut system).await; next_update = Instant::now() + INTERVAL; } } } } -fn update(system: &mut RestrictedSystem) { +async fn update(system: &mut RestrictedSystem) { let (new_ct, new_bri) = optimal_ct_bri(); - system.all_lamps_ct(new_ct, new_bri); + system.all_lamps_ct(new_ct, new_bri).await; } fn optimal_ct_bri() -> (u16, u8) { - let now = OffsetDateTime::now_local().expect("Timezone not found"); + let now = local_now(); match now.hour() { - 0..=8 | 22.. => (500, 180), + 0..=8 | 21.. => (500, 100), 9..=16 => (270, u8::MAX), - 17..=19 => (300, u8::MAX), - 20..=21 => (400, 220), + 17..=18 => (300, u8::MAX), + 19..=20 => (460, 220), } } -fn handle_event(e: RelevantEvent) { - use protocol::large_bedroom::DeskButton as D; - use RelevantEvent as R; - - match e { - R::DeskButton(D::OneOfFour(p)) if p.is_long() => todo!(), - unhandled => warn!("Unhandled button: {unhandled:?}"), - } -} +// fn handle_event(e: RelevantEvent) { +// use protocol::large_bedroom::DeskButton as D; +// use RelevantEvent as R; +// +// match e { +// R::DeskButton(D::OneOfFour(p)) if p.is_long() => todo!(), +// unhandled => warn!("Unhandled button: {unhandled:?}"), +// } +// } diff --git a/crates/brain/src/input/api.rs b/crates/brain/src/input/api.rs index 3750c504..fd5df8ec 100644 --- a/crates/brain/src/input/api.rs +++ b/crates/brain/src/input/api.rs @@ -65,7 +65,7 @@ async fn sensor_event(aState(state): aState, body: Bytes) { let msg: protocol::SensorMessage<20> = match protocol::SensorMessage::decode(&mut bytes) { Ok(msg) => msg, Err(e) => { - warn!("Failed to decode received body: {e}"); + warn!("Failed to decode received body: {e:?}"); return; } }; diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index f54e3a38..afe0952b 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -1,9 +1,9 @@ use crossbeam_channel; +use std::ops::Sub; +use std::thread; use tokio::sync::broadcast; use tracing::error; use tracing::info; -use std::ops::Sub; -use std::thread; use byteorder::{BigEndian, ReadBytesExt}; use chrono::{self, DateTime, Utc}; @@ -15,11 +15,6 @@ use crate::controller::Event; pub mod wakeup; pub use wakeup::WakeUp; -#[derive(Serialize, Deserialize, Debug)] -pub enum Action { - // SendEvent(Event), -} - #[derive(thiserror::Error, Debug)] pub enum Error { #[error("Could store/edit job on disk")] @@ -31,7 +26,7 @@ pub enum Error { #[derive(Serialize, Deserialize, Debug)] pub struct Job { pub time: DateTime, - pub action: Action, + pub event: Event, /// how long after the time was missed the alarm /// should still go off pub expiration: Option, @@ -40,12 +35,12 @@ pub struct Job { impl Job { pub fn from( time: DateTime, - action: impl Into, + event: Event, expiration: Option, ) -> Self { Job { time, - action: action.into(), + event: event.into(), expiration, } } @@ -106,7 +101,9 @@ fn waker( Err(Disconnected) => return, Err(Timeout) => { // time to sound the alarm - sound_alarm(&event_tx, current_alarm); + event_tx + .send(current_alarm.event) + .expect("controller should listen on this"); alarm_list.remove_alarm(id).unwrap(); continue; //get next alarm } @@ -125,13 +122,6 @@ fn waker( } } -fn sound_alarm(event_tx: &broadcast::Sender, job: Job) { - todo!(); - // match job.action { - // Action::SendEvent(ev) => event_tx.send(ev).unwrap(), - // }; -} - impl Jobs { pub fn setup( event_tx: broadcast::Sender, @@ -165,18 +155,18 @@ impl Jobs { self.list.get_alarm(id) } - pub fn list(&self) -> Vec<(u64, Job)> { - let start: &[u8] = &[0]; - let alarms = self.list.db.range(start..); - - let mut list = Vec::new(); - for (key, alarm) in alarms.filter_map(Result::ok) { - let alarm = bincode::deserialize(&alarm).unwrap(); - let key = key.as_ref().read_u64::().unwrap(); - list.push((key, alarm)); - } - list - } + // pub fn list(&self) -> Vec<(u64, Job)> { + // let start: &[u8] = &[0]; + // let alarms = self.list.db.range(start..); + // + // let mut list = Vec::new(); + // for (key, alarm) in alarms.filter_map(Result::ok) { + // let alarm = bincode::deserialize(&alarm).unwrap(); + // let key = key.as_ref().read_u64::().unwrap(); + // list.push((key, alarm)); + // } + // list + // } } impl JobList { diff --git a/crates/brain/src/input/jobs/wakeup.rs b/crates/brain/src/input/jobs/wakeup.rs index c1e67811..8bf40bf1 100644 --- a/crates/brain/src/input/jobs/wakeup.rs +++ b/crates/brain/src/input/jobs/wakeup.rs @@ -1,10 +1,13 @@ +use crate::controller::Event; + use super::{Job, Jobs}; use chrono::{DateTime, Local, Timelike, Utc}; -use tokio::runtime::Runtime; -use tracing::info; use std::sync::Arc; -use tokio::sync::Mutex; use std::time::Duration; +use tokio::runtime::Runtime; +use tokio::sync::{broadcast, Mutex}; +use tokio::task; +use tracing::{error, info}; // TODO FIXME multiple things left to do: // - usually and tomorrow are not written to db @@ -19,12 +22,37 @@ pub enum Error { JobError(#[from] super::Error), } +async fn reset_on_wakeup(wake_up: WakeUp, mut event_rx: broadcast::Receiver) { + loop { + match event_rx.recv().await { + Ok(Event::WakeUp) => { + if let Err(e) = wake_up.reset() { + /* TODO: this should make more "noise" then this <28-04-24, dvdsk> */ + error!("Could not reset wakeup system for next wake: {e}"); + } + } + Err(broadcast::error::RecvError::Closed) => return, + _ => (), + } + } +} + #[derive(Clone)] pub struct WakeUp(Arc>); impl WakeUp { - pub fn setup(db: sled::Db, jobs: Jobs) -> Result { + /// # Important + /// The receiver must be subscribed before the jobs system is started + /// or it can miss alarms + pub fn setup( + db: sled::Db, + jobs: Jobs, + event_rx: broadcast::Receiver, + ) -> Result { let inner = Inner::setup(db, jobs)?; let inner = Arc::new(Mutex::new(inner)); + let this = Self(inner.clone()); + task::spawn(reset_on_wakeup(this, event_rx)); + Ok(Self(inner)) } pub async fn tomorrow(&self) -> Option<(u8, u8)> { @@ -117,7 +145,7 @@ impl Inner { Ok(()) } - /// reset the alarm, if their is a usual alarm + /// reset the alarm, if there is a usual alarm /// time we set that, otherwise remove all pub fn reset(&mut self) -> Result<(), Error> { if let Some((hour, min)) = self.usually { @@ -165,7 +193,7 @@ impl Inner { fn job_from(hour: u8, min: u8) -> Job { Job { time: to_datetime(hour, min), - action: todo!(), //Action::SendEvent(Event::WakeUp), + event: Event::WakeUp, expiration: Some(Duration::from_secs(3 * 60 * 60)), } } diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index c3d9a78b..1c4c1586 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -1,3 +1,4 @@ +use std::array; use std::net::IpAddr; use clap::Parser; @@ -39,19 +40,21 @@ async fn main() -> Result<(), Box> { .cache_capacity(1024 * 1024 * 32) //32 mb cache .open()?; - let (event_tx, _event_rx) = broadcast::channel(250); + // must create all listeners before jobs/alarm events can be send + // or they may be lost. + let (event_tx, event_rx) = broadcast::channel(250); + let subscribed_rxs = array::from_fn(|_| event_tx.subscribe()); let (jobs, _waker_thread) = input::jobs::Jobs::setup(event_tx.clone(), db.clone())?; - let wakeup = input::jobs::WakeUp::setup(db.clone(), jobs.clone())?; + let wakeup = input::jobs::WakeUp::setup(db.clone(), jobs.clone(), event_rx)?; // let (_mpd_status, _mpd_watcher_thread, _updater_tx) = // input::MpdStatus::start_updating(opt.mpd_ip)?; let system = system::System::init(jobs); - controller::start(event_tx.clone(), system); + let _tasks = controller::start(subscribed_rxs, event_tx.clone(), system); input::api::setup(wakeup.clone(), event_tx, opt.port).await?; - std::future::pending::<()>().await; - Ok(()) + unreachable!(); } pub fn setup_tracing() { @@ -64,7 +67,7 @@ pub fn setup_tracing() { .try_from_env() .unwrap_or_else(|_| { filter::EnvFilter::builder() - .parse("HomeAutomation=debug,info") + .parse("brain=debug,info") .unwrap() }); diff --git a/crates/brain/src/system/lamps/eventually_consistent_bridge.rs b/crates/brain/src/system/lamps/eventually_consistent_bridge.rs index d3efa8ff..7db5ab22 100644 --- a/crates/brain/src/system/lamps/eventually_consistent_bridge.rs +++ b/crates/brain/src/system/lamps/eventually_consistent_bridge.rs @@ -2,17 +2,17 @@ use super::{bridge_connect, lamp::Lamp}; use super::{ApplyChangeError, State}; use crate::errors::Error; use futures_util::stream::Peekable; -use futures_util::{FutureExt, Stream, StreamExt}; -use philipshue::LightCommand; -use std::collections::HashMap; +use futures_util::{Stream, StreamExt}; +use std::collections::{HashMap, HashSet}; use std::pin::Pin; -use std::time::Duration; -use tokio::select; +use std::time::{Duration, Instant}; use tokio::sync::oneshot; -use tracing::error; +use tokio::time::{timeout, timeout_at}; +use tracing::{error, warn}; use philipshue::bridge::Bridge; +#[derive(Debug)] pub(crate) enum Change { AllOff, AllOn, @@ -49,6 +49,7 @@ pub(crate) struct CachedBridge { pub(crate) known_state: State, // get names using: curl 192.168.1.11/api//lights | jq | grep '"name": "' lookup: HashMap, + reported_missing: HashSet, } impl CachedBridge { @@ -68,9 +69,17 @@ impl CachedBridge { needed_state: state.clone(), known_state: state, lookup, + reported_missing: HashSet::new(), }) } + fn report_missing_if_not_reported_yet(&mut self, missing_lamp: &str) { + let new = self.reported_missing.insert(missing_lamp.to_string()); + if new { + error!("no lamp with name: {missing_lamp} in lookup table, was recently (re)named?"); + } + } + pub(crate) fn apply_changes(&mut self) -> Result<(), Error> { for (id, lamp) in self.known_state.iter_mut() { let Some(needed) = self.needed_state.get(id) else { @@ -78,19 +87,23 @@ impl CachedBridge { }; if lamp != needed { - self.bridge - .set_light_state( - *id, - &LightCommand::default() - .with_xy(needed.xy.unwrap()) - .with_bri(needed.bri), - ) - .unwrap(); + if let Err(e) = self.bridge.set_light_state(*id, &needed.light_cmd()) { + warn!("could not apply changes to lamp: {e}") + } + *lamp = needed.clone() } } Ok(()) } + + fn push_state(&mut self) -> Result<(), Error> { + for (id, lamp) in self.known_state.iter_mut() { + let _ignore_err = self.bridge.set_light_state(*id, &lamp.light_cmd()); + } + Ok(()) + } + pub(crate) fn prep_change(&mut self, change: &Change) { match change { Change::AllOff => { @@ -105,7 +118,6 @@ impl CachedBridge { } Change::Off { name } => { let Some(lamp_id) = self.lookup.get(*name) else { - error!("no lamp with name: {name} in lookup table, was recently (re)named?"); return; }; if let Some(lamp) = self.needed_state.get_mut(lamp_id) { @@ -116,7 +128,7 @@ impl CachedBridge { } Change::On { name } => { let Some(lamp_id) = self.lookup.get(*name) else { - error!("no lamp with name: {name} in lookup table, was recently (re)named?"); + self.report_missing_if_not_reported_yet(*name); return; }; if let Some(lamp) = self.needed_state.get_mut(&lamp_id) { @@ -127,34 +139,38 @@ impl CachedBridge { } Change::CtBri { name, bri, ct } => { let Some(lamp_id) = self.lookup.get(*name) else { - error!("no lamp with name: {name} in lookup table, was recently (re)named?"); + self.report_missing_if_not_reported_yet(*name); return; }; if let Some(lamp) = self.needed_state.get_mut(lamp_id) { lamp.bri = *bri; lamp.ct = Some(*ct); + lamp.xy = None; } } Change::XyBri { name, bri, xy } => { let Some(lamp_id) = self.lookup.get(*name) else { - error!("no lamp with name: {name} in lookup table, was recently (re)named?"); + self.report_missing_if_not_reported_yet(*name); return; }; if let Some(lamp) = self.needed_state.get_mut(lamp_id) { lamp.bri = *bri; lamp.xy = Some(*xy); + lamp.ct = None; } } Change::AllCtBri { bri, ct } => { self.needed_state.values_mut().for_each(|lamp| { lamp.bri = *bri; lamp.ct = Some(*ct); + lamp.xy = None; }); } Change::AllXY { bri, xy } => { self.needed_state.values_mut().for_each(|lamp| { lamp.bri = *bri; lamp.xy = Some(*xy); + lamp.ct = None; }); } } @@ -168,31 +184,56 @@ pub(crate) async fn process_lamp_changes( where S: Stream>, Change)>, { + const MAX_DUR: Duration = Duration::from_millis(100); + let mut last_state_push = Instant::now(); loop { - let mut to_answer = Vec::new(); - // process backlog - loop { - let Some((_, change)) = stream.as_mut().peek_mut().now_or_never().flatten() else { - let change_appears = stream.as_mut().peek_mut(); - let not_instant = tokio::time::sleep(Duration::from_millis(50)); - select! { - _ = change_appears => continue, - _ = not_instant => break, + if last_state_push.elapsed() > Duration::from_secs(5) { + if let Err(err) = bridge.push_state() { + return err; + } + last_state_push = Instant::now(); + } + let (tx, change) = match timeout(Duration::from_secs(5), stream.next()).await { + Ok(Some(next)) => next, + Ok(None) => unreachable!("light system should not drop"), + Err(_timeout) => { + if let Err(err) = bridge.push_state() { + return err; + } else { + continue; + } + } + }; + + bridge.prep_change(&change); + let mut to_answer = vec![tx]; + + let now = Instant::now(); + let deadline = tokio::time::Instant::from(now) + MAX_DUR; + + // process backlog + while now.elapsed() < MAX_DUR { + match timeout_at(deadline, stream.next()).await { + Err(_timeout) => break, + Ok(None) => unreachable!("light system should not drop"), + Ok(Some((tx, change))) => { + bridge.prep_change(&change); + to_answer.push(tx); } }; - bridge.prep_change(change); - // remove the now processed item from the stream and store its - // answer tx - let (tx, _) = stream.as_mut().next().await.expect("just peeked"); - to_answer.push(tx); } if let Err(e) = bridge.apply_changes() { + error!("Could not apply changes to bridge immediately, err: {e}"); for tx in to_answer { let _ignore_canceld_requester = tx.send(Err(ApplyChangeError)); } return e; + } else { + for tx in to_answer { + let _ignore_canceld_requester = tx.send(Ok(())); + } } } } diff --git a/crates/brain/src/system/lamps/lamp.rs b/crates/brain/src/system/lamps/lamp.rs index 18823774..0b03f095 100644 --- a/crates/brain/src/system/lamps/lamp.rs +++ b/crates/brain/src/system/lamps/lamp.rs @@ -1,3 +1,5 @@ +use philipshue::LightCommand; + //adaptation from philipshue LightState that adds some //values and removes unused #[derive(Debug, Clone, PartialEq)] @@ -11,6 +13,20 @@ pub struct Lamp { pub reachable: bool, } +impl Lamp { + pub(crate) fn light_cmd(&self) -> LightCommand { + let light_cmd = LightCommand::default().with_bri(self.bri); + let light_cmd = if let Some(xy) = self.xy { + light_cmd.with_xy(xy) + } else if let Some(ct) = self.ct { + light_cmd.with_ct(ct) + } else { + unreachable!("lamp must have ct or xy set"); + }; + light_cmd + } +} + impl From<&philipshue::hue::LightState> for Lamp { fn from(state: &philipshue::hue::LightState) -> Self { Lamp { @@ -25,6 +41,7 @@ impl From<&philipshue::hue::LightState> for Lamp { } } +#[allow(dead_code)] fn gamma_correct(mut x: f32) -> f32 { if x > 0.04045 { x = (x + 0.055) / (1f32 + 0.055); @@ -36,6 +53,7 @@ fn gamma_correct(mut x: f32) -> f32 { //r,g,b between 0 and one //https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d +#[allow(dead_code)] pub fn xy_from_rgb(rgb: (f32, f32, f32)) -> (f32, f32) { let (r, g, b) = rgb; let r = gamma_correct(r); diff --git a/crates/brain/src/system/lamps/mod.rs b/crates/brain/src/system/lamps/mod.rs index 94f78c64..6c546fbe 100644 --- a/crates/brain/src/system/lamps/mod.rs +++ b/crates/brain/src/system/lamps/mod.rs @@ -69,30 +69,25 @@ pub struct ApplyChangeError; macro_rules! light_fn { ($name:ident, $change:ident$(; $($arg:ident: $type:ty),+)?) => { - pub fn $name(&mut self, $($($arg: $type),+)?) -> Result<(), ApplyChangeError> { + pub async fn $name(&mut self, $($($arg: $type),+)?) -> Result<(), ApplyChangeError> { // todo use oneshot to get error back from other side let (tx, rx) = tokio::sync::oneshot::channel(); self.tx.send((tx, Change::$change$({$($arg),+})?)).expect("managed_bridge should channel should never drop as managed bridge task should never end"); - let res = rx.blocking_recv().expect("managed_bridge should not crash and thus not drop the receive end of the channel"); + let res = rx.await.expect("managed_bridge should not crash and thus not drop the receive end of the channel"); res } }; } +#[allow(dead_code)] impl Lighting { pub fn start_init() -> Self { let (tx, rx) = mpsc::unbounded_channel(); let manage_bridge = manage_bridge(rx); - let manage_bridge = tokio::task::spawn(manage_bridge); + tokio::task::spawn(manage_bridge); Self { tx } } - //how to deal with errors? - pub fn toggle(&mut self) -> Result<(), Error> { - error!("not implemented"); - Ok(()) - } - light_fn! {all_off, AllOff} light_fn! {all_on, AllOn} light_fn! {single_off, Off; name: &'static str} diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index e52a6114..cc19150b 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -12,7 +12,7 @@ authors.workspace = true serde = { version = "1.0", features = ["derive"], default-features = false } postcard = { version = "1.0", features = ["experimental-derive"] } heapless = { version = "0.8.0", features = ["serde"] } -strum = { version = "0.26.2", default-features = false } +strum = { version = "0.26.2", default-features = false, features = ["derive"] } thiserror = { version = "1.0", optional = true } defmt = "0.3.6" @@ -20,10 +20,18 @@ defmt = "0.3.6" sht31 = { version = "0.3.0", git = "https://github.com/dvdsk/SHT31-rs", features = ["serde", "postcard"]} bosch-bme680 = { version = "1.0.2", git = "https://github.com/dvdsk/async-bosch-bme680", features = ["serde", "postcard"] } max44009 = { version = "0.2", git = "https://github.com/dvdsk/max44009-rs", features = ["serde", "postcard"] } +mhzx = { version = "0.3", git = "https://github.com/dvdsk/mhzx", features = ["serde", "postcard"] } +sps30-async = { version = "0.2.0", git = "https://github.com/dvdsk/sps30-async", features = ["serde", "postcard"] } +bme280 = { version = "0.5", git = "https://github.com/dvdsk/bme280-rs", features = ["postcard", "serde", "with_defmt"]} # needed for bme680 error I2C type embassy-stm32 = { version = "0.1.0", features = ["stm32f401cc"] } embassy-embedded-hal = "0.1.0" +linux-embedded-hal = { version = "0.4.0", features = ["i2c"], default-features = false } +nix = "0.28.0" +embedded-hal = "1.0.0" [features] -alloc = ["postcard/alloc", "serde/std", "sht31/thiserror", "bosch-bme680/thiserror"] +alloc = ["postcard/alloc", "serde/std", "sht31/thiserror", +"bosch-bme680/thiserror", "mhzx/thiserror", "sps30-async/thiserror", +"max44009/thiserror"] diff --git a/crates/protocol/src/downcast_err.rs b/crates/protocol/src/downcast_err.rs new file mode 100644 index 00000000..bb0c1837 --- /dev/null +++ b/crates/protocol/src/downcast_err.rs @@ -0,0 +1,105 @@ +mod i2c; +mod rpi_button; +mod uart; + +use bosch_bme680::BmeError; +pub use i2c::{I2cError, LinuxI2cError}; +pub use rpi_button::RpiButtonError; +pub use uart::Error as UartError; + +pub trait ConcreteErrorType { + type Concrete; + fn strip_generics(self) -> Self::Concrete; +} + +impl ConcreteErrorType for BmeError +where + E: Into + core::fmt::Debug, +{ + type Concrete = BmeError; + fn strip_generics(self) -> Self::Concrete { + match self { + BmeError::WriteError(i2c) => BmeError::WriteError(i2c.into()), + BmeError::WriteReadError(i2c) => BmeError::WriteReadError(i2c.into()), + BmeError::UnexpectedChipId(id) => BmeError::UnexpectedChipId(id), + BmeError::MeasuringTimeOut => BmeError::MeasuringTimeOut, + } + } +} + +impl ConcreteErrorType for max44009::Error +where + E: Into + core::fmt::Debug + defmt::Format, +{ + type Concrete = max44009::Error; + fn strip_generics(self) -> Self::Concrete { + match self { + max44009::Error::I2C(i2c) => max44009::Error::I2C(i2c.into()), + max44009::Error::OperationNotAvailable => max44009::Error::OperationNotAvailable, + } + } +} + +impl ConcreteErrorType for mhzx::Error +where + E1: Into + core::fmt::Debug + defmt::Format, + E2: Into + core::fmt::Debug + defmt::Format, +{ + type Concrete = mhzx::Error; + fn strip_generics(self) -> Self::Concrete { + match self { + mhzx::Error::InvalidChecksum => Self::Concrete::InvalidChecksum, + mhzx::Error::InvalidPacket => Self::Concrete::InvalidPacket, + mhzx::Error::WritingToUart(e) => Self::Concrete::WritingToUart(e.into()), + mhzx::Error::FlushingUart(e) => Self::Concrete::FlushingUart(e.into()), + mhzx::Error::ReadingEOF => Self::Concrete::ReadingEOF, + mhzx::Error::Reading(e) => Self::Concrete::Reading(e.into()), + } + } +} + +impl ConcreteErrorType for sps30_async::Error +where + E1: Into + core::fmt::Debug + defmt::Format, + E2: Into + core::fmt::Debug + defmt::Format, +{ + type Concrete = sps30_async::Error; + fn strip_generics(self) -> Self::Concrete { + match self { + sps30_async::Error::SerialR(e) => sps30_async::Error::SerialR(e.into()), + sps30_async::Error::SerialW(e) => sps30_async::Error::SerialW(e.into()), + sps30_async::Error::SHDLC(e) => sps30_async::Error::SHDLC(e), + sps30_async::Error::InvalidFrame => sps30_async::Error::InvalidFrame, + sps30_async::Error::EmptyResult => sps30_async::Error::EmptyResult, + sps30_async::Error::ChecksumFailed => sps30_async::Error::ChecksumFailed, + sps30_async::Error::InvalidResponse => sps30_async::Error::InvalidResponse, + sps30_async::Error::DeviceError(e) => sps30_async::Error::DeviceError(e), + sps30_async::Error::MeasurementDataTooShort => { + sps30_async::Error::MeasurementDataTooShort + } + sps30_async::Error::CleaningIntervalDataTooShort => { + sps30_async::Error::CleaningIntervalDataTooShort + } + sps30_async::Error::SerialInvalidUtf8 => sps30_async::Error::SerialInvalidUtf8, + sps30_async::Error::ReadingEOF => sps30_async::Error::ReadingEOF, + sps30_async::Error::FrameTooLarge => sps30_async::Error::FrameTooLarge, + } + } +} + +impl ConcreteErrorType for bme280::Error +where + E: Into + core::fmt::Debug, +{ + type Concrete = bme280::Error; + fn strip_generics(self) -> Self::Concrete { + match self { + bme280::Error::CompensationFailed => bme280::Error::CompensationFailed, + bme280::Error::Bus(e) => bme280::Error::Bus(e.into()), + bme280::Error::InvalidData => bme280::Error::InvalidData, + bme280::Error::NoCalibrationData => bme280::Error::NoCalibrationData, + bme280::Error::UnsupportedChip => bme280::Error::UnsupportedChip, + bme280::Error::Delay => bme280::Error::Delay, + } + } +} diff --git a/crates/protocol/src/extended_errors.rs b/crates/protocol/src/downcast_err/i2c.rs similarity index 51% rename from crates/protocol/src/extended_errors.rs rename to crates/protocol/src/downcast_err/i2c.rs index a4041a2b..25518e83 100644 --- a/crates/protocol/src/extended_errors.rs +++ b/crates/protocol/src/downcast_err/i2c.rs @@ -1,8 +1,7 @@ -use bosch_bme680::BmeError; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; -#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] +#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] #[cfg_attr(feature = "thiserror", derive(thiserror::Error))] pub enum I2cError { #[cfg_attr(feature = "thiserror", error("Bus error"))] @@ -51,35 +50,51 @@ impl From Self::Concrete; +#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +#[cfg_attr(feature = "thiserror", derive(thiserror::Error))] +// linux error codes should be stable across different linux kernels +pub enum LinuxI2cError { + FailedLibcCall(i32), + Io(Option), } -impl ConcreteErrorType for BmeError -where - E: Into + core::fmt::Debug, -{ - type Concrete = BmeError; - fn strip_generics(self) -> Self::Concrete { +#[cfg(feature = "thiserror")] +impl core::fmt::Display for LinuxI2cError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - BmeError::WriteError(i2c) => BmeError::WriteError(i2c.into()), - BmeError::WriteReadError(i2c) => BmeError::WriteReadError(i2c.into()), - BmeError::UnexpectedChipId(id) => BmeError::UnexpectedChipId(id), - BmeError::MeasuringTimeOut => BmeError::MeasuringTimeOut, + LinuxI2cError::FailedLibcCall(failed_libc_call) => { + let errno = nix::errno::Errno::from_raw(*failed_libc_call); + write!(f, "Error calling I2C interface: {errno}") + } + LinuxI2cError::Io(Some(raw_os_error)) => { + let io_error = std::io::Error::from_raw_os_error(*raw_os_error); + write!(f, "Io error using I2C interface: {io_error}, more details in logs on sensing device") + } + LinuxI2cError::Io(None) => { + write!( + f, + "Unknown error using I2C interface, check logs on sensing device" + ) + } } } } -impl ConcreteErrorType for max44009::Error -where - E: Into + core::fmt::Debug + defmt::Format, -{ - type Concrete = max44009::Error; - fn strip_generics(self) -> Self::Concrete { - match self { - max44009::Error::I2C(i2c) => max44009::Error::I2C(i2c.into()), - max44009::Error::OperationNotAvailable => max44009::Error::OperationNotAvailable, +impl From for LinuxI2cError { + fn from(value: linux_embedded_hal::I2CError) -> Self { + value.inner().into() + } +} + +impl From<&linux_embedded_hal::i2cdev::linux::LinuxI2CError> for LinuxI2cError { + fn from(value: &linux_embedded_hal::i2cdev::linux::LinuxI2CError) -> Self { + use linux_embedded_hal::i2cdev::linux::LinuxI2CError; + + match value { + LinuxI2CError::Errno(failing_libc_call) => { + LinuxI2cError::FailedLibcCall(*failing_libc_call) + } + LinuxI2CError::Io(io_error) => LinuxI2cError::Io(io_error.raw_os_error()), } } } diff --git a/crates/protocol/src/downcast_err/rpi_button.rs b/crates/protocol/src/downcast_err/rpi_button.rs new file mode 100644 index 00000000..64d5b372 --- /dev/null +++ b/crates/protocol/src/downcast_err/rpi_button.rs @@ -0,0 +1,36 @@ +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +#[cfg_attr(feature = "thiserror", derive(thiserror::Error))] +/// The gpio_cdev::Error is not constant size and impossible to inspect. The +/// alternative would be to send the error as a string. The error struct must +/// have a statically determined maximum size to allow encoding/decoding on +/// embedded systems. Thus sending a string is also not an option +pub enum RpiButtonError { + #[cfg_attr( + feature = "thiserror", + error("Error interfacing with Linux GPIO interface") + )] + GpioInterfaceError, + #[cfg_attr( + feature = "thiserror", + error("Error interfacing with Linux GPIO interface") + )] + GpioChipNotFound, + #[cfg_attr( + feature = "thiserror", + error("Error interfacing with Linux GPIO interface") + )] + ListingChips, + #[cfg_attr( + feature = "thiserror", + error("Error interfacing with Linux GPIO interface") + )] + GettingLine(u32), + #[cfg_attr( + feature = "thiserror", + error("Error interfacing with Linux GPIO interface") + )] + GetEventValue, +} diff --git a/crates/protocol/src/downcast_err/uart.rs b/crates/protocol/src/downcast_err/uart.rs new file mode 100644 index 00000000..1fdef9e5 --- /dev/null +++ b/crates/protocol/src/downcast_err/uart.rs @@ -0,0 +1,40 @@ +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +#[cfg_attr(feature = "thiserror", derive(thiserror::Error))] +pub enum Error { + #[cfg_attr(feature = "thiserror", error("Framing error"))] + Framing, + #[cfg_attr(feature = "thiserror", error("Noise error"))] + Noise, + #[cfg_attr(feature = "thiserror", error("RX buffer overrun"))] + Overrun, + #[cfg_attr(feature = "thiserror", error("Parity check error"))] + Parity, + #[cfg_attr(feature = "thiserror", error("Buffer too large for DMA"))] + BufferTooLong, + + // Author note: I strongly dislike non-exhaustive for this reason. I want to + // know I handle every error case at compile time that is why we have a type + // system! Now I can update the code and run into an unhandled error years + // after the update. The opsession with never increasing major versions that + // has caused this spread of non-exhaustive needs to stop. + #[cfg_attr(feature = "thiserror", error("A new error was added upstream unknown to the protocol and it occurred, please update the From for UsartError implementation"))] + NewUnhandledError, +} + +impl From for Error { + fn from(err: embassy_stm32::usart::Error) -> Self { + use embassy_stm32::usart::Error; + + match err { + Error::Framing => Self::Framing, + Error::Noise => Self::Noise, + Error::Overrun => Self::Overrun, + Error::Parity => Self::Parity, + Error::BufferTooLong => Self::BufferTooLong, + _ => Self::NewUnhandledError, + } + } +} diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index ea0b24c5..b6dbcc3d 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -1,81 +1,51 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; -use crate::button_enum; -use crate::extended_errors::I2cError; +pub mod bed; +pub mod desk; -button_enum! { - /// No these are not borg, these are buttons on a string of cat5. - /// They are numbered starting at the farthest from the end - DeskButton { - OneOfFour, - TwoOfFour, - ThreeOfFour, - FourOfFour, - OneOfThree, - TwoOfThree, - ThirdOfThree, - } +#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] +pub enum Reading { + Bed(bed::Reading), + Desk(desk::Reading), } -button_enum! { - /// All button are on the headboard of the bed. As seen from the foot of the - /// bed it looks like this: - /// - /// LR----------------------------| - /// |--------------|--------------| - /// |-----------321|123-----------| - /// |654-----------|-----------456| - /// - /// Legend: - /// L: TopLeft, R: TopRight, 1: MiddleInner, 2: MiddleCenter, 3: MiddleOuter, - /// 4: OuterInner, 5: OuterCenter, 6: OuterOuter - BedButton { - TopLeft, - TopRight, - MiddleInner, - MiddleCenter, - MiddleOuter, - LowerInner, - LowerCenter, - LowerOuter, - } +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +pub enum Error { + Bed(bed::Error), + Desk(desk::Error), } -#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] -pub enum LargeBedroom { - Brightness(f32), - Temperature(f32), - Humidity(f32), - GassResistance(f32), // in Ohm - Pressure(f32), - /// parts per million - Co2(u16), - /// weight on the left side of the bed - WeightLeft(u32), - /// weight on the right side of the bed - WeightRight(u32), - DeskButton(DeskButton), - BedButton(BedButton), +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +pub enum Device { + Bed(bed::Device), + Desk(desk::Device), } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] -pub enum SensorError { - Sht31(sht31::error::SHTError), - Bme680(bosch_bme680::BmeError), - Max44(max44009::Error), -} -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] -pub enum Device { - Sht31, - Bme680, - Max44, +#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] +pub enum Actuator { + CleanSensor, + CalibrateCo2, } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] -pub enum Error { - Running(SensorError), - Setup(SensorError), - SetupTimedOut(Device), +impl Actuator { + #[cfg(feature = "alloc")] + pub fn encode(&self) -> Vec { + postcard::to_allocvec_cobs(self).expect("Encoding should not fail") + } + + /// Buffer should be at least Self::ENCODED_SIZE long. The returned slice contains + /// the serialized data. It can be shorter then the input buffer. + pub fn encode_slice<'a>(&self, buf: &'a mut [u8]) -> &'a mut [u8] { + postcard::to_slice_cobs(self, buf).expect("Encoding should not fail") + } + + pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { + postcard::from_bytes_cobs(bytes.as_mut()).map_err(crate::DecodeError) + } + + pub fn version(&self) -> u8 { + 0 + } } diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs new file mode 100644 index 00000000..509792ee --- /dev/null +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -0,0 +1,172 @@ +use crate::button_enum; +use crate::downcast_err::{I2cError, UartError}; + +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +button_enum! { + /// All button are on the headboard of the bed. As seen from the foot of the + /// bed it looks like this: + /// + /// LR----------------------------| + /// |--------------|--------------| + /// |-----------321|123-----------| + /// |654-----------|-----------456| + /// + /// Legend: + /// L: TopLeft, R: TopRight, 1: MiddleInner, 2: MiddleCenter, 3: MiddleOuter, + /// 4: OuterInner, 5: OuterCenter, 6: OuterOuter + Button { + TopLeft, + TopRight, + MiddleInner, + MiddleCenter, + MiddleOuter, + LowerInner, + LowerCenter, + LowerOuter, + } +} + +#[derive( + strum::EnumDiscriminants, Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, +)] +#[strum_discriminants(derive(Hash))] +pub enum Reading { + Button(Button), + Brightness(f32), + Temperature(f32), + Humidity(f32), + GassResistance(f32), // in Ohm + Pressure(f32), + /// parts per million + Co2(u16), + /// weight on the left side of the bed + WeightLeft(u32), + /// weight on the right side of the bed + WeightRight(u32), + + /// Mass Concentration PM1.0 \[μg/m³\] + MassPm1_0(f32), + /// Mass Concentration PM2.5 \[μg/m³\] + MassPm2_5(f32), + /// Mass Concentration PM4.0 \[μg/m³\] + MassPm4_0(f32), + /// Mass Concentration PM10 \[μg/m³\] + MassPm10(f32), + /// Number Concentration PM0.5 \[#/cm³\] + MassPm0_5(f32), + /// Number Concentration PM1.0 \[#/cm³\] + NumberPm1_0(f32), + /// Number Concentration PM2.5 \[#/cm³\] + NumberPm2_5(f32), + /// Number Concentration PM4.0 \[#/cm³\] + NumberPm4_0(f32), + /// Number Concentration PM10 \[#/cm³\] + NumberPm10(f32), + /// Typical Particle Size8 \[μm\] + TypicalParticleSize(f32), +} + +impl Into for Reading { + fn into(self) -> f32 { + match self { + Reading::Brightness(val) => val, + Reading::Temperature(val) => val, + Reading::Humidity(val) => val, + Reading::GassResistance(val) => val, + Reading::Pressure(val) => val, + Reading::Co2(val) => val as f32, + Reading::WeightLeft(val) => val as f32, + Reading::WeightRight(val) => val as f32, + Reading::Button(val) => val.into(), + Reading::MassPm1_0(val) => val, + Reading::MassPm2_5(val) => val, + Reading::MassPm4_0(val) => val, + Reading::MassPm10(val) => val, + Reading::MassPm0_5(val) => val, + Reading::NumberPm1_0(val) => val, + Reading::NumberPm2_5(val) => val, + Reading::NumberPm4_0(val) => val, + Reading::NumberPm10(val) => val, + Reading::TypicalParticleSize(val) => val, + } + } +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +pub enum Error { + Running(SensorError), + Setup(SensorError), + SetupTimedOut(Device), + Timeout(Device), +} + +impl Error { + pub fn broken_readings(&self) -> &[ReadingDiscriminants] { + match self { + Self::Running(sensor_err) | Self::Setup(sensor_err) => sensor_err.broken_readings(), + Self::SetupTimedOut(device) | Self::Timeout(device) => device.broken_readings(), + } + } +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +pub enum SensorError { + Sht31(sht31::error::SHTError), + Bme680(bosch_bme680::BmeError), + Max44(max44009::Error), + Mhz14(mhzx::Error), + Sps30(sps30_async::Error), +} + +impl SensorError { + pub fn broken_readings(&self) -> &[ReadingDiscriminants] { + let device = match self { + SensorError::Sht31(_) => Device::Sht31, + SensorError::Bme680(_) => Device::Bme680, + SensorError::Max44(_) => Device::Max44, + SensorError::Mhz14(_) => Device::Mhz14, + SensorError::Sps30(_) => Device::Sps30, + }; + device.broken_readings() + } +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +pub enum Device { + Sht31, + Bme680, + Max44, + Mhz14, + Sps30, +} + +impl Device { + pub fn broken_readings(&self) -> &'static [ReadingDiscriminants] { + match self { + Device::Sht31 => &[ + ReadingDiscriminants::Temperature, + ReadingDiscriminants::Humidity, + ], + Device::Bme680 => &[ + ReadingDiscriminants::GassResistance, + ReadingDiscriminants::Pressure, + ], + Device::Max44 => &[ReadingDiscriminants::Brightness], + Device::Mhz14 => &[ReadingDiscriminants::Co2], + Device::Sps30 => &[ + ReadingDiscriminants::MassPm1_0, + ReadingDiscriminants::MassPm2_5, + ReadingDiscriminants::MassPm4_0, + ReadingDiscriminants::MassPm10, + ReadingDiscriminants::MassPm0_5, + ReadingDiscriminants::NumberPm1_0, + ReadingDiscriminants::NumberPm2_5, + ReadingDiscriminants::NumberPm4_0, + ReadingDiscriminants::NumberPm10, + ReadingDiscriminants::TypicalParticleSize, + ], + } + } +} diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs new file mode 100644 index 00000000..23c6d4c4 --- /dev/null +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -0,0 +1,101 @@ +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +use crate::button_enum; +use crate::downcast_err::{LinuxI2cError, RpiButtonError}; + +button_enum! { + /// No these are not borg, these are buttons on a string of cat5. + /// They are numbered starting at the farthest from the end + Button { + OneOfFour, + TwoOfFour, + ThreeOfFour, + FourOfFour, + OneOfThree, + TwoOfThree, + ThreeOfThree, + } +} + +#[derive( + strum::EnumDiscriminants, Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, +)] +#[strum_discriminants(derive(Hash))] +pub enum Reading { + Temperature(f32), + Humidity(f32), + Pressure(f32), + Button(Button), +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +pub enum Error { + Running(SensorError), + Setup(SetupError), + SetupTimedOut(Device), + Timeout(Device), +} + +impl Error { + pub fn broken_readings(&self) -> &[ReadingDiscriminants] { + match self { + Self::Running(sensor_err) => sensor_err.broken_readings(), + Self::Setup(sensor_err) => sensor_err.broken_readings(), + Self::SetupTimedOut(device) | Self::Timeout(device) => device.broken_readings(), + } + } +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +pub enum SetupError { + BmeError(bme280::Error), + Gpio(RpiButtonError), + I2c(LinuxI2cError), +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +pub enum SensorError { + BmeError(bme280::Error), + Gpio(RpiButtonError), +} + +impl SensorError { + pub fn broken_readings(&self) -> &'static [ReadingDiscriminants] { + let device = match self { + SensorError::BmeError(_) => Device::Bme280, + SensorError::Gpio(_) => Device::Gpio, + }; + + device.broken_readings() + } +} + +impl SetupError { + pub fn broken_readings(&self) -> &'static [ReadingDiscriminants] { + let device = match self { + SetupError::BmeError(_) | SetupError::I2c(_) => Device::Bme280, + SetupError::Gpio(_) => Device::Gpio, + }; + + device.broken_readings() + } +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +pub enum Device { + Bme280, + Gpio, +} + +impl Device { + pub fn broken_readings(&self) -> &'static [ReadingDiscriminants] { + match self { + Device::Bme280 => &[ + ReadingDiscriminants::Temperature, + ReadingDiscriminants::Humidity, + ], + Device::Gpio => todo!(), + } + } +} diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 96dcc7b9..828efa52 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; pub mod large_bedroom; pub mod small_bedroom; -pub mod extended_errors; +pub mod downcast_err; /// turns an enum of empty variants into one with [`Press`](crate::Press) inside each variant also /// adds a method `press(&self)` that returns an instance of [`Press`](crate::Press). It can be @@ -25,6 +25,7 @@ macro_rules! button_enum { ( $(#[$outer:meta])* $name:ident {$($variant:ident,)*}) => { + #[derive(strum::VariantNames)] #[derive( Clone, Copy, @@ -35,6 +36,7 @@ macro_rules! button_enum { postcard::experimental::max_size::MaxSize )] $(#[$outer])* // docs + #[repr(u8)] pub enum $name { $($variant(crate::Press),)* } @@ -46,6 +48,15 @@ macro_rules! button_enum { } } } + + impl Into for $name { + fn into(self) -> f32 { + match self { + $(Self::$variant(p) if p.is_long() => 2.0,)* + $(Self::$variant(_) => 1.0,)* + } + } + } }; } pub(crate) use button_enum; @@ -72,16 +83,19 @@ impl Press { } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] -pub enum Sensor { - LargeBedroomError(large_bedroom::Error), - LargeBedroom(large_bedroom::LargeBedroom), - SmallBedroom(small_bedroom::SmallBedroom), - #[cfg(test)] +#[derive(strum::VariantNames, Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] +pub enum Reading { + LargeBedroom(large_bedroom::Reading), + // SmallBedroom(small_bedroom::Reading), Test, } -impl Sensor { +#[derive(strum::VariantNames, Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] +pub enum Error { + LargeBedroom(large_bedroom::Error), +} + +impl Reading { pub fn version() -> u8 { 0u8 } @@ -89,15 +103,20 @@ impl Sensor { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SensorMessage { - pub values: heapless::Vec, + pub values: heapless::Vec, MAX_ITEMS>, pub version: u8, } +#[derive(Debug, Clone)] +#[cfg_attr(feature = "thiserror", derive(thiserror::Error))] +#[cfg_attr(feature = "thiserror", error("Could not decode SensorMessage: {0}"))] +pub struct DecodeError(pub postcard::Error); + impl SensorMessage { /// the 2x is the max overhead from COBS encoding the encoded data /// +2 is for the version /// +4 covers the length of the heapless list - pub const ENCODED_SIZE: usize = 2 * (MAX_ITEMS * Sensor::POSTCARD_MAX_SIZE + 2 + 4); + pub const ENCODED_SIZE: usize = 2 * (MAX_ITEMS * Reading::POSTCARD_MAX_SIZE + 2 + 4); pub fn new() -> Self { Self { @@ -121,31 +140,11 @@ impl SensorMessage { postcard::to_slice_cobs(self, buf).expect("Encoding should not fail") } - pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { - postcard::from_bytes_cobs(bytes.as_mut()) + pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { + postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeError) } pub fn version(&self) -> u8 { self.version } } - -// #[cfg(test)] -// mod test { -// use super::*; -// -// #[test] -// fn decode_from_different_max_items() { -// let mut values = heapless::Vec::new(); -// values.push(Sensor::Test).unwrap(); -// let mut bytes = SensorMessage::<1> { -// values: values.clone(), -// version: 0u8, -// } -// .encode(); -// -// let decoded: SensorMessage<100> = SensorMessage::<100>::decode(&mut bytes).unwrap(); -// -// assert_eq!(decoded.values.to_vec(), values.to_vec()); -// } -// } diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 00000000..0fa740be --- /dev/null +++ b/deploy.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +set -e + +BUILD_ARG=$1 +DIR=debug; +if [[ "$BUILD_ARG" == "--release" ]]; then + DIR=release +fi + +SERVER="sgc" # ssh config name or full address + +cross build --target=aarch64-unknown-linux-gnu $BUILD_ARG +rsync -vh --progress \ + target/aarch64-unknown-linux-gnu/$DIR/brain \ + $SERVER:/tmp/ + +cmds=" +sudo mv /tmp/brain /home/ha/brain +sudo chown ha:ha /home/ha/brain +sudo systemctl restart ha +" + +ssh -t sgc "$cmds" diff --git a/deploy_optimized.sh b/deploy_optimized.sh new file mode 100755 index 00000000..2dbdbf45 --- /dev/null +++ b/deploy_optimized.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +source deploy.sh "--release" From c50a88c381c07b5e4d93e3813d2d5bd755ea49b3 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 24 May 2024 23:44:43 +0200 Subject: [PATCH 088/687] vendored desk_sensors (running on pi) into ha --- Cargo.lock | 221 +- crates/brain/src/controller/rooms/kitchen.rs | 5 +- .../src/controller/rooms/large_bedroom.rs | 31 +- .../src/controller/rooms/small_bedroom.rs | 9 +- crates/brain/src/input/api.rs | 2 +- crates/desk_sensors/.gitignore | 1 + crates/desk_sensors/Cargo.lock | 1789 +++++++++++++++++ crates/desk_sensors/Cargo.toml | 21 + crates/desk_sensors/deploy.sh | 24 + crates/desk_sensors/src/buttons.rs | 87 + crates/desk_sensors/src/main.rs | 93 + crates/desk_sensors/src/sensors.rs | 64 + crates/protocol/Cargo.toml | 2 + crates/protocol/src/downcast_err.rs | 2 +- .../protocol/src/downcast_err/rpi_button.rs | 128 +- crates/protocol/src/large_bedroom/desk.rs | 6 +- 16 files changed, 2444 insertions(+), 41 deletions(-) create mode 100644 crates/desk_sensors/.gitignore create mode 100644 crates/desk_sensors/Cargo.lock create mode 100644 crates/desk_sensors/Cargo.toml create mode 100755 crates/desk_sensors/deploy.sh create mode 100644 crates/desk_sensors/src/buttons.rs create mode 100644 crates/desk_sensors/src/main.rs create mode 100644 crates/desk_sensors/src/sensors.rs diff --git a/Cargo.lock b/Cargo.lock index aca3fffe..b5dee844 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -288,6 +288,7 @@ version = "0.5.1" source = "git+https://github.com/dvdsk/bme280-rs#4999b005d26a16312acb3dbc64b72658df49a16d" dependencies = [ "defmt", + "derive_more", "embedded-hal 1.0.0", "maybe-async-cfg", "postcard", @@ -489,6 +490,33 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" +[[package]] +name = "color-eyre" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + [[package]] name = "colorchoice" version = "1.0.1" @@ -521,6 +549,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "cookie" version = "0.12.0" @@ -658,7 +692,7 @@ dependencies = [ "crossbeam-utils 0.7.2", "lazy_static", "maybe-uninit", - "memoffset", + "memoffset 0.5.6", "scopeguard", ] @@ -749,6 +783,36 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn 1.0.109", +] + +[[package]] +name = "desk_sensors" +version = "0.2.0" +dependencies = [ + "bme280", + "clap", + "color-eyre", + "embedded-hal-async", + "gpiocdev-embedded-hal", + "linux-embedded-hal", + "protocol", + "tokio 1.37.0", + "tracing", + "tracing-error", + "tracing-subscriber", +] + [[package]] name = "document-features" version = "0.2.8" @@ -1003,6 +1067,16 @@ dependencies = [ "backtrace", ] +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + [[package]] name = "failure" version = "0.1.8" @@ -1257,6 +1331,54 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "gpio-cdev" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09831ec59b80be69e75d29cf36e16afbbe5fd1af9c1bf4689ad91c77db5aa6a6" +dependencies = [ + "bitflags 2.5.0", + "libc", + "nix 0.27.1", +] + +[[package]] +name = "gpiocdev" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5119c89eccee09c4f6e9ca2b112aea1cd80bac31cd29169f171a48ae5552d1c" +dependencies = [ + "futures 0.3.30", + "gpiocdev-uapi", + "thiserror", + "tokio 1.37.0", + "tokio-stream", +] + +[[package]] +name = "gpiocdev-embedded-hal" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26476d24320fe1b9ebc76392f984abe4a6147844c7e5a69538318f15b026cca8" +dependencies = [ + "embedded-hal 1.0.0", + "embedded-hal-async", + "gpiocdev", + "thiserror", +] + +[[package]] +name = "gpiocdev-uapi" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a02357253f833a6ce4e93f17e8dd3e169c941ea71b83d442ed9c55f784045204" +dependencies = [ + "bitflags 2.5.0", + "ioctl-sys", + "libc", + "thiserror", +] + [[package]] name = "h2" version = "0.1.26" @@ -1645,6 +1767,12 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + [[package]] name = "indexmap" version = "1.9.3" @@ -1684,6 +1812,12 @@ dependencies = [ "mach2", ] +[[package]] +name = "ioctl-sys" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bd11f3a29434026f5ff98c730b668ba74b1033637b8817940b54d040696133c" + [[package]] name = "iovec" version = "0.1.4" @@ -1757,10 +1891,13 @@ dependencies = [ "cast", "embedded-hal 1.0.0", "embedded-hal-nb", + "gpio-cdev", "i2cdev", "nb 1.1.0", "nix 0.27.1", "serialport", + "spidev", + "sysfs_gpio", ] [[package]] @@ -1879,6 +2016,24 @@ dependencies = [ "autocfg 1.3.0", ] +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg 1.3.0", +] + +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg 1.3.0", +] + [[package]] name = "mhzx" version = "0.3.0" @@ -1994,6 +2149,19 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "nix" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +dependencies = [ + "bitflags 1.3.2", + "cc", + "cfg-if 1.0.0", + "libc", + "memoffset 0.6.5", +] + [[package]] name = "nix" version = "0.26.4" @@ -2003,6 +2171,8 @@ dependencies = [ "bitflags 1.3.2", "cfg-if 1.0.0", "libc", + "memoffset 0.7.1", + "pin-utils", ] [[package]] @@ -2084,6 +2254,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + [[package]] name = "parking" version = "2.2.0" @@ -2300,6 +2476,8 @@ dependencies = [ "embassy-embedded-hal", "embassy-stm32", "embedded-hal 1.0.0", + "gpiocdev", + "gpiocdev-embedded-hal", "heapless 0.8.0", "linux-embedded-hal", "max44009", @@ -2979,6 +3157,17 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "spidev" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2800c129338c77998c1dcb6d4200447e018beb7d29959eb104cba2d45f83c1a" +dependencies = [ + "bitflags 2.5.0", + "libc", + "nix 0.26.4", +] + [[package]] name = "spin" version = "0.5.2" @@ -3116,6 +3305,15 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "sysfs_gpio" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8808c55bc926565c62ef7838bcaa8add51585236803e2bdfa1472e3a3ab5e17" +dependencies = [ + "nix 0.23.2", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -3363,6 +3561,17 @@ dependencies = [ "tokio 1.37.0", ] +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio 1.37.0", +] + [[package]] name = "tokio-sync" version = "0.1.8" @@ -3490,6 +3699,16 @@ dependencies = [ "valuable", ] +[[package]] +name = "tracing-error" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +dependencies = [ + "tracing", + "tracing-subscriber", +] + [[package]] name = "tracing-journald" version = "0.3.0" diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index 08ce5199..2609fbca 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -4,7 +4,6 @@ use futures_concurrency::future::Race; use futures_util::FutureExt; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; -use tracing::{instrument, warn}; use crate::controller::{local_now, Event, RestrictedSystem}; @@ -49,7 +48,7 @@ fn filter(event: Event) -> Option { pub async fn run( mut event_rx: broadcast::Receiver, // todo if state change message everyone using this - event_tx: broadcast::Sender, + _event_tx: broadcast::Sender, mut system: RestrictedSystem, ) { enum Res { @@ -57,7 +56,7 @@ pub async fn run( ShouldUpdate, } - let state = State::Normal; + let _state = State::Normal; let mut next_update = Instant::now() + INTERVAL; loop { let get_event = event_rx.recv_filter_mapped(filter).map(Res::Event); diff --git a/crates/brain/src/controller/rooms/large_bedroom.rs b/crates/brain/src/controller/rooms/large_bedroom.rs index 3c2486d5..fbcd45bd 100644 --- a/crates/brain/src/controller/rooms/large_bedroom.rs +++ b/crates/brain/src/controller/rooms/large_bedroom.rs @@ -4,7 +4,6 @@ use futures_concurrency::future::Race; use futures_util::FutureExt; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; -use tracing::warn; use crate::controller::{local_now, Event, RestrictedSystem}; @@ -35,15 +34,15 @@ impl RecvFiltered for broadcast::Receiver { #[derive(Debug)] enum RelevantEvent { WakeUp, - WeightLeft(u32), - WeightRight(u32), - Brightness(f32), // millilux + // WeightLeft(u32), + // WeightRight(u32), + // Brightness(f32), // millilux DeskButton(protocol::large_bedroom::desk::Button), - BedButton(protocol::large_bedroom::bed::Button), + // BedButton(protocol::large_bedroom::bed::Button), } fn filter(event: Event) -> Option { - use protocol::large_bedroom::bed::Reading as B; + // use protocol::large_bedroom::bed::Reading as B; use protocol::large_bedroom::desk::Reading as D; use protocol::large_bedroom::Reading as R; use protocol::Reading::LargeBedroom as LB; @@ -52,10 +51,10 @@ fn filter(event: Event) -> Option { Some(match event { WakeUp => RelevantEvent::WakeUp, Sensor(LB(R::Desk(D::Button(b)))) => RelevantEvent::DeskButton(b), - Sensor(LB(R::Bed(B::Button(b)))) => RelevantEvent::BedButton(b), - Sensor(LB(R::Bed(B::Brightness(l)))) => RelevantEvent::Brightness(l), - Sensor(LB(R::Bed(B::WeightLeft(w)))) => RelevantEvent::WeightLeft(w), - Sensor(LB(R::Bed(B::WeightRight(w)))) => RelevantEvent::WeightRight(w), + // Sensor(LB(R::Bed(B::Button(b)))) => RelevantEvent::BedButton(b), + // Sensor(LB(R::Bed(B::Brightness(l)))) => RelevantEvent::Brightness(l), + // Sensor(LB(R::Bed(B::WeightLeft(w)))) => RelevantEvent::WeightLeft(w), + // Sensor(LB(R::Bed(B::WeightRight(w)))) => RelevantEvent::WeightRight(w), _ => return None, }) } @@ -108,7 +107,15 @@ fn handle_event(e: RelevantEvent) { // use RelevantEvent as R; match e { - // R::DeskButton(DeskButton::OneOfFour(p)) if p.is_long() => (), - unhandled => warn!("Unhandled relevant event: {unhandled:?}"), + RelevantEvent::WakeUp => (), + // RelevantEvent::WeightLeft(_) => (), + // RelevantEvent::WeightRight(_) => (), + // RelevantEvent::Brightness(_) => (), + RelevantEvent::DeskButton(b) => handle_button(b), + // RelevantEvent::BedButton(_) => (), } } + +fn handle_button(b: protocol::large_bedroom::desk::Button) { + println!("button pressed: {b:?}"); +} diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 28714274..7c1c88aa 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -4,15 +4,14 @@ use futures_concurrency::future::Race; use futures_util::FutureExt; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; -use tracing::warn; use crate::controller::{local_now, Event, RestrictedSystem}; enum State { - Sleep, - Wakeup, + _Sleep, + _Wakeup, Normal, - Away, + _Away, } const INTERVAL: Duration = Duration::from_secs(5); @@ -57,7 +56,7 @@ pub async fn run( ShouldUpdate, } - let state = State::Normal; + let _state = State::Normal; let mut next_update = Instant::now() + INTERVAL; loop { let get_event = event_rx.recv_filter_mapped(filter).map(Res::Event); diff --git a/crates/brain/src/input/api.rs b/crates/brain/src/input/api.rs index fd5df8ec..693f7219 100644 --- a/crates/brain/src/input/api.rs +++ b/crates/brain/src/input/api.rs @@ -70,7 +70,7 @@ async fn sensor_event(aState(state): aState, body: Bytes) { } }; // in future convert from older protocol here - for value in msg.values { + for value in msg.values.into_iter().filter_map(Result::ok) { state.event_tx.send(Event::Sensor(value)).unwrap(); } } diff --git a/crates/desk_sensors/.gitignore b/crates/desk_sensors/.gitignore new file mode 100644 index 00000000..ea8c4bf7 --- /dev/null +++ b/crates/desk_sensors/.gitignore @@ -0,0 +1 @@ +/target diff --git a/crates/desk_sensors/Cargo.lock b/crates/desk_sensors/Cargo.lock new file mode 100644 index 00000000..261ab945 --- /dev/null +++ b/crates/desk_sensors/Cargo.lock @@ -0,0 +1,1789 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "bitfield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "bme280" +version = "0.5.1" +source = "git+https://github.com/dvdsk/bme280-rs#4999b005d26a16312acb3dbc64b72658df49a16d" +dependencies = [ + "defmt", + "derive_more", + "embedded-hal 1.0.0", + "maybe-async-cfg", + "postcard", + "serde", +] + +[[package]] +name = "bosch-bme680" +version = "1.0.2" +source = "git+https://github.com/dvdsk/async-bosch-bme680#455d5d3194f137d9e0403779badc645e1bad7a05" +dependencies = [ + "bitfield 0.14.0", + "defmt", + "embedded-hal 1.0.0", + "embedded-hal-async", + "postcard", + "serde", + "thiserror", +] + +[[package]] +name = "bxcan" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ac3d0c0a542d0ab5521211f873f62706a7136df415676f676d347e5a41dd80" +dependencies = [ + "bitflags 1.3.2", + "embedded-hal 0.2.7", + "nb 1.1.0", + "vcell", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cc" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + +[[package]] +name = "color-eyre" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "const_format" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal", + "bitfield 0.13.2", + "embedded-hal 0.2.7", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + +[[package]] +name = "defmt" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb" +dependencies = [ + "defmt-parser", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "defmt-parser" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" +dependencies = [ + "thiserror", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn 1.0.109", +] + +[[package]] +name = "desk_sensors" +version = "0.2.0" +dependencies = [ + "bme280", + "clap", + "color-eyre", + "gpio-cdev", + "linux-embedded-hal", + "nix 0.29.0", + "protocol", + "tracing", + "tracing-error", + "tracing-subscriber", +] + +[[package]] +name = "document-features" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +dependencies = [ + "litrs", +] + +[[package]] +name = "embassy-embedded-hal" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca4a9380d03e61063067b8239f67d2fa9f108ede7c46b4273804f6b79e59a1d" +dependencies = [ + "embassy-futures", + "embassy-sync", + "embassy-time", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-storage", + "embedded-storage-async", + "nb 1.1.0", +] + +[[package]] +name = "embassy-futures" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f878075b9794c1e4ac788c95b728f26aa6366d32eeb10c7051389f898f7d067" + +[[package]] +name = "embassy-hal-internal" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0ec47cf8bab914018d4bd2b4f0aaeb46e4f52ab1e7985df88aeef2c6eda5aed" +dependencies = [ + "cortex-m", + "critical-section", + "num-traits", +] + +[[package]] +name = "embassy-net-driver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d" + +[[package]] +name = "embassy-stm32" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32bc0257b5ade13a1b93e8b9949268f44d57e8ce03e599ef1c5a62024a0fbff9" +dependencies = [ + "bit_field", + "bxcan", + "cfg-if", + "cortex-m", + "cortex-m-rt", + "critical-section", + "document-features", + "embassy-embedded-hal", + "embassy-futures", + "embassy-hal-internal", + "embassy-net-driver", + "embassy-sync", + "embassy-usb-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-nb", + "embedded-io 0.6.1", + "embedded-io-async", + "embedded-storage", + "embedded-storage-async", + "futures", + "nb 1.1.0", + "proc-macro2", + "quote", + "rand_core", + "sdio-host", + "stm32-fmc", + "stm32-metapac", + "vcell", +] + +[[package]] +name = "embassy-sync" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd938f25c0798db4280fcd8026bf4c2f48789aebf8f77b6e5cf8a7693ba114ec" +dependencies = [ + "cfg-if", + "critical-section", + "embedded-io-async", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c844070d9f80dc66ee739299183312baee2e1cdeb6e90b4ea2af44f4676da5" +dependencies = [ + "cfg-if", + "critical-section", + "document-features", + "embassy-time-driver", + "embassy-time-queue-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time-driver" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e0c214077aaa9206958b16411c157961fb7990d4ea628120a78d1a5a28aed24" +dependencies = [ + "document-features", +] + +[[package]] +name = "embassy-time-queue-driver" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1177859559ebf42cd24ae7ba8fe6ee707489b01d0bf471f8827b7b12dcb0bc0" + +[[package]] +name = "embassy-usb-driver" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fc247028eae04174b6635104a35b1ed336aabef4654f5e87a8f32327d231970" + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "defmt", + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" +dependencies = [ + "embedded-hal 1.0.0", + "nb 1.1.0", +] + +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-io-async" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" +dependencies = [ + "defmt", + "embedded-io 0.6.1", +] + +[[package]] +name = "embedded-storage" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" + +[[package]] +name = "embedded-storage-async" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc" +dependencies = [ + "embedded-storage", +] + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-macro", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "gpio-cdev" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09831ec59b80be69e75d29cf36e16afbbe5fd1af9c1bf4689ad91c77db5aa6a6" +dependencies = [ + "bitflags 2.5.0", + "libc", + "nix 0.27.1", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version 0.4.0", + "serde", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32 0.3.1", + "serde", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "i2cdev" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597f56d08cebc0fb3e67d49f48124f49e1c7ac297a21d60bc90a28b9482fb35c" +dependencies = [ + "bitflags 2.5.0", + "byteorder", + "libc", + "nix 0.26.4", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "io-kit-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b" +dependencies = [ + "core-foundation-sys", + "mach2", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "linux-embedded-hal" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d566b726e1b6810f66c6f1c769889248439c27f06a59df2881a735454cfa02" +dependencies = [ + "cast", + "embedded-hal 1.0.0", + "embedded-hal-nb", + "gpio-cdev", + "i2cdev", + "nb 1.1.0", + "nix 0.27.1", + "serialport", + "spidev", + "sysfs_gpio", +] + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "max44009" +version = "0.2.0" +source = "git+https://github.com/dvdsk/max44009-rs#7b7df2e3173476c250fca3eb242f0dd366857599" +dependencies = [ + "defmt", + "embedded-hal-async", + "postcard", + "serde", + "thiserror", +] + +[[package]] +name = "maybe-async-cfg" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21fb8fac02158b9b529eb692491895d8459dbac939f3bc6e32159969646ffe55" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "pulldown-cmark", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mhzx" +version = "0.3.0" +source = "git+https://github.com/dvdsk/mhzx#08f6e7adb4ec98749fa84f24f8ff9e0e3c83d164" +dependencies = [ + "defmt", + "embedded-io-async", + "heapless 0.8.0", + "postcard", + "serde", + "thiserror", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +dependencies = [ + "adler", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "nix" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +dependencies = [ + "bitflags 1.3.2", + "cc", + "cfg-if", + "libc", + "memoffset 0.6.5", +] + +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.7.1", + "pin-utils", +] + +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "libc", +] + +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "cfg_aliases 0.1.1", + "libc", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "cfg_aliases 0.2.1", + "libc", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "postcard" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +dependencies = [ + "cobs", + "const_format", + "embedded-io 0.4.0", + "heapless 0.7.17", + "postcard-derive", + "serde", +] + +[[package]] +name = "postcard-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4b01218787dd4420daf63875163a787a78294ad48a24e9f6fa8c6507759a79" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "protocol" +version = "0.1.0" +dependencies = [ + "bme280", + "bosch-bme680", + "defmt", + "embassy-embedded-hal", + "embassy-stm32", + "embedded-hal 1.0.0", + "heapless 0.8.0", + "linux-embedded-hal", + "max44009", + "mhzx", + "nix 0.28.0", + "postcard", + "serde", + "sht31", + "sps30-async", + "strum", +] + +[[package]] +name = "pulldown-cmark" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" +dependencies = [ + "bitflags 2.5.0", + "memchr", + "unicase", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.3", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.23", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sdio-host" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93c025f9cfe4c388c328ece47d11a54a823da3b5ad0370b22d95ad47137f85a" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.202" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.202" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "serialport" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5a15d0be940df84846264b09b51b10b931fb2f275becb80934e3568a016828" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "core-foundation-sys", + "io-kit-sys", + "mach2", + "nix 0.26.4", + "regex", + "scopeguard", + "unescaper", + "winapi", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "sht31" +version = "0.3.1" +source = "git+https://github.com/dvdsk/SHT31-rs#a7b6bd94fb137e16bf326eff5fb591624369a2cf" +dependencies = [ + "crc", + "defmt", + "embedded-hal-async", + "postcard", + "serde", + "thiserror", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "spidev" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2800c129338c77998c1dcb6d4200447e018beb7d29959eb104cba2d45f83c1a" +dependencies = [ + "bitflags 2.5.0", + "libc", + "nix 0.26.4", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "sps30-async" +version = "0.2.0" +source = "git+https://github.com/dvdsk/sps30-async#a5e81ec034727442c048acea2e8eb07fe4be78e4" +dependencies = [ + "defmt", + "embedded-hal-async", + "embedded-io-async", + "heapless 0.8.0", + "postcard", + "serde", + "thiserror", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stm32-fmc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830ed60f33e6194ecb377f5d6ab765dc0e37e7b65e765f1fa87df13336658d63" +dependencies = [ + "embedded-hal 0.2.7", +] + +[[package]] +name = "stm32-metapac" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deabea56a8821dcea05d0109f3ab3135f31eb572444e5da203d06149c594c8c6" +dependencies = [ + "cortex-m", + "cortex-m-rt", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.66", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sysfs_gpio" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8808c55bc926565c62ef7838bcaa8add51585236803e2bdfa1472e3a3ab5e17" +dependencies = [ + "nix 0.23.2", +] + +[[package]] +name = "thiserror" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "unescaper" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0adf6ad32eb5b3cadff915f7b770faaac8f7ff0476633aa29eb0d9584d889d34" +dependencies = [ + "thiserror", +] + +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/crates/desk_sensors/Cargo.toml b/crates/desk_sensors/Cargo.toml new file mode 100644 index 00000000..6de7117d --- /dev/null +++ b/crates/desk_sensors/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "desk_sensors" +version = "0.2.0" +edition.workspace = true +license.workspace = true +authors.workspace = true + +[dependencies] +linux-embedded-hal = "0.4" +gpiocdev-embedded-hal = { version = "0.1.1", features = ["async_tokio"] } +bme280 = { version = "0.5", git = "https://github.com/dvdsk/bme280-rs", features = ["postcard", "serde", "with_std"] } + +clap = { version = "4.5.4", features = ["derive"] } +color-eyre = "0.6.3" +tracing = "0.1.40" +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +tracing-error = "0.2.0" + +protocol = { path = "../protocol", features = ["alloc"] } +tokio = { version = "1.37.0", features = ["rt", "time"] } +embedded-hal-async = "1.0.0" diff --git a/crates/desk_sensors/deploy.sh b/crates/desk_sensors/deploy.sh new file mode 100755 index 00000000..88e639c9 --- /dev/null +++ b/crates/desk_sensors/deploy.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -e + +BUILD_ARG=$1 +SERVER="sgc" # ssh config name or full adress +RELEASE=debug + +if [[ BUILD_ARG == "--release" ]]; then + RELEASE=release +fi + +rustup override set nightly +cross build --target=aarch64-unknown-linux-gnu $BUILD_ARG +rsync -vh --progress \ + target/aarch64-unknown-linux-gnu/$RELEASE/sensor_central \ + $SERVER:/tmp/ + +cmds=" +sudo mv /tmp/sensor_central /home/ha/sensor_central +sudo chown ha:ha /home/ha/sensor_central +sudo systemctl restart sens.service +" + +ssh -t sgc "$cmds" diff --git a/crates/desk_sensors/src/buttons.rs b/crates/desk_sensors/src/buttons.rs new file mode 100644 index 00000000..6d2bf4b9 --- /dev/null +++ b/crates/desk_sensors/src/buttons.rs @@ -0,0 +1,87 @@ +use embedded_hal_async::digital::Wait; +use protocol::{Press, Reading}; +use std::sync::mpsc::Sender; +use std::time::{Duration, Instant}; +use tracing::error; + +use std::thread; + +use protocol::large_bedroom::desk::{Button, SetupError}; + +use crate::{send_error, send_reading}; + +const CHIP: &str = "pinctrl-bcm2835"; + +async fn watch_pin( + offset: u32, + as_button: impl Fn(Press) -> Button, + tx: &Sender>, +) { + use protocol::large_bedroom::desk; + + const DEBOUNCE: Duration = Duration::from_millis(5); + const MAX_PRESS: Duration = Duration::from_secs(5); + + let mut pin = match gpiocdev_embedded_hal::tokio::InputPin::new(CHIP, offset) { + Ok(pin) => pin, + Err(error) => { + error!("error opening gpio {offset} on {CHIP}: {error}"); + let error: protocol::downcast_err::GpioError = error.into(); + let error = desk::Error::Setup(SetupError::Gpio(error)); + send_error(tx, error); + return; + } + }; + + loop { + if let Err(error) = pin.wait_for_rising_edge().await { + error!("error waiting for rising edge for gpio {offset} on {CHIP}: {error}"); + let error: protocol::downcast_err::GpioError = error.into(); + let error = desk::Error::Running(desk::SensorError::Gpio(error)); + send_error(tx, error); + return; + } + + let now = Instant::now(); + match tokio::time::timeout(MAX_PRESS, pin.wait_for_falling_edge()).await { + Ok(Err(error)) => { + error!("error waiting for falling edge for gpio {offset} on {CHIP}: {error}"); + let error: protocol::downcast_err::GpioError = error.into(); + let error = desk::Error::Running(desk::SensorError::Gpio(error)); + send_error(tx, error); + return; + } + Ok(Ok(())) => (), + Err(_timeout) => continue, + } + + let press = now.elapsed(); + if press > DEBOUNCE { + let button = (as_button)(Press(press.as_millis() as u16)); + let reading = desk::Reading::Button(button); + send_reading(tx, reading); + } + } +} + +async fn watch_pins(tx: &Sender>) { + tokio::join!( + watch_pin(27, Button::OneOfThree, tx), + watch_pin(22, Button::TwoOfThree, tx), + watch_pin(18, Button::ThreeOfThree, tx), + watch_pin(23, Button::FourOfFour, tx), + watch_pin(24, Button::ThreeOfFour, tx), + watch_pin(26, Button::TwoOfFour, tx), + watch_pin(17, Button::OneOfFour, tx), + ); + unreachable!("none of those should return, and never all of them"); +} + +pub fn start_monitoring(tx: Sender>) { + thread::spawn(move || { + let rt = tokio::runtime::Builder::new_current_thread() + .build() + .unwrap(); + rt.block_on(watch_pins(&tx)) + }); +} diff --git a/crates/desk_sensors/src/main.rs b/crates/desk_sensors/src/main.rs new file mode 100644 index 00000000..c33cf98a --- /dev/null +++ b/crates/desk_sensors/src/main.rs @@ -0,0 +1,93 @@ +use clap::Parser; +use color_eyre::Result; +use std::io::{ErrorKind, Write}; +use std::net::{SocketAddr, TcpStream}; +use std::sync::mpsc::{self, Sender}; +use std::time::Duration; + +mod buttons; +mod sensors; + +#[derive(Parser)] +#[command(name = "local sensors")] +#[command(version = "1.0")] +#[command(about = "reads sensors attached to rpi gpio pins and i2c perhipheral")] +struct Cli { + /// where to send the data on the local system + #[arg(short, long, default_value = "1234")] + update_port: u16, +} + +fn main() { + color_eyre::install().unwrap(); + let cli = Cli::parse(); + + setup_tracing().unwrap(); + + let (tx, rx) = mpsc::channel(); + buttons::start_monitoring(tx.clone()); + if let Err(error) = sensors::start_monitoring(tx.clone()) { + send_error(&tx, error); + } + + let mut msg: protocol::SensorMessage<20> = protocol::SensorMessage::new(); + let addr = SocketAddr::from(([127, 0, 0, 1], cli.update_port)); + loop { + let mut stream = match TcpStream::connect(addr) { + Ok(stream) => stream, + Err(err) if err.kind() == ErrorKind::ConnectionRefused => { + std::thread::sleep(Duration::from_secs(5)); + continue; + } + Err(err) => panic!("could not connect to server: {}", err), + }; + + loop { + let result = rx.recv().unwrap(); + msg.values.push(result).expect("capacity > 0"); + while let Ok(result) = rx.try_recv() { + let res = msg.values.push(result); + if res.is_err() { + break; + } + } + let bytes = msg.encode(); + stream.write_all(&bytes).unwrap(); + } + } +} + +fn setup_tracing() -> Result<()> { + use tracing_error::ErrorLayer; + use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt, Layer}; + + let file_subscriber = tracing_subscriber::fmt::layer() + .with_file(true) + .with_line_number(true) + .with_target(false) + .with_ansi(false) + .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()); + tracing_subscriber::registry() + .with(file_subscriber) + .with(ErrorLayer::default()) + .init(); + Ok(()) +} + +fn send_error( + tx: &Sender>, + error: protocol::large_bedroom::desk::Error, +) { + use protocol::large_bedroom::Error::Desk as DeskE; + use protocol::Error::LargeBedroom as LbE; + tx.send(Err(LbE(DeskE(error)))).unwrap(); +} + +fn send_reading( + tx: &Sender>, + reading: protocol::large_bedroom::desk::Reading, +) { + use protocol::large_bedroom::Reading::Desk; + use protocol::Reading::LargeBedroom as Lb; + tx.send(Ok(Lb(Desk(reading)))).unwrap(); +} diff --git a/crates/desk_sensors/src/sensors.rs b/crates/desk_sensors/src/sensors.rs new file mode 100644 index 00000000..dbcef7ca --- /dev/null +++ b/crates/desk_sensors/src/sensors.rs @@ -0,0 +1,64 @@ +use bme280::i2c::BME280 as Bme280; +use bme280::{self, Measurements}; +use hal::{Delay, I2cdev}; +use linux_embedded_hal as hal; +use protocol::downcast_err::ConcreteErrorType; + +use std::sync::mpsc::Sender; +use std::thread; +use std::time::{Duration, Instant}; + +use protocol::large_bedroom::desk::Reading as DeskReading; +use protocol::large_bedroom::desk::{Error, SensorError, SetupError}; +use protocol::Reading; + +use crate::{send_error, send_reading}; + +pub fn init() -> Result, Error> { + let i2c_bus = I2cdev::new("/dev/i2c-1") + .inspect_err(|e| tracing::error!("Could not open i2c bus: {e}")) + .map_err(|e| (&e).into()) + .map_err(|e| Error::Setup(SetupError::I2c(e)))?; + + let mut bme280 = Bme280::new_primary(i2c_bus); + bme280 + .init(&mut Delay) + .inspect_err(|e| tracing::error!("Could not init bme280 sensor: {e}")) + .map_err(|e| e.strip_generics()) + .map_err(|e| Error::Setup(SetupError::BmeError(e)))?; + Ok(bme280) +} + +pub fn start_monitoring(tx: Sender>) -> Result<(), Error> { + let mut bme = init()?; + + let mut last_warning = Instant::now() - Duration::from_secs(10_000); + thread::spawn(move || { + loop { + match bme.measure(&mut Delay) { + Ok(Measurements { + temperature, + pressure, + humidity, + .. + }) => { + send_reading(&tx, DeskReading::Temperature(temperature)); + send_reading(&tx, DeskReading::Humidity(humidity)); + send_reading(&tx, DeskReading::Pressure(pressure)); + } + Err(e) => { + if last_warning.elapsed() > Duration::from_secs(300) { + last_warning = Instant::now(); + tracing::error!("Could not read bme280 sensor: {e}"); + } + let err = e.strip_generics(); + send_error(&tx, Error::Running(SensorError::BmeError(err))) + } + } + + std::thread::sleep(Duration::from_secs(5)); + } + }); + + Ok(()) +} diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index cc19150b..6d404373 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -28,6 +28,8 @@ bme280 = { version = "0.5", git = "https://github.com/dvdsk/bme280-rs", features embassy-stm32 = { version = "0.1.0", features = ["stm32f401cc"] } embassy-embedded-hal = "0.1.0" linux-embedded-hal = { version = "0.4.0", features = ["i2c"], default-features = false } +gpiocdev-embedded-hal = "0.1.1" +gpiocdev = "0.7" nix = "0.28.0" embedded-hal = "1.0.0" diff --git a/crates/protocol/src/downcast_err.rs b/crates/protocol/src/downcast_err.rs index bb0c1837..ac4a987b 100644 --- a/crates/protocol/src/downcast_err.rs +++ b/crates/protocol/src/downcast_err.rs @@ -4,7 +4,7 @@ mod uart; use bosch_bme680::BmeError; pub use i2c::{I2cError, LinuxI2cError}; -pub use rpi_button::RpiButtonError; +pub use rpi_button::GpioError; pub use uart::Error as UartError; pub trait ConcreteErrorType { diff --git a/crates/protocol/src/downcast_err/rpi_button.rs b/crates/protocol/src/downcast_err/rpi_button.rs index 64d5b372..ad761a9a 100644 --- a/crates/protocol/src/downcast_err/rpi_button.rs +++ b/crates/protocol/src/downcast_err/rpi_button.rs @@ -1,36 +1,134 @@ +/// The gpio_cdev::Error is not constant size. The alternative would be to send +/// the error as a fixed size string. The error struct must have a statically +/// determined maximum size to allow encoding/decoding on embedded systems. Thus +/// sending a string is also not an option +/// +/// We could add a second message type with variable message size but we would +/// still need to add serde support to the origonal error use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] #[cfg_attr(feature = "thiserror", derive(thiserror::Error))] -/// The gpio_cdev::Error is not constant size and impossible to inspect. The -/// alternative would be to send the error as a string. The error struct must -/// have a statically determined maximum size to allow encoding/decoding on -/// embedded systems. Thus sending a string is also not an option -pub enum RpiButtonError { +pub enum CdevError { + /// An operation cannot be performed due to a limitation in the ABI version being used. #[cfg_attr( feature = "thiserror", - error("Error interfacing with Linux GPIO interface") + error( + "An operation cannot be performed due to a limitation in the ABI version being used." + ) )] - GpioInterfaceError, + AbiLimitation, + /// Problem accessing GPIO chip character devices #[cfg_attr( feature = "thiserror", - error("Error interfacing with Linux GPIO interface") + error("Problem accessing GPIO chip character devices") )] - GpioChipNotFound, + GpioChip, + /// An error returned when there is a problem with an argument. #[cfg_attr( feature = "thiserror", - error("Error interfacing with Linux GPIO interface") + error("An error returned when there is a problem with an argument.") )] - ListingChips, + InvalidArgument, + /// No gpiochips are available to the user. #[cfg_attr( feature = "thiserror", - error("Error interfacing with Linux GPIO interface") + error("No gpiochips are available to the user.") )] - GettingLine(u32), + NoGpioChips, + /// Returned when the strict mode of find_named_lines finds multiple lines with the same name. + #[cfg_attr(feature = "thiserror", error("Returned when the strict mode of find_named_lines finds multiple lines with the same name."))] + NonuniqueLineName, + /// An error returned from an underlying os call. #[cfg_attr( feature = "thiserror", - error("Error interfacing with Linux GPIO interface") + error("An error returned from an underlying os call.") )] - GetEventValue, + Os, + /// An error returned from an underlying uAPI call. + #[cfg_attr( + feature = "thiserror", + error("An error returned from an underlying uAPI call.") + )] + Uapi, + /// The response to a uAPI command contained unexpected content. + #[cfg_attr( + feature = "thiserror", + error("The response to a uAPI command contained unexpected content.") + )] + UnexpectedResponse, + /// The kernel or build does not support the requested uAPI ABI version. + #[cfg_attr( + feature = "thiserror", + error("The kernel or build does not support the requested uAPI ABI version.") + )] + UnsupportedAbi, + /// The kernel has no support for any uAPI ABI version. + #[cfg_attr( + feature = "thiserror", + error("The kernel has no support for any uAPI ABI version.") + )] + NoAbiSupport, +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +#[cfg_attr(feature = "thiserror", derive(thiserror::Error))] +pub enum GpioError { + /// Requests can only contain a single requested line. + #[cfg_attr( + feature = "thiserror", + error("Requests can only contain a single requested line.") + )] + MultipleLinesRequested, + + /// InputPins must be in input mode. + #[cfg_attr(feature = "thiserror", error("InputPins must be in input mode."))] + RequiresInputMode, + + /// OutputPins must be in output mode. + #[cfg_attr(feature = "thiserror", error("OutputPins must be in output mode."))] + RequiresOutputMode, + + /// Cannot find named line. + #[cfg_attr(feature = "thiserror", error("Cannot find named line."))] + UnfoundLine, + + /// An error returned from an underlying gpiocdev call. + #[cfg_attr( + feature = "thiserror", + error("An error returned from an underlying gpiocdev call.") + )] + Cdev(CdevError), +} + +impl From for GpioError { + fn from(value: gpiocdev_embedded_hal::Error) -> Self { + use gpiocdev_embedded_hal::Error; + match value { + Error::MultipleLinesRequested => GpioError::MultipleLinesRequested, + Error::RequiresInputMode => GpioError::RequiresInputMode, + Error::RequiresOutputMode => GpioError::RequiresOutputMode, + Error::UnfoundLine(_) => GpioError::UnfoundLine, + Error::Cdev(e) => GpioError::Cdev(e.into()), + } + } +} + +impl From for CdevError { + fn from(value: gpiocdev::Error) -> Self { + use gpiocdev::Error; + match value { + Error::AbiLimitation(_, _) => CdevError::AbiLimitation, + Error::GpioChip(_, _) => CdevError::GpioChip, + Error::InvalidArgument(_) => CdevError::InvalidArgument, + Error::NoGpioChips() => CdevError::NoGpioChips, + Error::NonuniqueLineName(_) => CdevError::NonuniqueLineName, + Error::Os(_) => CdevError::Os, + Error::Uapi(_, _) => CdevError::Uapi, + Error::UnexpectedResponse(_) => CdevError::UnexpectedResponse, + Error::UnsupportedAbi(_, _) => CdevError::UnsupportedAbi, + Error::NoAbiSupport() => CdevError::NoAbiSupport, + } + } } diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index 23c6d4c4..00c92b4f 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -2,7 +2,7 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; use crate::button_enum; -use crate::downcast_err::{LinuxI2cError, RpiButtonError}; +use crate::downcast_err::{GpioError, LinuxI2cError}; button_enum! { /// No these are not borg, these are buttons on a string of cat5. @@ -50,14 +50,14 @@ impl Error { #[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] pub enum SetupError { BmeError(bme280::Error), - Gpio(RpiButtonError), + Gpio(GpioError), I2c(LinuxI2cError), } #[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] pub enum SensorError { BmeError(bme280::Error), - Gpio(RpiButtonError), + Gpio(GpioError), } impl SensorError { From 38e19b4d627a7ceb61a308e0d69152e3d182d64d Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 24 May 2024 23:45:46 +0200 Subject: [PATCH 089/687] vendored inspection server into homeautomation will be modified to use subscribe/update server later --- crates/server/.gitignore | 2 + crates/server/Cargo.lock | 1717 ++++++++++++++++++++++++++++++ crates/server/Cargo.toml | 16 + crates/server/src/main.rs | 122 +++ crates/server/src/tui.rs | 186 ++++ crates/server/src/tui/reading.rs | 149 +++ crates/server/src/tui/render.rs | 187 ++++ 7 files changed, 2379 insertions(+) create mode 100644 crates/server/.gitignore create mode 100644 crates/server/Cargo.lock create mode 100644 crates/server/Cargo.toml create mode 100644 crates/server/src/main.rs create mode 100644 crates/server/src/tui.rs create mode 100644 crates/server/src/tui/reading.rs create mode 100644 crates/server/src/tui/render.rs diff --git a/crates/server/.gitignore b/crates/server/.gitignore new file mode 100644 index 00000000..f3508536 --- /dev/null +++ b/crates/server/.gitignore @@ -0,0 +1,2 @@ +/target +log.txt diff --git a/crates/server/Cargo.lock b/crates/server/Cargo.lock new file mode 100644 index 00000000..32de1ed9 --- /dev/null +++ b/crates/server/Cargo.lock @@ -0,0 +1,1717 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "bitfield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "bosch-bme680" +version = "1.0.2" +dependencies = [ + "bitfield 0.14.0", + "defmt", + "embedded-hal 1.0.0", + "embedded-hal-async", + "postcard", + "serde", +] + +[[package]] +name = "bxcan" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ac3d0c0a542d0ab5521211f873f62706a7136df415676f676d347e5a41dd80" +dependencies = [ + "bitflags 1.3.2", + "embedded-hal 0.2.7", + "nb 1.1.0", + "vcell", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cassowary" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" + +[[package]] +name = "castaway" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a17ed5635fc8536268e5d4de1e22e81ac34419e5f052d4d51f4e01dcc263fcc" +dependencies = [ + "rustversion", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + +[[package]] +name = "color-eyre" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + +[[package]] +name = "compact_str" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "ryu", + "static_assertions", +] + +[[package]] +name = "const_format" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal", + "bitfield 0.13.2", + "embedded-hal 0.2.7", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2722f5b7d6ea8583cffa4d247044e280ccbb9fe501bed56552e2ba48b02d5f3d" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + +[[package]] +name = "crossterm" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" +dependencies = [ + "bitflags 2.5.0", + "crossterm_winapi", + "libc", + "mio", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + +[[package]] +name = "defmt" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3939552907426de152b3c2c6f51ed53f98f448babd26f28694c95f5906194595" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18bdc7a7b92ac413e19e95240e75d3a73a8d8e78aa24a594c22cbb4d44b4bbda" +dependencies = [ + "defmt-parser", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "defmt-parser" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" +dependencies = [ + "thiserror", +] + +[[package]] +name = "document-features" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +dependencies = [ + "litrs", +] + +[[package]] +name = "either" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" + +[[package]] +name = "embassy-embedded-hal" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca4a9380d03e61063067b8239f67d2fa9f108ede7c46b4273804f6b79e59a1d" +dependencies = [ + "embassy-futures", + "embassy-sync", + "embassy-time", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-storage", + "embedded-storage-async", + "nb 1.1.0", +] + +[[package]] +name = "embassy-futures" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f878075b9794c1e4ac788c95b728f26aa6366d32eeb10c7051389f898f7d067" + +[[package]] +name = "embassy-hal-internal" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0ec47cf8bab914018d4bd2b4f0aaeb46e4f52ab1e7985df88aeef2c6eda5aed" +dependencies = [ + "cortex-m", + "critical-section", + "num-traits", +] + +[[package]] +name = "embassy-net-driver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d" + +[[package]] +name = "embassy-stm32" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32bc0257b5ade13a1b93e8b9949268f44d57e8ce03e599ef1c5a62024a0fbff9" +dependencies = [ + "bit_field", + "bxcan", + "cfg-if", + "cortex-m", + "cortex-m-rt", + "critical-section", + "document-features", + "embassy-embedded-hal", + "embassy-futures", + "embassy-hal-internal", + "embassy-net-driver", + "embassy-sync", + "embassy-usb-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-nb", + "embedded-io", + "embedded-io-async", + "embedded-storage", + "embedded-storage-async", + "futures", + "nb 1.1.0", + "proc-macro2", + "quote", + "rand_core", + "sdio-host", + "stm32-fmc", + "stm32-metapac", + "vcell", +] + +[[package]] +name = "embassy-sync" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd938f25c0798db4280fcd8026bf4c2f48789aebf8f77b6e5cf8a7693ba114ec" +dependencies = [ + "cfg-if", + "critical-section", + "embedded-io-async", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c844070d9f80dc66ee739299183312baee2e1cdeb6e90b4ea2af44f4676da5" +dependencies = [ + "cfg-if", + "critical-section", + "document-features", + "embassy-time-driver", + "embassy-time-queue-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time-driver" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e0c214077aaa9206958b16411c157961fb7990d4ea628120a78d1a5a28aed24" +dependencies = [ + "document-features", +] + +[[package]] +name = "embassy-time-queue-driver" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1177859559ebf42cd24ae7ba8fe6ee707489b01d0bf471f8827b7b12dcb0bc0" + +[[package]] +name = "embassy-usb-driver" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fc247028eae04174b6635104a35b1ed336aabef4654f5e87a8f32327d231970" + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "defmt", + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" +dependencies = [ + "embedded-hal 1.0.0", + "nb 1.1.0", +] + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-io-async" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" +dependencies = [ + "defmt", + "embedded-io", +] + +[[package]] +name = "embedded-storage" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" + +[[package]] +name = "embedded-storage-async" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc" +dependencies = [ + "embedded-storage", +] + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-macro", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version 0.4.0", + "serde", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32 0.3.1", + "serde", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "histogram" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bd81cb9a629d0a868f2092937332fca5fd985971d2155bf6fcc225ef8a6be2c" +dependencies = [ + "thiserror", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "indoc" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "lru" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "max44009" +version = "0.2.0" +source = "git+https://github.com/dvdsk/max44009-rs#207e39cec2dcc4d254b46fada1954d6f637d4a5d" +dependencies = [ + "defmt", + "embedded-hal-async", + "postcard", + "serde", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "mhzx" +version = "0.3.0" +dependencies = [ + "defmt", + "embedded-io-async", + "heapless 0.8.0", + "postcard", + "serde", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + +[[package]] +name = "parking_lot" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.5", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "postcard" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +dependencies = [ + "cobs", + "const_format", + "heapless 0.7.17", + "postcard-derive", + "serde", +] + +[[package]] +name = "postcard-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4b01218787dd4420daf63875163a787a78294ad48a24e9f6fa8c6507759a79" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "protocol" +version = "0.1.0" +dependencies = [ + "bosch-bme680", + "defmt", + "embassy-embedded-hal", + "embassy-stm32", + "heapless 0.8.0", + "max44009", + "mhzx", + "postcard", + "serde", + "sht31", + "sps30-async", + "strum", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "ratatui" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a564a852040e82671dc50a37d88f3aa83bbc690dfc6844cfe7a2591620206a80" +dependencies = [ + "bitflags 2.5.0", + "cassowary", + "compact_str", + "crossterm", + "indoc", + "itertools", + "lru", + "paste", + "stability", + "strum", + "unicode-segmentation", + "unicode-width", +] + +[[package]] +name = "redox_syscall" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags 2.5.0", +] + +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.3", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.22", +] + +[[package]] +name = "rustversion" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sdio-host" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93c025f9cfe4c388c328ece47d11a54a823da3b5ad0370b22d95ad47137f85a" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.200" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.200" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "server" +version = "0.1.0" +dependencies = [ + "color-eyre", + "crossterm", + "histogram", + "protocol", + "ratatui", + "tracing", + "tracing-error", + "tracing-subscriber", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "sht31" +version = "0.3.1" +source = "git+https://github.com/dvdsk/SHT31-rs#a7b6bd94fb137e16bf326eff5fb591624369a2cf" +dependencies = [ + "crc", + "defmt", + "embedded-hal-async", + "postcard", + "serde", +] + +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "sps30-async" +version = "0.2.0" +dependencies = [ + "defmt", + "embedded-hal-async", + "embedded-io-async", + "heapless 0.8.0", + "postcard", + "serde", +] + +[[package]] +name = "stability" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ff9eaf853dec4c8802325d8b6d3dffa86cc707fd7a1a4cdbf416e13b061787a" +dependencies = [ + "quote", + "syn 2.0.60", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "stm32-fmc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830ed60f33e6194ecb377f5d6ab765dc0e37e7b65e765f1fa87df13336658d63" +dependencies = [ + "embedded-hal 0.2.7", +] + +[[package]] +name = "stm32-metapac" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deabea56a8821dcea05d0109f3ab3135f31eb572444e5da203d06149c594c8c6" +dependencies = [ + "cortex-m", + "cortex-m-rt", +] + +[[package]] +name = "strum" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.60", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "unicode-width" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] diff --git a/crates/server/Cargo.toml b/crates/server/Cargo.toml new file mode 100644 index 00000000..25ada7e2 --- /dev/null +++ b/crates/server/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "server" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +color-eyre = "0.6.3" +crossterm = "0.27.0" +histogram = "0.10.1" +protocol = { path = "/home/david/Documents/HomeAutomation/crates/protocol" } +ratatui = "0.26.2" +tracing = "0.1.40" +tracing-error = "0.2.0" +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } diff --git a/crates/server/src/main.rs b/crates/server/src/main.rs new file mode 100644 index 00000000..771f436f --- /dev/null +++ b/crates/server/src/main.rs @@ -0,0 +1,122 @@ +use std::io::prelude::*; +use std::io::BufReader; +use std::net::{TcpListener, TcpStream}; +use std::sync::mpsc; +use std::sync::mpsc::Sender; +use std::thread; + +use color_eyre::Result; + +use protocol::SensorMessage; + +mod tui; + +fn handle_client(stream: TcpStream, tx: Sender) { + let mut reader = BufReader::new(stream); + let mut buf = Vec::new(); + loop { + let n_read = match reader.read_until(0, &mut buf) { + Err(e) => { + tx.send(Update::ConnFailed).unwrap(); + return; + } + Ok(bytes) => bytes, + }; + let msg = &mut buf[0..n_read]; + let msg = match SensorMessage::<6>::decode(msg) { + Ok(msg) => msg, + Err(e) => { + tx.send(Update::DecodeFailed(e)).unwrap(); + continue; + } + }; + let values = msg.values; + for value in values.into_iter() { + tx.send(Update::Data(value)).unwrap(); + } + + buf.clear(); + } +} + +enum Update { + Data(protocol::Sensor), + ConnFailed, + NewConn(std::net::SocketAddr), + DecodeFailed(protocol::DecodeError), +} + +fn main() -> Result<()> { + setup_tracing().unwrap(); + let (tx, rx) = mpsc::channel(); + + thread::spawn(|| tui::run(rx)); + + let listener = TcpListener::bind("0.0.0.0:1234")?; + + // accept connections and process them serially + for stream in listener.incoming() { + let stream = match stream { + Ok(stream) => stream, + Err(e) => { + println!("new connection failed: {e}"); + continue; + } + }; + + tx.send(Update::NewConn(stream.peer_addr().unwrap())) + .unwrap(); + { + let tx = tx.clone(); + std::thread::spawn(move || handle_client(stream, tx)); + } + } + Ok(()) +} + +fn setup_tracing() -> Result<()> { + use tracing_error::ErrorLayer; + use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt, Layer}; + + color_eyre::install().unwrap(); + + let log_file = std::fs::File::create("log.txt")?; + let file_subscriber = tracing_subscriber::fmt::layer() + .with_file(true) + .with_line_number(true) + .with_writer(log_file) + .with_target(false) + .with_ansi(false) + .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()); + tracing_subscriber::registry() + .with(file_subscriber) + .with(ErrorLayer::default()) + .init(); + Ok(()) +} + +/// Similar to the `std::dbg!` macro, but generates `tracing` events rather +/// than printing to stdout. +/// +/// By default, the verbosity level for the generated events is `DEBUG`, but +/// this can be customized. +#[macro_export] +macro_rules! trace_dbg { + (target: $target:expr, level: $level:expr, $ex:expr) => {{ + match $ex { + value => { + tracing::event!(target: $target, $level, ?value, stringify!($ex)); + value + } + } + }}; + (level: $level:expr, $ex:expr) => { + trace_dbg!(target: module_path!(), level: $level, $ex) + }; + (target: $target:expr, $ex:expr) => { + trace_dbg!(target: $target, level: tracing::Level::DEBUG, $ex) + }; + ($ex:expr) => { + trace_dbg!(level: tracing::Level::DEBUG, $ex) + }; +} diff --git a/crates/server/src/tui.rs b/crates/server/src/tui.rs new file mode 100644 index 00000000..a181a6f9 --- /dev/null +++ b/crates/server/src/tui.rs @@ -0,0 +1,186 @@ +use crossterm::{ + event::{self, KeyCode, KeyEventKind, KeyModifiers}, + terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, + ExecutableCommand, +}; +use ratatui::{ + prelude::{CrosstermBackend, Terminal}, + style::{Color, Style}, + widgets::ListState, +}; +use std::{ + io::stdout, + sync::mpsc, + time::{Duration, Instant}, +}; + +mod reading; +use reading::Readings; +mod render; +use crate::Update; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum ActiveList { + Readings, + Actuators, +} + +impl ActiveList { + fn style(&self, list: Self) -> Style { + if *self == list { + Style::default().fg(Color::Black) + } else { + Style::default().fg(Color::Indexed(242)) + } + } + + fn swap(self) -> Self { + match self { + Self::Readings => Self::Actuators, + Self::Actuators => Self::Readings, + } + } +} + +struct ConnInfo { + last_msg: Instant, + addr: std::net::SocketAddr, +} + +impl ConnInfo { + fn conn_status(&self) -> String { + let Self { last_msg, addr } = self; + let elapsed = last_msg.elapsed().as_secs(); + if elapsed < 2 { + format!("client: {addr}\nlast message less then 2 seconds ago") + } else { + format!("client: {addr}\nlast message {elapsed}s ago") + } + } + fn got_msg(&mut self) { + self.last_msg = Instant::now(); + } +} + +pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { + let mut readings = Readings { map: Vec::new() }; + let mut conn_info = None; + + stdout().execute(EnterAlternateScreen)?; + enable_raw_mode()?; + let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; + terminal.clear()?; + + let mut active_list = ActiveList::Readings; + let mut reading_list_state = ListState::default(); + let mut actuator_list_state = ListState::default(); + let actuators = vec![ + "placeholder 1".to_owned(), + "placeholder 2".to_owned(), + "placeholder 3".to_owned(), + ]; + let mut plot_buf = Vec::new(); + let mut selected = None; + + loop { + let conn_status = conn_info + .as_ref() + .map(ConnInfo::conn_status) + .unwrap_or_else(|| format!("no connected client")); + + let chart = if let Some(key) = selected { + readings.chart(key, &mut plot_buf) + } else { + None + }; + + let histogram = if let Some(key) = selected { + readings.histogram(key) + } else { + readings.histogram_all() + }; + + terminal.draw(|frame| { + render::all( + frame, + readings.list(), + &mut reading_list_state, + actuators.clone(), + &mut actuator_list_state, + active_list, + &histogram, + chart, + &conn_status, + ); + })?; + + if event::poll(Duration::from_millis(16))? { + if let event::Event::Key(key) = event::read()? { + if key.kind == KeyEventKind::Press { + if key.code == KeyCode::Char('q') { + break; + } + if key.code == KeyCode::Char('c') + && key.modifiers.contains(KeyModifiers::CONTROL) + { + break; + } + if key.code == KeyCode::Left { + active_list = active_list.swap(); + } + if key.code == KeyCode::Right { + active_list = active_list.swap(); + } + if key.code == KeyCode::Down { + reading_list_state.select(Some( + reading_list_state + .selected() + .map(|i| { + if i + 1 >= readings.list().len() { + 0 + } else { + i + 1 + } + }) + .unwrap_or(0), + )); + } + if key.code == KeyCode::Up { + reading_list_state.select( + reading_list_state + .selected() + .map(|i| if i == 0 { None } else { Some(i - 1) }) + .unwrap_or_else(|| Some(readings.list().len() - 1)), + ); + } + } + } + } + + selected = reading_list_state.selected().map(|i| readings.map[i].0); + + match rx.try_recv() { + Ok(Update::Data(data)) => { + conn_info.as_mut().unwrap().got_msg(); + readings.add(data); + } + Ok(Update::NewConn(source)) => { + conn_info = Some(ConnInfo { + last_msg: Instant::now(), + addr: source, + }); + } + Ok(Update::DecodeFailed(_)) => { + conn_info.as_mut().unwrap().got_msg(); + } + Ok(Update::ConnFailed) => { + conn_info = None; + } + _ => (), + } + } + + stdout().execute(LeaveAlternateScreen)?; + disable_raw_mode()?; + Ok(()) +} diff --git a/crates/server/src/tui/reading.rs b/crates/server/src/tui/reading.rs new file mode 100644 index 00000000..d0e59cff --- /dev/null +++ b/crates/server/src/tui/reading.rs @@ -0,0 +1,149 @@ +use histogram::Histogram; +use protocol::{ + large_bedroom::{Error, LargeBedroomDiscriminants}, + Sensor, +}; +use ratatui::{text::Line, widgets::Bar}; +use std::{collections::VecDeque, time::Instant}; + +pub struct SensorInfo { + timing: Histogram, + history: VecDeque<(Instant, f32)>, + condition: Result<(), Error>, +} + +impl SensorInfo { + fn last(&self) -> Result { + self.condition.clone()?; + + let last = self + .history + .front() + .expect("Items are put in the map when they arrive with a value"); + Ok(last.1) + } + + fn last_at(&self) -> Result { + self.condition.clone()?; + + let last = self + .history + .front() + .expect("Items are put in the map when they arrive with a value"); + Ok(last.0) + } +} + +pub struct Readings { + pub map: Vec<(LargeBedroomDiscriminants, SensorInfo)>, +} + +impl Readings { + pub fn add(&mut self, data: Sensor) { + match data { + Sensor::LargeBedroom(data) => { + let key = LargeBedroomDiscriminants::from(data); + if let Some((_, info)) = self.map.iter_mut().find(|p| p.0 == key) { + if let Ok(last_reading) = info.last_at() { + info.timing + .increment(last_reading.elapsed().as_millis() as u64) + .unwrap(); + } + info.history.push_front((Instant::now(), data.into())); + info.condition = Ok(()); + } else { + let mut history = VecDeque::new(); + history.push_front((Instant::now(), data.into())); + self.map.push(( + key, + SensorInfo { + timing: Histogram::new(4, 24).unwrap(), + history, + condition: Ok(()), + }, + )); + } + } + Sensor::LargeBedroomError(err) => { + for key in err.broken_readings() { + if let Some((_, info)) = self.map.iter_mut().find(|p| p.0 == *key) { + info.condition = Err(err.clone()); + } else { + self.map.push(( + *key, + SensorInfo { + timing: Histogram::new(4, 24).unwrap(), + history: VecDeque::new(), + condition: Err(err.clone()), + }, + )) + } + } + } + _ => todo!(), + } + } + + pub fn list(&self) -> Vec { + self.map + .iter() + .map(|(key, val)| { + let val = val.last(); + format!("{key:?}: {val:?}\n") + }) + .collect() + } + + pub fn histogram_all(&self) -> Vec { + let mut all = Histogram::new(4, 24).unwrap(); + for (_, val) in self.map.iter() { + all = all.checked_add(&val.timing).unwrap(); + } + histogram_bars(&all) + } + + pub fn histogram(&self, key: LargeBedroomDiscriminants) -> Vec { + let hist = &self.map.iter().find(|p| p.0 == key).unwrap().1.timing; + histogram_bars(hist) + } + + pub fn chart<'a>( + &mut self, + key: LargeBedroomDiscriminants, + plot_buf: &'a mut Vec<(f64, f64)>, + ) -> Option> { + let data = &self.map.iter_mut().find(|p| p.0 == key).unwrap().1; + + plot_buf.clear(); + for xy in data + .history + .iter() + .map(|(x, y)| (x.elapsed().as_secs_f64(), *y as f64)) + { + plot_buf.push(xy); + } + + Some(ChartParts { + name: format!("{key:?}"), + data: plot_buf, + }) + } +} + +pub struct ChartParts<'a> { + pub name: String, + pub data: &'a [(f64, f64)], +} + +fn histogram_bars(hist: &Histogram) -> Vec> { + let percentiles = hist.percentiles(&[25.0, 50.0, 75.0, 90.0, 95.0, 100.0]).unwrap(); + percentiles + .into_iter() + .map(|(p, bucket)| { + Bar::default() + .value(bucket.count()) + .text_value(format!("p{p}: {}", bucket.count())) + .label(Line::from(format!("{}..{}", bucket.start(), bucket.end()))) + }) + .collect() +} diff --git a/crates/server/src/tui/render.rs b/crates/server/src/tui/render.rs new file mode 100644 index 00000000..cf956d51 --- /dev/null +++ b/crates/server/src/tui/render.rs @@ -0,0 +1,187 @@ +use ratatui::{ + self, + layout::{Constraint, Layout, Rect}, + style::{Color, Modifier, Style, Stylize}, + symbols, + widgets::{ + Axis, Bar, BarChart, BarGroup, Block, Borders, Chart, Dataset, GraphType, List, ListState, + Paragraph, + }, + Frame, +}; + +use super::{reading::ChartParts, ActiveList}; + +pub(crate) fn all( + frame: &mut Frame, + readings: Vec, + reading_list_state: &mut ListState, + actuators: Vec, + actuator_list_state: &mut ListState, + active_list: ActiveList, + histogram: &[Bar], + chart: Option, + conn_status: &str, +) { + let area = frame.size(); + let [top, bottom] = Layout::vertical([Constraint::Min(10), Constraint::Min(10)]) + .flex(ratatui::layout::Flex::Legacy) + .areas(area); + + render_top( + frame, + top, + readings, + reading_list_state, + actuators, + actuator_list_state, + active_list, + conn_status, + ); + render_lower(frame, bottom, histogram, chart); +} + +fn render_lower(frame: &mut Frame, layout: Rect, histogram: &[Bar], chart: Option) { + match chart { + Some(chart) => detail_view(frame, layout, chart, histogram), + None => global_view(frame, layout, histogram), + } +} + +fn detail_view(frame: &mut Frame, layout: Rect, chart: ChartParts, histogram: &[Bar]) { + let [top, lower] = Layout::vertical([Constraint::Percentage(65), Constraint::Percentage(35)]) + .flex(ratatui::layout::Flex::Legacy) + .areas(layout); + + let dataset = Dataset::default() + .name(chart.name) + .marker(symbols::Marker::Dot) + .graph_type(GraphType::Line) + .style(Style::default()) + .data(chart.data); + + let x_bounds = [ + 0f64, + chart.data.last().map(|(x, _)| x).copied().unwrap_or(0f64), + ]; + + let y_bounds = chart + .data + .iter() + .map(|(_, y)| y) + .fold([f64::MAX, f64::MIN], |[start, end], y| { + [start.min(*y), end.max(*y)] + }); + let y_range = y_bounds[1] - y_bounds[0]; + let y_margin = f64::max(y_range * 0.5, 0.001 * y_bounds[0].abs()); + let y_bounds = [y_bounds[0] - y_margin, y_bounds[1] + y_margin]; + + let x_labels = vec!["0".into(), format_time(x_bounds[1]).into()]; + let y_labels = vec![ + format!("{:.3}", y_bounds[0]).into(), + format!("{:.3}", y_bounds[1]).into(), + ]; + + let x_axis = Axis::default() + .title("Time") + .style(Style::default()) + .bounds(x_bounds) + .labels(x_labels); + let y_axis = Axis::default() + .title("Value") + .style(Style::default()) + .bounds(y_bounds) + .labels(y_labels); + let linechart = Chart::new(vec![dataset]) + .block(Block::bordered().title("History")) + .x_axis(x_axis) + .y_axis(y_axis); + frame.render_widget(linechart, top); + + let barchart = BarChart::default() + .block(Block::bordered().title("Histogram")) + .data(BarGroup::default().bars(histogram)) + .bar_width(12) + .bar_style(Style::default()) + .value_style(Style::default()); + frame.render_widget(barchart, lower) +} + +fn global_view(frame: &mut Frame, layout: Rect, histogram: &[Bar]) { + let barchart = BarChart::default() + .block(Block::bordered().title("Histogram")) + .data(BarGroup::default().bars(histogram)) + .bar_width(12) + .bar_style(Style::default()) + .value_style(Style::default()); + frame.render_widget(barchart, layout) +} + +pub(crate) fn render_top( + frame: &mut Frame, + layout: Rect, + readings: Vec, + reading_list_state: &mut ListState, + actuators: Vec, + actuator_list_state: &mut ListState, + active_list: ActiveList, + conn_status: &str, +) { + let vertical: [_; 2] = Layout::vertical([Constraint::Max(2), Constraint::Min(5)]) + .flex(ratatui::layout::Flex::Legacy) + .areas(layout); + + frame.render_widget(Paragraph::new(conn_status), vertical[0]); + + let horizontal: [_; 2] = + Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]) + .flex(ratatui::layout::Flex::Legacy) + .areas(vertical[1]); + + frame.render_stateful_widget( + List::new(readings) + .block( + Block::default() + .title("Sensor readings") + .borders(Borders::ALL) + .border_style(active_list.style(ActiveList::Readings)), + ) + .style(active_list.style(ActiveList::Readings)) + .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) + .highlight_symbol(">>") + .repeat_highlight_symbol(false) + .direction(ratatui::widgets::ListDirection::TopToBottom), + horizontal[0], + reading_list_state, + ); + + frame.render_stateful_widget( + List::new(actuators) + .block( + Block::default() + .title("Actuators") + .borders(Borders::ALL) + .border_style(active_list.style(ActiveList::Actuators)), + ) + .style(active_list.style(ActiveList::Actuators)) + .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) + .highlight_symbol(">>") + .repeat_highlight_symbol(false) + .direction(ratatui::widgets::ListDirection::TopToBottom), + horizontal[1], + actuator_list_state, + ); +} + +fn format_time(seconds: f64) -> String { + let seconds = seconds as u32; + if seconds < 60 { + format!("{}s ago", seconds) + } else if seconds < 600 { + let m = seconds / 60; + let s = seconds % 60; + format!("{m}:{s:0>1} ago") + } else { + format!("{}m ago", seconds / 60) + } +} From 0549ffda5070714ec58a970cbf719aac8c7fe579 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 24 May 2024 23:48:29 +0200 Subject: [PATCH 090/687] rename sensor server to sensor_tui --- crates/{server => sensor_tui}/.gitignore | 0 crates/{server => sensor_tui}/Cargo.lock | 0 crates/{server => sensor_tui}/Cargo.toml | 7 ++++--- crates/{server => sensor_tui}/src/main.rs | 0 crates/{server => sensor_tui}/src/tui.rs | 0 crates/{server => sensor_tui}/src/tui/reading.rs | 0 crates/{server => sensor_tui}/src/tui/render.rs | 0 7 files changed, 4 insertions(+), 3 deletions(-) rename crates/{server => sensor_tui}/.gitignore (100%) rename crates/{server => sensor_tui}/Cargo.lock (100%) rename crates/{server => sensor_tui}/Cargo.toml (80%) rename crates/{server => sensor_tui}/src/main.rs (100%) rename crates/{server => sensor_tui}/src/tui.rs (100%) rename crates/{server => sensor_tui}/src/tui/reading.rs (100%) rename crates/{server => sensor_tui}/src/tui/render.rs (100%) diff --git a/crates/server/.gitignore b/crates/sensor_tui/.gitignore similarity index 100% rename from crates/server/.gitignore rename to crates/sensor_tui/.gitignore diff --git a/crates/server/Cargo.lock b/crates/sensor_tui/Cargo.lock similarity index 100% rename from crates/server/Cargo.lock rename to crates/sensor_tui/Cargo.lock diff --git a/crates/server/Cargo.toml b/crates/sensor_tui/Cargo.toml similarity index 80% rename from crates/server/Cargo.toml rename to crates/sensor_tui/Cargo.toml index 25ada7e2..7a2e6950 100644 --- a/crates/server/Cargo.toml +++ b/crates/sensor_tui/Cargo.toml @@ -1,7 +1,8 @@ [package] -name = "server" -version = "0.1.0" -edition = "2021" +name = "sensor_tui" +edition.workspace = true +license.workspace = true +authors.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/crates/server/src/main.rs b/crates/sensor_tui/src/main.rs similarity index 100% rename from crates/server/src/main.rs rename to crates/sensor_tui/src/main.rs diff --git a/crates/server/src/tui.rs b/crates/sensor_tui/src/tui.rs similarity index 100% rename from crates/server/src/tui.rs rename to crates/sensor_tui/src/tui.rs diff --git a/crates/server/src/tui/reading.rs b/crates/sensor_tui/src/tui/reading.rs similarity index 100% rename from crates/server/src/tui/reading.rs rename to crates/sensor_tui/src/tui/reading.rs diff --git a/crates/server/src/tui/render.rs b/crates/sensor_tui/src/tui/render.rs similarity index 100% rename from crates/server/src/tui/render.rs rename to crates/sensor_tui/src/tui/render.rs From de796d8d00d7ed6e33269874bc300a4cbecc0656 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 24 May 2024 23:59:42 +0200 Subject: [PATCH 091/687] venored data server into ha --- crates/data_server/.gitignore | 2 + crates/data_server/Cargo.lock | 1639 ++++++++++++++++++++++++++++++++ crates/data_server/Cargo.toml | 16 + crates/data_server/deploy.sh | 24 + crates/data_server/src/main.rs | 191 ++++ 5 files changed, 1872 insertions(+) create mode 100644 crates/data_server/.gitignore create mode 100644 crates/data_server/Cargo.lock create mode 100644 crates/data_server/Cargo.toml create mode 100755 crates/data_server/deploy.sh create mode 100644 crates/data_server/src/main.rs diff --git a/crates/data_server/.gitignore b/crates/data_server/.gitignore new file mode 100644 index 00000000..53eaa219 --- /dev/null +++ b/crates/data_server/.gitignore @@ -0,0 +1,2 @@ +/target +**/*.rs.bk diff --git a/crates/data_server/Cargo.lock b/crates/data_server/Cargo.lock new file mode 100644 index 00000000..2ecccfc7 --- /dev/null +++ b/crates/data_server/Cargo.lock @@ -0,0 +1,1639 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "bitfield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bosch-bme680" +version = "1.0.2" +source = "git+https://github.com/dvdsk/async-bosch-bme680#455d5d3194f137d9e0403779badc645e1bad7a05" +dependencies = [ + "bitfield 0.14.0", + "defmt", + "embedded-hal 1.0.0", + "embedded-hal-async", + "postcard", + "serde", + "thiserror", +] + +[[package]] +name = "bxcan" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ac3d0c0a542d0ab5521211f873f62706a7136df415676f676d347e5a41dd80" +dependencies = [ + "bitflags", + "embedded-hal 0.2.7", + "nb 1.1.0", + "vcell", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cc" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + +[[package]] +name = "color-eyre" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "const_format" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal", + "bitfield 0.13.2", + "embedded-hal 0.2.7", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2722f5b7d6ea8583cffa4d247044e280ccbb9fe501bed56552e2ba48b02d5f3d" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + +[[package]] +name = "data-server" +version = "0.2.0" +dependencies = [ + "clap", + "color-eyre", + "protocol", + "tokio", + "tokio-stream", + "tracing", + "tracing-error", + "tracing-subscriber", +] + +[[package]] +name = "defmt" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0" +dependencies = [ + "bitflags", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb" +dependencies = [ + "defmt-parser", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "defmt-parser" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" +dependencies = [ + "thiserror", +] + +[[package]] +name = "document-features" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +dependencies = [ + "litrs", +] + +[[package]] +name = "embassy-embedded-hal" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca4a9380d03e61063067b8239f67d2fa9f108ede7c46b4273804f6b79e59a1d" +dependencies = [ + "embassy-futures", + "embassy-sync", + "embassy-time", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-storage", + "embedded-storage-async", + "nb 1.1.0", +] + +[[package]] +name = "embassy-futures" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f878075b9794c1e4ac788c95b728f26aa6366d32eeb10c7051389f898f7d067" + +[[package]] +name = "embassy-hal-internal" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0ec47cf8bab914018d4bd2b4f0aaeb46e4f52ab1e7985df88aeef2c6eda5aed" +dependencies = [ + "cortex-m", + "critical-section", + "num-traits", +] + +[[package]] +name = "embassy-net-driver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d" + +[[package]] +name = "embassy-stm32" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32bc0257b5ade13a1b93e8b9949268f44d57e8ce03e599ef1c5a62024a0fbff9" +dependencies = [ + "bit_field", + "bxcan", + "cfg-if", + "cortex-m", + "cortex-m-rt", + "critical-section", + "document-features", + "embassy-embedded-hal", + "embassy-futures", + "embassy-hal-internal", + "embassy-net-driver", + "embassy-sync", + "embassy-usb-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-nb", + "embedded-io 0.6.1", + "embedded-io-async", + "embedded-storage", + "embedded-storage-async", + "futures", + "nb 1.1.0", + "proc-macro2", + "quote", + "rand_core", + "sdio-host", + "stm32-fmc", + "stm32-metapac", + "vcell", +] + +[[package]] +name = "embassy-sync" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd938f25c0798db4280fcd8026bf4c2f48789aebf8f77b6e5cf8a7693ba114ec" +dependencies = [ + "cfg-if", + "critical-section", + "embedded-io-async", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c844070d9f80dc66ee739299183312baee2e1cdeb6e90b4ea2af44f4676da5" +dependencies = [ + "cfg-if", + "critical-section", + "document-features", + "embassy-time-driver", + "embassy-time-queue-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time-driver" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e0c214077aaa9206958b16411c157961fb7990d4ea628120a78d1a5a28aed24" +dependencies = [ + "document-features", +] + +[[package]] +name = "embassy-time-queue-driver" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1177859559ebf42cd24ae7ba8fe6ee707489b01d0bf471f8827b7b12dcb0bc0" + +[[package]] +name = "embassy-usb-driver" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fc247028eae04174b6635104a35b1ed336aabef4654f5e87a8f32327d231970" + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "defmt", + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" +dependencies = [ + "embedded-hal 1.0.0", + "nb 1.1.0", +] + +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-io-async" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" +dependencies = [ + "defmt", + "embedded-io 0.6.1", +] + +[[package]] +name = "embedded-storage" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" + +[[package]] +name = "embedded-storage-async" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc" +dependencies = [ + "embedded-storage", +] + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-macro", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version 0.4.0", + "serde", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32 0.3.1", + "serde", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "max44009" +version = "0.2.0" +source = "git+https://github.com/dvdsk/max44009-rs#7b7df2e3173476c250fca3eb242f0dd366857599" +dependencies = [ + "defmt", + "embedded-hal-async", + "postcard", + "serde", + "thiserror", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "mhzx" +version = "0.3.0" +source = "git+https://github.com/dvdsk/mhzx#08f6e7adb4ec98749fa84f24f8ff9e0e3c83d164" +dependencies = [ + "defmt", + "embedded-io-async", + "heapless 0.8.0", + "postcard", + "serde", + "thiserror", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "postcard" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +dependencies = [ + "cobs", + "const_format", + "embedded-io 0.4.0", + "heapless 0.7.17", + "postcard-derive", + "serde", +] + +[[package]] +name = "postcard-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4b01218787dd4420daf63875163a787a78294ad48a24e9f6fa8c6507759a79" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "protocol" +version = "0.1.0" +dependencies = [ + "bosch-bme680", + "defmt", + "embassy-embedded-hal", + "embassy-stm32", + "heapless 0.8.0", + "max44009", + "mhzx", + "postcard", + "serde", + "sht31", + "sps30-async", + "strum", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.3", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.23", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sdio-host" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93c025f9cfe4c388c328ece47d11a54a823da3b5ad0370b22d95ad47137f85a" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.202" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.202" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "sht31" +version = "0.3.1" +source = "git+https://github.com/dvdsk/SHT31-rs#a7b6bd94fb137e16bf326eff5fb591624369a2cf" +dependencies = [ + "crc", + "defmt", + "embedded-hal-async", + "postcard", + "serde", + "thiserror", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "sps30-async" +version = "0.2.0" +source = "git+https://github.com/dvdsk/sps30-async#a5e81ec034727442c048acea2e8eb07fe4be78e4" +dependencies = [ + "defmt", + "embedded-hal-async", + "embedded-io-async", + "heapless 0.8.0", + "postcard", + "serde", + "thiserror", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stm32-fmc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830ed60f33e6194ecb377f5d6ab765dc0e37e7b65e765f1fa87df13336658d63" +dependencies = [ + "embedded-hal 0.2.7", +] + +[[package]] +name = "stm32-metapac" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deabea56a8821dcea05d0109f3ab3135f31eb572444e5da203d06149c594c8c6" +dependencies = [ + "cortex-m", + "cortex-m-rt", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.65", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/crates/data_server/Cargo.toml b/crates/data_server/Cargo.toml new file mode 100644 index 00000000..f3058b8c --- /dev/null +++ b/crates/data_server/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "data-server" +edition.workspace = true +license.workspace = true +authors.workspace = true + +[dependencies] +clap = { version = "4", features = ["derive"] } +color-eyre = "0.6.3" +tracing = "0.1.40" +tracing-error = "0.2.0" +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } + +protocol = { path = "/home/david/Documents/HomeAutomation/crates/protocol", features = ["alloc"] } +tokio = { version = "1.37.0", features = ["rt", "macros", "net", "sync", "io-util"] } +tokio-stream = { version = "0.1.15", features = ["net"] } diff --git a/crates/data_server/deploy.sh b/crates/data_server/deploy.sh new file mode 100755 index 00000000..65d3e593 --- /dev/null +++ b/crates/data_server/deploy.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -e + +BUILD_ARG=$1 +SERVER="sgc" # ssh config name or full adress +RELEASE=debug +NAME=datasplitter + +if [[ BUILD_ARG == "--release" ]]; then + RELEASE=release +fi + +cross build --target=aarch64-unknown-linux-gnu $BUILD_ARG +rsync -vh --progress \ + target/aarch64-unknown-linux-gnu/$RELEASE/$NAME \ + $SERVER:/tmp/ + +cmds=" +sudo mv /tmp/$NAME /home/data/$NAME +sudo chown data:data /home/data/$NAME +sudo systemctl restart datasplitter.service +" + +ssh -t sgc "$cmds" diff --git a/crates/data_server/src/main.rs b/crates/data_server/src/main.rs new file mode 100644 index 00000000..55413298 --- /dev/null +++ b/crates/data_server/src/main.rs @@ -0,0 +1,191 @@ +use color_eyre::eyre::Context; +use std::mem; +use std::net::SocketAddr; +use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufStream}; +use tokio::net::{TcpListener, TcpStream}; +use tokio::sync::mpsc::{self, Sender}; +use tokio_stream::wrappers::TcpListenerStream; +use tokio_stream::StreamExt; + +use color_eyre::{Result, Section}; +use protocol::{Sensor, SensorMessage}; + +use clap::Parser; +use tokio::select; +use tracing::warn; + +#[derive(Parser)] +#[command(name = "data server")] +#[command(version = "1.0")] +#[command(about = "Receives sensor events and spreads those to subscribed services")] +struct Cli { + /// Optional name to operate on + #[arg(short, long)] + subscribe_port: u16, + + /// Sets a custom config file + #[arg(short, long)] + update_port: u16, +} + +async fn handle_client(stream: TcpStream, tx: Sender) { + let mut reader = BufStream::new(stream); + let mut buf = Vec::new(); + loop { + let n_read = match reader.read_until(0, &mut buf).await { + Err(e) => { + warn!("Connection failed/closed: {e}"); + return; + } + Ok(bytes) => bytes, + }; + let msg = &mut buf[0..n_read]; + let msg = match SensorMessage::<6>::decode(msg) { + Ok(msg) => msg, + Err(e) => { + warn!("decode failed: {e:?}"); + return; + } + }; + let values = msg.values; + for value in values.into_iter() { + tx.send(Event::NewReading(value)).await.unwrap(); + } + + buf.clear(); + } +} + +enum Event { + NewSub(TcpStream), + NewReading(Sensor), +} + +async fn spread_updates( + mut events: mpsc::Receiver, + events_tx: &mpsc::Sender, +) -> Result<()> { + let mut subscribers = Vec::new(); + + while let Some(event) = events.recv().await { + let reading = match event { + Event::NewSub(sub) => { + subscribers.push(sub); + continue; + } + Event::NewReading(reading) => reading, + }; + + let mut msg: SensorMessage<40> = SensorMessage::new(); + msg.values.push(reading).expect("capacity should be > 0"); + + while let Ok(event) = events.try_recv() { + match event { + Event::NewSub(sub) => { + subscribers.push(sub); + continue; + } + Event::NewReading(reading) => { + if let Err(failed_to_push) = msg.values.push(reading) { + // re queue + events_tx + .send(Event::NewReading(failed_to_push)) + .await + .unwrap(); + break; + } + } + } + } + + let bytes = msg.encode(); + let subs = mem::take(&mut subscribers); + for mut sub in subs.into_iter() { + if let Err(e) = sub.write_all(&bytes).await { + warn!("Error writing to subscriber: {e}"); + } else { + subscribers.push(sub); + } + } + } + + Ok(()) +} + +async fn register_subs(port: u16, share: &mpsc::Sender) -> Result<()> { + let addr = SocketAddr::from(([127, 0, 0, 1], port)); + let listener = TcpListener::bind(addr) + .await + .wrap_err("Could not start listening for new subscribers") + .with_note(|| format!("trying to listen on port: {port}"))?; + let mut listener = TcpListenerStream::new(listener); + + // accept connections and process them serially + while let Some(stream) = listener.next().await { + match stream { + Ok(stream) => tokio::spawn(handle_client(stream, share.clone())), + Err(e) => { + println!("new connection failed: {e}"); + continue; + } + }; + } + Ok(()) +} + +async fn receive_updates(port: u16, tx: &mpsc::Sender) -> Result<()> { + let addr = SocketAddr::from(([127, 0, 0, 1], port)); + let listener = TcpListener::bind(addr).await + .wrap_err("Could not start receiving updates") + .with_note(|| format!("trying to listen on port: {port}"))?; + let mut listener = TcpListenerStream::new(listener); + + // accept connections and process them serially + while let Some(res) = listener.next().await { + match res { + Ok(stream) => tx.send(Event::NewSub(stream)).await.unwrap(), + Err(e) => { + println!("new connection failed: {e}"); + continue; + } + }; + } + Ok(()) +} + +#[tokio::main(flavor = "current_thread")] +async fn main() -> Result<()> { + setup_tracing().unwrap(); + + let Cli { + subscribe_port, + update_port, + } = Cli::parse(); + assert_ne!(subscribe_port, update_port); + + let (tx, rx) = mpsc::channel(2000); + select! { + e = receive_updates(update_port, &tx) => e, + e = register_subs(subscribe_port, &tx) => e, + e = spread_updates(rx, &tx) => e, + } +} + +fn setup_tracing() -> Result<()> { + use tracing_error::ErrorLayer; + use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt, Layer}; + + color_eyre::install().unwrap(); + + let file_subscriber = tracing_subscriber::fmt::layer() + .with_file(true) + .with_line_number(true) + .with_target(false) + .with_ansi(false) + .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()); + tracing_subscriber::registry() + .with(file_subscriber) + .with(ErrorLayer::default()) + .init(); + Ok(()) +} From 7088ab1ba92d3da8eb71c3cd033ce1a91f26729b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 25 May 2024 15:48:17 +0200 Subject: [PATCH 092/687] add new trait (temp name Tomato) to walkt through reading --- crates/protocol/src/large_bedroom.rs | 10 ++++- crates/protocol/src/large_bedroom/bed.rs | 53 +++++++++++++---------- crates/protocol/src/large_bedroom/desk.rs | 18 +++++++- crates/protocol/src/lib.rs | 50 ++++++++++++++++++++- 4 files changed, 102 insertions(+), 29 deletions(-) diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index b6dbcc3d..c1cf16f0 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -1,15 +1,22 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; +use crate::{all_nodes, Tomato}; + pub mod bed; pub mod desk; -#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] +#[derive( + strum::EnumDiscriminants, Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, +)] +#[strum_discriminants(derive(Hash))] pub enum Reading { Bed(bed::Reading), Desk(desk::Reading), } +all_nodes! {Reading; ReadingDiscriminants; Bed, Desk} + #[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] pub enum Error { Bed(bed::Error), @@ -22,7 +29,6 @@ pub enum Device { Desk(desk::Device), } - #[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] pub enum Actuator { CleanSensor, diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 509792ee..6b38b9f3 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -1,5 +1,5 @@ -use crate::button_enum; use crate::downcast_err::{I2cError, UartError}; +use crate::{button_enum, Tomato, TomatoItem}; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -68,29 +68,34 @@ pub enum Reading { TypicalParticleSize(f32), } -impl Into for Reading { - fn into(self) -> f32 { - match self { - Reading::Brightness(val) => val, - Reading::Temperature(val) => val, - Reading::Humidity(val) => val, - Reading::GassResistance(val) => val, - Reading::Pressure(val) => val, - Reading::Co2(val) => val as f32, - Reading::WeightLeft(val) => val as f32, - Reading::WeightRight(val) => val as f32, - Reading::Button(val) => val.into(), - Reading::MassPm1_0(val) => val, - Reading::MassPm2_5(val) => val, - Reading::MassPm4_0(val) => val, - Reading::MassPm10(val) => val, - Reading::MassPm0_5(val) => val, - Reading::NumberPm1_0(val) => val, - Reading::NumberPm2_5(val) => val, - Reading::NumberPm4_0(val) => val, - Reading::NumberPm10(val) => val, - Reading::TypicalParticleSize(val) => val, - } +impl Tomato for Reading { + fn inner<'a>(&'a self) -> TomatoItem<'a> { + let val = match self { + Reading::Brightness(val) => *val, + Reading::Temperature(val) => *val, + Reading::Humidity(val) => *val, + Reading::GassResistance(val) => *val, + Reading::Pressure(val) => *val, + Reading::Co2(val) => *val as f32, + Reading::WeightLeft(val) => *val as f32, + Reading::WeightRight(val) => *val as f32, + Reading::Button(val) => (*val).into(), + Reading::MassPm1_0(val) => *val, + Reading::MassPm2_5(val) => *val, + Reading::MassPm4_0(val) => *val, + Reading::MassPm10(val) => *val, + Reading::MassPm0_5(val) => *val, + Reading::NumberPm1_0(val) => *val, + Reading::NumberPm2_5(val) => *val, + Reading::NumberPm4_0(val) => *val, + Reading::NumberPm10(val) => *val, + Reading::TypicalParticleSize(val) => *val, + }; + TomatoItem::Leaf(val) + } + + fn id(&self) -> crate::TomatoId { + ReadingDiscriminants::from(self) as crate::TomatoId } } diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index 00c92b4f..b2902127 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -1,8 +1,8 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; -use crate::button_enum; use crate::downcast_err::{GpioError, LinuxI2cError}; +use crate::{button_enum, Tomato, TomatoItem}; button_enum! { /// No these are not borg, these are buttons on a string of cat5. @@ -29,6 +29,22 @@ pub enum Reading { Button(Button), } +impl Tomato for Reading { + fn inner<'a>(&'a self) -> TomatoItem<'a> { + let val = match self { + Reading::Temperature(val) => *val, + Reading::Humidity(val) => *val, + Reading::Pressure(val) => *val, + Reading::Button(val) => (*val).into(), + }; + TomatoItem::Leaf(val) + } + + fn id(&self) -> crate::TomatoId { + ReadingDiscriminants::from(self) as crate::TomatoId + } +} + #[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] pub enum Error { Running(SensorError), diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 828efa52..721a7c88 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -1,5 +1,7 @@ #![cfg_attr(not(feature = "alloc"), no_std)] +use core::any::type_name; + use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -83,11 +85,55 @@ impl Press { } } -#[derive(strum::VariantNames, Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] +type TomatoId = u8; +pub enum TomatoItem<'a> { + Leaf(f32), + Node(&'a dyn Tomato), +} + +pub trait Tomato { + fn inner<'a>(&'a self) -> TomatoItem<'a>; + fn name(&self) -> &'static str { + type_name::() + } + fn id(&self) -> TomatoId; +} + +macro_rules! all_nodes { + ($name:ident; $variant:ident; $($var:ident),*) => { + impl Tomato for $name { + fn inner<'a>(&'a self) -> crate::TomatoItem<'a> { + match self { + $( + $name::$var(inner) => crate::TomatoItem::Node(inner as &dyn Tomato) + ),* + } + } + + fn id(&self) -> crate::TomatoId { + $variant::from(self) as crate::TomatoId + } + } + }; +} +pub(crate) use all_nodes; +all_nodes! {Reading; ReadingDiscriminants; LargeBedroom} //, Test} + +#[derive( + strum::EnumDiscriminants, + strum::VariantNames, + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, +)] +#[strum_discriminants(derive(Hash))] pub enum Reading { LargeBedroom(large_bedroom::Reading), // SmallBedroom(small_bedroom::Reading), - Test, + // Test, } #[derive(strum::VariantNames, Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] From ad81618ef9920a71c9983e02bc29fe3a63aae37e Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 26 May 2024 18:20:47 +0200 Subject: [PATCH 093/687] add lib for subscribing --- crates/data_server/Cargo.toml | 1 + crates/data_server/src/lib.rs | 54 ++++++++++++++++++++++++++++++++++ crates/data_server/src/main.rs | 4 +-- 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 crates/data_server/src/lib.rs diff --git a/crates/data_server/Cargo.toml b/crates/data_server/Cargo.toml index f3058b8c..dbcfe41a 100644 --- a/crates/data_server/Cargo.toml +++ b/crates/data_server/Cargo.toml @@ -14,3 +14,4 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } protocol = { path = "/home/david/Documents/HomeAutomation/crates/protocol", features = ["alloc"] } tokio = { version = "1.37.0", features = ["rt", "macros", "net", "sync", "io-util"] } tokio-stream = { version = "0.1.15", features = ["net"] } +thiserror = "1.0.61" diff --git a/crates/data_server/src/lib.rs b/crates/data_server/src/lib.rs new file mode 100644 index 00000000..1bb6339b --- /dev/null +++ b/crates/data_server/src/lib.rs @@ -0,0 +1,54 @@ +use std::io::{BufRead, BufReader}; +use std::net::{TcpStream, ToSocketAddrs}; + +use protocol::{DecodeError, SensorMessage}; + +pub struct Subscriber { + reader: BufReader, + buf: Vec, + values: std::vec::IntoIter, +} + +type Msg = Result; + +impl Subscriber { + pub fn connect(addr: impl ToSocketAddrs) -> Result { + let conn = TcpStream::connect(addr)?; + let reader = BufReader::new(conn); + let buf = Vec::new(); + + Ok(Self { + reader, + buf, + values: vec![].into_iter(), + }) + } + + pub fn next(&mut self) -> Result { + if let Some(val) = self.values.next() { + return Ok(val); + } + + let n_read = self + .reader + .read_until(0, &mut self.buf) + .map_err(SubscribeError::ConnFailed)?; + + let msg = &mut self.buf[0..n_read]; + let msg = SensorMessage::<6>::decode(msg).map_err(SubscribeError::DecodeFailed)?; + + self.values = msg.values.to_vec().into_iter(); + Ok(self + .values + .next() + .expect("min values in sensormessage is one")) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum SubscribeError { + #[error("The connection to the subscribe server failed")] + ConnFailed(std::io::Error), + #[error("The connection to the subscribe server failed")] + DecodeFailed(DecodeError), +} diff --git a/crates/data_server/src/main.rs b/crates/data_server/src/main.rs index 55413298..bc73ffdf 100644 --- a/crates/data_server/src/main.rs +++ b/crates/data_server/src/main.rs @@ -8,7 +8,7 @@ use tokio_stream::wrappers::TcpListenerStream; use tokio_stream::StreamExt; use color_eyre::{Result, Section}; -use protocol::{Sensor, SensorMessage}; +use protocol::{Reading, SensorMessage}; use clap::Parser; use tokio::select; @@ -58,7 +58,7 @@ async fn handle_client(stream: TcpStream, tx: Sender) { enum Event { NewSub(TcpStream), - NewReading(Sensor), + NewReading(Result), } async fn spread_updates( From 29feb6e6ab3304d6deeea50e131fcb695a278140 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 26 May 2024 18:26:19 +0200 Subject: [PATCH 094/687] add tree to tui --- Cargo.lock | 249 ++++++++++++++++++ .../{data_server => data-server}/.gitignore | 0 .../{data_server => data-server}/Cargo.lock | 0 .../{data_server => data-server}/Cargo.toml | 0 crates/{data_server => data-server}/deploy.sh | 0 .../{data_server => data-server}/src/lib.rs | 0 .../{data_server => data-server}/src/main.rs | 0 crates/sensor_tui/Cargo.toml | 5 +- crates/sensor_tui/src/main.rs | 64 +---- crates/sensor_tui/src/tui.rs | 60 ++--- crates/sensor_tui/src/tui/reading.rs | 189 ++++++++----- crates/sensor_tui/src/tui/render.rs | 22 +- 12 files changed, 419 insertions(+), 170 deletions(-) rename crates/{data_server => data-server}/.gitignore (100%) rename crates/{data_server => data-server}/Cargo.lock (100%) rename crates/{data_server => data-server}/Cargo.toml (100%) rename crates/{data_server => data-server}/deploy.sh (100%) rename crates/{data_server => data-server}/src/lib.rs (100%) rename crates/{data_server => data-server}/src/main.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index b5dee844..8ee9de67 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,18 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if 1.0.0", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -26,6 +38,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -390,12 +408,27 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +[[package]] +name = "cassowary" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" + [[package]] name = "cast" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" +[[package]] +name = "castaway" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a17ed5635fc8536268e5d4de1e22e81ac34419e5f052d4d51f4e01dcc263fcc" +dependencies = [ + "rustversion", +] + [[package]] name = "cc" version = "1.0.98" @@ -523,6 +556,19 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +[[package]] +name = "compact_str" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" +dependencies = [ + "castaway", + "cfg-if 1.0.0", + "itoa 1.0.11", + "ryu", + "static_assertions", +] + [[package]] name = "const_fn" version = "0.4.10" @@ -733,6 +779,31 @@ version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +[[package]] +name = "crossterm" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" +dependencies = [ + "bitflags 2.5.0", + "crossterm_winapi", + "libc", + "mio 0.8.11", + "parking_lot 0.12.2", + "signal-hook", + "signal-hook-mio", + "winapi 0.3.9", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "ct-logs" version = "0.6.0" @@ -742,6 +813,21 @@ dependencies = [ "sct 0.6.1", ] +[[package]] +name = "data-server" +version = "0.0.0" +dependencies = [ + "clap", + "color-eyre", + "protocol", + "thiserror", + "tokio 1.37.0", + "tokio-stream", + "tracing", + "tracing-error", + "tracing-subscriber", +] + [[package]] name = "defmt" version = "0.3.8" @@ -1445,6 +1531,10 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] [[package]] name = "heapless" @@ -1489,6 +1579,15 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "histogram" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bd81cb9a629d0a868f2092937332fca5fd985971d2155bf6fcc225ef8a6be2c" +dependencies = [ + "thiserror", +] + [[package]] name = "http" version = "0.1.21" @@ -1839,6 +1938,15 @@ version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.8" @@ -1940,6 +2048,15 @@ dependencies = [ "log", ] +[[package]] +name = "lru" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +dependencies = [ + "hashbrown 0.14.5", +] + [[package]] name = "mach2" version = "0.4.2" @@ -2098,6 +2215,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", + "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] @@ -2340,6 +2458,12 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "percent-encoding" version = "1.0.1" @@ -2663,6 +2787,26 @@ dependencies = [ "rand_core 0.3.1", ] +[[package]] +name = "ratatui" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f44c9e68fd46eda15c646fbb85e1040b657a58cdc8c98db1d97a55930d991eef" +dependencies = [ + "bitflags 2.5.0", + "cassowary", + "compact_str", + "crossterm", + "itertools", + "lru", + "paste", + "stability", + "strum", + "unicode-segmentation", + "unicode-truncate", + "unicode-width", +] + [[package]] name = "rdrand" version = "0.4.0" @@ -2980,6 +3124,22 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "sensor_tui" +version = "0.0.0" +dependencies = [ + "color-eyre", + "crossterm", + "data-server", + "histogram", + "protocol", + "ratatui", + "tracing", + "tracing-error", + "tracing-subscriber", + "tui-tree-widget", +] + [[package]] name = "serde" version = "1.0.202" @@ -3098,6 +3258,27 @@ dependencies = [ "thiserror", ] +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +dependencies = [ + "libc", + "mio 0.8.11", + "signal-hook", +] + [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -3197,12 +3378,28 @@ dependencies = [ "thiserror", ] +[[package]] +name = "stability" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ff9eaf853dec4c8802325d8b6d3dffa86cc707fd7a1a4cdbf416e13b061787a" +dependencies = [ + "quote", + "syn 2.0.65", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "stm32-fmc" version = "0.3.0" @@ -3764,6 +3961,16 @@ dependencies = [ "cfg-if 0.1.10", ] +[[package]] +name = "tui-tree-widget" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6201de8ad8d88cb6cac4cfe3436d9a1ea31c0732a7aec4c2cc3b23186ad7dcc" +dependencies = [ + "ratatui", + "unicode-width", +] + [[package]] name = "tz-rs" version = "0.6.14" @@ -3812,6 +4019,28 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "unicode-truncate" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5fbabedabe362c618c714dbefda9927b5afc8e2a8102f47f081089a9019226" +dependencies = [ + "itertools", + "unicode-width", +] + +[[package]] +name = "unicode-width" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" + [[package]] name = "unicode-xid" version = "0.2.4" @@ -4264,3 +4493,23 @@ checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" dependencies = [ "tap", ] + +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] diff --git a/crates/data_server/.gitignore b/crates/data-server/.gitignore similarity index 100% rename from crates/data_server/.gitignore rename to crates/data-server/.gitignore diff --git a/crates/data_server/Cargo.lock b/crates/data-server/Cargo.lock similarity index 100% rename from crates/data_server/Cargo.lock rename to crates/data-server/Cargo.lock diff --git a/crates/data_server/Cargo.toml b/crates/data-server/Cargo.toml similarity index 100% rename from crates/data_server/Cargo.toml rename to crates/data-server/Cargo.toml diff --git a/crates/data_server/deploy.sh b/crates/data-server/deploy.sh similarity index 100% rename from crates/data_server/deploy.sh rename to crates/data-server/deploy.sh diff --git a/crates/data_server/src/lib.rs b/crates/data-server/src/lib.rs similarity index 100% rename from crates/data_server/src/lib.rs rename to crates/data-server/src/lib.rs diff --git a/crates/data_server/src/main.rs b/crates/data-server/src/main.rs similarity index 100% rename from crates/data_server/src/main.rs rename to crates/data-server/src/main.rs diff --git a/crates/sensor_tui/Cargo.toml b/crates/sensor_tui/Cargo.toml index 7a2e6950..457fe67f 100644 --- a/crates/sensor_tui/Cargo.toml +++ b/crates/sensor_tui/Cargo.toml @@ -10,8 +10,11 @@ authors.workspace = true color-eyre = "0.6.3" crossterm = "0.27.0" histogram = "0.10.1" -protocol = { path = "/home/david/Documents/HomeAutomation/crates/protocol" } ratatui = "0.26.2" tracing = "0.1.40" tracing-error = "0.2.0" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +tui-tree-widget = "0.20.0" + +protocol = { path = "/home/david/Documents/HomeAutomation/crates/protocol" } +data-server = { path = "/home/david/Documents/HomeAutomation/crates/data-server" } diff --git a/crates/sensor_tui/src/main.rs b/crates/sensor_tui/src/main.rs index 771f436f..ec9d239e 100644 --- a/crates/sensor_tui/src/main.rs +++ b/crates/sensor_tui/src/main.rs @@ -1,49 +1,14 @@ -use std::io::prelude::*; -use std::io::BufReader; -use std::net::{TcpListener, TcpStream}; +use std::net::SocketAddr; use std::sync::mpsc; -use std::sync::mpsc::Sender; use std::thread; use color_eyre::Result; -use protocol::SensorMessage; - mod tui; -fn handle_client(stream: TcpStream, tx: Sender) { - let mut reader = BufReader::new(stream); - let mut buf = Vec::new(); - loop { - let n_read = match reader.read_until(0, &mut buf) { - Err(e) => { - tx.send(Update::ConnFailed).unwrap(); - return; - } - Ok(bytes) => bytes, - }; - let msg = &mut buf[0..n_read]; - let msg = match SensorMessage::<6>::decode(msg) { - Ok(msg) => msg, - Err(e) => { - tx.send(Update::DecodeFailed(e)).unwrap(); - continue; - } - }; - let values = msg.values; - for value in values.into_iter() { - tx.send(Update::Data(value)).unwrap(); - } - - buf.clear(); - } -} - enum Update { - Data(protocol::Sensor), - ConnFailed, - NewConn(std::net::SocketAddr), - DecodeFailed(protocol::DecodeError), + Reading(protocol::Reading), + Error(protocol::Error), } fn main() -> Result<()> { @@ -52,25 +17,18 @@ fn main() -> Result<()> { thread::spawn(|| tui::run(rx)); - let listener = TcpListener::bind("0.0.0.0:1234")?; + let addr = SocketAddr::from(([127, 0, 0, 1], 1235)); + let mut sub = data_server::Subscriber::connect(addr).unwrap(); - // accept connections and process them serially - for stream in listener.incoming() { - let stream = match stream { - Ok(stream) => stream, - Err(e) => { - println!("new connection failed: {e}"); - continue; - } + while let Ok(val) = sub.next() { + let update = match val { + Ok(reading) => Update::Reading(reading), + Err(error) => Update::Error(error), }; - tx.send(Update::NewConn(stream.peer_addr().unwrap())) - .unwrap(); - { - let tx = tx.clone(); - std::thread::spawn(move || handle_client(stream, tx)); - } + tx.send(update).unwrap(); } + Ok(()) } diff --git a/crates/sensor_tui/src/tui.rs b/crates/sensor_tui/src/tui.rs index a181a6f9..453c3835 100644 --- a/crates/sensor_tui/src/tui.rs +++ b/crates/sensor_tui/src/tui.rs @@ -8,10 +8,9 @@ use ratatui::{ style::{Color, Style}, widgets::ListState, }; +use tui_tree_widget::TreeState; use std::{ - io::stdout, - sync::mpsc, - time::{Duration, Instant}, + collections::HashMap, io::stdout, sync::mpsc, time::{Duration, Instant} }; mod reading; @@ -63,7 +62,7 @@ impl ConnInfo { } pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { - let mut readings = Readings { map: Vec::new() }; + let mut readings = Readings { ground: Vec::new(), data: HashMap::new() }; let mut conn_info = None; stdout().execute(EnterAlternateScreen)?; @@ -72,7 +71,7 @@ pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { terminal.clear()?; let mut active_list = ActiveList::Readings; - let mut reading_list_state = ListState::default(); + let mut reading_list_state = TreeState::default(); let mut actuator_list_state = ListState::default(); let actuators = vec![ "placeholder 1".to_owned(), @@ -80,7 +79,6 @@ pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { "placeholder 3".to_owned(), ]; let mut plot_buf = Vec::new(); - let mut selected = None; loop { let conn_status = conn_info @@ -88,14 +86,15 @@ pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { .map(ConnInfo::conn_status) .unwrap_or_else(|| format!("no connected client")); - let chart = if let Some(key) = selected { - readings.chart(key, &mut plot_buf) + let chart = if !reading_list_state.selected().is_empty() { + readings.chart(reading_list_state.selected(), &mut plot_buf) } else { None }; - let histogram = if let Some(key) = selected { - readings.histogram(key) + let histogram = if !reading_list_state.selected().is_empty() { + let key = reading_list_state.selected().first().unwrap(); + readings.histogram(*key) } else { readings.histogram_all() }; @@ -103,7 +102,7 @@ pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { terminal.draw(|frame| { render::all( frame, - readings.list(), + &readings.ground, &mut reading_list_state, actuators.clone(), &mut actuator_list_state, @@ -132,49 +131,22 @@ pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { active_list = active_list.swap(); } if key.code == KeyCode::Down { - reading_list_state.select(Some( - reading_list_state - .selected() - .map(|i| { - if i + 1 >= readings.list().len() { - 0 - } else { - i + 1 - } - }) - .unwrap_or(0), - )); + reading_list_state.key_down(); } if key.code == KeyCode::Up { - reading_list_state.select( - reading_list_state - .selected() - .map(|i| if i == 0 { None } else { Some(i - 1) }) - .unwrap_or_else(|| Some(readings.list().len() - 1)), - ); + reading_list_state.key_up(); } } } } - selected = reading_list_state.selected().map(|i| readings.map[i].0); - match rx.try_recv() { - Ok(Update::Data(data)) => { - conn_info.as_mut().unwrap().got_msg(); - readings.add(data); - } - Ok(Update::NewConn(source)) => { - conn_info = Some(ConnInfo { - last_msg: Instant::now(), - addr: source, - }); - } - Ok(Update::DecodeFailed(_)) => { + Ok(Update::Reading(reading)) => { conn_info.as_mut().unwrap().got_msg(); + readings.add(reading); } - Ok(Update::ConnFailed) => { - conn_info = None; + Ok(Update::Error(err)) => { + tracing::warn!("sensor error: {err:?}"); } _ => (), } diff --git a/crates/sensor_tui/src/tui/reading.rs b/crates/sensor_tui/src/tui/reading.rs index d0e59cff..ac57ad45 100644 --- a/crates/sensor_tui/src/tui/reading.rs +++ b/crates/sensor_tui/src/tui/reading.rs @@ -1,10 +1,10 @@ use histogram::Histogram; -use protocol::{ - large_bedroom::{Error, LargeBedroomDiscriminants}, - Sensor, -}; +use protocol::large_bedroom::Error; +use protocol::{Reading, Tomato, TomatoItem}; use ratatui::{text::Line, widgets::Bar}; +use std::collections::HashMap; use std::{collections::VecDeque, time::Instant}; +use tui_tree_widget::TreeItem; pub struct SensorInfo { timing: Histogram, @@ -34,87 +34,152 @@ impl SensorInfo { } } +pub type TreeKey = [u8; 6]; pub struct Readings { - pub map: Vec<(LargeBedroomDiscriminants, SensorInfo)>, + pub ground: Vec>, + pub data: HashMap, } -impl Readings { - pub fn add(&mut self, data: Sensor) { - match data { - Sensor::LargeBedroom(data) => { - let key = LargeBedroomDiscriminants::from(data); - if let Some((_, info)) = self.map.iter_mut().find(|p| p.0 == key) { - if let Ok(last_reading) = info.last_at() { - info.timing - .increment(last_reading.elapsed().as_millis() as u64) - .unwrap(); - } - info.history.push_front((Instant::now(), data.into())); - info.condition = Ok(()); - } else { - let mut history = VecDeque::new(); - history.push_front((Instant::now(), data.into())); - self.map.push(( - key, - SensorInfo { - timing: Histogram::new(4, 24).unwrap(), - history, - condition: Ok(()), - }, - )); - } +fn add_leaf(tomato: &dyn Tomato, tree: &mut TreeItem<'static, TreeKey>, key: TreeKey) { + // let text = format!("{}: {}", tomato.name(), val); + let new_item = TreeItem::new_leaf(key, tomato.name()); + // todo is exists its fine handle that + tree.add_child(new_item); // errors when identifier already exists + + // let new_child = tree + // .children() + // .iter() + // .position(|item| *item.identifier() == tomato.id()) + // .expect("just added it"); + // let existing = tree.child_mut(new_child).expect("just added it") +} + +fn add_root<'a>( + tomato: &dyn Tomato, + ground: &'a mut Vec>, +) -> &'a mut TreeItem<'static, TreeKey> { + let key = [tomato.id(); 6]; + let exists = ground.iter().any(|item| *item.identifier() == key); + if !exists { + let new_root = TreeItem::new(key, tomato.name(), vec![]).unwrap(); + ground.push(new_root); + } + + ground + .iter_mut() + .find(|item| *item.identifier() == key) + .expect("checked and added if missing") +} + +fn add_node<'a>( + tomato: &dyn Tomato, + tree: &'a mut TreeItem<'static, TreeKey>, +) -> &'a mut TreeItem<'static, TreeKey> { + let key = [tomato.id(); 6]; + let new_item = TreeItem::new(key, tomato.name(), Vec::new()).unwrap(); + // todo is exists its fine handle that + tree.add_child(new_item); // errors when identifier already exists + let new_child = tree + .children() + .iter() + .position(|item| *item.identifier() == key) + .expect("just added it"); + tree.child_mut(new_child).expect("just added it") +} + +fn extract_keyval(reading: &Reading) -> (TreeKey, f32) { + let mut key = [0u8; 6]; + key[0] = reading.id(); + + let mut reading = reading as &dyn Tomato; + for byte in &mut key[1..] { + reading = match reading.inner() { + TomatoItem::Node(inner) => { + *byte = inner.id(); + inner } - Sensor::LargeBedroomError(err) => { - for key in err.broken_readings() { - if let Some((_, info)) = self.map.iter_mut().find(|p| p.0 == *key) { - info.condition = Err(err.clone()); - } else { - self.map.push(( - *key, - SensorInfo { - timing: Histogram::new(4, 24).unwrap(), - history: VecDeque::new(), - condition: Err(err.clone()), - }, - )) - } - } + TomatoItem::Leaf(val) => { + *byte = reading.id(); + return (key, val); } - _ => todo!(), + }; + } + unreachable!("reading should not be deeper then key size") +} + +impl Readings { + pub fn add(&mut self, reading: Reading) { + self.update_tree(&reading); + self.record_data(reading); + } + + fn record_data(&mut self, reading: Reading) { + let (key, val) = extract_keyval(&reading); + + if let Some(info) = self.data.get_mut(&key) { + if let Ok(last_reading) = info.last_at() { + info.timing + .increment(last_reading.elapsed().as_millis() as u64) + .unwrap(); + } + info.history.push_front((Instant::now(), val)); + info.condition = Ok(()); + } else { + let mut history = VecDeque::new(); + history.push_front((Instant::now(), val)); + self.data.insert( + key, + SensorInfo { + timing: Histogram::new(4, 24).unwrap(), + history, + condition: Ok(()), + }, + ); } } - pub fn list(&self) -> Vec { - self.map - .iter() - .map(|(key, val)| { - let val = val.last(); - format!("{key:?}: {val:?}\n") - }) - .collect() + fn update_tree(&mut self, reading: &Reading) { + let (key, _) = extract_keyval(reading); + + let mut tomato = reading as &dyn Tomato; + let mut tree = add_root(tomato, &mut self.ground); + loop { + match tomato.inner() { + TomatoItem::Leaf(_) => { + add_leaf(tomato, tree, key); + return; + } + TomatoItem::Node(inner) => { + tomato = inner; + tree = add_node(tomato, tree); + } + }; + } } pub fn histogram_all(&self) -> Vec { let mut all = Histogram::new(4, 24).unwrap(); - for (_, val) in self.map.iter() { + for (_, val) in self.data.iter() { all = all.checked_add(&val.timing).unwrap(); } histogram_bars(&all) } - pub fn histogram(&self, key: LargeBedroomDiscriminants) -> Vec { - let hist = &self.map.iter().find(|p| p.0 == key).unwrap().1.timing; + pub fn histogram(&self, key: TreeKey) -> Vec { + let hist = &self.data.get(&key).unwrap().timing; histogram_bars(hist) } pub fn chart<'a>( &mut self, - key: LargeBedroomDiscriminants, + selected: &[TreeKey], plot_buf: &'a mut Vec<(f64, f64)>, ) -> Option> { - let data = &self.map.iter_mut().find(|p| p.0 == key).unwrap().1; - plot_buf.clear(); + + let key = selected.first().unwrap(); + let data = &self.data.get(key).expect("data is never removed"); + for xy in data .history .iter() @@ -136,7 +201,9 @@ pub struct ChartParts<'a> { } fn histogram_bars(hist: &Histogram) -> Vec> { - let percentiles = hist.percentiles(&[25.0, 50.0, 75.0, 90.0, 95.0, 100.0]).unwrap(); + let percentiles = hist + .percentiles(&[25.0, 50.0, 75.0, 90.0, 95.0, 100.0]) + .unwrap(); percentiles .into_iter() .map(|(p, bucket)| { diff --git a/crates/sensor_tui/src/tui/render.rs b/crates/sensor_tui/src/tui/render.rs index cf956d51..163a1213 100644 --- a/crates/sensor_tui/src/tui/render.rs +++ b/crates/sensor_tui/src/tui/render.rs @@ -1,7 +1,7 @@ use ratatui::{ self, layout::{Constraint, Layout, Rect}, - style::{Color, Modifier, Style, Stylize}, + style::{Modifier, Style}, symbols, widgets::{ Axis, Bar, BarChart, BarGroup, Block, Borders, Chart, Dataset, GraphType, List, ListState, @@ -9,13 +9,14 @@ use ratatui::{ }, Frame, }; +use tui_tree_widget::{Tree, TreeItem, TreeState}; -use super::{reading::ChartParts, ActiveList}; +use super::{reading::{ChartParts, TreeKey}, ActiveList}; pub(crate) fn all( frame: &mut Frame, - readings: Vec, - reading_list_state: &mut ListState, + readings: &[TreeItem<'static, TreeKey>], + reading_state: &mut TreeState, actuators: Vec, actuator_list_state: &mut ListState, active_list: ActiveList, @@ -32,7 +33,7 @@ pub(crate) fn all( frame, top, readings, - reading_list_state, + reading_state, actuators, actuator_list_state, active_list, @@ -120,8 +121,8 @@ fn global_view(frame: &mut Frame, layout: Rect, histogram: &[Bar]) { pub(crate) fn render_top( frame: &mut Frame, layout: Rect, - readings: Vec, - reading_list_state: &mut ListState, + readings: &[TreeItem<'static, TreeKey>], + reading_list_state: &mut TreeState, actuators: Vec, actuator_list_state: &mut ListState, active_list: ActiveList, @@ -139,7 +140,8 @@ pub(crate) fn render_top( .areas(vertical[1]); frame.render_stateful_widget( - List::new(readings) + Tree::new(&readings) + .expect("all item identifiers should be unique") .block( Block::default() .title("Sensor readings") @@ -148,9 +150,7 @@ pub(crate) fn render_top( ) .style(active_list.style(ActiveList::Readings)) .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) - .highlight_symbol(">>") - .repeat_highlight_symbol(false) - .direction(ratatui::widgets::ListDirection::TopToBottom), + .highlight_symbol(">>"), horizontal[0], reading_list_state, ); From bfe7b92d69f53ad9caac5fe3b418562c846e01ab Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 27 May 2024 13:40:12 +0200 Subject: [PATCH 095/687] renames desk_sensors + update tui tree using fork --- Cargo.lock | 5 +-- crates/data-server/deploy.sh | 10 ++--- .../{desk_sensors => desk-sensors}/.gitignore | 0 .../{desk_sensors => desk-sensors}/Cargo.lock | 0 .../{desk_sensors => desk-sensors}/Cargo.toml | 2 +- .../{desk_sensors => desk-sensors}/deploy.sh | 0 .../src/buttons.rs | 0 .../src/main.rs | 0 .../src/sensors.rs | 0 crates/sensor_tui/Cargo.toml | 2 +- crates/sensor_tui/src/main.rs | 7 ++-- crates/sensor_tui/src/tui/reading.rs | 42 ++++++++----------- 12 files changed, 29 insertions(+), 39 deletions(-) rename crates/{desk_sensors => desk-sensors}/.gitignore (100%) rename crates/{desk_sensors => desk-sensors}/Cargo.lock (100%) rename crates/{desk_sensors => desk-sensors}/Cargo.toml (96%) rename crates/{desk_sensors => desk-sensors}/deploy.sh (100%) rename crates/{desk_sensors => desk-sensors}/src/buttons.rs (100%) rename crates/{desk_sensors => desk-sensors}/src/main.rs (100%) rename crates/{desk_sensors => desk-sensors}/src/sensors.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 8ee9de67..6ba25e75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -883,7 +883,7 @@ dependencies = [ ] [[package]] -name = "desk_sensors" +name = "desk-sensors" version = "0.2.0" dependencies = [ "bme280", @@ -3964,8 +3964,7 @@ dependencies = [ [[package]] name = "tui-tree-widget" version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6201de8ad8d88cb6cac4cfe3436d9a1ea31c0732a7aec4c2cc3b23186ad7dcc" +source = "git+https://github.com/dvdsk/tui-rs-tree-widget#4da570ec5761b51bcd4c667dc66da1b197fe9b22" dependencies = [ "ratatui", "unicode-width", diff --git a/crates/data-server/deploy.sh b/crates/data-server/deploy.sh index 65d3e593..29b5bf69 100755 --- a/crates/data-server/deploy.sh +++ b/crates/data-server/deploy.sh @@ -2,9 +2,9 @@ set -e BUILD_ARG=$1 -SERVER="sgc" # ssh config name or full adress +SERVER="sgc" # ssh config name or full address RELEASE=debug -NAME=datasplitter +NAME=data-server if [[ BUILD_ARG == "--release" ]]; then RELEASE=release @@ -16,9 +16,9 @@ rsync -vh --progress \ $SERVER:/tmp/ cmds=" -sudo mv /tmp/$NAME /home/data/$NAME -sudo chown data:data /home/data/$NAME -sudo systemctl restart datasplitter.service +sudo mv /tmp/$NAME /home/ha/$NAME +sudo chown ha:ha /home/ha/$NAME +sudo systemctl restart data-server.service " ssh -t sgc "$cmds" diff --git a/crates/desk_sensors/.gitignore b/crates/desk-sensors/.gitignore similarity index 100% rename from crates/desk_sensors/.gitignore rename to crates/desk-sensors/.gitignore diff --git a/crates/desk_sensors/Cargo.lock b/crates/desk-sensors/Cargo.lock similarity index 100% rename from crates/desk_sensors/Cargo.lock rename to crates/desk-sensors/Cargo.lock diff --git a/crates/desk_sensors/Cargo.toml b/crates/desk-sensors/Cargo.toml similarity index 96% rename from crates/desk_sensors/Cargo.toml rename to crates/desk-sensors/Cargo.toml index 6de7117d..bc59d10b 100644 --- a/crates/desk_sensors/Cargo.toml +++ b/crates/desk-sensors/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "desk_sensors" +name = "desk-sensors" version = "0.2.0" edition.workspace = true license.workspace = true diff --git a/crates/desk_sensors/deploy.sh b/crates/desk-sensors/deploy.sh similarity index 100% rename from crates/desk_sensors/deploy.sh rename to crates/desk-sensors/deploy.sh diff --git a/crates/desk_sensors/src/buttons.rs b/crates/desk-sensors/src/buttons.rs similarity index 100% rename from crates/desk_sensors/src/buttons.rs rename to crates/desk-sensors/src/buttons.rs diff --git a/crates/desk_sensors/src/main.rs b/crates/desk-sensors/src/main.rs similarity index 100% rename from crates/desk_sensors/src/main.rs rename to crates/desk-sensors/src/main.rs diff --git a/crates/desk_sensors/src/sensors.rs b/crates/desk-sensors/src/sensors.rs similarity index 100% rename from crates/desk_sensors/src/sensors.rs rename to crates/desk-sensors/src/sensors.rs diff --git a/crates/sensor_tui/Cargo.toml b/crates/sensor_tui/Cargo.toml index 457fe67f..6b52404e 100644 --- a/crates/sensor_tui/Cargo.toml +++ b/crates/sensor_tui/Cargo.toml @@ -14,7 +14,7 @@ ratatui = "0.26.2" tracing = "0.1.40" tracing-error = "0.2.0" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -tui-tree-widget = "0.20.0" +tui-tree-widget = { version = "0.20.0", git = "https://github.com/dvdsk/tui-rs-tree-widget" } protocol = { path = "/home/david/Documents/HomeAutomation/crates/protocol" } data-server = { path = "/home/david/Documents/HomeAutomation/crates/data-server" } diff --git a/crates/sensor_tui/src/main.rs b/crates/sensor_tui/src/main.rs index ec9d239e..532d744a 100644 --- a/crates/sensor_tui/src/main.rs +++ b/crates/sensor_tui/src/main.rs @@ -13,13 +13,12 @@ enum Update { fn main() -> Result<()> { setup_tracing().unwrap(); - let (tx, rx) = mpsc::channel(); - - thread::spawn(|| tui::run(rx)); - let addr = SocketAddr::from(([127, 0, 0, 1], 1235)); let mut sub = data_server::Subscriber::connect(addr).unwrap(); + let (tx, rx) = mpsc::channel(); + thread::spawn(|| tui::run(rx)); + while let Ok(val) = sub.next() { let update = match val { Ok(reading) => Update::Reading(reading), diff --git a/crates/sensor_tui/src/tui/reading.rs b/crates/sensor_tui/src/tui/reading.rs index ac57ad45..d25fdca4 100644 --- a/crates/sensor_tui/src/tui/reading.rs +++ b/crates/sensor_tui/src/tui/reading.rs @@ -13,16 +13,6 @@ pub struct SensorInfo { } impl SensorInfo { - fn last(&self) -> Result { - self.condition.clone()?; - - let last = self - .history - .front() - .expect("Items are put in the map when they arrive with a value"); - Ok(last.1) - } - fn last_at(&self) -> Result { self.condition.clone()?; @@ -36,22 +26,24 @@ impl SensorInfo { pub type TreeKey = [u8; 6]; pub struct Readings { + // in the ground there are multiple trees pub ground: Vec>, pub data: HashMap, } -fn add_leaf(tomato: &dyn Tomato, tree: &mut TreeItem<'static, TreeKey>, key: TreeKey) { - // let text = format!("{}: {}", tomato.name(), val); - let new_item = TreeItem::new_leaf(key, tomato.name()); +fn add_leaf(name: &'static str, val: f32, tree: &mut TreeItem<'static, TreeKey>, key: TreeKey) { + let text = format!("{}: {}", name, val); + let new_item = TreeItem::new_leaf(key, text.clone()); // todo is exists its fine handle that - tree.add_child(new_item); // errors when identifier already exists - - // let new_child = tree - // .children() - // .iter() - // .position(|item| *item.identifier() == tomato.id()) - // .expect("just added it"); - // let existing = tree.child_mut(new_child).expect("just added it") + let _ignore_existing = tree.add_child(new_item); // errors when identifier already exists + + let new_child = tree + .children() + .iter() + .position(|item| *item.identifier() == key) + .expect("just added it"); + let existing = tree.child_mut(new_child).expect("just added it"); + existing.update_text(text); } fn add_root<'a>( @@ -77,8 +69,8 @@ fn add_node<'a>( ) -> &'a mut TreeItem<'static, TreeKey> { let key = [tomato.id(); 6]; let new_item = TreeItem::new(key, tomato.name(), Vec::new()).unwrap(); - // todo is exists its fine handle that - tree.add_child(new_item); // errors when identifier already exists + // add just in case it was not there yet + let _ignore_existing = tree.add_child(new_item); let new_child = tree .children() .iter() @@ -145,8 +137,8 @@ impl Readings { let mut tree = add_root(tomato, &mut self.ground); loop { match tomato.inner() { - TomatoItem::Leaf(_) => { - add_leaf(tomato, tree, key); + TomatoItem::Leaf(val) => { + add_leaf(tomato.name(), val, tree, key); return; } TomatoItem::Node(inner) => { From 410da302d13392b0d587675789c1c02f9bb879d6 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 27 May 2024 13:42:33 +0200 Subject: [PATCH 096/687] updated deploy to reflect new name --- crates/desk-sensors/deploy.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/desk-sensors/deploy.sh b/crates/desk-sensors/deploy.sh index 88e639c9..1295305b 100755 --- a/crates/desk-sensors/deploy.sh +++ b/crates/desk-sensors/deploy.sh @@ -12,13 +12,13 @@ fi rustup override set nightly cross build --target=aarch64-unknown-linux-gnu $BUILD_ARG rsync -vh --progress \ - target/aarch64-unknown-linux-gnu/$RELEASE/sensor_central \ + target/aarch64-unknown-linux-gnu/$RELEASE/desk-sensors \ $SERVER:/tmp/ cmds=" -sudo mv /tmp/sensor_central /home/ha/sensor_central -sudo chown ha:ha /home/ha/sensor_central -sudo systemctl restart sens.service +sudo mv /tmp/desk-sensors /home/ha/desk-sensors +sudo chown ha:ha /home/ha/desk-sensors +sudo systemctl restart desk-sensors.service " ssh -t sgc "$cmds" From 25bf0d0cabc4a7fc32d8e36d590c32007d9127f9 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 27 May 2024 13:42:55 +0200 Subject: [PATCH 097/687] rename sensor_tui --- crates/{sensor_tui => sensor-tui}/.gitignore | 0 crates/{sensor_tui => sensor-tui}/Cargo.lock | 0 crates/{sensor_tui => sensor-tui}/Cargo.toml | 2 +- crates/{sensor_tui => sensor-tui}/src/main.rs | 0 crates/{sensor_tui => sensor-tui}/src/tui.rs | 0 crates/{sensor_tui => sensor-tui}/src/tui/reading.rs | 0 crates/{sensor_tui => sensor-tui}/src/tui/render.rs | 0 7 files changed, 1 insertion(+), 1 deletion(-) rename crates/{sensor_tui => sensor-tui}/.gitignore (100%) rename crates/{sensor_tui => sensor-tui}/Cargo.lock (100%) rename crates/{sensor_tui => sensor-tui}/Cargo.toml (97%) rename crates/{sensor_tui => sensor-tui}/src/main.rs (100%) rename crates/{sensor_tui => sensor-tui}/src/tui.rs (100%) rename crates/{sensor_tui => sensor-tui}/src/tui/reading.rs (100%) rename crates/{sensor_tui => sensor-tui}/src/tui/render.rs (100%) diff --git a/crates/sensor_tui/.gitignore b/crates/sensor-tui/.gitignore similarity index 100% rename from crates/sensor_tui/.gitignore rename to crates/sensor-tui/.gitignore diff --git a/crates/sensor_tui/Cargo.lock b/crates/sensor-tui/Cargo.lock similarity index 100% rename from crates/sensor_tui/Cargo.lock rename to crates/sensor-tui/Cargo.lock diff --git a/crates/sensor_tui/Cargo.toml b/crates/sensor-tui/Cargo.toml similarity index 97% rename from crates/sensor_tui/Cargo.toml rename to crates/sensor-tui/Cargo.toml index 6b52404e..b77a6d68 100644 --- a/crates/sensor_tui/Cargo.toml +++ b/crates/sensor-tui/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "sensor_tui" +name = "sensor-tui" edition.workspace = true license.workspace = true authors.workspace = true diff --git a/crates/sensor_tui/src/main.rs b/crates/sensor-tui/src/main.rs similarity index 100% rename from crates/sensor_tui/src/main.rs rename to crates/sensor-tui/src/main.rs diff --git a/crates/sensor_tui/src/tui.rs b/crates/sensor-tui/src/tui.rs similarity index 100% rename from crates/sensor_tui/src/tui.rs rename to crates/sensor-tui/src/tui.rs diff --git a/crates/sensor_tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs similarity index 100% rename from crates/sensor_tui/src/tui/reading.rs rename to crates/sensor-tui/src/tui/reading.rs diff --git a/crates/sensor_tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs similarity index 100% rename from crates/sensor_tui/src/tui/render.rs rename to crates/sensor-tui/src/tui/render.rs From 5bc3f875b52e9e0fbbc275b379de4c1cd783bda6 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 27 May 2024 16:36:22 +0200 Subject: [PATCH 098/687] use rust-lld linker for crosscompilation --- crates/desk-sensors/.cargo/config.toml | 2 ++ crates/desk-sensors/deploy.sh | 3 +-- crates/desk-sensors/rust-toolchain.toml | 5 +++++ 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 crates/desk-sensors/.cargo/config.toml create mode 100644 crates/desk-sensors/rust-toolchain.toml diff --git a/crates/desk-sensors/.cargo/config.toml b/crates/desk-sensors/.cargo/config.toml new file mode 100644 index 00000000..4c770202 --- /dev/null +++ b/crates/desk-sensors/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +rustflags = ["-Clinker=rust-lld"] diff --git a/crates/desk-sensors/deploy.sh b/crates/desk-sensors/deploy.sh index 1295305b..e5488106 100755 --- a/crates/desk-sensors/deploy.sh +++ b/crates/desk-sensors/deploy.sh @@ -9,8 +9,7 @@ if [[ BUILD_ARG == "--release" ]]; then RELEASE=release fi -rustup override set nightly -cross build --target=aarch64-unknown-linux-gnu $BUILD_ARG +cargo build --target=aarch64-unknown-linux-musl $BUILD_ARG rsync -vh --progress \ target/aarch64-unknown-linux-gnu/$RELEASE/desk-sensors \ $SERVER:/tmp/ diff --git a/crates/desk-sensors/rust-toolchain.toml b/crates/desk-sensors/rust-toolchain.toml new file mode 100644 index 00000000..6e888d40 --- /dev/null +++ b/crates/desk-sensors/rust-toolchain.toml @@ -0,0 +1,5 @@ +[toolchain] +channel = "stable" +components = [] +targets = [ "aarch64-unknown-linux-musl" ] +profile = "minimal" From 69caf84281bf9f55d95ca8f20c311f185c828ec6 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 27 May 2024 16:37:09 +0200 Subject: [PATCH 099/687] adjusted deploy to take workspace into account --- crates/desk-sensors/deploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/desk-sensors/deploy.sh b/crates/desk-sensors/deploy.sh index e5488106..4a3ef694 100755 --- a/crates/desk-sensors/deploy.sh +++ b/crates/desk-sensors/deploy.sh @@ -11,7 +11,7 @@ fi cargo build --target=aarch64-unknown-linux-musl $BUILD_ARG rsync -vh --progress \ - target/aarch64-unknown-linux-gnu/$RELEASE/desk-sensors \ + ../../target/aarch64-unknown-linux-musl/$RELEASE/desk-sensors \ $SERVER:/tmp/ cmds=" From 30816a10e4f3fac6ceb3b9aefac26dde649d30b9 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 27 May 2024 18:43:25 +0200 Subject: [PATCH 100/687] remove need for cross for data-server --- Cargo.lock | 2 +- crates/data-server/.cargo/config.toml | 2 ++ crates/data-server/deploy.sh | 11 +++-------- crates/data-server/rust-toolchain.toml | 5 +++++ crates/data-server/src/lib.rs | 2 +- crates/desk-sensors/Cargo.toml | 2 +- crates/desk-sensors/deploy.sh | 10 +++------- crates/desk-sensors/src/buttons.rs | 3 ++- crates/sensor-tui/src/main.rs | 9 ++++++--- 9 files changed, 24 insertions(+), 22 deletions(-) create mode 100644 crates/data-server/.cargo/config.toml create mode 100644 crates/data-server/rust-toolchain.toml diff --git a/Cargo.lock b/Cargo.lock index 6ba25e75..6f23aad6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3125,7 +3125,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] -name = "sensor_tui" +name = "sensor-tui" version = "0.0.0" dependencies = [ "color-eyre", diff --git a/crates/data-server/.cargo/config.toml b/crates/data-server/.cargo/config.toml new file mode 100644 index 00000000..1002fed4 --- /dev/null +++ b/crates/data-server/.cargo/config.toml @@ -0,0 +1,2 @@ +[target.aarch64-unknown-linux-musl] +rustflags = ["-Clinker=rust-lld"] diff --git a/crates/data-server/deploy.sh b/crates/data-server/deploy.sh index 29b5bf69..4ee670ce 100755 --- a/crates/data-server/deploy.sh +++ b/crates/data-server/deploy.sh @@ -1,18 +1,13 @@ #!/usr/bin/env bash set -e -BUILD_ARG=$1 +BUILD_ARG=--release SERVER="sgc" # ssh config name or full address -RELEASE=debug NAME=data-server -if [[ BUILD_ARG == "--release" ]]; then - RELEASE=release -fi - -cross build --target=aarch64-unknown-linux-gnu $BUILD_ARG +cargo build --target=aarch64-unknown-linux-musl $BUILD_ARG rsync -vh --progress \ - target/aarch64-unknown-linux-gnu/$RELEASE/$NAME \ + ../../target/aarch64-unknown-linux-musl/release/$NAME \ $SERVER:/tmp/ cmds=" diff --git a/crates/data-server/rust-toolchain.toml b/crates/data-server/rust-toolchain.toml new file mode 100644 index 00000000..6e888d40 --- /dev/null +++ b/crates/data-server/rust-toolchain.toml @@ -0,0 +1,5 @@ +[toolchain] +channel = "stable" +components = [] +targets = [ "aarch64-unknown-linux-musl" ] +profile = "minimal" diff --git a/crates/data-server/src/lib.rs b/crates/data-server/src/lib.rs index 1bb6339b..44f87e74 100644 --- a/crates/data-server/src/lib.rs +++ b/crates/data-server/src/lib.rs @@ -35,7 +35,7 @@ impl Subscriber { .map_err(SubscribeError::ConnFailed)?; let msg = &mut self.buf[0..n_read]; - let msg = SensorMessage::<6>::decode(msg).map_err(SubscribeError::DecodeFailed)?; + let msg = SensorMessage::<50>::decode(msg).map_err(SubscribeError::DecodeFailed)?; self.values = msg.values.to_vec().into_iter(); Ok(self diff --git a/crates/desk-sensors/Cargo.toml b/crates/desk-sensors/Cargo.toml index bc59d10b..4f64060c 100644 --- a/crates/desk-sensors/Cargo.toml +++ b/crates/desk-sensors/Cargo.toml @@ -17,5 +17,5 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } tracing-error = "0.2.0" protocol = { path = "../protocol", features = ["alloc"] } -tokio = { version = "1.37.0", features = ["rt", "time"] } +tokio = { version = "1.37.0", features = ["rt", "time", "macros"] } embedded-hal-async = "1.0.0" diff --git a/crates/desk-sensors/deploy.sh b/crates/desk-sensors/deploy.sh index 4a3ef694..9438f703 100755 --- a/crates/desk-sensors/deploy.sh +++ b/crates/desk-sensors/deploy.sh @@ -1,13 +1,9 @@ #!/usr/bin/env bash set -e -BUILD_ARG=$1 -SERVER="sgc" # ssh config name or full adress -RELEASE=debug - -if [[ BUILD_ARG == "--release" ]]; then - RELEASE=release -fi +SERVER="sgc" # ssh config name or full address +BUILD_ARG=--release +RELEASE=release cargo build --target=aarch64-unknown-linux-musl $BUILD_ARG rsync -vh --progress \ diff --git a/crates/desk-sensors/src/buttons.rs b/crates/desk-sensors/src/buttons.rs index 6d2bf4b9..e9882d4f 100644 --- a/crates/desk-sensors/src/buttons.rs +++ b/crates/desk-sensors/src/buttons.rs @@ -10,7 +10,7 @@ use protocol::large_bedroom::desk::{Button, SetupError}; use crate::{send_error, send_reading}; -const CHIP: &str = "pinctrl-bcm2835"; +const CHIP: &str = "/dev/gpiochip0"; async fn watch_pin( offset: u32, @@ -80,6 +80,7 @@ async fn watch_pins(tx: &Sender>) { pub fn start_monitoring(tx: Sender>) { thread::spawn(move || { let rt = tokio::runtime::Builder::new_current_thread() + .enable_io() .build() .unwrap(); rt.block_on(watch_pins(&tx)) diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index 532d744a..b3183d6c 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -2,7 +2,8 @@ use std::net::SocketAddr; use std::sync::mpsc; use std::thread; -use color_eyre::Result; +use color_eyre::eyre::WrapErr; +use color_eyre::{Help, Result}; mod tui; @@ -13,8 +14,10 @@ enum Update { fn main() -> Result<()> { setup_tracing().unwrap(); - let addr = SocketAddr::from(([127, 0, 0, 1], 1235)); - let mut sub = data_server::Subscriber::connect(addr).unwrap(); + let addr = SocketAddr::from(([192, 168, 1, 43], 1235)); + let mut sub = data_server::Subscriber::connect(addr) + .wrap_err("failed to connect") + .with_suggestion(|| format!("verify the server is listening on: {addr}"))?; let (tx, rx) = mpsc::channel(); thread::spawn(|| tui::run(rx)); From b92459c60b7ef276039a1ad0dbe87283a96f8e46 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 28 May 2024 10:51:47 +0200 Subject: [PATCH 101/687] listen for all traffic instead of local only --- crates/data-server/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/data-server/src/main.rs b/crates/data-server/src/main.rs index bc73ffdf..21d71751 100644 --- a/crates/data-server/src/main.rs +++ b/crates/data-server/src/main.rs @@ -113,7 +113,7 @@ async fn spread_updates( } async fn register_subs(port: u16, share: &mpsc::Sender) -> Result<()> { - let addr = SocketAddr::from(([127, 0, 0, 1], port)); + let addr = SocketAddr::from(([0, 0, 0, 0], port)); let listener = TcpListener::bind(addr) .await .wrap_err("Could not start listening for new subscribers") @@ -134,7 +134,7 @@ async fn register_subs(port: u16, share: &mpsc::Sender) -> Result<()> { } async fn receive_updates(port: u16, tx: &mpsc::Sender) -> Result<()> { - let addr = SocketAddr::from(([127, 0, 0, 1], port)); + let addr = SocketAddr::from(([0, 0, 0, 0], port)); let listener = TcpListener::bind(addr).await .wrap_err("Could not start receiving updates") .with_note(|| format!("trying to listen on port: {port}"))?; From 8f4dd7b242a2d5ef799cfa8f4d77af4668113e79 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 28 May 2024 14:30:23 +0200 Subject: [PATCH 102/687] fix functions swapped, log new connections --- crates/data-server/src/main.rs | 37 ++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/crates/data-server/src/main.rs b/crates/data-server/src/main.rs index 21d71751..070c18cb 100644 --- a/crates/data-server/src/main.rs +++ b/crates/data-server/src/main.rs @@ -12,7 +12,7 @@ use protocol::{Reading, SensorMessage}; use clap::Parser; use tokio::select; -use tracing::warn; +use tracing::{info, warn}; #[derive(Parser)] #[command(name = "data server")] @@ -112,45 +112,48 @@ async fn spread_updates( Ok(()) } -async fn register_subs(port: u16, share: &mpsc::Sender) -> Result<()> { +async fn handle_data_sources(port: u16, share: &mpsc::Sender) -> Result<()> { let addr = SocketAddr::from(([0, 0, 0, 0], port)); let listener = TcpListener::bind(addr) .await .wrap_err("Could not start listening for new subscribers") .with_note(|| format!("trying to listen on port: {port}"))?; - let mut listener = TcpListenerStream::new(listener); - // accept connections and process them serially - while let Some(stream) = listener.next().await { - match stream { - Ok(stream) => tokio::spawn(handle_client(stream, share.clone())), + loop { + let res = listener.accept().await; + match res { + Ok((stream, source)) => { + info!("new data source connected from: {source}"); + tokio::spawn(handle_client(stream, share.clone())); + } Err(e) => { println!("new connection failed: {e}"); continue; } }; } - Ok(()) } -async fn receive_updates(port: u16, tx: &mpsc::Sender) -> Result<()> { +async fn register_subs(port: u16, tx: &mpsc::Sender) -> Result<()> { let addr = SocketAddr::from(([0, 0, 0, 0], port)); - let listener = TcpListener::bind(addr).await + let listener = TcpListener::bind(addr) + .await .wrap_err("Could not start receiving updates") .with_note(|| format!("trying to listen on port: {port}"))?; - let mut listener = TcpListenerStream::new(listener); - // accept connections and process them serially - while let Some(res) = listener.next().await { + loop { + let res = listener.accept().await; match res { - Ok(stream) => tx.send(Event::NewSub(stream)).await.unwrap(), + Ok((stream, source)) => { + info!("new subscriber connected from: {source}"); + tx.send(Event::NewSub(stream)).await.unwrap(); + } Err(e) => { - println!("new connection failed: {e}"); + warn!("new connection failed: {e}"); continue; } }; } - Ok(()) } #[tokio::main(flavor = "current_thread")] @@ -165,8 +168,8 @@ async fn main() -> Result<()> { let (tx, rx) = mpsc::channel(2000); select! { - e = receive_updates(update_port, &tx) => e, e = register_subs(subscribe_port, &tx) => e, + e = handle_data_sources(update_port, &tx) => e, e = spread_updates(rx, &tx) => e, } } From c8e09547f37c65995d69c944a56f423ebaea6825 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 28 May 2024 14:30:41 +0200 Subject: [PATCH 103/687] fix tokio runtime error + log events --- crates/desk-sensors/deploy.sh | 2 +- crates/desk-sensors/src/buttons.rs | 10 +++++++++- crates/desk-sensors/src/main.rs | 10 +++++++++- crates/desk-sensors/src/sensors.rs | 4 +++- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/crates/desk-sensors/deploy.sh b/crates/desk-sensors/deploy.sh index 9438f703..706e6fb0 100755 --- a/crates/desk-sensors/deploy.sh +++ b/crates/desk-sensors/deploy.sh @@ -13,7 +13,7 @@ rsync -vh --progress \ cmds=" sudo mv /tmp/desk-sensors /home/ha/desk-sensors sudo chown ha:ha /home/ha/desk-sensors -sudo systemctl restart desk-sensors.service +# sudo systemctl restart desk-sensors.service " ssh -t sgc "$cmds" diff --git a/crates/desk-sensors/src/buttons.rs b/crates/desk-sensors/src/buttons.rs index e9882d4f..376bed3f 100644 --- a/crates/desk-sensors/src/buttons.rs +++ b/crates/desk-sensors/src/buttons.rs @@ -2,7 +2,7 @@ use embedded_hal_async::digital::Wait; use protocol::{Press, Reading}; use std::sync::mpsc::Sender; use std::time::{Duration, Instant}; -use tracing::error; +use tracing::{debug, error, info, trace}; use std::thread; @@ -22,6 +22,7 @@ async fn watch_pin( const DEBOUNCE: Duration = Duration::from_millis(5); const MAX_PRESS: Duration = Duration::from_secs(5); + // pins are pulled down to ground let mut pin = match gpiocdev_embedded_hal::tokio::InputPin::new(CHIP, offset) { Ok(pin) => pin, Err(error) => { @@ -33,6 +34,8 @@ async fn watch_pin( } }; + info!("opened_pin: {offset}"); + loop { if let Err(error) = pin.wait_for_rising_edge().await { error!("error waiting for rising edge for gpio {offset} on {CHIP}: {error}"); @@ -43,6 +46,7 @@ async fn watch_pin( } let now = Instant::now(); + trace!("waiting for button to be released"); match tokio::time::timeout(MAX_PRESS, pin.wait_for_falling_edge()).await { Ok(Err(error)) => { error!("error waiting for falling edge for gpio {offset} on {CHIP}: {error}"); @@ -57,9 +61,12 @@ async fn watch_pin( let press = now.elapsed(); if press > DEBOUNCE { + debug!("sending button press (pressed for: {press:?})"); let button = (as_button)(Press(press.as_millis() as u16)); let reading = desk::Reading::Button(button); send_reading(tx, reading); + } else { + trace!("press too short, caught as bounce"); } } } @@ -81,6 +88,7 @@ pub fn start_monitoring(tx: Sender>) { thread::spawn(move || { let rt = tokio::runtime::Builder::new_current_thread() .enable_io() + .enable_time() .build() .unwrap(); rt.block_on(watch_pins(&tx)) diff --git a/crates/desk-sensors/src/main.rs b/crates/desk-sensors/src/main.rs index c33cf98a..7eabe570 100644 --- a/crates/desk-sensors/src/main.rs +++ b/crates/desk-sensors/src/main.rs @@ -4,6 +4,7 @@ use std::io::{ErrorKind, Write}; use std::net::{SocketAddr, TcpStream}; use std::sync::mpsc::{self, Sender}; use std::time::Duration; +use tracing::{debug, info}; mod buttons; mod sensors; @@ -32,6 +33,8 @@ fn main() { let mut msg: protocol::SensorMessage<20> = protocol::SensorMessage::new(); let addr = SocketAddr::from(([127, 0, 0, 1], cli.update_port)); + info!("connecting to dataserver on: {}", cli.update_port); + loop { let mut stream = match TcpStream::connect(addr) { Ok(stream) => stream, @@ -43,6 +46,7 @@ fn main() { }; loop { + msg.values.clear(); let result = rx.recv().unwrap(); msg.values.push(result).expect("capacity > 0"); while let Ok(result) = rx.try_recv() { @@ -51,8 +55,12 @@ fn main() { break; } } + debug!("Sending message: {msg:?}"); let bytes = msg.encode(); - stream.write_all(&bytes).unwrap(); + if stream.write_all(&bytes).is_err() { + std::thread::sleep(Duration::from_secs(5)); + break; // reconnect + } } } } diff --git a/crates/desk-sensors/src/sensors.rs b/crates/desk-sensors/src/sensors.rs index dbcef7ca..35f458c8 100644 --- a/crates/desk-sensors/src/sensors.rs +++ b/crates/desk-sensors/src/sensors.rs @@ -3,6 +3,7 @@ use bme280::{self, Measurements}; use hal::{Delay, I2cdev}; use linux_embedded_hal as hal; use protocol::downcast_err::ConcreteErrorType; +use tracing::debug; use std::sync::mpsc::Sender; use std::thread; @@ -36,12 +37,13 @@ pub fn start_monitoring(tx: Sender>) -> Result< thread::spawn(move || { loop { match bme.measure(&mut Delay) { - Ok(Measurements { + Ok(m @ Measurements { temperature, pressure, humidity, .. }) => { + debug!("got measurements: {m:?}"); send_reading(&tx, DeskReading::Temperature(temperature)); send_reading(&tx, DeskReading::Humidity(humidity)); send_reading(&tx, DeskReading::Pressure(pressure)); From a2b14598550c4de9c5caf6c6dd581892340fff08 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 28 May 2024 15:01:13 +0200 Subject: [PATCH 104/687] fixy warns --- crates/data-server/src/main.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/data-server/src/main.rs b/crates/data-server/src/main.rs index 070c18cb..0cd696d5 100644 --- a/crates/data-server/src/main.rs +++ b/crates/data-server/src/main.rs @@ -4,8 +4,6 @@ use std::net::SocketAddr; use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufStream}; use tokio::net::{TcpListener, TcpStream}; use tokio::sync::mpsc::{self, Sender}; -use tokio_stream::wrappers::TcpListenerStream; -use tokio_stream::StreamExt; use color_eyre::{Result, Section}; use protocol::{Reading, SensorMessage}; From b06a48723a777b3380068b867d38c8623f561344 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 28 May 2024 18:10:05 +0200 Subject: [PATCH 105/687] fixes subscribe --- Cargo.lock | 59 ++++++++++--------- crates/data-server/src/lib.rs | 14 ++++- crates/data-server/src/main.rs | 5 +- crates/desk-sensors/deploy.sh | 2 +- crates/desk-sensors/src/main.rs | 3 +- crates/sensor-tui/src/main.rs | 9 +-- crates/sensor-tui/src/tui.rs | 84 +++++++++++----------------- crates/sensor-tui/src/tui/reading.rs | 64 ++++++++++----------- crates/sensor-tui/src/tui/render.rs | 17 ++---- 9 files changed, 120 insertions(+), 137 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6f23aad6..d08c3d9a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -116,7 +116,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -207,7 +207,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -499,7 +499,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -789,7 +789,7 @@ dependencies = [ "crossterm_winapi", "libc", "mio 0.8.11", - "parking_lot 0.12.2", + "parking_lot 0.12.3", "signal-hook", "signal-hook-mio", "winapi 0.3.9", @@ -848,7 +848,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -1358,7 +1358,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -1785,9 +1785,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" dependencies = [ "bytes 1.6.0", "futures-util", @@ -1795,7 +1795,6 @@ dependencies = [ "http-body 1.0.0", "hyper 1.3.1", "pin-project-lite", - "socket2", "tokio 1.37.0", ] @@ -2408,9 +2407,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api 0.4.12", "parking_lot_core 0.9.10", @@ -2505,7 +2504,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -2583,9 +2582,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.83" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" +checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" dependencies = [ "unicode-ident", ] @@ -3142,22 +3141,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.202" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.202" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -3385,7 +3384,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ff9eaf853dec4c8802325d8b6d3dffa86cc707fd7a1a4cdbf416e13b061787a" dependencies = [ "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -3453,7 +3452,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -3469,9 +3468,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.65" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -3555,7 +3554,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -3654,7 +3653,7 @@ dependencies = [ "libc", "mio 0.8.11", "num_cpus", - "parking_lot 0.12.2", + "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", "socket2", @@ -3712,7 +3711,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -3883,7 +3882,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -4193,7 +4192,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", "wasm-bindgen-shared", ] @@ -4227,7 +4226,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4510,5 +4509,5 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] diff --git a/crates/data-server/src/lib.rs b/crates/data-server/src/lib.rs index 44f87e74..7419c48d 100644 --- a/crates/data-server/src/lib.rs +++ b/crates/data-server/src/lib.rs @@ -2,6 +2,7 @@ use std::io::{BufRead, BufReader}; use std::net::{TcpStream, ToSocketAddrs}; use protocol::{DecodeError, SensorMessage}; +use tracing::trace; pub struct Subscriber { reader: BufReader, @@ -34,8 +35,15 @@ impl Subscriber { .read_until(0, &mut self.buf) .map_err(SubscribeError::ConnFailed)?; + if n_read == 0 { + return Err(SubscribeError::ConnEnded)?; + } + + self.buf.resize(n_read, 0); // ensure stop delimiter in bytes let msg = &mut self.buf[0..n_read]; + trace!("{:?}", &msg); let msg = SensorMessage::<50>::decode(msg).map_err(SubscribeError::DecodeFailed)?; + self.buf.clear(); self.values = msg.values.to_vec().into_iter(); Ok(self @@ -47,8 +55,10 @@ impl Subscriber { #[derive(Debug, thiserror::Error)] pub enum SubscribeError { - #[error("The connection to the subscribe server failed")] + #[error("The connection to the subscribe server failed, error: {0}")] ConnFailed(std::io::Error), - #[error("The connection to the subscribe server failed")] + #[error("Could not decode message, is protocol lib up to date on server and client? Decoderror: {0:?}")] DecodeFailed(DecodeError), + #[error("Connection ended")] + ConnEnded, } diff --git a/crates/data-server/src/main.rs b/crates/data-server/src/main.rs index 0cd696d5..8e5a72d1 100644 --- a/crates/data-server/src/main.rs +++ b/crates/data-server/src/main.rs @@ -74,7 +74,7 @@ async fn spread_updates( Event::NewReading(reading) => reading, }; - let mut msg: SensorMessage<40> = SensorMessage::new(); + let mut msg: SensorMessage<50> = SensorMessage::new(); msg.values.push(reading).expect("capacity should be > 0"); while let Ok(event) = events.try_recv() { @@ -164,6 +164,9 @@ async fn main() -> Result<()> { } = Cli::parse(); assert_ne!(subscribe_port, update_port); + info!("listening for updates on port: {update_port}"); + info!("serving subscribers on port: {subscribe_port}"); + let (tx, rx) = mpsc::channel(2000); select! { e = register_subs(subscribe_port, &tx) => e, diff --git a/crates/desk-sensors/deploy.sh b/crates/desk-sensors/deploy.sh index 706e6fb0..9438f703 100755 --- a/crates/desk-sensors/deploy.sh +++ b/crates/desk-sensors/deploy.sh @@ -13,7 +13,7 @@ rsync -vh --progress \ cmds=" sudo mv /tmp/desk-sensors /home/ha/desk-sensors sudo chown ha:ha /home/ha/desk-sensors -# sudo systemctl restart desk-sensors.service +sudo systemctl restart desk-sensors.service " ssh -t sgc "$cmds" diff --git a/crates/desk-sensors/src/main.rs b/crates/desk-sensors/src/main.rs index 7eabe570..c73cff00 100644 --- a/crates/desk-sensors/src/main.rs +++ b/crates/desk-sensors/src/main.rs @@ -4,7 +4,7 @@ use std::io::{ErrorKind, Write}; use std::net::{SocketAddr, TcpStream}; use std::sync::mpsc::{self, Sender}; use std::time::Duration; -use tracing::{debug, info}; +use tracing::{debug, info, warn}; mod buttons; mod sensors; @@ -39,6 +39,7 @@ fn main() { let mut stream = match TcpStream::connect(addr) { Ok(stream) => stream, Err(err) if err.kind() == ErrorKind::ConnectionRefused => { + warn!("could not connect to data server, retrying in 5 seconds"); std::thread::sleep(Duration::from_secs(5)); continue; } diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index b3183d6c..8ce66f3f 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -22,16 +22,17 @@ fn main() -> Result<()> { let (tx, rx) = mpsc::channel(); thread::spawn(|| tui::run(rx)); - while let Ok(val) = sub.next() { - let update = match val { + loop { + let update = match sub + .next() + .wrap_err("Error getting next reading from server")? + { Ok(reading) => Update::Reading(reading), Err(error) => Update::Error(error), }; tx.send(update).unwrap(); } - - Ok(()) } fn setup_tracing() -> Result<()> { diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index 453c3835..a486e0bb 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -8,10 +8,8 @@ use ratatui::{ style::{Color, Style}, widgets::ListState, }; +use std::{collections::HashMap, io::stdout, sync::mpsc, time::Duration}; use tui_tree_widget::TreeState; -use std::{ - collections::HashMap, io::stdout, sync::mpsc, time::{Duration, Instant} -}; mod reading; use reading::Readings; @@ -33,44 +31,26 @@ impl ActiveList { } } - fn swap(self) -> Self { - match self { - Self::Readings => Self::Actuators, - Self::Actuators => Self::Readings, - } - } -} - -struct ConnInfo { - last_msg: Instant, - addr: std::net::SocketAddr, -} - -impl ConnInfo { - fn conn_status(&self) -> String { - let Self { last_msg, addr } = self; - let elapsed = last_msg.elapsed().as_secs(); - if elapsed < 2 { - format!("client: {addr}\nlast message less then 2 seconds ago") - } else { - format!("client: {addr}\nlast message {elapsed}s ago") - } - } - fn got_msg(&mut self) { - self.last_msg = Instant::now(); - } + // fn swap(self) -> Self { + // match self { + // Self::Readings => Self::Actuators, + // Self::Actuators => Self::Readings, + // } + // } } pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { - let mut readings = Readings { ground: Vec::new(), data: HashMap::new() }; - let mut conn_info = None; + let mut readings = Readings { + ground: Vec::new(), + data: HashMap::new(), + }; stdout().execute(EnterAlternateScreen)?; enable_raw_mode()?; let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; terminal.clear()?; - let mut active_list = ActiveList::Readings; + let active_list = ActiveList::Readings; let mut reading_list_state = TreeState::default(); let mut actuator_list_state = ListState::default(); let actuators = vec![ @@ -81,22 +61,16 @@ pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { let mut plot_buf = Vec::new(); loop { - let conn_status = conn_info - .as_ref() - .map(ConnInfo::conn_status) - .unwrap_or_else(|| format!("no connected client")); - - let chart = if !reading_list_state.selected().is_empty() { - readings.chart(reading_list_state.selected(), &mut plot_buf) - } else { - None - }; - - let histogram = if !reading_list_state.selected().is_empty() { - let key = reading_list_state.selected().first().unwrap(); - readings.histogram(*key) + let data = reading_list_state + .selected() + .first() + .map(|key| readings.data.get(key)) + .flatten(); + + let (chart, histogram) = if let Some(data) = data { + (data.chart(&mut plot_buf), data.histogram()) } else { - readings.histogram_all() + (None, readings.histogram_all()) }; terminal.draw(|frame| { @@ -109,12 +83,16 @@ pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { active_list, &histogram, chart, - &conn_status, ); })?; + if reading_list_state.selected().is_empty() { + reading_list_state.select_first(); + } + if event::poll(Duration::from_millis(16))? { if let event::Event::Key(key) = event::read()? { + tracing::trace!("key pressed: {key:?}"); if key.kind == KeyEventKind::Press { if key.code == KeyCode::Char('q') { break; @@ -125,10 +103,12 @@ pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { break; } if key.code == KeyCode::Left { - active_list = active_list.swap(); + reading_list_state.key_left(); + // active_list = active_list.swap(); } if key.code == KeyCode::Right { - active_list = active_list.swap(); + reading_list_state.key_right(); + // active_list = active_list.swap(); } if key.code == KeyCode::Down { reading_list_state.key_down(); @@ -136,13 +116,15 @@ pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { if key.code == KeyCode::Up { reading_list_state.key_up(); } + // if key.code == KeyCode::Enter { + // reading_list_state. + // } } } } match rx.try_recv() { Ok(Update::Reading(reading)) => { - conn_info.as_mut().unwrap().got_msg(); readings.add(reading); } Ok(Update::Error(err)) => { diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index d25fdca4..e11d9ac9 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -7,6 +7,7 @@ use std::{collections::VecDeque, time::Instant}; use tui_tree_widget::TreeItem; pub struct SensorInfo { + name: &'static str, timing: Histogram, history: VecDeque<(Instant, f32)>, condition: Result<(), Error>, @@ -22,6 +23,27 @@ impl SensorInfo { .expect("Items are put in the map when they arrive with a value"); Ok(last.0) } + + pub fn histogram(&self) -> Vec { + histogram_bars(&self.timing) + } + + pub fn chart<'a>(&self, plot_buf: &'a mut Vec<(f64, f64)>) -> Option> { + plot_buf.clear(); + + for xy in self + .history + .iter() + .map(|(x, y)| (x.elapsed().as_secs_f64(), *y as f64)) + { + plot_buf.push(xy); + } + + Some(ChartParts { + name: self.name, + data: plot_buf, + }) + } } pub type TreeKey = [u8; 6]; @@ -79,7 +101,7 @@ fn add_node<'a>( tree.child_mut(new_child).expect("just added it") } -fn extract_keyval(reading: &Reading) -> (TreeKey, f32) { +fn extract_leaf_info(reading: &Reading) -> (TreeKey, &'static str, f32) { let mut key = [0u8; 6]; key[0] = reading.id(); @@ -91,8 +113,8 @@ fn extract_keyval(reading: &Reading) -> (TreeKey, f32) { inner } TomatoItem::Leaf(val) => { - *byte = reading.id(); - return (key, val); + let name = reading.name(); + return (key, name, val); } }; } @@ -106,7 +128,7 @@ impl Readings { } fn record_data(&mut self, reading: Reading) { - let (key, val) = extract_keyval(&reading); + let (key, name, val) = extract_leaf_info(&reading); if let Some(info) = self.data.get_mut(&key) { if let Ok(last_reading) = info.last_at() { @@ -122,6 +144,7 @@ impl Readings { self.data.insert( key, SensorInfo { + name, timing: Histogram::new(4, 24).unwrap(), history, condition: Ok(()), @@ -131,7 +154,7 @@ impl Readings { } fn update_tree(&mut self, reading: &Reading) { - let (key, _) = extract_keyval(reading); + let (key, _, _) = extract_leaf_info(reading); let mut tomato = reading as &dyn Tomato; let mut tree = add_root(tomato, &mut self.ground); @@ -156,39 +179,10 @@ impl Readings { } histogram_bars(&all) } - - pub fn histogram(&self, key: TreeKey) -> Vec { - let hist = &self.data.get(&key).unwrap().timing; - histogram_bars(hist) - } - - pub fn chart<'a>( - &mut self, - selected: &[TreeKey], - plot_buf: &'a mut Vec<(f64, f64)>, - ) -> Option> { - plot_buf.clear(); - - let key = selected.first().unwrap(); - let data = &self.data.get(key).expect("data is never removed"); - - for xy in data - .history - .iter() - .map(|(x, y)| (x.elapsed().as_secs_f64(), *y as f64)) - { - plot_buf.push(xy); - } - - Some(ChartParts { - name: format!("{key:?}"), - data: plot_buf, - }) - } } pub struct ChartParts<'a> { - pub name: String, + pub name: &'static str, pub data: &'a [(f64, f64)], } diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs index 163a1213..1ae1f786 100644 --- a/crates/sensor-tui/src/tui/render.rs +++ b/crates/sensor-tui/src/tui/render.rs @@ -5,13 +5,15 @@ use ratatui::{ symbols, widgets::{ Axis, Bar, BarChart, BarGroup, Block, Borders, Chart, Dataset, GraphType, List, ListState, - Paragraph, }, Frame, }; use tui_tree_widget::{Tree, TreeItem, TreeState}; -use super::{reading::{ChartParts, TreeKey}, ActiveList}; +use super::{ + reading::{ChartParts, TreeKey}, + ActiveList, +}; pub(crate) fn all( frame: &mut Frame, @@ -22,7 +24,6 @@ pub(crate) fn all( active_list: ActiveList, histogram: &[Bar], chart: Option, - conn_status: &str, ) { let area = frame.size(); let [top, bottom] = Layout::vertical([Constraint::Min(10), Constraint::Min(10)]) @@ -37,7 +38,6 @@ pub(crate) fn all( actuators, actuator_list_state, active_list, - conn_status, ); render_lower(frame, bottom, histogram, chart); } @@ -126,18 +126,11 @@ pub(crate) fn render_top( actuators: Vec, actuator_list_state: &mut ListState, active_list: ActiveList, - conn_status: &str, ) { - let vertical: [_; 2] = Layout::vertical([Constraint::Max(2), Constraint::Min(5)]) - .flex(ratatui::layout::Flex::Legacy) - .areas(layout); - - frame.render_widget(Paragraph::new(conn_status), vertical[0]); - let horizontal: [_; 2] = Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]) .flex(ratatui::layout::Flex::Legacy) - .areas(vertical[1]); + .areas(layout); frame.render_stateful_widget( Tree::new(&readings) From 9bb4fffe5a5c8c792fe8cb0d6765788d10834442 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 29 May 2024 19:02:08 +0200 Subject: [PATCH 106/687] buttons now show their name --- Cargo.lock | 1 + crates/protocol/Cargo.toml | 1 + crates/protocol/src/large_bedroom/desk.rs | 2 +- crates/protocol/src/lib.rs | 37 ++++++++++++++++++++--- crates/sensor-tui/src/tui/reading.rs | 19 +++++++----- 5 files changed, 47 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d08c3d9a..f561b644 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2612,6 +2612,7 @@ dependencies = [ "sps30-async", "strum", "thiserror", + "tracing", ] [[package]] diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index 6d404373..c047d430 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -32,6 +32,7 @@ gpiocdev-embedded-hal = "0.1.1" gpiocdev = "0.7" nix = "0.28.0" embedded-hal = "1.0.0" +tracing = "0.1.40" [features] alloc = ["postcard/alloc", "serde/std", "sht31/thiserror", diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index b2902127..398ce417 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -35,7 +35,7 @@ impl Tomato for Reading { Reading::Temperature(val) => *val, Reading::Humidity(val) => *val, Reading::Pressure(val) => *val, - Reading::Button(val) => (*val).into(), + Reading::Button(val) => return TomatoItem::Node(val), }; TomatoItem::Leaf(val) } diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 721a7c88..c25b3e17 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -1,6 +1,6 @@ #![cfg_attr(not(feature = "alloc"), no_std)] -use core::any::type_name; +use core::fmt; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -38,6 +38,7 @@ macro_rules! button_enum { postcard::experimental::max_size::MaxSize )] $(#[$outer])* // docs + /// SAFETY: must be repr(u8) or id fn will create undefined behaviour #[repr(u8)] pub enum $name { $($variant(crate::Press),)* @@ -59,6 +60,28 @@ macro_rules! button_enum { } } } + + impl crate::Tomato for $name { + fn inner<'a>(&'a self) -> crate::TomatoItem<'a> { + crate::TomatoItem::Leaf((*self).into()) + } + fn name(&self) -> String { + let dbg_repr = format!("{:?}", self); + dbg_repr + .split_once('(') + .map(|(name, _)| name) + .unwrap_or("-") + .to_string() + } + fn id(&self) -> crate::TomatoId { + // SAFETY: Because `Self` is marked `repr(u8)`, its layout is a + // `repr(C)` `union` between `repr(C)` structs, each of which + // has the `u8` discriminant as its first field, so we can read + // the discriminant without offsetting the pointer. + let discriminant = unsafe { *<*const _>::from(self).cast::() }; + discriminant as crate::TomatoId + } + } }; } pub(crate) use button_enum; @@ -86,15 +109,21 @@ impl Press { } type TomatoId = u8; +#[derive(Debug)] pub enum TomatoItem<'a> { Leaf(f32), Node(&'a dyn Tomato), } -pub trait Tomato { +pub trait Tomato: fmt::Debug { fn inner<'a>(&'a self) -> TomatoItem<'a>; - fn name(&self) -> &'static str { - type_name::() + fn name(&self) -> String { + let dbg_repr = format!("{:?}", self); + dbg_repr + .split_once('(') + .map(|(name, _)| name) + .unwrap_or("-") + .to_string() } fn id(&self) -> TomatoId; } diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index e11d9ac9..2370aece 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -7,7 +7,7 @@ use std::{collections::VecDeque, time::Instant}; use tui_tree_widget::TreeItem; pub struct SensorInfo { - name: &'static str, + name: String, timing: Histogram, history: VecDeque<(Instant, f32)>, condition: Result<(), Error>, @@ -40,7 +40,7 @@ impl SensorInfo { } Some(ChartParts { - name: self.name, + name: self.name.clone(), data: plot_buf, }) } @@ -53,7 +53,7 @@ pub struct Readings { pub data: HashMap, } -fn add_leaf(name: &'static str, val: f32, tree: &mut TreeItem<'static, TreeKey>, key: TreeKey) { +fn add_leaf(name: String, val: f32, tree: &mut TreeItem<'static, TreeKey>, key: TreeKey) { let text = format!("{}: {}", name, val); let new_item = TreeItem::new_leaf(key, text.clone()); // todo is exists its fine handle that @@ -101,7 +101,7 @@ fn add_node<'a>( tree.child_mut(new_child).expect("just added it") } -fn extract_leaf_info(reading: &Reading) -> (TreeKey, &'static str, f32) { +fn extract_leaf_info(reading: &Reading) -> (TreeKey, String, f32) { let mut key = [0u8; 6]; key[0] = reading.id(); @@ -156,8 +156,11 @@ impl Readings { fn update_tree(&mut self, reading: &Reading) { let (key, _, _) = extract_leaf_info(reading); - let mut tomato = reading as &dyn Tomato; - let mut tree = add_root(tomato, &mut self.ground); + let mut tree = add_root(reading as &dyn Tomato, &mut self.ground); + let mut tomato = match reading.inner() { + TomatoItem::Leaf(_) => unreachable!("no values at level 0"), + TomatoItem::Node(inner) => inner, + }; loop { match tomato.inner() { TomatoItem::Leaf(val) => { @@ -165,8 +168,8 @@ impl Readings { return; } TomatoItem::Node(inner) => { - tomato = inner; tree = add_node(tomato, tree); + tomato = inner; } }; } @@ -182,7 +185,7 @@ impl Readings { } pub struct ChartParts<'a> { - pub name: &'static str, + pub name: String, pub data: &'a [(f64, f64)], } From 5de6b2167f2babc0402daec02e6596b3c0c32e29 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 29 May 2024 22:51:08 +0200 Subject: [PATCH 107/687] add state to large_room and handle some buttons --- Cargo.lock | 341 ++---------------- crates/brain/.cargo/config.toml | 2 + crates/brain/Cargo.toml | 9 +- deploy.sh => crates/brain/deploy.sh | 10 +- crates/brain/rust-toolchain.toml | 5 + .../src/controller/rooms/large_bedroom.rs | 46 ++- crates/brain/src/errors.rs | 4 - crates/brain/src/input/api.rs | 26 +- crates/brain/src/input/jobs.rs | 12 +- crates/brain/src/input/mod.rs | 1 + crates/brain/src/input/sensors.rs | 40 ++ crates/brain/src/main.rs | 11 +- crates/data-server/src/lib.rs | 55 ++- crates/desk-sensors/.cargo/config.toml | 2 +- deploy_optimized.sh | 3 - 15 files changed, 184 insertions(+), 383 deletions(-) create mode 100644 crates/brain/.cargo/config.toml rename deploy.sh => crates/brain/deploy.sh (55%) create mode 100644 crates/brain/rust-toolchain.toml create mode 100644 crates/brain/src/input/sensors.rs delete mode 100755 deploy_optimized.sh diff --git a/Cargo.lock b/Cargo.lock index f561b644..eb87bac2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -243,12 +243,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "bincode" version = "1.3.3" @@ -338,7 +332,7 @@ dependencies = [ "bytes 1.6.0", "chrono", "clap", - "crossbeam-channel", + "data-server", "futures 0.3.30", "futures-concurrency", "futures-util", @@ -347,7 +341,6 @@ dependencies = [ "philipshue", "protocol", "rand 0.8.5", - "reqwest 0.11.27", "serde", "serde_yaml", "sled", @@ -629,16 +622,6 @@ dependencies = [ "url 1.7.2", ] -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.6" @@ -707,15 +690,6 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" -[[package]] -name = "crossbeam-channel" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" -dependencies = [ - "crossbeam-utils 0.8.20", -] - [[package]] name = "crossbeam-deque" version = "0.7.4" @@ -810,7 +784,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d3686f5fa27dbc1d76c751300376e167c5a43387f44bb451fd1c24776e49113" dependencies = [ - "sct 0.6.1", + "sct", ] [[package]] @@ -1483,25 +1457,6 @@ dependencies = [ "tokio-io", ] -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes 1.6.0", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.2.6", - "slab", - "tokio 1.37.0", - "tokio-util", - "tracing", -] - [[package]] name = "hash32" version = "0.2.1" @@ -1599,17 +1554,6 @@ dependencies = [ "itoa 0.4.8", ] -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes 1.6.0", - "fnv", - "itoa 1.0.11", -] - [[package]] name = "http" version = "1.1.0" @@ -1633,17 +1577,6 @@ dependencies = [ "tokio-buf", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes 1.6.0", - "http 0.2.12", - "pin-project-lite", -] - [[package]] name = "http-body" version = "1.0.0" @@ -1688,7 +1621,7 @@ dependencies = [ "bytes 0.4.12", "futures 0.1.31", "futures-cpupool", - "h2 0.1.26", + "h2", "http 0.1.21", "http-body 0.1.0", "httparse", @@ -1706,31 +1639,7 @@ dependencies = [ "tokio-tcp", "tokio-threadpool", "tokio-timer", - "want 0.2.0", -] - -[[package]] -name = "hyper" -version = "0.14.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" -dependencies = [ - "bytes 1.6.0", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa 1.0.11", - "pin-project-lite", - "socket2", - "tokio 1.37.0", - "tower-service", - "tracing", - "want 0.3.1", + "want", ] [[package]] @@ -1762,25 +1671,11 @@ dependencies = [ "ct-logs", "futures 0.1.31", "hyper 0.12.36", - "rustls 0.16.0", + "rustls", "tokio-io", - "tokio-rustls 0.10.3", + "tokio-rustls", "webpki", - "webpki-roots 0.17.0", -] - -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http 0.2.12", - "hyper 0.14.28", - "rustls 0.21.12", - "tokio 1.37.0", - "tokio-rustls 0.24.1", + "webpki-roots", ] [[package]] @@ -1925,12 +1820,6 @@ dependencies = [ "libc", ] -[[package]] -name = "ipnet" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" - [[package]] name = "is_terminal_polyfill" version = "1.70.0" @@ -2481,7 +2370,7 @@ version = "0.3.2" source = "git+https://github.com/dvdsk/philipshue?branch=master#c52c7fa306a78c3432f5619bb4de75ccd55fb19f" dependencies = [ "error-chain", - "reqwest 0.9.24", + "reqwest", "serde", "serde_derive", "serde_json", @@ -2890,7 +2779,7 @@ version = "0.9.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab" dependencies = [ - "base64 0.10.1", + "base64", "bytes 0.4.12", "cookie", "cookie_store", @@ -2899,11 +2788,11 @@ dependencies = [ "futures 0.1.31", "http 0.1.21", "hyper 0.12.36", - "hyper-rustls 0.17.1", + "hyper-rustls", "log", "mime", "mime_guess", - "rustls 0.16.0", + "rustls", "serde", "serde_json", "serde_urlencoded 0.5.5", @@ -2911,54 +2800,13 @@ dependencies = [ "tokio 0.1.22", "tokio-executor", "tokio-io", - "tokio-rustls 0.10.3", + "tokio-rustls", "tokio-threadpool", "tokio-timer", "url 1.7.2", "uuid", - "webpki-roots 0.17.0", - "winreg 0.6.2", -] - -[[package]] -name = "reqwest" -version = "0.11.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" -dependencies = [ - "base64 0.21.7", - "bytes 1.6.0", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.28", - "hyper-rustls 0.24.2", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding 2.3.1", - "pin-project-lite", - "rustls 0.21.12", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded 0.7.1", - "sync_wrapper 0.1.2", - "system-configuration", - "tokio 1.37.0", - "tokio-rustls 0.24.1", - "tower-service", - "url 2.5.0", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots 0.25.4", - "winreg 0.50.0", + "webpki-roots", + "winreg", ] [[package]] @@ -2971,26 +2819,11 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted 0.7.1", + "untrusted", "web-sys", "winapi 0.3.9", ] -[[package]] -name = "ring" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" -dependencies = [ - "cc", - "cfg-if 1.0.0", - "getrandom", - "libc", - "spin 0.9.8", - "untrusted 0.9.0", - "windows-sys 0.52.0", -] - [[package]] name = "rustc-demangle" version = "0.1.24" @@ -3021,44 +2854,13 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" dependencies = [ - "base64 0.10.1", + "base64", "log", - "ring 0.16.20", - "sct 0.6.1", + "ring", + "sct", "webpki", ] -[[package]] -name = "rustls" -version = "0.21.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" -dependencies = [ - "log", - "ring 0.17.8", - "rustls-webpki", - "sct 0.7.1", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", -] - [[package]] name = "rustversion" version = "1.0.17" @@ -3083,18 +2885,8 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] - -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -3511,27 +3303,6 @@ dependencies = [ "nix 0.23.2", ] -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "tap" version = "1.0.1" @@ -3743,21 +3514,11 @@ dependencies = [ "bytes 0.4.12", "futures 0.1.31", "iovec", - "rustls 0.16.0", + "rustls", "tokio-io", "webpki", ] -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.12", - "tokio 1.37.0", -] - [[package]] name = "tokio-stream" version = "0.1.15" @@ -3822,19 +3583,6 @@ dependencies = [ "tokio-executor", ] -[[package]] -name = "tokio-util" -version = "0.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" -dependencies = [ - "bytes 1.6.0", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio 1.37.0", -] - [[package]] name = "tower" version = "0.4.13" @@ -4058,12 +3806,6 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - [[package]] name = "url" version = "1.7.2" @@ -4151,15 +3893,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" @@ -4197,18 +3930,6 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" version = "0.2.92" @@ -4254,8 +3975,8 @@ version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", + "ring", + "untrusted", ] [[package]] @@ -4267,12 +3988,6 @@ dependencies = [ "webpki", ] -[[package]] -name = "webpki-roots" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" - [[package]] name = "winapi" version = "0.2.8" @@ -4464,16 +4179,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if 1.0.0", - "windows-sys 0.48.0", -] - [[package]] name = "ws2_32-sys" version = "0.2.1" diff --git a/crates/brain/.cargo/config.toml b/crates/brain/.cargo/config.toml new file mode 100644 index 00000000..1002fed4 --- /dev/null +++ b/crates/brain/.cargo/config.toml @@ -0,0 +1,2 @@ +[target.aarch64-unknown-linux-musl] +rustflags = ["-Clinker=rust-lld"] diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 0a441867..1fed70fe 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -8,6 +8,7 @@ authors.workspace = true [dependencies] protocol = { path = "../protocol" } +data-server = { path = "../data-server" } futures = "0.3" tokio = { version = "1", features = ["full"] } @@ -23,13 +24,13 @@ bincode = "1.3" thiserror = "1.0" chrono = { version = "0.4", features = ["serde"] } +time = { version = "0.3.36", features = ["macros"] } +tz-rs = "0.6.14" + bytes = "1.5" byteorder = "1.4" -crossbeam-channel = "0.5" - sled = "0.34" -reqwest = {version = "0.11", default-features = false, features = ["rustls-tls"]} mpd = "0.1" rand = "0.8" @@ -41,6 +42,4 @@ tracing-journald = "0.3.0" log-panics = "2.1.0" clap = { version = "4.5.4", features = ["derive"] } futures-concurrency = "7.5.0" -time = { version = "0.3.36", features = ["macros"] } strum = { version = "0.26.2", default-features = false, features = ["derive"] } -tz-rs = "0.6.14" diff --git a/deploy.sh b/crates/brain/deploy.sh similarity index 55% rename from deploy.sh rename to crates/brain/deploy.sh index 0fa740be..09425ed9 100755 --- a/deploy.sh +++ b/crates/brain/deploy.sh @@ -1,17 +1,11 @@ #!/usr/bin/env bash set -e -BUILD_ARG=$1 -DIR=debug; -if [[ "$BUILD_ARG" == "--release" ]]; then - DIR=release -fi - SERVER="sgc" # ssh config name or full address -cross build --target=aarch64-unknown-linux-gnu $BUILD_ARG +cargo build --target=aarch64-unknown-linux-musl --release rsync -vh --progress \ - target/aarch64-unknown-linux-gnu/$DIR/brain \ + target/aarch64-unknown-linux-gnu/release/brain \ $SERVER:/tmp/ cmds=" diff --git a/crates/brain/rust-toolchain.toml b/crates/brain/rust-toolchain.toml new file mode 100644 index 00000000..6e888d40 --- /dev/null +++ b/crates/brain/rust-toolchain.toml @@ -0,0 +1,5 @@ +[toolchain] +channel = "stable" +components = [] +targets = [ "aarch64-unknown-linux-musl" ] +profile = "minimal" diff --git a/crates/brain/src/controller/rooms/large_bedroom.rs b/crates/brain/src/controller/rooms/large_bedroom.rs index fbcd45bd..ef01ec57 100644 --- a/crates/brain/src/controller/rooms/large_bedroom.rs +++ b/crates/brain/src/controller/rooms/large_bedroom.rs @@ -7,10 +7,12 @@ use tokio::time::{sleep_until, Instant}; use crate::controller::{local_now, Event, RestrictedSystem}; +#[derive(Debug, Clone, PartialEq, Eq)] enum State { // Sleep, // Wakeup, Normal, + Bright, // Away, } @@ -70,26 +72,40 @@ pub async fn run( ShouldUpdate, } - let _state = State::Normal; + let mut state = State::Normal; let mut next_update = Instant::now() + INTERVAL; loop { let get_event = event_rx.recv_filter_mapped(filter).map(Res::Event); let tick = sleep_until(next_update).map(|_| Res::ShouldUpdate); let res = (get_event, tick).race().await; - match res { + let new_state = match res { Res::Event(e) => handle_event(e), Res::ShouldUpdate => { - update(&mut system).await; + update(&mut system, &state).await; next_update = Instant::now() + INTERVAL; + None } + }; + + if let Some(new) = new_state { + state = new; + update(&mut system, &state).await; + next_update = Instant::now() + INTERVAL; } } } -async fn update(system: &mut RestrictedSystem) { - let (new_ct, new_bri) = optimal_ct_bri(); - system.all_lamps_ct(new_ct, new_bri).await; +async fn update(system: &mut RestrictedSystem, state: &State) { + match state { + State::Normal => { + let (new_ct, new_bri) = optimal_ct_bri(); + system.all_lamps_ct(new_ct, new_bri).await; + } + State::Bright => { + system.all_lamps_ct(254, u8::MAX).await; + } + } } fn optimal_ct_bri() -> (u16, u8) { @@ -102,12 +118,12 @@ fn optimal_ct_bri() -> (u16, u8) { } } -fn handle_event(e: RelevantEvent) { +fn handle_event(e: RelevantEvent) -> Option { // use protocol::large_bedroom::DeskButton; // use RelevantEvent as R; match e { - RelevantEvent::WakeUp => (), + RelevantEvent::WakeUp => None, // RelevantEvent::WeightLeft(_) => (), // RelevantEvent::WeightRight(_) => (), // RelevantEvent::Brightness(_) => (), @@ -116,6 +132,18 @@ fn handle_event(e: RelevantEvent) { } } -fn handle_button(b: protocol::large_bedroom::desk::Button) { +fn handle_button(b: protocol::large_bedroom::desk::Button) -> Option { + use protocol::large_bedroom::desk::Button; + println!("button pressed: {b:?}"); + match b { + Button::OneOfFour(press) if press.is_long() => Some(State::Bright), + Button::FourOfFour(press) if !press.is_long() => Some(State::Normal), + // Button::TwoOfFour(_) => todo!(), + // Button::ThreeOfFour(_) => todo!(), + // Button::OneOfThree(_) => todo!(), + // Button::TwoOfThree(_) => todo!(), + // Button::ThreeOfThree(_) => todo!(), + _ => None, + } } diff --git a/crates/brain/src/errors.rs b/crates/brain/src/errors.rs index 07d2aff3..6f432c3e 100644 --- a/crates/brain/src/errors.rs +++ b/crates/brain/src/errors.rs @@ -4,12 +4,8 @@ pub enum Error { IO(#[from] std::io::Error), #[error("Could not parse yaml")] YamlParsing(#[from] serde_yaml::Error), - #[error("Channel send error")] - Channel(#[from] crossbeam_channel::SendError<()>), #[error("Database error")] DataBase(#[from] sled::Error), - #[error("Could not download youtube")] - Download(#[from] reqwest::Error), #[error("Error while adjusting lighting: {0}")] Lamps(#[from] crate::system::lamps::Error), #[error("Error contacting mpd")] diff --git a/crates/brain/src/input/api.rs b/crates/brain/src/input/api.rs index 693f7219..42d35e29 100644 --- a/crates/brain/src/input/api.rs +++ b/crates/brain/src/input/api.rs @@ -1,12 +1,8 @@ use axum::body::Bytes; use axum::extract::State as aState; use axum::http::StatusCode; -use axum::routing::{get, post}; +use axum::routing::get; use axum::Router; -use tokio::sync::broadcast; -use tracing::warn; - -use crate::controller::Event; use super::jobs::WakeUp; @@ -60,37 +56,19 @@ async fn set_tomorrow(aState(state): aState, body: Bytes) -> StatusCode { StatusCode::OK } -async fn sensor_event(aState(state): aState, body: Bytes) { - let mut bytes = body[..].to_vec(); - let msg: protocol::SensorMessage<20> = match protocol::SensorMessage::decode(&mut bytes) { - Ok(msg) => msg, - Err(e) => { - warn!("Failed to decode received body: {e:?}"); - return; - } - }; - // in future convert from older protocol here - for value in msg.values.into_iter().filter_map(Result::ok) { - state.event_tx.send(Event::Sensor(value)).unwrap(); - } -} - #[derive(Clone)] pub struct State { wakeup: WakeUp, - event_tx: broadcast::Sender, } pub async fn setup( wakeup: WakeUp, - event_tx: broadcast::Sender, port: u16, ) -> Result<(), Error> { let app = Router::new() .route("/alarm/usually", get(usually).post(set_usually)) .route("/alarm/tomorrow", get(tomorrow).post(set_tomorrow)) - .route("/event", post(sensor_event)) - .with_state(State { wakeup, event_tx }); + .with_state(State { wakeup }); // https is done at the loadbalancer let listener = tokio::net::TcpListener::bind(format!("127.0.0.1:{port}")) diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index afe0952b..58f5764d 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -1,5 +1,5 @@ -use crossbeam_channel; use std::ops::Sub; +use std::sync::mpsc; use std::thread; use tokio::sync::broadcast; use tracing::error; @@ -20,7 +20,7 @@ pub enum Error { #[error("Could store/edit job on disk")] DbError(#[from] sled::Error), #[error("Could not inform waker about new job")] - CommError(#[from] crossbeam_channel::SendError<()>), + CommError(#[from] mpsc::SendError<()>), } #[derive(Serialize, Deserialize, Debug)] @@ -63,7 +63,7 @@ impl Sub> for &Job { #[derive(Debug, Clone)] pub struct Jobs { - waker_tx: crossbeam_channel::Sender<()>, + waker_tx: mpsc::Sender<()>, list: JobList, } @@ -72,11 +72,11 @@ struct JobList { db: sled::Tree, } -use crossbeam_channel::RecvTimeoutError::*; +use mpsc::RecvTimeoutError::*; fn waker( mut alarm_list: JobList, event_tx: broadcast::Sender, - waker_rx: crossbeam_channel::Receiver<()>, + waker_rx: mpsc::Receiver<()>, ) { loop { //This can fail #TODO make sure an non waking error alarm is send to the user @@ -131,7 +131,7 @@ impl Jobs { db: db.open_tree("alarms")?, }; - let (waker_tx, waker_rx) = crossbeam_channel::unbounded(); + let (waker_tx, waker_rx) = mpsc::channel(); let waker_db_copy = list.clone(); let waker_thread = thread::spawn(move || waker(waker_db_copy, event_tx, waker_rx)); diff --git a/crates/brain/src/input/mod.rs b/crates/brain/src/input/mod.rs index e2b5e971..cdc636d1 100644 --- a/crates/brain/src/input/mod.rs +++ b/crates/brain/src/input/mod.rs @@ -1,4 +1,5 @@ pub mod jobs; pub mod api; +pub mod sensors; // pub mod mpd_status; // pub use mpd_status::MpdStatus; diff --git a/crates/brain/src/input/sensors.rs b/crates/brain/src/input/sensors.rs new file mode 100644 index 00000000..23c88933 --- /dev/null +++ b/crates/brain/src/input/sensors.rs @@ -0,0 +1,40 @@ +use std::net::SocketAddr; + +use data_server::{AsyncSubscriber, SubscribeError}; +use std::time::Duration; +use tokio::sync::broadcast; +use tracing::{error, warn}; + +use crate::controller::Event; + +pub async fn subscribe(event_tx: broadcast::Sender, subscribe_port: u16) { + loop { + let mut sub = loop { + let addr = SocketAddr::from(([127, 0, 0, 1], subscribe_port)); + match AsyncSubscriber::connect(addr).await { + Ok(sub) => break sub, + Err(SubscribeError::DecodeFailed(e)) => { + error!("Decode failed: {e:?}. is protocol lib up to date? Exiting"); + return; + } + Err(other) => { + warn!("Error subscribing to sensor readings: {other}, retrying..."); + } + } + tokio::time::sleep(Duration::from_secs(5)).await; + }; + + loop { + match sub.next().await { + Ok(Ok(reading)) => event_tx.send(Event::Sensor(reading)).unwrap(), + Ok(Err(_)) => continue, + Err(e) => { + warn!("Error while subscribed to sensor readings: {e}, retrying..."); + break; + } + }; + } + + tokio::time::sleep(Duration::from_secs(5)).await; + } +} diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index 1c4c1586..2f9d67b2 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -15,9 +15,9 @@ mod input; #[derive(Parser)] #[command(version, about, long_about=None)] struct Opt { - /// secret url part on which sensor data is received + /// port where to subscribe for updates #[clap(short, long)] - key: String, + subscribe_port: u16, /// ip address for mpd server #[clap(short, long)] @@ -52,7 +52,12 @@ async fn main() -> Result<(), Box> { let system = system::System::init(jobs); let _tasks = controller::start(subscribed_rxs, event_tx.clone(), system); - input::api::setup(wakeup.clone(), event_tx, opt.port).await?; + + tokio::task::spawn(input::sensors::subscribe( + event_tx, + opt.subscribe_port, + )); + input::api::setup(wakeup.clone(), opt.port).await?; unreachable!(); } diff --git a/crates/data-server/src/lib.rs b/crates/data-server/src/lib.rs index 7419c48d..6379afd4 100644 --- a/crates/data-server/src/lib.rs +++ b/crates/data-server/src/lib.rs @@ -2,6 +2,7 @@ use std::io::{BufRead, BufReader}; use std::net::{TcpStream, ToSocketAddrs}; use protocol::{DecodeError, SensorMessage}; +use tokio::io::AsyncBufReadExt; use tracing::trace; pub struct Subscriber { @@ -13,8 +14,8 @@ pub struct Subscriber { type Msg = Result; impl Subscriber { - pub fn connect(addr: impl ToSocketAddrs) -> Result { - let conn = TcpStream::connect(addr)?; + pub fn connect(addr: impl ToSocketAddrs) -> Result { + let conn = TcpStream::connect(addr).map_err(SubscribeError::ConnFailed)?; let reader = BufReader::new(conn); let buf = Vec::new(); @@ -53,6 +54,56 @@ impl Subscriber { } } +pub struct AsyncSubscriber { + reader: tokio::io::BufReader, + buf: Vec, + values: std::vec::IntoIter, +} + +impl AsyncSubscriber { + pub async fn connect(addr: impl tokio::net::ToSocketAddrs) -> Result { + let conn = tokio::net::TcpStream::connect(addr) + .await + .map_err(SubscribeError::ConnFailed)?; + let reader = tokio::io::BufReader::new(conn); + let buf = Vec::new(); + + Ok(Self { + reader, + buf, + values: vec![].into_iter(), + }) + } + + pub async fn next(&mut self) -> Result { + if let Some(val) = self.values.next() { + return Ok(val); + } + + let n_read = self + .reader + .read_until(0, &mut self.buf) + .await + .map_err(SubscribeError::ConnFailed)?; + + if n_read == 0 { + return Err(SubscribeError::ConnEnded)?; + } + + self.buf.resize(n_read, 0); // ensure stop delimiter in bytes + let msg = &mut self.buf[0..n_read]; + trace!("{:?}", &msg); + let msg = SensorMessage::<50>::decode(msg).map_err(SubscribeError::DecodeFailed)?; + self.buf.clear(); + + self.values = msg.values.to_vec().into_iter(); + Ok(self + .values + .next() + .expect("min values in sensormessage is one")) + } +} + #[derive(Debug, thiserror::Error)] pub enum SubscribeError { #[error("The connection to the subscribe server failed, error: {0}")] diff --git a/crates/desk-sensors/.cargo/config.toml b/crates/desk-sensors/.cargo/config.toml index 4c770202..1002fed4 100644 --- a/crates/desk-sensors/.cargo/config.toml +++ b/crates/desk-sensors/.cargo/config.toml @@ -1,2 +1,2 @@ -[build] +[target.aarch64-unknown-linux-musl] rustflags = ["-Clinker=rust-lld"] diff --git a/deploy_optimized.sh b/deploy_optimized.sh deleted file mode 100755 index 2dbdbf45..00000000 --- a/deploy_optimized.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -source deploy.sh "--release" From 8c1275fc55aa400a9c15bd6025a9a0767519dc05 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 29 May 2024 22:57:20 +0200 Subject: [PATCH 108/687] cleaned up unsused dependencies --- Cargo.lock | 31 +------------------------------ crates/brain/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eb87bac2..2406ef50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -166,15 +166,11 @@ dependencies = [ "pin-project-lite", "rustversion", "serde", - "serde_json", - "serde_path_to_error", - "serde_urlencoded 0.7.1", "sync_wrapper 1.0.1", "tokio 1.37.0", "tower", "tower-layer", "tower-service", - "tracing", ] [[package]] @@ -195,7 +191,6 @@ dependencies = [ "sync_wrapper 0.1.2", "tower-layer", "tower-service", - "tracing", ] [[package]] @@ -2795,7 +2790,7 @@ dependencies = [ "rustls", "serde", "serde_json", - "serde_urlencoded 0.5.5", + "serde_urlencoded", "time 0.1.45", "tokio 0.1.22", "tokio-executor", @@ -2963,16 +2958,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_path_to_error" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" -dependencies = [ - "itoa 1.0.11", - "serde", -] - [[package]] name = "serde_urlencoded" version = "0.5.5" @@ -2985,18 +2970,6 @@ dependencies = [ "url 1.7.2", ] -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa 1.0.11", - "ryu", - "serde", -] - [[package]] name = "serde_yaml" version = "0.9.34+deprecated" @@ -3596,7 +3569,6 @@ dependencies = [ "tokio 1.37.0", "tower-layer", "tower-service", - "tracing", ] [[package]] @@ -3617,7 +3589,6 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "log", "pin-project-lite", "tracing-attributes", "tracing-core", diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 1fed70fe..1f8b5d58 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -12,7 +12,7 @@ data-server = { path = "../data-server" } futures = "0.3" tokio = { version = "1", features = ["full"] } -axum = "0.7.4" +axum = { version = "0.7.4", default-features = false, features = ["tokio", "http1"] } axum-macros = "0.4.1" philipshue = { git = "https://github.com/dvdsk/philipshue", branch = "master" } From bd4887f565d78cc7ceaa0eecfdd0dc4606316d59 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 29 May 2024 22:57:50 +0200 Subject: [PATCH 109/687] switched back to cross due to TLS needed for hue lib --- crates/brain/deploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/brain/deploy.sh b/crates/brain/deploy.sh index 09425ed9..2e40ed53 100755 --- a/crates/brain/deploy.sh +++ b/crates/brain/deploy.sh @@ -3,7 +3,7 @@ set -e SERVER="sgc" # ssh config name or full address -cargo build --target=aarch64-unknown-linux-musl --release +cross build --target=aarch64-unknown-linux-musl --release rsync -vh --progress \ target/aarch64-unknown-linux-gnu/release/brain \ $SERVER:/tmp/ From 02f2b623246ef4c1e9311124baddae90112fc8b6 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 30 May 2024 13:45:51 +0200 Subject: [PATCH 110/687] remove bridge discovery enabling us to drop last C dependency easing crosscompile --- Cargo.lock | 1211 +++-------------- crates/brain/Cargo.toml | 2 +- crates/brain/deploy.sh | 4 +- crates/brain/src/main.rs | 11 +- crates/brain/src/system.rs | 4 +- .../brain/src/system/lamps/bridge_connect.rs | 27 +- .../lamps/eventually_consistent_bridge.rs | 4 +- crates/brain/src/system/lamps/mod.rs | 11 +- 8 files changed, 181 insertions(+), 1093 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2406ef50..6536a076 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", "version_check", "zerocopy", @@ -128,15 +128,6 @@ dependencies = [ "critical-section", ] -[[package]] -name = "autocfg" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" -dependencies = [ - "autocfg 1.3.0", -] - [[package]] name = "autocfg" version = "1.3.0" @@ -151,23 +142,23 @@ checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", "axum-core", - "bytes 1.6.0", + "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "http", + "http-body", "http-body-util", - "hyper 1.3.1", + "hyper", "hyper-util", - "itoa 1.0.11", + "itoa", "matchit", "memchr", "mime", - "percent-encoding 2.3.1", + "percent-encoding", "pin-project-lite", "rustversion", "serde", "sync_wrapper 1.0.1", - "tokio 1.37.0", + "tokio", "tower", "tower-layer", "tower-service", @@ -180,10 +171,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" dependencies = [ "async-trait", - "bytes 1.6.0", + "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "http", + "http-body", "http-body-util", "mime", "pin-project-lite", @@ -213,7 +204,7 @@ checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object", @@ -231,12 +222,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.10.1" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -dependencies = [ - "byteorder", -] +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bincode" @@ -324,25 +312,25 @@ dependencies = [ "axum-macros", "bincode", "byteorder", - "bytes 1.6.0", + "bytes", "chrono", "clap", "data-server", - "futures 0.3.30", + "futures", "futures-concurrency", "futures-util", "log-panics", "mpd", "philipshue", "protocol", - "rand 0.8.5", + "rand", "serde", "serde_yaml", "sled", "strum", "thiserror", - "time 0.3.36", - "tokio 1.37.0", + "time", + "tokio", "tracing", "tracing-journald", "tracing-subscriber", @@ -379,17 +367,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" -[[package]] -name = "bytes" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -dependencies = [ - "byteorder", - "either", - "iovec", -] - [[package]] name = "bytes" version = "1.6.0" @@ -423,12 +400,6 @@ version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -496,15 +467,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "cobs" version = "0.2.3" @@ -551,8 +513,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" dependencies = [ "castaway", - "cfg-if 1.0.0", - "itoa 1.0.11", + "cfg-if", + "itoa", "ryu", "static_assertions", ] @@ -589,34 +551,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" -[[package]] -name = "cookie" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" -dependencies = [ - "time 0.1.45", - "url 1.7.2", -] - -[[package]] -name = "cookie_store" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" -dependencies = [ - "cookie", - "failure", - "idna 0.1.5", - "log", - "publicsuffix", - "serde", - "serde_json", - "time 0.1.45", - "try_from", - "url 1.7.2", -] - [[package]] name = "core-foundation-sys" version = "0.8.6" @@ -676,7 +610,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -685,61 +619,13 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" -[[package]] -name = "crossbeam-deque" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20ff29ded3204c5106278a81a38f4b482636ed4fa1e6cfbeef193291beb29ed" -dependencies = [ - "crossbeam-epoch 0.8.2", - "crossbeam-utils 0.7.2", - "maybe-uninit", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" -dependencies = [ - "autocfg 1.3.0", - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "lazy_static", - "maybe-uninit", - "memoffset 0.5.6", - "scopeguard", -] - [[package]] name = "crossbeam-epoch" version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "crossbeam-utils 0.8.20", -] - -[[package]] -name = "crossbeam-queue" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" -dependencies = [ - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "maybe-uninit", -] - -[[package]] -name = "crossbeam-utils" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" -dependencies = [ - "autocfg 1.3.0", - "cfg-if 0.1.10", - "lazy_static", + "crossbeam-utils", ] [[package]] @@ -757,11 +643,11 @@ dependencies = [ "bitflags 2.5.0", "crossterm_winapi", "libc", - "mio 0.8.11", + "mio", "parking_lot 0.12.3", "signal-hook", "signal-hook-mio", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -770,16 +656,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "ct-logs" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d3686f5fa27dbc1d76c751300376e167c5a43387f44bb451fd1c24776e49113" -dependencies = [ - "sct", + "winapi", ] [[package]] @@ -790,7 +667,7 @@ dependencies = [ "color-eyre", "protocol", "thiserror", - "tokio 1.37.0", + "tokio", "tokio-stream", "tracing", "tracing-error", @@ -862,7 +739,7 @@ dependencies = [ "gpiocdev-embedded-hal", "linux-embedded-hal", "protocol", - "tokio 1.37.0", + "tokio", "tracing", "tracing-error", "tracing-subscriber", @@ -877,12 +754,6 @@ dependencies = [ "litrs", ] -[[package]] -name = "dtoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" - [[package]] name = "either" version = "1.12.0" @@ -937,7 +808,7 @@ checksum = "32bc0257b5ade13a1b93e8b9949268f44d57e8ce03e599ef1c5a62024a0fbff9" dependencies = [ "bit_field", "bxcan", - "cfg-if 1.0.0", + "cfg-if", "cortex-m", "cortex-m-rt", "critical-section", @@ -956,11 +827,11 @@ dependencies = [ "embedded-io-async", "embedded-storage", "embedded-storage-async", - "futures 0.3.30", + "futures", "nb 1.1.0", "proc-macro2", "quote", - "rand_core 0.6.4", + "rand_core", "sdio-host", "stm32-fmc", "stm32-metapac", @@ -973,7 +844,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd938f25c0798db4280fcd8026bf4c2f48789aebf8f77b6e5cf8a7693ba114ec" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "critical-section", "embedded-io-async", "futures-util", @@ -986,7 +857,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9c844070d9f80dc66ee739299183312baee2e1cdeb6e90b4ea2af44f4676da5" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "critical-section", "document-features", "embassy-time-driver", @@ -1098,15 +969,6 @@ dependencies = [ "embedded-storage", ] -[[package]] -name = "encoding_rs" -version = "0.8.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" -dependencies = [ - "cfg-if 1.0.0", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -1132,28 +994,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "failure" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" -dependencies = [ - "backtrace", - "failure_derive", -] - -[[package]] -name = "failure_derive" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure", -] - [[package]] name = "fastrand" version = "1.9.0" @@ -1163,16 +1003,6 @@ dependencies = [ "instant", ] -[[package]] -name = "flate2" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - [[package]] name = "fnv" version = "1.0.7" @@ -1185,7 +1015,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ - "percent-encoding 2.3.1", + "percent-encoding", ] [[package]] @@ -1195,43 +1025,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" dependencies = [ "libc", - "winapi 0.3.9", -] - -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags 1.3.2", - "fuchsia-zircon-sys", + "winapi", ] -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - [[package]] name = "funty" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" -[[package]] -name = "futures" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" - [[package]] name = "futures" version = "0.3.30" @@ -1268,7 +1070,7 @@ dependencies = [ "futures-lite", "pin-project", "slab", - "smallvec 1.13.2", + "smallvec", ] [[package]] @@ -1277,16 +1079,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" -[[package]] -name = "futures-cpupool" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -dependencies = [ - "futures 0.1.31", - "num_cpus", -] - [[package]] name = "futures-executor" version = "0.3.30" @@ -1375,9 +1167,9 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -1403,10 +1195,10 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5119c89eccee09c4f6e9ca2b112aea1cd80bac31cd29169f171a48ae5552d1c" dependencies = [ - "futures 0.3.30", + "futures", "gpiocdev-uapi", "thiserror", - "tokio 1.37.0", + "tokio", "tokio-stream", ] @@ -1434,24 +1226,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "h2" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" -dependencies = [ - "byteorder", - "bytes 0.4.12", - "fnv", - "futures 0.1.31", - "http 0.1.21", - "indexmap 1.9.3", - "log", - "slab", - "string", - "tokio-io", -] - [[package]] name = "hash32" version = "0.2.1" @@ -1470,12 +1244,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "hashbrown" version = "0.14.5" @@ -1496,7 +1264,7 @@ dependencies = [ "hash32 0.2.1", "rustc_version 0.4.0", "serde", - "spin 0.9.8", + "spin", "stable_deref_trait", ] @@ -1538,38 +1306,15 @@ dependencies = [ "thiserror", ] -[[package]] -name = "http" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" -dependencies = [ - "bytes 0.4.12", - "fnv", - "itoa 0.4.8", -] - [[package]] name = "http" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ - "bytes 1.6.0", + "bytes", "fnv", - "itoa 1.0.11", -] - -[[package]] -name = "http-body" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "http 0.1.21", - "tokio-buf", + "itoa", ] [[package]] @@ -1578,8 +1323,8 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ - "bytes 1.6.0", - "http 1.1.0", + "bytes", + "http", ] [[package]] @@ -1588,10 +1333,10 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" dependencies = [ - "bytes 1.6.0", + "bytes", "futures-core", - "http 1.1.0", - "http-body 1.0.0", + "http", + "http-body", "pin-project-lite", ] @@ -1607,70 +1352,24 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "hyper" -version = "0.12.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c843caf6296fc1f93444735205af9ed4e109a539005abb2564ae1d6fad34c52" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "futures-cpupool", - "h2", - "http 0.1.21", - "http-body 0.1.0", - "httparse", - "iovec", - "itoa 0.4.8", - "log", - "net2", - "rustc_version 0.2.3", - "time 0.1.45", - "tokio 0.1.22", - "tokio-buf", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "tokio-tcp", - "tokio-threadpool", - "tokio-timer", - "want", -] - [[package]] name = "hyper" version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ - "bytes 1.6.0", + "bytes", "futures-channel", "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "http", + "http-body", "httparse", "httpdate", - "itoa 1.0.11", + "itoa", "pin-project-lite", - "smallvec 1.13.2", - "tokio 1.37.0", -] - -[[package]] -name = "hyper-rustls" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719d85c7df4a7f309a77d145340a063ea929dcb2e025bae46a80345cffec2952" -dependencies = [ - "bytes 0.4.12", - "ct-logs", - "futures 0.1.31", - "hyper 0.12.36", - "rustls", - "tokio-io", - "tokio-rustls", - "webpki", - "webpki-roots", + "smallvec", + "tokio", + "want", ] [[package]] @@ -1679,13 +1378,18 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" dependencies = [ - "bytes 1.6.0", + "bytes", + "futures-channel", "futures-util", - "http 1.1.0", - "http-body 1.0.0", - "hyper 1.3.1", + "http", + "http-body", + "hyper", "pin-project-lite", - "tokio 1.37.0", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", ] [[package]] @@ -1723,28 +1427,6 @@ dependencies = [ "cc", ] -[[package]] -name = "idna" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "idna" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "idna" version = "0.5.0" @@ -1761,16 +1443,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg 1.3.0", - "hashbrown 0.12.3", -] - [[package]] name = "indexmap" version = "2.2.6" @@ -1778,7 +1450,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown", ] [[package]] @@ -1787,7 +1459,7 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1807,13 +1479,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bd11f3a29434026f5ff98c730b668ba74b1033637b8817940b54d040696133c" [[package]] -name = "iovec" -version = "0.1.4" +name = "ipnet" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is_terminal_polyfill" @@ -1830,12 +1499,6 @@ dependencies = [ "either", ] -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - [[package]] name = "itoa" version = "1.0.11" @@ -1851,16 +1514,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -1897,22 +1550,13 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" -[[package]] -name = "lock_api" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" -dependencies = [ - "scopeguard", -] - [[package]] name = "lock_api" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ - "autocfg 1.3.0", + "autocfg", "scopeguard", ] @@ -1937,7 +1581,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" dependencies = [ - "hashbrown 0.14.5", + "hashbrown", ] [[package]] @@ -1958,12 +1602,6 @@ dependencies = [ "regex-automata 0.1.10", ] -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - [[package]] name = "matchit" version = "0.7.3" @@ -1995,34 +1633,19 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - [[package]] name = "memchr" version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" -[[package]] -name = "memoffset" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" -dependencies = [ - "autocfg 1.3.0", -] - [[package]] name = "memoffset" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ - "autocfg 1.3.0", + "autocfg", ] [[package]] @@ -2031,7 +1654,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" dependencies = [ - "autocfg 1.3.0", + "autocfg", ] [[package]] @@ -2053,16 +1676,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "mime_guess" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" -dependencies = [ - "mime", - "unicase", -] - [[package]] name = "miniz_oxide" version = "0.7.3" @@ -2072,25 +1685,6 @@ dependencies = [ "adler", ] -[[package]] -name = "mio" -version = "0.6.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" -dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log", - "miow", - "net2", - "slab", - "winapi 0.2.8", -] - [[package]] name = "mio" version = "0.8.11" @@ -2099,22 +1693,10 @@ checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.48.0", ] -[[package]] -name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] - [[package]] name = "mpd" version = "0.1.0" @@ -2139,17 +1721,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" -[[package]] -name = "net2" -version = "0.2.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", -] - [[package]] name = "nix" version = "0.23.2" @@ -2158,7 +1729,7 @@ checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" dependencies = [ "bitflags 1.3.2", "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "memoffset 0.6.5", ] @@ -2170,7 +1741,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", - "cfg-if 1.0.0", + "cfg-if", "libc", "memoffset 0.7.1", "pin-utils", @@ -2183,7 +1754,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ "bitflags 2.5.0", - "cfg-if 1.0.0", + "cfg-if", "libc", ] @@ -2194,7 +1765,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ "bitflags 2.5.0", - "cfg-if 1.0.0", + "cfg-if", "cfg_aliases", "libc", ] @@ -2206,7 +1777,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ "overload", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2221,7 +1792,7 @@ version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "autocfg 1.3.0", + "autocfg", ] [[package]] @@ -2267,17 +1838,6 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" -[[package]] -name = "parking_lot" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -dependencies = [ - "lock_api 0.3.4", - "parking_lot_core 0.6.3", - "rustc_version 0.2.3", -] - [[package]] name = "parking_lot" version = "0.11.2" @@ -2285,7 +1845,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", - "lock_api 0.4.12", + "lock_api", "parking_lot_core 0.8.6", ] @@ -2295,37 +1855,22 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ - "lock_api 0.4.12", + "lock_api", "parking_lot_core 0.9.10", ] -[[package]] -name = "parking_lot_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66b810a62be75176a80873726630147a5ca780cd33921e0b5709033e66b0a" -dependencies = [ - "cfg-if 0.1.10", - "cloudabi", - "libc", - "redox_syscall 0.1.57", - "rustc_version 0.2.3", - "smallvec 0.6.14", - "winapi 0.3.9", -] - [[package]] name = "parking_lot_core" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "instant", "libc", "redox_syscall 0.2.16", - "smallvec 1.13.2", - "winapi 0.3.9", + "smallvec", + "winapi", ] [[package]] @@ -2334,10 +1879,10 @@ version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall 0.5.1", - "smallvec 1.13.2", + "smallvec", "windows-targets 0.52.5", ] @@ -2347,12 +1892,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" - [[package]] name = "percent-encoding" version = "2.3.1" @@ -2361,8 +1900,8 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "philipshue" -version = "0.3.2" -source = "git+https://github.com/dvdsk/philipshue?branch=master#c52c7fa306a78c3432f5619bb4de75ccd55fb19f" +version = "0.3.3" +source = "git+https://github.com/dvdsk/philipshue?branch=master#827e4d08eb05a5d6aa8071b67cd58751419ed3ea" dependencies = [ "error-chain", "reqwest", @@ -2499,16 +2038,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "publicsuffix" -version = "1.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b4ce31ff0a27d93c8de1849cf58162283752f065a90d508f1105fa6c9a213f" -dependencies = [ - "idna 0.2.3", - "url 2.5.0", -] - [[package]] name = "pulldown-cmark" version = "0.9.6" @@ -2535,25 +2064,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -dependencies = [ - "autocfg 0.1.8", - "libc", - "rand_chacha 0.1.1", - "rand_core 0.4.2", - "rand_hc", - "rand_isaac", - "rand_jitter", - "rand_os", - "rand_pcg", - "rand_xorshift", - "winapi 0.3.9", -] - [[package]] name = "rand" version = "0.8.5" @@ -2561,18 +2071,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -dependencies = [ - "autocfg 0.1.8", - "rand_core 0.3.1", + "rand_chacha", + "rand_core", ] [[package]] @@ -2582,24 +2082,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", + "rand_core", ] -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.6.4" @@ -2609,68 +2094,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -dependencies = [ - "libc", - "rand_core 0.4.2", - "winapi 0.3.9", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.4.2", - "rdrand", - "winapi 0.3.9", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -dependencies = [ - "autocfg 0.1.8", - "rand_core 0.4.2", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "ratatui" version = "0.26.3" @@ -2691,21 +2114,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - [[package]] name = "redox_syscall" version = "0.2.16" @@ -2770,53 +2178,38 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" -version = "0.9.24" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab" +checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ "base64", - "bytes 0.4.12", - "cookie", - "cookie_store", - "encoding_rs", - "flate2", - "futures 0.1.31", - "http 0.1.21", - "hyper 0.12.36", - "hyper-rustls", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "ipnet", + "js-sys", "log", "mime", - "mime_guess", - "rustls", + "once_cell", + "percent-encoding", + "pin-project-lite", "serde", "serde_json", "serde_urlencoded", - "time 0.1.45", - "tokio 0.1.22", - "tokio-executor", - "tokio-io", - "tokio-rustls", - "tokio-threadpool", - "tokio-timer", - "url 1.7.2", - "uuid", - "webpki-roots", - "winreg", -] - -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted", + "sync_wrapper 0.1.2", + "tokio", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", "web-sys", - "winapi 0.3.9", + "winreg", ] [[package]] @@ -2843,19 +2236,6 @@ dependencies = [ "semver 1.0.23", ] -[[package]] -name = "rustls" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" -dependencies = [ - "base64", - "log", - "ring", - "sct", - "webpki", -] - [[package]] name = "rustversion" version = "1.0.17" @@ -2874,16 +2254,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "sdio-host" version = "0.5.0" @@ -2953,21 +2323,21 @@ version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ - "itoa 1.0.11", + "itoa", "ryu", "serde", ] [[package]] name = "serde_urlencoded" -version = "0.5.5" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ - "dtoa", - "itoa 0.4.8", + "form_urlencoded", + "itoa", + "ryu", "serde", - "url 1.7.2", ] [[package]] @@ -2976,8 +2346,8 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.2.6", - "itoa 1.0.11", + "indexmap", + "itoa", "ryu", "serde", "unsafe-libyaml", @@ -2990,7 +2360,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f5a15d0be940df84846264b09b51b10b931fb2f275becb80934e3568a016828" dependencies = [ "bitflags 2.5.0", - "cfg-if 1.0.0", + "cfg-if", "core-foundation-sys", "io-kit-sys", "mach2", @@ -2998,7 +2368,7 @@ dependencies = [ "regex", "scopeguard", "unescaper", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -3040,7 +2410,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" dependencies = [ "libc", - "mio 0.8.11", + "mio", "signal-hook", ] @@ -3059,7 +2429,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ - "autocfg 1.3.0", + "autocfg", ] [[package]] @@ -3069,8 +2439,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" dependencies = [ "crc32fast", - "crossbeam-epoch 0.9.18", - "crossbeam-utils 0.8.20", + "crossbeam-epoch", + "crossbeam-utils", "fs2", "fxhash", "libc", @@ -3078,15 +2448,6 @@ dependencies = [ "parking_lot 0.11.2", ] -[[package]] -name = "smallvec" -version = "0.6.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" -dependencies = [ - "maybe-uninit", -] - [[package]] name = "smallvec" version = "1.13.2" @@ -3114,19 +2475,13 @@ dependencies = [ "nix 0.26.4", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" dependencies = [ - "lock_api 0.4.12", + "lock_api", ] [[package]] @@ -3184,15 +2539,6 @@ dependencies = [ "cortex-m-rt", ] -[[package]] -name = "string" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" -dependencies = [ - "bytes 0.4.12", -] - [[package]] name = "strsim" version = "0.11.1" @@ -3255,18 +2601,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "unicode-xid", -] - [[package]] name = "sysfs_gpio" version = "0.6.2" @@ -3308,21 +2642,10 @@ version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", ] -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi 0.3.9", -] - [[package]] name = "time" version = "0.3.36" @@ -3368,25 +2691,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "tokio" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "mio 0.6.23", - "num_cpus", - "tokio-current-thread", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "tokio-tcp", - "tokio-threadpool", - "tokio-timer", -] - [[package]] name = "tokio" version = "1.37.0" @@ -3394,9 +2698,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", - "bytes 1.6.0", + "bytes", "libc", - "mio 0.8.11", + "mio", "num_cpus", "parking_lot 0.12.3", "pin-project-lite", @@ -3406,48 +2710,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "tokio-buf" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" -dependencies = [ - "bytes 0.4.12", - "either", - "futures 0.1.31", -] - -[[package]] -name = "tokio-current-thread" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" -dependencies = [ - "futures 0.1.31", - "tokio-executor", -] - -[[package]] -name = "tokio-executor" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" -dependencies = [ - "crossbeam-utils 0.7.2", - "futures 0.1.31", -] - -[[package]] -name = "tokio-io" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "log", -] - [[package]] name = "tokio-macros" version = "2.2.0" @@ -3459,39 +2721,6 @@ dependencies = [ "syn 2.0.66", ] -[[package]] -name = "tokio-reactor" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" -dependencies = [ - "crossbeam-utils 0.7.2", - "futures 0.1.31", - "lazy_static", - "log", - "mio 0.6.23", - "num_cpus", - "parking_lot 0.9.0", - "slab", - "tokio-executor", - "tokio-io", - "tokio-sync", -] - -[[package]] -name = "tokio-rustls" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d7cf08f990090abd6c6a73cab46fed62f85e8aef8b99e4b918a9f4a637f0676" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "iovec", - "rustls", - "tokio-io", - "webpki", -] - [[package]] name = "tokio-stream" version = "0.1.15" @@ -3500,60 +2729,7 @@ checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", - "tokio 1.37.0", -] - -[[package]] -name = "tokio-sync" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" -dependencies = [ - "fnv", - "futures 0.1.31", -] - -[[package]] -name = "tokio-tcp" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "iovec", - "mio 0.6.23", - "tokio-io", - "tokio-reactor", -] - -[[package]] -name = "tokio-threadpool" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" -dependencies = [ - "crossbeam-deque", - "crossbeam-queue", - "crossbeam-utils 0.7.2", - "futures 0.1.31", - "lazy_static", - "log", - "num_cpus", - "slab", - "tokio-executor", -] - -[[package]] -name = "tokio-timer" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" -dependencies = [ - "crossbeam-utils 0.7.2", - "futures 0.1.31", - "slab", - "tokio-executor", + "tokio", ] [[package]] @@ -3566,7 +2742,7 @@ dependencies = [ "futures-util", "pin-project", "pin-project-lite", - "tokio 1.37.0", + "tokio", "tower-layer", "tower-service", ] @@ -3658,7 +2834,7 @@ dependencies = [ "once_cell", "regex", "sharded-slab", - "smallvec 1.13.2", + "smallvec", "thread_local", "tracing", "tracing-core", @@ -3671,15 +2847,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "try_from" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" -dependencies = [ - "cfg-if 0.1.10", -] - [[package]] name = "tui-tree-widget" version = "0.20.0" @@ -3771,23 +2938,6 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "url" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -dependencies = [ - "idna 0.1.5", - "matches", - "percent-encoding 1.0.1", -] - [[package]] name = "url" version = "2.5.0" @@ -3795,8 +2945,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna 0.5.0", - "percent-encoding 2.3.1", + "idna", + "percent-encoding", ] [[package]] @@ -3805,15 +2955,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" -[[package]] -name = "uuid" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" -dependencies = [ - "rand 0.6.5", -] - [[package]] name = "valuable" version = "0.1.0" @@ -3855,21 +2996,13 @@ checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" [[package]] name = "want" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "futures 0.1.31", - "log", "try-lock", ] -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -3882,7 +3015,7 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen-macro", ] @@ -3901,6 +3034,18 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.92" @@ -3940,31 +3085,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a262ae37dd9d60f60dd473d1158f9fbebf110ba7b6a5051c8160460f6043718b" -dependencies = [ - "webpki", -] - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - [[package]] name = "winapi" version = "0.3.9" @@ -3975,12 +3095,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -4143,21 +3257,12 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winreg" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "ws2_32-sys" -version = "0.2.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "cfg-if", + "windows-sys 0.48.0", ] [[package]] diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 1f8b5d58..88ff7f7b 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -15,7 +15,7 @@ tokio = { version = "1", features = ["full"] } axum = { version = "0.7.4", default-features = false, features = ["tokio", "http1"] } axum-macros = "0.4.1" -philipshue = { git = "https://github.com/dvdsk/philipshue", branch = "master" } +philipshue = { git = "https://github.com/dvdsk/philipshue", branch = "master", default-features = false } serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.9" diff --git a/crates/brain/deploy.sh b/crates/brain/deploy.sh index 2e40ed53..a6beadf9 100755 --- a/crates/brain/deploy.sh +++ b/crates/brain/deploy.sh @@ -3,9 +3,9 @@ set -e SERVER="sgc" # ssh config name or full address -cross build --target=aarch64-unknown-linux-musl --release +cargo build --target=aarch64-unknown-linux-musl --release rsync -vh --progress \ - target/aarch64-unknown-linux-gnu/release/brain \ + target/aarch64-unknown-linux-musl/release/brain \ $SERVER:/tmp/ cmds=" diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index 2f9d67b2..ec4b5204 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -27,6 +27,10 @@ struct Opt { /// a loadbalancer/reverse proxy to get traffic to this #[clap(short, long)] port: u16, + + /// ip address of the hue bridge, format as: 127.0.0.1 + #[clap(short, long)] + hue_bridge_ip: String, } #[tokio::main] @@ -50,13 +54,10 @@ async fn main() -> Result<(), Box> { // let (_mpd_status, _mpd_watcher_thread, _updater_tx) = // input::MpdStatus::start_updating(opt.mpd_ip)?; - let system = system::System::init(jobs); + let system = system::System::init(jobs, opt.hue_bridge_ip); let _tasks = controller::start(subscribed_rxs, event_tx.clone(), system); - tokio::task::spawn(input::sensors::subscribe( - event_tx, - opt.subscribe_port, - )); + tokio::task::spawn(input::sensors::subscribe(event_tx, opt.subscribe_port)); input::api::setup(wakeup.clone(), opt.port).await?; unreachable!(); diff --git a/crates/brain/src/system.rs b/crates/brain/src/system.rs index d72f7634..a31f4e53 100644 --- a/crates/brain/src/system.rs +++ b/crates/brain/src/system.rs @@ -14,10 +14,10 @@ pub struct System { } impl System { - pub fn init(jobs: Jobs) -> Self { + pub fn init(jobs: Jobs, hue_bridge_ip: String) -> Self { Self { jobs, - lights: Lighting::start_init(), + lights: Lighting::start_init(hue_bridge_ip), // mpd: Mpd, } } diff --git a/crates/brain/src/system/lamps/bridge_connect.rs b/crates/brain/src/system/lamps/bridge_connect.rs index b56873d6..4b3dd252 100644 --- a/crates/brain/src/system/lamps/bridge_connect.rs +++ b/crates/brain/src/system/lamps/bridge_connect.rs @@ -1,7 +1,7 @@ use philipshue::bridge; use philipshue::bridge::Bridge; use philipshue::errors::{BridgeError::LinkButtonNotPressed, HueError, HueErrorKind}; -use tracing::{info, error}; +use tracing::{error, info}; use super::Error; use std::collections::BTreeMap; @@ -46,21 +46,6 @@ fn register(ip: &str) -> Result { return Err(RegisterError::Timedout); } -fn find_bridge_ip() -> Result { - let mut discovered = bridge::discover().map_err(Error::Discovery)?; - if discovered.len() == 0 { - error!("No bridge found!"); - return Err(Error::NoBridgeFound); - } else if discovered.len() > 1 { - error!( - "Found multiple hue bridges: {:?}, continuing with first one in list", - discovered - ); - } - - Ok(discovered.pop().unwrap().into_ip()) -} - fn saved_bridge_info() -> Result<(String, String), ()> { let path = Path::new("hueBridgeLogin"); match File::open(&path) { @@ -89,13 +74,14 @@ fn update_saved_bridge_info(bridge_ip: &str, login: &str) -> Result<(), SaveBrid serde_yaml::to_writer(file, &(bridge_ip, login)).map_err(SaveBridgeError::Writing) } -pub fn get_bridge_and_status() -> Result<(Bridge, BTreeMap), Error> { +pub fn get_bridge_and_status( + ip: &str, +) -> Result<(Bridge, BTreeMap), Error> { let Ok((ip, login)) = saved_bridge_info() else { - let ip = find_bridge_ip()?; let login = register(&ip)?; - update_saved_bridge_info(&ip, &login)?; + update_saved_bridge_info(ip, &login)?; - let bridge = Bridge::new(&ip, &login); + let bridge = Bridge::new(ip, &login); let lights_info = bridge.get_all_lights().map_err(Error::GettingLights)?; return Ok((bridge, lights_info)); }; @@ -106,7 +92,6 @@ pub fn get_bridge_and_status() -> Result<(Bridge, BTreeMap Ok((bridge, lights_info)), Err(_) => { - let ip = find_bridge_ip()?; let login = register(&ip)?; update_saved_bridge_info(&ip, &login)?; diff --git a/crates/brain/src/system/lamps/eventually_consistent_bridge.rs b/crates/brain/src/system/lamps/eventually_consistent_bridge.rs index 7db5ab22..70a451f3 100644 --- a/crates/brain/src/system/lamps/eventually_consistent_bridge.rs +++ b/crates/brain/src/system/lamps/eventually_consistent_bridge.rs @@ -53,8 +53,8 @@ pub(crate) struct CachedBridge { } impl CachedBridge { - pub(crate) fn try_init() -> Result { - let (bridge, lights_info) = bridge_connect::get_bridge_and_status()?; + pub(crate) fn try_init(ip: &str) -> Result { + let (bridge, lights_info) = bridge_connect::get_bridge_and_status(ip)?; let state: HashMap = lights_info .iter() .map(|(id, light)| (*id, Lamp::from(&light.state))) diff --git a/crates/brain/src/system/lamps/mod.rs b/crates/brain/src/system/lamps/mod.rs index 6c546fbe..4c49297a 100644 --- a/crates/brain/src/system/lamps/mod.rs +++ b/crates/brain/src/system/lamps/mod.rs @@ -18,6 +18,7 @@ mod lamp; type State = HashMap; async fn manage_bridge( + ip: String, rx: mpsc::UnboundedReceiver<(oneshot::Sender>, Change)>, ) { let stream = stream::unfold(rx, |mut rx| async move { @@ -29,7 +30,7 @@ async fn manage_bridge( let stream = stream.peekable(); pin_mut!(stream); loop { - let error = match eventually_consistent_bridge::CachedBridge::try_init() { + let error = match eventually_consistent_bridge::CachedBridge::try_init(&ip) { Ok(bridge) => { eventually_consistent_bridge::process_lamp_changes(&mut stream, bridge).await } @@ -53,10 +54,6 @@ pub struct Lighting { pub enum Error { #[error("Could not get lights from bridge")] GettingLights(philipshue::errors::HueError), - #[error("Could not find the bridge via upnp")] - NoBridgeFound, - #[error("Error while trying to discover the bridge")] - Discovery(philipshue::errors::HueError), #[error("Failed to register on bridge")] Register(#[from] bridge_connect::RegisterError), #[error("Something went wrong saving bridge account to disk: {0}")] @@ -81,9 +78,9 @@ macro_rules! light_fn { #[allow(dead_code)] impl Lighting { - pub fn start_init() -> Self { + pub fn start_init(ip: String) -> Self { let (tx, rx) = mpsc::unbounded_channel(); - let manage_bridge = manage_bridge(rx); + let manage_bridge = manage_bridge(ip, rx); tokio::task::spawn(manage_bridge); Self { tx } } From aa869f576f7cdbf92518d7635a6b1b4fe2c89ea5 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 31 May 2024 15:30:56 +0200 Subject: [PATCH 111/687] fixes lag in lighting sys --- Cargo.lock | 21 +++--------- crates/brain/Cargo.toml | 1 - crates/brain/deploy.sh | 4 +-- crates/brain/src/controller/mod.rs | 12 +++++++ .../src/controller/rooms/large_bedroom.rs | 32 ++++++++++++++++--- crates/brain/src/input/sensors.rs | 9 +++--- crates/brain/src/main.rs | 11 +++---- .../brain/src/system/lamps/bridge_connect.rs | 25 +++++++++------ .../lamps/eventually_consistent_bridge.rs | 29 +++++++++-------- crates/brain/src/system/lamps/lamp.rs | 4 ++- crates/brain/src/system/lamps/mod.rs | 2 +- crates/desk-sensors/src/buttons.rs | 2 +- 12 files changed, 91 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6536a076..4a73b5ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -319,7 +319,6 @@ dependencies = [ "futures", "futures-concurrency", "futures-util", - "log-panics", "mpd", "philipshue", "protocol", @@ -1566,15 +1565,6 @@ version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" -[[package]] -name = "log-panics" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f9dd8546191c1850ecf67d22f5ff00a935b890d0e84713159a55495cc2ac5f" -dependencies = [ - "log", -] - [[package]] name = "lru" version = "0.12.3" @@ -1901,7 +1891,7 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "philipshue" version = "0.3.3" -source = "git+https://github.com/dvdsk/philipshue?branch=master#827e4d08eb05a5d6aa8071b67cd58751419ed3ea" +source = "git+https://github.com/dvdsk/philipshue?branch=master#328fda7ad085fefe5d3f23d205414d803c6aa69e" dependencies = [ "error-chain", "reqwest", @@ -2184,7 +2174,6 @@ checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ "base64", "bytes", - "futures-channel", "futures-core", "futures-util", "http", @@ -2693,9 +2682,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", @@ -2712,9 +2701,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 88ff7f7b..fa82b2a7 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -39,7 +39,6 @@ futures-util = "0.3.30" tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } tracing-journald = "0.3.0" -log-panics = "2.1.0" clap = { version = "4.5.4", features = ["derive"] } futures-concurrency = "7.5.0" strum = { version = "0.26.2", default-features = false, features = ["derive"] } diff --git a/crates/brain/deploy.sh b/crates/brain/deploy.sh index a6beadf9..8b9b44e1 100755 --- a/crates/brain/deploy.sh +++ b/crates/brain/deploy.sh @@ -5,13 +5,13 @@ SERVER="sgc" # ssh config name or full address cargo build --target=aarch64-unknown-linux-musl --release rsync -vh --progress \ - target/aarch64-unknown-linux-musl/release/brain \ + ../../target/aarch64-unknown-linux-musl/release/brain \ $SERVER:/tmp/ cmds=" sudo mv /tmp/brain /home/ha/brain sudo chown ha:ha /home/ha/brain -sudo systemctl restart ha +sudo systemctl restart brain " ssh -t sgc "$cmds" diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 2e975561..bf21e654 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -39,6 +39,18 @@ impl RestrictedSystem { self.system.lights.set_ct(name, bri, ct).await.unwrap(); } } + + async fn all_lamps_off(&mut self) { + for name in &self.allowed_lights { + self.system.lights.single_off(name).await.unwrap(); + } + } + + async fn all_lamps_on(&mut self) { + for name in &self.allowed_lights { + self.system.lights.single_on(name).await.unwrap(); + } + } } pub fn start( diff --git a/crates/brain/src/controller/rooms/large_bedroom.rs b/crates/brain/src/controller/rooms/large_bedroom.rs index ef01ec57..76ea09eb 100644 --- a/crates/brain/src/controller/rooms/large_bedroom.rs +++ b/crates/brain/src/controller/rooms/large_bedroom.rs @@ -4,6 +4,7 @@ use futures_concurrency::future::Race; use futures_util::FutureExt; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; +use tracing::{info, warn}; use crate::controller::{local_now, Event, RestrictedSystem}; @@ -11,8 +12,10 @@ use crate::controller::{local_now, Event, RestrictedSystem}; enum State { // Sleep, // Wakeup, + FadeOut(Instant), Normal, Bright, + Off, // Away, } @@ -82,30 +85,47 @@ pub async fn run( let new_state = match res { Res::Event(e) => handle_event(e), Res::ShouldUpdate => { - update(&mut system, &state).await; next_update = Instant::now() + INTERVAL; - None + update(&mut system, &state).await } }; if let Some(new) = new_state { + info!("transitioning to new state: {new:?}"); state = new; - update(&mut system, &state).await; next_update = Instant::now() + INTERVAL; + if update(&mut system, &state).await.is_some() { + warn!("Transiting to a new state while in the first update is not allowed") + } } } } -async fn update(system: &mut RestrictedSystem, state: &State) { +async fn update(system: &mut RestrictedSystem, state: &State) -> Option { match state { + State::Off => { + system.all_lamps_off().await; + /* TODO: make states have destructors, maybe even remove enum in + * favor of polymorphism? */ + } State::Normal => { let (new_ct, new_bri) = optimal_ct_bri(); + system.all_lamps_on().await; system.all_lamps_ct(new_ct, new_bri).await; } State::Bright => { + system.all_lamps_on().await; system.all_lamps_ct(254, u8::MAX).await; } + State::FadeOut(started) => { + system.all_lamps_on().await; + system.all_lamps_ct(1, u8::MAX).await; + if started.elapsed() > Duration::from_secs(40) { + return Some(State::Off) + } + } } + None } fn optimal_ct_bri() -> (u16, u8) { @@ -137,7 +157,9 @@ fn handle_button(b: protocol::large_bedroom::desk::Button) -> Option { println!("button pressed: {b:?}"); match b { - Button::OneOfFour(press) if press.is_long() => Some(State::Bright), + Button::OneOfFour(press) if press.is_long() => Some(State::Off), + Button::OneOfFour(_) => Some(State::FadeOut(Instant::now())), + Button::TwoOfFour(press) if press.is_long() => Some(State::Bright), Button::FourOfFour(press) if !press.is_long() => Some(State::Normal), // Button::TwoOfFour(_) => todo!(), // Button::ThreeOfFour(_) => todo!(), diff --git a/crates/brain/src/input/sensors.rs b/crates/brain/src/input/sensors.rs index 23c88933..7eb1606d 100644 --- a/crates/brain/src/input/sensors.rs +++ b/crates/brain/src/input/sensors.rs @@ -7,11 +7,10 @@ use tracing::{error, warn}; use crate::controller::Event; -pub async fn subscribe(event_tx: broadcast::Sender, subscribe_port: u16) { +pub async fn subscribe(event_tx: broadcast::Sender, data_server: SocketAddr) { loop { let mut sub = loop { - let addr = SocketAddr::from(([127, 0, 0, 1], subscribe_port)); - match AsyncSubscriber::connect(addr).await { + match AsyncSubscriber::connect(data_server).await { Ok(sub) => break sub, Err(SubscribeError::DecodeFailed(e)) => { error!("Decode failed: {e:?}. is protocol lib up to date? Exiting"); @@ -26,7 +25,9 @@ pub async fn subscribe(event_tx: broadcast::Sender, subscribe_port: u16) loop { match sub.next().await { - Ok(Ok(reading)) => event_tx.send(Event::Sensor(reading)).unwrap(), + Ok(Ok(reading)) => { + event_tx.send(Event::Sensor(reading)).unwrap(); + } Ok(Err(_)) => continue, Err(e) => { warn!("Error while subscribed to sensor readings: {e}, retrying..."); diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index ec4b5204..0b9f4046 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -1,5 +1,5 @@ use std::array; -use std::net::IpAddr; +use std::net::{IpAddr, SocketAddr}; use clap::Parser; use sled; @@ -15,9 +15,9 @@ mod input; #[derive(Parser)] #[command(version, about, long_about=None)] struct Opt { - /// port where to subscribe for updates + /// ip address whete to subscribe for updates #[clap(short, long)] - subscribe_port: u16, + data_server: SocketAddr, /// ip address for mpd server #[clap(short, long)] @@ -29,7 +29,7 @@ struct Opt { port: u16, /// ip address of the hue bridge, format as: 127.0.0.1 - #[clap(short, long)] + #[clap(short = 'b', long)] hue_bridge_ip: String, } @@ -57,7 +57,7 @@ async fn main() -> Result<(), Box> { let system = system::System::init(jobs, opt.hue_bridge_ip); let _tasks = controller::start(subscribed_rxs, event_tx.clone(), system); - tokio::task::spawn(input::sensors::subscribe(event_tx, opt.subscribe_port)); + tokio::task::spawn(input::sensors::subscribe(event_tx, opt.data_server)); input::api::setup(wakeup.clone(), opt.port).await?; unreachable!(); @@ -90,5 +90,4 @@ pub fn setup_tracing() { registry.init() } }; - log_panics::init(); } diff --git a/crates/brain/src/system/lamps/bridge_connect.rs b/crates/brain/src/system/lamps/bridge_connect.rs index 4b3dd252..527ee8cf 100644 --- a/crates/brain/src/system/lamps/bridge_connect.rs +++ b/crates/brain/src/system/lamps/bridge_connect.rs @@ -7,7 +7,6 @@ use super::Error; use std::collections::BTreeMap; use std::fs::File; use std::path::Path; -use std::thread; use std::time::Duration; #[derive(Debug, thiserror::Error)] @@ -18,10 +17,10 @@ pub enum RegisterError { Timedout, } -fn register(ip: &str) -> Result { +async fn register(ip: &str) -> Result { for _ in 0..5 { //try 5 times to connect - match bridge::register_user(ip, "homeAutomationSys") { + match bridge::register_user(ip, "homeAutomationSys").await { Ok(received_login) => { println!("Success, linked to bridge"); info!("User registered: {}, on IP: {}", &received_login, ip); @@ -35,7 +34,7 @@ fn register(ip: &str) -> Result { _, )) => { println!("Please, press the link on the bridge. Retrying in 5 seconds"); - thread::sleep(Duration::from_secs(5)); + tokio::time::sleep(Duration::from_secs(5)).await; } Err(e) => { println!("Unexpected error occurred: {}", e); @@ -74,29 +73,35 @@ fn update_saved_bridge_info(bridge_ip: &str, login: &str) -> Result<(), SaveBrid serde_yaml::to_writer(file, &(bridge_ip, login)).map_err(SaveBridgeError::Writing) } -pub fn get_bridge_and_status( +pub async fn get_bridge_and_status( ip: &str, ) -> Result<(Bridge, BTreeMap), Error> { let Ok((ip, login)) = saved_bridge_info() else { - let login = register(&ip)?; + let login = register(&ip).await?; update_saved_bridge_info(ip, &login)?; let bridge = Bridge::new(ip, &login); - let lights_info = bridge.get_all_lights().map_err(Error::GettingLights)?; + let lights_info = bridge + .get_all_lights() + .await + .map_err(Error::GettingLights)?; return Ok((bridge, lights_info)); }; let bridge = Bridge::new(&ip, &login); - let res = bridge.get_all_lights(); + let res = bridge.get_all_lights().await; match res { Ok(lights_info) => Ok((bridge, lights_info)), Err(_) => { - let login = register(&ip)?; + let login = register(&ip).await?; update_saved_bridge_info(&ip, &login)?; let bridge = Bridge::new(&ip, &login); - let lights_info = bridge.get_all_lights().map_err(Error::GettingLights)?; + let lights_info = bridge + .get_all_lights() + .await + .map_err(Error::GettingLights)?; Ok((bridge, lights_info)) } } diff --git a/crates/brain/src/system/lamps/eventually_consistent_bridge.rs b/crates/brain/src/system/lamps/eventually_consistent_bridge.rs index 70a451f3..93d05692 100644 --- a/crates/brain/src/system/lamps/eventually_consistent_bridge.rs +++ b/crates/brain/src/system/lamps/eventually_consistent_bridge.rs @@ -53,8 +53,8 @@ pub(crate) struct CachedBridge { } impl CachedBridge { - pub(crate) fn try_init(ip: &str) -> Result { - let (bridge, lights_info) = bridge_connect::get_bridge_and_status(ip)?; + pub(crate) async fn try_init(ip: &str) -> Result { + let (bridge, lights_info) = bridge_connect::get_bridge_and_status(ip).await?; let state: HashMap = lights_info .iter() .map(|(id, light)| (*id, Lamp::from(&light.state))) @@ -80,14 +80,14 @@ impl CachedBridge { } } - pub(crate) fn apply_changes(&mut self) -> Result<(), Error> { + pub(crate) async fn apply_changes(&mut self) -> Result<(), Error> { for (id, lamp) in self.known_state.iter_mut() { let Some(needed) = self.needed_state.get(id) else { continue; }; if lamp != needed { - if let Err(e) = self.bridge.set_light_state(*id, &needed.light_cmd()) { + if let Err(e) = self.bridge.set_light_state(*id, &needed.light_cmd()).await { warn!("could not apply changes to lamp: {e}") } *lamp = needed.clone() @@ -97,9 +97,9 @@ impl CachedBridge { Ok(()) } - fn push_state(&mut self) -> Result<(), Error> { + async fn push_state(&mut self) -> Result<(), Error> { for (id, lamp) in self.known_state.iter_mut() { - let _ignore_err = self.bridge.set_light_state(*id, &lamp.light_cmd()); + let _ignore_err = self.bridge.set_light_state(*id, &lamp.light_cmd()).await; } Ok(()) } @@ -118,10 +118,11 @@ impl CachedBridge { } Change::Off { name } => { let Some(lamp_id) = self.lookup.get(*name) else { + self.report_missing_if_not_reported_yet(*name); return; }; if let Some(lamp) = self.needed_state.get_mut(lamp_id) { - lamp.on = true; + lamp.on = false; } else { error!("no lamp with id: {lamp_id} exists"); } @@ -132,7 +133,7 @@ impl CachedBridge { return; }; if let Some(lamp) = self.needed_state.get_mut(&lamp_id) { - lamp.on = false; + lamp.on = true; } else { error!("no lamp with id: {lamp_id} exists"); } @@ -184,11 +185,11 @@ pub(crate) async fn process_lamp_changes( where S: Stream>, Change)>, { - const MAX_DUR: Duration = Duration::from_millis(100); + const MAX_DUR: Duration = Duration::from_millis(5); let mut last_state_push = Instant::now(); loop { if last_state_push.elapsed() > Duration::from_secs(5) { - if let Err(err) = bridge.push_state() { + if let Err(err) = bridge.push_state().await { return err; } last_state_push = Instant::now(); @@ -198,7 +199,7 @@ where Ok(Some(next)) => next, Ok(None) => unreachable!("light system should not drop"), Err(_timeout) => { - if let Err(err) = bridge.push_state() { + if let Err(err) = bridge.push_state().await { return err; } else { continue; @@ -224,15 +225,15 @@ where }; } - if let Err(e) = bridge.apply_changes() { + if let Err(e) = bridge.apply_changes().await { error!("Could not apply changes to bridge immediately, err: {e}"); for tx in to_answer { - let _ignore_canceld_requester = tx.send(Err(ApplyChangeError)); + let _ignore_canceled_requester = tx.send(Err(ApplyChangeError)); } return e; } else { for tx in to_answer { - let _ignore_canceld_requester = tx.send(Ok(())); + let _ignore_canceled_requester = tx.send(Ok(())); } } } diff --git a/crates/brain/src/system/lamps/lamp.rs b/crates/brain/src/system/lamps/lamp.rs index 0b03f095..a3c477a2 100644 --- a/crates/brain/src/system/lamps/lamp.rs +++ b/crates/brain/src/system/lamps/lamp.rs @@ -15,7 +15,9 @@ pub struct Lamp { impl Lamp { pub(crate) fn light_cmd(&self) -> LightCommand { - let light_cmd = LightCommand::default().with_bri(self.bri); + let mut light_cmd = LightCommand::default().with_bri(self.bri); + light_cmd.on = Some(self.on); + let light_cmd = if let Some(xy) = self.xy { light_cmd.with_xy(xy) } else if let Some(ct) = self.ct { diff --git a/crates/brain/src/system/lamps/mod.rs b/crates/brain/src/system/lamps/mod.rs index 4c49297a..bebc8925 100644 --- a/crates/brain/src/system/lamps/mod.rs +++ b/crates/brain/src/system/lamps/mod.rs @@ -30,7 +30,7 @@ async fn manage_bridge( let stream = stream.peekable(); pin_mut!(stream); loop { - let error = match eventually_consistent_bridge::CachedBridge::try_init(&ip) { + let error = match eventually_consistent_bridge::CachedBridge::try_init(&ip).await { Ok(bridge) => { eventually_consistent_bridge::process_lamp_changes(&mut stream, bridge).await } diff --git a/crates/desk-sensors/src/buttons.rs b/crates/desk-sensors/src/buttons.rs index 376bed3f..69223cb2 100644 --- a/crates/desk-sensors/src/buttons.rs +++ b/crates/desk-sensors/src/buttons.rs @@ -20,7 +20,7 @@ async fn watch_pin( use protocol::large_bedroom::desk; const DEBOUNCE: Duration = Duration::from_millis(5); - const MAX_PRESS: Duration = Duration::from_secs(5); + const MAX_PRESS: Duration = Duration::from_secs(10); // pins are pulled down to ground let mut pin = match gpiocdev_embedded_hal::tokio::InputPin::new(CHIP, offset) { From edccbe910c2a8e59a0e053a1ccb7406320e8c1d2 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 31 May 2024 15:31:42 +0200 Subject: [PATCH 112/687] adds script to try ha brain without passing in all args --- crates/brain/test.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100755 crates/brain/test.sh diff --git a/crates/brain/test.sh b/crates/brain/test.sh new file mode 100755 index 00000000..511a4787 --- /dev/null +++ b/crates/brain/test.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +SERVER="sgc" # ssh config name or full address +cmds="sudo systemctl stop brain" +ssh -t sgc "$cmds" + +RUST_LOG=reqwest::connect=info,hyper_util=info,sled=info,trace RUST_BACKTRACE=1 cargo r -- \ + --data-server 192.168.1.43:1235 \ + --mpd-ip 127.0.0.1 \ + --port 34326 \ + --hue-bridge-ip 192.168.1.11 + +cmds="sudo systemctl start brain" +ssh -t sgc "$cmds" From 8787919dba60bd38df499ca057640a8da7c29f0e Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 2 Jun 2024 17:52:45 +0200 Subject: [PATCH 113/687] switch to new hue lib --- Cargo.lock | 1047 ++++++++++++++--- crates/brain/Cargo.toml | 2 +- .../brain/src/system/lamps/bridge_connect.rs | 46 +- .../lamps/eventually_consistent_bridge.rs | 6 +- crates/brain/src/system/lamps/lamp.rs | 18 +- crates/brain/src/system/lamps/mod.rs | 5 +- 6 files changed, 939 insertions(+), 185 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4a73b5ec..babf75b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", "version_check", "zerocopy", @@ -108,6 +108,216 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "async-attributes" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite 0.2.14", +] + +[[package]] +name = "async-executor" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8828ec6e544c02b0d6691d21ed9f9218d0384a82542855073c2a3f58304aaf0" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand 2.1.0", + "futures-lite 2.3.0", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.3.1", + "async-executor", + "async-io 2.3.3", + "async-lock 3.4.0", + "blocking", + "futures-lite 2.3.0", + "once_cell", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "cfg-if 1.0.0", + "concurrent-queue", + "futures-lite 1.13.0", + "log", + "parking", + "polling 2.8.0", + "rustix 0.37.27", + "slab", + "socket2 0.4.10", + "waker-fn", +] + +[[package]] +name = "async-io" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" +dependencies = [ + "async-lock 3.4.0", + "cfg-if 1.0.0", + "concurrent-queue", + "futures-io", + "futures-lite 2.3.0", + "parking", + "polling 3.7.1", + "rustix 0.38.34", + "slab", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener 5.3.1", + "event-listener-strategy", + "pin-project-lite 0.2.14", +] + +[[package]] +name = "async-process" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +dependencies = [ + "async-io 1.13.0", + "async-lock 2.8.0", + "async-signal", + "blocking", + "cfg-if 1.0.0", + "event-listener 3.1.0", + "futures-lite 1.13.0", + "rustix 0.38.34", + "windows-sys 0.48.0", +] + +[[package]] +name = "async-signal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "329972aa325176e89114919f2a80fdae4f4c040f66a370b1a1159c6c0f94e7aa" +dependencies = [ + "async-io 2.3.3", + "async-lock 3.4.0", + "atomic-waker", + "cfg-if 1.0.0", + "futures-core", + "futures-io", + "rustix 0.38.34", + "signal-hook-registry", + "slab", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-attributes", + "async-channel 1.9.0", + "async-global-executor", + "async-io 1.13.0", + "async-lock 2.8.0", + "async-process", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite 1.13.0", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite 0.2.14", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-stream" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22068c0c19514942eefcfd4daf8976ef1aad84e61539f95cd200c35202f80af5" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25f9db3b38af870bf7e5cc649167533b493928e50744e2c30ae350230b414670" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + [[package]] name = "async-trait" version = "0.1.80" @@ -128,6 +338,12 @@ dependencies = [ "critical-section", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.3.0" @@ -142,23 +358,23 @@ checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", "axum-core", - "bytes", + "bytes 1.6.0", "futures-util", - "http", - "http-body", + "http 1.1.0", + "http-body 1.0.0", "http-body-util", - "hyper", + "hyper 1.3.1", "hyper-util", - "itoa", + "itoa 1.0.11", "matchit", "memchr", "mime", "percent-encoding", - "pin-project-lite", + "pin-project-lite 0.2.14", "rustversion", "serde", "sync_wrapper 1.0.1", - "tokio", + "tokio 1.38.0", "tower", "tower-layer", "tower-service", @@ -171,13 +387,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" dependencies = [ "async-trait", - "bytes", + "bytes 1.6.0", "futures-util", - "http", - "http-body", + "http 1.1.0", + "http-body 1.0.0", "http-body-util", "mime", - "pin-project-lite", + "pin-project-lite 0.2.14", "rustversion", "sync_wrapper 0.1.2", "tower-layer", @@ -204,7 +420,7 @@ checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object", @@ -222,9 +438,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.22.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "bincode" @@ -277,6 +493,19 @@ dependencies = [ "wyz", ] +[[package]] +name = "blocking" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +dependencies = [ + "async-channel 2.3.1", + "async-task", + "futures-io", + "futures-lite 2.3.0", + "piper", +] + [[package]] name = "bme280" version = "0.5.1" @@ -312,15 +541,15 @@ dependencies = [ "axum-macros", "bincode", "byteorder", - "bytes", + "bytes 1.6.0", "chrono", "clap", "data-server", "futures", "futures-concurrency", "futures-util", + "hueclient", "mpd", - "philipshue", "protocol", "rand", "serde", @@ -329,7 +558,7 @@ dependencies = [ "strum", "thiserror", "time", - "tokio", + "tokio 1.38.0", "tracing", "tracing-journald", "tracing-subscriber", @@ -366,6 +595,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" + [[package]] name = "bytes" version = "1.6.0" @@ -399,6 +634,12 @@ version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -512,12 +753,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" dependencies = [ "castaway", - "cfg-if", - "itoa", + "cfg-if 1.0.0", + "itoa 1.0.11", "ryu", "static_assertions", ] +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "const_fn" version = "0.4.10" @@ -609,7 +859,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -642,11 +892,11 @@ dependencies = [ "bitflags 2.5.0", "crossterm_winapi", "libc", - "mio", + "mio 0.8.11", "parking_lot 0.12.3", "signal-hook", "signal-hook-mio", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -655,7 +905,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -666,7 +916,7 @@ dependencies = [ "color-eyre", "protocol", "thiserror", - "tokio", + "tokio 1.38.0", "tokio-stream", "tracing", "tracing-error", @@ -738,12 +988,22 @@ dependencies = [ "gpiocdev-embedded-hal", "linux-embedded-hal", "protocol", - "tokio", + "tokio 1.38.0", "tracing", "tracing-error", "tracing-subscriber", ] +[[package]] +name = "dns-parser" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" +dependencies = [ + "byteorder", + "quick-error", +] + [[package]] name = "document-features" version = "0.2.8" @@ -807,7 +1067,7 @@ checksum = "32bc0257b5ade13a1b93e8b9949268f44d57e8ce03e599ef1c5a62024a0fbff9" dependencies = [ "bit_field", "bxcan", - "cfg-if", + "cfg-if 1.0.0", "cortex-m", "cortex-m-rt", "critical-section", @@ -843,7 +1103,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd938f25c0798db4280fcd8026bf4c2f48789aebf8f77b6e5cf8a7693ba114ec" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "critical-section", "embedded-io-async", "futures-util", @@ -856,7 +1116,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9c844070d9f80dc66ee739299183312baee2e1cdeb6e90b4ea2af44f4676da5" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "critical-section", "document-features", "embassy-time-driver", @@ -968,6 +1228,15 @@ dependencies = [ "embedded-storage", ] +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -975,12 +1244,65 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] -name = "error-chain" -version = "0.11.0" +name = "err-derive" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" +checksum = "22deed3a8124cff5fa835713fa105621e43bbdc46690c3a6b68328a012d350d4" dependencies = [ - "backtrace", + "proc-macro-error", + "proc-macro2", + "quote", + "rustversion", + "syn 1.0.109", + "synstructure", +] + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite 0.2.14", +] + +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite 0.2.14", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener 5.3.1", + "pin-project-lite 0.2.14", ] [[package]] @@ -1002,6 +1324,12 @@ dependencies = [ "instant", ] +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + [[package]] name = "fnv" version = "1.0.7" @@ -1024,9 +1352,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", +] + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags 1.3.2", + "fuchsia-zircon-sys", ] +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + [[package]] name = "funty" version = "2.0.0" @@ -1066,7 +1410,7 @@ checksum = "51ee14e256b9143bfafbf2fddeede6f396650bacf95d06fc1b3f2b503df129a0" dependencies = [ "bitvec", "futures-core", - "futures-lite", + "futures-lite 1.13.0", "pin-project", "slab", "smallvec", @@ -1101,15 +1445,28 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ - "fastrand", + "fastrand 1.9.0", "futures-core", "futures-io", "memchr", "parking", - "pin-project-lite", + "pin-project-lite 0.2.14", "waker-fn", ] +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand 2.1.0", + "futures-core", + "futures-io", + "parking", + "pin-project-lite 0.2.14", +] + [[package]] name = "futures-macro" version = "0.3.30" @@ -1146,7 +1503,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite", + "pin-project-lite 0.2.14", "pin-utils", "slab", ] @@ -1166,7 +1523,7 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi", ] @@ -1177,6 +1534,18 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "gpio-cdev" version = "0.6.0" @@ -1197,7 +1566,7 @@ dependencies = [ "futures", "gpiocdev-uapi", "thiserror", - "tokio", + "tokio 1.38.0", "tokio-stream", ] @@ -1225,6 +1594,26 @@ dependencies = [ "thiserror", ] +[[package]] +name = "h2" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535" +dependencies = [ + "bytes 0.5.6", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 1.9.3", + "slab", + "tokio 0.2.25", + "tokio-util", + "tracing", + "tracing-futures", +] + [[package]] name = "hash32" version = "0.2.1" @@ -1243,6 +1632,12 @@ dependencies = [ "byteorder", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.5" @@ -1305,15 +1700,36 @@ dependencies = [ "thiserror", ] +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes 1.6.0", + "fnv", + "itoa 1.0.11", +] + [[package]] name = "http" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ - "bytes", + "bytes 1.6.0", "fnv", - "itoa", + "itoa 1.0.11", +] + +[[package]] +name = "http-body" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" +dependencies = [ + "bytes 0.5.6", + "http 0.2.12", ] [[package]] @@ -1322,53 +1738,98 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ - "bytes", - "http", + "bytes 1.6.0", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes 1.6.0", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", + "pin-project-lite 0.2.14", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hueclient" +version = "0.4.3" +source = "git+https://github.com/dvdsk/hue.rs#e668d4a1050a3d45117bfcaf5fea4579d7ec1e34" +dependencies = [ + "futures", + "futures-util", + "mdns", + "regex", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tokio 1.38.0", ] [[package]] -name = "http-body-util" -version = "0.1.1" +name = "hyper" +version = "0.13.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "8a6f157065790a3ed2f88679250419b5cdd96e714a0d65f7797fd337186e96bb" dependencies = [ - "bytes", + "bytes 0.5.6", + "futures-channel", "futures-core", - "http", - "http-body", - "pin-project-lite", + "futures-util", + "h2", + "http 0.2.12", + "http-body 0.3.1", + "httparse", + "httpdate 0.3.2", + "itoa 0.4.8", + "pin-project", + "socket2 0.3.19", + "tokio 0.2.25", + "tower-service", + "tracing", + "want", ] -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - [[package]] name = "hyper" version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ - "bytes", + "bytes 1.6.0", "futures-channel", "futures-util", - "http", - "http-body", + "http 1.1.0", + "http-body 1.0.0", "httparse", - "httpdate", - "itoa", - "pin-project-lite", + "httpdate 1.0.3", + "itoa 1.0.11", + "pin-project-lite 0.2.14", "smallvec", - "tokio", - "want", + "tokio 1.38.0", ] [[package]] @@ -1377,18 +1838,13 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" dependencies = [ - "bytes", - "futures-channel", + "bytes 1.6.0", "futures-util", - "http", - "http-body", - "hyper", - "pin-project-lite", - "socket2", - "tokio", - "tower", - "tower-service", - "tracing", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.3.1", + "pin-project-lite 0.2.14", + "tokio 1.38.0", ] [[package]] @@ -1442,6 +1898,16 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + [[package]] name = "indexmap" version = "2.2.6" @@ -1449,7 +1915,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -1458,7 +1924,7 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1471,12 +1937,32 @@ dependencies = [ "mach2", ] +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "ioctl-sys" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bd11f3a29434026f5ff98c730b668ba74b1033637b8817940b54d040696133c" +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + [[package]] name = "ipnet" version = "2.9.0" @@ -1498,6 +1984,12 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + [[package]] name = "itoa" version = "1.0.11" @@ -1513,6 +2005,25 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1543,6 +2054,18 @@ dependencies = [ "sysfs_gpio", ] +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + [[package]] name = "litrs" version = "0.4.1" @@ -1564,6 +2087,9 @@ name = "log" version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +dependencies = [ + "value-bag", +] [[package]] name = "lru" @@ -1571,7 +2097,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" dependencies = [ - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -1623,6 +2149,22 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "mdns" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c769962ac75a6ea437f0922b27834bcccd4c013d591383a16ae5731e3ef0f3f3" +dependencies = [ + "async-std", + "async-stream", + "dns-parser", + "err-derive", + "futures-core", + "futures-util", + "log", + "net2", +] + [[package]] name = "memchr" version = "2.7.2" @@ -1666,6 +2208,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "miniz_oxide" version = "0.7.3" @@ -1675,6 +2227,25 @@ dependencies = [ "adler", ] +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + [[package]] name = "mio" version = "0.8.11" @@ -1687,6 +2258,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + [[package]] name = "mpd" version = "0.1.0" @@ -1711,6 +2294,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" +[[package]] +name = "net2" +version = "0.2.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + [[package]] name = "nix" version = "0.23.2" @@ -1719,7 +2313,7 @@ checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" dependencies = [ "bitflags 1.3.2", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "memoffset 0.6.5", ] @@ -1731,7 +2325,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", - "cfg-if", + "cfg-if 1.0.0", "libc", "memoffset 0.7.1", "pin-utils", @@ -1744,7 +2338,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ "bitflags 2.5.0", - "cfg-if", + "cfg-if 1.0.0", "libc", ] @@ -1755,7 +2349,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ "bitflags 2.5.0", - "cfg-if", + "cfg-if 1.0.0", "cfg_aliases", "libc", ] @@ -1767,7 +2361,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ "overload", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1855,12 +2449,12 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "instant", "libc", "redox_syscall 0.2.16", "smallvec", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1869,7 +2463,7 @@ version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall 0.5.1", "smallvec", @@ -1888,18 +2482,6 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "philipshue" -version = "0.3.3" -source = "git+https://github.com/dvdsk/philipshue?branch=master#328fda7ad085fefe5d3f23d205414d803c6aa69e" -dependencies = [ - "error-chain", - "reqwest", - "serde", - "serde_derive", - "serde_json", -] - [[package]] name = "pin-project" version = "1.1.5" @@ -1920,6 +2502,12 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "pin-project-lite" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -1932,6 +2520,48 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" +dependencies = [ + "atomic-waker", + "fastrand 2.1.0", + "futures-io", +] + +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if 1.0.0", + "concurrent-queue", + "libc", + "log", + "pin-project-lite 0.2.14", + "windows-sys 0.48.0", +] + +[[package]] +name = "polling" +version = "3.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6a007746f34ed64099e88783b0ae369eaa3da6392868ba262e2af9b8fbaea1" +dependencies = [ + "cfg-if 1.0.0", + "concurrent-queue", + "hermit-abi", + "pin-project-lite 0.2.14", + "rustix 0.38.34", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "postcard" version = "1.0.8" @@ -2039,6 +2669,12 @@ dependencies = [ "unicase", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quote" version = "1.0.36" @@ -2168,32 +2804,30 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" -version = "0.12.4" +version = "0.10.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +checksum = "0718f81a8e14c4dbb3b34cf23dc6aaf9ab8a0dfec160c534b3dbca1aaa21f47c" dependencies = [ "base64", - "bytes", + "bytes 0.5.6", + "encoding_rs", "futures-core", "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-util", + "http 0.2.12", + "http-body 0.3.1", + "hyper 0.13.10", "ipnet", "js-sys", + "lazy_static", "log", "mime", - "once_cell", + "mime_guess", "percent-encoding", - "pin-project-lite", + "pin-project-lite 0.2.14", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 0.1.2", - "tokio", - "tower-service", + "tokio 0.2.25", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -2225,6 +2859,33 @@ dependencies = [ "semver 1.0.23", ] +[[package]] +name = "rustix" +version = "0.37.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys 0.4.14", + "windows-sys 0.52.0", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -2312,7 +2973,7 @@ version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ - "itoa", + "itoa 1.0.11", "ryu", "serde", ] @@ -2324,7 +2985,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa", + "itoa 1.0.11", "ryu", "serde", ] @@ -2335,8 +2996,8 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap", - "itoa", + "indexmap 2.2.6", + "itoa 1.0.11", "ryu", "serde", "unsafe-libyaml", @@ -2349,7 +3010,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f5a15d0be940df84846264b09b51b10b931fb2f275becb80934e3568a016828" dependencies = [ "bitflags 2.5.0", - "cfg-if", + "cfg-if 1.0.0", "core-foundation-sys", "io-kit-sys", "mach2", @@ -2357,7 +3018,7 @@ dependencies = [ "regex", "scopeguard", "unescaper", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2399,7 +3060,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" dependencies = [ "libc", - "mio", + "mio 0.8.11", "signal-hook", ] @@ -2443,6 +3104,27 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "socket2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "socket2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +dependencies = [ + "libc", + "winapi 0.3.9", +] + [[package]] name = "socket2" version = "0.5.7" @@ -2590,6 +3272,18 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + [[package]] name = "sysfs_gpio" version = "0.6.2" @@ -2631,7 +3325,7 @@ version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", ] @@ -2680,6 +3374,23 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tokio" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092" +dependencies = [ + "bytes 0.5.6", + "fnv", + "futures-core", + "iovec", + "lazy_static", + "memchr", + "mio 0.6.23", + "pin-project-lite 0.1.12", + "slab", +] + [[package]] name = "tokio" version = "1.38.0" @@ -2687,14 +3398,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", - "bytes", + "bytes 1.6.0", "libc", - "mio", + "mio 0.8.11", "num_cpus", "parking_lot 0.12.3", - "pin-project-lite", + "pin-project-lite 0.2.14", "signal-hook-registry", - "socket2", + "socket2 0.5.7", "tokio-macros", "windows-sys 0.48.0", ] @@ -2717,8 +3428,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", - "pin-project-lite", - "tokio", + "pin-project-lite 0.2.14", + "tokio 1.38.0", +] + +[[package]] +name = "tokio-util" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" +dependencies = [ + "bytes 0.5.6", + "futures-core", + "futures-sink", + "log", + "pin-project-lite 0.1.12", + "tokio 0.2.25", ] [[package]] @@ -2730,8 +3455,8 @@ dependencies = [ "futures-core", "futures-util", "pin-project", - "pin-project-lite", - "tokio", + "pin-project-lite 0.2.14", + "tokio 1.38.0", "tower-layer", "tower-service", ] @@ -2754,7 +3479,8 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "pin-project-lite", + "log", + "pin-project-lite 0.2.14", "tracing-attributes", "tracing-core", ] @@ -2790,6 +3516,16 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + [[package]] name = "tracing-journald" version = "0.3.0" @@ -2950,6 +3686,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "value-bag" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" + [[package]] name = "vcell" version = "0.1.3" @@ -3004,7 +3746,9 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", + "serde", + "serde_json", "wasm-bindgen-macro", ] @@ -3029,7 +3773,7 @@ version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -3074,6 +3818,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -3084,6 +3834,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -3246,12 +4002,21 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winreg" -version = "0.52.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" dependencies = [ - "cfg-if", - "windows-sys 0.48.0", + "winapi 0.3.9", +] + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", ] [[package]] diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index fa82b2a7..090cc4d4 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -15,7 +15,7 @@ tokio = { version = "1", features = ["full"] } axum = { version = "0.7.4", default-features = false, features = ["tokio", "http1"] } axum-macros = "0.4.1" -philipshue = { git = "https://github.com/dvdsk/philipshue", branch = "master", default-features = false } +hueclient = { git = "https://github.com/dvdsk/hue.rs"} serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.9" diff --git a/crates/brain/src/system/lamps/bridge_connect.rs b/crates/brain/src/system/lamps/bridge_connect.rs index 527ee8cf..e63408af 100644 --- a/crates/brain/src/system/lamps/bridge_connect.rs +++ b/crates/brain/src/system/lamps/bridge_connect.rs @@ -1,38 +1,32 @@ -use philipshue::bridge; -use philipshue::bridge::Bridge; -use philipshue::errors::{BridgeError::LinkButtonNotPressed, HueError, HueErrorKind}; +use hueclient::Bridge; +use hueclient::HueError; use tracing::{error, info}; use super::Error; -use std::collections::BTreeMap; use std::fs::File; +use std::net::IpAddr; use std::path::Path; use std::time::Duration; #[derive(Debug, thiserror::Error)] pub enum RegisterError { #[error("Something went wrong registering the user inside the hue library")] - HueError(philipshue::errors::HueError), + HueError(hueclient::HueError), #[error("Link button was not pressed within 25 seconds")] Timedout, } -async fn register(ip: &str) -> Result { +async fn register(ip: IpAddr) -> Result { for _ in 0..5 { //try 5 times to connect - match bridge::register_user(ip, "homeAutomationSys").await { - Ok(received_login) => { + let bridge = Bridge::for_ip(ip); + match bridge.register_user("ha-brain").await { + Ok(bridge) => { println!("Success, linked to bridge"); - info!("User registered: {}, on IP: {}", &received_login, ip); - return Ok(received_login); + info!("User registered: {}, on IP: {ip:?}", bridge.username); + return Ok(bridge); } - Err(HueError( - HueErrorKind::BridgeError { - error: LinkButtonNotPressed, - .. - }, - _, - )) => { + Err(HueError::BridgeError { code: 101, .. }) => { println!("Please, press the link on the bridge. Retrying in 5 seconds"); tokio::time::sleep(Duration::from_secs(5)).await; } @@ -67,7 +61,7 @@ pub enum SaveBridgeError { #[error("Error writing bridge logins to file: {0}")] Writing(serde_yaml::Error), } -fn update_saved_bridge_info(bridge_ip: &str, login: &str) -> Result<(), SaveBridgeError> { +fn update_saved_bridge_info(bridge_ip: IpAddr, login: &str) -> Result<(), SaveBridgeError> { let path = Path::new("hueBridgeLogin"); let file = File::create(&path).map_err(|err| SaveBridgeError::CreatingFile { err, path })?; serde_yaml::to_writer(file, &(bridge_ip, login)).map_err(SaveBridgeError::Writing) @@ -75,12 +69,12 @@ fn update_saved_bridge_info(bridge_ip: &str, login: &str) -> Result<(), SaveBrid pub async fn get_bridge_and_status( ip: &str, -) -> Result<(Bridge, BTreeMap), Error> { +) -> Result<(Bridge, Vec), Error> { + let ip: IpAddr = ip.parse().expect("string should be an ip"); let Ok((ip, login)) = saved_bridge_info() else { - let login = register(&ip).await?; - update_saved_bridge_info(ip, &login)?; + let bridge = register(ip.clone()).await?; + update_saved_bridge_info(ip.clone(), &bridge.username)?; - let bridge = Bridge::new(ip, &login); let lights_info = bridge .get_all_lights() .await @@ -88,16 +82,16 @@ pub async fn get_bridge_and_status( return Ok((bridge, lights_info)); }; - let bridge = Bridge::new(&ip, &login); + let ip: IpAddr = ip.parse().expect("string should be an ip"); + let bridge = Bridge::for_ip(ip).with_user(login); let res = bridge.get_all_lights().await; match res { Ok(lights_info) => Ok((bridge, lights_info)), Err(_) => { - let login = register(&ip).await?; - update_saved_bridge_info(&ip, &login)?; + let bridge = register(ip.clone()).await?; + update_saved_bridge_info(ip.clone(), &bridge.username)?; - let bridge = Bridge::new(&ip, &login); let lights_info = bridge .get_all_lights() .await diff --git a/crates/brain/src/system/lamps/eventually_consistent_bridge.rs b/crates/brain/src/system/lamps/eventually_consistent_bridge.rs index 93d05692..2f85ed31 100644 --- a/crates/brain/src/system/lamps/eventually_consistent_bridge.rs +++ b/crates/brain/src/system/lamps/eventually_consistent_bridge.rs @@ -10,7 +10,7 @@ use tokio::sync::oneshot; use tokio::time::{timeout, timeout_at}; use tracing::{error, warn}; -use philipshue::bridge::Bridge; +use hueclient::Bridge; #[derive(Debug)] pub(crate) enum Change { @@ -57,11 +57,11 @@ impl CachedBridge { let (bridge, lights_info) = bridge_connect::get_bridge_and_status(ip).await?; let state: HashMap = lights_info .iter() - .map(|(id, light)| (*id, Lamp::from(&light.state))) + .map(|light| (light.id, Lamp::from(&light.light.state))) .collect(); let lookup = lights_info .into_iter() - .map(|(id, light)| (light.name, id)) + .map(|light| (light.light.name, light.id)) .collect(); Ok(Self { diff --git a/crates/brain/src/system/lamps/lamp.rs b/crates/brain/src/system/lamps/lamp.rs index a3c477a2..513f92ea 100644 --- a/crates/brain/src/system/lamps/lamp.rs +++ b/crates/brain/src/system/lamps/lamp.rs @@ -1,4 +1,4 @@ -use philipshue::LightCommand; +use hueclient::{CommandLight, LightState}; //adaptation from philipshue LightState that adds some //values and removes unused @@ -10,16 +10,15 @@ pub struct Lamp { pub sat: Option, pub xy: Option<(f32, f32)>, pub ct: Option, - pub reachable: bool, } impl Lamp { - pub(crate) fn light_cmd(&self) -> LightCommand { - let mut light_cmd = LightCommand::default().with_bri(self.bri); + pub(crate) fn light_cmd(&self) -> CommandLight { + let mut light_cmd = CommandLight::default().with_bri(self.bri); light_cmd.on = Some(self.on); - let light_cmd = if let Some(xy) = self.xy { - light_cmd.with_xy(xy) + let light_cmd = if let Some((x, y)) = self.xy { + light_cmd.with_xy(x, y) } else if let Some(ct) = self.ct { light_cmd.with_ct(ct) } else { @@ -29,16 +28,15 @@ impl Lamp { } } -impl From<&philipshue::hue::LightState> for Lamp { - fn from(state: &philipshue::hue::LightState) -> Self { +impl From<&LightState> for Lamp { + fn from(state: &LightState) -> Self { Lamp { on: state.on, - bri: state.bri, + bri: state.bri.unwrap_or(0), hue: state.hue, sat: state.sat, xy: state.xy, ct: state.ct, - reachable: state.reachable, } } } diff --git a/crates/brain/src/system/lamps/mod.rs b/crates/brain/src/system/lamps/mod.rs index bebc8925..525c3883 100644 --- a/crates/brain/src/system/lamps/mod.rs +++ b/crates/brain/src/system/lamps/mod.rs @@ -1,6 +1,3 @@ -extern crate philipshue; -extern crate serde_yaml; - use futures_util::{pin_mut, stream, StreamExt}; use tokio::sync::{mpsc, oneshot}; use tracing::error; @@ -53,7 +50,7 @@ pub struct Lighting { #[derive(thiserror::Error, Debug)] pub enum Error { #[error("Could not get lights from bridge")] - GettingLights(philipshue::errors::HueError), + GettingLights(hueclient::HueError), #[error("Failed to register on bridge")] Register(#[from] bridge_connect::RegisterError), #[error("Something went wrong saving bridge account to disk: {0}")] From 3ed1999ee4a1b5a8f0540b8f2644aad333e03983 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 2 Jun 2024 22:55:31 +0200 Subject: [PATCH 114/687] rate limit hue api calls --- Cargo.lock | 468 ++++-------------- .../lamps/eventually_consistent_bridge.rs | 12 +- 2 files changed, 116 insertions(+), 364 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index babf75b4..060e06b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -138,7 +138,7 @@ dependencies = [ "concurrent-queue", "event-listener-strategy", "futures-core", - "pin-project-lite 0.2.14", + "pin-project-lite", ] [[package]] @@ -225,7 +225,7 @@ checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ "event-listener 5.3.1", "event-listener-strategy", - "pin-project-lite 0.2.14", + "pin-project-lite", ] [[package]] @@ -285,7 +285,7 @@ dependencies = [ "log", "memchr", "once_cell", - "pin-project-lite 0.2.14", + "pin-project-lite", "pin-utils", "slab", "wasm-bindgen-futures", @@ -358,23 +358,23 @@ checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", "axum-core", - "bytes 1.6.0", + "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "http", + "http-body", "http-body-util", - "hyper 1.3.1", + "hyper", "hyper-util", - "itoa 1.0.11", + "itoa", "matchit", "memchr", "mime", "percent-encoding", - "pin-project-lite 0.2.14", + "pin-project-lite", "rustversion", "serde", "sync_wrapper 1.0.1", - "tokio 1.38.0", + "tokio", "tower", "tower-layer", "tower-service", @@ -387,13 +387,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" dependencies = [ "async-trait", - "bytes 1.6.0", + "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "http", + "http-body", "http-body-util", "mime", - "pin-project-lite 0.2.14", + "pin-project-lite", "rustversion", "sync_wrapper 0.1.2", "tower-layer", @@ -438,9 +438,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.13.1" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bincode" @@ -541,7 +541,7 @@ dependencies = [ "axum-macros", "bincode", "byteorder", - "bytes 1.6.0", + "bytes", "chrono", "clap", "data-server", @@ -558,7 +558,7 @@ dependencies = [ "strum", "thiserror", "time", - "tokio 1.38.0", + "tokio", "tracing", "tracing-journald", "tracing-subscriber", @@ -595,12 +595,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" -[[package]] -name = "bytes" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" - [[package]] name = "bytes" version = "1.6.0" @@ -754,7 +748,7 @@ checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" dependencies = [ "castaway", "cfg-if 1.0.0", - "itoa 1.0.11", + "itoa", "ryu", "static_assertions", ] @@ -892,11 +886,11 @@ dependencies = [ "bitflags 2.5.0", "crossterm_winapi", "libc", - "mio 0.8.11", + "mio", "parking_lot 0.12.3", "signal-hook", "signal-hook-mio", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -905,7 +899,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -916,7 +910,7 @@ dependencies = [ "color-eyre", "protocol", "thiserror", - "tokio 1.38.0", + "tokio", "tokio-stream", "tracing", "tracing-error", @@ -988,7 +982,7 @@ dependencies = [ "gpiocdev-embedded-hal", "linux-embedded-hal", "protocol", - "tokio 1.38.0", + "tokio", "tracing", "tracing-error", "tracing-subscriber", @@ -1228,15 +1222,6 @@ dependencies = [ "embedded-storage", ] -[[package]] -name = "encoding_rs" -version = "0.8.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" -dependencies = [ - "cfg-if 1.0.0", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -1281,7 +1266,7 @@ checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" dependencies = [ "concurrent-queue", "parking", - "pin-project-lite 0.2.14", + "pin-project-lite", ] [[package]] @@ -1292,7 +1277,7 @@ checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ "concurrent-queue", "parking", - "pin-project-lite 0.2.14", + "pin-project-lite", ] [[package]] @@ -1302,7 +1287,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ "event-listener 5.3.1", - "pin-project-lite 0.2.14", + "pin-project-lite", ] [[package]] @@ -1352,25 +1337,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags 1.3.2", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - [[package]] name = "funty" version = "2.0.0" @@ -1450,7 +1419,7 @@ dependencies = [ "futures-io", "memchr", "parking", - "pin-project-lite 0.2.14", + "pin-project-lite", "waker-fn", ] @@ -1464,7 +1433,7 @@ dependencies = [ "futures-core", "futures-io", "parking", - "pin-project-lite 0.2.14", + "pin-project-lite", ] [[package]] @@ -1503,7 +1472,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.14", + "pin-project-lite", "pin-utils", "slab", ] @@ -1566,7 +1535,7 @@ dependencies = [ "futures", "gpiocdev-uapi", "thiserror", - "tokio 1.38.0", + "tokio", "tokio-stream", ] @@ -1594,26 +1563,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "h2" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535" -dependencies = [ - "bytes 0.5.6", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 1.9.3", - "slab", - "tokio 0.2.25", - "tokio-util", - "tracing", - "tracing-futures", -] - [[package]] name = "hash32" version = "0.2.1" @@ -1632,12 +1581,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "hashbrown" version = "0.14.5" @@ -1700,36 +1643,15 @@ dependencies = [ "thiserror", ] -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes 1.6.0", - "fnv", - "itoa 1.0.11", -] - [[package]] name = "http" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ - "bytes 1.6.0", + "bytes", "fnv", - "itoa 1.0.11", -] - -[[package]] -name = "http-body" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" -dependencies = [ - "bytes 0.5.6", - "http 0.2.12", + "itoa", ] [[package]] @@ -1738,8 +1660,8 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ - "bytes 1.6.0", - "http 1.1.0", + "bytes", + "http", ] [[package]] @@ -1748,11 +1670,11 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" dependencies = [ - "bytes 1.6.0", + "bytes", "futures-core", - "http 1.1.0", - "http-body 1.0.0", - "pin-project-lite 0.2.14", + "http", + "http-body", + "pin-project-lite", ] [[package]] @@ -1761,12 +1683,6 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" -[[package]] -name = "httpdate" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" - [[package]] name = "httpdate" version = "1.0.3" @@ -1776,7 +1692,7 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hueclient" version = "0.4.3" -source = "git+https://github.com/dvdsk/hue.rs#e668d4a1050a3d45117bfcaf5fea4579d7ec1e34" +source = "git+https://github.com/dvdsk/hue.rs#fd3096d4c16c38c663cc325738ef63dc55c09f19" dependencies = [ "futures", "futures-util", @@ -1786,31 +1702,7 @@ dependencies = [ "serde", "serde_json", "thiserror", - "tokio 1.38.0", -] - -[[package]] -name = "hyper" -version = "0.13.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a6f157065790a3ed2f88679250419b5cdd96e714a0d65f7797fd337186e96bb" -dependencies = [ - "bytes 0.5.6", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http 0.2.12", - "http-body 0.3.1", - "httparse", - "httpdate 0.3.2", - "itoa 0.4.8", - "pin-project", - "socket2 0.3.19", - "tokio 0.2.25", - "tower-service", - "tracing", - "want", + "tokio", ] [[package]] @@ -1819,17 +1711,18 @@ version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ - "bytes 1.6.0", + "bytes", "futures-channel", "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "http", + "http-body", "httparse", - "httpdate 1.0.3", - "itoa 1.0.11", - "pin-project-lite 0.2.14", + "httpdate", + "itoa", + "pin-project-lite", "smallvec", - "tokio 1.38.0", + "tokio", + "want", ] [[package]] @@ -1838,13 +1731,18 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" dependencies = [ - "bytes 1.6.0", + "bytes", + "futures-channel", "futures-util", - "http 1.1.0", - "http-body 1.0.0", - "hyper 1.3.1", - "pin-project-lite 0.2.14", - "tokio 1.38.0", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2 0.5.7", + "tokio", + "tower", + "tower-service", + "tracing", ] [[package]] @@ -1898,16 +1796,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - [[package]] name = "indexmap" version = "2.2.6" @@ -1915,7 +1803,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown", ] [[package]] @@ -1954,15 +1842,6 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bd11f3a29434026f5ff98c730b668ba74b1033637b8817940b54d040696133c" -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - [[package]] name = "ipnet" version = "2.9.0" @@ -1984,12 +1863,6 @@ dependencies = [ "either", ] -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - [[package]] name = "itoa" version = "1.0.11" @@ -2005,16 +1878,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "kv-log-macro" version = "1.0.7" @@ -2097,7 +1960,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" dependencies = [ - "hashbrown 0.14.5", + "hashbrown", ] [[package]] @@ -2208,16 +2071,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "mime_guess" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" -dependencies = [ - "mime", - "unicase", -] - [[package]] name = "miniz_oxide" version = "0.7.3" @@ -2227,25 +2080,6 @@ dependencies = [ "adler", ] -[[package]] -name = "mio" -version = "0.6.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" -dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log", - "miow", - "net2", - "slab", - "winapi 0.2.8", -] - [[package]] name = "mio" version = "0.8.11" @@ -2258,18 +2092,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] - [[package]] name = "mpd" version = "0.1.0" @@ -2302,7 +2124,7 @@ checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" dependencies = [ "cfg-if 0.1.10", "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2361,7 +2183,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ "overload", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2454,7 +2276,7 @@ dependencies = [ "libc", "redox_syscall 0.2.16", "smallvec", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2502,12 +2324,6 @@ dependencies = [ "syn 2.0.66", ] -[[package]] -name = "pin-project-lite" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" - [[package]] name = "pin-project-lite" version = "0.2.14" @@ -2543,7 +2359,7 @@ dependencies = [ "concurrent-queue", "libc", "log", - "pin-project-lite 0.2.14", + "pin-project-lite", "windows-sys 0.48.0", ] @@ -2556,7 +2372,7 @@ dependencies = [ "cfg-if 1.0.0", "concurrent-queue", "hermit-abi", - "pin-project-lite 0.2.14", + "pin-project-lite", "rustix 0.38.34", "tracing", "windows-sys 0.52.0", @@ -2625,9 +2441,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.84" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] @@ -2804,30 +2620,32 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" -version = "0.10.10" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0718f81a8e14c4dbb3b34cf23dc6aaf9ab8a0dfec160c534b3dbca1aaa21f47c" +checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ "base64", - "bytes 0.5.6", - "encoding_rs", + "bytes", "futures-core", "futures-util", - "http 0.2.12", - "http-body 0.3.1", - "hyper 0.13.10", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", "ipnet", "js-sys", - "lazy_static", "log", "mime", - "mime_guess", + "once_cell", "percent-encoding", - "pin-project-lite 0.2.14", + "pin-project-lite", "serde", "serde_json", "serde_urlencoded", - "tokio 0.2.25", + "sync_wrapper 0.1.2", + "tokio", + "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -2973,7 +2791,7 @@ version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ - "itoa 1.0.11", + "itoa", "ryu", "serde", ] @@ -2985,7 +2803,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.11", + "itoa", "ryu", "serde", ] @@ -2996,8 +2814,8 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.2.6", - "itoa 1.0.11", + "indexmap", + "itoa", "ryu", "serde", "unsafe-libyaml", @@ -3018,7 +2836,7 @@ dependencies = [ "regex", "scopeguard", "unescaper", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -3060,7 +2878,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" dependencies = [ "libc", - "mio 0.8.11", + "mio", "signal-hook", ] @@ -3104,17 +2922,6 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -[[package]] -name = "socket2" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "winapi 0.3.9", -] - [[package]] name = "socket2" version = "0.4.10" @@ -3122,7 +2929,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -3227,11 +3034,11 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +checksum = "f7993a8e3a9e88a00351486baae9522c91b123a088f76469e5bd5cc17198ea87" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", "rustversion", @@ -3374,23 +3181,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "tokio" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092" -dependencies = [ - "bytes 0.5.6", - "fnv", - "futures-core", - "iovec", - "lazy_static", - "memchr", - "mio 0.6.23", - "pin-project-lite 0.1.12", - "slab", -] - [[package]] name = "tokio" version = "1.38.0" @@ -3398,12 +3188,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", - "bytes 1.6.0", + "bytes", "libc", - "mio 0.8.11", + "mio", "num_cpus", "parking_lot 0.12.3", - "pin-project-lite 0.2.14", + "pin-project-lite", "signal-hook-registry", "socket2 0.5.7", "tokio-macros", @@ -3428,22 +3218,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", - "pin-project-lite 0.2.14", - "tokio 1.38.0", -] - -[[package]] -name = "tokio-util" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" -dependencies = [ - "bytes 0.5.6", - "futures-core", - "futures-sink", - "log", - "pin-project-lite 0.1.12", - "tokio 0.2.25", + "pin-project-lite", + "tokio", ] [[package]] @@ -3455,8 +3231,8 @@ dependencies = [ "futures-core", "futures-util", "pin-project", - "pin-project-lite 0.2.14", - "tokio 1.38.0", + "pin-project-lite", + "tokio", "tower-layer", "tower-service", ] @@ -3479,8 +3255,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "log", - "pin-project-lite 0.2.14", + "pin-project-lite", "tracing-attributes", "tracing-core", ] @@ -3516,16 +3291,6 @@ dependencies = [ "tracing-subscriber", ] -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", -] - [[package]] name = "tracing-journald" version = "0.3.0" @@ -3747,8 +3512,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if 1.0.0", - "serde", - "serde_json", "wasm-bindgen-macro", ] @@ -3818,12 +3581,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - [[package]] name = "winapi" version = "0.3.9" @@ -3834,12 +3591,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -4002,21 +3753,12 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winreg" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "ws2_32-sys" -version = "0.2.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "cfg-if 1.0.0", + "windows-sys 0.48.0", ] [[package]] diff --git a/crates/brain/src/system/lamps/eventually_consistent_bridge.rs b/crates/brain/src/system/lamps/eventually_consistent_bridge.rs index 2f85ed31..bb3b851d 100644 --- a/crates/brain/src/system/lamps/eventually_consistent_bridge.rs +++ b/crates/brain/src/system/lamps/eventually_consistent_bridge.rs @@ -44,6 +44,7 @@ pub(crate) enum Change { type LampId = usize; pub(crate) struct CachedBridge { + last_cmd_send: Instant, pub(crate) bridge: Bridge, pub(crate) needed_state: State, pub(crate) known_state: State, @@ -70,6 +71,7 @@ impl CachedBridge { known_state: state, lookup, reported_missing: HashSet::new(), + last_cmd_send: Instant::now(), }) } @@ -87,9 +89,12 @@ impl CachedBridge { }; if lamp != needed { + let next_send_possible = self.last_cmd_send + Duration::from_millis(100); + tokio::time::sleep_until(next_send_possible.into()).await; if let Err(e) = self.bridge.set_light_state(*id, &needed.light_cmd()).await { warn!("could not apply changes to lamp: {e}") } + self.last_cmd_send = Instant::now(); *lamp = needed.clone() } } @@ -99,7 +104,12 @@ impl CachedBridge { async fn push_state(&mut self) -> Result<(), Error> { for (id, lamp) in self.known_state.iter_mut() { - let _ignore_err = self.bridge.set_light_state(*id, &lamp.light_cmd()).await; + let next_send_possible = self.last_cmd_send + Duration::from_millis(100); + tokio::time::sleep_until(next_send_possible.into()).await; + if let Err(e) = self.bridge.set_light_state(*id, &lamp.light_cmd()).await { + warn!("could not apply changes to lamp: {e}") + } + self.last_cmd_send = Instant::now(); } Ok(()) } From af9dbb4fe529b372c92fa1d4aac438e8740e0ee9 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 3 Jun 2024 12:45:39 +0200 Subject: [PATCH 115/687] fix compilation for nostd --- crates/protocol/src/large_bedroom.rs | 2 ++ crates/protocol/src/large_bedroom/bed.rs | 5 ++++- crates/protocol/src/large_bedroom/desk.rs | 5 ++++- crates/protocol/src/lib.rs | 9 +++++++-- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index c1cf16f0..ba0a3371 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -1,6 +1,7 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; +#[cfg(feature = "alloc")] use crate::{all_nodes, Tomato}; pub mod bed; @@ -15,6 +16,7 @@ pub enum Reading { Desk(desk::Reading), } +#[cfg(feature = "alloc")] all_nodes! {Reading; ReadingDiscriminants; Bed, Desk} #[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 6b38b9f3..4076cbbe 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -1,5 +1,7 @@ use crate::downcast_err::{I2cError, UartError}; -use crate::{button_enum, Tomato, TomatoItem}; +#[cfg(feature = "alloc")] +use crate::{Tomato, TomatoItem}; +use crate::button_enum; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -68,6 +70,7 @@ pub enum Reading { TypicalParticleSize(f32), } +#[cfg(feature = "alloc")] impl Tomato for Reading { fn inner<'a>(&'a self) -> TomatoItem<'a> { let val = match self { diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index 398ce417..df3c41ee 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -2,7 +2,9 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; use crate::downcast_err::{GpioError, LinuxI2cError}; -use crate::{button_enum, Tomato, TomatoItem}; +#[cfg(feature = "alloc")] +use crate::{Tomato, TomatoItem}; +use crate::button_enum; button_enum! { /// No these are not borg, these are buttons on a string of cat5. @@ -29,6 +31,7 @@ pub enum Reading { Button(Button), } +#[cfg(feature = "alloc")] impl Tomato for Reading { fn inner<'a>(&'a self) -> TomatoItem<'a> { let val = match self { diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index c25b3e17..50c54690 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -1,7 +1,5 @@ #![cfg_attr(not(feature = "alloc"), no_std)] -use core::fmt; - use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -61,6 +59,7 @@ macro_rules! button_enum { } } + #[cfg(feature = "alloc")] impl crate::Tomato for $name { fn inner<'a>(&'a self) -> crate::TomatoItem<'a> { crate::TomatoItem::Leaf((*self).into()) @@ -108,13 +107,16 @@ impl Press { } } +#[cfg(feature = "alloc")] type TomatoId = u8; +#[cfg(feature = "alloc")] #[derive(Debug)] pub enum TomatoItem<'a> { Leaf(f32), Node(&'a dyn Tomato), } +#[cfg(feature = "alloc")] pub trait Tomato: fmt::Debug { fn inner<'a>(&'a self) -> TomatoItem<'a>; fn name(&self) -> String { @@ -128,6 +130,7 @@ pub trait Tomato: fmt::Debug { fn id(&self) -> TomatoId; } +#[cfg(feature = "alloc")] macro_rules! all_nodes { ($name:ident; $variant:ident; $($var:ident),*) => { impl Tomato for $name { @@ -145,7 +148,9 @@ macro_rules! all_nodes { } }; } +#[cfg(feature = "alloc")] pub(crate) use all_nodes; +#[cfg(feature = "alloc")] all_nodes! {Reading; ReadingDiscriminants; LargeBedroom} //, Test} #[derive( From 365267c757a483b9f32ad23b6a95570ec24bd1f7 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 3 Jun 2024 13:37:34 +0200 Subject: [PATCH 116/687] last work on generic errors --- Cargo.lock | 3 +-- Cargo.toml | 2 +- crates/desk-sensors/src/buttons.rs | 2 +- crates/protocol/Cargo.toml | 15 ++++++++------- crates/protocol/src/downcast_err.rs | 2 ++ crates/protocol/src/downcast_err/i2c.rs | 2 ++ 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 060e06b2..bd14ed96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -509,7 +509,7 @@ dependencies = [ [[package]] name = "bme280" version = "0.5.1" -source = "git+https://github.com/dvdsk/bme280-rs#4999b005d26a16312acb3dbc64b72658df49a16d" +source = "git+https://github.com/dvdsk/bme280-rs#a147bfc93d73a827616121f194972d6cc9cb3d11" dependencies = [ "defmt", "derive_more", @@ -2457,7 +2457,6 @@ dependencies = [ "defmt", "embassy-embedded-hal", "embassy-stm32", - "embedded-hal 1.0.0", "gpiocdev", "gpiocdev-embedded-hal", "heapless 0.8.0", diff --git a/Cargo.toml b/Cargo.toml index a15fcb1d..9e16af4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ resolver = "2" members = ["crates/*"] [workspace.package] -rust-version = "1.70" +rust-version = "1.78" edition = "2021" license = "GPLv3" authors = ["David Kleingeld & Eva van Houten"] diff --git a/crates/desk-sensors/src/buttons.rs b/crates/desk-sensors/src/buttons.rs index 69223cb2..f75ec11d 100644 --- a/crates/desk-sensors/src/buttons.rs +++ b/crates/desk-sensors/src/buttons.rs @@ -66,7 +66,7 @@ async fn watch_pin( let reading = desk::Reading::Button(button); send_reading(tx, reading); } else { - trace!("press too short, caught as bounce"); + trace!("press too short, caught as bounce: {offset}"); } } } diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index c047d430..71678396 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -27,14 +27,15 @@ bme280 = { version = "0.5", git = "https://github.com/dvdsk/bme280-rs", features # needed for bme680 error I2C type embassy-stm32 = { version = "0.1.0", features = ["stm32f401cc"] } embassy-embedded-hal = "0.1.0" -linux-embedded-hal = { version = "0.4.0", features = ["i2c"], default-features = false } -gpiocdev-embedded-hal = "0.1.1" -gpiocdev = "0.7" -nix = "0.28.0" -embedded-hal = "1.0.0" -tracing = "0.1.40" + +linux-embedded-hal = { version = "0.4.0", features = ["i2c"], default-features = false, optional = true } +gpiocdev-embedded-hal = { version = "0.1.1", optional = true } +gpiocdev = { version = "0.7.1", optional = true } +nix = { version = "0.28.0", optional = true } +tracing = { version = "0.1.40", optional = true } [features] alloc = ["postcard/alloc", "serde/std", "sht31/thiserror", "bosch-bme680/thiserror", "mhzx/thiserror", "sps30-async/thiserror", -"max44009/thiserror"] +"max44009/thiserror", "linux-embedded-hal", "gpiocdev-embedded-hal", "gpiocdev", +"nix", "tracing"] diff --git a/crates/protocol/src/downcast_err.rs b/crates/protocol/src/downcast_err.rs index ac4a987b..b1ac5c52 100644 --- a/crates/protocol/src/downcast_err.rs +++ b/crates/protocol/src/downcast_err.rs @@ -1,9 +1,11 @@ mod i2c; +// #[cfg(feature = "alloc")] mod rpi_button; mod uart; use bosch_bme680::BmeError; pub use i2c::{I2cError, LinuxI2cError}; +// #[cfg(feature = "alloc")] pub use rpi_button::GpioError; pub use uart::Error as UartError; diff --git a/crates/protocol/src/downcast_err/i2c.rs b/crates/protocol/src/downcast_err/i2c.rs index 25518e83..43fe18c8 100644 --- a/crates/protocol/src/downcast_err/i2c.rs +++ b/crates/protocol/src/downcast_err/i2c.rs @@ -80,12 +80,14 @@ impl core::fmt::Display for LinuxI2cError { } } +#[cfg(alloc)] impl From for LinuxI2cError { fn from(value: linux_embedded_hal::I2CError) -> Self { value.inner().into() } } +#[cfg(alloc)] impl From<&linux_embedded_hal::i2cdev::linux::LinuxI2CError> for LinuxI2cError { fn from(value: &linux_embedded_hal::i2cdev::linux::LinuxI2CError) -> Self { use linux_embedded_hal::i2cdev::linux::LinuxI2CError; From 67af22aa8db4295c3e5ae2a2fc894f8679b4341e Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 3 Jun 2024 14:29:54 +0200 Subject: [PATCH 117/687] replaces error types with heapless string<200> --- Cargo.lock | 2 + crates/desk-sensors/Cargo.toml | 1 + crates/desk-sensors/src/buttons.rs | 8 +- crates/desk-sensors/src/sensors.rs | 48 ++++--- crates/protocol/Cargo.toml | 2 +- crates/protocol/src/downcast_err.rs | 107 -------------- crates/protocol/src/downcast_err/i2c.rs | 102 ------------- .../protocol/src/downcast_err/rpi_button.rs | 134 ------------------ crates/protocol/src/downcast_err/uart.rs | 40 ------ crates/protocol/src/large_bedroom/bed.rs | 19 +-- crates/protocol/src/large_bedroom/desk.rs | 25 ++-- crates/protocol/src/lib.rs | 13 +- 12 files changed, 70 insertions(+), 431 deletions(-) delete mode 100644 crates/protocol/src/downcast_err.rs delete mode 100644 crates/protocol/src/downcast_err/i2c.rs delete mode 100644 crates/protocol/src/downcast_err/rpi_button.rs delete mode 100644 crates/protocol/src/downcast_err/uart.rs diff --git a/Cargo.lock b/Cargo.lock index bd14ed96..fbbb11ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -980,6 +980,7 @@ dependencies = [ "color-eyre", "embedded-hal-async", "gpiocdev-embedded-hal", + "heapless 0.8.0", "linux-embedded-hal", "protocol", "tokio", @@ -1611,6 +1612,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" dependencies = [ + "defmt", "hash32 0.3.1", "serde", "stable_deref_trait", diff --git a/crates/desk-sensors/Cargo.toml b/crates/desk-sensors/Cargo.toml index 4f64060c..99335bab 100644 --- a/crates/desk-sensors/Cargo.toml +++ b/crates/desk-sensors/Cargo.toml @@ -19,3 +19,4 @@ tracing-error = "0.2.0" protocol = { path = "../protocol", features = ["alloc"] } tokio = { version = "1.37.0", features = ["rt", "time", "macros"] } embedded-hal-async = "1.0.0" +heapless = "0.8.0" diff --git a/crates/desk-sensors/src/buttons.rs b/crates/desk-sensors/src/buttons.rs index f75ec11d..d56b23c8 100644 --- a/crates/desk-sensors/src/buttons.rs +++ b/crates/desk-sensors/src/buttons.rs @@ -1,5 +1,5 @@ use embedded_hal_async::digital::Wait; -use protocol::{Press, Reading}; +use protocol::{make_error_string, Press, Reading}; use std::sync::mpsc::Sender; use std::time::{Duration, Instant}; use tracing::{debug, error, info, trace}; @@ -27,7 +27,7 @@ async fn watch_pin( Ok(pin) => pin, Err(error) => { error!("error opening gpio {offset} on {CHIP}: {error}"); - let error: protocol::downcast_err::GpioError = error.into(); + let error = make_error_string(error); let error = desk::Error::Setup(SetupError::Gpio(error)); send_error(tx, error); return; @@ -39,7 +39,7 @@ async fn watch_pin( loop { if let Err(error) = pin.wait_for_rising_edge().await { error!("error waiting for rising edge for gpio {offset} on {CHIP}: {error}"); - let error: protocol::downcast_err::GpioError = error.into(); + let error = make_error_string(error); let error = desk::Error::Running(desk::SensorError::Gpio(error)); send_error(tx, error); return; @@ -50,7 +50,7 @@ async fn watch_pin( match tokio::time::timeout(MAX_PRESS, pin.wait_for_falling_edge()).await { Ok(Err(error)) => { error!("error waiting for falling edge for gpio {offset} on {CHIP}: {error}"); - let error: protocol::downcast_err::GpioError = error.into(); + let error = make_error_string(error); let error = desk::Error::Running(desk::SensorError::Gpio(error)); send_error(tx, error); return; diff --git a/crates/desk-sensors/src/sensors.rs b/crates/desk-sensors/src/sensors.rs index 35f458c8..9b5da468 100644 --- a/crates/desk-sensors/src/sensors.rs +++ b/crates/desk-sensors/src/sensors.rs @@ -2,30 +2,32 @@ use bme280::i2c::BME280 as Bme280; use bme280::{self, Measurements}; use hal::{Delay, I2cdev}; use linux_embedded_hal as hal; -use protocol::downcast_err::ConcreteErrorType; use tracing::debug; +use std::str::FromStr; use std::sync::mpsc::Sender; use std::thread; use std::time::{Duration, Instant}; use protocol::large_bedroom::desk::Reading as DeskReading; use protocol::large_bedroom::desk::{Error, SensorError, SetupError}; -use protocol::Reading; +use protocol::{make_error_string, Reading}; use crate::{send_error, send_reading}; pub fn init() -> Result, Error> { let i2c_bus = I2cdev::new("/dev/i2c-1") .inspect_err(|e| tracing::error!("Could not open i2c bus: {e}")) - .map_err(|e| (&e).into()) + .map_err(|e| e.to_string()) + .map_err(|e| heapless::String::from_str(&e[..200]).unwrap()) .map_err(|e| Error::Setup(SetupError::I2c(e)))?; let mut bme280 = Bme280::new_primary(i2c_bus); bme280 .init(&mut Delay) .inspect_err(|e| tracing::error!("Could not init bme280 sensor: {e}")) - .map_err(|e| e.strip_generics()) + .map_err(|e| e.to_string()) + .map_err(|e| heapless::String::from_str(&e[..200]).unwrap()) .map_err(|e| Error::Setup(SetupError::BmeError(e)))?; Ok(bme280) } @@ -34,32 +36,32 @@ pub fn start_monitoring(tx: Sender>) -> Result< let mut bme = init()?; let mut last_warning = Instant::now() - Duration::from_secs(10_000); - thread::spawn(move || { - loop { - match bme.measure(&mut Delay) { - Ok(m @ Measurements { + thread::spawn(move || loop { + match bme.measure(&mut Delay) { + Ok( + m @ Measurements { temperature, pressure, humidity, .. - }) => { - debug!("got measurements: {m:?}"); - send_reading(&tx, DeskReading::Temperature(temperature)); - send_reading(&tx, DeskReading::Humidity(humidity)); - send_reading(&tx, DeskReading::Pressure(pressure)); - } - Err(e) => { - if last_warning.elapsed() > Duration::from_secs(300) { - last_warning = Instant::now(); - tracing::error!("Could not read bme280 sensor: {e}"); - } - let err = e.strip_generics(); - send_error(&tx, Error::Running(SensorError::BmeError(err))) + }, + ) => { + debug!("got measurements: {m:?}"); + send_reading(&tx, DeskReading::Temperature(temperature)); + send_reading(&tx, DeskReading::Humidity(humidity)); + send_reading(&tx, DeskReading::Pressure(pressure)); + } + Err(e) => { + if last_warning.elapsed() > Duration::from_secs(300) { + last_warning = Instant::now(); + tracing::error!("Could not read bme280 sensor: {e}"); } + let err = make_error_string(e); + send_error(&tx, Error::Running(SensorError::BmeError(err))) } - - std::thread::sleep(Duration::from_secs(5)); } + + std::thread::sleep(Duration::from_secs(5)); }); Ok(()) diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index 71678396..298b8332 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -11,7 +11,7 @@ authors.workspace = true [dependencies] serde = { version = "1.0", features = ["derive"], default-features = false } postcard = { version = "1.0", features = ["experimental-derive"] } -heapless = { version = "0.8.0", features = ["serde"] } +heapless = { version = "0.8.0", features = ["serde", "defmt-03"] } strum = { version = "0.26.2", default-features = false, features = ["derive"] } thiserror = { version = "1.0", optional = true } defmt = "0.3.6" diff --git a/crates/protocol/src/downcast_err.rs b/crates/protocol/src/downcast_err.rs deleted file mode 100644 index b1ac5c52..00000000 --- a/crates/protocol/src/downcast_err.rs +++ /dev/null @@ -1,107 +0,0 @@ -mod i2c; -// #[cfg(feature = "alloc")] -mod rpi_button; -mod uart; - -use bosch_bme680::BmeError; -pub use i2c::{I2cError, LinuxI2cError}; -// #[cfg(feature = "alloc")] -pub use rpi_button::GpioError; -pub use uart::Error as UartError; - -pub trait ConcreteErrorType { - type Concrete; - fn strip_generics(self) -> Self::Concrete; -} - -impl ConcreteErrorType for BmeError -where - E: Into + core::fmt::Debug, -{ - type Concrete = BmeError; - fn strip_generics(self) -> Self::Concrete { - match self { - BmeError::WriteError(i2c) => BmeError::WriteError(i2c.into()), - BmeError::WriteReadError(i2c) => BmeError::WriteReadError(i2c.into()), - BmeError::UnexpectedChipId(id) => BmeError::UnexpectedChipId(id), - BmeError::MeasuringTimeOut => BmeError::MeasuringTimeOut, - } - } -} - -impl ConcreteErrorType for max44009::Error -where - E: Into + core::fmt::Debug + defmt::Format, -{ - type Concrete = max44009::Error; - fn strip_generics(self) -> Self::Concrete { - match self { - max44009::Error::I2C(i2c) => max44009::Error::I2C(i2c.into()), - max44009::Error::OperationNotAvailable => max44009::Error::OperationNotAvailable, - } - } -} - -impl ConcreteErrorType for mhzx::Error -where - E1: Into + core::fmt::Debug + defmt::Format, - E2: Into + core::fmt::Debug + defmt::Format, -{ - type Concrete = mhzx::Error; - fn strip_generics(self) -> Self::Concrete { - match self { - mhzx::Error::InvalidChecksum => Self::Concrete::InvalidChecksum, - mhzx::Error::InvalidPacket => Self::Concrete::InvalidPacket, - mhzx::Error::WritingToUart(e) => Self::Concrete::WritingToUart(e.into()), - mhzx::Error::FlushingUart(e) => Self::Concrete::FlushingUart(e.into()), - mhzx::Error::ReadingEOF => Self::Concrete::ReadingEOF, - mhzx::Error::Reading(e) => Self::Concrete::Reading(e.into()), - } - } -} - -impl ConcreteErrorType for sps30_async::Error -where - E1: Into + core::fmt::Debug + defmt::Format, - E2: Into + core::fmt::Debug + defmt::Format, -{ - type Concrete = sps30_async::Error; - fn strip_generics(self) -> Self::Concrete { - match self { - sps30_async::Error::SerialR(e) => sps30_async::Error::SerialR(e.into()), - sps30_async::Error::SerialW(e) => sps30_async::Error::SerialW(e.into()), - sps30_async::Error::SHDLC(e) => sps30_async::Error::SHDLC(e), - sps30_async::Error::InvalidFrame => sps30_async::Error::InvalidFrame, - sps30_async::Error::EmptyResult => sps30_async::Error::EmptyResult, - sps30_async::Error::ChecksumFailed => sps30_async::Error::ChecksumFailed, - sps30_async::Error::InvalidResponse => sps30_async::Error::InvalidResponse, - sps30_async::Error::DeviceError(e) => sps30_async::Error::DeviceError(e), - sps30_async::Error::MeasurementDataTooShort => { - sps30_async::Error::MeasurementDataTooShort - } - sps30_async::Error::CleaningIntervalDataTooShort => { - sps30_async::Error::CleaningIntervalDataTooShort - } - sps30_async::Error::SerialInvalidUtf8 => sps30_async::Error::SerialInvalidUtf8, - sps30_async::Error::ReadingEOF => sps30_async::Error::ReadingEOF, - sps30_async::Error::FrameTooLarge => sps30_async::Error::FrameTooLarge, - } - } -} - -impl ConcreteErrorType for bme280::Error -where - E: Into + core::fmt::Debug, -{ - type Concrete = bme280::Error; - fn strip_generics(self) -> Self::Concrete { - match self { - bme280::Error::CompensationFailed => bme280::Error::CompensationFailed, - bme280::Error::Bus(e) => bme280::Error::Bus(e.into()), - bme280::Error::InvalidData => bme280::Error::InvalidData, - bme280::Error::NoCalibrationData => bme280::Error::NoCalibrationData, - bme280::Error::UnsupportedChip => bme280::Error::UnsupportedChip, - bme280::Error::Delay => bme280::Error::Delay, - } - } -} diff --git a/crates/protocol/src/downcast_err/i2c.rs b/crates/protocol/src/downcast_err/i2c.rs deleted file mode 100644 index 43fe18c8..00000000 --- a/crates/protocol/src/downcast_err/i2c.rs +++ /dev/null @@ -1,102 +0,0 @@ -use postcard::experimental::max_size::MaxSize; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] -#[cfg_attr(feature = "thiserror", derive(thiserror::Error))] -pub enum I2cError { - #[cfg_attr(feature = "thiserror", error("Bus error"))] - Bus, - #[cfg_attr(feature = "thiserror", error("Arbitration lost"))] - Arbitration, - #[cfg_attr( - feature = "thiserror", - error("ACK not received (either to the address or to a data byte)") - )] - Nack, - #[cfg_attr(feature = "thiserror", error("Timeout"))] - Timeout, - #[cfg_attr(feature = "thiserror", error("CRC error"))] - Crc, - #[cfg_attr(feature = "thiserror", error("Overrun error"))] - Overrun, - #[cfg_attr(feature = "thiserror", error("Zero-length transfers are not allowed"))] - ZeroLengthTransfer, - #[cfg_attr( - feature = "thiserror", - error("Configuration of the inner I2C bus failed.") - )] - Config, -} - -impl From> - for I2cError -{ - fn from( - value: embassy_embedded_hal::shared_bus::I2cDeviceError, - ) -> Self { - use embassy_embedded_hal::shared_bus::I2cDeviceError; - use embassy_stm32::i2c::Error; - - match value { - I2cDeviceError::I2c(Error::Bus) => Self::Bus, - I2cDeviceError::I2c(Error::Arbitration) => Self::Arbitration, - I2cDeviceError::I2c(Error::Nack) => Self::Nack, - I2cDeviceError::I2c(Error::Timeout) => Self::Timeout, - I2cDeviceError::I2c(Error::Crc) => Self::Crc, - I2cDeviceError::I2c(Error::Overrun) => Self::Overrun, - I2cDeviceError::I2c(Error::ZeroLengthTransfer) => Self::ZeroLengthTransfer, - I2cDeviceError::Config => Self::Config, - } - } -} - -#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] -#[cfg_attr(feature = "thiserror", derive(thiserror::Error))] -// linux error codes should be stable across different linux kernels -pub enum LinuxI2cError { - FailedLibcCall(i32), - Io(Option), -} - -#[cfg(feature = "thiserror")] -impl core::fmt::Display for LinuxI2cError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - LinuxI2cError::FailedLibcCall(failed_libc_call) => { - let errno = nix::errno::Errno::from_raw(*failed_libc_call); - write!(f, "Error calling I2C interface: {errno}") - } - LinuxI2cError::Io(Some(raw_os_error)) => { - let io_error = std::io::Error::from_raw_os_error(*raw_os_error); - write!(f, "Io error using I2C interface: {io_error}, more details in logs on sensing device") - } - LinuxI2cError::Io(None) => { - write!( - f, - "Unknown error using I2C interface, check logs on sensing device" - ) - } - } - } -} - -#[cfg(alloc)] -impl From for LinuxI2cError { - fn from(value: linux_embedded_hal::I2CError) -> Self { - value.inner().into() - } -} - -#[cfg(alloc)] -impl From<&linux_embedded_hal::i2cdev::linux::LinuxI2CError> for LinuxI2cError { - fn from(value: &linux_embedded_hal::i2cdev::linux::LinuxI2CError) -> Self { - use linux_embedded_hal::i2cdev::linux::LinuxI2CError; - - match value { - LinuxI2CError::Errno(failing_libc_call) => { - LinuxI2cError::FailedLibcCall(*failing_libc_call) - } - LinuxI2CError::Io(io_error) => LinuxI2cError::Io(io_error.raw_os_error()), - } - } -} diff --git a/crates/protocol/src/downcast_err/rpi_button.rs b/crates/protocol/src/downcast_err/rpi_button.rs deleted file mode 100644 index ad761a9a..00000000 --- a/crates/protocol/src/downcast_err/rpi_button.rs +++ /dev/null @@ -1,134 +0,0 @@ -/// The gpio_cdev::Error is not constant size. The alternative would be to send -/// the error as a fixed size string. The error struct must have a statically -/// determined maximum size to allow encoding/decoding on embedded systems. Thus -/// sending a string is also not an option -/// -/// We could add a second message type with variable message size but we would -/// still need to add serde support to the origonal error -use postcard::experimental::max_size::MaxSize; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] -#[cfg_attr(feature = "thiserror", derive(thiserror::Error))] -pub enum CdevError { - /// An operation cannot be performed due to a limitation in the ABI version being used. - #[cfg_attr( - feature = "thiserror", - error( - "An operation cannot be performed due to a limitation in the ABI version being used." - ) - )] - AbiLimitation, - /// Problem accessing GPIO chip character devices - #[cfg_attr( - feature = "thiserror", - error("Problem accessing GPIO chip character devices") - )] - GpioChip, - /// An error returned when there is a problem with an argument. - #[cfg_attr( - feature = "thiserror", - error("An error returned when there is a problem with an argument.") - )] - InvalidArgument, - /// No gpiochips are available to the user. - #[cfg_attr( - feature = "thiserror", - error("No gpiochips are available to the user.") - )] - NoGpioChips, - /// Returned when the strict mode of find_named_lines finds multiple lines with the same name. - #[cfg_attr(feature = "thiserror", error("Returned when the strict mode of find_named_lines finds multiple lines with the same name."))] - NonuniqueLineName, - /// An error returned from an underlying os call. - #[cfg_attr( - feature = "thiserror", - error("An error returned from an underlying os call.") - )] - Os, - /// An error returned from an underlying uAPI call. - #[cfg_attr( - feature = "thiserror", - error("An error returned from an underlying uAPI call.") - )] - Uapi, - /// The response to a uAPI command contained unexpected content. - #[cfg_attr( - feature = "thiserror", - error("The response to a uAPI command contained unexpected content.") - )] - UnexpectedResponse, - /// The kernel or build does not support the requested uAPI ABI version. - #[cfg_attr( - feature = "thiserror", - error("The kernel or build does not support the requested uAPI ABI version.") - )] - UnsupportedAbi, - /// The kernel has no support for any uAPI ABI version. - #[cfg_attr( - feature = "thiserror", - error("The kernel has no support for any uAPI ABI version.") - )] - NoAbiSupport, -} - -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] -#[cfg_attr(feature = "thiserror", derive(thiserror::Error))] -pub enum GpioError { - /// Requests can only contain a single requested line. - #[cfg_attr( - feature = "thiserror", - error("Requests can only contain a single requested line.") - )] - MultipleLinesRequested, - - /// InputPins must be in input mode. - #[cfg_attr(feature = "thiserror", error("InputPins must be in input mode."))] - RequiresInputMode, - - /// OutputPins must be in output mode. - #[cfg_attr(feature = "thiserror", error("OutputPins must be in output mode."))] - RequiresOutputMode, - - /// Cannot find named line. - #[cfg_attr(feature = "thiserror", error("Cannot find named line."))] - UnfoundLine, - - /// An error returned from an underlying gpiocdev call. - #[cfg_attr( - feature = "thiserror", - error("An error returned from an underlying gpiocdev call.") - )] - Cdev(CdevError), -} - -impl From for GpioError { - fn from(value: gpiocdev_embedded_hal::Error) -> Self { - use gpiocdev_embedded_hal::Error; - match value { - Error::MultipleLinesRequested => GpioError::MultipleLinesRequested, - Error::RequiresInputMode => GpioError::RequiresInputMode, - Error::RequiresOutputMode => GpioError::RequiresOutputMode, - Error::UnfoundLine(_) => GpioError::UnfoundLine, - Error::Cdev(e) => GpioError::Cdev(e.into()), - } - } -} - -impl From for CdevError { - fn from(value: gpiocdev::Error) -> Self { - use gpiocdev::Error; - match value { - Error::AbiLimitation(_, _) => CdevError::AbiLimitation, - Error::GpioChip(_, _) => CdevError::GpioChip, - Error::InvalidArgument(_) => CdevError::InvalidArgument, - Error::NoGpioChips() => CdevError::NoGpioChips, - Error::NonuniqueLineName(_) => CdevError::NonuniqueLineName, - Error::Os(_) => CdevError::Os, - Error::Uapi(_, _) => CdevError::Uapi, - Error::UnexpectedResponse(_) => CdevError::UnexpectedResponse, - Error::UnsupportedAbi(_, _) => CdevError::UnsupportedAbi, - Error::NoAbiSupport() => CdevError::NoAbiSupport, - } - } -} diff --git a/crates/protocol/src/downcast_err/uart.rs b/crates/protocol/src/downcast_err/uart.rs deleted file mode 100644 index 1fdef9e5..00000000 --- a/crates/protocol/src/downcast_err/uart.rs +++ /dev/null @@ -1,40 +0,0 @@ -use postcard::experimental::max_size::MaxSize; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] -#[cfg_attr(feature = "thiserror", derive(thiserror::Error))] -pub enum Error { - #[cfg_attr(feature = "thiserror", error("Framing error"))] - Framing, - #[cfg_attr(feature = "thiserror", error("Noise error"))] - Noise, - #[cfg_attr(feature = "thiserror", error("RX buffer overrun"))] - Overrun, - #[cfg_attr(feature = "thiserror", error("Parity check error"))] - Parity, - #[cfg_attr(feature = "thiserror", error("Buffer too large for DMA"))] - BufferTooLong, - - // Author note: I strongly dislike non-exhaustive for this reason. I want to - // know I handle every error case at compile time that is why we have a type - // system! Now I can update the code and run into an unhandled error years - // after the update. The opsession with never increasing major versions that - // has caused this spread of non-exhaustive needs to stop. - #[cfg_attr(feature = "thiserror", error("A new error was added upstream unknown to the protocol and it occurred, please update the From for UsartError implementation"))] - NewUnhandledError, -} - -impl From for Error { - fn from(err: embassy_stm32::usart::Error) -> Self { - use embassy_stm32::usart::Error; - - match err { - Error::Framing => Self::Framing, - Error::Noise => Self::Noise, - Error::Overrun => Self::Overrun, - Error::Parity => Self::Parity, - Error::BufferTooLong => Self::BufferTooLong, - _ => Self::NewUnhandledError, - } - } -} diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 4076cbbe..eaafad00 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -1,7 +1,6 @@ -use crate::downcast_err::{I2cError, UartError}; +use crate::button_enum; #[cfg(feature = "alloc")] use crate::{Tomato, TomatoItem}; -use crate::button_enum; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -119,13 +118,17 @@ impl Error { } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, Eq, PartialEq)] pub enum SensorError { - Sht31(sht31::error::SHTError), - Bme680(bosch_bme680::BmeError), - Max44(max44009::Error), - Mhz14(mhzx::Error), - Sps30(sps30_async::Error), + Sht31(heapless::String<200>), + Bme680(heapless::String<200>), + Max44(heapless::String<200>), + Mhz14(heapless::String<200>), + Sps30(heapless::String<200>), +} + +impl MaxSize for SensorError { + const POSTCARD_MAX_SIZE: usize = 201; } impl SensorError { diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index df3c41ee..76a66d36 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -1,10 +1,9 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; -use crate::downcast_err::{GpioError, LinuxI2cError}; +use crate::button_enum; #[cfg(feature = "alloc")] use crate::{Tomato, TomatoItem}; -use crate::button_enum; button_enum! { /// No these are not borg, these are buttons on a string of cat5. @@ -66,17 +65,25 @@ impl Error { } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, Eq, PartialEq)] pub enum SetupError { - BmeError(bme280::Error), - Gpio(GpioError), - I2c(LinuxI2cError), + BmeError(heapless::String<200>), + Gpio(heapless::String<200>), + I2c(heapless::String<200>), } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +impl MaxSize for SetupError { + const POSTCARD_MAX_SIZE: usize = 200+1; +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, Eq, PartialEq)] pub enum SensorError { - BmeError(bme280::Error), - Gpio(GpioError), + BmeError(heapless::String<200>), + Gpio(heapless::String<200>), +} + +impl MaxSize for SensorError { + const POSTCARD_MAX_SIZE: usize = 200+1; } impl SensorError { diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 50c54690..9a52bbcf 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -6,8 +6,6 @@ use serde::{Deserialize, Serialize}; pub mod large_bedroom; pub mod small_bedroom; -pub mod downcast_err; - /// turns an enum of empty variants into one with [`Press`](crate::Press) inside each variant also /// adds a method `press(&self)` that returns an instance of [`Press`](crate::Press). It can be /// used to quickly find out if a button event is a long or short press. @@ -117,7 +115,7 @@ pub enum TomatoItem<'a> { } #[cfg(feature = "alloc")] -pub trait Tomato: fmt::Debug { +pub trait Tomato: core::fmt::Debug { fn inner<'a>(&'a self) -> TomatoItem<'a>; fn name(&self) -> String { let dbg_repr = format!("{:?}", self); @@ -228,3 +226,12 @@ impl SensorMessage { self.version } } + +pub type ErrorString = heapless::String<200>; +pub fn make_error_string(e: impl core::fmt::Display) -> ErrorString { + use core::fmt::Write; + + let mut s = ErrorString::new(); + core::write!(s, "{e}").ok(); + s +} From 5e384b6cc95af68350ceb9ddba1260ad9739fe25 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 3 Jun 2024 14:52:09 +0200 Subject: [PATCH 118/687] cleanup protocol deps and moved bed-sensornode here --- Cargo.lock | 478 +----- crates/protocol/Cargo.toml | 23 +- sensor-nodes/bed-sensors/.cargo/config.toml | 16 + sensor-nodes/bed-sensors/.gitignore | 1 + sensor-nodes/bed-sensors/Cargo.lock | 1567 ++++++++++++++++++ sensor-nodes/bed-sensors/Cargo.toml | 67 + sensor-nodes/bed-sensors/build.rs | 5 + sensor-nodes/bed-sensors/rust-toolchain.toml | 6 + sensor-nodes/bed-sensors/src/channel.rs | 133 ++ sensor-nodes/bed-sensors/src/main.rs | 249 +++ sensor-nodes/bed-sensors/src/network.rs | 86 + sensor-nodes/bed-sensors/src/sensors.rs | 90 + sensor-nodes/bed-sensors/src/sensors/fast.rs | 124 ++ sensor-nodes/bed-sensors/src/sensors/slow.rs | 211 +++ 14 files changed, 2567 insertions(+), 489 deletions(-) create mode 100644 sensor-nodes/bed-sensors/.cargo/config.toml create mode 100644 sensor-nodes/bed-sensors/.gitignore create mode 100644 sensor-nodes/bed-sensors/Cargo.lock create mode 100644 sensor-nodes/bed-sensors/Cargo.toml create mode 100644 sensor-nodes/bed-sensors/build.rs create mode 100644 sensor-nodes/bed-sensors/rust-toolchain.toml create mode 100644 sensor-nodes/bed-sensors/src/channel.rs create mode 100644 sensor-nodes/bed-sensors/src/main.rs create mode 100644 sensor-nodes/bed-sensors/src/network.rs create mode 100644 sensor-nodes/bed-sensors/src/sensors.rs create mode 100644 sensor-nodes/bed-sensors/src/sensors/fast.rs create mode 100644 sensor-nodes/bed-sensors/src/sensors/slow.rs diff --git a/Cargo.lock b/Cargo.lock index fbbb11ba..a653dfe0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -427,15 +427,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "bare-metal" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" -dependencies = [ - "rustc_version 0.2.3", -] - [[package]] name = "base64" version = "0.22.1" @@ -451,24 +442,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bit_field" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" - -[[package]] -name = "bitfield" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" - -[[package]] -name = "bitfield" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" - [[package]] name = "bitflags" version = "1.3.2" @@ -511,28 +484,13 @@ name = "bme280" version = "0.5.1" source = "git+https://github.com/dvdsk/bme280-rs#a147bfc93d73a827616121f194972d6cc9cb3d11" dependencies = [ - "defmt", "derive_more", - "embedded-hal 1.0.0", + "embedded-hal", "maybe-async-cfg", "postcard", "serde", ] -[[package]] -name = "bosch-bme680" -version = "1.0.2" -source = "git+https://github.com/dvdsk/async-bosch-bme680#455d5d3194f137d9e0403779badc645e1bad7a05" -dependencies = [ - "bitfield 0.14.0", - "defmt", - "embedded-hal 1.0.0", - "embedded-hal-async", - "postcard", - "serde", - "thiserror", -] - [[package]] name = "brain" version = "0.1.0" @@ -577,18 +535,6 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" -[[package]] -name = "bxcan" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ac3d0c0a542d0ab5521211f873f62706a7136df415676f676d347e5a41dd80" -dependencies = [ - "bitflags 1.3.2", - "embedded-hal 0.2.7", - "nb 1.1.0", - "vcell", -] - [[package]] name = "byteorder" version = "1.5.0" @@ -640,12 +586,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - [[package]] name = "chrono" version = "0.4.38" @@ -800,53 +740,6 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" -[[package]] -name = "cortex-m" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" -dependencies = [ - "bare-metal", - "bitfield 0.13.2", - "embedded-hal 0.2.7", - "volatile-register", -] - -[[package]] -name = "cortex-m-rt" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1" -dependencies = [ - "cortex-m-rt-macros", -] - -[[package]] -name = "cortex-m-rt-macros" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "crc" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - [[package]] name = "crc32fast" version = "1.4.2" @@ -967,7 +860,7 @@ dependencies = [ "convert_case", "proc-macro2", "quote", - "rustc_version 0.4.0", + "rustc_version", "syn 1.0.109", ] @@ -999,169 +892,17 @@ dependencies = [ "quick-error", ] -[[package]] -name = "document-features" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" -dependencies = [ - "litrs", -] - [[package]] name = "either" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" -[[package]] -name = "embassy-embedded-hal" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca4a9380d03e61063067b8239f67d2fa9f108ede7c46b4273804f6b79e59a1d" -dependencies = [ - "embassy-futures", - "embassy-sync", - "embassy-time", - "embedded-hal 0.2.7", - "embedded-hal 1.0.0", - "embedded-hal-async", - "embedded-storage", - "embedded-storage-async", - "nb 1.1.0", -] - -[[package]] -name = "embassy-futures" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f878075b9794c1e4ac788c95b728f26aa6366d32eeb10c7051389f898f7d067" - -[[package]] -name = "embassy-hal-internal" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0ec47cf8bab914018d4bd2b4f0aaeb46e4f52ab1e7985df88aeef2c6eda5aed" -dependencies = [ - "cortex-m", - "critical-section", - "num-traits", -] - -[[package]] -name = "embassy-net-driver" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d" - -[[package]] -name = "embassy-stm32" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32bc0257b5ade13a1b93e8b9949268f44d57e8ce03e599ef1c5a62024a0fbff9" -dependencies = [ - "bit_field", - "bxcan", - "cfg-if 1.0.0", - "cortex-m", - "cortex-m-rt", - "critical-section", - "document-features", - "embassy-embedded-hal", - "embassy-futures", - "embassy-hal-internal", - "embassy-net-driver", - "embassy-sync", - "embassy-usb-driver", - "embedded-hal 0.2.7", - "embedded-hal 1.0.0", - "embedded-hal-async", - "embedded-hal-nb", - "embedded-io 0.6.1", - "embedded-io-async", - "embedded-storage", - "embedded-storage-async", - "futures", - "nb 1.1.0", - "proc-macro2", - "quote", - "rand_core", - "sdio-host", - "stm32-fmc", - "stm32-metapac", - "vcell", -] - -[[package]] -name = "embassy-sync" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd938f25c0798db4280fcd8026bf4c2f48789aebf8f77b6e5cf8a7693ba114ec" -dependencies = [ - "cfg-if 1.0.0", - "critical-section", - "embedded-io-async", - "futures-util", - "heapless 0.8.0", -] - -[[package]] -name = "embassy-time" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c844070d9f80dc66ee739299183312baee2e1cdeb6e90b4ea2af44f4676da5" -dependencies = [ - "cfg-if 1.0.0", - "critical-section", - "document-features", - "embassy-time-driver", - "embassy-time-queue-driver", - "embedded-hal 0.2.7", - "embedded-hal 1.0.0", - "embedded-hal-async", - "futures-util", - "heapless 0.8.0", -] - -[[package]] -name = "embassy-time-driver" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c214077aaa9206958b16411c157961fb7990d4ea628120a78d1a5a28aed24" -dependencies = [ - "document-features", -] - -[[package]] -name = "embassy-time-queue-driver" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1177859559ebf42cd24ae7ba8fe6ee707489b01d0bf471f8827b7b12dcb0bc0" - -[[package]] -name = "embassy-usb-driver" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fc247028eae04174b6635104a35b1ed336aabef4654f5e87a8f32327d231970" - -[[package]] -name = "embedded-hal" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" -dependencies = [ - "nb 0.1.3", - "void", -] - [[package]] name = "embedded-hal" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" -dependencies = [ - "defmt", -] [[package]] name = "embedded-hal-async" @@ -1169,8 +910,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" dependencies = [ - "defmt", - "embedded-hal 1.0.0", + "embedded-hal", ] [[package]] @@ -1179,8 +919,8 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" dependencies = [ - "embedded-hal 1.0.0", - "nb 1.1.0", + "embedded-hal", + "nb", ] [[package]] @@ -1189,40 +929,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" -[[package]] -name = "embedded-io" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" -dependencies = [ - "defmt", -] - -[[package]] -name = "embedded-io-async" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" -dependencies = [ - "defmt", - "embedded-io 0.6.1", -] - -[[package]] -name = "embedded-storage" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" - -[[package]] -name = "embedded-storage-async" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc" -dependencies = [ - "embedded-storage", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -1546,7 +1252,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26476d24320fe1b9ebc76392f984abe4a6147844c7e5a69538318f15b026cca8" dependencies = [ - "embedded-hal 1.0.0", + "embedded-hal", "embedded-hal-async", "gpiocdev", "thiserror", @@ -1600,7 +1306,7 @@ checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" dependencies = [ "atomic-polyfill", "hash32 0.2.1", - "rustc_version 0.4.0", + "rustc_version", "serde", "spin", "stable_deref_trait", @@ -1908,11 +1614,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d566b726e1b6810f66c6f1c769889248439c27f06a59df2881a735454cfa02" dependencies = [ "cast", - "embedded-hal 1.0.0", + "embedded-hal", "embedded-hal-nb", "gpio-cdev", "i2cdev", - "nb 1.1.0", + "nb", "nix 0.27.1", "serialport", "spidev", @@ -1931,12 +1637,6 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" -[[package]] -name = "litrs" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" - [[package]] name = "lock_api" version = "0.4.12" @@ -1989,18 +1689,6 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" -[[package]] -name = "max44009" -version = "0.2.0" -source = "git+https://github.com/dvdsk/max44009-rs#7b7df2e3173476c250fca3eb242f0dd366857599" -dependencies = [ - "defmt", - "embedded-hal-async", - "postcard", - "serde", - "thiserror", -] - [[package]] name = "maybe-async-cfg" version = "0.2.3" @@ -2054,19 +1742,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "mhzx" -version = "0.3.0" -source = "git+https://github.com/dvdsk/mhzx#08f6e7adb4ec98749fa84f24f8ff9e0e3c83d164" -dependencies = [ - "defmt", - "embedded-io-async", - "heapless 0.8.0", - "postcard", - "serde", - "thiserror", -] - [[package]] name = "mime" version = "0.3.17" @@ -2103,15 +1778,6 @@ dependencies = [ "bufstream", ] -[[package]] -name = "nb" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" -dependencies = [ - "nb 1.1.0", -] - [[package]] name = "nb" version = "1.1.0" @@ -2166,18 +1832,6 @@ dependencies = [ "libc", ] -[[package]] -name = "nix" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" -dependencies = [ - "bitflags 2.5.0", - "cfg-if 1.0.0", - "cfg_aliases", - "libc", -] - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -2388,7 +2042,7 @@ checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" dependencies = [ "cobs", "const_format", - "embedded-io 0.4.0", + "embedded-io", "heapless 0.7.17", "postcard-derive", "serde", @@ -2454,25 +2108,12 @@ dependencies = [ name = "protocol" version = "0.1.0" dependencies = [ - "bme280", - "bosch-bme680", "defmt", - "embassy-embedded-hal", - "embassy-stm32", - "gpiocdev", - "gpiocdev-embedded-hal", "heapless 0.8.0", - "linux-embedded-hal", - "max44009", - "mhzx", - "nix 0.28.0", "postcard", "serde", - "sht31", - "sps30-async", "strum", "thiserror", - "tracing", ] [[package]] @@ -2660,22 +2301,13 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver 0.9.0", -] - [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.23", + "semver", ] [[package]] @@ -2723,33 +2355,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sdio-host" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93c025f9cfe4c388c328ece47d11a54a823da3b5ad0370b22d95ad47137f85a" - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - [[package]] name = "semver" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "sensor-tui" version = "0.0.0" @@ -2849,19 +2460,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "sht31" -version = "0.3.1" -source = "git+https://github.com/dvdsk/SHT31-rs#a7b6bd94fb137e16bf326eff5fb591624369a2cf" -dependencies = [ - "crc", - "defmt", - "embedded-hal-async", - "postcard", - "serde", - "thiserror", -] - [[package]] name = "signal-hook" version = "0.3.17" @@ -2963,20 +2561,6 @@ dependencies = [ "lock_api", ] -[[package]] -name = "sps30-async" -version = "0.2.0" -source = "git+https://github.com/dvdsk/sps30-async#a5e81ec034727442c048acea2e8eb07fe4be78e4" -dependencies = [ - "defmt", - "embedded-hal-async", - "embedded-io-async", - "heapless 0.8.0", - "postcard", - "serde", - "thiserror", -] - [[package]] name = "stability" version = "0.2.0" @@ -2999,25 +2583,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "stm32-fmc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830ed60f33e6194ecb377f5d6ab765dc0e37e7b65e765f1fa87df13336658d63" -dependencies = [ - "embedded-hal 0.2.7", -] - -[[package]] -name = "stm32-metapac" -version = "15.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deabea56a8821dcea05d0109f3ab3135f31eb572444e5da203d06149c594c8c6" -dependencies = [ - "cortex-m", - "cortex-m-rt", -] - [[package]] name = "strsim" version = "0.11.1" @@ -3458,33 +3023,12 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" -[[package]] -name = "vcell" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" - [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - -[[package]] -name = "volatile-register" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" -dependencies = [ - "vcell", -] - [[package]] name = "waker-fn" version = "1.2.0" diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index 298b8332..36d1210b 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -16,26 +16,5 @@ strum = { version = "0.26.2", default-features = false, features = ["derive"] } thiserror = { version = "1.0", optional = true } defmt = "0.3.6" -# sensors, we need these to be able to display/receive their errors -sht31 = { version = "0.3.0", git = "https://github.com/dvdsk/SHT31-rs", features = ["serde", "postcard"]} -bosch-bme680 = { version = "1.0.2", git = "https://github.com/dvdsk/async-bosch-bme680", features = ["serde", "postcard"] } -max44009 = { version = "0.2", git = "https://github.com/dvdsk/max44009-rs", features = ["serde", "postcard"] } -mhzx = { version = "0.3", git = "https://github.com/dvdsk/mhzx", features = ["serde", "postcard"] } -sps30-async = { version = "0.2.0", git = "https://github.com/dvdsk/sps30-async", features = ["serde", "postcard"] } -bme280 = { version = "0.5", git = "https://github.com/dvdsk/bme280-rs", features = ["postcard", "serde", "with_defmt"]} - -# needed for bme680 error I2C type -embassy-stm32 = { version = "0.1.0", features = ["stm32f401cc"] } -embassy-embedded-hal = "0.1.0" - -linux-embedded-hal = { version = "0.4.0", features = ["i2c"], default-features = false, optional = true } -gpiocdev-embedded-hal = { version = "0.1.1", optional = true } -gpiocdev = { version = "0.7.1", optional = true } -nix = { version = "0.28.0", optional = true } -tracing = { version = "0.1.40", optional = true } - [features] -alloc = ["postcard/alloc", "serde/std", "sht31/thiserror", -"bosch-bme680/thiserror", "mhzx/thiserror", "sps30-async/thiserror", -"max44009/thiserror", "linux-embedded-hal", "gpiocdev-embedded-hal", "gpiocdev", -"nix", "tracing"] +alloc = ["postcard/alloc", "serde/std"] diff --git a/sensor-nodes/bed-sensors/.cargo/config.toml b/sensor-nodes/bed-sensors/.cargo/config.toml new file mode 100644 index 00000000..1e24e032 --- /dev/null +++ b/sensor-nodes/bed-sensors/.cargo/config.toml @@ -0,0 +1,16 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +# replace STM32F103C8 with your chip as listed in `probe-rs chip list` +# runner = "probe-rs run --chip STM32F103C8" +runner = "probe-rs run --chip STM32F401CCUx" + +[build] +# target = "thumbv7m-none-eabi" for f103 +target = "thumbv7em-none-eabihf" + +[env] +DEFMT_LOG = "debug,sps30_async=trace,bosch_bme680=info" +EMBASSY_EXECUTOR_TASK_ARENA_SIZE="8000" + +# [unstable] +# build-std = ["core"] +# build-std-features = ["panic_immediate_abort"] diff --git a/sensor-nodes/bed-sensors/.gitignore b/sensor-nodes/bed-sensors/.gitignore new file mode 100644 index 00000000..ea8c4bf7 --- /dev/null +++ b/sensor-nodes/bed-sensors/.gitignore @@ -0,0 +1 @@ +/target diff --git a/sensor-nodes/bed-sensors/Cargo.lock b/sensor-nodes/bed-sensors/Cargo.lock new file mode 100644 index 00000000..113bc129 --- /dev/null +++ b/sensor-nodes/bed-sensors/Cargo.lock @@ -0,0 +1,1567 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "bitfield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "bme280" +version = "0.5.1" +source = "git+https://github.com/dvdsk/bme280-rs#4999b005d26a16312acb3dbc64b72658df49a16d" +dependencies = [ + "defmt", + "embedded-hal 1.0.0", + "maybe-async-cfg", + "postcard", + "serde", +] + +[[package]] +name = "bosch-bme680" +version = "1.0.2" +source = "git+https://github.com/dvdsk/async-bosch-bme680#455d5d3194f137d9e0403779badc645e1bad7a05" +dependencies = [ + "bitfield 0.14.0", + "defmt", + "embedded-hal 1.0.0", + "embedded-hal-async", + "postcard", + "serde", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + +[[package]] +name = "const_format" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal", + "bitfield 0.13.2", + "critical-section", + "embedded-hal 0.2.7", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + +[[package]] +name = "darling" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.66", +] + +[[package]] +name = "darling_macro" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "defmt" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb" +dependencies = [ + "defmt-parser", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "defmt-parser" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" +dependencies = [ + "thiserror", +] + +[[package]] +name = "defmt-rtt" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab697b3dbbc1750b7c8b821aa6f6e7f2480b47a99bc057a2ed7b170ebef0c51" +dependencies = [ + "critical-section", + "defmt", +] + +[[package]] +name = "document-features" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +dependencies = [ + "litrs", +] + +[[package]] +name = "embassy-embedded-hal" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +dependencies = [ + "defmt", + "embassy-futures", + "embassy-sync", + "embassy-time", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-storage", + "embedded-storage-async", + "nb 1.1.0", +] + +[[package]] +name = "embassy-executor" +version = "0.5.0" +source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +dependencies = [ + "cortex-m", + "critical-section", + "defmt", + "document-features", + "embassy-executor-macros", + "embassy-time-driver", + "embassy-time-queue-driver", +] + +[[package]] +name = "embassy-executor-macros" +version = "0.4.1" +source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "embassy-futures" +version = "0.1.1" +source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" + +[[package]] +name = "embassy-hal-internal" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +dependencies = [ + "cortex-m", + "critical-section", + "defmt", + "num-traits", +] + +[[package]] +name = "embassy-net" +version = "0.4.0" +source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +dependencies = [ + "defmt", + "document-features", + "embassy-net-driver", + "embassy-sync", + "embassy-time", + "embedded-io-async", + "embedded-nal-async", + "heapless 0.8.0", + "managed", + "smoltcp", +] + +[[package]] +name = "embassy-net-driver" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +dependencies = [ + "defmt", +] + +[[package]] +name = "embassy-net-driver-channel" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +dependencies = [ + "embassy-futures", + "embassy-net-driver", + "embassy-sync", +] + +[[package]] +name = "embassy-net-wiznet" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +dependencies = [ + "defmt", + "embassy-futures", + "embassy-net-driver-channel", + "embassy-time", + "embedded-hal 1.0.0", + "embedded-hal-async", +] + +[[package]] +name = "embassy-stm32" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +dependencies = [ + "bit_field", + "bitflags 2.5.0", + "cfg-if", + "cortex-m", + "cortex-m-rt", + "critical-section", + "defmt", + "document-features", + "embassy-embedded-hal", + "embassy-futures", + "embassy-hal-internal", + "embassy-net-driver", + "embassy-sync", + "embassy-time", + "embassy-time-driver", + "embassy-usb-driver", + "embassy-usb-synopsys-otg", + "embedded-can", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-nb", + "embedded-io", + "embedded-io-async", + "embedded-storage", + "embedded-storage-async", + "futures-util", + "nb 1.1.0", + "proc-macro2", + "quote", + "rand_core", + "sdio-host", + "static_assertions", + "stm32-fmc", + "stm32-metapac", + "vcell", + "volatile-register", +] + +[[package]] +name = "embassy-sync" +version = "0.5.0" +source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +dependencies = [ + "cfg-if", + "critical-section", + "defmt", + "embedded-io-async", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time" +version = "0.3.0" +source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +dependencies = [ + "cfg-if", + "critical-section", + "defmt", + "document-features", + "embassy-time-driver", + "embassy-time-queue-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time-driver" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +dependencies = [ + "document-features", +] + +[[package]] +name = "embassy-time-queue-driver" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" + +[[package]] +name = "embassy-usb-driver" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +dependencies = [ + "defmt", +] + +[[package]] +name = "embassy-usb-synopsys-otg" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +dependencies = [ + "critical-section", + "embassy-sync", + "embassy-usb-driver", +] + +[[package]] +name = "embedded-can" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "defmt", + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-hal-bus" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57b4e6ede84339ebdb418cd986e6320a34b017cdf99b5cc3efceec6450b06886" +dependencies = [ + "critical-section", + "defmt", + "embedded-hal 1.0.0", + "embedded-hal-async", +] + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" +dependencies = [ + "embedded-hal 1.0.0", + "nb 1.1.0", +] + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-io-async" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" +dependencies = [ + "defmt", + "embedded-io", +] + +[[package]] +name = "embedded-nal" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a943fad5ed3d3f8a00f1e80f6bba371f1e7f0df28ec38477535eb318dc19cc" +dependencies = [ + "nb 1.1.0", + "no-std-net", +] + +[[package]] +name = "embedded-nal-async" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72229137a4fc12d239b0b7f50f04b30790678da6d782a0f3f1909bf57ec4b759" +dependencies = [ + "embedded-io-async", + "embedded-nal", + "no-std-net", +] + +[[package]] +name = "embedded-storage" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" + +[[package]] +name = "embedded-storage-async" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc" +dependencies = [ + "embedded-storage", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-macro", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "gpiocdev" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5119c89eccee09c4f6e9ca2b112aea1cd80bac31cd29169f171a48ae5552d1c" +dependencies = [ + "gpiocdev-uapi", + "thiserror", +] + +[[package]] +name = "gpiocdev-embedded-hal" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26476d24320fe1b9ebc76392f984abe4a6147844c7e5a69538318f15b026cca8" +dependencies = [ + "embedded-hal 1.0.0", + "gpiocdev", + "thiserror", +] + +[[package]] +name = "gpiocdev-uapi" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a02357253f833a6ce4e93f17e8dd3e169c941ea71b83d442ed9c55f784045204" +dependencies = [ + "bitflags 2.5.0", + "ioctl-sys", + "libc", + "thiserror", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version 0.4.0", + "serde", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "defmt", + "hash32 0.3.1", + "serde", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "i2cdev" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597f56d08cebc0fb3e67d49f48124f49e1c7ac297a21d60bc90a28b9482fb35c" +dependencies = [ + "bitflags 2.5.0", + "byteorder", + "libc", + "nix 0.26.4", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "io-kit-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b" +dependencies = [ + "core-foundation-sys", + "mach2", +] + +[[package]] +name = "ioctl-sys" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bd11f3a29434026f5ff98c730b668ba74b1033637b8817940b54d040696133c" + +[[package]] +name = "large-bed" +version = "0.1.0" +dependencies = [ + "bosch-bme680", + "cortex-m", + "cortex-m-rt", + "defmt", + "defmt-rtt", + "embassy-embedded-hal", + "embassy-executor", + "embassy-futures", + "embassy-net", + "embassy-net-wiznet", + "embassy-stm32", + "embassy-sync", + "embassy-time", + "embedded-hal 0.2.7", + "embedded-hal-async", + "embedded-hal-bus", + "embedded-io-async", + "futures", + "heapless 0.8.0", + "max44009", + "mhzx 0.3.0", + "nb 1.1.0", + "panic-probe", + "protocol", + "rand", + "sht31", + "sps30-async 0.2.0", + "static_cell", +] + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "linux-embedded-hal" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d566b726e1b6810f66c6f1c769889248439c27f06a59df2881a735454cfa02" +dependencies = [ + "cast", + "embedded-hal 1.0.0", + "embedded-hal-nb", + "i2cdev", + "nb 1.1.0", + "nix 0.27.1", + "serialport", +] + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + +[[package]] +name = "managed" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" + +[[package]] +name = "max44009" +version = "0.2.0" +source = "git+https://github.com/dvdsk/max44009-rs#7b7df2e3173476c250fca3eb242f0dd366857599" +dependencies = [ + "defmt", + "embedded-hal-async", + "postcard", + "serde", +] + +[[package]] +name = "maybe-async-cfg" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21fb8fac02158b9b529eb692491895d8459dbac939f3bc6e32159969646ffe55" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "pulldown-cmark", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "mhzx" +version = "0.3.0" +dependencies = [ + "defmt", + "embedded-io-async", + "heapless 0.8.0", + "postcard", + "serde", +] + +[[package]] +name = "mhzx" +version = "0.3.0" +source = "git+https://github.com/dvdsk/mhzx#08f6e7adb4ec98749fa84f24f8ff9e0e3c83d164" +dependencies = [ + "defmt", + "embedded-io-async", + "heapless 0.8.0", + "postcard", + "serde", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", +] + +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "libc", +] + +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "panic-probe" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4047d9235d1423d66cc97da7d07eddb54d4f154d6c13805c6d0793956f4f25b0" +dependencies = [ + "cortex-m", + "defmt", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + +[[package]] +name = "postcard" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +dependencies = [ + "cobs", + "const_format", + "heapless 0.7.17", + "postcard-derive", + "serde", +] + +[[package]] +name = "postcard-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4b01218787dd4420daf63875163a787a78294ad48a24e9f6fa8c6507759a79" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "protocol" +version = "0.1.0" +dependencies = [ + "bme280", + "bosch-bme680", + "defmt", + "embassy-embedded-hal", + "embassy-stm32", + "embedded-hal 1.0.0", + "gpiocdev", + "gpiocdev-embedded-hal", + "heapless 0.8.0", + "linux-embedded-hal", + "max44009", + "mhzx 0.3.0 (git+https://github.com/dvdsk/mhzx)", + "nix 0.28.0", + "postcard", + "serde", + "sht31", + "sps30-async 0.2.0 (git+https://github.com/dvdsk/sps30-async)", + "strum", + "tracing", +] + +[[package]] +name = "pulldown-cmark" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" +dependencies = [ + "bitflags 2.5.0", + "memchr", + "unicase", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.23", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sdio-host" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93c025f9cfe4c388c328ece47d11a54a823da3b5ad0370b22d95ad47137f85a" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "serialport" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5a15d0be940df84846264b09b51b10b931fb2f275becb80934e3568a016828" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "core-foundation-sys", + "io-kit-sys", + "mach2", + "nix 0.26.4", + "regex", + "scopeguard", + "unescaper", + "winapi", +] + +[[package]] +name = "sht31" +version = "0.3.1" +source = "git+https://github.com/dvdsk/SHT31-rs#a7b6bd94fb137e16bf326eff5fb591624369a2cf" +dependencies = [ + "crc", + "defmt", + "embedded-hal-async", + "postcard", + "serde", +] + +[[package]] +name = "smoltcp" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a1a996951e50b5971a2c8c0fa05a381480d70a933064245c4a223ddc87ccc97" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "cfg-if", + "defmt", + "heapless 0.8.0", + "managed", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "sps30-async" +version = "0.2.0" +dependencies = [ + "defmt", + "embedded-hal-async", + "embedded-io-async", + "heapless 0.8.0", + "postcard", + "serde", +] + +[[package]] +name = "sps30-async" +version = "0.2.0" +source = "git+https://github.com/dvdsk/sps30-async#a5e81ec034727442c048acea2e8eb07fe4be78e4" +dependencies = [ + "defmt", + "embedded-hal-async", + "embedded-io-async", + "heapless 0.8.0", + "postcard", + "serde", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "static_cell" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89b0684884a883431282db1e4343f34afc2ff6996fe1f4a1664519b66e14c1e" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "stm32-fmc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830ed60f33e6194ecb377f5d6ab765dc0e37e7b65e765f1fa87df13336658d63" +dependencies = [ + "embedded-hal 0.2.7", +] + +[[package]] +name = "stm32-metapac" +version = "15.0.0" +source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-f1297385e91f061fcb6134bb25f51e12d8abff93#acfef07196084706a9621a434d927229b616951f" +dependencies = [ + "cortex-m", + "cortex-m-rt", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7993a8e3a9e88a00351486baae9522c91b123a088f76469e5bd5cc17198ea87" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.66", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "unescaper" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0adf6ad32eb5b3cadff915f7b770faaac8f7ff0476633aa29eb0d9584d889d34" +dependencies = [ + "thiserror", +] + +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/sensor-nodes/bed-sensors/Cargo.toml b/sensor-nodes/bed-sensors/Cargo.toml new file mode 100644 index 00000000..a07ef52e --- /dev/null +++ b/sensor-nodes/bed-sensors/Cargo.toml @@ -0,0 +1,67 @@ +[package] +name = "bed-sensors" +version = "0.2.0" +rust-version = "1.78" +edition = "2021" +license = "GPLv3" +authors = ["David Kleingeld & Eva van Houten"] + +[dependencies] +embassy-stm32 = { version = "0.1.0", features = [ "defmt", "stm32f401cc", +"unstable-pac", "memory-x", "time-driver-tim1", "time", "exti" ] } +embassy-net = { version = "0.4.0", features = ["defmt", "proto-ipv4", "tcp", "dhcpv4","medium-ethernet"] } +embassy-net-wiznet = { version = "0.1.0", features = ["defmt"] } +embassy-sync = { version = "0.5.0", features = ["defmt"] } +embassy-executor = { version = "0.5.0", features = ["arch-cortex-m", +"executor-thread", "defmt", "integrated-timers", "executor-interrupt"] } +embassy-embedded-hal = { version = "0.1.0" } +embassy-time = { version = "0.3.0", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-futures = { version = "0.1.0"} + +defmt = "0.3" +defmt-rtt = "0.4" + +cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } +cortex-m-rt = "0.7.0" +embedded-hal = "0.2.6" +embedded-hal-async = "1.0" +embedded-hal-bus = { version = "0.1", features = ["async", "defmt-03"] } +embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } +panic-probe = { version = "0.3", features = ["print-defmt"] } +futures = { version = "0.3.17", default-features = false, features = ["async-await"] } +heapless = { version = "0.8", default-features = false } +nb = "1.0.0" +rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } +static_cell = "2.0.0" + +# sensors +bosch-bme680 = { version = "1.0.2", git = "https://github.com/dvdsk/async-bosch-bme680" } +max44009 = { version = "0.2", git = "https://github.com/dvdsk/max44009-rs" } +sht31 = { version = "0.3.0", git = "https://github.com/dvdsk/SHT31-rs", features = ["postcard"] } +# mhzx = { version = "0.3.0", git = "https://github.com/dvdsk/mhzx", features = ["postcard"] } +mhzx = { version = "0.3.0", path = "/home/david/tmp/mh-zx-driver", features = ["serde", "postcard"] } +sps30-async = { version = "0.2.0", path = "/home/david/tmp/sps30", features = ["serde", "postcard"] } + +# encoding +protocol = { path = "../protocol" } + +[patch.crates-io] +embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "128575a" } +embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "128575a" } +embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "128575a" } +embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "128575a" } +embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "128575a" } +embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "128575a" } +embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "128575a" } +embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "128575a" } + +[profile.dev] +opt-level = "s" + +[profile.release] +lto = true +opt-level = "s" +incremental = false +codegen-units = 1 +# note: debug = true is okay - debuginfo isn't flashed to the device! +debug = true diff --git a/sensor-nodes/bed-sensors/build.rs b/sensor-nodes/bed-sensors/build.rs new file mode 100644 index 00000000..8cd32d7e --- /dev/null +++ b/sensor-nodes/bed-sensors/build.rs @@ -0,0 +1,5 @@ +fn main() { + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tlink.x"); + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); +} diff --git a/sensor-nodes/bed-sensors/rust-toolchain.toml b/sensor-nodes/bed-sensors/rust-toolchain.toml new file mode 100644 index 00000000..c17f644e --- /dev/null +++ b/sensor-nodes/bed-sensors/rust-toolchain.toml @@ -0,0 +1,6 @@ +[toolchain] +channel = "stable" +components = [ "rust-src", "rustfmt", "llvm-tools" ] +targets = [ + "thumbv7em-none-eabihf", +] diff --git a/sensor-nodes/bed-sensors/src/channel.rs b/sensor-nodes/bed-sensors/src/channel.rs new file mode 100644 index 00000000..db80d46c --- /dev/null +++ b/sensor-nodes/bed-sensors/src/channel.rs @@ -0,0 +1,133 @@ +use defmt::unwrap; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::mutex::Mutex; +use embassy_sync::priority_channel::{self, PriorityChannel}; +use embassy_time::{Duration, Instant}; +use heapless::Vec; +use protocol::large_bedroom::{Error, LargeBedroom}; +use protocol::Sensor; + +struct ErrorEvent { + error: Error, + at: Instant, +} + +pub struct Channel { + queue: PriorityChannel, + recent_errors: Mutex>, +} + +impl Channel { + pub fn new() -> Self { + Self { + queue: PriorityChannel::new(), + recent_errors: Mutex::new(Vec::new()), + } + } + + pub async fn clear(&self) { + while let Ok(_) = self.queue.try_receive() {} + self.recent_errors.lock().await.clear(); + } + + pub async fn receive(&self) -> PriorityValue { + self.queue.receive().await + } + + pub fn next_ready(&self) -> Option { + self.queue.try_receive().ok() + } + + pub fn send_error(&self, error: Error) { + let mut recent_errors = unwrap!(self.recent_errors.try_lock()); + + let mut to_remove: Vec = Vec::new(); + for (idx, event) in recent_errors.iter().enumerate() { + if event.at.elapsed() > Duration::from_secs(60) { + unwrap!(to_remove.push(idx)); + } else if event.error == error { + return; + } + } + + for idx in to_remove.iter().rev() { + recent_errors.swap_remove(*idx); + } + let entry = PriorityValue { + priority: 0, + value: Sensor::LargeBedroomError(error.clone()), + }; + + let full = self.queue.try_send(entry).is_err(); + + if !full { + let _ignore_full = recent_errors.push(ErrorEvent { + error, + at: Instant::now(), + }); + } + } + + pub fn send_p0(&self, value: LargeBedroom) { + let entry = PriorityValue { + priority: 0, + value: Sensor::LargeBedroom(value), + }; + let _ignore_full = self.queue.try_send(entry); + } + pub fn send_p1(&self, value: LargeBedroom) { + let entry = PriorityValue { + priority: 1, + value: Sensor::LargeBedroom(value), + }; + let _ignore_full = self.queue.try_send(entry); + } + + pub fn send_p2(&self, value: LargeBedroom) { + let entry = PriorityValue { + priority: 2, + value: Sensor::LargeBedroom(value), + }; + let _ignore_full = self.queue.try_send(entry); + } + + pub async fn send_critical_error(&self, error: Error) { + let entry = PriorityValue { + priority: 10, + value: Sensor::LargeBedroomError(error), + }; + + self.queue.send(entry).await; + } +} + +/// Higher prio will be send earlier +pub struct PriorityValue { + priority: u8, + pub value: Sensor, +} + +impl PriorityValue { + pub fn low_priority(&self) -> bool { + self.priority < 2 + } +} + +impl Eq for PriorityValue {} +impl PartialEq for PriorityValue { + fn eq(&self, other: &Self) -> bool { + self.priority.eq(&other.priority) + } +} + +impl PartialOrd for PriorityValue { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.priority.cmp(&other.priority)) + } +} + +impl Ord for PriorityValue { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.priority.cmp(&other.priority) + } +} diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs new file mode 100644 index 00000000..a6cf0943 --- /dev/null +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -0,0 +1,249 @@ +#![no_std] +#![no_main] + +use defmt::{error, info, trace, unwrap}; +use embassy_executor::Spawner; +use embassy_futures::select::Either; +use embassy_futures::{join, select}; +use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources}; +use embassy_net_wiznet::{chip::W5500, Device, Runner, State}; +use embassy_stm32::interrupt; +use embassy_stm32::exti::ExtiInput; +use embassy_stm32::gpio::{Level, Output, Pull, Speed}; +use embassy_stm32::i2c::{self, I2c}; +use embassy_stm32::mode::Async; +use embassy_stm32::peripherals::{IWDG, SPI1}; +use embassy_stm32::spi::{Config as SpiConfig, Spi}; +use embassy_stm32::time::Hertz; +use embassy_stm32::usart::{self, DataBits, StopBits, Uart}; +use embassy_stm32::wdg::IndependentWatchdog; +use embassy_stm32::Config; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::mutex::Mutex; +use embassy_sync::signal::Signal; +use embassy_time::{Delay, Timer}; +use embedded_hal_bus::spi::ExclusiveDevice; +use futures::{pin_mut, FutureExt}; +use heapless::Vec; +use rand::{rngs::SmallRng, Rng, SeedableRng}; +use static_cell::StaticCell; + +use {defmt_rtt as _, panic_probe as _}; + +mod channel; +mod network; +mod sensors; +use crate::channel::Channel; + +embassy_stm32::bind_interrupts!(struct Irqs { + I2C1_EV => embassy_stm32::i2c::EventInterruptHandler; + I2C1_ER => embassy_stm32::i2c::ErrorInterruptHandler; + USART1 => embassy_stm32::usart::InterruptHandler; + USART2 => embassy_stm32::usart::InterruptHandler; +}); + +use embassy_executor::InterruptExecutor; +static EXECUTOR_HIGH: InterruptExecutor = InterruptExecutor::new(); + +use embassy_stm32::interrupt::InterruptExt; +#[interrupt] +unsafe fn USART6() { + EXECUTOR_HIGH.on_interrupt() +} + +#[embassy_executor::task] +async fn print_if_running_task() -> ! { + loop { + Timer::after_secs(1).await; + defmt::info!("still running"); + } +} + +type EthernetSPI = ExclusiveDevice, Output<'static>, Delay>; +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner<'static, W5500, EthernetSPI, ExtiInput<'static>, Output<'static>>, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +async fn gen_random_number() -> u64 { + let seed = 5u64; + let mut rng = SmallRng::seed_from_u64(seed); + let seed = rng.gen(); + info!("Seed: {}", seed); + seed +} + +// 84 Mhz clock stm32f401 +fn config() -> Config { + use embassy_stm32::rcc::{ + AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllPreDiv, PllSource, + Sysclk, + }; + + let mut config = Config::default(); + config.rcc.hse = Some(Hse { + freq: Hertz(25_000_000), + mode: HseMode::Oscillator, + }); + config.rcc.pll_src = PllSource::HSE; + config.rcc.pll = Some(Pll { + prediv: PllPreDiv::DIV25, + mul: PllMul::MUL336, + divp: Some(PllPDiv::DIV4), + divq: None, + divr: None, + }); + config.rcc.ahb_pre = AHBPrescaler::DIV1; + config.rcc.apb1_pre = APBPrescaler::DIV2; + config.rcc.apb2_pre = APBPrescaler::DIV1; + config.rcc.sys = Sysclk::PLL1_P; + config +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_stm32::init(config()); + let dog = IndependentWatchdog::new(p.IWDG, 20 * 1000 * 1000); + let publish = Channel::new(); + let seed = gen_random_number().await; + + let mut usart_config = usart::Config::default(); + usart_config.baudrate = 9600; + usart_config.data_bits = DataBits::DataBits8; + usart_config.stop_bits = StopBits::STOP1; + // usart_config.parity = Parity::ParityEven; + let usart_mhz = unwrap!(Uart::new( + p.USART1, + p.PB7, + p.PB6, + Irqs, + p.DMA2_CH7, + p.DMA2_CH2, + usart_config, + )); + + let mut usart_config = usart::Config::default(); + usart_config.baudrate = 115200; + usart_config.data_bits = DataBits::DataBits8; + usart_config.stop_bits = StopBits::STOP1; + // usart_config.parity = Parity::ParityEven; + let usart_sps30 = unwrap!(Uart::new( + p.USART2, + p.PA3, + p.PA2, + Irqs, + p.DMA1_CH6, + p.DMA1_CH5, + usart_config, + )); + + let i2c = I2c::new( + p.I2C1, + p.PB8, + p.PB9, + Irqs, + p.DMA1_CH7, + p.DMA1_CH0, + // extra slow, helps with longer cable runs + Hertz(150_000), + i2c::Config::default(), + ); + let i2c: Mutex = Mutex::new(i2c); + + // let buttons = ButtonInputs { + // top_left: ExtiInput::new(p.PA13, p.EXTI13, Pull::Down), + // top_right: ExtiInput::new(p.PA14, p.EXTI14, Pull::Down), + // middle_inner: ExtiInput::new(p.PA9, p.EXTI9, Pull::Down), + // middle_center: ExtiInput::new(p.PA10, p.EXTI10, Pull::Down), + // middle_outer: ExtiInput::new(p.PA11, p.EXTI11, Pull::Down), + // lower_inner: ExtiInput::new(p.PA12, p.EXTI12, Pull::Down), + // lower_center: ExtiInput::new(p.PA15, p.EXTI15, Pull::Down), + // lower_outer: ExtiInput::new(p.PB5, p.EXTI5, Pull::Down), + // }; + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = Hertz(50_000_000); // up to 50m works + let (miso, mosi, clk) = (p.PA6, p.PA7, p.PA5); + let spi = Spi::new(p.SPI1, clk, mosi, miso, p.DMA2_CH3, p.DMA2_CH0, spi_cfg); + let cs = Output::new(p.PA4, Level::High, Speed::VeryHigh); + + let w5500_int = ExtiInput::new(p.PB0, p.EXTI0, Pull::Up); + let w5500_reset = Output::new(p.PB1, Level::High, Speed::VeryHigh); + + let mac_addr = [0x02, 234, 3, 4, 82, 231]; + static STATE: StaticCell> = StaticCell::new(); + let state = STATE.init(State::<8, 8>::new()); + let (device, runner) = embassy_net_wiznet::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs, Delay), + w5500_int, + w5500_reset, + ) + .await; + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Init network stack + let mut dns_servers: Vec<_, 3> = Vec::new(); + unwrap!(dns_servers.push(Ipv4Address([192, 168, 1, 1]))); + unwrap!(dns_servers.push(Ipv4Address([192, 168, 1, 1]))); + unwrap!(dns_servers.push(Ipv4Address([192, 168, 1, 1]))); + static STACK: StaticCell>> = StaticCell::new(); + static RESOURCES: StaticCell> = StaticCell::new(); + let stack = &*STACK.init(Stack::new( + device, + embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { + address: Ipv4Cidr::new(Ipv4Address([192, 168, 1, 6]), 24), + gateway: Some(Ipv4Address([192, 168, 1, 1])), + dns_servers, + }), + RESOURCES.init(StackResources::<2>::new()), + seed, + )); + + // Launch network task + unwrap!(spawner.spawn(net_task(stack))); + + embassy_stm32::interrupt::USART6.set_priority(embassy_stm32::interrupt::Priority::P6); + let spawner = EXECUTOR_HIGH.start(embassy_stm32::interrupt::USART6); + unwrap!(spawner.spawn(print_if_running_task())); + + let network_up: Signal = Signal::new(); + network_up.signal(()); + let send_published = network::send_published(stack, &publish, &network_up); + pin_mut!(send_published); + let keep_dog_happy = keep_dog_happy(dog); + let send_and_pet_dog = join::join(&mut send_published, keep_dog_happy); + + let init_then_measure = sensors::init_then_measure(&publish, i2c, usart_mhz, usart_sps30); + let init_then_measure = network_up.wait().then(|_| init_then_measure); + let res = select::select(send_and_pet_dog, init_then_measure).await; + let unrecoverable_err = match res { + Either::First(_) => defmt::unreachable!(), + Either::Second(Ok(())) => defmt::unreachable!(), + Either::Second(Err(err)) => err, + }; + + let send_critical_error = join::join( + publish.send_critical_error(unrecoverable_err.clone()), + send_published, + ); + error!("unrecoverable error, resetting: {}", unrecoverable_err); + send_critical_error.await; // if this takes too long the dog will get us +} + +async fn keep_dog_happy<'a>(mut dog: IndependentWatchdog<'a, IWDG>) { + loop { + dog.unleash(); + Timer::after_secs(8).await; + trace!("petting dog"); + dog.pet(); + } +} diff --git a/sensor-nodes/bed-sensors/src/network.rs b/sensor-nodes/bed-sensors/src/network.rs new file mode 100644 index 00000000..f4084568 --- /dev/null +++ b/sensor-nodes/bed-sensors/src/network.rs @@ -0,0 +1,86 @@ +use core::mem; + +use defmt::{info, unwrap, warn}; +use embassy_net::driver::Driver; +use embassy_net::tcp::TcpSocket; +use embassy_net::{Ipv4Address, Stack}; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::signal::Signal; +use embassy_time::{with_timeout, Duration, Instant, Timer}; +use embedded_io_async::Write; +use protocol::SensorMessage; + +use crate::channel::Channel; + +type Msg = SensorMessage<6>; + +async fn get_messages(publish: &Channel, msg: &mut Msg) { + msg.values.clear(); + let next = publish.receive().await; + let low_priority = next.low_priority(); + unwrap!(msg.values.push(next.value)); + + if low_priority { + let deadline = Instant::now() + Duration::from_millis(200); + while msg.space_left() { + let until = deadline.saturating_duration_since(Instant::now()); + match with_timeout(until, publish.receive()).await { + Ok(new) if new.low_priority() => { + unwrap!(msg.values.push(new.value)); + } + Ok(new) => { + unwrap!(msg.values.push(new.value)); + break; + } + Err(_timeout) => break, + } + } + } else { + while msg.space_left() { + let Some(next) = publish.next_ready() else { + break; + }; + unwrap!(msg.values.push(next.value)); + } + } +} + +pub async fn send_published( + stack: &Stack, + publish: &Channel, + network_up: &Signal, +) { + let mut rx_buffer = [0; 800]; + let mut tx_buffer = [0; Msg::ENCODED_SIZE * 4]; + + let mut msg = Msg::new(); + let mut encoded_msg_buffer = [0; Msg::ENCODED_SIZE]; + + let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(Duration::from_secs(5))); + let host_addr = Ipv4Address::new(192, 168, 1, 46); + let host_port = 1234; + + loop { + let connected = socket.remote_endpoint().is_some(); + if !connected { + if let Err(e) = socket.connect((host_addr, host_port)).await { + warn!("connect error: {:?}", e); + Timer::after_secs(1).await; + continue; + } else { + info!("(re-)connected"); + // prevent out-dated data from being send + publish.clear().await; + network_up.signal(()); + } + } + + get_messages(publish, &mut msg).await; + let to_send = msg.encode_slice(&mut encoded_msg_buffer); + + if let Err(e) = socket.write_all(to_send).await { + warn!("write error: {:?}", e); + } + } +} diff --git a/sensor-nodes/bed-sensors/src/sensors.rs b/sensor-nodes/bed-sensors/src/sensors.rs new file mode 100644 index 00000000..74e99b2b --- /dev/null +++ b/sensor-nodes/bed-sensors/src/sensors.rs @@ -0,0 +1,90 @@ +use embassy_embedded_hal::shared_bus; +use embassy_futures::join; +use embassy_stm32::i2c::I2c; +use embassy_stm32::mode::Async; +use embassy_stm32::peripherals::{I2C1, USART1, USART2}; +use embassy_stm32::usart::Uart; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::mutex::Mutex; +use embassy_time::{with_timeout, Delay, Duration}; +use max44009::{Max44009, SlaveAddr}; +use mhzx::MHZ; +use protocol::downcast_err::ConcreteErrorType; +use sps30_async::Sps30; + +use crate::channel::Channel; + +pub mod fast; +pub mod slow; + +// Todo make failed init not critical. Keep trying init in background +// while we are measuring + +pub async fn init_then_measure( + publish: &Channel, + i2c: Mutex>, + usart_mhz: Uart<'static, USART1, Async>, + usart_sps: Uart<'static, USART2, Async>, +) -> Result<(), protocol::large_bedroom::Error> { + use protocol::large_bedroom::Device; + use protocol::large_bedroom::Error; + use protocol::large_bedroom::SensorError; + + let bme_config = bosch_bme680::Configuration::default(); + let bme = with_timeout( + Duration::from_secs(12), + bosch_bme680::Bme680::new( + shared_bus::asynch::i2c::I2cDevice::new(&i2c), + bosch_bme680::DeviceAddress::Secondary, + Delay, + &bme_config, + 20, + ), + ) + .await + .map_err(|_| Error::SetupTimedOut(Device::Bme680))? + .map_err(|err| err.strip_generics()) + .map_err(SensorError::Bme680) + .map_err(Error::Setup)?; + + let mut max44009 = Max44009::new( + shared_bus::asynch::i2c::I2cDevice::new(&i2c), + SlaveAddr::default(), + ); + with_timeout( + Duration::from_millis(250), + max44009.set_measurement_mode(max44009::MeasurementMode::Continuous), + ) + .await + .map_err(|_| Error::SetupTimedOut(Device::Max44))? + .map_err(|err| err.strip_generics()) + .map_err(SensorError::Max44) + .map_err(Error::Setup)?; + + let sht = sht31::SHT31::new(shared_bus::asynch::i2c::I2cDevice::new(&i2c), Delay) + .with_mode(sht31::mode::SingleShot) + .with_unit(sht31::TemperatureUnit::Celsius) + .with_accuracy(sht31::Accuracy::High); + + let (tx, rx) = usart_mhz.split(); + let mut usart_buf = [0u8; 9 * 10]; // 9 byte messages + let rx = rx.into_ring_buffered(&mut usart_buf); + let mhz = MHZ::from_tx_rx(tx, rx); + + let (tx, rx) = usart_sps.split(); + let mut usart_buf = [0u8; 100]; + let rx = rx.into_ring_buffered(&mut usart_buf); + defmt::info!("hi"); + let sps30 = with_timeout(Duration::from_millis(100), Sps30::from_tx_rx(tx, rx, Delay)) + .await + .map_err(|_| Error::SetupTimedOut(Device::Sps30))? + .map_err(|err| err.strip_generics()) + .map_err(SensorError::Sps30) + .map_err(Error::Setup)?; + + let sensors_fast = fast::read(max44009, /*buttons,*/ &publish); + let sensors_slow = slow::read(sht, bme, mhz, sps30, &publish); + join::join(sensors_fast, sensors_slow).await; + + defmt::unreachable!(); +} diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed-sensors/src/sensors/fast.rs new file mode 100644 index 00000000..7b63538b --- /dev/null +++ b/sensor-nodes/bed-sensors/src/sensors/fast.rs @@ -0,0 +1,124 @@ +use defmt::{unwrap, warn}; +use embassy_futures::{ + join::{self, join3}, + yield_now, +}; +use embassy_stm32::exti::ExtiInput; +use embassy_time::{Duration, Instant, Timer}; +use embedded_hal_async::i2c::I2c; +use max44009::Max44009; + +use crate::channel::Channel; + +use protocol::downcast_err::{ConcreteErrorType, I2cError}; +use protocol::large_bedroom::{self, BedButton, LargeBedroom as LB}; + +fn sig_lux_diff(old: f32, new: f32) -> bool { + let diff = old - new; + // we do not have f32::abs on embedded + diff > old / 20.0 || -diff > old / 20.0 +} + +async fn report_lux( + mut max44: Max44009, + publish: &Channel, +) where + I2C: I2c, + I2C::Error: defmt::Format, + ::Error: Into, +{ + let mut prev_lux = f32::MAX; + let mut last_lux = Instant::now(); + const MIN_INTERVAL: Duration = Duration::from_secs(1); + + // todo!("reinit devices after error"); + loop { + Timer::after_millis(50).await; + let lux = match max44.read_lux().await { + Ok(lux) => lux, + Err(err) if last_lux.elapsed() > MIN_INTERVAL => { + let err = large_bedroom::SensorError::Max44(err.strip_generics()); + let err = large_bedroom::Error::Running(err); + let _ignore = publish.send_error(err); + continue; + } + Err(_) => continue, + }; + + if sig_lux_diff(prev_lux, lux) { + publish.send_p2(LB::Brightness(lux)) + } else if last_lux.elapsed() > MIN_INTERVAL { + publish.send_p1(LB::Brightness(lux)) + } else { + yield_now().await; + continue; + }; + + prev_lux = lux; + last_lux = Instant::now(); + } +} + +async fn watch_button( + mut input: ExtiInput<'static>, + event: impl Fn(protocol::Press) -> BedButton, + channel: &Channel, +) { + let mut went_high_at: Option = None; + loop { + if let Some(went_high_at) = went_high_at.take() { + input.wait_for_falling_edge().await; + let press = went_high_at.elapsed(); + if press > Duration::from_millis(5) { + let Ok(press) = press.as_millis().try_into() else { + warn!("extremely long button press registered, skipping"); + continue; + }; + let event = (event)(protocol::Press(press)); + let _ignore_full = channel.send_p2(LB::BedButton(event)); + } + } else { + input.wait_for_rising_edge().await; + went_high_at = Some(Instant::now()); + } + } +} + +pub struct ButtonInputs { + pub top_left: ExtiInput<'static>, + pub top_right: ExtiInput<'static>, + pub middle_inner: ExtiInput<'static>, + pub middle_center: ExtiInput<'static>, + pub middle_outer: ExtiInput<'static>, + pub lower_inner: ExtiInput<'static>, + pub lower_center: ExtiInput<'static>, + pub lower_outer: ExtiInput<'static>, +} + +pub async fn read( + max44: Max44009, + /*inputs: ButtonInputs,*/ + publish: &Channel, +) where + I2C: I2c, + I2C::Error: defmt::Format, + ::Error: Into, +{ + // let watch_buttons_1 = join5( + // watch_button(inputs.top_left, BedButton::TopLeft, publish), + // watch_button(inputs.top_right, BedButton::TopRight, publish), + // watch_button(inputs.middle_inner, BedButton::MiddleInner, publish), + // watch_button(inputs.middle_center, BedButton::MiddleCenter, publish), + // watch_button(inputs.middle_outer, BedButton::MiddleOuter, publish), + // ); + // + // let watch_buttons_2 = join3( + // watch_button(inputs.lower_inner, BedButton::LowerInner, publish), + // watch_button(inputs.lower_center, BedButton::LowerCenter, publish), + // watch_button(inputs.lower_outer, BedButton::LowerOuter, publish), + // ); + + let watch_lux = report_lux(max44, publish); + watch_lux.await; + // join::join3(watch_buttons_1, watch_buttons_2, watch_lux).await; +} diff --git a/sensor-nodes/bed-sensors/src/sensors/slow.rs b/sensor-nodes/bed-sensors/src/sensors/slow.rs new file mode 100644 index 00000000..37e86123 --- /dev/null +++ b/sensor-nodes/bed-sensors/src/sensors/slow.rs @@ -0,0 +1,211 @@ +use core::fmt; + +use defmt::unwrap; +use embassy_futures::{join, yield_now}; +use embassy_time::{with_timeout, Delay, Duration, Timer}; +use embedded_hal_async::delay::DelayNs; +use embedded_hal_async::i2c::I2c; + +use mhzx::MHZ; +use protocol::downcast_err::{ConcreteErrorType, I2cError, UartError}; +use protocol::large_bedroom::{Device, LargeBedroom as LB}; + +use bosch_bme680::{Bme680, MeasurementData}; +use sht31::mode::{Sht31Measure, Sht31Reader, SingleShot}; +use sht31::SHT31; +use sps30_async as sps30; +use sps30_async::Sps30; + +use crate::channel::Channel; + +const SPS30_UART_BUF_SIZE: usize = 100; +const SPS30_DRIVER_BUF_SIZE: usize = 2 * SPS30_UART_BUF_SIZE; + +pub async fn read( + mut sht: SHT31, + mut bme: Bme680, + mut mhz: MHZ, + mut sps: Sps30, + publish: &Channel, +) where + I2C: I2c, + I2C::Error: defmt::Format, + ::Error: Into, + TX1: embedded_io_async::Write, + TX1::Error: defmt::Format + Into, + RX1: embedded_io_async::Read, + RX1::Error: defmt::Format + Into, + TX2: embedded_io_async::Write, + TX2::Error: defmt::Format + Into, + RX2: embedded_io_async::Read, + RX2::Error: defmt::Format + Into, +{ + // sht works in two steps + // - send measure command before sleep + // - then read + if let Err(err) = sht.measure().await { + let err = protocol::large_bedroom::SensorError::Sht31(err); + let err = protocol::large_bedroom::Error::Running(err); + publish.send_error(err) + } + Timer::after_secs(1).await; + + loop { + defmt::info!("this is where we break"); + let sht_read = with_timeout(Duration::from_millis(100), sht.read()); + yield_now().await; + let bme_measure = bme.measure(); + yield_now().await; + let mhz_measure = with_timeout(Duration::from_millis(100), mhz.read_co2()); + yield_now().await; + let sps_measure = with_timeout(Duration::from_millis(100), sps.read_measurement()); + yield_now().await; // with this yield enabled the program hangs within 12 seconds + let (bme_res, sht_res, mhz_res, sps_res) = + join::join4(bme_measure, sht_read, mhz_measure, sps_measure).await; + // let (bme_res, sht_res, mhz_res) = join::join3(bme_measure, sht_read, mhz_measure).await; + yield_now().await; + + publish_bme_result(bme_res, publish); + yield_now().await; + publish_sht_result(sht_res, publish); + yield_now().await; + publish_mhz_result(mhz_res, publish); + yield_now().await; + publish_sps_result(sps_res, publish); + + // sht works in two steps + // - send measure command before sleep + // - then read + if let Err(err) = sht.measure().await { + let err = protocol::large_bedroom::SensorError::Sht31(err); + let err = protocol::large_bedroom::Error::Running(err); + publish.send_error(err) + } + Timer::after_secs(1).await; + } +} + +fn publish_sps_result( + sps_res: Result< + Result, sps30::Error>, + embassy_time::TimeoutError, + >, + publish: &Channel, +) where + TxError: fmt::Debug + defmt::Format + Into, + RxError: fmt::Debug + defmt::Format + Into, +{ + match sps_res { + Ok(Ok(Some(sps30::Measurement { + mass_pm1_0, + mass_pm2_5, + mass_pm4_0, + mass_pm10, + mass_pm0_5, + number_pm1_0, + number_pm2_5, + number_pm4_0, + number_pm10, + typical_particle_size, + }))) => { + publish.send_p0(LB::MassPm1_0(mass_pm1_0)); + publish.send_p0(LB::MassPm2_5(mass_pm2_5)); + publish.send_p0(LB::MassPm4_0(mass_pm4_0)); + publish.send_p0(LB::MassPm10(mass_pm10)); + publish.send_p0(LB::MassPm0_5(mass_pm0_5)); + publish.send_p0(LB::NumberPm1_0(number_pm1_0)); + publish.send_p0(LB::NumberPm2_5(number_pm2_5)); + publish.send_p0(LB::NumberPm4_0(number_pm4_0)); + publish.send_p0(LB::NumberPm10(number_pm10)); + publish.send_p0(LB::TypicalParticleSize(typical_particle_size)); + } + Ok(Ok(None)) => { + defmt::todo!("no idea when we hit this"); + } + Ok(Err(err)) => { + let err = err.strip_generics(); + let err = protocol::large_bedroom::SensorError::Sps30(err); + let err = protocol::large_bedroom::Error::Running(err); + publish.send_error(err) + } + Err(_timeout) => { + let err = protocol::large_bedroom::Error::Timeout(Device::Sps30); + publish.send_error(err) + } + } +} + +fn publish_mhz_result( + mhz_res: Result< + Result>, + embassy_time::TimeoutError, + >, + publish: &Channel, +) where + TxError: fmt::Debug + defmt::Format + Into, + RxError: fmt::Debug + defmt::Format + Into, +{ + match mhz_res { + Ok(Ok(mhzx::Measurement { co2, .. })) => { + publish.send_p0(LB::Co2(co2)); + } + Ok(Err(err)) => { + let err = err.strip_generics(); + let err = protocol::large_bedroom::SensorError::Mhz14(err); + let err = protocol::large_bedroom::Error::Running(err); + publish.send_error(err) + } + Err(_timeout) => { + let err = protocol::large_bedroom::Error::Timeout(Device::Mhz14); + publish.send_error(err) + } + } +} + +fn publish_sht_result( + sht_res: Result, embassy_time::TimeoutError>, + publish: &Channel, +) { + match sht_res { + Ok(Ok(sht31::Reading { + temperature, + humidity, + })) => { + publish.send_p0(LB::Temperature(temperature)); + publish.send_p0(LB::Humidity(humidity)); + } + Ok(Err(err)) => { + let err = protocol::large_bedroom::SensorError::Sht31(err); + let err = protocol::large_bedroom::Error::Running(err); + publish.send_error(err) + } + Err(_timeout) => { + let err = protocol::large_bedroom::Error::Timeout(Device::Sht31); + publish.send_error(err) + } + } +} + +fn publish_bme_result( + bme_res: Result>, + publish: &Channel, +) where + E: Into, +{ + match bme_res { + Ok(MeasurementData { + pressure, + gas_resistance, + .. + }) => { + let gas_resistance = unwrap!(gas_resistance); // sensor is on + publish.send_p0(LB::GassResistance(gas_resistance)); + publish.send_p0(LB::Pressure(pressure)); + } + Err(err) => { + let err = protocol::large_bedroom::SensorError::Bme680(err.strip_generics()); + let err = protocol::large_bedroom::Error::Running(err); + publish.send_error(err) + } + } +} From e05f4574f039df79c5032731bf35a3a8304113fa Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 3 Jun 2024 14:55:04 +0200 Subject: [PATCH 119/687] fix workspace eating up sensor-nodes --- Cargo.toml | 2 + sensor-nodes/bed-sensors/Cargo.lock | 430 +++------------------------- sensor-nodes/bed-sensors/Cargo.toml | 2 +- 3 files changed, 37 insertions(+), 397 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9e16af4d..bf1f3520 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,11 @@ [workspace] resolver = "2" members = ["crates/*"] +exclude = ["sensor-nodes/bed-sensors"] [workspace.package] rust-version = "1.78" edition = "2021" license = "GPLv3" authors = ["David Kleingeld & Eva van Houten"] + diff --git a/sensor-nodes/bed-sensors/Cargo.lock b/sensor-nodes/bed-sensors/Cargo.lock index 113bc129..021ca323 100644 --- a/sensor-nodes/bed-sensors/Cargo.lock +++ b/sensor-nodes/bed-sensors/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - [[package]] name = "atomic-polyfill" version = "1.0.3" @@ -35,6 +26,40 @@ dependencies = [ "rustc_version 0.2.3", ] +[[package]] +name = "bed-sensors" +version = "0.2.0" +dependencies = [ + "bosch-bme680", + "cortex-m", + "cortex-m-rt", + "defmt", + "defmt-rtt", + "embassy-embedded-hal", + "embassy-executor", + "embassy-futures", + "embassy-net", + "embassy-net-wiznet", + "embassy-stm32", + "embassy-sync", + "embassy-time", + "embedded-hal 0.2.7", + "embedded-hal-async", + "embedded-hal-bus", + "embedded-io-async", + "futures", + "heapless 0.8.0", + "max44009", + "mhzx", + "nb 1.1.0", + "panic-probe", + "protocol", + "rand", + "sht31", + "sps30-async", + "static_cell", +] + [[package]] name = "bit_field" version = "0.10.2" @@ -65,18 +90,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" -[[package]] -name = "bme280" -version = "0.5.1" -source = "git+https://github.com/dvdsk/bme280-rs#4999b005d26a16312acb3dbc64b72658df49a16d" -dependencies = [ - "defmt", - "embedded-hal 1.0.0", - "maybe-async-cfg", - "postcard", - "serde", -] - [[package]] name = "bosch-bme680" version = "1.0.2" @@ -86,8 +99,6 @@ dependencies = [ "defmt", "embedded-hal 1.0.0", "embedded-hal-async", - "postcard", - "serde", ] [[package]] @@ -96,24 +107,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - [[package]] name = "cobs" version = "0.2.3" @@ -140,12 +139,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "core-foundation-sys" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" - [[package]] name = "cortex-m" version = "0.7.7" @@ -692,39 +685,6 @@ dependencies = [ "pin-utils", ] -[[package]] -name = "gpiocdev" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5119c89eccee09c4f6e9ca2b112aea1cd80bac31cd29169f171a48ae5552d1c" -dependencies = [ - "gpiocdev-uapi", - "thiserror", -] - -[[package]] -name = "gpiocdev-embedded-hal" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26476d24320fe1b9ebc76392f984abe4a6147844c7e5a69538318f15b026cca8" -dependencies = [ - "embedded-hal 1.0.0", - "gpiocdev", - "thiserror", -] - -[[package]] -name = "gpiocdev-uapi" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a02357253f833a6ce4e93f17e8dd3e169c941ea71b83d442ed9c55f784045204" -dependencies = [ - "bitflags 2.5.0", - "ioctl-sys", - "libc", - "thiserror", -] - [[package]] name = "hash32" version = "0.2.1" @@ -775,95 +735,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "i2cdev" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597f56d08cebc0fb3e67d49f48124f49e1c7ac297a21d60bc90a28b9482fb35c" -dependencies = [ - "bitflags 2.5.0", - "byteorder", - "libc", - "nix 0.26.4", -] - [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -[[package]] -name = "io-kit-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b" -dependencies = [ - "core-foundation-sys", - "mach2", -] - -[[package]] -name = "ioctl-sys" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd11f3a29434026f5ff98c730b668ba74b1033637b8817940b54d040696133c" - -[[package]] -name = "large-bed" -version = "0.1.0" -dependencies = [ - "bosch-bme680", - "cortex-m", - "cortex-m-rt", - "defmt", - "defmt-rtt", - "embassy-embedded-hal", - "embassy-executor", - "embassy-futures", - "embassy-net", - "embassy-net-wiznet", - "embassy-stm32", - "embassy-sync", - "embassy-time", - "embedded-hal 0.2.7", - "embedded-hal-async", - "embedded-hal-bus", - "embedded-io-async", - "futures", - "heapless 0.8.0", - "max44009", - "mhzx 0.3.0", - "nb 1.1.0", - "panic-probe", - "protocol", - "rand", - "sht31", - "sps30-async 0.2.0", - "static_cell", -] - -[[package]] -name = "libc" -version = "0.2.155" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" - -[[package]] -name = "linux-embedded-hal" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d566b726e1b6810f66c6f1c769889248439c27f06a59df2881a735454cfa02" -dependencies = [ - "cast", - "embedded-hal 1.0.0", - "embedded-hal-nb", - "i2cdev", - "nb 1.1.0", - "nix 0.27.1", - "serialport", -] - [[package]] name = "litrs" version = "0.4.1" @@ -880,15 +757,6 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "mach2" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" -dependencies = [ - "libc", -] - [[package]] name = "managed" version = "0.8.0" @@ -902,44 +770,11 @@ source = "git+https://github.com/dvdsk/max44009-rs#7b7df2e3173476c250fca3eb242f0 dependencies = [ "defmt", "embedded-hal-async", - "postcard", - "serde", -] - -[[package]] -name = "maybe-async-cfg" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21fb8fac02158b9b529eb692491895d8459dbac939f3bc6e32159969646ffe55" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "pulldown-cmark", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "memchr" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[package]] -name = "mhzx" -version = "0.3.0" -dependencies = [ - "defmt", - "embedded-io-async", - "heapless 0.8.0", - "postcard", - "serde", ] [[package]] name = "mhzx" version = "0.3.0" -source = "git+https://github.com/dvdsk/mhzx#08f6e7adb4ec98749fa84f24f8ff9e0e3c83d164" dependencies = [ "defmt", "embedded-io-async", @@ -963,40 +798,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" -[[package]] -name = "nix" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", -] - -[[package]] -name = "nix" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "libc", -] - -[[package]] -name = "nix" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "cfg_aliases", - "libc", -] - [[package]] name = "no-std-net" version = "0.6.0" @@ -1012,12 +813,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - [[package]] name = "panic-probe" version = "0.3.2" @@ -1107,36 +902,11 @@ dependencies = [ name = "protocol" version = "0.1.0" dependencies = [ - "bme280", - "bosch-bme680", "defmt", - "embassy-embedded-hal", - "embassy-stm32", - "embedded-hal 1.0.0", - "gpiocdev", - "gpiocdev-embedded-hal", "heapless 0.8.0", - "linux-embedded-hal", - "max44009", - "mhzx 0.3.0 (git+https://github.com/dvdsk/mhzx)", - "nix 0.28.0", "postcard", "serde", - "sht31", - "sps30-async 0.2.0 (git+https://github.com/dvdsk/sps30-async)", "strum", - "tracing", -] - -[[package]] -name = "pulldown-cmark" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" -dependencies = [ - "bitflags 2.5.0", - "memchr", - "unicase", ] [[package]] @@ -1163,35 +933,6 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -[[package]] -name = "regex" -version = "1.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" - [[package]] name = "rustc_version" version = "0.2.3" @@ -1269,24 +1010,6 @@ dependencies = [ "syn 2.0.66", ] -[[package]] -name = "serialport" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f5a15d0be940df84846264b09b51b10b931fb2f275becb80934e3568a016828" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "core-foundation-sys", - "io-kit-sys", - "mach2", - "nix 0.26.4", - "regex", - "scopeguard", - "unescaper", - "winapi", -] - [[package]] name = "sht31" version = "0.3.1" @@ -1296,7 +1019,6 @@ dependencies = [ "defmt", "embedded-hal-async", "postcard", - "serde", ] [[package]] @@ -1334,19 +1056,6 @@ dependencies = [ "serde", ] -[[package]] -name = "sps30-async" -version = "0.2.0" -source = "git+https://github.com/dvdsk/sps30-async#a5e81ec034727442c048acea2e8eb07fe4be78e4" -dependencies = [ - "defmt", - "embedded-hal-async", - "embedded-io-async", - "heapless 0.8.0", - "postcard", - "serde", -] - [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1456,55 +1165,6 @@ dependencies = [ "syn 2.0.66", ] -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] - -[[package]] -name = "unescaper" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0adf6ad32eb5b3cadff915f7b770faaac8f7ff0476633aa29eb0d9584d889d34" -dependencies = [ - "thiserror", -] - -[[package]] -name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - [[package]] name = "unicode-ident" version = "1.0.12" @@ -1543,25 +1203,3 @@ checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" dependencies = [ "vcell", ] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/sensor-nodes/bed-sensors/Cargo.toml b/sensor-nodes/bed-sensors/Cargo.toml index a07ef52e..b4eebc9e 100644 --- a/sensor-nodes/bed-sensors/Cargo.toml +++ b/sensor-nodes/bed-sensors/Cargo.toml @@ -43,7 +43,7 @@ mhzx = { version = "0.3.0", path = "/home/david/tmp/mh-zx-driver", features = [" sps30-async = { version = "0.2.0", path = "/home/david/tmp/sps30", features = ["serde", "postcard"] } # encoding -protocol = { path = "../protocol" } +protocol = { path = "../../crates/protocol" } [patch.crates-io] embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "128575a" } From c503b20706f352f293117868a55250f2f19c8b96 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 3 Jun 2024 15:26:59 +0200 Subject: [PATCH 120/687] format error string on device --- crates/protocol/src/lib.rs | 7 +- sensor-nodes/bed-sensors/src/channel.rs | 33 ++++--- sensor-nodes/bed-sensors/src/network.rs | 2 - sensor-nodes/bed-sensors/src/sensors.rs | 14 ++- sensor-nodes/bed-sensors/src/sensors/fast.rs | 44 +++++---- sensor-nodes/bed-sensors/src/sensors/slow.rs | 93 ++++++++++---------- 6 files changed, 99 insertions(+), 94 deletions(-) diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 9a52bbcf..cd2bef08 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -228,10 +228,13 @@ impl SensorMessage { } pub type ErrorString = heapless::String<200>; -pub fn make_error_string(e: impl core::fmt::Display) -> ErrorString { +// thiserror does not work on nostd. That will change when this lands: +// https://github.com/rust-lang/rust/issues/103765 +// at that point try switching this to fmt::Display +pub fn make_error_string(e: impl core::fmt::Debug) -> ErrorString { use core::fmt::Write; let mut s = ErrorString::new(); - core::write!(s, "{e}").ok(); + core::write!(s, "{e:?}").ok(); s } diff --git a/sensor-nodes/bed-sensors/src/channel.rs b/sensor-nodes/bed-sensors/src/channel.rs index db80d46c..a60bd0ed 100644 --- a/sensor-nodes/bed-sensors/src/channel.rs +++ b/sensor-nodes/bed-sensors/src/channel.rs @@ -4,8 +4,7 @@ use embassy_sync::mutex::Mutex; use embassy_sync::priority_channel::{self, PriorityChannel}; use embassy_time::{Duration, Instant}; use heapless::Vec; -use protocol::large_bedroom::{Error, LargeBedroom}; -use protocol::Sensor; +use protocol::large_bedroom::bed::{self, Error, Reading}; struct ErrorEvent { error: Error, @@ -38,7 +37,7 @@ impl Channel { self.queue.try_receive().ok() } - pub fn send_error(&self, error: Error) { + pub fn send_error(&self, error: bed::Error) { let mut recent_errors = unwrap!(self.recent_errors.try_lock()); let mut to_remove: Vec = Vec::new(); @@ -55,7 +54,9 @@ impl Channel { } let entry = PriorityValue { priority: 0, - value: Sensor::LargeBedroomError(error.clone()), + value: Err(protocol::Error::LargeBedroom( + protocol::large_bedroom::Error::Bed(error.clone()), + )), }; let full = self.queue.try_send(entry).is_err(); @@ -68,25 +69,31 @@ impl Channel { } } - pub fn send_p0(&self, value: LargeBedroom) { + pub fn send_p0(&self, value: Reading) { let entry = PriorityValue { priority: 0, - value: Sensor::LargeBedroom(value), + value: Ok(protocol::Reading::LargeBedroom( + protocol::large_bedroom::Reading::Bed(value), + )), }; let _ignore_full = self.queue.try_send(entry); } - pub fn send_p1(&self, value: LargeBedroom) { + pub fn send_p1(&self, value: Reading) { let entry = PriorityValue { priority: 1, - value: Sensor::LargeBedroom(value), + value: Ok(protocol::Reading::LargeBedroom( + protocol::large_bedroom::Reading::Bed(value), + )), }; let _ignore_full = self.queue.try_send(entry); } - pub fn send_p2(&self, value: LargeBedroom) { + pub fn send_p2(&self, value: Reading) { let entry = PriorityValue { priority: 2, - value: Sensor::LargeBedroom(value), + value: Ok(protocol::Reading::LargeBedroom( + protocol::large_bedroom::Reading::Bed(value), + )), }; let _ignore_full = self.queue.try_send(entry); } @@ -94,7 +101,9 @@ impl Channel { pub async fn send_critical_error(&self, error: Error) { let entry = PriorityValue { priority: 10, - value: Sensor::LargeBedroomError(error), + value: Err(protocol::Error::LargeBedroom( + protocol::large_bedroom::Error::Bed(error), + )), }; self.queue.send(entry).await; @@ -104,7 +113,7 @@ impl Channel { /// Higher prio will be send earlier pub struct PriorityValue { priority: u8, - pub value: Sensor, + pub value: Result, } impl PriorityValue { diff --git a/sensor-nodes/bed-sensors/src/network.rs b/sensor-nodes/bed-sensors/src/network.rs index f4084568..5a4527a0 100644 --- a/sensor-nodes/bed-sensors/src/network.rs +++ b/sensor-nodes/bed-sensors/src/network.rs @@ -1,5 +1,3 @@ -use core::mem; - use defmt::{info, unwrap, warn}; use embassy_net::driver::Driver; use embassy_net::tcp::TcpSocket; diff --git a/sensor-nodes/bed-sensors/src/sensors.rs b/sensor-nodes/bed-sensors/src/sensors.rs index 74e99b2b..55a5e6f7 100644 --- a/sensor-nodes/bed-sensors/src/sensors.rs +++ b/sensor-nodes/bed-sensors/src/sensors.rs @@ -9,7 +9,8 @@ use embassy_sync::mutex::Mutex; use embassy_time::{with_timeout, Delay, Duration}; use max44009::{Max44009, SlaveAddr}; use mhzx::MHZ; -use protocol::downcast_err::ConcreteErrorType; +use protocol::large_bedroom::bed::{Device, Error, SensorError}; +use protocol::make_error_string; use sps30_async::Sps30; use crate::channel::Channel; @@ -25,10 +26,7 @@ pub async fn init_then_measure( i2c: Mutex>, usart_mhz: Uart<'static, USART1, Async>, usart_sps: Uart<'static, USART2, Async>, -) -> Result<(), protocol::large_bedroom::Error> { - use protocol::large_bedroom::Device; - use protocol::large_bedroom::Error; - use protocol::large_bedroom::SensorError; +) -> Result<(), protocol::large_bedroom::bed::Error> { let bme_config = bosch_bme680::Configuration::default(); let bme = with_timeout( @@ -43,7 +41,7 @@ pub async fn init_then_measure( ) .await .map_err(|_| Error::SetupTimedOut(Device::Bme680))? - .map_err(|err| err.strip_generics()) + .map_err(|err| make_error_string(err)) .map_err(SensorError::Bme680) .map_err(Error::Setup)?; @@ -57,7 +55,7 @@ pub async fn init_then_measure( ) .await .map_err(|_| Error::SetupTimedOut(Device::Max44))? - .map_err(|err| err.strip_generics()) + .map_err(|err| make_error_string(err)) .map_err(SensorError::Max44) .map_err(Error::Setup)?; @@ -78,7 +76,7 @@ pub async fn init_then_measure( let sps30 = with_timeout(Duration::from_millis(100), Sps30::from_tx_rx(tx, rx, Delay)) .await .map_err(|_| Error::SetupTimedOut(Device::Sps30))? - .map_err(|err| err.strip_generics()) + .map_err(|err| make_error_string(err)) .map_err(SensorError::Sps30) .map_err(Error::Setup)?; diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed-sensors/src/sensors/fast.rs index 7b63538b..e9e7a167 100644 --- a/sensor-nodes/bed-sensors/src/sensors/fast.rs +++ b/sensor-nodes/bed-sensors/src/sensors/fast.rs @@ -1,8 +1,5 @@ -use defmt::{unwrap, warn}; -use embassy_futures::{ - join::{self, join3}, - yield_now, -}; +use defmt::warn; +use embassy_futures::yield_now; use embassy_stm32::exti::ExtiInput; use embassy_time::{Duration, Instant, Timer}; use embedded_hal_async::i2c::I2c; @@ -10,8 +7,11 @@ use max44009::Max44009; use crate::channel::Channel; -use protocol::downcast_err::{ConcreteErrorType, I2cError}; -use protocol::large_bedroom::{self, BedButton, LargeBedroom as LB}; +use protocol::large_bedroom::{ + bed::Button, + bed::{self, SensorError}, + bed::Reading, +}; fn sig_lux_diff(old: f32, new: f32) -> bool { let diff = old - new; @@ -19,13 +19,10 @@ fn sig_lux_diff(old: f32, new: f32) -> bool { diff > old / 20.0 || -diff > old / 20.0 } -async fn report_lux( - mut max44: Max44009, - publish: &Channel, -) where +async fn report_lux(mut max44: Max44009, publish: &Channel) +where I2C: I2c, I2C::Error: defmt::Format, - ::Error: Into, { let mut prev_lux = f32::MAX; let mut last_lux = Instant::now(); @@ -37,8 +34,9 @@ async fn report_lux( let lux = match max44.read_lux().await { Ok(lux) => lux, Err(err) if last_lux.elapsed() > MIN_INTERVAL => { - let err = large_bedroom::SensorError::Max44(err.strip_generics()); - let err = large_bedroom::Error::Running(err); + let err = protocol::make_error_string(err); + let err = SensorError::Max44(err); + let err = bed::Error::Running(err); let _ignore = publish.send_error(err); continue; } @@ -46,9 +44,9 @@ async fn report_lux( }; if sig_lux_diff(prev_lux, lux) { - publish.send_p2(LB::Brightness(lux)) + publish.send_p2(Reading::Brightness(lux)) } else if last_lux.elapsed() > MIN_INTERVAL { - publish.send_p1(LB::Brightness(lux)) + publish.send_p1(Reading::Brightness(lux)) } else { yield_now().await; continue; @@ -59,9 +57,10 @@ async fn report_lux( } } +#[allow(dead_code)] async fn watch_button( mut input: ExtiInput<'static>, - event: impl Fn(protocol::Press) -> BedButton, + event: impl Fn(protocol::Press) -> Button, channel: &Channel, ) { let mut went_high_at: Option = None; @@ -75,7 +74,7 @@ async fn watch_button( continue; }; let event = (event)(protocol::Press(press)); - let _ignore_full = channel.send_p2(LB::BedButton(event)); + let _ignore_full = channel.send_p2(Reading::Button(event)); } } else { input.wait_for_rising_edge().await; @@ -84,6 +83,7 @@ async fn watch_button( } } +#[allow(dead_code)] pub struct ButtonInputs { pub top_left: ExtiInput<'static>, pub top_right: ExtiInput<'static>, @@ -95,14 +95,10 @@ pub struct ButtonInputs { pub lower_outer: ExtiInput<'static>, } -pub async fn read( - max44: Max44009, - /*inputs: ButtonInputs,*/ - publish: &Channel, -) where +pub async fn read(max44: Max44009, /*inputs: ButtonInputs,*/ publish: &Channel) +where I2C: I2c, I2C::Error: defmt::Format, - ::Error: Into, { // let watch_buttons_1 = join5( // watch_button(inputs.top_left, BedButton::TopLeft, publish), diff --git a/sensor-nodes/bed-sensors/src/sensors/slow.rs b/sensor-nodes/bed-sensors/src/sensors/slow.rs index 37e86123..77b8ea70 100644 --- a/sensor-nodes/bed-sensors/src/sensors/slow.rs +++ b/sensor-nodes/bed-sensors/src/sensors/slow.rs @@ -7,10 +7,10 @@ use embedded_hal_async::delay::DelayNs; use embedded_hal_async::i2c::I2c; use mhzx::MHZ; -use protocol::downcast_err::{ConcreteErrorType, I2cError, UartError}; -use protocol::large_bedroom::{Device, LargeBedroom as LB}; +use protocol::large_bedroom::bed::{Device, Error, Reading, SensorError}; use bosch_bme680::{Bme680, MeasurementData}; +use protocol::make_error_string; use sht31::mode::{Sht31Measure, Sht31Reader, SingleShot}; use sht31::SHT31; use sps30_async as sps30; @@ -30,22 +30,22 @@ pub async fn read( ) where I2C: I2c, I2C::Error: defmt::Format, - ::Error: Into, TX1: embedded_io_async::Write, - TX1::Error: defmt::Format + Into, + TX1::Error: defmt::Format, RX1: embedded_io_async::Read, - RX1::Error: defmt::Format + Into, + RX1::Error: defmt::Format, TX2: embedded_io_async::Write, - TX2::Error: defmt::Format + Into, + TX2::Error: defmt::Format, RX2: embedded_io_async::Read, - RX2::Error: defmt::Format + Into, + RX2::Error: defmt::Format, { // sht works in two steps // - send measure command before sleep // - then read if let Err(err) = sht.measure().await { - let err = protocol::large_bedroom::SensorError::Sht31(err); - let err = protocol::large_bedroom::Error::Running(err); + let err = protocol::make_error_string(err); + let err = SensorError::Sht31(err); + let err = Error::Running(err); publish.send_error(err) } Timer::after_secs(1).await; @@ -77,8 +77,9 @@ pub async fn read( // - send measure command before sleep // - then read if let Err(err) = sht.measure().await { - let err = protocol::large_bedroom::SensorError::Sht31(err); - let err = protocol::large_bedroom::Error::Running(err); + let err = protocol::make_error_string(err); + let err = SensorError::Sht31(err); + let err = Error::Running(err); publish.send_error(err) } Timer::after_secs(1).await; @@ -92,8 +93,8 @@ fn publish_sps_result( >, publish: &Channel, ) where - TxError: fmt::Debug + defmt::Format + Into, - RxError: fmt::Debug + defmt::Format + Into, + TxError: fmt::Debug + defmt::Format, + RxError: fmt::Debug + defmt::Format, { match sps_res { Ok(Ok(Some(sps30::Measurement { @@ -108,28 +109,28 @@ fn publish_sps_result( number_pm10, typical_particle_size, }))) => { - publish.send_p0(LB::MassPm1_0(mass_pm1_0)); - publish.send_p0(LB::MassPm2_5(mass_pm2_5)); - publish.send_p0(LB::MassPm4_0(mass_pm4_0)); - publish.send_p0(LB::MassPm10(mass_pm10)); - publish.send_p0(LB::MassPm0_5(mass_pm0_5)); - publish.send_p0(LB::NumberPm1_0(number_pm1_0)); - publish.send_p0(LB::NumberPm2_5(number_pm2_5)); - publish.send_p0(LB::NumberPm4_0(number_pm4_0)); - publish.send_p0(LB::NumberPm10(number_pm10)); - publish.send_p0(LB::TypicalParticleSize(typical_particle_size)); + publish.send_p0(Reading::MassPm1_0(mass_pm1_0)); + publish.send_p0(Reading::MassPm2_5(mass_pm2_5)); + publish.send_p0(Reading::MassPm4_0(mass_pm4_0)); + publish.send_p0(Reading::MassPm10(mass_pm10)); + publish.send_p0(Reading::MassPm0_5(mass_pm0_5)); + publish.send_p0(Reading::NumberPm1_0(number_pm1_0)); + publish.send_p0(Reading::NumberPm2_5(number_pm2_5)); + publish.send_p0(Reading::NumberPm4_0(number_pm4_0)); + publish.send_p0(Reading::NumberPm10(number_pm10)); + publish.send_p0(Reading::TypicalParticleSize(typical_particle_size)); } Ok(Ok(None)) => { defmt::todo!("no idea when we hit this"); } Ok(Err(err)) => { - let err = err.strip_generics(); - let err = protocol::large_bedroom::SensorError::Sps30(err); - let err = protocol::large_bedroom::Error::Running(err); + let err = make_error_string(err); + let err = SensorError::Sps30(err); + let err = Error::Running(err); publish.send_error(err) } Err(_timeout) => { - let err = protocol::large_bedroom::Error::Timeout(Device::Sps30); + let err = Error::Timeout(Device::Sps30); publish.send_error(err) } } @@ -142,21 +143,21 @@ fn publish_mhz_result( >, publish: &Channel, ) where - TxError: fmt::Debug + defmt::Format + Into, - RxError: fmt::Debug + defmt::Format + Into, + TxError: fmt::Debug + defmt::Format, + RxError: fmt::Debug + defmt::Format, { match mhz_res { Ok(Ok(mhzx::Measurement { co2, .. })) => { - publish.send_p0(LB::Co2(co2)); + publish.send_p0(Reading::Co2(co2)); } Ok(Err(err)) => { - let err = err.strip_generics(); - let err = protocol::large_bedroom::SensorError::Mhz14(err); - let err = protocol::large_bedroom::Error::Running(err); + let err = make_error_string(err); + let err = SensorError::Mhz14(err); + let err = Error::Running(err); publish.send_error(err) } Err(_timeout) => { - let err = protocol::large_bedroom::Error::Timeout(Device::Mhz14); + let err = Error::Timeout(Device::Mhz14); publish.send_error(err) } } @@ -171,16 +172,17 @@ fn publish_sht_result( temperature, humidity, })) => { - publish.send_p0(LB::Temperature(temperature)); - publish.send_p0(LB::Humidity(humidity)); + publish.send_p0(Reading::Temperature(temperature)); + publish.send_p0(Reading::Humidity(humidity)); } Ok(Err(err)) => { - let err = protocol::large_bedroom::SensorError::Sht31(err); - let err = protocol::large_bedroom::Error::Running(err); + let err = make_error_string(err); + let err = SensorError::Sht31(err); + let err = Error::Running(err); publish.send_error(err) } Err(_timeout) => { - let err = protocol::large_bedroom::Error::Timeout(Device::Sht31); + let err = Error::Timeout(Device::Sht31); publish.send_error(err) } } @@ -189,9 +191,7 @@ fn publish_sht_result( fn publish_bme_result( bme_res: Result>, publish: &Channel, -) where - E: Into, -{ +) { match bme_res { Ok(MeasurementData { pressure, @@ -199,12 +199,13 @@ fn publish_bme_result( .. }) => { let gas_resistance = unwrap!(gas_resistance); // sensor is on - publish.send_p0(LB::GassResistance(gas_resistance)); - publish.send_p0(LB::Pressure(pressure)); + publish.send_p0(Reading::GassResistance(gas_resistance)); + publish.send_p0(Reading::Pressure(pressure)); } Err(err) => { - let err = protocol::large_bedroom::SensorError::Bme680(err.strip_generics()); - let err = protocol::large_bedroom::Error::Running(err); + let err = make_error_string(err); + let err = SensorError::Bme680(err); + let err = Error::Running(err); publish.send_error(err) } } From 9f0681c56452c130572830dc986c53585e706264 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 4 Jun 2024 14:38:34 +0200 Subject: [PATCH 121/687] format errors on device --- crates/desk-sensors/src/sensors.rs | 7 +--- crates/protocol/src/lib.rs | 2 + sensor-nodes/bed-sensors/.cargo/config.toml | 2 +- sensor-nodes/bed-sensors/Cargo.lock | 44 ++++++++++----------- sensor-nodes/bed-sensors/Cargo.toml | 25 ++++++------ sensor-nodes/bed-sensors/src/channel.rs | 4 +- sensor-nodes/bed-sensors/src/error_cache.rs | 18 +++++++++ sensor-nodes/bed-sensors/src/main.rs | 15 ++++--- sensor-nodes/bed-sensors/src/network.rs | 6 +-- sensor-nodes/bed-sensors/src/sensors.rs | 15 +++---- 10 files changed, 80 insertions(+), 58 deletions(-) create mode 100644 sensor-nodes/bed-sensors/src/error_cache.rs diff --git a/crates/desk-sensors/src/sensors.rs b/crates/desk-sensors/src/sensors.rs index 9b5da468..cacdd7ae 100644 --- a/crates/desk-sensors/src/sensors.rs +++ b/crates/desk-sensors/src/sensors.rs @@ -4,7 +4,6 @@ use hal::{Delay, I2cdev}; use linux_embedded_hal as hal; use tracing::debug; -use std::str::FromStr; use std::sync::mpsc::Sender; use std::thread; use std::time::{Duration, Instant}; @@ -18,16 +17,14 @@ use crate::{send_error, send_reading}; pub fn init() -> Result, Error> { let i2c_bus = I2cdev::new("/dev/i2c-1") .inspect_err(|e| tracing::error!("Could not open i2c bus: {e}")) - .map_err(|e| e.to_string()) - .map_err(|e| heapless::String::from_str(&e[..200]).unwrap()) + .map_err(|e| protocol::make_error_string(e)) .map_err(|e| Error::Setup(SetupError::I2c(e)))?; let mut bme280 = Bme280::new_primary(i2c_bus); bme280 .init(&mut Delay) .inspect_err(|e| tracing::error!("Could not init bme280 sensor: {e}")) - .map_err(|e| e.to_string()) - .map_err(|e| heapless::String::from_str(&e[..200]).unwrap()) + .map_err(|e| protocol::make_error_string(e)) .map_err(|e| Error::Setup(SetupError::BmeError(e)))?; Ok(bme280) } diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index cd2bef08..0b4ccfb0 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -232,9 +232,11 @@ pub type ErrorString = heapless::String<200>; // https://github.com/rust-lang/rust/issues/103765 // at that point try switching this to fmt::Display pub fn make_error_string(e: impl core::fmt::Debug) -> ErrorString { + defmt::info!("making error string"); use core::fmt::Write; let mut s = ErrorString::new(); core::write!(s, "{e:?}").ok(); + defmt::info!("done"); s } diff --git a/sensor-nodes/bed-sensors/.cargo/config.toml b/sensor-nodes/bed-sensors/.cargo/config.toml index 1e24e032..84537f49 100644 --- a/sensor-nodes/bed-sensors/.cargo/config.toml +++ b/sensor-nodes/bed-sensors/.cargo/config.toml @@ -9,7 +9,7 @@ target = "thumbv7em-none-eabihf" [env] DEFMT_LOG = "debug,sps30_async=trace,bosch_bme680=info" -EMBASSY_EXECUTOR_TASK_ARENA_SIZE="8000" +EMBASSY_EXECUTOR_TASK_ARENA_SIZE="20000" # [unstable] # build-std = ["core"] diff --git a/sensor-nodes/bed-sensors/Cargo.lock b/sensor-nodes/bed-sensors/Cargo.lock index 021ca323..c2a3e182 100644 --- a/sensor-nodes/bed-sensors/Cargo.lock +++ b/sensor-nodes/bed-sensors/Cargo.lock @@ -43,7 +43,7 @@ dependencies = [ "embassy-stm32", "embassy-sync", "embassy-time", - "embedded-hal 0.2.7", + "embedded-hal 1.0.0", "embedded-hal-async", "embedded-hal-bus", "embedded-io-async", @@ -93,7 +93,6 @@ checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bosch-bme680" version = "1.0.2" -source = "git+https://github.com/dvdsk/async-bosch-bme680#455d5d3194f137d9e0403779badc645e1bad7a05" dependencies = [ "bitfield 0.14.0", "defmt", @@ -282,7 +281,7 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "defmt", "embassy-futures", @@ -299,7 +298,7 @@ dependencies = [ [[package]] name = "embassy-executor" version = "0.5.0" -source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "cortex-m", "critical-section", @@ -313,7 +312,7 @@ dependencies = [ [[package]] name = "embassy-executor-macros" version = "0.4.1" -source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "darling", "proc-macro2", @@ -324,12 +323,12 @@ dependencies = [ [[package]] name = "embassy-futures" version = "0.1.1" -source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" [[package]] name = "embassy-hal-internal" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "cortex-m", "critical-section", @@ -340,7 +339,7 @@ dependencies = [ [[package]] name = "embassy-net" version = "0.4.0" -source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "defmt", "document-features", @@ -357,7 +356,7 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "defmt", ] @@ -365,7 +364,7 @@ dependencies = [ [[package]] name = "embassy-net-driver-channel" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "embassy-futures", "embassy-net-driver", @@ -375,7 +374,7 @@ dependencies = [ [[package]] name = "embassy-net-wiznet" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "defmt", "embassy-futures", @@ -388,7 +387,7 @@ dependencies = [ [[package]] name = "embassy-stm32" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "bit_field", "bitflags 2.5.0", @@ -431,8 +430,8 @@ dependencies = [ [[package]] name = "embassy-sync" -version = "0.5.0" -source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +version = "0.6.0" +source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "cfg-if", "critical-section", @@ -445,7 +444,7 @@ dependencies = [ [[package]] name = "embassy-time" version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "cfg-if", "critical-section", @@ -463,7 +462,7 @@ dependencies = [ [[package]] name = "embassy-time-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "document-features", ] @@ -471,12 +470,12 @@ dependencies = [ [[package]] name = "embassy-time-queue-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" [[package]] name = "embassy-usb-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "defmt", ] @@ -484,7 +483,7 @@ dependencies = [ [[package]] name = "embassy-usb-synopsys-otg" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=128575a#128575aebe18eea29862c52a88f81671fbcbf610" +source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "critical-section", "embassy-sync", @@ -531,14 +530,15 @@ dependencies = [ [[package]] name = "embedded-hal-bus" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b4e6ede84339ebdb418cd986e6320a34b017cdf99b5cc3efceec6450b06886" +checksum = "0d3980bf28e8577db59fe2bdb3df868a419469d2cecb363644eea2b6f7797669" dependencies = [ "critical-section", "defmt", "embedded-hal 1.0.0", "embedded-hal-async", + "portable-atomic", ] [[package]] @@ -1089,7 +1089,7 @@ dependencies = [ [[package]] name = "stm32-metapac" version = "15.0.0" -source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-f1297385e91f061fcb6134bb25f51e12d8abff93#acfef07196084706a9621a434d927229b616951f" +source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-59b1f65bd109c3ef35782e6c44062208d0ef3d0e#2ad339796e0f40bd6fa784dbfe30a071d93cc886" dependencies = [ "cortex-m", "cortex-m-rt", diff --git a/sensor-nodes/bed-sensors/Cargo.toml b/sensor-nodes/bed-sensors/Cargo.toml index b4eebc9e..4fa6cb65 100644 --- a/sensor-nodes/bed-sensors/Cargo.toml +++ b/sensor-nodes/bed-sensors/Cargo.toml @@ -11,7 +11,7 @@ embassy-stm32 = { version = "0.1.0", features = [ "defmt", "stm32f401cc", "unstable-pac", "memory-x", "time-driver-tim1", "time", "exti" ] } embassy-net = { version = "0.4.0", features = ["defmt", "proto-ipv4", "tcp", "dhcpv4","medium-ethernet"] } embassy-net-wiznet = { version = "0.1.0", features = ["defmt"] } -embassy-sync = { version = "0.5.0", features = ["defmt"] } +embassy-sync = { version = "0.6.0", features = ["defmt"] } embassy-executor = { version = "0.5.0", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers", "executor-interrupt"] } embassy-embedded-hal = { version = "0.1.0" } @@ -23,9 +23,9 @@ defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" -embedded-hal = "0.2.6" +embedded-hal = "1.0.0" embedded-hal-async = "1.0" -embedded-hal-bus = { version = "0.1", features = ["async", "defmt-03"] } +embedded-hal-bus = { version = "0.2", features = ["async", "defmt-03"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } @@ -35,7 +35,7 @@ rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } static_cell = "2.0.0" # sensors -bosch-bme680 = { version = "1.0.2", git = "https://github.com/dvdsk/async-bosch-bme680" } +bosch-bme680 = { version = "1.0.2", path = "/home/david/Documents/async-bosch-bme680" } max44009 = { version = "0.2", git = "https://github.com/dvdsk/max44009-rs" } sht31 = { version = "0.3.0", git = "https://github.com/dvdsk/SHT31-rs", features = ["postcard"] } # mhzx = { version = "0.3.0", git = "https://github.com/dvdsk/mhzx", features = ["postcard"] } @@ -44,16 +44,17 @@ sps30-async = { version = "0.2.0", path = "/home/david/tmp/sps30", features = [" # encoding protocol = { path = "../../crates/protocol" } +# fasthash = { version = "0.4.0", default-features = false } [patch.crates-io] -embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "128575a" } -embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "128575a" } -embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "128575a" } -embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "128575a" } -embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "128575a" } -embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "128575a" } -embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "128575a" } -embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "128575a" } +embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } +embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } +embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } +embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } +embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } +embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } +embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } +embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } [profile.dev] opt-level = "s" diff --git a/sensor-nodes/bed-sensors/src/channel.rs b/sensor-nodes/bed-sensors/src/channel.rs index a60bd0ed..27d337ae 100644 --- a/sensor-nodes/bed-sensors/src/channel.rs +++ b/sensor-nodes/bed-sensors/src/channel.rs @@ -12,8 +12,8 @@ struct ErrorEvent { } pub struct Channel { - queue: PriorityChannel, - recent_errors: Mutex>, + queue: PriorityChannel, + recent_errors: Mutex>, } impl Channel { diff --git a/sensor-nodes/bed-sensors/src/error_cache.rs b/sensor-nodes/bed-sensors/src/error_cache.rs new file mode 100644 index 00000000..f6416cb0 --- /dev/null +++ b/sensor-nodes/bed-sensors/src/error_cache.rs @@ -0,0 +1,18 @@ +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::blocking_mutex::Mutex; +// use fasthash::{murmur3, Murmur3Hasher, SeaHasher}; +use heapless::LinearMap; +/// static global error fmt message cache +use protocol::large_bedroom::bed::Error; + +static ERROR_CACHE: Mutex, 20>> = + Mutex::new(LinearMap::new()); + +pub fn make_error_string(e: impl core::fmt::Debug) -> heapless::String<200> { + defmt::warn!("hi"); + // let hash = murmur3::hash32(e); + // let res = ERROR_CACHE.lock(|map| { + // map.get(&hash) + // }); + heapless::String::new() +} diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index a6cf0943..068c8a55 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -12,7 +12,7 @@ use embassy_stm32::exti::ExtiInput; use embassy_stm32::gpio::{Level, Output, Pull, Speed}; use embassy_stm32::i2c::{self, I2c}; use embassy_stm32::mode::Async; -use embassy_stm32::peripherals::{IWDG, SPI1}; +use embassy_stm32::peripherals::IWDG; use embassy_stm32::spi::{Config as SpiConfig, Spi}; use embassy_stm32::time::Hertz; use embassy_stm32::usart::{self, DataBits, StopBits, Uart}; @@ -33,6 +33,7 @@ use {defmt_rtt as _, panic_probe as _}; mod channel; mod network; mod sensors; +mod error_cache; use crate::channel::Channel; embassy_stm32::bind_interrupts!(struct Irqs { @@ -59,7 +60,7 @@ async fn print_if_running_task() -> ! { } } -type EthernetSPI = ExclusiveDevice, Output<'static>, Delay>; +type EthernetSPI = ExclusiveDevice, Output<'static>, Delay>; #[embassy_executor::task] async fn ethernet_task( runner: Runner<'static, W5500, EthernetSPI, ExtiInput<'static>, Output<'static>>, @@ -110,7 +111,7 @@ fn config() -> Config { #[embassy_executor::main] async fn main(spawner: Spawner) { let p = embassy_stm32::init(config()); - let dog = IndependentWatchdog::new(p.IWDG, 20 * 1000 * 1000); + // let dog = IndependentWatchdog::new(p.IWDG, 20 * 1000 * 1000); let publish = Channel::new(); let seed = gen_random_number().await; @@ -173,6 +174,7 @@ async fn main(spawner: Spawner) { let (miso, mosi, clk) = (p.PA6, p.PA7, p.PA5); let spi = Spi::new(p.SPI1, clk, mosi, miso, p.DMA2_CH3, p.DMA2_CH0, spi_cfg); let cs = Output::new(p.PA4, Level::High, Speed::VeryHigh); + let spi = unwrap!(ExclusiveDevice::new(spi, cs, Delay)); let w5500_int = ExtiInput::new(p.PB0, p.EXTI0, Pull::Up); let w5500_reset = Output::new(p.PB1, Level::High, Speed::VeryHigh); @@ -183,7 +185,7 @@ async fn main(spawner: Spawner) { let (device, runner) = embassy_net_wiznet::new( mac_addr, state, - ExclusiveDevice::new(spi, cs, Delay), + spi, w5500_int, w5500_reset, ) @@ -219,8 +221,9 @@ async fn main(spawner: Spawner) { network_up.signal(()); let send_published = network::send_published(stack, &publish, &network_up); pin_mut!(send_published); - let keep_dog_happy = keep_dog_happy(dog); - let send_and_pet_dog = join::join(&mut send_published, keep_dog_happy); + // let keep_dog_happy = keep_dog_happy(dog); + // let send_and_pet_dog = join::join(&mut send_published, keep_dog_happy); + let send_and_pet_dog = &mut send_published; let init_then_measure = sensors::init_then_measure(&publish, i2c, usart_mhz, usart_sps30); let init_then_measure = network_up.wait().then(|_| init_then_measure); diff --git a/sensor-nodes/bed-sensors/src/network.rs b/sensor-nodes/bed-sensors/src/network.rs index 5a4527a0..a1cb8208 100644 --- a/sensor-nodes/bed-sensors/src/network.rs +++ b/sensor-nodes/bed-sensors/src/network.rs @@ -10,7 +10,7 @@ use protocol::SensorMessage; use crate::channel::Channel; -type Msg = SensorMessage<6>; +type Msg = SensorMessage<4>; async fn get_messages(publish: &Channel, msg: &mut Msg) { msg.values.clear(); @@ -49,14 +49,14 @@ pub async fn send_published( network_up: &Signal, ) { let mut rx_buffer = [0; 800]; - let mut tx_buffer = [0; Msg::ENCODED_SIZE * 4]; + let mut tx_buffer = [0; Msg::ENCODED_SIZE * 2]; let mut msg = Msg::new(); let mut encoded_msg_buffer = [0; Msg::ENCODED_SIZE]; let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); socket.set_timeout(Some(Duration::from_secs(5))); - let host_addr = Ipv4Address::new(192, 168, 1, 46); + let host_addr = Ipv4Address::new(192, 168, 1, 43); let host_port = 1234; loop { diff --git a/sensor-nodes/bed-sensors/src/sensors.rs b/sensor-nodes/bed-sensors/src/sensors.rs index 55a5e6f7..8afcd530 100644 --- a/sensor-nodes/bed-sensors/src/sensors.rs +++ b/sensor-nodes/bed-sensors/src/sensors.rs @@ -1,8 +1,8 @@ +use defmt::info; use embassy_embedded_hal::shared_bus; use embassy_futures::join; use embassy_stm32::i2c::I2c; use embassy_stm32::mode::Async; -use embassy_stm32::peripherals::{I2C1, USART1, USART2}; use embassy_stm32::usart::Uart; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; @@ -10,7 +10,7 @@ use embassy_time::{with_timeout, Delay, Duration}; use max44009::{Max44009, SlaveAddr}; use mhzx::MHZ; use protocol::large_bedroom::bed::{Device, Error, SensorError}; -use protocol::make_error_string; +use crate::error_cache::make_error_string; use sps30_async::Sps30; use crate::channel::Channel; @@ -23,14 +23,15 @@ pub mod slow; pub async fn init_then_measure( publish: &Channel, - i2c: Mutex>, - usart_mhz: Uart<'static, USART1, Async>, - usart_sps: Uart<'static, USART2, Async>, + i2c: Mutex>, + usart_mhz: Uart<'static, Async>, + usart_sps: Uart<'static, Async>, ) -> Result<(), protocol::large_bedroom::bed::Error> { + info!("initializing sensors"); let bme_config = bosch_bme680::Configuration::default(); let bme = with_timeout( - Duration::from_secs(12), + Duration::from_secs(2), bosch_bme680::Bme680::new( shared_bus::asynch::i2c::I2cDevice::new(&i2c), bosch_bme680::DeviceAddress::Secondary, @@ -45,6 +46,7 @@ pub async fn init_then_measure( .map_err(SensorError::Bme680) .map_err(Error::Setup)?; + defmt::info!("hi"); let mut max44009 = Max44009::new( shared_bus::asynch::i2c::I2cDevice::new(&i2c), SlaveAddr::default(), @@ -72,7 +74,6 @@ pub async fn init_then_measure( let (tx, rx) = usart_sps.split(); let mut usart_buf = [0u8; 100]; let rx = rx.into_ring_buffered(&mut usart_buf); - defmt::info!("hi"); let sps30 = with_timeout(Duration::from_millis(100), Sps30::from_tx_rx(tx, rx, Delay)) .await .map_err(|_| Error::SetupTimedOut(Device::Sps30))? From 6d14f77c0cfa80dbe4e4e537c9d875dffcf02d63 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 6 Jun 2024 15:38:47 +0200 Subject: [PATCH 122/687] prep do string formatting only at the last possible instance to save ram --- sensor-nodes/bed-sensors/.cargo/config.toml | 2 +- sensor-nodes/bed-sensors/src/channel.rs | 86 ++++++++++---------- sensor-nodes/bed-sensors/src/error_cache.rs | 81 +++++++++++++++--- sensor-nodes/bed-sensors/src/main.rs | 46 +++++------ sensor-nodes/bed-sensors/src/network.rs | 8 +- sensor-nodes/bed-sensors/src/sensors.rs | 13 ++- sensor-nodes/bed-sensors/src/sensors/fast.rs | 10 +-- sensor-nodes/bed-sensors/src/sensors/slow.rs | 40 ++++----- 8 files changed, 165 insertions(+), 121 deletions(-) diff --git a/sensor-nodes/bed-sensors/.cargo/config.toml b/sensor-nodes/bed-sensors/.cargo/config.toml index 84537f49..05349a7d 100644 --- a/sensor-nodes/bed-sensors/.cargo/config.toml +++ b/sensor-nodes/bed-sensors/.cargo/config.toml @@ -9,7 +9,7 @@ target = "thumbv7em-none-eabihf" [env] DEFMT_LOG = "debug,sps30_async=trace,bosch_bme680=info" -EMBASSY_EXECUTOR_TASK_ARENA_SIZE="20000" +EMBASSY_EXECUTOR_TASK_ARENA_SIZE="4000" # [unstable] # build-std = ["core"] diff --git a/sensor-nodes/bed-sensors/src/channel.rs b/sensor-nodes/bed-sensors/src/channel.rs index 27d337ae..333ae108 100644 --- a/sensor-nodes/bed-sensors/src/channel.rs +++ b/sensor-nodes/bed-sensors/src/channel.rs @@ -1,43 +1,65 @@ +use core::fmt; + use defmt::unwrap; use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::channel::Channel; use embassy_sync::mutex::Mutex; use embassy_sync::priority_channel::{self, PriorityChannel}; use embassy_time::{Duration, Instant}; use heapless::Vec; -use protocol::large_bedroom::bed::{self, Error, Reading}; +use protocol::large_bedroom::bed::Reading; + +use crate::error_cache; -struct ErrorEvent { - error: Error, +struct ErrorEvent +where + T: defmt::Format + fmt::Debug, + R: defmt::Format + fmt::Debug, + I: defmt::Format + fmt::Debug, +{ + error: error_cache::Error, at: Instant, } -pub struct Channel { - queue: PriorityChannel, - recent_errors: Mutex>, +pub struct Queues +where + T: defmt::Format + fmt::Debug, + R: defmt::Format + fmt::Debug, + I: defmt::Format + fmt::Debug, +{ + sensor_queue: PriorityChannel, + error_queue: Channel, 20>, + recent_errors: Mutex, 5>>, } -impl Channel { +impl Queues +where + T: defmt::Format + fmt::Debug + PartialEq, + R: defmt::Format + fmt::Debug + PartialEq, + I: defmt::Format + fmt::Debug + PartialEq, +{ pub fn new() -> Self { Self { - queue: PriorityChannel::new(), + sensor_queue: PriorityChannel::new(), + error_queue: Channel::new(), recent_errors: Mutex::new(Vec::new()), } } pub async fn clear(&self) { - while let Ok(_) = self.queue.try_receive() {} + while let Ok(_) = self.sensor_queue.try_receive() {} self.recent_errors.lock().await.clear(); } pub async fn receive(&self) -> PriorityValue { - self.queue.receive().await + self.sensor_queue.receive().await } pub fn next_ready(&self) -> Option { - self.queue.try_receive().ok() + self.sensor_queue.try_receive().ok() } - pub fn send_error(&self, error: bed::Error) { + pub fn queue_error(&self, error: error_cache::Error) { let mut recent_errors = unwrap!(self.recent_errors.try_lock()); let mut to_remove: Vec = Vec::new(); @@ -52,14 +74,7 @@ impl Channel { for idx in to_remove.iter().rev() { recent_errors.swap_remove(*idx); } - let entry = PriorityValue { - priority: 0, - value: Err(protocol::Error::LargeBedroom( - protocol::large_bedroom::Error::Bed(error.clone()), - )), - }; - - let full = self.queue.try_send(entry).is_err(); + let full = self.error_queue.try_send(error.clone()).is_err(); if !full { let _ignore_full = recent_errors.push(ErrorEvent { @@ -72,48 +87,37 @@ impl Channel { pub fn send_p0(&self, value: Reading) { let entry = PriorityValue { priority: 0, - value: Ok(protocol::Reading::LargeBedroom( + value: protocol::Reading::LargeBedroom( protocol::large_bedroom::Reading::Bed(value), - )), + ), }; - let _ignore_full = self.queue.try_send(entry); + let _ignore_full = self.sensor_queue.try_send(entry); } pub fn send_p1(&self, value: Reading) { let entry = PriorityValue { priority: 1, - value: Ok(protocol::Reading::LargeBedroom( + value: protocol::Reading::LargeBedroom( protocol::large_bedroom::Reading::Bed(value), - )), + ), }; - let _ignore_full = self.queue.try_send(entry); + let _ignore_full = self.sensor_queue.try_send(entry); } pub fn send_p2(&self, value: Reading) { let entry = PriorityValue { priority: 2, - value: Ok(protocol::Reading::LargeBedroom( + value: protocol::Reading::LargeBedroom( protocol::large_bedroom::Reading::Bed(value), - )), + ), }; - let _ignore_full = self.queue.try_send(entry); - } - - pub async fn send_critical_error(&self, error: Error) { - let entry = PriorityValue { - priority: 10, - value: Err(protocol::Error::LargeBedroom( - protocol::large_bedroom::Error::Bed(error), - )), - }; - - self.queue.send(entry).await; + let _ignore_full = self.sensor_queue.try_send(entry); } } /// Higher prio will be send earlier pub struct PriorityValue { priority: u8, - pub value: Result, + pub value: protocol::Reading, } impl PriorityValue { diff --git a/sensor-nodes/bed-sensors/src/error_cache.rs b/sensor-nodes/bed-sensors/src/error_cache.rs index f6416cb0..9ddff2bf 100644 --- a/sensor-nodes/bed-sensors/src/error_cache.rs +++ b/sensor-nodes/bed-sensors/src/error_cache.rs @@ -1,18 +1,73 @@ -use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; -use embassy_sync::blocking_mutex::Mutex; +use core::fmt; + +// use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +// use embassy_sync::blocking_mutex::Mutex; // use fasthash::{murmur3, Murmur3Hasher, SeaHasher}; -use heapless::LinearMap; +// use heapless::LinearMap; +use protocol::large_bedroom::bed::{self, Device}; +use protocol::make_error_string; /// static global error fmt message cache -use protocol::large_bedroom::bed::Error; +// use protocol::large_bedroom::bed::Error; + +// static ERROR_CACHE: Mutex, 20>> = +// Mutex::new(LinearMap::new()); + +#[derive(PartialEq, Eq, Clone)] +pub enum SensorError +where + TxError: defmt::Format + fmt::Debug, + RxError: defmt::Format + fmt::Debug, + I2cError: defmt::Format + fmt::Debug, +{ + Mhz14(mhzx::Error), + Sps30(sps30_async::Error), + Sht31(sht31::SHTError), + Bme680(bosch_bme680::BmeError), + Max44(max44009::Error), +} -static ERROR_CACHE: Mutex, 20>> = - Mutex::new(LinearMap::new()); +impl Into for SensorError +where + TxError: defmt::Format + fmt::Debug, + RxError: defmt::Format + fmt::Debug, + I2cError: defmt::Format + fmt::Debug, +{ + fn into(self) -> bed::SensorError { + match self { + SensorError::Mhz14(e) => bed::SensorError::Mhz14(make_error_string(e)), + SensorError::Sps30(e) => bed::SensorError::Sps30(make_error_string(e)), + SensorError::Sht31(e) => bed::SensorError::Sht31(make_error_string(e)), + SensorError::Bme680(e) => bed::SensorError::Bme680(make_error_string(e)), + SensorError::Max44(e) => bed::SensorError::Max44(make_error_string(e)), + } + } +} + +#[derive(PartialEq, Eq, Clone)] +pub enum Error +where + TxError: defmt::Format + fmt::Debug, + RxError: defmt::Format + fmt::Debug, + I2cError: defmt::Format + fmt::Debug, +{ + Running(SensorError), + Setup(SensorError), + Timeout(Device), + SetupTimedOut(Device), +} -pub fn make_error_string(e: impl core::fmt::Debug) -> heapless::String<200> { - defmt::warn!("hi"); - // let hash = murmur3::hash32(e); - // let res = ERROR_CACHE.lock(|map| { - // map.get(&hash) - // }); - heapless::String::new() +impl Into for Error +where + TxError: defmt::Format + fmt::Debug, + RxError: defmt::Format + fmt::Debug, + I2cError: defmt::Format + fmt::Debug, +{ + fn into(self) -> bed::Error { + match self { + Error::Running(e) => bed::Error::Running(e.into()), + Error::Setup(e) => bed::Error::Setup(e.into()), + Error::Timeout(dev) => bed::Error::Timeout(dev), + Error::SetupTimedOut(dev) => bed::Error::SetupTimedOut(dev), + } + } } diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index 068c8a55..27a10ed1 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -34,7 +34,7 @@ mod channel; mod network; mod sensors; mod error_cache; -use crate::channel::Channel; +use crate::channel::Queues; embassy_stm32::bind_interrupts!(struct Irqs { I2C1_EV => embassy_stm32::i2c::EventInterruptHandler; @@ -73,14 +73,6 @@ async fn net_task(stack: &'static Stack>) -> ! { stack.run().await } -async fn gen_random_number() -> u64 { - let seed = 5u64; - let mut rng = SmallRng::seed_from_u64(seed); - let seed = rng.gen(); - info!("Seed: {}", seed); - seed -} - // 84 Mhz clock stm32f401 fn config() -> Config { use embassy_stm32::rcc::{ @@ -112,8 +104,7 @@ fn config() -> Config { async fn main(spawner: Spawner) { let p = embassy_stm32::init(config()); // let dog = IndependentWatchdog::new(p.IWDG, 20 * 1000 * 1000); - let publish = Channel::new(); - let seed = gen_random_number().await; + let publish = Queues::new(); let mut usart_config = usart::Config::default(); usart_config.baudrate = 9600; @@ -207,7 +198,7 @@ async fn main(spawner: Spawner) { dns_servers, }), RESOURCES.init(StackResources::<2>::new()), - seed, + 384, )); // Launch network task @@ -217,6 +208,7 @@ async fn main(spawner: Spawner) { let spawner = EXECUTOR_HIGH.start(embassy_stm32::interrupt::USART6); unwrap!(spawner.spawn(print_if_running_task())); + Timer::after_secs(999).await; let network_up: Signal = Signal::new(); network_up.signal(()); let send_published = network::send_published(stack, &publish, &network_up); @@ -225,21 +217,21 @@ async fn main(spawner: Spawner) { // let send_and_pet_dog = join::join(&mut send_published, keep_dog_happy); let send_and_pet_dog = &mut send_published; - let init_then_measure = sensors::init_then_measure(&publish, i2c, usart_mhz, usart_sps30); - let init_then_measure = network_up.wait().then(|_| init_then_measure); - let res = select::select(send_and_pet_dog, init_then_measure).await; - let unrecoverable_err = match res { - Either::First(_) => defmt::unreachable!(), - Either::Second(Ok(())) => defmt::unreachable!(), - Either::Second(Err(err)) => err, - }; - - let send_critical_error = join::join( - publish.send_critical_error(unrecoverable_err.clone()), - send_published, - ); - error!("unrecoverable error, resetting: {}", unrecoverable_err); - send_critical_error.await; // if this takes too long the dog will get us + // let init_then_measure = sensors::init_then_measure(&publish, i2c, usart_mhz, usart_sps30); + // let init_then_measure = network_up.wait().then(|_| init_then_measure); + // let res = select::select(send_and_pet_dog, init_then_measure).await; + // let unrecoverable_err = match res { + // Either::First(_) => defmt::unreachable!(), + // Either::Second(Ok(())) => defmt::unreachable!(), + // Either::Second(Err(err)) => err, + // }; + // + // let send_critical_error = join::join( + // publish.send_critical_error(unrecoverable_err.clone()), + // send_published, + // ); + // error!("unrecoverable error, resetting: {}", unrecoverable_err); + // send_critical_error.await; // if this takes too long the dog will get us } async fn keep_dog_happy<'a>(mut dog: IndependentWatchdog<'a, IWDG>) { diff --git a/sensor-nodes/bed-sensors/src/network.rs b/sensor-nodes/bed-sensors/src/network.rs index a1cb8208..420f6c81 100644 --- a/sensor-nodes/bed-sensors/src/network.rs +++ b/sensor-nodes/bed-sensors/src/network.rs @@ -8,11 +8,11 @@ use embassy_time::{with_timeout, Duration, Instant, Timer}; use embedded_io_async::Write; use protocol::SensorMessage; -use crate::channel::Channel; +use crate::channel::Queues; type Msg = SensorMessage<4>; -async fn get_messages(publish: &Channel, msg: &mut Msg) { +async fn get_messages(publish: &Queues, msg: &mut Msg) { msg.values.clear(); let next = publish.receive().await; let low_priority = next.low_priority(); @@ -45,10 +45,10 @@ async fn get_messages(publish: &Channel, msg: &mut Msg) { pub async fn send_published( stack: &Stack, - publish: &Channel, + publish: &Queues, network_up: &Signal, ) { - let mut rx_buffer = [0; 800]; + let mut rx_buffer = [0; 200]; let mut tx_buffer = [0; Msg::ENCODED_SIZE * 2]; let mut msg = Msg::new(); diff --git a/sensor-nodes/bed-sensors/src/sensors.rs b/sensor-nodes/bed-sensors/src/sensors.rs index 8afcd530..07d49d74 100644 --- a/sensor-nodes/bed-sensors/src/sensors.rs +++ b/sensor-nodes/bed-sensors/src/sensors.rs @@ -9,11 +9,11 @@ use embassy_sync::mutex::Mutex; use embassy_time::{with_timeout, Delay, Duration}; use max44009::{Max44009, SlaveAddr}; use mhzx::MHZ; -use protocol::large_bedroom::bed::{Device, Error, SensorError}; -use crate::error_cache::make_error_string; +use protocol::large_bedroom::bed::Device; use sps30_async::Sps30; -use crate::channel::Channel; +use crate::channel::Queues; +use crate::error_cache::{Error, SensorError}; pub mod fast; pub mod slow; @@ -22,11 +22,11 @@ pub mod slow; // while we are measuring pub async fn init_then_measure( - publish: &Channel, + publish: &Queues, i2c: Mutex>, usart_mhz: Uart<'static, Async>, usart_sps: Uart<'static, Async>, -) -> Result<(), protocol::large_bedroom::bed::Error> { +) -> Result<(), Error> { info!("initializing sensors"); let bme_config = bosch_bme680::Configuration::default(); @@ -42,7 +42,6 @@ pub async fn init_then_measure( ) .await .map_err(|_| Error::SetupTimedOut(Device::Bme680))? - .map_err(|err| make_error_string(err)) .map_err(SensorError::Bme680) .map_err(Error::Setup)?; @@ -57,7 +56,6 @@ pub async fn init_then_measure( ) .await .map_err(|_| Error::SetupTimedOut(Device::Max44))? - .map_err(|err| make_error_string(err)) .map_err(SensorError::Max44) .map_err(Error::Setup)?; @@ -77,7 +75,6 @@ pub async fn init_then_measure( let sps30 = with_timeout(Duration::from_millis(100), Sps30::from_tx_rx(tx, rx, Delay)) .await .map_err(|_| Error::SetupTimedOut(Device::Sps30))? - .map_err(|err| make_error_string(err)) .map_err(SensorError::Sps30) .map_err(Error::Setup)?; diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed-sensors/src/sensors/fast.rs index e9e7a167..78952d2a 100644 --- a/sensor-nodes/bed-sensors/src/sensors/fast.rs +++ b/sensor-nodes/bed-sensors/src/sensors/fast.rs @@ -5,7 +5,7 @@ use embassy_time::{Duration, Instant, Timer}; use embedded_hal_async::i2c::I2c; use max44009::Max44009; -use crate::channel::Channel; +use crate::channel::Queues; use protocol::large_bedroom::{ bed::Button, @@ -19,7 +19,7 @@ fn sig_lux_diff(old: f32, new: f32) -> bool { diff > old / 20.0 || -diff > old / 20.0 } -async fn report_lux(mut max44: Max44009, publish: &Channel) +async fn report_lux(mut max44: Max44009, publish: &Queues) where I2C: I2c, I2C::Error: defmt::Format, @@ -37,7 +37,7 @@ where let err = protocol::make_error_string(err); let err = SensorError::Max44(err); let err = bed::Error::Running(err); - let _ignore = publish.send_error(err); + let _ignore = publish.queue_error(err); continue; } Err(_) => continue, @@ -61,7 +61,7 @@ where async fn watch_button( mut input: ExtiInput<'static>, event: impl Fn(protocol::Press) -> Button, - channel: &Channel, + channel: &Queues, ) { let mut went_high_at: Option = None; loop { @@ -95,7 +95,7 @@ pub struct ButtonInputs { pub lower_outer: ExtiInput<'static>, } -pub async fn read(max44: Max44009, /*inputs: ButtonInputs,*/ publish: &Channel) +pub async fn read(max44: Max44009, /*inputs: ButtonInputs,*/ publish: &Queues) where I2C: I2c, I2C::Error: defmt::Format, diff --git a/sensor-nodes/bed-sensors/src/sensors/slow.rs b/sensor-nodes/bed-sensors/src/sensors/slow.rs index 77b8ea70..98952cea 100644 --- a/sensor-nodes/bed-sensors/src/sensors/slow.rs +++ b/sensor-nodes/bed-sensors/src/sensors/slow.rs @@ -7,7 +7,7 @@ use embedded_hal_async::delay::DelayNs; use embedded_hal_async::i2c::I2c; use mhzx::MHZ; -use protocol::large_bedroom::bed::{Device, Error, Reading, SensorError}; +use protocol::large_bedroom::bed::{Device, Reading}; use bosch_bme680::{Bme680, MeasurementData}; use protocol::make_error_string; @@ -16,7 +16,9 @@ use sht31::SHT31; use sps30_async as sps30; use sps30_async::Sps30; -use crate::channel::Channel; +use crate::error_cache::SensorError; +use crate::error_cache::Error; +use crate::channel::Queues; const SPS30_UART_BUF_SIZE: usize = 100; const SPS30_DRIVER_BUF_SIZE: usize = 2 * SPS30_UART_BUF_SIZE; @@ -26,7 +28,7 @@ pub async fn read( mut bme: Bme680, mut mhz: MHZ, mut sps: Sps30, - publish: &Channel, + publish: &Queues, ) where I2C: I2c, I2C::Error: defmt::Format, @@ -43,10 +45,9 @@ pub async fn read( // - send measure command before sleep // - then read if let Err(err) = sht.measure().await { - let err = protocol::make_error_string(err); let err = SensorError::Sht31(err); let err = Error::Running(err); - publish.send_error(err) + publish.queue_error(err) } Timer::after_secs(1).await; @@ -77,10 +78,9 @@ pub async fn read( // - send measure command before sleep // - then read if let Err(err) = sht.measure().await { - let err = protocol::make_error_string(err); let err = SensorError::Sht31(err); let err = Error::Running(err); - publish.send_error(err) + publish.queue_error(err) } Timer::after_secs(1).await; } @@ -91,7 +91,7 @@ fn publish_sps_result( Result, sps30::Error>, embassy_time::TimeoutError, >, - publish: &Channel, + publish: &Queues, ) where TxError: fmt::Debug + defmt::Format, RxError: fmt::Debug + defmt::Format, @@ -124,14 +124,13 @@ fn publish_sps_result( defmt::todo!("no idea when we hit this"); } Ok(Err(err)) => { - let err = make_error_string(err); let err = SensorError::Sps30(err); let err = Error::Running(err); - publish.send_error(err) + publish.queue_error(err) } Err(_timeout) => { let err = Error::Timeout(Device::Sps30); - publish.send_error(err) + publish.queue_error(err) } } } @@ -141,7 +140,7 @@ fn publish_mhz_result( Result>, embassy_time::TimeoutError, >, - publish: &Channel, + publish: &Queues, ) where TxError: fmt::Debug + defmt::Format, RxError: fmt::Debug + defmt::Format, @@ -151,21 +150,20 @@ fn publish_mhz_result( publish.send_p0(Reading::Co2(co2)); } Ok(Err(err)) => { - let err = make_error_string(err); let err = SensorError::Mhz14(err); let err = Error::Running(err); - publish.send_error(err) + publish.queue_error(err) } Err(_timeout) => { let err = Error::Timeout(Device::Mhz14); - publish.send_error(err) + publish.queue_error(err) } } } fn publish_sht_result( sht_res: Result, embassy_time::TimeoutError>, - publish: &Channel, + publish: &Queues, ) { match sht_res { Ok(Ok(sht31::Reading { @@ -176,21 +174,20 @@ fn publish_sht_result( publish.send_p0(Reading::Humidity(humidity)); } Ok(Err(err)) => { - let err = make_error_string(err); let err = SensorError::Sht31(err); let err = Error::Running(err); - publish.send_error(err) + publish.queue_error(err) } Err(_timeout) => { let err = Error::Timeout(Device::Sht31); - publish.send_error(err) + publish.queue_error(err) } } } fn publish_bme_result( bme_res: Result>, - publish: &Channel, + publish: &Queues, ) { match bme_res { Ok(MeasurementData { @@ -203,10 +200,9 @@ fn publish_bme_result( publish.send_p0(Reading::Pressure(pressure)); } Err(err) => { - let err = make_error_string(err); let err = SensorError::Bme680(err); let err = Error::Running(err); - publish.send_error(err) + publish.queue_error(err) } } } From c61773e9bbb02c187dd89257d993657a578a62bf Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 6 Jun 2024 20:53:03 +0200 Subject: [PATCH 123/687] compiles with perhipheral generics removed --- crates/protocol/src/lib.rs | 8 +- sensor-nodes/bed-sensors/src/channel.rs | 88 ++++++++------------ sensor-nodes/bed-sensors/src/error_cache.rs | 42 +++------- sensor-nodes/bed-sensors/src/main.rs | 2 +- sensor-nodes/bed-sensors/src/sensors.rs | 22 ++++- sensor-nodes/bed-sensors/src/sensors/fast.rs | 25 ++---- sensor-nodes/bed-sensors/src/sensors/slow.rs | 62 +++++--------- 7 files changed, 101 insertions(+), 148 deletions(-) diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 0b4ccfb0..6d68abaa 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -181,7 +181,13 @@ impl Reading { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SensorMessage { - pub values: heapless::Vec, MAX_ITEMS>, + pub values: heapless::Vec, + pub version: u8, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ErrorReport { + pub error: Error, pub version: u8, } diff --git a/sensor-nodes/bed-sensors/src/channel.rs b/sensor-nodes/bed-sensors/src/channel.rs index 333ae108..0c12e77c 100644 --- a/sensor-nodes/bed-sensors/src/channel.rs +++ b/sensor-nodes/bed-sensors/src/channel.rs @@ -1,43 +1,27 @@ use core::fmt; -use defmt::unwrap; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::channel::Channel; use embassy_sync::mutex::Mutex; use embassy_sync::priority_channel::{self, PriorityChannel}; -use embassy_time::{Duration, Instant}; +use embassy_time::Instant; use heapless::Vec; use protocol::large_bedroom::bed::Reading; use crate::error_cache; -struct ErrorEvent -where - T: defmt::Format + fmt::Debug, - R: defmt::Format + fmt::Debug, - I: defmt::Format + fmt::Debug, -{ - error: error_cache::Error, +struct ErrorEvent { + error: error_cache::Error, at: Instant, } -pub struct Queues -where - T: defmt::Format + fmt::Debug, - R: defmt::Format + fmt::Debug, - I: defmt::Format + fmt::Debug, -{ +pub struct Queues { sensor_queue: PriorityChannel, - error_queue: Channel, 20>, - recent_errors: Mutex, 5>>, + error_queue: Channel, + recent_errors: Mutex>, } -impl Queues -where - T: defmt::Format + fmt::Debug + PartialEq, - R: defmt::Format + fmt::Debug + PartialEq, - I: defmt::Format + fmt::Debug + PartialEq, -{ +impl Queues { pub fn new() -> Self { Self { sensor_queue: PriorityChannel::new(), @@ -59,46 +43,42 @@ where self.sensor_queue.try_receive().ok() } - pub fn queue_error(&self, error: error_cache::Error) { - let mut recent_errors = unwrap!(self.recent_errors.try_lock()); - - let mut to_remove: Vec = Vec::new(); - for (idx, event) in recent_errors.iter().enumerate() { - if event.at.elapsed() > Duration::from_secs(60) { - unwrap!(to_remove.push(idx)); - } else if event.error == error { - return; - } - } - - for idx in to_remove.iter().rev() { - recent_errors.swap_remove(*idx); - } - let full = self.error_queue.try_send(error.clone()).is_err(); - - if !full { - let _ignore_full = recent_errors.push(ErrorEvent { - error, - at: Instant::now(), - }); - } + pub fn queue_error(&self, _error: error_cache::Error) { + // let mut recent_errors = unwrap!(self.recent_errors.try_lock()); + // + // let mut to_remove: Vec = Vec::new(); + // for (idx, event) in recent_errors.iter().enumerate() { + // if event.at.elapsed() > Duration::from_secs(60) { + // unwrap!(to_remove.push(idx)); + // } else if event.error == error { + // return; + // } + // } + // + // for idx in to_remove.iter().rev() { + // recent_errors.swap_remove(*idx); + // } + // let full = self.error_queue.try_send(error).is_err(); + + // if !full { + // let _ignore_full = recent_errors.push(ErrorEvent { + // error, + // at: Instant::now(), + // }); + // } } pub fn send_p0(&self, value: Reading) { let entry = PriorityValue { priority: 0, - value: protocol::Reading::LargeBedroom( - protocol::large_bedroom::Reading::Bed(value), - ), + value: protocol::Reading::LargeBedroom(protocol::large_bedroom::Reading::Bed(value)), }; let _ignore_full = self.sensor_queue.try_send(entry); } pub fn send_p1(&self, value: Reading) { let entry = PriorityValue { priority: 1, - value: protocol::Reading::LargeBedroom( - protocol::large_bedroom::Reading::Bed(value), - ), + value: protocol::Reading::LargeBedroom(protocol::large_bedroom::Reading::Bed(value)), }; let _ignore_full = self.sensor_queue.try_send(entry); } @@ -106,9 +86,7 @@ where pub fn send_p2(&self, value: Reading) { let entry = PriorityValue { priority: 2, - value: protocol::Reading::LargeBedroom( - protocol::large_bedroom::Reading::Bed(value), - ), + value: protocol::Reading::LargeBedroom(protocol::large_bedroom::Reading::Bed(value)), }; let _ignore_full = self.sensor_queue.try_send(entry); } diff --git a/sensor-nodes/bed-sensors/src/error_cache.rs b/sensor-nodes/bed-sensors/src/error_cache.rs index 9ddff2bf..be64b49a 100644 --- a/sensor-nodes/bed-sensors/src/error_cache.rs +++ b/sensor-nodes/bed-sensors/src/error_cache.rs @@ -6,32 +6,24 @@ use core::fmt; // use heapless::LinearMap; use protocol::large_bedroom::bed::{self, Device}; use protocol::make_error_string; + +use crate::sensors::{I2cError, UartError}; /// static global error fmt message cache // use protocol::large_bedroom::bed::Error; // static ERROR_CACHE: Mutex, 20>> = // Mutex::new(LinearMap::new()); -#[derive(PartialEq, Eq, Clone)] -pub enum SensorError -where - TxError: defmt::Format + fmt::Debug, - RxError: defmt::Format + fmt::Debug, - I2cError: defmt::Format + fmt::Debug, -{ - Mhz14(mhzx::Error), - Sps30(sps30_async::Error), +#[derive(PartialEq, Eq)] +pub enum SensorError { + Mhz14(mhzx::Error), + Sps30(sps30_async::Error), Sht31(sht31::SHTError), Bme680(bosch_bme680::BmeError), Max44(max44009::Error), } -impl Into for SensorError -where - TxError: defmt::Format + fmt::Debug, - RxError: defmt::Format + fmt::Debug, - I2cError: defmt::Format + fmt::Debug, -{ +impl Into for SensorError { fn into(self) -> bed::SensorError { match self { SensorError::Mhz14(e) => bed::SensorError::Mhz14(make_error_string(e)), @@ -43,25 +35,15 @@ where } } -#[derive(PartialEq, Eq, Clone)] -pub enum Error -where - TxError: defmt::Format + fmt::Debug, - RxError: defmt::Format + fmt::Debug, - I2cError: defmt::Format + fmt::Debug, -{ - Running(SensorError), - Setup(SensorError), +#[derive(PartialEq, Eq)] +pub enum Error { + Running(SensorError), + Setup(SensorError), Timeout(Device), SetupTimedOut(Device), } -impl Into for Error -where - TxError: defmt::Format + fmt::Debug, - RxError: defmt::Format + fmt::Debug, - I2cError: defmt::Format + fmt::Debug, -{ +impl Into for Error { fn into(self) -> bed::Error { match self { Error::Running(e) => bed::Error::Running(e.into()), diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index 27a10ed1..1464ff5f 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -217,7 +217,7 @@ async fn main(spawner: Spawner) { // let send_and_pet_dog = join::join(&mut send_published, keep_dog_happy); let send_and_pet_dog = &mut send_published; - // let init_then_measure = sensors::init_then_measure(&publish, i2c, usart_mhz, usart_sps30); + let init_then_measure = sensors::init_then_measure(&publish, i2c, usart_mhz, usart_sps30); // let init_then_measure = network_up.wait().then(|_| init_then_measure); // let res = select::select(send_and_pet_dog, init_then_measure).await; // let unrecoverable_err = match res { diff --git a/sensor-nodes/bed-sensors/src/sensors.rs b/sensor-nodes/bed-sensors/src/sensors.rs index 07d49d74..d2d4ad28 100644 --- a/sensor-nodes/bed-sensors/src/sensors.rs +++ b/sensor-nodes/bed-sensors/src/sensors.rs @@ -1,5 +1,5 @@ use defmt::info; -use embassy_embedded_hal::shared_bus; +use embassy_embedded_hal::shared_bus::{self, I2cDeviceError}; use embassy_futures::join; use embassy_stm32::i2c::I2c; use embassy_stm32::mode::Async; @@ -20,6 +20,22 @@ pub mod slow; // Todo make failed init not critical. Keep trying init in background // while we are measuring +// +pub type I2cError = I2cDeviceError; +pub type UartError = embassy_stm32::usart::Error; + +pub mod concrete_types { + use embassy_embedded_hal::shared_bus; + use embassy_stm32::i2c::I2c; + use embassy_stm32::mode::Async; + use embassy_stm32::usart::{RingBufferedUartRx, UartTx}; + use embassy_sync::blocking_mutex::raw::NoopRawMutex; + use shared_bus::asynch::i2c::I2cDevice; + + pub type ConcreteSharedI2c<'a, 'b> = I2cDevice<'a, NoopRawMutex, I2c<'b, Async>>; + pub type ConcreteTx<'a> = UartTx<'a, Async>; + pub type ConcreteRx<'a> = RingBufferedUartRx<'a>; +} pub async fn init_then_measure( publish: &Queues, @@ -27,16 +43,14 @@ pub async fn init_then_measure( usart_mhz: Uart<'static, Async>, usart_sps: Uart<'static, Async>, ) -> Result<(), Error> { - info!("initializing sensors"); - let bme_config = bosch_bme680::Configuration::default(); let bme = with_timeout( Duration::from_secs(2), bosch_bme680::Bme680::new( shared_bus::asynch::i2c::I2cDevice::new(&i2c), bosch_bme680::DeviceAddress::Secondary, Delay, - &bme_config, + &bosch_bme680::Configuration::default(), 20, ), ) diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed-sensors/src/sensors/fast.rs index 78952d2a..61604d3c 100644 --- a/sensor-nodes/bed-sensors/src/sensors/fast.rs +++ b/sensor-nodes/bed-sensors/src/sensors/fast.rs @@ -2,16 +2,14 @@ use defmt::warn; use embassy_futures::yield_now; use embassy_stm32::exti::ExtiInput; use embassy_time::{Duration, Instant, Timer}; -use embedded_hal_async::i2c::I2c; use max44009::Max44009; use crate::channel::Queues; +use crate::error_cache::{Error, SensorError}; -use protocol::large_bedroom::{ - bed::Button, - bed::{self, SensorError}, - bed::Reading, -}; +use protocol::large_bedroom::{bed::Button, bed::Reading}; + +use super::concrete_types::ConcreteSharedI2c as I2c; fn sig_lux_diff(old: f32, new: f32) -> bool { let diff = old - new; @@ -19,11 +17,7 @@ fn sig_lux_diff(old: f32, new: f32) -> bool { diff > old / 20.0 || -diff > old / 20.0 } -async fn report_lux(mut max44: Max44009, publish: &Queues) -where - I2C: I2c, - I2C::Error: defmt::Format, -{ +async fn report_lux(mut max44: Max44009>, publish: &Queues) { let mut prev_lux = f32::MAX; let mut last_lux = Instant::now(); const MIN_INTERVAL: Duration = Duration::from_secs(1); @@ -34,9 +28,8 @@ where let lux = match max44.read_lux().await { Ok(lux) => lux, Err(err) if last_lux.elapsed() > MIN_INTERVAL => { - let err = protocol::make_error_string(err); let err = SensorError::Max44(err); - let err = bed::Error::Running(err); + let err = Error::Running(err); let _ignore = publish.queue_error(err); continue; } @@ -95,11 +88,7 @@ pub struct ButtonInputs { pub lower_outer: ExtiInput<'static>, } -pub async fn read(max44: Max44009, /*inputs: ButtonInputs,*/ publish: &Queues) -where - I2C: I2c, - I2C::Error: defmt::Format, -{ +pub async fn read(max44: Max44009>, /*inputs: ButtonInputs,*/ publish: &Queues) { // let watch_buttons_1 = join5( // watch_button(inputs.top_left, BedButton::TopLeft, publish), // watch_button(inputs.top_right, BedButton::TopRight, publish), diff --git a/sensor-nodes/bed-sensors/src/sensors/slow.rs b/sensor-nodes/bed-sensors/src/sensors/slow.rs index 98952cea..6ba21363 100644 --- a/sensor-nodes/bed-sensors/src/sensors/slow.rs +++ b/sensor-nodes/bed-sensors/src/sensors/slow.rs @@ -1,46 +1,36 @@ -use core::fmt; - use defmt::unwrap; use embassy_futures::{join, yield_now}; use embassy_time::{with_timeout, Delay, Duration, Timer}; -use embedded_hal_async::delay::DelayNs; -use embedded_hal_async::i2c::I2c; use mhzx::MHZ; use protocol::large_bedroom::bed::{Device, Reading}; use bosch_bme680::{Bme680, MeasurementData}; -use protocol::make_error_string; use sht31::mode::{Sht31Measure, Sht31Reader, SingleShot}; use sht31::SHT31; use sps30_async as sps30; use sps30_async::Sps30; -use crate::error_cache::SensorError; -use crate::error_cache::Error; use crate::channel::Queues; +use crate::error_cache::Error; +use crate::error_cache::SensorError; + +use super::{I2cError, UartError}; const SPS30_UART_BUF_SIZE: usize = 100; const SPS30_DRIVER_BUF_SIZE: usize = 2 * SPS30_UART_BUF_SIZE; -pub async fn read( - mut sht: SHT31, - mut bme: Bme680, - mut mhz: MHZ, - mut sps: Sps30, - publish: &Queues, -) where - I2C: I2c, - I2C::Error: defmt::Format, - TX1: embedded_io_async::Write, - TX1::Error: defmt::Format, - RX1: embedded_io_async::Read, - RX1::Error: defmt::Format, - TX2: embedded_io_async::Write, - TX2::Error: defmt::Format, - RX2: embedded_io_async::Read, - RX2::Error: defmt::Format, -{ +use super::concrete_types::ConcreteRx as Rx; +use super::concrete_types::ConcreteSharedI2c as I2c; +use super::concrete_types::ConcreteTx as Tx; + +pub async fn read( + mut sht: SHT31>, + mut bme: Bme680, Delay>, + mut mhz: MHZ, Rx<'_>>, + mut sps: Sps30, Rx<'_>, Delay>, + publish: &'_ Queues, +) { // sht works in two steps // - send measure command before sleep // - then read @@ -86,16 +76,13 @@ pub async fn read( } } -fn publish_sps_result( +fn publish_sps_result( sps_res: Result< - Result, sps30::Error>, + Result, sps30::Error>, embassy_time::TimeoutError, >, publish: &Queues, -) where - TxError: fmt::Debug + defmt::Format, - RxError: fmt::Debug + defmt::Format, -{ +) { match sps_res { Ok(Ok(Some(sps30::Measurement { mass_pm1_0, @@ -135,16 +122,13 @@ fn publish_sps_result( } } -fn publish_mhz_result( +fn publish_mhz_result( mhz_res: Result< - Result>, + Result>, embassy_time::TimeoutError, >, publish: &Queues, -) where - TxError: fmt::Debug + defmt::Format, - RxError: fmt::Debug + defmt::Format, -{ +) { match mhz_res { Ok(Ok(mhzx::Measurement { co2, .. })) => { publish.send_p0(Reading::Co2(co2)); @@ -185,8 +169,8 @@ fn publish_sht_result( } } -fn publish_bme_result( - bme_res: Result>, +fn publish_bme_result( + bme_res: Result>, publish: &Queues, ) { match bme_res { From 08f4e929c358a1101eb6e822b9ba827e1a27a2ef Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 8 Jun 2024 22:02:07 +0200 Subject: [PATCH 124/687] adds rng based on pac adc to feed network seed --- sensor-nodes/bed-sensors/.cargo/config.toml | 3 +- sensor-nodes/bed-sensors/Cargo.lock | 36 ++++---- sensor-nodes/bed-sensors/Cargo.toml | 34 +++++--- sensor-nodes/bed-sensors/src/channel.rs | 52 +++++------ sensor-nodes/bed-sensors/src/error_cache.rs | 15 +--- sensor-nodes/bed-sensors/src/main.rs | 80 +++++++++-------- sensor-nodes/bed-sensors/src/network.rs | 16 ++-- sensor-nodes/bed-sensors/src/rng.rs | 90 ++++++++++++++++++++ sensor-nodes/bed-sensors/src/sensors.rs | 2 +- sensor-nodes/bed-sensors/src/sensors/fast.rs | 4 +- sensor-nodes/bed-sensors/src/sensors/slow.rs | 18 ++-- 11 files changed, 214 insertions(+), 136 deletions(-) create mode 100644 sensor-nodes/bed-sensors/src/rng.rs diff --git a/sensor-nodes/bed-sensors/.cargo/config.toml b/sensor-nodes/bed-sensors/.cargo/config.toml index 05349a7d..e88f9bcf 100644 --- a/sensor-nodes/bed-sensors/.cargo/config.toml +++ b/sensor-nodes/bed-sensors/.cargo/config.toml @@ -2,6 +2,7 @@ # replace STM32F103C8 with your chip as listed in `probe-rs chip list` # runner = "probe-rs run --chip STM32F103C8" runner = "probe-rs run --chip STM32F401CCUx" +linker = "flip-link" [build] # target = "thumbv7m-none-eabi" for f103 @@ -9,7 +10,7 @@ target = "thumbv7em-none-eabihf" [env] DEFMT_LOG = "debug,sps30_async=trace,bosch_bme680=info" -EMBASSY_EXECUTOR_TASK_ARENA_SIZE="4000" +EMBASSY_EXECUTOR_TASK_ARENA_SIZE="7000" # [unstable] # build-std = ["core"] diff --git a/sensor-nodes/bed-sensors/Cargo.lock b/sensor-nodes/bed-sensors/Cargo.lock index c2a3e182..ffd6c526 100644 --- a/sensor-nodes/bed-sensors/Cargo.lock +++ b/sensor-nodes/bed-sensors/Cargo.lock @@ -26,6 +26,12 @@ dependencies = [ "rustc_version 0.2.3", ] +[[package]] +name = "bare-metal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" + [[package]] name = "bed-sensors" version = "0.2.0" @@ -58,6 +64,7 @@ dependencies = [ "sht31", "sps30-async", "static_cell", + "stm32f4", ] [[package]] @@ -144,7 +151,7 @@ version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" dependencies = [ - "bare-metal", + "bare-metal 0.2.5", "bitfield 0.13.2", "critical-section", "embedded-hal 0.2.7", @@ -281,7 +288,6 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "defmt", "embassy-futures", @@ -298,7 +304,6 @@ dependencies = [ [[package]] name = "embassy-executor" version = "0.5.0" -source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "cortex-m", "critical-section", @@ -312,7 +317,6 @@ dependencies = [ [[package]] name = "embassy-executor-macros" version = "0.4.1" -source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "darling", "proc-macro2", @@ -323,12 +327,10 @@ dependencies = [ [[package]] name = "embassy-futures" version = "0.1.1" -source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" [[package]] name = "embassy-hal-internal" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "cortex-m", "critical-section", @@ -339,7 +341,6 @@ dependencies = [ [[package]] name = "embassy-net" version = "0.4.0" -source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "defmt", "document-features", @@ -356,7 +357,6 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "defmt", ] @@ -364,7 +364,6 @@ dependencies = [ [[package]] name = "embassy-net-driver-channel" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "embassy-futures", "embassy-net-driver", @@ -374,7 +373,6 @@ dependencies = [ [[package]] name = "embassy-net-wiznet" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "defmt", "embassy-futures", @@ -387,7 +385,6 @@ dependencies = [ [[package]] name = "embassy-stm32" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "bit_field", "bitflags 2.5.0", @@ -431,7 +428,6 @@ dependencies = [ [[package]] name = "embassy-sync" version = "0.6.0" -source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "cfg-if", "critical-section", @@ -444,7 +440,6 @@ dependencies = [ [[package]] name = "embassy-time" version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "cfg-if", "critical-section", @@ -462,7 +457,6 @@ dependencies = [ [[package]] name = "embassy-time-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "document-features", ] @@ -470,12 +464,10 @@ dependencies = [ [[package]] name = "embassy-time-queue-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" [[package]] name = "embassy-usb-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "defmt", ] @@ -483,7 +475,6 @@ dependencies = [ [[package]] name = "embassy-usb-synopsys-otg" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=039d8ed#039d8ed671c70c4716edd8ffa2d40f3babef9b43" dependencies = [ "critical-section", "embassy-sync", @@ -1095,6 +1086,17 @@ dependencies = [ "cortex-m-rt", ] +[[package]] +name = "stm32f4" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb94729242cd1aebe6dab42a2ca0131985ae93bc3ab2751b680df724bb35528d" +dependencies = [ + "bare-metal 1.0.0", + "cortex-m", + "vcell", +] + [[package]] name = "strsim" version = "0.11.1" diff --git a/sensor-nodes/bed-sensors/Cargo.toml b/sensor-nodes/bed-sensors/Cargo.toml index 4fa6cb65..aa2bc8a6 100644 --- a/sensor-nodes/bed-sensors/Cargo.toml +++ b/sensor-nodes/bed-sensors/Cargo.toml @@ -31,7 +31,6 @@ panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.8", default-features = false } nb = "1.0.0" -rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } static_cell = "2.0.0" # sensors @@ -44,23 +43,38 @@ sps30-async = { version = "0.2.0", path = "/home/david/tmp/sps30", features = [" # encoding protocol = { path = "../../crates/protocol" } + +# used only for RNG since embassy's adc is currently broken and we need +# an adc to get a true RNG. +# stm32f4xx-hal = { version = "0.21.0", default-features = false, features = ["stm32f401"] } +stm32f4 = { version = "0.15.1", default-features = false, features = ["stm32f401"] } +rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } # fasthash = { version = "0.4.0", default-features = false } [patch.crates-io] -embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } -embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } -embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } -embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } -embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } -embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } -embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } -embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } +# embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } +# embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } +# embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } +# embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } +# embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } +# embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } +# embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } +# embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } + +embassy-stm32 = {path = "../../../embassy/embassy-stm32" } +embassy-net = {path = "../../../embassy/embassy-net" } +embassy-net-wiznet = {path = "../../../embassy/embassy-net-wiznet" } +embassy-sync = {path = "../../../embassy/embassy-sync" } +embassy-executor = {path = "../../../embassy/embassy-executor" } +embassy-embedded-hal = {path = "../../../embassy/embassy-embedded-hal" } +embassy-time = {path = "../../../embassy/embassy-time" } +embassy-futures = {path = "../../../embassy/embassy-futures" } [profile.dev] opt-level = "s" [profile.release] -lto = true +lto = "fat" opt-level = "s" incremental = false codegen-units = 1 diff --git a/sensor-nodes/bed-sensors/src/channel.rs b/sensor-nodes/bed-sensors/src/channel.rs index 0c12e77c..b465f155 100644 --- a/sensor-nodes/bed-sensors/src/channel.rs +++ b/sensor-nodes/bed-sensors/src/channel.rs @@ -1,24 +1,18 @@ -use core::fmt; - use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::channel::Channel; use embassy_sync::mutex::Mutex; use embassy_sync::priority_channel::{self, PriorityChannel}; -use embassy_time::Instant; -use heapless::Vec; +use embassy_time::{Duration, Instant}; +use heapless::HistoryBuffer; use protocol::large_bedroom::bed::Reading; use crate::error_cache; -struct ErrorEvent { - error: error_cache::Error, - at: Instant, -} - pub struct Queues { sensor_queue: PriorityChannel, error_queue: Channel, - recent_errors: Mutex>, + recent_errors: Mutex>, + recent_is_since: Instant, } impl Queues { @@ -26,7 +20,8 @@ impl Queues { Self { sensor_queue: PriorityChannel::new(), error_queue: Channel::new(), - recent_errors: Mutex::new(Vec::new()), + recent_errors: Mutex::new(HistoryBuffer::new()), + recent_is_since: Instant::now(), } } @@ -43,29 +38,20 @@ impl Queues { self.sensor_queue.try_receive().ok() } - pub fn queue_error(&self, _error: error_cache::Error) { - // let mut recent_errors = unwrap!(self.recent_errors.try_lock()); - // - // let mut to_remove: Vec = Vec::new(); - // for (idx, event) in recent_errors.iter().enumerate() { - // if event.at.elapsed() > Duration::from_secs(60) { - // unwrap!(to_remove.push(idx)); - // } else if event.error == error { - // return; - // } - // } - // - // for idx in to_remove.iter().rev() { - // recent_errors.swap_remove(*idx); - // } - // let full = self.error_queue.try_send(error).is_err(); + pub fn queue_error(&self, error: error_cache::Error) { + // unwrap safe: is not used in interrupts + let mut recent_errors = defmt::unwrap!(self.recent_errors.try_lock()); + if self.recent_is_since.elapsed() > Duration::from_secs(60 * 5) { + recent_errors.clear(); + } + if recent_errors.contains(&error) { + return; + } - // if !full { - // let _ignore_full = recent_errors.push(ErrorEvent { - // error, - // at: Instant::now(), - // }); - // } + let Ok(()) = self.error_queue.try_send(error.clone()) else { + return; + }; + recent_errors.write(error) } pub fn send_p0(&self, value: Reading) { diff --git a/sensor-nodes/bed-sensors/src/error_cache.rs b/sensor-nodes/bed-sensors/src/error_cache.rs index be64b49a..526016e7 100644 --- a/sensor-nodes/bed-sensors/src/error_cache.rs +++ b/sensor-nodes/bed-sensors/src/error_cache.rs @@ -1,20 +1,9 @@ -use core::fmt; - -// use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; -// use embassy_sync::blocking_mutex::Mutex; -// use fasthash::{murmur3, Murmur3Hasher, SeaHasher}; -// use heapless::LinearMap; use protocol::large_bedroom::bed::{self, Device}; use protocol::make_error_string; use crate::sensors::{I2cError, UartError}; -/// static global error fmt message cache -// use protocol::large_bedroom::bed::Error; - -// static ERROR_CACHE: Mutex, 20>> = -// Mutex::new(LinearMap::new()); -#[derive(PartialEq, Eq)] +#[derive(defmt::Format, PartialEq, Eq, Clone)] pub enum SensorError { Mhz14(mhzx::Error), Sps30(sps30_async::Error), @@ -35,7 +24,7 @@ impl Into for SensorError { } } -#[derive(PartialEq, Eq)] +#[derive(defmt::Format, PartialEq, Eq, Clone)] pub enum Error { Running(SensorError), Setup(SensorError), diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index 1464ff5f..21e0202d 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -1,16 +1,16 @@ #![no_std] #![no_main] -use defmt::{error, info, trace, unwrap}; +use defmt::{error, trace, unwrap}; use embassy_executor::Spawner; +use embassy_futures::select; use embassy_futures::select::Either; -use embassy_futures::{join, select}; use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources}; use embassy_net_wiznet::{chip::W5500, Device, Runner, State}; -use embassy_stm32::interrupt; use embassy_stm32::exti::ExtiInput; use embassy_stm32::gpio::{Level, Output, Pull, Speed}; use embassy_stm32::i2c::{self, I2c}; +use embassy_stm32::interrupt; use embassy_stm32::mode::Async; use embassy_stm32::peripherals::IWDG; use embassy_stm32::spi::{Config as SpiConfig, Spi}; @@ -21,19 +21,19 @@ use embassy_stm32::Config; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; use embassy_sync::signal::Signal; -use embassy_time::{Delay, Timer}; +use embassy_time::{Delay, Instant, Timer}; use embedded_hal_bus::spi::ExclusiveDevice; use futures::{pin_mut, FutureExt}; use heapless::Vec; -use rand::{rngs::SmallRng, Rng, SeedableRng}; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; mod channel; +mod error_cache; mod network; mod sensors; -mod error_cache; +mod rng; use crate::channel::Queues; embassy_stm32::bind_interrupts!(struct Irqs { @@ -55,6 +55,20 @@ unsafe fn USART6() { #[embassy_executor::task] async fn print_if_running_task() -> ! { loop { + // let mut now = Instant::now(); + // let mut biggest = 0; + // for _ in 0..1000 { + // Timer::after_millis(1).await; + // let new_now = Instant::now(); + // let elapsed = (new_now - now).as_millis(); + // now = new_now; + // + // if elapsed > biggest { + // biggest = elapsed; + // } + // } + // defmt::info!("still running, largest delay was: {}ms", biggest); + Timer::after_secs(1).await; defmt::info!("still running"); } @@ -103,8 +117,9 @@ fn config() -> Config { #[embassy_executor::main] async fn main(spawner: Spawner) { let p = embassy_stm32::init(config()); + let seed = rng::generate_seed_blocking(); + defmt::info!("random seed: {}", seed); // let dog = IndependentWatchdog::new(p.IWDG, 20 * 1000 * 1000); - let publish = Queues::new(); let mut usart_config = usart::Config::default(); usart_config.baudrate = 9600; @@ -149,6 +164,7 @@ async fn main(spawner: Spawner) { ); let i2c: Mutex = Mutex::new(i2c); + /* // let buttons = ButtonInputs { // top_left: ExtiInput::new(p.PA13, p.EXTI13, Pull::Down), // top_right: ExtiInput::new(p.PA14, p.EXTI14, Pull::Down), @@ -159,6 +175,7 @@ async fn main(spawner: Spawner) { // lower_center: ExtiInput::new(p.PA15, p.EXTI15, Pull::Down), // lower_outer: ExtiInput::new(p.PB5, p.EXTI5, Pull::Down), // }; + */ let mut spi_cfg = SpiConfig::default(); spi_cfg.frequency = Hertz(50_000_000); // up to 50m works @@ -171,16 +188,10 @@ async fn main(spawner: Spawner) { let w5500_reset = Output::new(p.PB1, Level::High, Speed::VeryHigh); let mac_addr = [0x02, 234, 3, 4, 82, 231]; - static STATE: StaticCell> = StaticCell::new(); - let state = STATE.init(State::<8, 8>::new()); - let (device, runner) = embassy_net_wiznet::new( - mac_addr, - state, - spi, - w5500_int, - w5500_reset, - ) - .await; + static STATE: StaticCell> = StaticCell::new(); + let state = STATE.init(State::<3, 2>::new()); + let (device, runner) = + embassy_net_wiznet::new(mac_addr, state, spi, w5500_int, w5500_reset).await; unwrap!(spawner.spawn(ethernet_task(runner))); // Init network stack @@ -188,7 +199,7 @@ async fn main(spawner: Spawner) { unwrap!(dns_servers.push(Ipv4Address([192, 168, 1, 1]))); unwrap!(dns_servers.push(Ipv4Address([192, 168, 1, 1]))); unwrap!(dns_servers.push(Ipv4Address([192, 168, 1, 1]))); - static STACK: StaticCell>> = StaticCell::new(); + static STACK: StaticCell> = StaticCell::new(); static RESOURCES: StaticCell> = StaticCell::new(); let stack = &*STACK.init(Stack::new( device, @@ -198,7 +209,7 @@ async fn main(spawner: Spawner) { dns_servers, }), RESOURCES.init(StackResources::<2>::new()), - 384, + seed, )); // Launch network task @@ -208,30 +219,25 @@ async fn main(spawner: Spawner) { let spawner = EXECUTOR_HIGH.start(embassy_stm32::interrupt::USART6); unwrap!(spawner.spawn(print_if_running_task())); - Timer::after_secs(999).await; - let network_up: Signal = Signal::new(); - network_up.signal(()); - let send_published = network::send_published(stack, &publish, &network_up); + let publish = Queues::new(); + let send_published = network::send_published(stack, &publish); pin_mut!(send_published); // let keep_dog_happy = keep_dog_happy(dog); // let send_and_pet_dog = join::join(&mut send_published, keep_dog_happy); let send_and_pet_dog = &mut send_published; let init_then_measure = sensors::init_then_measure(&publish, i2c, usart_mhz, usart_sps30); - // let init_then_measure = network_up.wait().then(|_| init_then_measure); - // let res = select::select(send_and_pet_dog, init_then_measure).await; - // let unrecoverable_err = match res { - // Either::First(_) => defmt::unreachable!(), - // Either::Second(Ok(())) => defmt::unreachable!(), - // Either::Second(Err(err)) => err, - // }; - // - // let send_critical_error = join::join( - // publish.send_critical_error(unrecoverable_err.clone()), - // send_published, - // ); - // error!("unrecoverable error, resetting: {}", unrecoverable_err); - // send_critical_error.await; // if this takes too long the dog will get us + let res = select::select(send_and_pet_dog, init_then_measure).await; + let unrecoverable_err = match res { + Either::First(_) => defmt::unreachable!(), + Either::Second(Ok(())) => defmt::unreachable!(), + Either::Second(Err(err)) => err, + }; + + // at this point no other errors have occurred + error!("unrecoverable error, resetting: {}", unrecoverable_err); + publish.queue_error(unrecoverable_err); + send_published.await; // if this takes too long the dog will get us } async fn keep_dog_happy<'a>(mut dog: IndependentWatchdog<'a, IWDG>) { diff --git a/sensor-nodes/bed-sensors/src/network.rs b/sensor-nodes/bed-sensors/src/network.rs index 420f6c81..a6e1f5a0 100644 --- a/sensor-nodes/bed-sensors/src/network.rs +++ b/sensor-nodes/bed-sensors/src/network.rs @@ -1,9 +1,7 @@ -use defmt::{info, unwrap, warn}; +use defmt::{debug, info, unwrap, warn}; use embassy_net::driver::Driver; use embassy_net::tcp::TcpSocket; use embassy_net::{Ipv4Address, Stack}; -use embassy_sync::blocking_mutex::raw::NoopRawMutex; -use embassy_sync::signal::Signal; use embassy_time::{with_timeout, Duration, Instant, Timer}; use embedded_io_async::Write; use protocol::SensorMessage; @@ -46,19 +44,20 @@ async fn get_messages(publish: &Queues, msg: &mut Msg) { pub async fn send_published( stack: &Stack, publish: &Queues, - network_up: &Signal, ) { - let mut rx_buffer = [0; 200]; - let mut tx_buffer = [0; Msg::ENCODED_SIZE * 2]; + let mut rx_buffer = [0; 1024]; + let mut tx_buffer = [0; 1024]; + // let mut tx_buffer = [0; Msg::ENCODED_SIZE * 2]; let mut msg = Msg::new(); let mut encoded_msg_buffer = [0; Msg::ENCODED_SIZE]; let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); - socket.set_timeout(Some(Duration::from_secs(5))); - let host_addr = Ipv4Address::new(192, 168, 1, 43); + // socket.set_timeout(Some(Duration::from_secs(5))); + let host_addr = Ipv4Address::new(192, 168, 1, 46); let host_port = 1234; + debug!("Configured socket and connecting"); loop { let connected = socket.remote_endpoint().is_some(); if !connected { @@ -70,7 +69,6 @@ pub async fn send_published( info!("(re-)connected"); // prevent out-dated data from being send publish.clear().await; - network_up.signal(()); } } diff --git a/sensor-nodes/bed-sensors/src/rng.rs b/sensor-nodes/bed-sensors/src/rng.rs new file mode 100644 index 00000000..db82b817 --- /dev/null +++ b/sensor-nodes/bed-sensors/src/rng.rs @@ -0,0 +1,90 @@ +use rand::{RngCore, SeedableRng}; +use stm32f4::stm32f401; +// use stm32f4xx_hal::{ +// adc::{ +// config::{AdcConfig, Resolution, SampleTime}, +// Adc, +// }, +// pac, +// prelude::*, +// }; +// +// /// #Warning +// /// Should only be called before async tasks are spawned. This takes a lot of +// /// time to run and will disturb any async task running. +// pub fn generate_seed_once() -> u64 { +// let p = pac::Peripherals::take().expect("function generate_once should only be called once"); +// let gpioa = p.GPIOA.split(); +// let adc_pin = gpioa.pa1.into_analog(); +// +// let adc_config = AdcConfig::default().resolution(Resolution::Twelve); +// +// let mut adc = Adc::adc1(p.ADC1, true, adc_config); +// +// let mut seed = [0u8; 16]; +// for byte in &mut seed { +// let sample = adc.convert(&adc_pin, SampleTime::Cycles_3); +// let most_noisy_byte = (sample & 0b0000_0000_1111_1111) as u8; +// *byte = most_noisy_byte; +// } +// +// let mut rng = rand::rngs::SmallRng::from_seed(seed); +// rng.next_u64() +// } + +/// #Warning +/// Should only be called before async tasks are spawned. This takes a lot of +/// time to run and will disturb any async task running. +pub fn generate_seed_blocking() -> u64 { + let p = + stm32f401::Peripherals::take().expect("function generate_once should only be called once"); + + // enable clock to the adc such that we can control it + p.RCC.apb2enr.modify(|_, reg| reg.adc1en().enabled()); + + p.ADC_COMMON.ccr.modify(|_, reg| { + reg + // disable vbat (needed to enable the temp sensor) + .vbate() + .disabled() + // enable the temperature sensor + .tsvrefe() + .enabled() + }); + + // set resolution to 12bit + p.ADC1.cr1.modify(|_, reg| reg.res().twelve_bit()); + // adc conversion sequence has only 1 value + p.ADC1.sqr1.modify(|_, reg| reg.l().bits(0b0000)); + // setup channel 18 which is connected to the internal temperature sensor + p.ADC1.sqr3.modify(|_, reg| reg.sq1().variant(18)); + // enable the end of conversion bit + p.ADC1.cr2.modify(|_, reg| reg.eocs().each_conversion()); + // disable continues conversions + p.ADC1.cr2.modify(|_, reg| reg.cont().clear_bit()); + + // finally start the adc + p.ADC1.cr2.modify(|_, reg| reg.adon().set_bit()); + + let adc_read = || { + // clear any overrun status first + p.ADC1.sr.modify(|_, reg| reg.ovr().clear_bit()); + // start single conversion mode for a regular channel (18) + p.ADC1.cr2.modify(|_, reg| reg.swstart().set_bit()); + + // while not status register end of conversion bit is set + while !p.ADC1.sr.read().eoc().bit_is_set() {} + let value = p.ADC1.dr.read().bits(); + value + }; + + let mut seed = [0u8; 16]; + for byte in &mut seed { + let sample = adc_read(); + let most_noisy_byte = (sample & 0b0000_0000_1111_1111) as u8; + *byte = most_noisy_byte; + } + + let mut rng = rand::rngs::SmallRng::from_seed(seed); + rng.next_u64() +} diff --git a/sensor-nodes/bed-sensors/src/sensors.rs b/sensor-nodes/bed-sensors/src/sensors.rs index d2d4ad28..a6732249 100644 --- a/sensor-nodes/bed-sensors/src/sensors.rs +++ b/sensor-nodes/bed-sensors/src/sensors.rs @@ -32,7 +32,7 @@ pub mod concrete_types { use embassy_sync::blocking_mutex::raw::NoopRawMutex; use shared_bus::asynch::i2c::I2cDevice; - pub type ConcreteSharedI2c<'a, 'b> = I2cDevice<'a, NoopRawMutex, I2c<'b, Async>>; + pub type ConcreteSharedI2c<'a> = I2cDevice<'a, NoopRawMutex, I2c<'static, Async>>; pub type ConcreteTx<'a> = UartTx<'a, Async>; pub type ConcreteRx<'a> = RingBufferedUartRx<'a>; } diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed-sensors/src/sensors/fast.rs index 61604d3c..4060e7b8 100644 --- a/sensor-nodes/bed-sensors/src/sensors/fast.rs +++ b/sensor-nodes/bed-sensors/src/sensors/fast.rs @@ -17,7 +17,7 @@ fn sig_lux_diff(old: f32, new: f32) -> bool { diff > old / 20.0 || -diff > old / 20.0 } -async fn report_lux(mut max44: Max44009>, publish: &Queues) { +async fn report_lux(mut max44: Max44009>, publish: &Queues) { let mut prev_lux = f32::MAX; let mut last_lux = Instant::now(); const MIN_INTERVAL: Duration = Duration::from_secs(1); @@ -88,7 +88,7 @@ pub struct ButtonInputs { pub lower_outer: ExtiInput<'static>, } -pub async fn read(max44: Max44009>, /*inputs: ButtonInputs,*/ publish: &Queues) { +pub async fn read(max44: Max44009>, /*inputs: ButtonInputs,*/ publish: &Queues) { // let watch_buttons_1 = join5( // watch_button(inputs.top_left, BedButton::TopLeft, publish), // watch_button(inputs.top_right, BedButton::TopRight, publish), diff --git a/sensor-nodes/bed-sensors/src/sensors/slow.rs b/sensor-nodes/bed-sensors/src/sensors/slow.rs index 6ba21363..85878457 100644 --- a/sensor-nodes/bed-sensors/src/sensors/slow.rs +++ b/sensor-nodes/bed-sensors/src/sensors/slow.rs @@ -1,5 +1,5 @@ use defmt::unwrap; -use embassy_futures::{join, yield_now}; +use embassy_futures::join; use embassy_time::{with_timeout, Delay, Duration, Timer}; use mhzx::MHZ; @@ -24,9 +24,10 @@ use super::concrete_types::ConcreteRx as Rx; use super::concrete_types::ConcreteSharedI2c as I2c; use super::concrete_types::ConcreteTx as Tx; +#[inline(always)] pub async fn read( - mut sht: SHT31>, - mut bme: Bme680, Delay>, + mut sht: SHT31>, + mut bme: Bme680, Delay>, mut mhz: MHZ, Rx<'_>>, mut sps: Sps30, Rx<'_>, Delay>, publish: &'_ Queues, @@ -44,24 +45,15 @@ pub async fn read( loop { defmt::info!("this is where we break"); let sht_read = with_timeout(Duration::from_millis(100), sht.read()); - yield_now().await; - let bme_measure = bme.measure(); - yield_now().await; + let bme_measure = bme.measure(); // can not hang let mhz_measure = with_timeout(Duration::from_millis(100), mhz.read_co2()); - yield_now().await; let sps_measure = with_timeout(Duration::from_millis(100), sps.read_measurement()); - yield_now().await; // with this yield enabled the program hangs within 12 seconds let (bme_res, sht_res, mhz_res, sps_res) = join::join4(bme_measure, sht_read, mhz_measure, sps_measure).await; - // let (bme_res, sht_res, mhz_res) = join::join3(bme_measure, sht_read, mhz_measure).await; - yield_now().await; publish_bme_result(bme_res, publish); - yield_now().await; publish_sht_result(sht_res, publish); - yield_now().await; publish_mhz_result(mhz_res, publish); - yield_now().await; publish_sps_result(sps_res, publish); // sht works in two steps From 3cec453c37f7015f1638470f50024724cb013edf Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 9 Jun 2024 12:03:46 +0200 Subject: [PATCH 125/687] adds state machine (fault tolerance) for Bme680 --- sensor-nodes/bed-sensors/src/sensors.rs | 1 + sensor-nodes/bed-sensors/src/sensors/retry.rs | 85 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 sensor-nodes/bed-sensors/src/sensors/retry.rs diff --git a/sensor-nodes/bed-sensors/src/sensors.rs b/sensor-nodes/bed-sensors/src/sensors.rs index a6732249..9892b861 100644 --- a/sensor-nodes/bed-sensors/src/sensors.rs +++ b/sensor-nodes/bed-sensors/src/sensors.rs @@ -17,6 +17,7 @@ use crate::error_cache::{Error, SensorError}; pub mod fast; pub mod slow; +pub mod retry; // Todo make failed init not critical. Keep trying init in background // while we are measuring diff --git a/sensor-nodes/bed-sensors/src/sensors/retry.rs b/sensor-nodes/bed-sensors/src/sensors/retry.rs new file mode 100644 index 00000000..b13f47c0 --- /dev/null +++ b/sensor-nodes/bed-sensors/src/sensors/retry.rs @@ -0,0 +1,85 @@ +use bosch_bme680::{BmeError, Configuration, DeviceAddress, MeasurementData}; +use embassy_embedded_hal::shared_bus::{self, I2cDeviceError}; +use embassy_stm32::i2c::I2c; +use embassy_stm32::mode::Async; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::mutex::Mutex; +use embassy_time::Delay; + +// use super::concrete_types::ConcreteRx as Rx; +use super::concrete_types::ConcreteSharedI2c; +// use super::concrete_types::ConcreteTx as Tx; +use crate::error_cache::{Error, SensorError}; + +enum Bme680<'a> { + Ready { + bme: bosch_bme680::Bme680, Delay>, + i2c: &'a Mutex>, + }, + Uninit { + i2c: &'a Mutex>, + }, +} + +impl<'a> Bme680<'a> { + pub fn new(i2c: &'a Mutex>) -> Self { + Self::Uninit { i2c } + } + + /// cancel safe, any cancelation will end us in the Uninit state + /// which is where we want to be after stopping in the middle of + /// a transaction + pub async fn try_measure(&mut self) -> Result { + let i2c = *match self { + Bme680::Ready { i2c, .. } => i2c, + Bme680::Uninit { i2c } => i2c, + }; + + let mut owned_self = Self::Uninit { i2c }; + core::mem::swap(&mut owned_self, self); + let (mut new_self, res) = owned_self.advance_state().await; + core::mem::swap(&mut new_self, self); + res + } + + async fn advance_state(mut self) -> (Self, Result) { + match self { + Bme680::Ready { ref mut bme, i2c } => match bme.measure().await { + Ok(val) => return (self, Ok(val)), + Err(err) => { + let new_self = Self::Uninit { i2c }; + let err = Error::Running(SensorError::Bme680(err)); + (new_self, Err(err)) + } + }, + Bme680::Uninit { i2c } => { + let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(i2c); + match bosch_bme680::Bme680::new( + shared_i2c, + DeviceAddress::Secondary, + Delay, + &Configuration::default(), + 21, + ) + .await + { + Ok(mut bme) => { + let val = match bme.measure().await { + Ok(val) => val, + Err(err) => { + let err = Error::Running(SensorError::Bme680(err)); + return (self, Err(err)); + } + }; + let new_self = Self::Ready { bme, i2c }; + (new_self, Ok(val)) + } + Err(err) => { + let err = Error::Setup(SensorError::Bme680(err)); + (self, Err(err)) + } + } + } + } + } +} From 803c6fcf8717cd9bbc3e7a3a627a0562fe254117 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 9 Jun 2024 13:16:09 +0200 Subject: [PATCH 126/687] adds generic ReInitOnError driver wrapper --- sensor-nodes/bed-sensors/src/sensors/retry.rs | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) diff --git a/sensor-nodes/bed-sensors/src/sensors/retry.rs b/sensor-nodes/bed-sensors/src/sensors/retry.rs index b13f47c0..d782e948 100644 --- a/sensor-nodes/bed-sensors/src/sensors/retry.rs +++ b/sensor-nodes/bed-sensors/src/sensors/retry.rs @@ -5,12 +5,167 @@ use embassy_stm32::mode::Async; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; use embassy_time::Delay; +use max44009::{Max44009, SlaveAddr}; // use super::concrete_types::ConcreteRx as Rx; use super::concrete_types::ConcreteSharedI2c; // use super::concrete_types::ConcreteTx as Tx; use crate::error_cache::{Error, SensorError}; +trait Driver: Sized { + type Parts: Clone; + type Measurement; + + async fn init() -> Result; + async fn measure(&mut self) -> Result; +} + +enum ReInitOnErrorDriver +where + D: Driver, +{ + Ready { driver: D, parts: D::Parts }, + Uninit { parts: D::Parts }, +} + +impl ReInitOnErrorDriver { + pub fn new(parts: D::Parts) -> Self { + Self::Uninit { parts } + } + + pub async fn try_measure(&mut self) -> Result { + let parts = match self { + Self::Ready { parts, .. } => parts, + Self::Uninit { parts } => parts, + } + .clone(); + + let mut owned_self = Self::Uninit { parts }; + core::mem::swap(&mut owned_self, self); + let (mut new_self, res) = owned_self.advance_state().await; + core::mem::swap(&mut new_self, self); + res + } + + async fn advance_state(mut self) -> (Self, Result) { + match self { + Self::Ready { + mut driver, + parts, + // make a trait over driver that has a measure method + } => match driver.measure().await { + Ok(val) => { + let new_self = Self::Ready { driver, parts }; + (new_self, Ok(val)) + } + Err(err) => { + let new_self = Self::Uninit { parts }; + (new_self, Err(Error::Running(err))) + } + }, + Self::Uninit { parts } => { + match D::init().await { + Ok(mut driver) => { + // uses driver::measure again, make that return a SensorError + match driver.measure().await { + Ok(val) => { + let new_self = Self::Ready { driver, parts }; + (new_self, Ok(val)) + } + Err(err) => { + let new_self = Self::Uninit { parts }; + let err = Error::Running(err); + return (new_self, Err(err)); + } + } + } + Err(err) => { + let new_self = Self::Uninit { parts }; + let err = Error::Setup(err); + (new_self, Err(err)) + } + } + } + } + } +} + +enum Max44<'a> { + Ready { + driver: Max44009>, + i2c: &'a Mutex>, + }, + Uninit { + i2c: &'a Mutex>, + }, +} + +impl<'a> Max44<'a> { + pub fn new(i2c: &'a Mutex>) -> Self { + Self::Uninit { i2c } + } + + /// cancel safe, any cancelation will end us in the Uninit state + /// which is where we want to be after stopping in the middle of + /// a transaction + pub async fn try_measure(&mut self) -> Result { + let i2c = *match self { + Self::Ready { i2c, .. } => i2c, + Self::Uninit { i2c } => i2c, + }; + + let mut owned_self = Self::Uninit { i2c }; + core::mem::swap(&mut owned_self, self); + let (mut new_self, res) = owned_self.advance_state().await; + core::mem::swap(&mut new_self, self); + res + } + + async fn advance_state(mut self) -> (Self, Result) { + match self { + Self::Ready { + ref mut driver, + i2c, + // make a trait over driver that has a measure method + } => match driver.read_lux().await { + Ok(val) => return (self, Ok(val)), + Err(err) => { + let new_self = Self::Uninit { i2c }; + let err = Error::Running(SensorError::Max44(err)); + (new_self, Err(err)) + } + }, + Self::Uninit { i2c } => { + let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(i2c); + // wrap these two into something returning Ok or Err + // then make it a generic arg, maybe Driverfactory::init + let mut driver = Max44009::new(shared_i2c, SlaveAddr::default()); + match driver + .set_measurement_mode(max44009::MeasurementMode::Continuous) + .await + { + Ok(()) => { + // uses driver::measure again, make that return a SensorError + let val = match driver.read_lux().await { + Ok(val) => val, + Err(err) => { + let err = Error::Running(SensorError::Max44(err)); + return (self, Err(err)); + } + }; + let new_self = Self::Ready { driver, i2c }; + (new_self, Ok(val)) + } + Err(err) => { + let err = Error::Setup(SensorError::Max44(err)); + (self, Err(err)) + } + } + } + } + } +} + enum Bme680<'a> { Ready { bme: bosch_bme680::Bme680, Delay>, From 682f9ce3fad4992d1b5c4e08de915183937d39bf Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 9 Jun 2024 17:27:24 +0200 Subject: [PATCH 127/687] wraps i2c sensors providing re-init on error --- sensor-nodes/bed-sensors/.cargo/config.toml | 4 +- sensor-nodes/bed-sensors/src/main.rs | 40 +-- sensor-nodes/bed-sensors/src/sensors.rs | 40 +-- sensor-nodes/bed-sensors/src/sensors/fast.rs | 15 +- sensor-nodes/bed-sensors/src/sensors/retry.rs | 249 +++++++----------- sensor-nodes/bed-sensors/src/sensors/slow.rs | 63 ++--- 6 files changed, 140 insertions(+), 271 deletions(-) diff --git a/sensor-nodes/bed-sensors/.cargo/config.toml b/sensor-nodes/bed-sensors/.cargo/config.toml index e88f9bcf..590ccd28 100644 --- a/sensor-nodes/bed-sensors/.cargo/config.toml +++ b/sensor-nodes/bed-sensors/.cargo/config.toml @@ -9,8 +9,8 @@ linker = "flip-link" target = "thumbv7em-none-eabihf" [env] -DEFMT_LOG = "debug,sps30_async=trace,bosch_bme680=info" -EMBASSY_EXECUTOR_TASK_ARENA_SIZE="7000" +DEFMT_LOG = "debug,sps30_async=info,bosch_bme680=info" +EMBASSY_EXECUTOR_TASK_ARENA_SIZE="8000" # [unstable] # build-std = ["core"] diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index 21e0202d..11cb16a4 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -20,10 +20,9 @@ use embassy_stm32::wdg::IndependentWatchdog; use embassy_stm32::Config; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; -use embassy_sync::signal::Signal; -use embassy_time::{Delay, Instant, Timer}; +use embassy_time::{Delay, Timer}; use embedded_hal_bus::spi::ExclusiveDevice; -use futures::{pin_mut, FutureExt}; +use futures::pin_mut; use heapless::Vec; use static_cell::StaticCell; @@ -32,8 +31,8 @@ use {defmt_rtt as _, panic_probe as _}; mod channel; mod error_cache; mod network; -mod sensors; mod rng; +mod sensors; use crate::channel::Queues; embassy_stm32::bind_interrupts!(struct Irqs { @@ -54,21 +53,24 @@ unsafe fn USART6() { #[embassy_executor::task] async fn print_if_running_task() -> ! { - loop { - // let mut now = Instant::now(); - // let mut biggest = 0; - // for _ in 0..1000 { - // Timer::after_millis(1).await; - // let new_now = Instant::now(); - // let elapsed = (new_now - now).as_millis(); - // now = new_now; - // - // if elapsed > biggest { - // biggest = elapsed; - // } - // } - // defmt::info!("still running, largest delay was: {}ms", biggest); + // use embassy_time::Instant; + // loop { + // let mut now = Instant::now(); + // let mut biggest = 0; + // for _ in 0..1000 { + // Timer::after_millis(1).await; + // let new_now = Instant::now(); + // let elapsed = (new_now - now).as_millis(); + // now = new_now; + // + // if elapsed > biggest { + // biggest = elapsed; + // } + // } + // defmt::info!("still running, largest delay was: {}ms", biggest); + // } + loop { Timer::after_secs(1).await; defmt::info!("still running"); } @@ -175,7 +177,7 @@ async fn main(spawner: Spawner) { // lower_center: ExtiInput::new(p.PA15, p.EXTI15, Pull::Down), // lower_outer: ExtiInput::new(p.PB5, p.EXTI5, Pull::Down), // }; - */ + */ let mut spi_cfg = SpiConfig::default(); spi_cfg.frequency = Hertz(50_000_000); // up to 50m works diff --git a/sensor-nodes/bed-sensors/src/sensors.rs b/sensor-nodes/bed-sensors/src/sensors.rs index 9892b861..ae852d66 100644 --- a/sensor-nodes/bed-sensors/src/sensors.rs +++ b/sensor-nodes/bed-sensors/src/sensors.rs @@ -1,5 +1,5 @@ use defmt::info; -use embassy_embedded_hal::shared_bus::{self, I2cDeviceError}; +use embassy_embedded_hal::shared_bus::I2cDeviceError; use embassy_futures::join; use embassy_stm32::i2c::I2c; use embassy_stm32::mode::Async; @@ -7,13 +7,13 @@ use embassy_stm32::usart::Uart; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; use embassy_time::{with_timeout, Delay, Duration}; -use max44009::{Max44009, SlaveAddr}; use mhzx::MHZ; use protocol::large_bedroom::bed::Device; use sps30_async::Sps30; use crate::channel::Queues; use crate::error_cache::{Error, SensorError}; +use crate::sensors::retry::{Bme680Driver, Max44Driver, Sht31Driver}; pub mod fast; pub mod slow; @@ -45,39 +45,9 @@ pub async fn init_then_measure( usart_sps: Uart<'static, Async>, ) -> Result<(), Error> { info!("initializing sensors"); - let bme = with_timeout( - Duration::from_secs(2), - bosch_bme680::Bme680::new( - shared_bus::asynch::i2c::I2cDevice::new(&i2c), - bosch_bme680::DeviceAddress::Secondary, - Delay, - &bosch_bme680::Configuration::default(), - 20, - ), - ) - .await - .map_err(|_| Error::SetupTimedOut(Device::Bme680))? - .map_err(SensorError::Bme680) - .map_err(Error::Setup)?; - - defmt::info!("hi"); - let mut max44009 = Max44009::new( - shared_bus::asynch::i2c::I2cDevice::new(&i2c), - SlaveAddr::default(), - ); - with_timeout( - Duration::from_millis(250), - max44009.set_measurement_mode(max44009::MeasurementMode::Continuous), - ) - .await - .map_err(|_| Error::SetupTimedOut(Device::Max44))? - .map_err(SensorError::Max44) - .map_err(Error::Setup)?; - - let sht = sht31::SHT31::new(shared_bus::asynch::i2c::I2cDevice::new(&i2c), Delay) - .with_mode(sht31::mode::SingleShot) - .with_unit(sht31::TemperatureUnit::Celsius) - .with_accuracy(sht31::Accuracy::High); + let bme = Bme680Driver::new(&i2c); + let max44009 = Max44Driver::new(&i2c); + let sht = Sht31Driver::new(&i2c); let (tx, rx) = usart_mhz.split(); let mut usart_buf = [0u8; 9 * 10]; // 9 byte messages diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed-sensors/src/sensors/fast.rs index 4060e7b8..a38bda8f 100644 --- a/sensor-nodes/bed-sensors/src/sensors/fast.rs +++ b/sensor-nodes/bed-sensors/src/sensors/fast.rs @@ -2,14 +2,11 @@ use defmt::warn; use embassy_futures::yield_now; use embassy_stm32::exti::ExtiInput; use embassy_time::{Duration, Instant, Timer}; -use max44009::Max44009; - -use crate::channel::Queues; -use crate::error_cache::{Error, SensorError}; use protocol::large_bedroom::{bed::Button, bed::Reading}; -use super::concrete_types::ConcreteSharedI2c as I2c; +use crate::channel::Queues; +use super::retry::Max44Driver; fn sig_lux_diff(old: f32, new: f32) -> bool { let diff = old - new; @@ -17,7 +14,7 @@ fn sig_lux_diff(old: f32, new: f32) -> bool { diff > old / 20.0 || -diff > old / 20.0 } -async fn report_lux(mut max44: Max44009>, publish: &Queues) { +async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues) { let mut prev_lux = f32::MAX; let mut last_lux = Instant::now(); const MIN_INTERVAL: Duration = Duration::from_secs(1); @@ -25,11 +22,9 @@ async fn report_lux(mut max44: Max44009>, publish: &Queues) { // todo!("reinit devices after error"); loop { Timer::after_millis(50).await; - let lux = match max44.read_lux().await { + let lux = match max44.try_measure().await { Ok(lux) => lux, Err(err) if last_lux.elapsed() > MIN_INTERVAL => { - let err = SensorError::Max44(err); - let err = Error::Running(err); let _ignore = publish.queue_error(err); continue; } @@ -88,7 +83,7 @@ pub struct ButtonInputs { pub lower_outer: ExtiInput<'static>, } -pub async fn read(max44: Max44009>, /*inputs: ButtonInputs,*/ publish: &Queues) { +pub async fn read(max44: Max44Driver<'_>, /*inputs: ButtonInputs,*/ publish: &Queues) { // let watch_buttons_1 = join5( // watch_button(inputs.top_left, BedButton::TopLeft, publish), // watch_button(inputs.top_right, BedButton::TopRight, publish), diff --git a/sensor-nodes/bed-sensors/src/sensors/retry.rs b/sensor-nodes/bed-sensors/src/sensors/retry.rs index d782e948..626360f6 100644 --- a/sensor-nodes/bed-sensors/src/sensors/retry.rs +++ b/sensor-nodes/bed-sensors/src/sensors/retry.rs @@ -1,26 +1,105 @@ -use bosch_bme680::{BmeError, Configuration, DeviceAddress, MeasurementData}; -use embassy_embedded_hal::shared_bus::{self, I2cDeviceError}; +use bosch_bme680::Bme680; +use embassy_embedded_hal::shared_bus; use embassy_stm32::i2c::I2c; use embassy_stm32::mode::Async; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; -use embassy_time::Delay; +use embassy_time::{Delay, Timer}; use max44009::{Max44009, SlaveAddr}; +use sht31::mode::SingleShot; +use sht31::SHT31; -// use super::concrete_types::ConcreteRx as Rx; use super::concrete_types::ConcreteSharedI2c; -// use super::concrete_types::ConcreteTx as Tx; use crate::error_cache::{Error, SensorError}; -trait Driver: Sized { +impl<'a> Driver for Max44009> { + type Parts = &'a Mutex>; + type Measurement = f32; + + #[inline(always)] + async fn init(parts: Self::Parts) -> Result { + let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); + // wrap these two into something returning Ok or Err + // then make it a generic arg, maybe Driverfactory::init + let mut driver = Max44009::new(shared_i2c, SlaveAddr::default()); + driver + .set_measurement_mode(max44009::MeasurementMode::Continuous) + .await + .map_err(SensorError::Max44)?; + Ok(driver) + } + + #[inline(always)] + async fn measure(&mut self) -> Result { + self.read_lux().await.map_err(SensorError::Max44) + } +} + +pub type Max44Driver<'a> = ReInitOnErrorDriver>>; + +impl<'a> Driver for Bme680, Delay> { + type Parts = &'a Mutex>; + type Measurement = bosch_bme680::MeasurementData; + + #[inline(always)] + async fn init(parts: Self::Parts) -> Result { + let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); + Bme680::new( + shared_i2c, + bosch_bme680::DeviceAddress::Secondary, + Delay, + &bosch_bme680::Configuration::default(), + 21, + ) + .await + .map_err(SensorError::Bme680) + } + + #[inline(always)] + async fn measure(&mut self) -> Result { + self.measure().await.map_err(SensorError::Bme680) + } +} + +pub type Bme680Driver<'a> = ReInitOnErrorDriver, Delay>>; + +impl<'a> Driver for SHT31> { + type Parts = &'a Mutex>; + type Measurement = sht31::Reading; + + #[inline(always)] + async fn init(parts: Self::Parts) -> Result { + let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); + Ok(SHT31::new(shared_i2c, Delay) + .with_mode(SingleShot) + .with_unit(sht31::TemperatureUnit::Celsius) + .with_accuracy(sht31::Accuracy::High)) + } + + #[inline(always)] + async fn measure(&mut self) -> Result { + use sht31::mode::Sht31Measure; + use sht31::mode::Sht31Reader; + + Sht31Measure::measure(self) + .await + .map_err(SensorError::Sht31)?; + Timer::after_secs(1).await; + self.read().await.map_err(SensorError::Sht31) + } +} + +pub type Sht31Driver<'a> = ReInitOnErrorDriver>>; + +pub trait Driver: Sized { type Parts: Clone; type Measurement; - async fn init() -> Result; + async fn init(parts: Self::Parts) -> Result; async fn measure(&mut self) -> Result; } -enum ReInitOnErrorDriver +pub enum ReInitOnErrorDriver where D: Driver, { @@ -47,7 +126,8 @@ impl ReInitOnErrorDriver { res } - async fn advance_state(mut self) -> (Self, Result) { + #[inline(always)] + async fn advance_state(self) -> (Self, Result) { match self { Self::Ready { mut driver, @@ -64,7 +144,7 @@ impl ReInitOnErrorDriver { } }, Self::Uninit { parts } => { - match D::init().await { + match D::init(parts.clone()).await { Ok(mut driver) => { // uses driver::measure again, make that return a SensorError match driver.measure().await { @@ -89,152 +169,3 @@ impl ReInitOnErrorDriver { } } } - -enum Max44<'a> { - Ready { - driver: Max44009>, - i2c: &'a Mutex>, - }, - Uninit { - i2c: &'a Mutex>, - }, -} - -impl<'a> Max44<'a> { - pub fn new(i2c: &'a Mutex>) -> Self { - Self::Uninit { i2c } - } - - /// cancel safe, any cancelation will end us in the Uninit state - /// which is where we want to be after stopping in the middle of - /// a transaction - pub async fn try_measure(&mut self) -> Result { - let i2c = *match self { - Self::Ready { i2c, .. } => i2c, - Self::Uninit { i2c } => i2c, - }; - - let mut owned_self = Self::Uninit { i2c }; - core::mem::swap(&mut owned_self, self); - let (mut new_self, res) = owned_self.advance_state().await; - core::mem::swap(&mut new_self, self); - res - } - - async fn advance_state(mut self) -> (Self, Result) { - match self { - Self::Ready { - ref mut driver, - i2c, - // make a trait over driver that has a measure method - } => match driver.read_lux().await { - Ok(val) => return (self, Ok(val)), - Err(err) => { - let new_self = Self::Uninit { i2c }; - let err = Error::Running(SensorError::Max44(err)); - (new_self, Err(err)) - } - }, - Self::Uninit { i2c } => { - let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(i2c); - // wrap these two into something returning Ok or Err - // then make it a generic arg, maybe Driverfactory::init - let mut driver = Max44009::new(shared_i2c, SlaveAddr::default()); - match driver - .set_measurement_mode(max44009::MeasurementMode::Continuous) - .await - { - Ok(()) => { - // uses driver::measure again, make that return a SensorError - let val = match driver.read_lux().await { - Ok(val) => val, - Err(err) => { - let err = Error::Running(SensorError::Max44(err)); - return (self, Err(err)); - } - }; - let new_self = Self::Ready { driver, i2c }; - (new_self, Ok(val)) - } - Err(err) => { - let err = Error::Setup(SensorError::Max44(err)); - (self, Err(err)) - } - } - } - } - } -} - -enum Bme680<'a> { - Ready { - bme: bosch_bme680::Bme680, Delay>, - i2c: &'a Mutex>, - }, - Uninit { - i2c: &'a Mutex>, - }, -} - -impl<'a> Bme680<'a> { - pub fn new(i2c: &'a Mutex>) -> Self { - Self::Uninit { i2c } - } - - /// cancel safe, any cancelation will end us in the Uninit state - /// which is where we want to be after stopping in the middle of - /// a transaction - pub async fn try_measure(&mut self) -> Result { - let i2c = *match self { - Bme680::Ready { i2c, .. } => i2c, - Bme680::Uninit { i2c } => i2c, - }; - - let mut owned_self = Self::Uninit { i2c }; - core::mem::swap(&mut owned_self, self); - let (mut new_self, res) = owned_self.advance_state().await; - core::mem::swap(&mut new_self, self); - res - } - - async fn advance_state(mut self) -> (Self, Result) { - match self { - Bme680::Ready { ref mut bme, i2c } => match bme.measure().await { - Ok(val) => return (self, Ok(val)), - Err(err) => { - let new_self = Self::Uninit { i2c }; - let err = Error::Running(SensorError::Bme680(err)); - (new_self, Err(err)) - } - }, - Bme680::Uninit { i2c } => { - let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(i2c); - match bosch_bme680::Bme680::new( - shared_i2c, - DeviceAddress::Secondary, - Delay, - &Configuration::default(), - 21, - ) - .await - { - Ok(mut bme) => { - let val = match bme.measure().await { - Ok(val) => val, - Err(err) => { - let err = Error::Running(SensorError::Bme680(err)); - return (self, Err(err)); - } - }; - let new_self = Self::Ready { bme, i2c }; - (new_self, Ok(val)) - } - Err(err) => { - let err = Error::Setup(SensorError::Bme680(err)); - (self, Err(err)) - } - } - } - } - } -} diff --git a/sensor-nodes/bed-sensors/src/sensors/slow.rs b/sensor-nodes/bed-sensors/src/sensors/slow.rs index 85878457..b2834e14 100644 --- a/sensor-nodes/bed-sensors/src/sensors/slow.rs +++ b/sensor-nodes/bed-sensors/src/sensors/slow.rs @@ -1,13 +1,12 @@ use defmt::unwrap; use embassy_futures::join; -use embassy_time::{with_timeout, Delay, Duration, Timer}; +use embassy_time::{with_timeout, Delay, Duration}; +use embassy_time::{Instant, Timer}; use mhzx::MHZ; use protocol::large_bedroom::bed::{Device, Reading}; -use bosch_bme680::{Bme680, MeasurementData}; -use sht31::mode::{Sht31Measure, Sht31Reader, SingleShot}; -use sht31::SHT31; +use bosch_bme680::MeasurementData; use sps30_async as sps30; use sps30_async::Sps30; @@ -15,37 +14,30 @@ use crate::channel::Queues; use crate::error_cache::Error; use crate::error_cache::SensorError; -use super::{I2cError, UartError}; +use super::retry::{Bme680Driver, Sht31Driver}; +use super::UartError; const SPS30_UART_BUF_SIZE: usize = 100; const SPS30_DRIVER_BUF_SIZE: usize = 2 * SPS30_UART_BUF_SIZE; use super::concrete_types::ConcreteRx as Rx; -use super::concrete_types::ConcreteSharedI2c as I2c; use super::concrete_types::ConcreteTx as Tx; #[inline(always)] pub async fn read( - mut sht: SHT31>, - mut bme: Bme680, Delay>, + mut sht: Sht31Driver<'_>, + mut bme: Bme680Driver<'_>, mut mhz: MHZ, Rx<'_>>, mut sps: Sps30, Rx<'_>, Delay>, publish: &'_ Queues, ) { - // sht works in two steps - // - send measure command before sleep - // - then read - if let Err(err) = sht.measure().await { - let err = SensorError::Sht31(err); - let err = Error::Running(err); - publish.queue_error(err) - } - Timer::after_secs(1).await; - + let mut next_sample = Instant::now(); loop { - defmt::info!("this is where we break"); - let sht_read = with_timeout(Duration::from_millis(100), sht.read()); - let bme_measure = bme.measure(); // can not hang + Timer::at(next_sample).await; + next_sample = Instant::now() + Duration::from_secs(1); + + let sht_read = with_timeout(Duration::from_millis(100), sht.try_measure()); + let bme_measure = bme.try_measure(); // can not hang let mhz_measure = with_timeout(Duration::from_millis(100), mhz.read_co2()); let sps_measure = with_timeout(Duration::from_millis(100), sps.read_measurement()); let (bme_res, sht_res, mhz_res, sps_res) = @@ -55,16 +47,6 @@ pub async fn read( publish_sht_result(sht_res, publish); publish_mhz_result(mhz_res, publish); publish_sps_result(sps_res, publish); - - // sht works in two steps - // - send measure command before sleep - // - then read - if let Err(err) = sht.measure().await { - let err = SensorError::Sht31(err); - let err = Error::Running(err); - publish.queue_error(err) - } - Timer::after_secs(1).await; } } @@ -138,7 +120,7 @@ fn publish_mhz_result( } fn publish_sht_result( - sht_res: Result, embassy_time::TimeoutError>, + sht_res: Result, embassy_time::TimeoutError>, publish: &Queues, ) { match sht_res { @@ -149,11 +131,7 @@ fn publish_sht_result( publish.send_p0(Reading::Temperature(temperature)); publish.send_p0(Reading::Humidity(humidity)); } - Ok(Err(err)) => { - let err = SensorError::Sht31(err); - let err = Error::Running(err); - publish.queue_error(err) - } + Ok(Err(err)) => publish.queue_error(err), Err(_timeout) => { let err = Error::Timeout(Device::Sht31); publish.queue_error(err) @@ -161,10 +139,7 @@ fn publish_sht_result( } } -fn publish_bme_result( - bme_res: Result>, - publish: &Queues, -) { +fn publish_bme_result(bme_res: Result, publish: &Queues) { match bme_res { Ok(MeasurementData { pressure, @@ -175,10 +150,6 @@ fn publish_bme_result( publish.send_p0(Reading::GassResistance(gas_resistance)); publish.send_p0(Reading::Pressure(pressure)); } - Err(err) => { - let err = SensorError::Bme680(err); - let err = Error::Running(err); - publish.queue_error(err) - } + Err(err) => publish.queue_error(err), } } From bbbf5c7d4c0d2a38f25ca468110a16ca93fcee8e Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 10 Jun 2024 15:28:46 +0200 Subject: [PATCH 128/687] updates channel/network to encode&send errors too --- crates/protocol/src/large_bedroom.rs | 2 +- crates/protocol/src/lib.rs | 53 +++++++++++++++++++++++-- sensor-nodes/bed-sensors/src/channel.rs | 20 +++++++++- sensor-nodes/bed-sensors/src/network.rs | 53 +++++++++++++++---------- 4 files changed, 102 insertions(+), 26 deletions(-) diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index ba0a3371..96bcd1ce 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -50,7 +50,7 @@ impl Actuator { } pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { - postcard::from_bytes_cobs(bytes.as_mut()).map_err(crate::DecodeError) + postcard::from_bytes_cobs(bytes.as_mut()).map_err(crate::DecodeError::CorruptEncoding) } pub fn version(&self) -> u8 { diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 6d68abaa..424a8671 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -191,10 +191,36 @@ pub struct ErrorReport { pub version: u8, } +pub const SENSOR_MSG: u8 = 0; +pub const ERROR_REPORT: u8 = 1; + +pub fn decode( + mut bytes: impl AsMut<[u8]>, +) -> Result, ErrorReport>, DecodeError> { + let bytes = bytes.as_mut(); + let msg_type = bytes[0]; + let bytes = &mut bytes[1..]; + + if msg_type == SENSOR_MSG { + Ok(Ok(SensorMessage::::decode(&mut bytes[1..])?)) + } else if msg_type == ERROR_REPORT { + Ok(Err(ErrorReport::decode(&mut bytes[1..])?)) + } else { + Err(DecodeError::IncorrectMsgType(msg_type)) + } +} + #[derive(Debug, Clone)] #[cfg_attr(feature = "thiserror", derive(thiserror::Error))] -#[cfg_attr(feature = "thiserror", error("Could not decode SensorMessage: {0}"))] -pub struct DecodeError(pub postcard::Error); +pub enum DecodeError { + #[cfg_attr(feature = "thiserror", error("Could not decode SensorMessage: {0}"))] + CorruptEncoding(postcard::Error), + #[cfg_attr( + feature = "thiserror", + error("Got an unknown message type, expected zero or one got: {}") + )] + IncorrectMsgType(u8), +} impl SensorMessage { /// the 2x is the max overhead from COBS encoding the encoded data @@ -225,7 +251,7 @@ impl SensorMessage { } pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { - postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeError) + postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeError::CorruptEncoding) } pub fn version(&self) -> u8 { @@ -233,6 +259,27 @@ impl SensorMessage { } } +impl ErrorReport { + /// the 2x is the max overhead from COBS encoding the encoded data + /// +2 is for the version + /// +4 covers the length of the heapless list + pub const ENCODED_SIZE: usize = 2 * (Error::POSTCARD_MAX_SIZE + 2); + + pub fn new(error: Error) -> Self { + Self { error, version: 0 } + } + + /// Buffer should be at least Self::ENCODED_SIZE long. The returned slice contains + /// the serialized data. It can be shorter then the input buffer. + pub fn encode_slice<'a>(&self, buf: &'a mut [u8]) -> &'a mut [u8] { + postcard::to_slice_cobs(self, buf).expect("Encoding should not fail") + } + + pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { + postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeError::CorruptEncoding) + } +} + pub type ErrorString = heapless::String<200>; // thiserror does not work on nostd. That will change when this lands: // https://github.com/rust-lang/rust/issues/103765 diff --git a/sensor-nodes/bed-sensors/src/channel.rs b/sensor-nodes/bed-sensors/src/channel.rs index b465f155..88f9b2c7 100644 --- a/sensor-nodes/bed-sensors/src/channel.rs +++ b/sensor-nodes/bed-sensors/src/channel.rs @@ -1,3 +1,4 @@ +use embassy_futures::select::{self, Either}; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::channel::Channel; use embassy_sync::mutex::Mutex; @@ -15,6 +16,11 @@ pub struct Queues { recent_is_since: Instant, } +pub enum QueueItem { + Reading(PriorityValue), + Error(error_cache::Error), +} + impl Queues { pub fn new() -> Self { Self { @@ -30,7 +36,19 @@ impl Queues { self.recent_errors.lock().await.clear(); } - pub async fn receive(&self) -> PriorityValue { + pub async fn receive(&self) -> QueueItem { + if let Ok(val) = self.sensor_queue.try_receive() { + return QueueItem::Reading(val); + } + + let race = select::select(self.sensor_queue.receive(), self.error_queue.receive()); + match race.await { + Either::First(reading) => QueueItem::Reading(reading), + Either::Second(error) => QueueItem::Error(error), + } + } + + pub async fn receive_reading(&self) -> PriorityValue { self.sensor_queue.receive().await } diff --git a/sensor-nodes/bed-sensors/src/network.rs b/sensor-nodes/bed-sensors/src/network.rs index a6e1f5a0..885ce02b 100644 --- a/sensor-nodes/bed-sensors/src/network.rs +++ b/sensor-nodes/bed-sensors/src/network.rs @@ -4,23 +4,22 @@ use embassy_net::tcp::TcpSocket; use embassy_net::{Ipv4Address, Stack}; use embassy_time::{with_timeout, Duration, Instant, Timer}; use embedded_io_async::Write; -use protocol::SensorMessage; +use protocol::{ErrorReport, SensorMessage}; -use crate::channel::Queues; +use crate::channel::{QueueItem, PriorityValue, Queues}; -type Msg = SensorMessage<4>; +type Msg = SensorMessage<10>; -async fn get_messages(publish: &Queues, msg: &mut Msg) { - msg.values.clear(); - let next = publish.receive().await; - let low_priority = next.low_priority(); - unwrap!(msg.values.push(next.value)); +async fn collect_pending(publish: &Queues, reading: PriorityValue) -> Msg { + let mut msg = Msg::new(); + let low_priority = reading.low_priority(); + unwrap!(msg.values.push(reading.value)); if low_priority { let deadline = Instant::now() + Duration::from_millis(200); while msg.space_left() { let until = deadline.saturating_duration_since(Instant::now()); - match with_timeout(until, publish.receive()).await { + match with_timeout(until, publish.receive_reading()).await { Ok(new) if new.low_priority() => { unwrap!(msg.values.push(new.value)); } @@ -39,18 +38,32 @@ async fn get_messages(publish: &Queues, msg: &mut Msg) { unwrap!(msg.values.push(next.value)); } } + msg } -pub async fn send_published( - stack: &Stack, - publish: &Queues, -) { - let mut rx_buffer = [0; 1024]; - let mut tx_buffer = [0; 1024]; - // let mut tx_buffer = [0; Msg::ENCODED_SIZE * 2]; +async fn get_messages<'a>(publish: &Queues, buf: &'a mut [u8]) -> &'a [u8] { + let next = publish.receive().await; + match next { + QueueItem::Reading(reading) => { + let msg = collect_pending(publish, reading).await; + msg.encode_slice(buf) + } + QueueItem::Error(error) => { + let error = protocol::large_bedroom::Error::Bed(error.into()); + let error = protocol::Error::LargeBedroom(error); + ErrorReport::new(error).encode_slice(buf) + } + } +} - let mut msg = Msg::new(); - let mut encoded_msg_buffer = [0; Msg::ENCODED_SIZE]; +const fn max(a: usize, b: usize) -> usize { + [a, b][(a < b) as usize] +} + +pub async fn send_published(stack: &Stack, publish: &Queues) { + let mut rx_buffer = [0; 1024]; + let mut tx_buffer = [0; max(Msg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE) * 2]; + let mut encoded_msg_buffer = [0; max(Msg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE)]; let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); // socket.set_timeout(Some(Duration::from_secs(5))); @@ -72,9 +85,7 @@ pub async fn send_published( } } - get_messages(publish, &mut msg).await; - let to_send = msg.encode_slice(&mut encoded_msg_buffer); - + let to_send = get_messages(publish, &mut encoded_msg_buffer).await; if let Err(e) = socket.write_all(to_send).await { warn!("write error: {:?}", e); } From a818c95542a086da3ffee6f5f5370fe6e4219a0f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 10 Jun 2024 15:29:07 +0200 Subject: [PATCH 129/687] adds svd file (usefull for debugger) --- sensor-nodes/bed-sensors/stm32f401.svd | 35196 +++++++++++++++++++++++ 1 file changed, 35196 insertions(+) create mode 100644 sensor-nodes/bed-sensors/stm32f401.svd diff --git a/sensor-nodes/bed-sensors/stm32f401.svd b/sensor-nodes/bed-sensors/stm32f401.svd new file mode 100644 index 00000000..b9353d01 --- /dev/null +++ b/sensor-nodes/bed-sensors/stm32f401.svd @@ -0,0 +1,35196 @@ + + + STM32F401 + 1.1 + STM32F401 + + CM4 + r1p0 + little + false + false + 4 + false + + 8 + 32 + 0x20 + 0x00000000 + 0xFFFFFFFF + + + ADC_Common + ADC common registers + ADC_Common + 0x40012300 + + 0x0 + 0x9 + registers + + + FPU + FPU interrupt + 81 + + + + CCR + CCR + ADC common control register + 0x4 + 0x20 + read-write + 0x00000000 + + + TSVREFE + Temperature sensor and VREFINT + enable + 23 + 1 + + TSVREFE + read-write + + Disabled + Temperature sensor and V_REFINT channel disabled + 0 + + + Enabled + Temperature sensor and V_REFINT channel enabled + 1 + + + + + VBATE + VBAT enable + 22 + 1 + + VBATE + read-write + + Disabled + V_BAT channel disabled + 0 + + + Enabled + V_BAT channel enabled + 1 + + + + + ADCPRE + ADC prescaler + 16 + 2 + + ADCPRE + read-write + + Div2 + PCLK2 divided by 2 + 0 + + + Div4 + PCLK2 divided by 4 + 1 + + + Div6 + PCLK2 divided by 6 + 2 + + + Div8 + PCLK2 divided by 8 + 3 + + + + + + + + + ADC1 + Analog-to-digital converter + ADC + 0x40012000 + + 0x0 + 0x51 + registers + + + ADC + ADC1 global interrupt + 18 + + + + SR + SR + status register + 0x0 + 0x20 + read-write + 0x00000000 + + + OVR + Overrun + 5 + 1 + zeroToClear + + OVRR + read + + NoOverrun + No overrun occurred + 0 + + + Overrun + Overrun occurred + 1 + + + + OVRW + write + + Clear + Clear flag + 0 + + + + + STRT + Regular channel start flag + 4 + 1 + zeroToClear + + STRTR + read + + NotStarted + No regular channel conversion started + 0 + + + Started + Regular channel conversion has started + 1 + + + + STRTW + write + + Clear + Clear flag + 0 + + + + + JSTRT + Injected channel start + flag + 3 + 1 + zeroToClear + + JSTRTR + read + + NotStarted + No injected channel conversion started + 0 + + + Started + Injected channel conversion has started + 1 + + + + JSTRTW + write + + Clear + Clear flag + 0 + + + + + JEOC + Injected channel end of + conversion + 2 + 1 + zeroToClear + + JEOCR + read + + NotComplete + Conversion is not complete + 0 + + + Complete + Conversion complete + 1 + + + + JEOCW + write + + Clear + Clear flag + 0 + + + + + EOC + Regular channel end of + conversion + 1 + 1 + zeroToClear + + EOCR + read + + NotComplete + Conversion is not complete + 0 + + + Complete + Conversion complete + 1 + + + + EOCW + write + + Clear + Clear flag + 0 + + + + + AWD + Analog watchdog flag + 0 + 1 + zeroToClear + + AWDR + read + + NoEvent + No analog watchdog event occurred + 0 + + + Event + Analog watchdog event occurred + 1 + + + + AWDW + write + + Clear + Clear flag + 0 + + + + + + + CR1 + CR1 + control register 1 + 0x4 + 0x20 + read-write + 0x00000000 + + + OVRIE + Overrun interrupt enable + 26 + 1 + + OVRIE + read-write + + Disabled + Overrun interrupt disabled + 0 + + + Enabled + Overrun interrupt enabled + 1 + + + + + RES + Resolution + 24 + 2 + + RES + read-write + + TwelveBit + 12-bit (15 ADCCLK cycles) + 0 + + + TenBit + 10-bit (13 ADCCLK cycles) + 1 + + + EightBit + 8-bit (11 ADCCLK cycles) + 2 + + + SixBit + 6-bit (9 ADCCLK cycles) + 3 + + + + + AWDEN + Analog watchdog enable on regular + channels + 23 + 1 + + AWDEN + read-write + + Disabled + Analog watchdog disabled on regular channels + 0 + + + Enabled + Analog watchdog enabled on regular channels + 1 + + + + + JAWDEN + Analog watchdog enable on injected + channels + 22 + 1 + + JAWDEN + read-write + + Disabled + Analog watchdog disabled on injected channels + 0 + + + Enabled + Analog watchdog enabled on injected channels + 1 + + + + + DISCNUM + Discontinuous mode channel + count + 13 + 3 + + + 0 + 7 + + + + + JDISCEN + Discontinuous mode on injected + channels + 12 + 1 + + JDISCEN + read-write + + Disabled + Discontinuous mode on injected channels disabled + 0 + + + Enabled + Discontinuous mode on injected channels enabled + 1 + + + + + DISCEN + Discontinuous mode on regular + channels + 11 + 1 + + DISCEN + read-write + + Disabled + Discontinuous mode on regular channels disabled + 0 + + + Enabled + Discontinuous mode on regular channels enabled + 1 + + + + + JAUTO + Automatic injected group + conversion + 10 + 1 + + JAUTO + read-write + + Disabled + Automatic injected group conversion disabled + 0 + + + Enabled + Automatic injected group conversion enabled + 1 + + + + + AWDSGL + Enable the watchdog on a single channel + in scan mode + 9 + 1 + + AWDSGL + read-write + + AllChannels + Analog watchdog enabled on all channels + 0 + + + SingleChannel + Analog watchdog enabled on a single channel + 1 + + + + + SCAN + Scan mode + 8 + 1 + + SCAN + read-write + + Disabled + Scan mode disabled + 0 + + + Enabled + Scan mode enabled + 1 + + + + + JEOCIE + Interrupt enable for injected + channels + 7 + 1 + + JEOCIE + read-write + + Disabled + JEOC interrupt disabled + 0 + + + Enabled + JEOC interrupt enabled + 1 + + + + + AWDIE + Analog watchdog interrupt + enable + 6 + 1 + + AWDIE + read-write + + Disabled + Analogue watchdog interrupt disabled + 0 + + + Enabled + Analogue watchdog interrupt enabled + 1 + + + + + EOCIE + Interrupt enable for EOC + 5 + 1 + + EOCIE + read-write + + Disabled + EOC interrupt disabled + 0 + + + Enabled + EOC interrupt enabled + 1 + + + + + AWDCH + Analog watchdog channel select + bits + 0 + 5 + + + 0 + 18 + + + + + + + CR2 + CR2 + control register 2 + 0x8 + 0x20 + read-write + 0x00000000 + + + SWSTART + Start conversion of regular + channels + 30 + 1 + + SWSTARTW + write + + Start + Starts conversion of regular channels + 1 + + + + + EXTEN + External trigger enable for regular + channels + 28 + 2 + + EXTEN + read-write + + Disabled + Trigger detection disabled + 0 + + + RisingEdge + Trigger detection on the rising edge + 1 + + + FallingEdge + Trigger detection on the falling edge + 2 + + + BothEdges + Trigger detection on both the rising and falling edges + 3 + + + + + EXTSEL + External event select for regular + group + 24 + 4 + + EXTSEL + read-write + + TIM1CC1 + Timer 1 CC1 event + 0 + + + TIM1CC2 + Timer 1 CC2 event + 1 + + + TIM1CC3 + Timer 1 CC3 event + 2 + + + TIM2CC2 + Timer 2 CC2 event + 3 + + + TIM2CC3 + Timer 2 CC3 event + 4 + + + TIM2CC4 + Timer 2 CC4 event + 5 + + + TIM2TRGO + Timer 2 TRGO event + 6 + + + TIM3CC1 + Timer 3 CC1 event + 7 + + + TIM3TRGO + Timer 3 TRGO event + 8 + + + TIM4CC4 + Timer 4 CC4 event + 9 + + + TIM5CC1 + Timer 5 CC1 event + 10 + + + TIM5CC2 + Timer 5 CC2 event + 11 + + + TIM5CC3 + Timer 5 CC3 event + 12 + + + EXTI11 + EXTI line 11 + 15 + + + + + JSWSTART + Start conversion of injected + channels + 22 + 1 + + JSWSTARTW + write + + Start + Starts conversion of injected channels + 1 + + + + + JEXTEN + External trigger enable for injected + channels + 20 + 2 + + JEXTEN + read-write + + Disabled + Trigger detection disabled + 0 + + + RisingEdge + Trigger detection on the rising edge + 1 + + + FallingEdge + Trigger detection on the falling edge + 2 + + + BothEdges + Trigger detection on both the rising and falling edges + 3 + + + + + JEXTSEL + External event select for injected + group + 16 + 4 + + JEXTSEL + read-write + + TIM1CC4 + Timer 1 CC4 event + 0 + + + TIM1TRGO + Timer 1 TRGO event + 1 + + + TIM2CC1 + Timer 2 CC1 event + 2 + + + TIM2TRGO + Timer 2 TRGO event + 3 + + + TIM3CC2 + Timer 3 CC2 event + 4 + + + TIM3CC4 + Timer 3 CC4 event + 5 + + + TIM4CC1 + Timer 4 CC1 event + 6 + + + TIM4CC2 + Timer 4 CC2 event + 7 + + + TIM4CC3 + Timer 4 CC3 event + 8 + + + TIM4TRGO + Timer 4 TRGO event + 9 + + + TIM5CC4 + Timer 5 CC4 event + 10 + + + TIM5TRGO + Timer 5 TRGO event + 11 + + + EXTI15 + EXTI line 15 + 15 + + + + + ALIGN + Data alignment + 11 + 1 + + ALIGN + read-write + + Right + Right alignment + 0 + + + Left + Left alignment + 1 + + + + + EOCS + End of conversion + selection + 10 + 1 + + EOCS + read-write + + EachSequence + The EOC bit is set at the end of each sequence of regular conversions + 0 + + + EachConversion + The EOC bit is set at the end of each regular conversion + 1 + + + + + DDS + DMA disable selection (for single ADC + mode) + 9 + 1 + + DDS + read-write + + Single + No new DMA request is issued after the last transfer + 0 + + + Continuous + DMA requests are issued as long as data are converted and DMA=1 + 1 + + + + + DMA + Direct memory access mode (for single + ADC mode) + 8 + 1 + + DMA + read-write + + Disabled + DMA mode disabled + 0 + + + Enabled + DMA mode enabled + 1 + + + + + CONT + Continuous conversion + 1 + 1 + + CONT + read-write + + Single + Single conversion mode + 0 + + + Continuous + Continuous conversion mode + 1 + + + + + ADON + A/D Converter ON / OFF + 0 + 1 + + ADON + read-write + + Disabled + Disable ADC conversion and go to power down mode + 0 + + + Enabled + Enable ADC + 1 + + + + + + + SMPR1 + SMPR1 + sample time register 1 + 0xC + 0x20 + read-write + 0x00000000 + + + SMP18 + Channel 18 sampling time selection + 24 + 3 + + + + SMP17 + Channel 17 sampling time selection + 21 + 3 + + + + SMP16 + Channel 16 sampling time selection + 18 + 3 + + + + SMP15 + Channel 15 sampling time selection + 15 + 3 + + + + SMP14 + Channel 14 sampling time selection + 12 + 3 + + + + SMP13 + Channel 13 sampling time selection + 9 + 3 + + + + SMP12 + Channel 12 sampling time selection + 6 + 3 + + + + SMP11 + Channel 11 sampling time selection + 3 + 3 + + + + SMP10 + Channel 10 sampling time selection + 0 + 3 + + SMP10 + read-write + + Cycles3 + 3 cycles + 0 + + + Cycles15 + 15 cycles + 1 + + + Cycles28 + 28 cycles + 2 + + + Cycles56 + 56 cycles + 3 + + + Cycles84 + 84 cycles + 4 + + + Cycles112 + 112 cycles + 5 + + + Cycles144 + 144 cycles + 6 + + + Cycles480 + 480 cycles + 7 + + + + + + + SMPR2 + SMPR2 + sample time register 2 + 0x10 + 0x20 + read-write + 0x00000000 + + + SMP9 + Channel 9 sampling time selection + 27 + 3 + + + + SMP8 + Channel 8 sampling time selection + 24 + 3 + + + + SMP7 + Channel 7 sampling time selection + 21 + 3 + + + + SMP6 + Channel 6 sampling time selection + 18 + 3 + + + + SMP5 + Channel 5 sampling time selection + 15 + 3 + + + + SMP4 + Channel 4 sampling time selection + 12 + 3 + + + + SMP3 + Channel 3 sampling time selection + 9 + 3 + + + + SMP2 + Channel 2 sampling time selection + 6 + 3 + + + + SMP1 + Channel 1 sampling time selection + 3 + 3 + + + + SMP0 + Channel 0 sampling time selection + 0 + 3 + + SMP0 + read-write + + Cycles3 + 3 cycles + 0 + + + Cycles15 + 15 cycles + 1 + + + Cycles28 + 28 cycles + 2 + + + Cycles56 + 56 cycles + 3 + + + Cycles84 + 84 cycles + 4 + + + Cycles112 + 112 cycles + 5 + + + Cycles144 + 144 cycles + 6 + + + Cycles480 + 480 cycles + 7 + + + + + + + 4 + 0x4 + 1-4 + JOFR%s + JOFR1 + injected channel data offset register + x + 0x14 + 0x20 + read-write + 0x00000000 + + + JOFFSET + Data offset for injected channel + x + 0 + 12 + + + 0 + 4095 + + + + + + + HTR + HTR + watchdog higher threshold + register + 0x24 + 0x20 + read-write + 0x00000FFF + + + HT + Analog watchdog higher + threshold + 0 + 12 + + + 0 + 4095 + + + + + + + LTR + LTR + watchdog lower threshold + register + 0x28 + 0x20 + read-write + 0x00000000 + + + LT + Analog watchdog lower + threshold + 0 + 12 + + + 0 + 4095 + + + + + + + SQR1 + SQR1 + regular sequence register 1 + 0x2C + 0x20 + read-write + 0x00000000 + + + L + Regular channel sequence + length + 20 + 4 + + + 0 + 15 + + + + + SQ16 + 16th conversion in regular + sequence + 15 + 5 + + + 0 + 18 + + + + + SQ15 + 15th conversion in regular + sequence + 10 + 5 + + + 0 + 18 + + + + + SQ14 + 14th conversion in regular + sequence + 5 + 5 + + + 0 + 18 + + + + + SQ13 + 13th conversion in regular + sequence + 0 + 5 + + + 0 + 18 + + + + + + + SQR2 + SQR2 + regular sequence register 2 + 0x30 + 0x20 + read-write + 0x00000000 + + + SQ12 + 12th conversion in regular + sequence + 25 + 5 + + + 0 + 18 + + + + + SQ11 + 11th conversion in regular + sequence + 20 + 5 + + + 0 + 18 + + + + + SQ10 + 10th conversion in regular + sequence + 15 + 5 + + + 0 + 18 + + + + + SQ9 + 9th conversion in regular + sequence + 10 + 5 + + + 0 + 18 + + + + + SQ8 + 8th conversion in regular + sequence + 5 + 5 + + + 0 + 18 + + + + + SQ7 + 7th conversion in regular + sequence + 0 + 5 + + + 0 + 18 + + + + + + + SQR3 + SQR3 + regular sequence register 3 + 0x34 + 0x20 + read-write + 0x00000000 + + + SQ6 + 6th conversion in regular + sequence + 25 + 5 + + + 0 + 18 + + + + + SQ5 + 5th conversion in regular + sequence + 20 + 5 + + + 0 + 18 + + + + + SQ4 + 4th conversion in regular + sequence + 15 + 5 + + + 0 + 18 + + + + + SQ3 + 3rd conversion in regular + sequence + 10 + 5 + + + 0 + 18 + + + + + SQ2 + 2nd conversion in regular + sequence + 5 + 5 + + + 0 + 18 + + + + + SQ1 + 1st conversion in regular + sequence + 0 + 5 + + + 0 + 18 + + + + + + + JSQR + JSQR + injected sequence register + 0x38 + 0x20 + read-write + 0x00000000 + + + JL + Injected sequence length + 20 + 2 + + + 0 + 3 + + + + + JSQ4 + 4th conversion in injected + sequence + 15 + 5 + + + 0 + 18 + + + + + JSQ3 + 3rd conversion in injected + sequence + 10 + 5 + + + 0 + 18 + + + + + JSQ2 + 2nd conversion in injected + sequence + 5 + 5 + + + 0 + 18 + + + + + JSQ1 + 1st conversion in injected + sequence + 0 + 5 + + + 0 + 18 + + + + + + + 4 + 0x4 + 1-4 + JDR%s + JDR1 + injected data register x + 0x3C + 0x20 + read-only + 0x00000000 + + + JDATA + Injected data + 0 + 16 + + + + + DR + DR + regular data register + 0x4C + 0x20 + read-only + 0x00000000 + + + DATA + Regular data + 0 + 16 + + + + + + + CRC + Cryptographic processor + CRC + 0x40023000 + + 0x0 + 0x400 + registers + + + + DR + DR + Data register + 0x0 + 0x20 + read-write + 0xFFFFFFFF + + + DR + Data Register + 0 + 32 + + + 0 + 4294967295 + + + + + + + IDR + IDR + Independent Data register + 0x4 + 0x20 + read-write + 0x00000000 + + + IDR + Independent Data register + 0 + 8 + + + 0 + 255 + + + + + + + CR + CR + Control register + 0x8 + 0x20 + write-only + 0x00000000 + + + RESET + Control regidter + 0 + 1 + + RESETW + write + + Reset + Resets the CRC calculation unit and sets the data register to 0xFFFF FFFF + 1 + + + + + + + + + DBGMCU + Debug support + DBG + 0xE0042000 + + 0x0 + 0x400 + registers + + + + IDCODE + IDCODE + IDCODE + 0x0 + 0x20 + read-only + 0x10006411 + + + DEV_ID + DEV_ID + 0 + 12 + + + REV_ID + REV_ID + 16 + 16 + + + + + CR + CR + Control Register + 0x4 + 0x20 + read-write + 0x00000000 + + + DBG_SLEEP + DBG_SLEEP + 0 + 1 + + + DBG_STOP + DBG_STOP + 1 + 1 + + + DBG_STANDBY + DBG_STANDBY + 2 + 1 + + + TRACE_IOEN + TRACE_IOEN + 5 + 1 + + + TRACE_MODE + TRACE_MODE + 6 + 2 + + + + + APB1_FZ + APB1_FZ + Debug MCU APB1 Freeze registe + 0x8 + 0x20 + read-write + 0x00000000 + + + DBG_TIM2_STOP + DBG_TIM2_STOP + 0 + 1 + + + DBG_TIM3_STOP + DBG_TIM3 _STOP + 1 + 1 + + + DBG_TIM4_STOP + DBG_TIM4_STOP + 2 + 1 + + + DBG_TIM5_STOP + DBG_TIM5_STOP + 3 + 1 + + + DBG_RTC_Stop + RTC stopped when Core is + halted + 10 + 1 + + + DBG_WWDG_STOP + DBG_WWDG_STOP + 11 + 1 + + + DBG_IWDG_STOP + DBG_IWDEG_STOP + 12 + 1 + + + DBG_I2C1_SMBUS_TIMEOUT + DBG_J2C1_SMBUS_TIMEOUT + 21 + 1 + + + DBG_I2C2_SMBUS_TIMEOUT + DBG_J2C2_SMBUS_TIMEOUT + 22 + 1 + + + DBG_I2C3SMBUS_TIMEOUT + DBG_J2C3SMBUS_TIMEOUT + 23 + 1 + + + + + APB2_FZ + APB2_FZ + Debug MCU APB2 Freeze registe + 0xC + 0x20 + read-write + 0x00000000 + + + DBG_TIM1_STOP + TIM1 counter stopped when core is + halted + 0 + 1 + + + DBG_TIM9_STOP + TIM9 counter stopped when core is + halted + 16 + 1 + + + DBG_TIM10_STOP + TIM10 counter stopped when core is + halted + 17 + 1 + + + DBG_TIM11_STOP + TIM11 counter stopped when core is + halted + 18 + 1 + + + + + + + EXTI + External interrupt/event + controller + EXTI + 0x40013C00 + + 0x0 + 0x400 + registers + + + TAMP_STAMP + Tamper and TimeStamp interrupts through the + EXTI line + 2 + + + EXTI0 + EXTI Line0 interrupt + 6 + + + EXTI1 + EXTI Line1 interrupt + 7 + + + EXTI2 + EXTI Line2 interrupt + 8 + + + EXTI3 + EXTI Line3 interrupt + 9 + + + EXTI4 + EXTI Line4 interrupt + 10 + + + EXTI9_5 + EXTI Line[9:5] interrupts + 23 + + + EXTI15_10 + EXTI Line[15:10] interrupts + 40 + + + + IMR + IMR + Interrupt mask register + (EXTI_IMR) + 0x0 + 0x20 + read-write + 0x00000000 + + + MR0 + Interrupt Mask on line 0 + 0 + 1 + + MR0 + read-write + + Masked + Interrupt request line is masked + 0 + + + Unmasked + Interrupt request line is unmasked + 1 + + + + + MR1 + Interrupt Mask on line 1 + 1 + 1 + + + + MR2 + Interrupt Mask on line 2 + 2 + 1 + + + + MR3 + Interrupt Mask on line 3 + 3 + 1 + + + + MR4 + Interrupt Mask on line 4 + 4 + 1 + + + + MR5 + Interrupt Mask on line 5 + 5 + 1 + + + + MR6 + Interrupt Mask on line 6 + 6 + 1 + + + + MR7 + Interrupt Mask on line 7 + 7 + 1 + + + + MR8 + Interrupt Mask on line 8 + 8 + 1 + + + + MR9 + Interrupt Mask on line 9 + 9 + 1 + + + + MR10 + Interrupt Mask on line 10 + 10 + 1 + + + + MR11 + Interrupt Mask on line 11 + 11 + 1 + + + + MR12 + Interrupt Mask on line 12 + 12 + 1 + + + + MR13 + Interrupt Mask on line 13 + 13 + 1 + + + + MR14 + Interrupt Mask on line 14 + 14 + 1 + + + + MR15 + Interrupt Mask on line 15 + 15 + 1 + + + + MR16 + Interrupt Mask on line 16 + 16 + 1 + + + + MR17 + Interrupt Mask on line 17 + 17 + 1 + + + + MR18 + Interrupt Mask on line 18 + 18 + 1 + + + + MR19 + Interrupt Mask on line 19 + 19 + 1 + + + + MR20 + Interrupt Mask on line 20 + 20 + 1 + + + + MR21 + Interrupt Mask on line 21 + 21 + 1 + + + + MR22 + Interrupt Mask on line 22 + 22 + 1 + + + + + + EMR + EMR + Event mask register (EXTI_EMR) + 0x4 + 0x20 + read-write + 0x00000000 + + + MR0 + Event Mask on line 0 + 0 + 1 + + MR0 + read-write + + Masked + Interrupt request line is masked + 0 + + + Unmasked + Interrupt request line is unmasked + 1 + + + + + MR1 + Event Mask on line 1 + 1 + 1 + + + + MR2 + Event Mask on line 2 + 2 + 1 + + + + MR3 + Event Mask on line 3 + 3 + 1 + + + + MR4 + Event Mask on line 4 + 4 + 1 + + + + MR5 + Event Mask on line 5 + 5 + 1 + + + + MR6 + Event Mask on line 6 + 6 + 1 + + + + MR7 + Event Mask on line 7 + 7 + 1 + + + + MR8 + Event Mask on line 8 + 8 + 1 + + + + MR9 + Event Mask on line 9 + 9 + 1 + + + + MR10 + Event Mask on line 10 + 10 + 1 + + + + MR11 + Event Mask on line 11 + 11 + 1 + + + + MR12 + Event Mask on line 12 + 12 + 1 + + + + MR13 + Event Mask on line 13 + 13 + 1 + + + + MR14 + Event Mask on line 14 + 14 + 1 + + + + MR15 + Event Mask on line 15 + 15 + 1 + + + + MR16 + Event Mask on line 16 + 16 + 1 + + + + MR17 + Event Mask on line 17 + 17 + 1 + + + + MR18 + Event Mask on line 18 + 18 + 1 + + + + MR19 + Event Mask on line 19 + 19 + 1 + + + + MR20 + Event Mask on line 20 + 20 + 1 + + + + MR21 + Event Mask on line 21 + 21 + 1 + + + + MR22 + Event Mask on line 22 + 22 + 1 + + + + + + RTSR + RTSR + Rising Trigger selection register + (EXTI_RTSR) + 0x8 + 0x20 + read-write + 0x00000000 + + + TR0 + Rising trigger event configuration of + line 0 + 0 + 1 + + TR0 + read-write + + Disabled + Rising edge trigger is disabled + 0 + + + Enabled + Rising edge trigger is enabled + 1 + + + + + TR1 + Rising trigger event configuration of + line 1 + 1 + 1 + + + + TR2 + Rising trigger event configuration of + line 2 + 2 + 1 + + + + TR3 + Rising trigger event configuration of + line 3 + 3 + 1 + + + + TR4 + Rising trigger event configuration of + line 4 + 4 + 1 + + + + TR5 + Rising trigger event configuration of + line 5 + 5 + 1 + + + + TR6 + Rising trigger event configuration of + line 6 + 6 + 1 + + + + TR7 + Rising trigger event configuration of + line 7 + 7 + 1 + + + + TR8 + Rising trigger event configuration of + line 8 + 8 + 1 + + + + TR9 + Rising trigger event configuration of + line 9 + 9 + 1 + + + + TR10 + Rising trigger event configuration of + line 10 + 10 + 1 + + + + TR11 + Rising trigger event configuration of + line 11 + 11 + 1 + + + + TR12 + Rising trigger event configuration of + line 12 + 12 + 1 + + + + TR13 + Rising trigger event configuration of + line 13 + 13 + 1 + + + + TR14 + Rising trigger event configuration of + line 14 + 14 + 1 + + + + TR15 + Rising trigger event configuration of + line 15 + 15 + 1 + + + + TR16 + Rising trigger event configuration of + line 16 + 16 + 1 + + + + TR17 + Rising trigger event configuration of + line 17 + 17 + 1 + + + + TR18 + Rising trigger event configuration of + line 18 + 18 + 1 + + + + TR19 + Rising trigger event configuration of + line 19 + 19 + 1 + + + + TR20 + Rising trigger event configuration of + line 20 + 20 + 1 + + + + TR21 + Rising trigger event configuration of + line 21 + 21 + 1 + + + + TR22 + Rising trigger event configuration of + line 22 + 22 + 1 + + + + + + FTSR + FTSR + Falling Trigger selection register + (EXTI_FTSR) + 0xC + 0x20 + read-write + 0x00000000 + + + TR0 + Falling trigger event configuration of + line 0 + 0 + 1 + + TR0 + read-write + + Disabled + Falling edge trigger is disabled + 0 + + + Enabled + Falling edge trigger is enabled + 1 + + + + + TR1 + Falling trigger event configuration of + line 1 + 1 + 1 + + + + TR2 + Falling trigger event configuration of + line 2 + 2 + 1 + + + + TR3 + Falling trigger event configuration of + line 3 + 3 + 1 + + + + TR4 + Falling trigger event configuration of + line 4 + 4 + 1 + + + + TR5 + Falling trigger event configuration of + line 5 + 5 + 1 + + + + TR6 + Falling trigger event configuration of + line 6 + 6 + 1 + + + + TR7 + Falling trigger event configuration of + line 7 + 7 + 1 + + + + TR8 + Falling trigger event configuration of + line 8 + 8 + 1 + + + + TR9 + Falling trigger event configuration of + line 9 + 9 + 1 + + + + TR10 + Falling trigger event configuration of + line 10 + 10 + 1 + + + + TR11 + Falling trigger event configuration of + line 11 + 11 + 1 + + + + TR12 + Falling trigger event configuration of + line 12 + 12 + 1 + + + + TR13 + Falling trigger event configuration of + line 13 + 13 + 1 + + + + TR14 + Falling trigger event configuration of + line 14 + 14 + 1 + + + + TR15 + Falling trigger event configuration of + line 15 + 15 + 1 + + + + TR16 + Falling trigger event configuration of + line 16 + 16 + 1 + + + + TR17 + Falling trigger event configuration of + line 17 + 17 + 1 + + + + TR18 + Falling trigger event configuration of + line 18 + 18 + 1 + + + + TR19 + Falling trigger event configuration of + line 19 + 19 + 1 + + + + TR20 + Falling trigger event configuration of + line 20 + 20 + 1 + + + + TR21 + Falling trigger event configuration of + line 21 + 21 + 1 + + + + TR22 + Falling trigger event configuration of + line 22 + 22 + 1 + + + + + + SWIER + SWIER + Software interrupt event register + (EXTI_SWIER) + 0x10 + 0x20 + read-write + 0x00000000 + + + SWIER0 + Software Interrupt on line + 0 + 0 + 1 + + SWIER0W + write + + Pend + Generates an interrupt request + 1 + + + + + SWIER1 + Software Interrupt on line + 1 + 1 + 1 + + + + SWIER2 + Software Interrupt on line + 2 + 2 + 1 + + + + SWIER3 + Software Interrupt on line + 3 + 3 + 1 + + + + SWIER4 + Software Interrupt on line + 4 + 4 + 1 + + + + SWIER5 + Software Interrupt on line + 5 + 5 + 1 + + + + SWIER6 + Software Interrupt on line + 6 + 6 + 1 + + + + SWIER7 + Software Interrupt on line + 7 + 7 + 1 + + + + SWIER8 + Software Interrupt on line + 8 + 8 + 1 + + + + SWIER9 + Software Interrupt on line + 9 + 9 + 1 + + + + SWIER10 + Software Interrupt on line + 10 + 10 + 1 + + + + SWIER11 + Software Interrupt on line + 11 + 11 + 1 + + + + SWIER12 + Software Interrupt on line + 12 + 12 + 1 + + + + SWIER13 + Software Interrupt on line + 13 + 13 + 1 + + + + SWIER14 + Software Interrupt on line + 14 + 14 + 1 + + + + SWIER15 + Software Interrupt on line + 15 + 15 + 1 + + + + SWIER16 + Software Interrupt on line + 16 + 16 + 1 + + + + SWIER17 + Software Interrupt on line + 17 + 17 + 1 + + + + SWIER18 + Software Interrupt on line + 18 + 18 + 1 + + + + SWIER19 + Software Interrupt on line + 19 + 19 + 1 + + + + SWIER20 + Software Interrupt on line + 20 + 20 + 1 + + + + SWIER21 + Software Interrupt on line + 21 + 21 + 1 + + + + SWIER22 + Software Interrupt on line + 22 + 22 + 1 + + + + + + PR + PR + Pending register (EXTI_PR) + 0x14 + 0x20 + read-write + 0x00000000 + + + PR0 + Pending bit 0 + 0 + 1 + oneToClear + + PR0R + read + + NotPending + No trigger request occurred + 0 + + + Pending + Selected trigger request occurred + 1 + + + + PR0W + write + + Clear + Clears pending bit + 1 + + + + + PR1 + Pending bit 1 + 1 + 1 + oneToClear + + read + + + write + + + + PR2 + Pending bit 2 + 2 + 1 + oneToClear + + read + + + write + + + + PR3 + Pending bit 3 + 3 + 1 + oneToClear + + read + + + write + + + + PR4 + Pending bit 4 + 4 + 1 + oneToClear + + read + + + write + + + + PR5 + Pending bit 5 + 5 + 1 + oneToClear + + read + + + write + + + + PR6 + Pending bit 6 + 6 + 1 + oneToClear + + read + + + write + + + + PR7 + Pending bit 7 + 7 + 1 + oneToClear + + read + + + write + + + + PR8 + Pending bit 8 + 8 + 1 + oneToClear + + read + + + write + + + + PR9 + Pending bit 9 + 9 + 1 + oneToClear + + read + + + write + + + + PR10 + Pending bit 10 + 10 + 1 + oneToClear + + read + + + write + + + + PR11 + Pending bit 11 + 11 + 1 + oneToClear + + read + + + write + + + + PR12 + Pending bit 12 + 12 + 1 + oneToClear + + read + + + write + + + + PR13 + Pending bit 13 + 13 + 1 + oneToClear + + read + + + write + + + + PR14 + Pending bit 14 + 14 + 1 + oneToClear + + read + + + write + + + + PR15 + Pending bit 15 + 15 + 1 + oneToClear + + read + + + write + + + + PR16 + Pending bit 16 + 16 + 1 + oneToClear + + read + + + write + + + + PR17 + Pending bit 17 + 17 + 1 + oneToClear + + read + + + write + + + + PR18 + Pending bit 18 + 18 + 1 + oneToClear + + read + + + write + + + + PR19 + Pending bit 19 + 19 + 1 + oneToClear + + read + + + write + + + + PR20 + Pending bit 20 + 20 + 1 + oneToClear + + read + + + write + + + + PR21 + Pending bit 21 + 21 + 1 + oneToClear + + read + + + write + + + + PR22 + Pending bit 22 + 22 + 1 + oneToClear + + read + + + write + + + + + + + + FLASH + FLASH + FLASH + 0x40023C00 + + 0x0 + 0x400 + registers + + + FLASH + FLASH global interrupt + 4 + + + + ACR + ACR + Flash access control register + 0x0 + 0x20 + 0x00000000 + + + LATENCY + Latency + 0 + 4 + read-write + + LATENCY + read-write + + WS0 + 0 wait states + 0 + + + WS1 + 1 wait states + 1 + + + WS2 + 2 wait states + 2 + + + WS3 + 3 wait states + 3 + + + WS4 + 4 wait states + 4 + + + WS5 + 5 wait states + 5 + + + WS6 + 6 wait states + 6 + + + WS7 + 7 wait states + 7 + + + WS8 + 8 wait states + 8 + + + WS9 + 9 wait states + 9 + + + WS10 + 10 wait states + 10 + + + WS11 + 11 wait states + 11 + + + WS12 + 12 wait states + 12 + + + WS13 + 13 wait states + 13 + + + WS14 + 14 wait states + 14 + + + WS15 + 15 wait states + 15 + + + + + PRFTEN + Prefetch enable + 8 + 1 + read-write + + PRFTEN + read-write + + Disabled + Prefetch is disabled + 0 + + + Enabled + Prefetch is enabled + 1 + + + + + ICEN + Instruction cache enable + 9 + 1 + read-write + + ICEN + read-write + + Disabled + Instruction cache is disabled + 0 + + + Enabled + Instruction cache is enabled + 1 + + + + + DCEN + Data cache enable + 10 + 1 + read-write + + DCEN + read-write + + Disabled + Data cache is disabled + 0 + + + Enabled + Data cache is enabled + 1 + + + + + ICRST + Instruction cache reset + 11 + 1 + write-only + + ICRST + write + + NotReset + Instruction cache is not reset + 0 + + + Reset + Instruction cache is reset + 1 + + + + + DCRST + Data cache reset + 12 + 1 + read-write + + DCRST + read-write + + NotReset + Data cache is not reset + 0 + + + Reset + Data cache is reset + 1 + + + + + + + KEYR + KEYR + Flash key register + 0x4 + 0x20 + write-only + 0x00000000 + + + KEY + FPEC key + 0 + 32 + + + 0 + 4294967295 + + + + + + + OPTKEYR + OPTKEYR + Flash option key register + 0x8 + 0x20 + write-only + 0x00000000 + + + OPTKEY + Option byte key + 0 + 32 + + + 0 + 4294967295 + + + + + + + SR + SR + Status register + 0xC + 0x20 + 0x00000000 + + + EOP + End of operation + 0 + 1 + read-write + oneToClear + + EOPW + write + + Clear + Clear error flag + 1 + + + + + OPERR + Operation error + 1 + 1 + read-write + oneToClear + + OPERRW + write + + Clear + Clear error flag + 1 + + + + + WRPERR + Write protection error + 4 + 1 + read-write + oneToClear + + WRPERRW + write + + Clear + Clear error flag + 1 + + + + + PGAERR + Programming alignment + error + 5 + 1 + read-write + oneToClear + + PGAERRW + write + + Clear + Clear error flag + 1 + + + + + PGPERR + Programming parallelism + error + 6 + 1 + read-write + oneToClear + + PGPERRW + write + + Clear + Clear error flag + 1 + + + + + PGSERR + Programming sequence error + 7 + 1 + read-write + oneToClear + + PGSERRW + write + + Clear + Clear error flag + 1 + + + + + BSY + Busy + 16 + 1 + read-only + + BSYR + read + + NotBusy + no Flash memory operation ongoing + 0 + + + Busy + Flash memory operation ongoing + 1 + + + + + + + CR + CR + Control register + 0x10 + 0x20 + read-write + 0x80000000 + + + PG + Programming + 0 + 1 + + PG + read-write + + Program + Flash programming activated + 1 + + + + + SER + Sector Erase + 1 + 1 + + SER + read-write + + SectorErase + Erase activated for selected sector + 1 + + + + + MER + Mass Erase + 2 + 1 + + MER + read-write + + MassErase + Erase activated for all user sectors + 1 + + + + + SNB + Sector number + 3 + 4 + + + 0 + 11 + + + + + PSIZE + Program size + 8 + 2 + + PSIZE + read-write + + PSIZE8 + Program x8 + 0 + + + PSIZE16 + Program x16 + 1 + + + PSIZE32 + Program x32 + 2 + + + PSIZE64 + Program x64 + 3 + + + + + STRT + Start + 16 + 1 + + STRT + read-write + + Start + Trigger an erase operation + 1 + + + + + EOPIE + End of operation interrupt + enable + 24 + 1 + + EOPIE + read-write + + Disabled + End of operation interrupt disabled + 0 + + + Enabled + End of operation interrupt enabled + 1 + + + + + ERRIE + Error interrupt enable + 25 + 1 + + ERRIE + read-write + + Disabled + Error interrupt generation disabled + 0 + + + Enabled + Error interrupt generation enabled + 1 + + + + + LOCK + Lock + 31 + 1 + + LOCK + read-write + + Unlocked + FLASH_CR register is unlocked + 0 + + + Locked + FLASH_CR register is locked + 1 + + + + + + + OPTCR + OPTCR + Flash option control register + 0x14 + 0x20 + read-write + 0x00000014 + + + OPTLOCK + Option lock + 0 + 1 + + + OPTSTRT + Option start + 1 + 1 + + + BOR_LEV + BOR reset Level + 2 + 2 + + + WDG_SW + WDG_SW User option bytes + 5 + 1 + + + nRST_STOP + nRST_STOP User option + bytes + 6 + 1 + + + nRST_STDBY + nRST_STDBY User option + bytes + 7 + 1 + + + RDP + Read protect + 8 + 8 + + + nWRP + Not write protect + 16 + 12 + + + + + + + IWDG + Independent watchdog + IWDG + 0x40003000 + + 0x0 + 0x400 + registers + + + + KR + KR + Key register + 0x0 + 0x20 + write-only + 0x00000000 + + + KEY + Key value + 0 + 16 + + KEY + write + + Enable + Enable access to PR, RLR and WINR registers (0x5555) + 21845 + + + Reset + Reset the watchdog value (0xAAAA) + 43690 + + + Start + Start the watchdog (0xCCCC) + 52428 + + + + + + + PR + PR + Prescaler register + 0x4 + 0x20 + read-write + 0x00000000 + + + PR + Prescaler divider + 0 + 3 + + PR + read-write + + DivideBy4 + Divider /4 + 0 + + + DivideBy8 + Divider /8 + 1 + + + DivideBy16 + Divider /16 + 2 + + + DivideBy32 + Divider /32 + 3 + + + DivideBy64 + Divider /64 + 4 + + + DivideBy128 + Divider /128 + 5 + + + DivideBy256 + Divider /256 + 6 + + + DivideBy256bis + Divider /256 + 7 + + + + + + + RLR + RLR + Reload register + 0x8 + 0x20 + read-write + 0x00000FFF + + + RL + Watchdog counter reload + value + 0 + 12 + + + 0 + 4095 + + + + + + + SR + SR + Status register + 0xC + 0x20 + read-only + 0x00000000 + + + RVU + Watchdog counter reload value + update + 1 + 1 + + + PVU + Watchdog prescaler value + update + 0 + 1 + + + + + + + OTG_FS_DEVICE + USB on the go full speed + USB_OTG_FS + 0x50000800 + + 0x0 + 0x400 + registers + + + + DCFG + DCFG + OTG_FS device configuration register + (OTG_FS_DCFG) + 0x0 + 0x20 + read-write + 0x02200000 + + + DSPD + Device speed + 0 + 2 + + + NZLSOHSK + Non-zero-length status OUT + handshake + 2 + 1 + + + DAD + Device address + 4 + 7 + + + PFIVL + Periodic frame interval + 11 + 2 + + + + + DCTL + DCTL + OTG_FS device control register + (OTG_FS_DCTL) + 0x4 + 0x20 + 0x00000000 + + + RWUSIG + Remote wakeup signaling + 0 + 1 + read-write + + + SDIS + Soft disconnect + 1 + 1 + read-write + + + GINSTS + Global IN NAK status + 2 + 1 + read-only + + + GONSTS + Global OUT NAK status + 3 + 1 + read-only + + + TCTL + Test control + 4 + 3 + read-write + + + SGINAK + Set global IN NAK + 7 + 1 + read-write + + + CGINAK + Clear global IN NAK + 8 + 1 + read-write + + + SGONAK + Set global OUT NAK + 9 + 1 + read-write + + + CGONAK + Clear global OUT NAK + 10 + 1 + read-write + + + POPRGDNE + Power-on programming done + 11 + 1 + read-write + + + + + DSTS + DSTS + OTG_FS device status register + (OTG_FS_DSTS) + 0x8 + 0x20 + read-only + 0x00000010 + + + SUSPSTS + Suspend status + 0 + 1 + + + ENUMSPD + Enumerated speed + 1 + 2 + + + EERR + Erratic error + 3 + 1 + + + FNSOF + Frame number of the received + SOF + 8 + 14 + + + + + DIEPMSK + DIEPMSK + OTG_FS device IN endpoint common interrupt + mask register (OTG_FS_DIEPMSK) + 0x10 + 0x20 + read-write + 0x00000000 + + + XFRCM + Transfer completed interrupt + mask + 0 + 1 + + + EPDM + Endpoint disabled interrupt + mask + 1 + 1 + + + TOM + Timeout condition mask (Non-isochronous + endpoints) + 3 + 1 + + + ITTXFEMSK + IN token received when TxFIFO empty + mask + 4 + 1 + + + INEPNMM + IN token received with EP mismatch + mask + 5 + 1 + + + INEPNEM + IN endpoint NAK effective + mask + 6 + 1 + + + + + DOEPMSK + DOEPMSK + OTG_FS device OUT endpoint common interrupt + mask register (OTG_FS_DOEPMSK) + 0x14 + 0x20 + read-write + 0x00000000 + + + XFRCM + Transfer completed interrupt + mask + 0 + 1 + + + EPDM + Endpoint disabled interrupt + mask + 1 + 1 + + + STUPM + SETUP phase done mask + 3 + 1 + + + OTEPDM + OUT token received when endpoint + disabled mask + 4 + 1 + + + + + DAINT + DAINT + OTG_FS device all endpoints interrupt + register (OTG_FS_DAINT) + 0x18 + 0x20 + read-only + 0x00000000 + + + IEPINT + IN endpoint interrupt bits + 0 + 16 + + + OEPINT + OUT endpoint interrupt + bits + 16 + 16 + + + + + DAINTMSK + DAINTMSK + OTG_FS all endpoints interrupt mask register + (OTG_FS_DAINTMSK) + 0x1C + 0x20 + read-write + 0x00000000 + + + IEPM + IN EP interrupt mask bits + 0 + 16 + + + OEPM + OUT EP interrupt mask bits + 16 + 16 + + + + + DVBUSDIS + DVBUSDIS + OTG_FS device VBUS discharge time + register + 0x28 + 0x20 + read-write + 0x000017D7 + + + VBUSDT + Device VBUS discharge time + 0 + 16 + + + + + DVBUSPULSE + DVBUSPULSE + OTG_FS device VBUS pulsing time + register + 0x2C + 0x20 + read-write + 0x000005B8 + + + DVBUSP + Device VBUS pulsing time + 0 + 12 + + + + + DIEPEMPMSK + DIEPEMPMSK + OTG_FS device IN endpoint FIFO empty + interrupt mask register + 0x34 + 0x20 + read-write + 0x00000000 + + + INEPTXFEM + IN EP Tx FIFO empty interrupt mask + bits + 0 + 16 + + + + + DIEP0 + Device IN endpoint 0 + 0x100 + + CTL + DIEPCTL0 + OTG_FS device control IN endpoint 0 control + register (OTG_FS_DIEPCTL0) + 0x0 + 0x20 + 0x00000000 + + + MPSIZ + Maximum packet size + 0 + 2 + read-write + + + USBAEP + USB active endpoint + 15 + 1 + read-only + + + NAKSTS + NAK status + 17 + 1 + read-only + + + EPTYP + Endpoint type + 18 + 2 + read-only + + + STALL + STALL handshake + 21 + 1 + read-write + + + TXFNUM + TxFIFO number + 22 + 4 + read-write + + + CNAK + Clear NAK + 26 + 1 + write-only + + + SNAK + Set NAK + 27 + 1 + write-only + + + EPDIS + Endpoint disable + 30 + 1 + read-only + + + EPENA + Endpoint enable + 31 + 1 + read-write + + + + + INT + DIEPINT0 + device endpoint-x interrupt + register + 0x8 + 0x20 + 0x00000080 + + + TXFE + TXFE + 7 + 1 + read-only + + + INEPNE + INEPNE + 6 + 1 + read-write + + + ITTXFE + ITTXFE + 4 + 1 + read-write + + + TOC + TOC + 3 + 1 + read-write + + + EPDISD + EPDISD + 1 + 1 + read-write + + + XFRC + XFRC + 0 + 1 + read-write + + + + + TSIZ + DIEPTSIZ0 + device endpoint-0 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + PKTCNT + Packet count + 19 + 2 + + + XFRSIZ + Transfer size + 0 + 7 + + + + + TXFSTS + DTXFSTS0 + OTG_FS device IN endpoint transmit FIFO + status register + 0x18 + 0x20 + read-only + 0x00000000 + + + INEPTFSAV + IN endpoint TxFIFO space + available + 0 + 16 + + + + + + 3 + 0x20 + 1-3 + DIEP%s + Device IN endpoint X + 0x120 + + CTL + DIEPCTL1 + OTG device endpoint-1 control + register + 0x0 + 0x20 + 0x00000000 + + + EPENA + EPENA + 31 + 1 + read-write + + + EPDIS + EPDIS + 30 + 1 + read-write + + + SODDFRM_SD1PID + SODDFRM/SD1PID + 29 + 1 + write-only + + + SD0PID_SEVNFRM + SD0PID/SEVNFRM + 28 + 1 + write-only + + + SNAK + SNAK + 27 + 1 + write-only + + + CNAK + CNAK + 26 + 1 + write-only + + + TXFNUM + TXFNUM + 22 + 4 + read-write + + + STALL + STALL handshake + 21 + 1 + read-write + + + EPTYP + EPTYP + 18 + 2 + read-write + + + NAKSTS + NAKSTS + 17 + 1 + read-only + + + EONUM_DPID + EONUM/DPID + 16 + 1 + read-only + + + USBAEP + USBAEP + 15 + 1 + read-write + + + MPSIZ + MPSIZ + 0 + 11 + read-write + + + + + INT + DIEPINT1 + device endpoint-1 interrupt + register + 0x8 + 0x20 + 0x00000080 + + + TXFE + TXFE + 7 + 1 + read-only + + + INEPNE + INEPNE + 6 + 1 + read-write + + + ITTXFE + ITTXFE + 4 + 1 + read-write + + + TOC + TOC + 3 + 1 + read-write + + + EPDISD + EPDISD + 1 + 1 + read-write + + + XFRC + XFRC + 0 + 1 + read-write + + + + + TSIZ + DIEPTSIZ1 + device endpoint-1 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + MCNT + Multi count + 29 + 2 + + + PKTCNT + Packet count + 19 + 10 + + + XFRSIZ + Transfer size + 0 + 19 + + + + + TXFSTS + DTXFSTS1 + OTG_FS device IN endpoint transmit FIFO + status register + 0x18 + 0x20 + read-only + 0x00000000 + + + INEPTFSAV + IN endpoint TxFIFO space + available + 0 + 16 + + + + + + DOEP0 + Device OUT endpoint 0 + 0x300 + + CTL + DOEPCTL0 + device endpoint-0 control + register + 0x0 + 0x20 + 0x00008000 + + + EPENA + EPENA + 31 + 1 + read-write + + + EPDIS + EPDIS + 30 + 1 + read-only + + + SNAK + SNAK + 27 + 1 + write-only + + + CNAK + CNAK + 26 + 1 + write-only + + + STALL + STALL handshake + 21 + 1 + read-write + + + SNPM + SNPM + 20 + 1 + read-write + + + EPTYP + EPTYP + 18 + 2 + read-only + + + NAKSTS + NAKSTS + 17 + 1 + read-only + + + USBAEP + USBAEP + 15 + 1 + read-only + + + MPSIZ + MPSIZ + 0 + 2 + read-only + + + + + INT + DOEPINT0 + device endpoint-0 interrupt + register + 0x8 + 0x20 + read-write + 0x00000080 + + + B2BSTUP + B2BSTUP + 6 + 1 + + + OTEPDIS + OTEPDIS + 4 + 1 + + + STUP + STUP + 3 + 1 + + + EPDISD + EPDISD + 1 + 1 + + + XFRC + XFRC + 0 + 1 + + + + + TSIZ + DOEPTSIZ0 + device OUT endpoint-0 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + STUPCNT + SETUP packet count + 29 + 2 + + + PKTCNT + Packet count + 19 + 1 + + + XFRSIZ + Transfer size + 0 + 7 + + + + + + 3 + 0x20 + 1-3 + DOEP%s + Device IN endpoint X + 0x320 + + CTL + DOEPCTL1 + device endpoint-1 control + register + 0x0 + 0x20 + 0x00000000 + + + EPENA + EPENA + 31 + 1 + read-write + + + EPDIS + EPDIS + 30 + 1 + read-write + + + SODDFRM + SODDFRM + 29 + 1 + write-only + + + SD0PID_SEVNFRM + SD0PID/SEVNFRM + 28 + 1 + write-only + + + SNAK + SNAK + 27 + 1 + write-only + + + CNAK + CNAK + 26 + 1 + write-only + + + STALL + STALL handshake + 21 + 1 + read-write + + + SNPM + SNPM + 20 + 1 + read-write + + + EPTYP + EPTYP + 18 + 2 + read-write + + + NAKSTS + NAKSTS + 17 + 1 + read-only + + + EONUM_DPID + EONUM/DPID + 16 + 1 + read-only + + + USBAEP + USBAEP + 15 + 1 + read-write + + + MPSIZ + MPSIZ + 0 + 11 + read-write + + + + + INT + DOEPINT1 + device endpoint-1 interrupt + register + 0x8 + 0x20 + read-write + 0x00000080 + + + B2BSTUP + B2BSTUP + 6 + 1 + + + OTEPDIS + OTEPDIS + 4 + 1 + + + STUP + STUP + 3 + 1 + + + EPDISD + EPDISD + 1 + 1 + + + XFRC + XFRC + 0 + 1 + + + + + TSIZ + DOEPTSIZ1 + device OUT endpoint-1 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + RXDPID_STUPCNT + Received data PID/SETUP packet + count + 29 + 2 + + + PKTCNT + Packet count + 19 + 10 + + + XFRSIZ + Transfer size + 0 + 19 + + + + + + + + OTG_FS_GLOBAL + USB on the go full speed + USB_OTG_FS + 0x50000000 + + 0x0 + 0x400 + registers + + + + GOTGCTL + GOTGCTL + OTG_FS control and status register + (OTG_FS_GOTGCTL) + 0x0 + 0x20 + 0x00000800 + + + SRQSCS + Session request success + 0 + 1 + read-only + + + SRQ + Session request + 1 + 1 + read-write + + + HNGSCS + Host negotiation success + 8 + 1 + read-only + + + HNPRQ + HNP request + 9 + 1 + read-write + + + HSHNPEN + Host set HNP enable + 10 + 1 + read-write + + + DHNPEN + Device HNP enabled + 11 + 1 + read-write + + + CIDSTS + Connector ID status + 16 + 1 + read-only + + + DBCT + Long/short debounce time + 17 + 1 + read-only + + + ASVLD + A-session valid + 18 + 1 + read-only + + + BSVLD + B-session valid + 19 + 1 + read-only + + + + + GOTGINT + GOTGINT + OTG_FS interrupt register + (OTG_FS_GOTGINT) + 0x4 + 0x20 + read-write + 0x00000000 + + + SEDET + Session end detected + 2 + 1 + + + SRSSCHG + Session request success status + change + 8 + 1 + + + HNSSCHG + Host negotiation success status + change + 9 + 1 + + + HNGDET + Host negotiation detected + 17 + 1 + + + ADTOCHG + A-device timeout change + 18 + 1 + + + DBCDNE + Debounce done + 19 + 1 + + + + + GAHBCFG + GAHBCFG + OTG_FS AHB configuration register + (OTG_FS_GAHBCFG) + 0x8 + 0x20 + read-write + 0x00000000 + + + GINT + Global interrupt mask + 0 + 1 + + + TXFELVL + TxFIFO empty level + 7 + 1 + + + PTXFELVL + Periodic TxFIFO empty + level + 8 + 1 + + + + + GUSBCFG + GUSBCFG + OTG_FS USB configuration register + (OTG_FS_GUSBCFG) + 0xC + 0x20 + 0x00000A00 + + + TOCAL + FS timeout calibration + 0 + 3 + read-write + + + PHYSEL + Full Speed serial transceiver + select + 6 + 1 + write-only + + + SRPCAP + SRP-capable + 8 + 1 + read-write + + + HNPCAP + HNP-capable + 9 + 1 + read-write + + + TRDT + USB turnaround time + 10 + 4 + read-write + + + FHMOD + Force host mode + 29 + 1 + read-write + + + FDMOD + Force device mode + 30 + 1 + read-write + + + CTXPKT + Corrupt Tx packet + 31 + 1 + read-write + + + + + GRSTCTL + GRSTCTL + OTG_FS reset register + (OTG_FS_GRSTCTL) + 0x10 + 0x20 + 0x20000000 + + + CSRST + Core soft reset + 0 + 1 + read-write + + + HSRST + HCLK soft reset + 1 + 1 + read-write + + + FCRST + Host frame counter reset + 2 + 1 + read-write + + + RXFFLSH + RxFIFO flush + 4 + 1 + read-write + + + TXFFLSH + TxFIFO flush + 5 + 1 + read-write + + + TXFNUM + TxFIFO number + 6 + 5 + read-write + + + AHBIDL + AHB master idle + 31 + 1 + read-only + + + + + GINTSTS + GINTSTS + OTG_FS core interrupt register + (OTG_FS_GINTSTS) + 0x14 + 0x20 + 0x04000020 + + + CMOD + Current mode of operation + 0 + 1 + read-only + + + MMIS + Mode mismatch interrupt + 1 + 1 + read-write + + + OTGINT + OTG interrupt + 2 + 1 + read-only + + + SOF + Start of frame + 3 + 1 + read-write + + + RXFLVL + RxFIFO non-empty + 4 + 1 + read-only + + + NPTXFE + Non-periodic TxFIFO empty + 5 + 1 + read-only + + + GINAKEFF + Global IN non-periodic NAK + effective + 6 + 1 + read-only + + + GOUTNAKEFF + Global OUT NAK effective + 7 + 1 + read-only + + + ESUSP + Early suspend + 10 + 1 + read-write + + + USBSUSP + USB suspend + 11 + 1 + read-write + + + USBRST + USB reset + 12 + 1 + read-write + + + ENUMDNE + Enumeration done + 13 + 1 + read-write + + + ISOODRP + Isochronous OUT packet dropped + interrupt + 14 + 1 + read-write + + + EOPF + End of periodic frame + interrupt + 15 + 1 + read-write + + + IEPINT + IN endpoint interrupt + 18 + 1 + read-only + + + OEPINT + OUT endpoint interrupt + 19 + 1 + read-only + + + IISOIXFR + Incomplete isochronous IN + transfer + 20 + 1 + read-write + + + IPXFR_INCOMPISOOUT + Incomplete periodic transfer(Host + mode)/Incomplete isochronous OUT transfer(Device + mode) + 21 + 1 + read-write + + + HPRTINT + Host port interrupt + 24 + 1 + read-only + + + HCINT + Host channels interrupt + 25 + 1 + read-only + + + PTXFE + Periodic TxFIFO empty + 26 + 1 + read-only + + + CIDSCHG + Connector ID status change + 28 + 1 + read-write + + + DISCINT + Disconnect detected + interrupt + 29 + 1 + read-write + + + SRQINT + Session request/new session detected + interrupt + 30 + 1 + read-write + + + WKUPINT + Resume/remote wakeup detected + interrupt + 31 + 1 + read-write + + + + + GINTMSK + GINTMSK + OTG_FS interrupt mask register + (OTG_FS_GINTMSK) + 0x18 + 0x20 + 0x00000000 + + + MMISM + Mode mismatch interrupt + mask + 1 + 1 + read-write + + + OTGINT + OTG interrupt mask + 2 + 1 + read-write + + + SOFM + Start of frame mask + 3 + 1 + read-write + + + RXFLVLM + Receive FIFO non-empty + mask + 4 + 1 + read-write + + + NPTXFEM + Non-periodic TxFIFO empty + mask + 5 + 1 + read-write + + + GINAKEFFM + Global non-periodic IN NAK effective + mask + 6 + 1 + read-write + + + GONAKEFFM + Global OUT NAK effective + mask + 7 + 1 + read-write + + + ESUSPM + Early suspend mask + 10 + 1 + read-write + + + USBSUSPM + USB suspend mask + 11 + 1 + read-write + + + USBRST + USB reset mask + 12 + 1 + read-write + + + ENUMDNEM + Enumeration done mask + 13 + 1 + read-write + + + ISOODRPM + Isochronous OUT packet dropped interrupt + mask + 14 + 1 + read-write + + + EOPFM + End of periodic frame interrupt + mask + 15 + 1 + read-write + + + EPMISM + Endpoint mismatch interrupt + mask + 17 + 1 + read-write + + + IEPINT + IN endpoints interrupt + mask + 18 + 1 + read-write + + + OEPINT + OUT endpoints interrupt + mask + 19 + 1 + read-write + + + IISOIXFRM + Incomplete isochronous IN transfer + mask + 20 + 1 + read-write + + + IPXFRM_IISOOXFRM + Incomplete periodic transfer mask(Host + mode)/Incomplete isochronous OUT transfer mask(Device + mode) + 21 + 1 + read-write + + + PRTIM + Host port interrupt mask + 24 + 1 + read-write + + + HCIM + Host channels interrupt + mask + 25 + 1 + read-write + + + PTXFEM + Periodic TxFIFO empty mask + 26 + 1 + read-write + + + CIDSCHGM + Connector ID status change + mask + 28 + 1 + read-write + + + DISCINT + Disconnect detected interrupt + mask + 29 + 1 + read-write + + + SRQIM + Session request/new session detected + interrupt mask + 30 + 1 + read-write + + + WUIM + Resume/remote wakeup detected interrupt + mask + 31 + 1 + read-write + + + + + GRXSTSR_Device + GRXSTSR_Device + OTG_FS Receive status debug read(Device + mode) + 0x1C + 0x20 + read-only + 0x00000000 + + + EPNUM + Endpoint number + 0 + 4 + + + BCNT + Byte count + 4 + 11 + + + DPID + Data PID + 15 + 2 + + + PKTSTS + Packet status + 17 + 4 + + + FRMNUM + Frame number + 21 + 4 + + + + + GRXSTSR_Host + GRXSTSR_Host + OTG status debug read (host mode) + GRXSTSR_Device + 0x1C + 0x20 + read-only + 0x00000000 + + + CHNUM + Channel number + 0 + 4 + + + BCNT + Byte count + 4 + 11 + + + DPID + Data PID + 15 + 2 + + + PKTSTS + Packet status + 17 + 4 + + + + + GRXFSIZ + GRXFSIZ + OTG_FS Receive FIFO size register + (OTG_FS_GRXFSIZ) + 0x24 + 0x20 + read-write + 0x00000200 + + + RXFD + RxFIFO depth + 0 + 16 + + + + + DIEPTXF0 + DIEPTXF0 + OTG_FS non-periodic transmit FIFO size + register (Device mode) + 0x28 + 0x20 + read-write + 0x00000200 + + + TX0FSA + Endpoint 0 transmit RAM start + address + 0 + 16 + + + TX0FD + Endpoint 0 TxFIFO depth + 16 + 16 + + + + + HNPTXFSIZ + HNPTXFSIZ + OTG_FS non-periodic transmit FIFO size + register (Host mode) + DIEPTXF0 + 0x28 + 0x20 + read-write + 0x00000200 + + + NPTXFSA + Non-periodic transmit RAM start + address + 0 + 16 + + + NPTXFD + Non-periodic TxFIFO depth + 16 + 16 + + + + + GNPTXSTS + GNPTXSTS + OTG_FS non-periodic transmit FIFO/queue + status register (OTG_FS_GNPTXSTS) + 0x2C + 0x20 + read-only + 0x00080200 + + + NPTXFSAV + Non-periodic TxFIFO space + available + 0 + 16 + + + NPTQXSAV + Non-periodic transmit request queue + space available + 16 + 8 + + + NPTXQTOP + Top of the non-periodic transmit request + queue + 24 + 7 + + + + + GCCFG + GCCFG + OTG_FS general core configuration register + (OTG_FS_GCCFG) + 0x38 + 0x20 + read-write + 0x00000000 + + + PWRDWN + Power down + 16 + 1 + + + VBUSASEN + Enable the VBUS sensing + device + 18 + 1 + + + VBUSBSEN + Enable the VBUS sensing + device + 19 + 1 + + + SOFOUTEN + SOF output enable + 20 + 1 + + + NOVBUSSENS + Vbus sensing disable option + 21 + 1 + + + + + CID + CID + core ID register + 0x3C + 0x20 + read-write + 0x00001000 + + + PRODUCT_ID + Product ID field + 0 + 32 + + + + + HPTXFSIZ + HPTXFSIZ + OTG_FS Host periodic transmit FIFO size + register (OTG_FS_HPTXFSIZ) + 0x100 + 0x20 + read-write + 0x02000600 + + + PTXSA + Host periodic TxFIFO start + address + 0 + 16 + + + PTXFSIZ + Host periodic TxFIFO depth + 16 + 16 + + + + + 3 + 0x4 + 1-3 + DIEPTXF%s + DIEPTXF1 + OTF_FS device IN endpoint transmit FIFO size register + 0x104 + 0x20 + read-write + 0x02000400 + + + INEPTXSA + IN endpoint FIFO2 transmit RAM start + address + 0 + 16 + + + INEPTXFD + IN endpoint TxFIFO depth + 16 + 16 + + + + + GRXSTSP_Device + OTG status read and pop (device mode) + 0x20 + 0x20 + read-only + 0x00000000 + + + FRMNUM + Frame number + 21 + 4 + + + PKTSTS + Packet status + 17 + 4 + + + DPID + Data PID + 15 + 2 + + + BCNT + Byte count + 4 + 11 + + + EPNUM + Endpoint number + 0 + 4 + + + + + GRXSTSP_Host + OTG status read and pop (host mode) + GRXSTSP_Device + 0x20 + 0x20 + read-only + 0x00000000 + + + PKTSTS + Packet status + 17 + 4 + + + DPID + Data PID + 15 + 2 + + + BCNT + Byte count + 4 + 11 + + + CHNUM + Channel number + 0 + 4 + + + + + + + OTG_FS_HOST + USB on the go full speed + USB_OTG_FS + 0x50000400 + + 0x0 + 0x400 + registers + + + + HCFG + HCFG + OTG_FS host configuration register + (OTG_FS_HCFG) + 0x0 + 0x20 + 0x00000000 + + + FSLSPCS + FS/LS PHY clock select + 0 + 2 + read-write + + + FSLSS + FS- and LS-only support + 2 + 1 + read-write + + + + + HFIR + HFIR + OTG_FS Host frame interval + register + 0x4 + 0x20 + read-write + 0x0000EA60 + + + FRIVL + Frame interval + 0 + 16 + + + + + HFNUM + HFNUM + OTG_FS host frame number/frame time + remaining register (OTG_FS_HFNUM) + 0x8 + 0x20 + read-only + 0x00003FFF + + + FRNUM + Frame number + 0 + 16 + + + FTREM + Frame time remaining + 16 + 16 + + + + + HPTXSTS + HPTXSTS + OTG_FS_Host periodic transmit FIFO/queue + status register (OTG_FS_HPTXSTS) + 0x10 + 0x20 + 0x00080100 + + + PTXFSAVL + Periodic transmit data FIFO space + available + 0 + 16 + read-write + + + PTXQSAV + Periodic transmit request queue space + available + 16 + 8 + read-only + + + PTXQTOP + Top of the periodic transmit request + queue + 24 + 8 + read-only + + + + + HAINT + HAINT + OTG_FS Host all channels interrupt + register + 0x14 + 0x20 + read-only + 0x00000000 + + + HAINT + Channel interrupts + 0 + 16 + + + + + HAINTMSK + HAINTMSK + OTG_FS host all channels interrupt mask + register + 0x18 + 0x20 + read-write + 0x00000000 + + + HAINTM + Channel interrupt mask + 0 + 16 + + + + + HPRT + HPRT + OTG_FS host port control and status register + (OTG_FS_HPRT) + 0x40 + 0x20 + 0x00000000 + + + PCSTS + Port connect status + 0 + 1 + read-only + + + PCDET + Port connect detected + 1 + 1 + read-write + + + PENA + Port enable + 2 + 1 + read-write + + + PENCHNG + Port enable/disable change + 3 + 1 + read-write + + + POCA + Port overcurrent active + 4 + 1 + read-only + + + POCCHNG + Port overcurrent change + 5 + 1 + read-write + + + PRES + Port resume + 6 + 1 + read-write + + + PSUSP + Port suspend + 7 + 1 + read-write + + + PRST + Port reset + 8 + 1 + read-write + + + PLSTS + Port line status + 10 + 2 + read-only + + + PPWR + Port power + 12 + 1 + read-write + + + PTCTL + Port test control + 13 + 4 + read-write + + + PSPD + Port speed + 17 + 2 + read-only + + + + + 8 + 0x20 + 0-7 + HC%s + Host channel + 0x100 + + CHAR + HCCHAR0 + OTG_FS host channel-0 characteristics + register (OTG_FS_HCCHAR0) + 0x0 + 0x20 + read-write + 0x00000000 + + + MPSIZ + Maximum packet size + 0 + 11 + + + EPNUM + Endpoint number + 11 + 4 + + + EPDIR + Endpoint direction + 15 + 1 + + + LSDEV + Low-speed device + 17 + 1 + + + EPTYP + Endpoint type + 18 + 2 + + + MCNT + Multicount + 20 + 2 + + + DAD + Device address + 22 + 7 + + + ODDFRM + Odd frame + 29 + 1 + + + CHDIS + Channel disable + 30 + 1 + + + CHENA + Channel enable + 31 + 1 + + + + + INT + HCINT0 + OTG_FS host channel-0 interrupt register + (OTG_FS_HCINT0) + 0x8 + 0x20 + read-write + 0x00000000 + + + XFRC + Transfer completed + 0 + 1 + + + CHH + Channel halted + 1 + 1 + + + STALL + STALL response received + interrupt + 3 + 1 + + + NAK + NAK response received + interrupt + 4 + 1 + + + ACK + ACK response received/transmitted + interrupt + 5 + 1 + + + TXERR + Transaction error + 7 + 1 + + + BBERR + Babble error + 8 + 1 + + + FRMOR + Frame overrun + 9 + 1 + + + DTERR + Data toggle error + 10 + 1 + + + + + INTMSK + HCINTMSK0 + OTG_FS host channel-0 mask register + (OTG_FS_HCINTMSK0) + 0xC + 0x20 + read-write + 0x00000000 + + + XFRCM + Transfer completed mask + 0 + 1 + + + CHHM + Channel halted mask + 1 + 1 + + + STALLM + STALL response received interrupt + mask + 3 + 1 + + + NAKM + NAK response received interrupt + mask + 4 + 1 + + + ACKM + ACK response received/transmitted + interrupt mask + 5 + 1 + + + NYET + response received interrupt + mask + 6 + 1 + + + TXERRM + Transaction error mask + 7 + 1 + + + BBERRM + Babble error mask + 8 + 1 + + + FRMORM + Frame overrun mask + 9 + 1 + + + DTERRM + Data toggle error mask + 10 + 1 + + + + + TSIZ + HCTSIZ0 + OTG_FS host channel-0 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + XFRSIZ + Transfer size + 0 + 19 + + + PKTCNT + Packet count + 19 + 10 + + + DPID + Data PID + 29 + 2 + + + + + + + + OTG_FS_PWRCLK + USB on the go full speed + USB_OTG_FS + 0x50000E00 + + 0x0 + 0x400 + registers + + + + PCGCCTL + PCGCCTL + OTG_FS power and clock gating control + register + 0x0 + 0x20 + read-write + 0x00000000 + + + STPPCLK + Stop PHY clock + 0 + 1 + + + GATEHCLK + Gate HCLK + 1 + 1 + + + PHYSUSP + PHY Suspended + 4 + 1 + + + + + + + PWR + Power control + PWR + 0x40007000 + + 0x0 + 0x400 + registers + + + + CR + CR + power control register + 0x0 + 0x20 + read-write + 0x00000000 + + + VOS + Regulator voltage scaling output + selection + 14 + 2 + + + ADCDC1 + ADCDC1 + 13 + 1 + + + FPDS + Flash power down in Stop + mode + 9 + 1 + + + DBP + Disable backup domain write + protection + 8 + 1 + + + PLS + PVD level selection + 5 + 3 + + + PVDE + Power voltage detector + enable + 4 + 1 + + + CSBF + Clear standby flag + 3 + 1 + + + CWUF + Clear wakeup flag + 2 + 1 + + + PDDS + Power down deepsleep + 1 + 1 + + + LPDS + Low-power deep sleep + 0 + 1 + + + + + CSR + CSR + power control/status register + 0x4 + 0x20 + 0x00000000 + + + WUF + Wakeup flag + 0 + 1 + read-only + + + SBF + Standby flag + 1 + 1 + read-only + + + PVDO + PVD output + 2 + 1 + read-only + + + BRR + Backup regulator ready + 3 + 1 + read-only + + + EWUP + Enable WKUP pin + 8 + 1 + read-write + + + BRE + Backup regulator enable + 9 + 1 + read-write + + + VOSRDY + Regulator voltage scaling output + selection ready bit + 14 + 1 + read-write + + + + + + + RCC + Reset and clock control + RCC + 0x40023800 + + 0x0 + 0x400 + registers + + + I2C1_EV + I2C1 event interrupt + 31 + + + I2C1_ER + I2C1 error interrupt + 32 + + + + CR + CR + clock control register + 0x0 + 0x20 + 0x00000083 + + + PLLI2SRDY + PLLI2S clock ready flag + 27 + 1 + read-only + + + + PLLI2SON + PLLI2S enable + 26 + 1 + read-write + + + + PLLRDY + Main PLL (PLL) clock ready + flag + 25 + 1 + read-only + + + + PLLON + Main PLL (PLL) enable + 24 + 1 + read-write + + + + CSSON + Clock security system + enable + 19 + 1 + read-write + + CSSON + read-write + + Off + Clock security system disabled (clock detector OFF) + 0 + + + On + Clock security system enable (clock detector ON if the HSE is ready, OFF if not) + 1 + + + + + HSEBYP + HSE clock bypass + 18 + 1 + read-write + + HSEBYP + read-write + + NotBypassed + HSE crystal oscillator not bypassed + 0 + + + Bypassed + HSE crystal oscillator bypassed with external clock + 1 + + + + + HSERDY + HSE clock ready flag + 17 + 1 + read-only + + + + HSEON + HSE clock enable + 16 + 1 + read-write + + + + HSICAL + Internal high-speed clock + calibration + 8 + 8 + read-only + + + 0 + 255 + + + + + HSITRIM + Internal high-speed clock + trimming + 3 + 5 + read-write + + + 0 + 31 + + + + + HSIRDY + Internal high-speed clock ready + flag + 1 + 1 + read-only + + HSIRDYR + read + + NotReady + Clock not ready + 0 + + + Ready + Clock ready + 1 + + + + + HSION + Internal high-speed clock + enable + 0 + 1 + read-write + + HSION + read-write + + Off + Clock Off + 0 + + + On + Clock On + 1 + + + + + + + PLLCFGR + PLLCFGR + PLL configuration register + 0x4 + 0x20 + read-write + 0x24003010 + + + PLLSRC + Main PLL(PLL) and audio PLL (PLLI2S) + entry clock source + 22 + 1 + + PLLSRC + read-write + + HSI + HSI clock selected as PLL and PLLI2S clock entry + 0 + + + HSE + HSE oscillator clock selected as PLL and PLLI2S clock entry + 1 + + + + + PLLM + Division factor for the main PLL (PLL) + and audio PLL (PLLI2S) input clock + 0 + 6 + + + 2 + 63 + + + + + PLLN + Main PLL (PLL) multiplication factor for + VCO + 6 + 9 + + + 50 + 432 + + + + + PLLP + Main PLL (PLL) division factor for main + system clock + 16 + 2 + + PLLP + read-write + + Div2 + PLLP=2 + 0 + + + Div4 + PLLP=4 + 1 + + + Div6 + PLLP=6 + 2 + + + Div8 + PLLP=8 + 3 + + + + + PLLQ + Main PLL (PLL) division factor for USB + OTG FS, SDIO and random number generator + clocks + 24 + 4 + + + 2 + 15 + + + + + + + CFGR + CFGR + clock configuration register + 0x8 + 0x20 + 0x00000000 + + + MCO2 + Microcontroller clock output + 2 + 30 + 2 + read-write + + MCO2 + read-write + + SYSCLK + System clock (SYSCLK) selected + 0 + + + PLLI2S + PLLI2S clock selected + 1 + + + HSE + HSE oscillator clock selected + 2 + + + PLL + PLL clock selected + 3 + + + + + MCO2PRE + MCO2 prescaler + 27 + 3 + read-write + + + + MCO1PRE + MCO1 prescaler + 24 + 3 + read-write + + MCO1PRE + read-write + + Div1 + No division + 0 + + + Div2 + Division by 2 + 4 + + + Div3 + Division by 3 + 5 + + + Div4 + Division by 4 + 6 + + + Div5 + Division by 5 + 7 + + + + + I2SSRC + I2S clock selection + 23 + 1 + read-write + + I2SSRC + read-write + + PLLI2S + PLLI2S clock used as I2S clock source + 0 + + + CKIN + External clock mapped on the I2S_CKIN pin used as I2S clock source + 1 + + + + + MCO1 + Microcontroller clock output + 1 + 21 + 2 + read-write + + MCO1 + read-write + + HSI + HSI clock selected + 0 + + + LSE + LSE oscillator selected + 1 + + + HSE + HSE oscillator clock selected + 2 + + + PLL + PLL clock selected + 3 + + + + + RTCPRE + HSE division factor for RTC + clock + 16 + 5 + read-write + + + 0 + 31 + + + + + PPRE2 + APB high-speed prescaler + (APB2) + 13 + 3 + read-write + + + + PPRE1 + APB Low speed prescaler + (APB1) + 10 + 3 + read-write + + PPRE1 + read-write + + Div1 + HCLK not divided + 0 + + + Div2 + HCLK divided by 2 + 4 + + + Div4 + HCLK divided by 4 + 5 + + + Div8 + HCLK divided by 8 + 6 + + + Div16 + HCLK divided by 16 + 7 + + + + + HPRE + AHB prescaler + 4 + 4 + read-write + + HPRE + read-write + + Div1 + SYSCLK not divided + 0 + + + Div2 + SYSCLK divided by 2 + 8 + + + Div4 + SYSCLK divided by 4 + 9 + + + Div8 + SYSCLK divided by 8 + 10 + + + Div16 + SYSCLK divided by 16 + 11 + + + Div64 + SYSCLK divided by 64 + 12 + + + Div128 + SYSCLK divided by 128 + 13 + + + Div256 + SYSCLK divided by 256 + 14 + + + Div512 + SYSCLK divided by 512 + 15 + + + + + SW + System clock switch + 0 + 2 + + SW + read-write + + HSI + HSI selected as system clock + 0 + + + HSE + HSE selected as system clock + 1 + + + PLL + PLL selected as system clock + 2 + + + + + SWS + System clock switch status + 2 + 2 + + SWSR + read + + HSI + HSI oscillator used as system clock + 0 + + + HSE + HSE oscillator used as system clock + 1 + + + PLL + PLL used as system clock + 2 + + + + + + + CIR + CIR + clock interrupt register + 0xC + 0x20 + 0x00000000 + + + CSSC + Clock security system interrupt + clear + 23 + 1 + write-only + + CSSCW + write + + Clear + Clear CSSF flag + 1 + + + + + PLLI2SRDYC + PLLI2S ready interrupt + clear + 21 + 1 + write-only + + + + PLLRDYC + Main PLL(PLL) ready interrupt + clear + 20 + 1 + write-only + + + + HSERDYC + HSE ready interrupt clear + 19 + 1 + write-only + + + + HSIRDYC + HSI ready interrupt clear + 18 + 1 + write-only + + + + LSERDYC + LSE ready interrupt clear + 17 + 1 + write-only + + + + LSIRDYC + LSI ready interrupt clear + 16 + 1 + write-only + + LSIRDYCW + write + + Clear + Clear interrupt flag + 1 + + + + + PLLI2SRDYIE + PLLI2S ready interrupt + enable + 13 + 1 + read-write + + + + PLLRDYIE + Main PLL (PLL) ready interrupt + enable + 12 + 1 + read-write + + + + HSERDYIE + HSE ready interrupt enable + 11 + 1 + read-write + + + + HSIRDYIE + HSI ready interrupt enable + 10 + 1 + read-write + + + + LSERDYIE + LSE ready interrupt enable + 9 + 1 + read-write + + + + LSIRDYIE + LSI ready interrupt enable + 8 + 1 + read-write + + LSIRDYIE + read-write + + Disabled + Interrupt disabled + 0 + + + Enabled + Interrupt enabled + 1 + + + + + CSSF + Clock security system interrupt + flag + 7 + 1 + read-only + + CSSFR + read + + NotInterrupted + No clock security interrupt caused by HSE clock failure + 0 + + + Interrupted + Clock security interrupt caused by HSE clock failure + 1 + + + + + PLLI2SRDYF + PLLI2S ready interrupt + flag + 5 + 1 + read-only + + + + PLLRDYF + Main PLL (PLL) ready interrupt + flag + 4 + 1 + read-only + + + + HSERDYF + HSE ready interrupt flag + 3 + 1 + read-only + + + + HSIRDYF + HSI ready interrupt flag + 2 + 1 + read-only + + + + LSERDYF + LSE ready interrupt flag + 1 + 1 + read-only + + + + LSIRDYF + LSI ready interrupt flag + 0 + 1 + read-only + + LSIRDYFR + read + + NotInterrupted + No clock ready interrupt + 0 + + + Interrupted + Clock ready interrupt + 1 + + + + + + + AHB1RSTR + AHB1RSTR + AHB1 peripheral reset register + 0x10 + 0x20 + read-write + 0x00000000 + + + DMA2RST + DMA2 reset + 22 + 1 + + + + DMA1RST + DMA2 reset + 21 + 1 + + + + CRCRST + CRC reset + 12 + 1 + + + + GPIOHRST + IO port H reset + 7 + 1 + + + + GPIOERST + IO port E reset + 4 + 1 + + + + GPIODRST + IO port D reset + 3 + 1 + + + + GPIOCRST + IO port C reset + 2 + 1 + + + + GPIOBRST + IO port B reset + 1 + 1 + + + + GPIOARST + IO port A reset + 0 + 1 + + GPIOARST + read-write + + Reset + Reset the selected module + 1 + + + + + + + AHB2RSTR + AHB2RSTR + AHB2 peripheral reset register + 0x14 + 0x20 + read-write + 0x00000000 + + + OTGFSRST + USB OTG FS module reset + 7 + 1 + + OTGFSRST + read-write + + Reset + Reset the selected module + 1 + + + + + + + APB1RSTR + APB1RSTR + APB1 peripheral reset register + 0x20 + 0x20 + read-write + 0x00000000 + + + PWRRST + Power interface reset + 28 + 1 + + + + I2C3RST + I2C3 reset + 23 + 1 + + + + I2C2RST + I2C 2 reset + 22 + 1 + + + + I2C1RST + I2C 1 reset + 21 + 1 + + + + USART2RST + USART 2 reset + 17 + 1 + + + + SPI3RST + SPI 3 reset + 15 + 1 + + + + SPI2RST + SPI 2 reset + 14 + 1 + + + + WWDGRST + Window watchdog reset + 11 + 1 + + + + TIM5RST + TIM5 reset + 3 + 1 + + + + TIM4RST + TIM4 reset + 2 + 1 + + + + TIM3RST + TIM3 reset + 1 + 1 + + + + TIM2RST + TIM2 reset + 0 + 1 + + TIM2RST + read-write + + Reset + Reset the selected module + 1 + + + + + + + APB2RSTR + APB2RSTR + APB2 peripheral reset register + 0x24 + 0x20 + read-write + 0x00000000 + + + TIM11RST + TIM11 reset + 18 + 1 + + + + TIM10RST + TIM10 reset + 17 + 1 + + + + TIM9RST + TIM9 reset + 16 + 1 + + + + SYSCFGRST + System configuration controller + reset + 14 + 1 + + + + SPI1RST + SPI 1 reset + 12 + 1 + + + + SDIORST + SDIO reset + 11 + 1 + + + + ADCRST + ADC interface reset (common to all + ADCs) + 8 + 1 + + + + USART6RST + USART6 reset + 5 + 1 + + + + USART1RST + USART1 reset + 4 + 1 + + + + TIM1RST + TIM1 reset + 0 + 1 + + TIM1RST + read-write + + Reset + Reset the selected module + 1 + + + + + SPI4RST + SPI4 reset + 13 + 1 + + + + + + AHB1ENR + AHB1ENR + AHB1 peripheral clock register + 0x30 + 0x20 + read-write + 0x00100000 + + + DMA2EN + DMA2 clock enable + 22 + 1 + + + + DMA1EN + DMA1 clock enable + 21 + 1 + + + + CRCEN + CRC clock enable + 12 + 1 + + + + GPIOHEN + IO port H clock enable + 7 + 1 + + + + GPIOEEN + IO port E clock enable + 4 + 1 + + + + GPIODEN + IO port D clock enable + 3 + 1 + + + + GPIOCEN + IO port C clock enable + 2 + 1 + + + + GPIOBEN + IO port B clock enable + 1 + 1 + + + + GPIOAEN + IO port A clock enable + 0 + 1 + + GPIOAEN + read-write + + Disabled + The selected clock is disabled + 0 + + + Enabled + The selected clock is enabled + 1 + + + + + + + AHB2ENR + AHB2ENR + AHB2 peripheral clock enable + register + 0x34 + 0x20 + read-write + 0x00000000 + + + OTGFSEN + USB OTG FS clock enable + 7 + 1 + + OTGFSEN + read-write + + Disabled + The selected clock is disabled + 0 + + + Enabled + The selected clock is enabled + 1 + + + + + + + APB1ENR + APB1ENR + APB1 peripheral clock enable + register + 0x40 + 0x20 + read-write + 0x00000000 + + + PWREN + Power interface clock + enable + 28 + 1 + + + + I2C3EN + I2C3 clock enable + 23 + 1 + + + + I2C2EN + I2C2 clock enable + 22 + 1 + + + + I2C1EN + I2C1 clock enable + 21 + 1 + + + + USART2EN + USART 2 clock enable + 17 + 1 + + + + SPI3EN + SPI3 clock enable + 15 + 1 + + + + SPI2EN + SPI2 clock enable + 14 + 1 + + + + WWDGEN + Window watchdog clock + enable + 11 + 1 + + + + TIM5EN + TIM5 clock enable + 3 + 1 + + + + TIM4EN + TIM4 clock enable + 2 + 1 + + + + TIM3EN + TIM3 clock enable + 1 + 1 + + + + TIM2EN + TIM2 clock enable + 0 + 1 + + TIM2EN + read-write + + Disabled + The selected clock is disabled + 0 + + + Enabled + The selected clock is enabled + 1 + + + + + + + APB2ENR + APB2ENR + APB2 peripheral clock enable + register + 0x44 + 0x20 + read-write + 0x00000000 + + + TIM11EN + TIM11 clock enable + 18 + 1 + + + + TIM10EN + TIM10 clock enable + 17 + 1 + + + + TIM9EN + TIM9 clock enable + 16 + 1 + + + + SYSCFGEN + System configuration controller clock + enable + 14 + 1 + + + + SPI1EN + SPI1 clock enable + 12 + 1 + + + + SDIOEN + SDIO clock enable + 11 + 1 + + + + ADC1EN + ADC1 clock enable + 8 + 1 + + + + USART6EN + USART6 clock enable + 5 + 1 + + + + USART1EN + USART1 clock enable + 4 + 1 + + + + TIM1EN + TIM1 clock enable + 0 + 1 + + TIM1EN + read-write + + Disabled + The selected clock is disabled + 0 + + + Enabled + The selected clock is enabled + 1 + + + + + SPI4EN + SPI4 clock enable + 13 + 1 + + + + + + AHB1LPENR + AHB1LPENR + AHB1 peripheral clock enable in low power + mode register + 0x50 + 0x20 + read-write + 0x7E6791FF + + + DMA2LPEN + DMA2 clock enable during Sleep + mode + 22 + 1 + + + + DMA1LPEN + DMA1 clock enable during Sleep + mode + 21 + 1 + + + + SRAM1LPEN + SRAM 1interface clock enable during + Sleep mode + 16 + 1 + + + + FLITFLPEN + Flash interface clock enable during + Sleep mode + 15 + 1 + + + + CRCLPEN + CRC clock enable during Sleep + mode + 12 + 1 + + + + GPIOHLPEN + IO port H clock enable during Sleep + mode + 7 + 1 + + + + GPIOELPEN + IO port E clock enable during Sleep + mode + 4 + 1 + + + + GPIODLPEN + IO port D clock enable during Sleep + mode + 3 + 1 + + + + GPIOCLPEN + IO port C clock enable during Sleep + mode + 2 + 1 + + + + GPIOBLPEN + IO port B clock enable during Sleep + mode + 1 + 1 + + + + GPIOALPEN + IO port A clock enable during sleep + mode + 0 + 1 + + GPIOALPEN + read-write + + DisabledInSleep + Selected module is disabled during Sleep mode + 0 + + + EnabledInSleep + Selected module is enabled during Sleep mode + 1 + + + + + + + AHB2LPENR + AHB2LPENR + AHB2 peripheral clock enable in low power + mode register + 0x54 + 0x20 + read-write + 0x000000F1 + + + OTGFSLPEN + USB OTG FS clock enable during Sleep + mode + 7 + 1 + + OTGFSLPEN + read-write + + DisabledInSleep + Selected module is disabled during Sleep mode + 0 + + + EnabledInSleep + Selected module is enabled during Sleep mode + 1 + + + + + + + APB1LPENR + APB1LPENR + APB1 peripheral clock enable in low power + mode register + 0x60 + 0x20 + read-write + 0x36FEC9FF + + + PWRLPEN + Power interface clock enable during + Sleep mode + 28 + 1 + + + + I2C3LPEN + I2C3 clock enable during Sleep + mode + 23 + 1 + + + + I2C2LPEN + I2C2 clock enable during Sleep + mode + 22 + 1 + + + + I2C1LPEN + I2C1 clock enable during Sleep + mode + 21 + 1 + + + + USART2LPEN + USART2 clock enable during Sleep + mode + 17 + 1 + + + + SPI3LPEN + SPI3 clock enable during Sleep + mode + 15 + 1 + + + + SPI2LPEN + SPI2 clock enable during Sleep + mode + 14 + 1 + + + + WWDGLPEN + Window watchdog clock enable during + Sleep mode + 11 + 1 + + + + TIM5LPEN + TIM5 clock enable during Sleep + mode + 3 + 1 + + + + TIM4LPEN + TIM4 clock enable during Sleep + mode + 2 + 1 + + + + TIM3LPEN + TIM3 clock enable during Sleep + mode + 1 + 1 + + + + TIM2LPEN + TIM2 clock enable during Sleep + mode + 0 + 1 + + TIM2LPEN + read-write + + DisabledInSleep + Selected module is disabled during Sleep mode + 0 + + + EnabledInSleep + Selected module is enabled during Sleep mode + 1 + + + + + + + APB2LPENR + APB2LPENR + APB2 peripheral clock enabled in low power + mode register + 0x64 + 0x20 + read-write + 0x00075F33 + + + TIM11LPEN + TIM11 clock enable during Sleep + mode + 18 + 1 + + + + TIM10LPEN + TIM10 clock enable during Sleep + mode + 17 + 1 + + + + TIM9LPEN + TIM9 clock enable during sleep + mode + 16 + 1 + + + + SYSCFGLPEN + System configuration controller clock + enable during Sleep mode + 14 + 1 + + + + SPI1LPEN + SPI 1 clock enable during Sleep + mode + 12 + 1 + + + + SDIOLPEN + SDIO clock enable during Sleep + mode + 11 + 1 + + + + ADC1LPEN + ADC1 clock enable during Sleep + mode + 8 + 1 + + + + USART6LPEN + USART6 clock enable during Sleep + mode + 5 + 1 + + + + USART1LPEN + USART1 clock enable during Sleep + mode + 4 + 1 + + + + TIM1LPEN + TIM1 clock enable during Sleep + mode + 0 + 1 + + TIM1LPEN + read-write + + DisabledInSleep + Selected module is disabled during Sleep mode + 0 + + + EnabledInSleep + Selected module is enabled during Sleep mode + 1 + + + + + SPI4LPEN + SPI4 clock enable during Sleep mode + 13 + 1 + + + + + + BDCR + BDCR + Backup domain control register + 0x70 + 0x20 + 0x00000000 + + + BDRST + Backup domain software + reset + 16 + 1 + read-write + + BDRST + read-write + + Disabled + Reset not activated + 0 + + + Enabled + Reset the entire RTC domain + 1 + + + + + RTCEN + RTC clock enable + 15 + 1 + read-write + + RTCEN + read-write + + Disabled + RTC clock disabled + 0 + + + Enabled + RTC clock enabled + 1 + + + + + LSEBYP + External low-speed oscillator + bypass + 2 + 1 + read-write + + LSEBYP + read-write + + NotBypassed + LSE crystal oscillator not bypassed + 0 + + + Bypassed + LSE crystal oscillator bypassed with external clock + 1 + + + + + LSERDY + External low-speed oscillator + ready + 1 + 1 + read-only + + LSERDYR + read + + NotReady + LSE oscillator not ready + 0 + + + Ready + LSE oscillator ready + 1 + + + + + LSEON + External low-speed oscillator + enable + 0 + 1 + read-write + + LSEON + read-write + + Off + LSE oscillator Off + 0 + + + On + LSE oscillator On + 1 + + + + + RTCSEL + RTC clock source selection + 8 + 2 + + RTCSEL + read-write + + NoClock + No clock + 0 + + + LSE + LSE oscillator clock used as RTC clock + 1 + + + LSI + LSI oscillator clock used as RTC clock + 2 + + + HSE + HSE oscillator clock divided by a prescaler used as RTC clock + 3 + + + + + + + CSR + CSR + clock control & status + register + 0x74 + 0x20 + 0x0E000000 + + + LPWRRSTF + Low-power reset flag + 31 + 1 + read-write + + + + WWDGRSTF + Window watchdog reset flag + 30 + 1 + read-write + + + + WDGRSTF + Independent watchdog reset + flag + 29 + 1 + read-write + + + + SFTRSTF + Software reset flag + 28 + 1 + read-write + + + + PORRSTF + POR/PDR reset flag + 27 + 1 + read-write + + + + PADRSTF + PIN reset flag + 26 + 1 + read-write + + + + BORRSTF + BOR reset flag + 25 + 1 + read-write + + BORRSTFR + read + + NoReset + No reset has occured + 0 + + + Reset + A reset has occured + 1 + + + + + RMVF + Remove reset flag + 24 + 1 + read-write + + RMVFW + write + + Clear + Clears the reset flag + 1 + + + + + LSIRDY + Internal low-speed oscillator + ready + 1 + 1 + read-only + + LSIRDYR + read + + NotReady + LSI oscillator not ready + 0 + + + Ready + LSI oscillator ready + 1 + + + + + LSION + Internal low-speed oscillator + enable + 0 + 1 + read-write + + LSION + read-write + + Off + LSI oscillator Off + 0 + + + On + LSI oscillator On + 1 + + + + + + + SSCGR + SSCGR + spread spectrum clock generation + register + 0x80 + 0x20 + read-write + 0x00000000 + + + SSCGEN + Spread spectrum modulation + enable + 31 + 1 + + SSCGEN + read-write + + Disabled + Spread spectrum modulation disabled + 0 + + + Enabled + Spread spectrum modulation enabled + 1 + + + + + SPREADSEL + Spread Select + 30 + 1 + + SPREADSEL + read-write + + Center + Center spread + 0 + + + Down + Down spread + 1 + + + + + INCSTEP + Incrementation step + 13 + 15 + + + 0 + 32767 + + + + + MODPER + Modulation period + 0 + 13 + + + 0 + 8191 + + + + + + + PLLI2SCFGR + PLLI2SCFGR + PLLI2S configuration register + 0x84 + 0x20 + read-write + 0x20003000 + + + PLLI2SR + PLLI2S division factor for I2S + clocks + 28 + 3 + + + 2 + 7 + + + + + PLLI2SN + PLLI2S multiplication factor for + VCO + 6 + 9 + + + 50 + 432 + + + + + + + DCKCFGR + RCC Dedicated Clock Configuration Register + 0x8C + 0x20 + read-write + 0x00000000 + + + TIMPRE + Timers clocks prescalers selection + 24 + 1 + + TIMPRE + read-write + + Mul1Or2 + If the APB prescaler is configured 1, TIMxCLK = PCLKx. Otherwise, TIMxCLK = 2xPCLKx + 0 + + + Mul1Or4 + If the APB prescaler is configured 1, 2 or 4, TIMxCLK = HCLK. Otherwise, TIMxCLK = 4xPCLKx + 1 + + + + + + + + + RTC + Real-time clock + RTC + 0x40002800 + + 0x0 + 0x400 + registers + + + I2C2_EV + I2C2 event interrupt + 33 + + + I2C2_ER + I2C2 error interrupt + 34 + + + + TR + TR + time register + 0x0 + 0x20 + read-write + 0x00000000 + + + PM + AM/PM notation + 22 + 1 + + PM + read-write + + AM + AM or 24-hour format + 0 + + + PM + PM + 1 + + + + + HT + Hour tens in BCD format + 20 + 2 + + + 0 + 3 + + + + + HU + Hour units in BCD format + 16 + 4 + + + 0 + 15 + + + + + MNT + Minute tens in BCD format + 12 + 3 + + + 0 + 7 + + + + + MNU + Minute units in BCD format + 8 + 4 + + + 0 + 15 + + + + + ST + Second tens in BCD format + 4 + 3 + + + 0 + 7 + + + + + SU + Second units in BCD format + 0 + 4 + + + 0 + 15 + + + + + + + DR + DR + date register + 0x4 + 0x20 + read-write + 0x00002101 + + + YT + Year tens in BCD format + 20 + 4 + + + 0 + 15 + + + + + YU + Year units in BCD format + 16 + 4 + + + 0 + 15 + + + + + WDU + Week day units + 13 + 3 + + + 1 + 7 + + + + + MT + Month tens in BCD format + 12 + 1 + + MT + read-write + + Zero + Month tens is 0 + 0 + + + One + Month tens is 1 + 1 + + + + + MU + Month units in BCD format + 8 + 4 + + + 0 + 15 + + + + + DT + Date tens in BCD format + 4 + 2 + + + 0 + 3 + + + + + DU + Date units in BCD format + 0 + 4 + + + 0 + 15 + + + + + + + CR + CR + control register + 0x8 + 0x20 + read-write + 0x00000000 + + + COE + Calibration output enable + 23 + 1 + + COE + read-write + + Disabled + Calibration output disabled + 0 + + + Enabled + Calibration output enabled + 1 + + + + + OSEL + Output selection + 21 + 2 + + OSEL + read-write + + Disabled + Output disabled + 0 + + + AlarmA + Alarm A output enabled + 1 + + + AlarmB + Alarm B output enabled + 2 + + + Wakeup + Wakeup output enabled + 3 + + + + + POL + Output polarity + 20 + 1 + + POL + read-write + + High + The pin is high when ALRAF/ALRBF/WUTF is asserted (depending on OSEL[1:0]) + 0 + + + Low + The pin is low when ALRAF/ALRBF/WUTF is asserted (depending on OSEL[1:0]) + 1 + + + + + COSEL + Calibration Output + selection + 19 + 1 + + COSEL + read-write + + CalFreq_512Hz + Calibration output is 512 Hz (with default prescaler setting) + 0 + + + CalFreq_1Hz + Calibration output is 1 Hz (with default prescaler setting) + 1 + + + + + BKP + Backup + 18 + 1 + + BKP + read-write + + DST_Not_Changed + Daylight Saving Time change has not been performed + 0 + + + DST_Changed + Daylight Saving Time change has been performed + 1 + + + + + SUB1H + Subtract 1 hour (winter time + change) + 17 + 1 + + SUB1HW + write + + Sub1 + Subtracts 1 hour to the current time. This can be used for winter time change outside initialization mode + 1 + + + + + ADD1H + Add 1 hour (summer time + change) + 16 + 1 + + ADD1HW + write + + Add1 + Adds 1 hour to the current time. This can be used for summer time change outside initialization mode + 1 + + + + + TSIE + Time-stamp interrupt + enable + 15 + 1 + + TSIE + read-write + + Disabled + Time-stamp Interrupt disabled + 0 + + + Enabled + Time-stamp Interrupt enabled + 1 + + + + + WUTIE + Wakeup timer interrupt + enable + 14 + 1 + + WUTIE + read-write + + Disabled + Wakeup timer interrupt disabled + 0 + + + Enabled + Wakeup timer interrupt enabled + 1 + + + + + ALRBIE + Alarm B interrupt enable + 13 + 1 + + ALRBIE + read-write + + Disabled + Alarm B Interrupt disabled + 0 + + + Enabled + Alarm B Interrupt enabled + 1 + + + + + ALRAIE + Alarm A interrupt enable + 12 + 1 + + ALRAIE + read-write + + Disabled + Alarm A interrupt disabled + 0 + + + Enabled + Alarm A interrupt enabled + 1 + + + + + TSE + Time stamp enable + 11 + 1 + + TSE + read-write + + Disabled + Timestamp disabled + 0 + + + Enabled + Timestamp enabled + 1 + + + + + WUTE + Wakeup timer enable + 10 + 1 + + WUTE + read-write + + Disabled + Wakeup timer disabled + 0 + + + Enabled + Wakeup timer enabled + 1 + + + + + ALRBE + Alarm B enable + 9 + 1 + + ALRBE + read-write + + Disabled + Alarm B disabled + 0 + + + Enabled + Alarm B enabled + 1 + + + + + ALRAE + Alarm A enable + 8 + 1 + + ALRAE + read-write + + Disabled + Alarm A disabled + 0 + + + Enabled + Alarm A enabled + 1 + + + + + DCE + Coarse digital calibration + enable + 7 + 1 + + + FMT + Hour format + 6 + 1 + + FMT + read-write + + Twenty_Four_Hour + 24 hour/day format + 0 + + + AM_PM + AM/PM hour format + 1 + + + + + BYPSHAD + Bypass the shadow + registers + 5 + 1 + + BYPSHAD + read-write + + ShadowReg + Calendar values (when reading from RTC_SSR, RTC_TR, and RTC_DR) are taken from the shadow registers, which are updated once every two RTCCLK cycles + 0 + + + BypassShadowReg + Calendar values (when reading from RTC_SSR, RTC_TR, and RTC_DR) are taken directly from the calendar counters + 1 + + + + + REFCKON + Reference clock detection enable (50 or + 60 Hz) + 4 + 1 + + REFCKON + read-write + + Disabled + RTC_REFIN detection disabled + 0 + + + Enabled + RTC_REFIN detection enabled + 1 + + + + + TSEDGE + Time-stamp event active + edge + 3 + 1 + + TSEDGE + read-write + + RisingEdge + RTC_TS input rising edge generates a time-stamp event + 0 + + + FallingEdge + RTC_TS input falling edge generates a time-stamp event + 1 + + + + + WUCKSEL + Wakeup clock selection + 0 + 3 + + WUCKSEL + read-write + + Div16 + RTC/16 clock is selected + 0 + + + Div8 + RTC/8 clock is selected + 1 + + + Div4 + RTC/4 clock is selected + 2 + + + Div2 + RTC/2 clock is selected + 3 + + + ClockSpare + ck_spre (usually 1 Hz) clock is selected + 4 + + + ClockSpareWithOffset + ck_spre (usually 1 Hz) clock is selected and 2^16 is added to the WUT counter value + 6 + + + + + + + ISR + ISR + initialization and status + register + 0xC + 0x20 + 0x00000007 + + + ALRAWF + Alarm A write flag + 0 + 1 + read-only + + ALRAWFR + read + + UpdateNotAllowed + Alarm update not allowed + 0 + + + UpdateAllowed + Alarm update allowed + 1 + + + + + ALRBWF + Alarm B write flag + 1 + 1 + read-only + + + + WUTWF + Wakeup timer write flag + 2 + 1 + read-only + + WUTWFR + read + + UpdateNotAllowed + Wakeup timer configuration update not allowed + 0 + + + UpdateAllowed + Wakeup timer configuration update allowed + 1 + + + + + SHPF + Shift operation pending + 3 + 1 + read-write + + SHPFR + read + + NoShiftPending + No shift operation is pending + 0 + + + ShiftPending + A shift operation is pending + 1 + + + + + INITS + Initialization status flag + 4 + 1 + read-only + + INITSR + read + + NotInitalized + Calendar has not been initialized + 0 + + + Initalized + Calendar has been initialized + 1 + + + + + RSF + Registers synchronization + flag + 5 + 1 + read-write + zeroToClear + + RSFR + read + + NotSynced + Calendar shadow registers not yet synchronized + 0 + + + Synced + Calendar shadow registers synchronized + 1 + + + + RSFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + INITF + Initialization flag + 6 + 1 + read-only + + INITFR + read + + NotAllowed + Calendar registers update is not allowed + 0 + + + Allowed + Calendar registers update is allowed + 1 + + + + + INIT + Initialization mode + 7 + 1 + read-write + + INIT + read-write + + FreeRunningMode + Free running mode + 0 + + + InitMode + Initialization mode used to program time and date register (RTC_TR and RTC_DR), and prescaler register (RTC_PRER). Counters are stopped and start counting from the new value when INIT is reset. + 1 + + + + + ALRAF + Alarm A flag + 8 + 1 + read-write + zeroToClear + + ALRAFR + read + + Match + This flag is set by hardware when the time/date registers (RTC_TR and RTC_DR) match the Alarm A register (RTC_ALRMAR) + 1 + + + + ALRAFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + ALRBF + Alarm B flag + 9 + 1 + read-write + zeroToClear + + ALRBFR + read + + Match + This flag is set by hardware when the time/date registers (RTC_TR and RTC_DR) match the Alarm B register (RTC_ALRMBR) + 1 + + + + ALRBFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + WUTF + Wakeup timer flag + 10 + 1 + read-write + zeroToClear + + WUTFR + read + + Zero + This flag is set by hardware when the wakeup auto-reload counter reaches 0 + 1 + + + + WUTFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + TSF + Time-stamp flag + 11 + 1 + read-write + zeroToClear + + TSFR + read + + TimestampEvent + This flag is set by hardware when a time-stamp event occurs + 1 + + + + TSFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + TSOVF + Time-stamp overflow flag + 12 + 1 + read-write + zeroToClear + + TSOVFR + read + + Overflow + This flag is set by hardware when a time-stamp event occurs while TSF is already set + 1 + + + + TSOVFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + TAMP1F + Tamper detection flag + 13 + 1 + read-write + zeroToClear + + TAMP1FR + read + + Tampered + This flag is set by hardware when a tamper detection event is detected on the RTC_TAMPx input + 1 + + + + TAMP1FW + write + + Clear + Flag cleared by software writing 0 + 0 + + + + + TAMP2F + TAMPER2 detection flag + 14 + 1 + read-write + zeroToClear + + read + + + write + + + + RECALPF + Recalibration pending Flag + 16 + 1 + read-only + + RECALPFR + read + + Pending + The RECALPF status flag is automatically set to 1 when software writes to the RTC_CALR register, indicating that the RTC_CALR register is blocked. When the new calibration settings are taken into account, this bit returns to 0 + 1 + + + + + + + PRER + PRER + prescaler register + 0x10 + 0x20 + read-write + 0x007F00FF + + + PREDIV_A + Asynchronous prescaler + factor + 16 + 7 + + + 0 + 127 + + + + + PREDIV_S + Synchronous prescaler + factor + 0 + 15 + + + 0 + 32767 + + + + + + + WUTR + WUTR + wakeup timer register + 0x14 + 0x20 + read-write + 0x0000FFFF + + + WUT + Wakeup auto-reload value + bits + 0 + 16 + + + 0 + 65535 + + + + + + + CALIBR + CALIBR + calibration register + 0x18 + 0x20 + read-write + 0x00000000 + + + DCS + Digital calibration sign + 7 + 1 + + + DC + Digital calibration + 0 + 5 + + + + + 2 + 0x4 + A,B + ALRM%sR + ALRMAR + Alarm register + 0x1C + 0x20 + read-write + 0x00000000 + + + MSK4 + Alarm date mask + 31 + 1 + + + + WDSEL + Week day selection + 30 + 1 + + WDSEL + read-write + + DateUnits + DU[3:0] represents the date units + 0 + + + WeekDay + DU[3:0] represents the week day. DT[1:0] is don’t care. + 1 + + + + + DT + Date tens in BCD format + 28 + 2 + + + 0 + 3 + + + + + DU + Date units or day in BCD format + 24 + 4 + + + 0 + 15 + + + + + MSK3 + Alarm hours mask + 23 + 1 + + + + PM + AM/PM notation + 22 + 1 + + PM + read-write + + AM + AM or 24-hour format + 0 + + + PM + PM + 1 + + + + + HT + Hour tens in BCD format + 20 + 2 + + + 0 + 3 + + + + + HU + Hour units in BCD format + 16 + 4 + + + 0 + 15 + + + + + MSK2 + Alarm minutes mask + 15 + 1 + + + + MNT + Minute tens in BCD format + 12 + 3 + + + 0 + 7 + + + + + MNU + Minute units in BCD format + 8 + 4 + + + 0 + 15 + + + + + MSK1 + Alarm seconds mask + 7 + 1 + + MSK1 + read-write + + Mask + Alarm set if the date/day match + 0 + + + NotMask + Date/day don’t care in Alarm comparison + 1 + + + + + ST + Second tens in BCD format + 4 + 3 + + + 0 + 7 + + + + + SU + Second units in BCD format + 0 + 4 + + + 0 + 15 + + + + + + + WPR + WPR + write protection register + 0x24 + 0x20 + write-only + 0x00000000 + + + KEY + Write protection key + 0 + 8 + + + 0 + 255 + + + + + + + SSR + SSR + sub second register + 0x28 + 0x20 + read-only + 0x00000000 + + + SS + Sub second value + 0 + 16 + + + 0 + 65535 + + + + + + + SHIFTR + SHIFTR + shift control register + 0x2C + 0x20 + write-only + 0x00000000 + + + ADD1S + Add one second + 31 + 1 + + ADD1SW + write + + Add1 + Add one second to the clock/calendar + 1 + + + + + SUBFS + Subtract a fraction of a + second + 0 + 15 + + + 0 + 32767 + + + + + + + TSTR + TSTR + time stamp time register + 0x30 + + + TSDR + TSDR + time stamp date register + 0x34 + + + TSSSR + TSSSR + timestamp sub second register + 0x38 + + + CALR + CALR + calibration register + 0x3C + 0x20 + read-write + 0x00000000 + + + CALP + Increase frequency of RTC by 488.5 + ppm + 15 + 1 + + CALP + read-write + + NoChange + No RTCCLK pulses are added + 0 + + + IncreaseFreq + One RTCCLK pulse is effectively inserted every 2^11 pulses (frequency increased by 488.5 ppm) + 1 + + + + + CALW8 + Use an 8-second calibration cycle + period + 14 + 1 + + CALW8 + read-write + + Eight_Second + When CALW8 is set to ‘1’, the 8-second calibration cycle period is selected + 1 + + + + + CALW16 + Use a 16-second calibration cycle + period + 13 + 1 + + CALW16 + read-write + + Sixteen_Second + When CALW16 is set to ‘1’, the 16-second calibration cycle period is selected.This bit must not be set to ‘1’ if CALW8=1 + 1 + + + + + CALM + Calibration minus + 0 + 9 + + + 0 + 511 + + + + + + + TAFCR + TAFCR + tamper and alternate function configuration + register + 0x40 + 0x20 + read-write + 0x00000000 + + + ALARMOUTTYPE + AFO_ALARM output type + 18 + 1 + + + TSINSEL + TIMESTAMP mapping + 17 + 1 + + + TAMP1INSEL + TAMPER1 mapping + 16 + 1 + + + TAMPPUDIS + TAMPER pull-up disable + 15 + 1 + + + TAMPPRCH + Tamper precharge duration + 13 + 2 + + + TAMPFLT + Tamper filter count + 11 + 2 + + + TAMPFREQ + Tamper sampling frequency + 8 + 3 + + + TAMPTS + Activate timestamp on tamper detection + event + 7 + 1 + + + TAMP2TRG + Active level for tamper 2 + 4 + 1 + + + TAMP2E + Tamper 2 detection enable + 3 + 1 + + + TAMPIE + Tamper interrupt enable + 2 + 1 + + + TAMP1TRG + Active level for tamper 1 + 1 + 1 + + + TAMP1E + Tamper 1 detection enable + 0 + 1 + + + + + 2 + 0x4 + A,B + ALRM%sSSR + ALRMASSR + Alarm sub-second register + 0x44 + 0x20 + read-write + 0x00000000 + + + MASKSS + Mask the most-significant bits starting + at this bit + 24 + 4 + + + 0 + 15 + + + + + SS + Sub seconds value + 0 + 15 + + + 0 + 32767 + + + + + + + 20 + 0x4 + 0-19 + BKP%sR + BKP0R + backup register + 0x50 + 0x20 + read-write + 0x00000000 + + + BKP + BKP + 0 + 32 + + + 0 + 4294967295 + + + + + + + + + SDIO + Secure digital input/output + interface + SDIO + 0x40012C00 + + 0x0 + 0x400 + registers + + + I2C3_EV + I2C3 event interrupt + 72 + + + I2C3_ER + I2C3 error interrupt + 73 + + + + POWER + POWER + power control register + 0x0 + 0x20 + read-write + 0x00000000 + + + PWRCTRL + PWRCTRL + 0 + 2 + + PWRCTRL + read-write + + PowerOff + Power off + 0 + + + PowerOn + Power on + 3 + + + + + + + CLKCR + CLKCR + SDI clock control register + 0x4 + 0x20 + read-write + 0x00000000 + + + HWFC_EN + HW Flow Control enable + 14 + 1 + + HWFC_EN + read-write + + Disabled + HW Flow Control is disabled + 0 + + + Enabled + HW Flow Control is enabled + 1 + + + + + NEGEDGE + SDIO_CK dephasing selection + bit + 13 + 1 + + NEGEDGE + read-write + + Rising + SDIO_CK generated on the rising edge + 0 + + + Falling + SDIO_CK generated on the falling edge + 1 + + + + + WIDBUS + Wide bus mode enable bit + 11 + 2 + + WIDBUS + read-write + + BusWidth1 + 1 lane wide bus + 0 + + + BusWidth4 + 4 lane wide bus + 1 + + + BusWidth8 + 8 lane wide bus + 2 + + + + + BYPASS + Clock divider bypass enable + bit + 10 + 1 + + BYPASS + read-write + + Disabled + SDIOCLK is divided according to the CLKDIV value before driving the SDIO_CK output signal. + 0 + + + Enabled + SDIOCLK directly drives the SDIO_CK output signal + 1 + + + + + PWRSAV + Power saving configuration + bit + 9 + 1 + + PWRSAV + read-write + + Enabled + SDIO_CK clock is always enabled + 0 + + + Disabled + SDIO_CK is only enabled when the bus is active + 1 + + + + + CLKEN + Clock enable bit + 8 + 1 + + CLKEN + read-write + + Disabled + Disable clock + 0 + + + Enabled + Enable clock + 1 + + + + + CLKDIV + Clock divide factor + 0 + 8 + + + 0 + 255 + + + + + + + ARG + ARG + argument register + 0x8 + 0x20 + read-write + 0x00000000 + + + CMDARG + Command argument + 0 + 32 + + + 0 + 4294967295 + + + + + + + CMD + CMD + command register + 0xC + 0x20 + read-write + 0x00000000 + + + CE_ATACMD + CE-ATA command + 14 + 1 + + CE_ATACMD + read-write + + Disabled + CE-ATA command disabled + 0 + + + Enabled + CE-ATA command enabled + 1 + + + + + nIEN + not Interrupt Enable + 13 + 1 + + nIEN + read-write + + Disabled + Interrupts to the CE-ATA not disabled + 0 + + + Enabled + Interrupt to the CE-ATA are disabled + 1 + + + + + ENCMDcompl + Enable CMD completion + 12 + 1 + + ENCMDcompl + read-write + + Disabled + Command complete signal disabled + 0 + + + Enabled + Command complete signal enabled + 1 + + + + + SDIOSuspend + SD I/O suspend command + 11 + 1 + + SDIOSuspend + read-write + + Disabled + Next command is not a SDIO suspend command + 0 + + + Enabled + Next command send is a SDIO suspend command + 1 + + + + + CPSMEN + Command path state machine (CPSM) Enable + bit + 10 + 1 + + CPSMEN + read-write + + Disabled + Command path state machine disabled + 0 + + + Enabled + Command path state machine enabled + 1 + + + + + WAITPEND + CPSM Waits for ends of data transfer + (CmdPend internal signal). + 9 + 1 + + WAITPEND + read-write + + Disabled + Don't wait for data end + 0 + + + Enabled + Wait for end of data transfer signal before sending command + 1 + + + + + WAITINT + CPSM waits for interrupt + request + 8 + 1 + + WAITINT + read-write + + Disabled + Don't wait for interrupt request + 0 + + + Enabled + Wait for interrupt request + 1 + + + + + WAITRESP + Wait for response bits + 6 + 2 + + WAITRESP + read-write + + NoResponse + No response + 0 + + + ShortResponse + Short response + 1 + + + NoResponse2 + No reponse + 2 + + + LongResponse + Long reponse + 3 + + + + + CMDINDEX + Command index + 0 + 6 + + + 0 + 63 + + + + + + + RESPCMD + RESPCMD + command response register + 0x10 + 0x20 + read-only + 0x00000000 + + + RESPCMD + Response command index + 0 + 6 + + + 0 + 63 + + + + + + + RESP1 + RESP1 + response 1..4 register + 0x14 + 0x20 + read-only + 0x00000000 + + + CARDSTATUS1 + Card Status + 0 + 32 + + + 0 + 4294967295 + + + + + + + RESP2 + RESP2 + response 1..4 register + 0x18 + 0x20 + read-only + 0x00000000 + + + CARDSTATUS2 + Card Status + 0 + 32 + + + 0 + 4294967295 + + + + + + + RESP3 + RESP3 + response 1..4 register + 0x1C + 0x20 + read-only + 0x00000000 + + + CARDSTATUS3 + Card Status + 0 + 32 + + + 0 + 4294967295 + + + + + + + RESP4 + RESP4 + response 1..4 register + 0x20 + 0x20 + read-only + 0x00000000 + + + CARDSTATUS4 + Card Status + 0 + 32 + + + 0 + 4294967295 + + + + + + + DTIMER + DTIMER + data timer register + 0x24 + 0x20 + read-write + 0x00000000 + + + DATATIME + Data timeout period + 0 + 32 + + + 0 + 4294967295 + + + + + + + DLEN + DLEN + data length register + 0x28 + 0x20 + read-write + 0x00000000 + + + DATALENGTH + Data length value + 0 + 25 + + + 0 + 33554431 + + + + + + + DCTRL + DCTRL + data control register + 0x2C + 0x20 + read-write + 0x00000000 + + + SDIOEN + SD I/O enable functions + 11 + 1 + + SDIOEN + read-write + + Disabled + SDIO operations disabled + 0 + + + Enabled + SDIO operations enabled + 1 + + + + + RWMOD + Read wait mode + 10 + 1 + + RWMOD + read-write + + D2 + Read wait control stopping using SDIO_D2 + 0 + + + Ck + Read wait control using SDIO_CK + 1 + + + + + RWSTOP + Read wait stop + 9 + 1 + + RWSTOP + read-write + + Disabled + Read wait in progress if RWSTART is enabled + 0 + + + Enabled + Enable for read wait stop if RWSTART is enabled + 1 + + + + + RWSTART + Read wait start + 8 + 1 + + RWSTART + read-write + + Disabled + Don't start read wait operation + 0 + + + Enabled + Read wait operation starts + 1 + + + + + DBLOCKSIZE + Data block size + 4 + 4 + + + 0 + 15 + + + + + DMAEN + DMA enable bit + 3 + 1 + + DMAEN + read-write + + Disabled + Dma disabled + 0 + + + Enabled + Dma enabled + 1 + + + + + DTMODE + Data transfer mode selection 1: Stream + or SDIO multibyte data transfer. + 2 + 1 + + DTMODE + read-write + + BlockMode + Bloack data transfer + 0 + + + StreamMode + Stream or SDIO multibyte data transfer + 1 + + + + + DTDIR + Data transfer direction + selection + 1 + 1 + + DTDIR + read-write + + ControllerToCard + From controller to card + 0 + + + CardToController + From card to controller + 1 + + + + + DTEN + DTEN + 0 + 1 + + DTEN + read-write + + Disabled + Disabled + 0 + + + Enabled + Start transfer + 1 + + + + + + + DCOUNT + DCOUNT + data counter register + 0x30 + 0x20 + read-only + 0x00000000 + + + DATACOUNT + Data count value + 0 + 25 + + + 0 + 33554431 + + + + + + + STA + STA + status register + 0x34 + 0x20 + read-only + 0x00000000 + + + CEATAEND + CE-ATA command completion signal + received for CMD61 + 23 + 1 + + CEATAEND + read + + NotReceived + Completion signal not received + 0 + + + Received + CE-ATA command completion signal received for CMD61 + 1 + + + + + SDIOIT + SDIO interrupt received + 22 + 1 + + SDIOIT + read + + NotReceived + SDIO interrupt not receieved + 0 + + + Received + SDIO interrupt received + 1 + + + + + RXDAVL + Data available in receive + FIFO + 21 + 1 + + RXDAVL + read + + NotAvailable + Data not available in receive FIFO + 0 + + + Available + Data available in receive FIFO + 1 + + + + + TXDAVL + Data available in transmit + FIFO + 20 + 1 + + TXDAVL + read + + NotAvailable + Data not available in transmit FIFO + 0 + + + Available + Data available in transmit FIFO + 1 + + + + + RXFIFOE + Receive FIFO empty + 19 + 1 + + RXFIFOE + read + + NotEmpty + Receive FIFO not empty + 0 + + + Empty + Receive FIFO empty + 1 + + + + + TXFIFOE + Transmit FIFO empty + 18 + 1 + + TXFIFOE + read + + NotEmpty + Transmit FIFO not empty + 0 + + + Empty + Transmit FIFO empty. When HW Flow Control is enabled, TXFIFOE signals becomes activated when the FIFO contains 2 words. + 1 + + + + + RXFIFOF + Receive FIFO full + 17 + 1 + + RXFIFOF + read + + NotFull + Transmit FIFO not full + 0 + + + Full + Receive FIFO full. When HW Flow Control is enabled, RXFIFOF signals becomes activated 2 words before the FIFO is full. + 1 + + + + + TXFIFOF + Transmit FIFO full + 16 + 1 + + TXFIFOF + read + + NotFull + Transmit FIFO not full + 0 + + + Full + Transmit FIFO full + 1 + + + + + RXFIFOHF + Receive FIFO half full: there are at + least 8 words in the FIFO + 15 + 1 + + RXFIFOHF + read + + NotHalfFull + Receive FIFO not half full + 0 + + + HalfFull + Receive FIFO half full. At least 8 words in the FIFO + 1 + + + + + TXFIFOHE + Transmit FIFO half empty: at least 8 + words can be written into the FIFO + 14 + 1 + + TXFIFOHE + read + + NotHalfEmpty + Transmit FIFO not half empty + 0 + + + HalfEmpty + Transmit FIFO half empty. At least 8 words can be written into the FIFO + 1 + + + + + RXACT + Data receive in progress + 13 + 1 + + RXACT + read + + NotInProgress + Data receive not in progress + 0 + + + InProgress + Data receive in progress + 1 + + + + + TXACT + Data transmit in progress + 12 + 1 + + TXACT + read + + NotInProgress + Data transmit is not in progress + 0 + + + InProgress + Data transmit in progress + 1 + + + + + CMDACT + Command transfer in + progress + 11 + 1 + + CMDACT + read + + NotInProgress + Command transfer not in progress + 0 + + + InProgress + Command tranfer in progress + 1 + + + + + DBCKEND + Data block sent/received (CRC check + passed) + 10 + 1 + + DBCKEND + read + + NotTransferred + Data block not sent/received (CRC check failed) + 0 + + + Transferred + Data block sent/received (CRC check passed) + 1 + + + + + STBITERR + Start bit not detected on all data + signals in wide bus mode + 9 + 1 + + STBITERR + read + + Detected + No start bit detected error + 0 + + + NotDetected + Start bit not detected error + 1 + + + + + DATAEND + Data end (data counter, SDIDCOUNT, is + zero) + 8 + 1 + + DATAEND + read + + NotDone + Not done + 0 + + + Done + Data end (DCOUNT, is zero) + 1 + + + + + CMDSENT + Command sent (no response + required) + 7 + 1 + + CMDSENT + read + + NotSent + Command not sent + 0 + + + Sent + Command sent (no response required) + 1 + + + + + CMDREND + Command response received (CRC check + passed) + 6 + 1 + + CMDREND + read + + NotDone + Command not done + 0 + + + Done + Command response received (CRC check passed) + 1 + + + + + RXOVERR + Received FIFO overrun + error + 5 + 1 + + RXOVERR + read + + NoOverrun + No FIFO overrun error + 0 + + + Overrun + Receive FIFO overrun error + 1 + + + + + TXUNDERR + Transmit FIFO underrun + error + 4 + 1 + + TXUNDERR + read + + NoUnderrun + No transmit FIFO underrun error + 0 + + + Underrun + Transmit FIFO underrun error + 1 + + + + + DTIMEOUT + Data timeout + 3 + 1 + + DTIMEOUT + read + + NoTimeout + No data timeout + 0 + + + Timeout + Data timeout + 1 + + + + + CTIMEOUT + Command response timeout + 2 + 1 + + CTIMEOUT + read + + NoTimeout + No Command timeout + 0 + + + Timeout + Command timeout + 1 + + + + + DCRCFAIL + Data block sent/received (CRC check + failed) + 1 + 1 + + DCRCFAIL + read + + NotFailed + No Data block sent/received crc check fail + 0 + + + Failed + Data block sent/received crc failed + 1 + + + + + CCRCFAIL + Command response received (CRC check + failed) + 0 + 1 + + CCRCFAIL + read + + NotFailed + Command response received, crc check passed + 0 + + + Failed + Command response received, crc check failed + 1 + + + + + + + ICR + ICR + interrupt clear register + 0x38 + 0x20 + read-write + 0x00000000 + + + CEATAENDC + CEATAEND flag clear bit + 23 + 1 + + + + SDIOITC + SDIOIT flag clear bit + 22 + 1 + + + + DBCKENDC + DBCKEND flag clear bit + 10 + 1 + + + + STBITERRC + STBITERR flag clear bit + 9 + 1 + + + + DATAENDC + DATAEND flag clear bit + 8 + 1 + + + + CMDSENTC + CMDSENT flag clear bit + 7 + 1 + + + + CMDRENDC + CMDREND flag clear bit + 6 + 1 + + + + RXOVERRC + RXOVERR flag clear bit + 5 + 1 + + + + TXUNDERRC + TXUNDERR flag clear bit + 4 + 1 + + + + DTIMEOUTC + DTIMEOUT flag clear bit + 3 + 1 + + + + CTIMEOUTC + CTIMEOUT flag clear bit + 2 + 1 + + + + DCRCFAILC + DCRCFAIL flag clear bit + 1 + 1 + + + + CCRCFAILC + CCRCFAIL flag clear bit + 0 + 1 + + CCRCFAILCW + write + + Clear + Clear flag + 1 + + + + + + + MASK + MASK + mask register + 0x3C + 0x20 + read-write + 0x00000000 + + + CEATAENDIE + CE-ATA command completion signal + received interrupt enable + 23 + 1 + + + + SDIOITIE + SDIO mode interrupt received interrupt + enable + 22 + 1 + + + + RXDAVLIE + Data available in Rx FIFO interrupt + enable + 21 + 1 + + + + TXDAVLIE + Data available in Tx FIFO interrupt + enable + 20 + 1 + + + + RXFIFOEIE + Rx FIFO empty interrupt + enable + 19 + 1 + + + + TXFIFOEIE + Tx FIFO empty interrupt + enable + 18 + 1 + + + + RXFIFOFIE + Rx FIFO full interrupt + enable + 17 + 1 + + + + TXFIFOFIE + Tx FIFO full interrupt + enable + 16 + 1 + + + + RXFIFOHFIE + Rx FIFO half full interrupt + enable + 15 + 1 + + + + TXFIFOHEIE + Tx FIFO half empty interrupt + enable + 14 + 1 + + + + RXACTIE + Data receive acting interrupt + enable + 13 + 1 + + + + TXACTIE + Data transmit acting interrupt + enable + 12 + 1 + + + + CMDACTIE + Command acting interrupt + enable + 11 + 1 + + + + DBCKENDIE + Data block end interrupt + enable + 10 + 1 + + + + STBITERRIE + Start bit error interrupt + enable + 9 + 1 + + + + DATAENDIE + Data end interrupt enable + 8 + 1 + + + + CMDSENTIE + Command sent interrupt + enable + 7 + 1 + + + + CMDRENDIE + Command response received interrupt + enable + 6 + 1 + + + + RXOVERRIE + Rx FIFO overrun error interrupt + enable + 5 + 1 + + + + TXUNDERRIE + Tx FIFO underrun error interrupt + enable + 4 + 1 + + + + DTIMEOUTIE + Data timeout interrupt + enable + 3 + 1 + + + + CTIMEOUTIE + Command timeout interrupt + enable + 2 + 1 + + + + DCRCFAILIE + Data CRC fail interrupt + enable + 1 + 1 + + + + CCRCFAILIE + Command CRC fail interrupt + enable + 0 + 1 + + CCRCFAILIE + read-write + + Disabled + Interrupt disabled + 0 + + + Enabled + Interrupt enabled + 1 + + + + + + + FIFOCNT + FIFOCNT + FIFO counter register + 0x48 + 0x20 + read-only + 0x00000000 + + + FIFOCOUNT + Remaining number of words to be written + to or read from the FIFO. + 0 + 24 + + + 0 + 16777215 + + + + + + + FIFO + FIFO + data FIFO register + 0x80 + 0x20 + read-write + 0x00000000 + + + FIFOData + Receive and transmit FIFO + data + 0 + 32 + + + 0 + 4294967295 + + + + + + + + + SYSCFG + System configuration controller + SYSCFG + 0x40013800 + + 0x0 + 0x400 + registers + + + + MEMRM + MEMRM + memory remap register + 0x0 + 0x20 + read-write + 0x00000000 + + + MEM_MODE + MEM_MODE + 0 + 2 + + + + + PMC + PMC + peripheral mode configuration + register + 0x4 + 0x20 + read-write + 0x00000000 + + + ADC1DC2 + ADC1DC2 + 16 + 1 + + + + + EXTICR1 + EXTICR1 + external interrupt configuration register + 1 + 0x8 + 0x20 + read-write + 0x00000000 + + + EXTI3 + EXTI x configuration (x = 0 to + 3) + 12 + 4 + + + EXTI2 + EXTI x configuration (x = 0 to + 3) + 8 + 4 + + + EXTI1 + EXTI x configuration (x = 0 to + 3) + 4 + 4 + + + EXTI0 + EXTI x configuration (x = 0 to + 3) + 0 + 4 + + + + + EXTICR2 + EXTICR2 + external interrupt configuration register + 2 + 0xC + 0x20 + read-write + 0x00000000 + + + EXTI7 + EXTI x configuration (x = 4 to + 7) + 12 + 4 + + + EXTI6 + EXTI x configuration (x = 4 to + 7) + 8 + 4 + + + EXTI5 + EXTI x configuration (x = 4 to + 7) + 4 + 4 + + + EXTI4 + EXTI x configuration (x = 4 to + 7) + 0 + 4 + + + + + EXTICR3 + EXTICR3 + external interrupt configuration register + 3 + 0x10 + 0x20 + read-write + 0x00000000 + + + EXTI11 + EXTI x configuration (x = 8 to + 11) + 12 + 4 + + + EXTI10 + EXTI10 + 8 + 4 + + + EXTI9 + EXTI x configuration (x = 8 to + 11) + 4 + 4 + + + EXTI8 + EXTI x configuration (x = 8 to + 11) + 0 + 4 + + + + + EXTICR4 + EXTICR4 + external interrupt configuration register + 4 + 0x14 + 0x20 + read-write + 0x00000000 + + + EXTI15 + EXTI x configuration (x = 12 to + 15) + 12 + 4 + + + EXTI14 + EXTI x configuration (x = 12 to + 15) + 8 + 4 + + + EXTI13 + EXTI x configuration (x = 12 to + 15) + 4 + 4 + + + EXTI12 + EXTI x configuration (x = 12 to + 15) + 0 + 4 + + + + + CMPCR + CMPCR + Compensation cell control + register + 0x20 + 0x20 + read-only + 0x00000000 + + + READY + READY + 8 + 1 + + + CMP_PD + Compensation cell + power-down + 0 + 1 + + + + + + + TIM1 + Advanced-timers + TIM + 0x40010000 + + 0x0 + 0x400 + registers + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + CMS + Center-aligned mode + selection + 5 + 2 + + CMS + read-write + + EdgeAligned + The counter counts up or down depending on the direction bit + 0 + + + CenterAligned1 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting down. + 1 + + + CenterAligned2 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting up. + 2 + + + CenterAligned3 + The counter counts up and down alternatively. Output compare interrupt flags are set both when the counter is counting up or down. + 3 + + + + + DIR + Direction + 4 + 1 + + DIR + read-write + + Up + Counter used as upcounter + 0 + + + Down + Counter used as downcounter + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + OIS4 + Output Idle state 4 + 14 + 1 + + + + OIS3N + Output Idle state 3 + 13 + 1 + + + + OIS3 + Output Idle state 3 + 12 + 1 + + + + OIS2N + Output Idle state 2 + 11 + 1 + + + + OIS2 + Output Idle state 2 + 10 + 1 + + + + OIS1N + Output Idle state 1 + 9 + 1 + + OIS1N + read-write + + Reset + OCxN=0 after a dead-time when MOE=0 + 0 + + + Set + OCxN=1 after a dead-time when MOE=0 + 1 + + + + + OIS1 + Output Idle state 1 + 8 + 1 + + OIS1 + read-write + + Reset + OCx=0 (after a dead-time if OCx(N) is implemented) when MOE=0 + 0 + + + Set + OCx=1 (after a dead-time if OCx(N) is implemented) when MOE=0 + 1 + + + + + TI1S + TI1 selection + 7 + 1 + + TI1S + read-write + + Normal + The TIMx_CH1 pin is connected to TI1 input + 0 + + + XOR + The TIMx_CH1, CH2, CH3 pins are connected to TI1 input + 1 + + + + + MMS + Master mode selection + 4 + 3 + + MMS + read-write + + Reset + The UG bit from the TIMx_EGR register is used as trigger output + 0 + + + Enable + The counter enable signal, CNT_EN, is used as trigger output + 1 + + + Update + The update event is selected as trigger output + 2 + + + ComparePulse + The trigger output send a positive pulse when the CC1IF flag it to be set, as soon as a capture or a compare match occurred + 3 + + + CompareOC1 + OC1REF signal is used as trigger output + 4 + + + CompareOC2 + OC2REF signal is used as trigger output + 5 + + + CompareOC3 + OC3REF signal is used as trigger output + 6 + + + CompareOC4 + OC4REF signal is used as trigger output + 7 + + + + + CCDS + Capture/compare DMA + selection + 3 + 1 + + CCDS + read-write + + OnCompare + CCx DMA request sent when CCx event occurs + 0 + + + OnUpdate + CCx DMA request sent when update event occurs + 1 + + + + + CCUS + Capture/compare control update + selection + 2 + 1 + + + CCPC + Capture/compare preloaded + control + 0 + 1 + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + ETP + External trigger polarity + 15 + 1 + + ETP + read-write + + NotInverted + ETR is noninverted, active at high level or rising edge + 0 + + + Inverted + ETR is inverted, active at low level or falling edge + 1 + + + + + ECE + External clock enable + 14 + 1 + + ECE + read-write + + Disabled + External clock mode 2 disabled + 0 + + + Enabled + External clock mode 2 enabled. The counter is clocked by any active edge on the ETRF signal. + 1 + + + + + ETPS + External trigger prescaler + 12 + 2 + + ETPS + read-write + + Div1 + Prescaler OFF + 0 + + + Div2 + ETRP frequency divided by 2 + 1 + + + Div4 + ETRP frequency divided by 4 + 2 + + + Div8 + ETRP frequency divided by 8 + 3 + + + + + ETF + External trigger filter + 8 + 4 + + ETF + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + MSM + Master/Slave mode + 7 + 1 + + MSM + read-write + + NoSync + No action + 0 + + + Sync + The effect of an event on the trigger input (TRGI) is delayed to allow a perfect synchronization between the current timer and its slaves (through TRGO). It is useful if we want to synchronize several timers on a single external event. + 1 + + + + + TS + Trigger selection + 4 + 3 + + TS + read-write + + ITR0 + Internal Trigger 0 (ITR0) + 0 + + + ITR1 + Internal Trigger 1 (ITR1) + 1 + + + ITR2 + Internal Trigger 2 (ITR2) + 2 + + + TI1F_ED + TI1 Edge Detector (TI1F_ED) + 4 + + + TI1FP1 + Filtered Timer Input 1 (TI1FP1) + 5 + + + TI2FP2 + Filtered Timer Input 2 (TI2FP2) + 6 + + + ETRF + External Trigger input (ETRF) + 7 + + + + + SMS + Slave mode selection + 0 + 3 + + SMS + read-write + + Disabled + Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal clock. + 0 + + + Encoder_Mode_1 + Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending on TI1FP2 level. + 1 + + + Encoder_Mode_2 + Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level. + 2 + + + Encoder_Mode_3 + Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. + 3 + + + Reset_Mode + Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and generates an update of the registers. + 4 + + + Gated_Mode + Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of the counter are controlled. + 5 + + + Trigger_Mode + Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not reset). Only the start of the counter is controlled. + 6 + + + Ext_Clock_Mode + External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter. + 7 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TDE + Trigger DMA request enable + 14 + 1 + + TDE + read-write + + Disabled + Trigger DMA request disabled + 0 + + + Enabled + Trigger DMA request enabled + 1 + + + + + COMDE + COM DMA request enable + 13 + 1 + + + CC4DE + Capture/Compare 4 DMA request + enable + 12 + 1 + + + + CC3DE + Capture/Compare 3 DMA request + enable + 11 + 1 + + + + CC2DE + Capture/Compare 2 DMA request + enable + 10 + 1 + + + + CC1DE + Capture/Compare 1 DMA request + enable + 9 + 1 + + CC1DE + read-write + + Disabled + CCx DMA request disabled + 0 + + + Enabled + CCx DMA request enabled + 1 + + + + + UDE + Update DMA request enable + 8 + 1 + + UDE + read-write + + Disabled + Update DMA request disabled + 0 + + + Enabled + Update DMA request enabled + 1 + + + + + BIE + Break interrupt enable + 7 + 1 + + + TIE + Trigger interrupt enable + 6 + 1 + + TIE + read-write + + Disabled + Trigger interrupt disabled + 0 + + + Enabled + Trigger interrupt enabled + 1 + + + + + COMIE + COM interrupt enable + 5 + 1 + + + CC4IE + Capture/Compare 4 interrupt + enable + 4 + 1 + + + + CC3IE + Capture/Compare 3 interrupt + enable + 3 + 1 + + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + CC1IE + read-write + + Disabled + CCx interrupt disabled + 0 + + + Enabled + CCx interrupt enabled + 1 + + + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC4OF + Capture/Compare 4 overcapture + flag + 12 + 1 + zeroToClear + + read + + + write + + + + CC3OF + Capture/Compare 3 overcapture + flag + 11 + 1 + zeroToClear + + read + + + write + + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + zeroToClear + + read + + + write + + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + zeroToClear + + CC1OFR + read + + Overcapture + The counter value has been captured in TIMx_CCRx register while CCxIF flag was already set + 1 + + + + CC1OFW + write + + Clear + Clear flag + 0 + + + + + BIF + Break interrupt flag + 7 + 1 + + + TIF + Trigger interrupt flag + 6 + 1 + zeroToClear + + TIFR + read + + NoTrigger + No trigger event occurred + 0 + + + Trigger + Trigger interrupt pending + 1 + + + + TIFW + write + + Clear + Clear flag + 0 + + + + + COMIF + COM interrupt flag + 5 + 1 + + + CC4IF + Capture/Compare 4 interrupt + flag + 4 + 1 + zeroToClear + + read + + + write + + + + CC3IF + Capture/Compare 3 interrupt + flag + 3 + 1 + zeroToClear + + read + + + write + + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + zeroToClear + + read + + + write + + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + zeroToClear + + CC1IFR + read + + Match + If CC1 is an output: The content of the counter TIMx_CNT matches the content of the TIMx_CCR1 register. If CC1 is an input: The counter value has been captured in TIMx_CCR1 register. + 1 + + + + CC1IFW + write + + Clear + Clear flag + 0 + + + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + BG + Break generation + 7 + 1 + + + TG + Trigger generation + 6 + 1 + + TGW + write + + Trigger + The TIF flag is set in TIMx_SR register. Related interrupt or DMA transfer can occur if enabled. + 1 + + + + + COMG + Capture/Compare control update + generation + 5 + 1 + + + CC4G + Capture/compare 4 + generation + 4 + 1 + + + + CC3G + Capture/compare 3 + generation + 3 + 1 + + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + CC1GW + write + + Trigger + If CC1 is an output: CC1IF flag is set, Corresponding interrupt or DMA request is sent if enabled. If CC1 is an input: The current value of the counter is captured in TIMx_CCR1 register. + 1 + + + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2CE + Output Compare 2 clear + enable + 15 + 1 + + + OC2M + Output Compare 2 mode + 12 + 3 + + + + OC2PE + Output Compare 2 preload + enable + 11 + 1 + + OC2PE + read-write + + Disabled + Preload register on CCR2 disabled. New values written to CCR2 are taken into account immediately + 0 + + + Enabled + Preload register on CCR2 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC2FE + Output Compare 2 fast + enable + 10 + 1 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + Output + CC2 channel is configured as output + 0 + + + + + OC1CE + Output Compare 1 clear + enable + 7 + 1 + + + OC1M + Output Compare 1 mode + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + Output Compare 1 preload + enable + 3 + 1 + + OC1PE + read-write + + Disabled + Preload register on CCR1 disabled. New values written to CCR1 are taken into account immediately + 0 + + + Enabled + Preload register on CCR1 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC1FE + Output Compare 1 fast + enable + 2 + 1 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + Output + CC1 channel is configured as output + 0 + + + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 4 + + + 0 + 15 + + + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + TI2 + CC2 channel is configured as input, IC2 is mapped on TI2 + 1 + + + TI1 + CC2 channel is configured as input, IC2 is mapped on TI1 + 2 + + + TRC + CC2 channel is configured as input, IC2 is mapped on TRC + 3 + + + + + IC1F + Input capture 1 filter + 4 + 4 + + IC1F + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + TI1 + CC1 channel is configured as input, IC1 is mapped on TI1 + 1 + + + TI2 + CC1 channel is configured as input, IC1 is mapped on TI2 + 2 + + + TRC + CC1 channel is configured as input, IC1 is mapped on TRC + 3 + + + + + + + CCMR2_Output + CCMR2_Output + capture/compare mode register 2 (output + mode) + 0x1C + 0x20 + read-write + 0x00000000 + + + OC4CE + Output compare 4 clear + enable + 15 + 1 + + + OC4M + Output compare 4 mode + 12 + 3 + + + + OC4PE + Output compare 4 preload + enable + 11 + 1 + + OC4PE + read-write + + Disabled + Preload register on CCR4 disabled. New values written to CCR4 are taken into account immediately + 0 + + + Enabled + Preload register on CCR4 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC4FE + Output compare 4 fast + enable + 10 + 1 + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + Output + CC4 channel is configured as output + 0 + + + + + OC3CE + Output compare 3 clear + enable + 7 + 1 + + + OC3M + Output compare 3 mode + 4 + 3 + + OC3M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC3PE + Output compare 3 preload + enable + 3 + 1 + + OC3PE + read-write + + Disabled + Preload register on CCR3 disabled. New values written to CCR3 are taken into account immediately + 0 + + + Enabled + Preload register on CCR3 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC3FE + Output compare 3 fast + enable + 2 + 1 + + + CC3S + Capture/Compare 3 + selection + 0 + 2 + + CC3S + read-write + + Output + CC3 channel is configured as output + 0 + + + + + + + CCMR2_Input + CCMR2_Input + capture/compare mode register 2 (input + mode) + CCMR2_Output + 0x1C + 0x20 + read-write + 0x00000000 + + + IC4F + Input capture 4 filter + 12 + 4 + + + 0 + 15 + + + + + IC4PSC + Input capture 4 prescaler + 10 + 2 + + + 0 + 3 + + + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + TI4 + CC4 channel is configured as input, IC4 is mapped on TI4 + 1 + + + TI3 + CC4 channel is configured as input, IC4 is mapped on TI3 + 2 + + + TRC + CC4 channel is configured as input, IC4 is mapped on TRC + 3 + + + + + IC3F + Input capture 3 filter + 4 + 4 + + + 0 + 15 + + + + + IC3PSC + Input capture 3 prescaler + 2 + 2 + + + 0 + 3 + + + + + CC3S + Capture/compare 3 + selection + 0 + 2 + + CC3S + read-write + + TI3 + CC3 channel is configured as input, IC3 is mapped on TI3 + 1 + + + TI4 + CC3 channel is configured as input, IC3 is mapped on TI4 + 2 + + + TRC + CC3 channel is configured as input, IC3 is mapped on TRC + 3 + + + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC4P + Capture/Compare 3 output + Polarity + 13 + 1 + + + CC4E + Capture/Compare 4 output + enable + 12 + 1 + + + CC3NP + Capture/Compare 3 output + Polarity + 11 + 1 + + + CC3NE + Capture/Compare 3 complementary output + enable + 10 + 1 + + + CC3P + Capture/Compare 3 output + Polarity + 9 + 1 + + + CC3E + Capture/Compare 3 output + enable + 8 + 1 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2NE + Capture/Compare 2 complementary output + enable + 6 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1NE + Capture/Compare 1 complementary output + enable + 2 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + counter value + 0 + 16 + + + 0 + 65535 + + + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + 0 + 65535 + + + + + + + 4 + 0x4 + 1-4 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + 0 + 65535 + + + + + + + DCR + DCR + DMA control register + 0x48 + 0x20 + read-write + 0x00000000 + + + DBL + DMA burst length + 8 + 5 + + + 0 + 18 + + + + + DBA + DMA base address + 0 + 5 + + + 0 + 31 + + + + + + + DMAR + DMAR + DMA address for full transfer + 0x4C + 0x20 + read-write + 0x00000000 + + + DMAB + DMA register for burst + accesses + 0 + 16 + + + + + RCR + RCR + repetition counter register + 0x30 + 0x20 + read-write + 0x00000000 + + + REP + Repetition counter value + 0 + 8 + + + + + BDTR + BDTR + break and dead-time register + 0x44 + 0x20 + read-write + 0x00000000 + + + MOE + Main output enable + 15 + 1 + + MOE + read-write + + DisabledIdle + OC/OCN are disabled or forced idle depending on OSSI + 0 + + + Enabled + OC/OCN are enabled if CCxE/CCxNE are set + 1 + + + + + AOE + Automatic output enable + 14 + 1 + + AOE + read-write + + Manual + MOE can be set only by software + 0 + + + Automatic + MOE can be set by software or automatically at the next update event (if none of the break inputs BRK and BRK2 is active) + 1 + + + + + BKP + Break polarity + 13 + 1 + + BKP + read-write + + ActiveLow + Break input BRKx is active low + 0 + + + ActiveHigh + Break input BRKx is active high + 1 + + + + + BKE + Break enable + 12 + 1 + + BKE + read-write + + Disabled + Break function x disabled + 0 + + + Enabled + Break function x disabled + 1 + + + + + OSSR + Off-state selection for Run + mode + 11 + 1 + + OSSR + read-write + + Disabled + When inactive, OC/OCN outputs are disabled + 0 + + + IdleLevel + When inactive, OC/OCN outputs are enabled with their inactive level + 1 + + + + + OSSI + Off-state selection for Idle + mode + 10 + 1 + + OSSI + read-write + + Disabled + When inactive, OC/OCN outputs are disabled + 0 + + + IdleLevel + When inactive, OC/OCN outputs are forced to idle level + 1 + + + + + LOCK + Lock configuration + 8 + 2 + + LOCK + read-write + + Off + No bit is write protected + 0 + + + Level1 + Any bits except MOE, OSSR, OSSI and LOCK in TIMx_BDTR register, OISx and OISxN bits in TIMx_CR2 register can no longer be written + 1 + + + Level2 + LOCK Level 1 + CC Polarity bits (CCxP/CCxNP bits in TIMx_CCER register, as long as the related channel is configured in output through the CCxS bits) as well as OSSR and OSSI bits can no longer be written + 2 + + + Level3 + LOCK Level 2 + CC Control bits (OCxM and OCxPE bits in TIMx_CCMRx registers, as long as the related channel is configured in output through the CCxS bits) can no longer be written + 3 + + + + + DTG + Dead-time generator setup + 0 + 8 + + + 0 + 255 + + + + + + + + + TIM10 + General-purpose-timers + TIM + 0x40014400 + + 0x0 + 0x400 + registers + + + SPI1 + SPI1 global interrupt + 35 + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC1M + Output Compare 1 mode + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + Output Compare 1 preload + enable + 3 + 1 + + + OC1FE + Output Compare 1 fast + enable + 2 + 1 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC1F + Input capture 1 filter + 4 + 4 + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + counter value + 0 + 16 + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + + + 1 + 0x0 + 1-1 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + + + + + TIM11 + General-purpose-timers + TIM + 0x40014800 + + 0x0 + 0x400 + registers + + + SPI2 + SPI2 global interrupt + 36 + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC1M + Output Compare 1 mode + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + Output Compare 1 preload + enable + 3 + 1 + + + OC1FE + Output Compare 1 fast + enable + 2 + 1 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC1F + Input capture 1 filter + 4 + 4 + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + counter value + 0 + 16 + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + + + 1 + 0x0 + 1-1 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + + + OR + OR + option register + 0x50 + 0x20 + read-write + 0x00000000 + + + RMP + Input 1 remapping + capability + 0 + 2 + + + + + + + TIM2 + General purpose timers + TIM + 0x40000000 + + 0x0 + 0x400 + registers + + + SPI3 + SPI3 global interrupt + 51 + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + CMS + Center-aligned mode + selection + 5 + 2 + + CMS + read-write + + EdgeAligned + The counter counts up or down depending on the direction bit + 0 + + + CenterAligned1 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting down. + 1 + + + CenterAligned2 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting up. + 2 + + + CenterAligned3 + The counter counts up and down alternatively. Output compare interrupt flags are set both when the counter is counting up or down. + 3 + + + + + DIR + Direction + 4 + 1 + + DIR + read-write + + Up + Counter used as upcounter + 0 + + + Down + Counter used as downcounter + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + TI1S + TI1 selection + 7 + 1 + + TI1S + read-write + + Normal + The TIMx_CH1 pin is connected to TI1 input + 0 + + + XOR + The TIMx_CH1, CH2, CH3 pins are connected to TI1 input + 1 + + + + + MMS + Master mode selection + 4 + 3 + + MMS + read-write + + Reset + The UG bit from the TIMx_EGR register is used as trigger output + 0 + + + Enable + The counter enable signal, CNT_EN, is used as trigger output + 1 + + + Update + The update event is selected as trigger output + 2 + + + ComparePulse + The trigger output send a positive pulse when the CC1IF flag it to be set, as soon as a capture or a compare match occurred + 3 + + + CompareOC1 + OC1REF signal is used as trigger output + 4 + + + CompareOC2 + OC2REF signal is used as trigger output + 5 + + + CompareOC3 + OC3REF signal is used as trigger output + 6 + + + CompareOC4 + OC4REF signal is used as trigger output + 7 + + + + + CCDS + Capture/compare DMA + selection + 3 + 1 + + CCDS + read-write + + OnCompare + CCx DMA request sent when CCx event occurs + 0 + + + OnUpdate + CCx DMA request sent when update event occurs + 1 + + + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + ETP + External trigger polarity + 15 + 1 + + ETP + read-write + + NotInverted + ETR is noninverted, active at high level or rising edge + 0 + + + Inverted + ETR is inverted, active at low level or falling edge + 1 + + + + + ECE + External clock enable + 14 + 1 + + ECE + read-write + + Disabled + External clock mode 2 disabled + 0 + + + Enabled + External clock mode 2 enabled. The counter is clocked by any active edge on the ETRF signal. + 1 + + + + + ETPS + External trigger prescaler + 12 + 2 + + ETPS + read-write + + Div1 + Prescaler OFF + 0 + + + Div2 + ETRP frequency divided by 2 + 1 + + + Div4 + ETRP frequency divided by 4 + 2 + + + Div8 + ETRP frequency divided by 8 + 3 + + + + + ETF + External trigger filter + 8 + 4 + + ETF + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + MSM + Master/Slave mode + 7 + 1 + + MSM + read-write + + NoSync + No action + 0 + + + Sync + The effect of an event on the trigger input (TRGI) is delayed to allow a perfect synchronization between the current timer and its slaves (through TRGO). It is useful if we want to synchronize several timers on a single external event. + 1 + + + + + TS + Trigger selection + 4 + 3 + + TS + read-write + + ITR0 + Internal Trigger 0 (ITR0) + 0 + + + ITR1 + Internal Trigger 1 (ITR1) + 1 + + + ITR2 + Internal Trigger 2 (ITR2) + 2 + + + TI1F_ED + TI1 Edge Detector (TI1F_ED) + 4 + + + TI1FP1 + Filtered Timer Input 1 (TI1FP1) + 5 + + + TI2FP2 + Filtered Timer Input 2 (TI2FP2) + 6 + + + ETRF + External Trigger input (ETRF) + 7 + + + + + SMS + Slave mode selection + 0 + 3 + + SMS + read-write + + Disabled + Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal clock. + 0 + + + Encoder_Mode_1 + Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending on TI1FP2 level. + 1 + + + Encoder_Mode_2 + Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level. + 2 + + + Encoder_Mode_3 + Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. + 3 + + + Reset_Mode + Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and generates an update of the registers. + 4 + + + Gated_Mode + Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of the counter are controlled. + 5 + + + Trigger_Mode + Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not reset). Only the start of the counter is controlled. + 6 + + + Ext_Clock_Mode + External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter. + 7 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TDE + Trigger DMA request enable + 14 + 1 + + TDE + read-write + + Disabled + Trigger DMA request disabled + 0 + + + Enabled + Trigger DMA request enabled + 1 + + + + + CC4DE + Capture/Compare 4 DMA request + enable + 12 + 1 + + + + CC3DE + Capture/Compare 3 DMA request + enable + 11 + 1 + + + + CC2DE + Capture/Compare 2 DMA request + enable + 10 + 1 + + + + CC1DE + Capture/Compare 1 DMA request + enable + 9 + 1 + + CC1DE + read-write + + Disabled + CCx DMA request disabled + 0 + + + Enabled + CCx DMA request enabled + 1 + + + + + UDE + Update DMA request enable + 8 + 1 + + UDE + read-write + + Disabled + Update DMA request disabled + 0 + + + Enabled + Update DMA request enabled + 1 + + + + + TIE + Trigger interrupt enable + 6 + 1 + + TIE + read-write + + Disabled + Trigger interrupt disabled + 0 + + + Enabled + Trigger interrupt enabled + 1 + + + + + CC4IE + Capture/Compare 4 interrupt + enable + 4 + 1 + + + + CC3IE + Capture/Compare 3 interrupt + enable + 3 + 1 + + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + CC1IE + read-write + + Disabled + CCx interrupt disabled + 0 + + + Enabled + CCx interrupt enabled + 1 + + + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC4OF + Capture/Compare 4 overcapture + flag + 12 + 1 + zeroToClear + + read + + + write + + + + CC3OF + Capture/Compare 3 overcapture + flag + 11 + 1 + zeroToClear + + read + + + write + + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + zeroToClear + + read + + + write + + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + zeroToClear + + CC1OFR + read + + Overcapture + The counter value has been captured in TIMx_CCRx register while CCxIF flag was already set + 1 + + + + CC1OFW + write + + Clear + Clear flag + 0 + + + + + TIF + Trigger interrupt flag + 6 + 1 + zeroToClear + + TIFR + read + + NoTrigger + No trigger event occurred + 0 + + + Trigger + Trigger interrupt pending + 1 + + + + TIFW + write + + Clear + Clear flag + 0 + + + + + CC4IF + Capture/Compare 4 interrupt + flag + 4 + 1 + zeroToClear + + read + + + write + + + + CC3IF + Capture/Compare 3 interrupt + flag + 3 + 1 + zeroToClear + + read + + + write + + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + zeroToClear + + read + + + write + + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + zeroToClear + + CC1IFR + read + + Match + If CC1 is an output: The content of the counter TIMx_CNT matches the content of the TIMx_CCR1 register. If CC1 is an input: The counter value has been captured in TIMx_CCR1 register. + 1 + + + + CC1IFW + write + + Clear + Clear flag + 0 + + + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + TG + Trigger generation + 6 + 1 + + TGW + write + + Trigger + The TIF flag is set in TIMx_SR register. Related interrupt or DMA transfer can occur if enabled. + 1 + + + + + CC4G + Capture/compare 4 + generation + 4 + 1 + + + + CC3G + Capture/compare 3 + generation + 3 + 1 + + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + CC1GW + write + + Trigger + If CC1 is an output: CC1IF flag is set, Corresponding interrupt or DMA request is sent if enabled. If CC1 is an input: The current value of the counter is captured in TIMx_CCR1 register. + 1 + + + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2CE + OC2CE + 15 + 1 + + + OC2M + OC2M + 12 + 3 + + + + OC2PE + OC2PE + 11 + 1 + + OC2PE + read-write + + Disabled + Preload register on CCR2 disabled. New values written to CCR2 are taken into account immediately + 0 + + + Enabled + Preload register on CCR2 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC2FE + OC2FE + 10 + 1 + + + CC2S + CC2S + 8 + 2 + + CC2S + read-write + + Output + CC2 channel is configured as output + 0 + + + + + OC1CE + OC1CE + 7 + 1 + + + OC1M + OC1M + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + OC1PE + 3 + 1 + + OC1PE + read-write + + Disabled + Preload register on CCR1 disabled. New values written to CCR1 are taken into account immediately + 0 + + + Enabled + Preload register on CCR1 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC1FE + OC1FE + 2 + 1 + + + CC1S + CC1S + 0 + 2 + + CC1S + read-write + + Output + CC1 channel is configured as output + 0 + + + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 4 + + + 0 + 15 + + + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + TI2 + CC2 channel is configured as input, IC2 is mapped on TI2 + 1 + + + TI1 + CC2 channel is configured as input, IC2 is mapped on TI1 + 2 + + + TRC + CC2 channel is configured as input, IC2 is mapped on TRC + 3 + + + + + IC1F + Input capture 1 filter + 4 + 4 + + IC1F + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + TI1 + CC1 channel is configured as input, IC1 is mapped on TI1 + 1 + + + TI2 + CC1 channel is configured as input, IC1 is mapped on TI2 + 2 + + + TRC + CC1 channel is configured as input, IC1 is mapped on TRC + 3 + + + + + + + CCMR2_Output + CCMR2_Output + capture/compare mode register 2 (output + mode) + 0x1C + 0x20 + read-write + 0x00000000 + + + OC4CE + O24CE + 15 + 1 + + + OC4M + OC4M + 12 + 3 + + + + OC4PE + OC4PE + 11 + 1 + + OC4PE + read-write + + Disabled + Preload register on CCR4 disabled. New values written to CCR4 are taken into account immediately + 0 + + + Enabled + Preload register on CCR4 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC4FE + OC4FE + 10 + 1 + + + CC4S + CC4S + 8 + 2 + + CC4S + read-write + + Output + CC4 channel is configured as output + 0 + + + + + OC3CE + OC3CE + 7 + 1 + + + OC3M + OC3M + 4 + 3 + + OC3M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC3PE + OC3PE + 3 + 1 + + OC3PE + read-write + + Disabled + Preload register on CCR3 disabled. New values written to CCR3 are taken into account immediately + 0 + + + Enabled + Preload register on CCR3 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC3FE + OC3FE + 2 + 1 + + + CC3S + CC3S + 0 + 2 + + CC3S + read-write + + Output + CC3 channel is configured as output + 0 + + + + + + + CCMR2_Input + CCMR2_Input + capture/compare mode register 2 (input + mode) + CCMR2_Output + 0x1C + 0x20 + read-write + 0x00000000 + + + IC4F + Input capture 4 filter + 12 + 4 + + + 0 + 15 + + + + + IC4PSC + Input capture 4 prescaler + 10 + 2 + + + 0 + 3 + + + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + TI4 + CC4 channel is configured as input, IC4 is mapped on TI4 + 1 + + + TI3 + CC4 channel is configured as input, IC4 is mapped on TI3 + 2 + + + TRC + CC4 channel is configured as input, IC4 is mapped on TRC + 3 + + + + + IC3F + Input capture 3 filter + 4 + 4 + + + 0 + 15 + + + + + IC3PSC + Input capture 3 prescaler + 2 + 2 + + + 0 + 3 + + + + + CC3S + Capture/compare 3 + selection + 0 + 2 + + CC3S + read-write + + TI3 + CC3 channel is configured as input, IC3 is mapped on TI3 + 1 + + + TI4 + CC3 channel is configured as input, IC3 is mapped on TI4 + 2 + + + TRC + CC3 channel is configured as input, IC3 is mapped on TRC + 3 + + + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC4NP + Capture/Compare 4 output + Polarity + 15 + 1 + + + CC4P + Capture/Compare 3 output + Polarity + 13 + 1 + + + CC4E + Capture/Compare 4 output + enable + 12 + 1 + + + CC3NP + Capture/Compare 3 output + Polarity + 11 + 1 + + + CC3P + Capture/Compare 3 output + Polarity + 9 + 1 + + + CC3E + Capture/Compare 3 output + enable + 8 + 1 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + Counter value + 0 + 32 + + + 0 + 4294967295 + + + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 32 + + + 0 + 4294967295 + + + + + + + 4 + 0x4 + 1-4 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 32 + + + 0 + 4294967295 + + + + + + + DCR + DCR + DMA control register + 0x48 + 0x20 + read-write + 0x00000000 + + + DBL + DMA burst length + 8 + 5 + + + 0 + 18 + + + + + DBA + DMA base address + 0 + 5 + + + 0 + 31 + + + + + + + DMAR + DMAR + DMA address for full transfer + 0x4C + 0x20 + read-write + 0x00000000 + + + DMAB + DMA register for burst + accesses + 0 + 16 + + + + + OR + OR + TIM5 option register + 0x50 + 0x20 + read-write + 0x00000000 + + + ITR1_RMP + Timer Input 4 remap + 10 + 2 + + + + + + + TIM3 + General purpose timers + TIM + 0x40000400 + + 0x0 + 0x400 + registers + + + SPI4 + SPI4 global interrupt + 84 + + + TIM4 + TIM4 global interrupt + 30 + + + TIM5 + TIM5 global interrupt + 50 + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + CMS + Center-aligned mode + selection + 5 + 2 + + CMS + read-write + + EdgeAligned + The counter counts up or down depending on the direction bit + 0 + + + CenterAligned1 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting down. + 1 + + + CenterAligned2 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting up. + 2 + + + CenterAligned3 + The counter counts up and down alternatively. Output compare interrupt flags are set both when the counter is counting up or down. + 3 + + + + + DIR + Direction + 4 + 1 + + DIR + read-write + + Up + Counter used as upcounter + 0 + + + Down + Counter used as downcounter + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + TI1S + TI1 selection + 7 + 1 + + TI1S + read-write + + Normal + The TIMx_CH1 pin is connected to TI1 input + 0 + + + XOR + The TIMx_CH1, CH2, CH3 pins are connected to TI1 input + 1 + + + + + MMS + Master mode selection + 4 + 3 + + MMS + read-write + + Reset + The UG bit from the TIMx_EGR register is used as trigger output + 0 + + + Enable + The counter enable signal, CNT_EN, is used as trigger output + 1 + + + Update + The update event is selected as trigger output + 2 + + + ComparePulse + The trigger output send a positive pulse when the CC1IF flag it to be set, as soon as a capture or a compare match occurred + 3 + + + CompareOC1 + OC1REF signal is used as trigger output + 4 + + + CompareOC2 + OC2REF signal is used as trigger output + 5 + + + CompareOC3 + OC3REF signal is used as trigger output + 6 + + + CompareOC4 + OC4REF signal is used as trigger output + 7 + + + + + CCDS + Capture/compare DMA + selection + 3 + 1 + + CCDS + read-write + + OnCompare + CCx DMA request sent when CCx event occurs + 0 + + + OnUpdate + CCx DMA request sent when update event occurs + 1 + + + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + ETP + External trigger polarity + 15 + 1 + + ETP + read-write + + NotInverted + ETR is noninverted, active at high level or rising edge + 0 + + + Inverted + ETR is inverted, active at low level or falling edge + 1 + + + + + ECE + External clock enable + 14 + 1 + + ECE + read-write + + Disabled + External clock mode 2 disabled + 0 + + + Enabled + External clock mode 2 enabled. The counter is clocked by any active edge on the ETRF signal. + 1 + + + + + ETPS + External trigger prescaler + 12 + 2 + + ETPS + read-write + + Div1 + Prescaler OFF + 0 + + + Div2 + ETRP frequency divided by 2 + 1 + + + Div4 + ETRP frequency divided by 4 + 2 + + + Div8 + ETRP frequency divided by 8 + 3 + + + + + ETF + External trigger filter + 8 + 4 + + ETF + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + MSM + Master/Slave mode + 7 + 1 + + MSM + read-write + + NoSync + No action + 0 + + + Sync + The effect of an event on the trigger input (TRGI) is delayed to allow a perfect synchronization between the current timer and its slaves (through TRGO). It is useful if we want to synchronize several timers on a single external event. + 1 + + + + + TS + Trigger selection + 4 + 3 + + TS + read-write + + ITR0 + Internal Trigger 0 (ITR0) + 0 + + + ITR1 + Internal Trigger 1 (ITR1) + 1 + + + ITR2 + Internal Trigger 2 (ITR2) + 2 + + + TI1F_ED + TI1 Edge Detector (TI1F_ED) + 4 + + + TI1FP1 + Filtered Timer Input 1 (TI1FP1) + 5 + + + TI2FP2 + Filtered Timer Input 2 (TI2FP2) + 6 + + + ETRF + External Trigger input (ETRF) + 7 + + + + + SMS + Slave mode selection + 0 + 3 + + SMS + read-write + + Disabled + Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal clock. + 0 + + + Encoder_Mode_1 + Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending on TI1FP2 level. + 1 + + + Encoder_Mode_2 + Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level. + 2 + + + Encoder_Mode_3 + Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. + 3 + + + Reset_Mode + Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and generates an update of the registers. + 4 + + + Gated_Mode + Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of the counter are controlled. + 5 + + + Trigger_Mode + Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not reset). Only the start of the counter is controlled. + 6 + + + Ext_Clock_Mode + External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter. + 7 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TDE + Trigger DMA request enable + 14 + 1 + + TDE + read-write + + Disabled + Trigger DMA request disabled + 0 + + + Enabled + Trigger DMA request enabled + 1 + + + + + CC4DE + Capture/Compare 4 DMA request + enable + 12 + 1 + + + + CC3DE + Capture/Compare 3 DMA request + enable + 11 + 1 + + + + CC2DE + Capture/Compare 2 DMA request + enable + 10 + 1 + + + + CC1DE + Capture/Compare 1 DMA request + enable + 9 + 1 + + CC1DE + read-write + + Disabled + CCx DMA request disabled + 0 + + + Enabled + CCx DMA request enabled + 1 + + + + + UDE + Update DMA request enable + 8 + 1 + + UDE + read-write + + Disabled + Update DMA request disabled + 0 + + + Enabled + Update DMA request enabled + 1 + + + + + TIE + Trigger interrupt enable + 6 + 1 + + TIE + read-write + + Disabled + Trigger interrupt disabled + 0 + + + Enabled + Trigger interrupt enabled + 1 + + + + + CC4IE + Capture/Compare 4 interrupt + enable + 4 + 1 + + + + CC3IE + Capture/Compare 3 interrupt + enable + 3 + 1 + + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + CC1IE + read-write + + Disabled + CCx interrupt disabled + 0 + + + Enabled + CCx interrupt enabled + 1 + + + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC4OF + Capture/Compare 4 overcapture + flag + 12 + 1 + zeroToClear + + read + + + write + + + + CC3OF + Capture/Compare 3 overcapture + flag + 11 + 1 + zeroToClear + + read + + + write + + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + zeroToClear + + read + + + write + + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + zeroToClear + + CC1OFR + read + + Overcapture + The counter value has been captured in TIMx_CCRx register while CCxIF flag was already set + 1 + + + + CC1OFW + write + + Clear + Clear flag + 0 + + + + + TIF + Trigger interrupt flag + 6 + 1 + zeroToClear + + TIFR + read + + NoTrigger + No trigger event occurred + 0 + + + Trigger + Trigger interrupt pending + 1 + + + + TIFW + write + + Clear + Clear flag + 0 + + + + + CC4IF + Capture/Compare 4 interrupt + flag + 4 + 1 + zeroToClear + + read + + + write + + + + CC3IF + Capture/Compare 3 interrupt + flag + 3 + 1 + zeroToClear + + read + + + write + + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + zeroToClear + + read + + + write + + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + zeroToClear + + CC1IFR + read + + Match + If CC1 is an output: The content of the counter TIMx_CNT matches the content of the TIMx_CCR1 register. If CC1 is an input: The counter value has been captured in TIMx_CCR1 register. + 1 + + + + CC1IFW + write + + Clear + Clear flag + 0 + + + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + TG + Trigger generation + 6 + 1 + + TGW + write + + Trigger + The TIF flag is set in TIMx_SR register. Related interrupt or DMA transfer can occur if enabled. + 1 + + + + + CC4G + Capture/compare 4 + generation + 4 + 1 + + + + CC3G + Capture/compare 3 + generation + 3 + 1 + + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + CC1GW + write + + Trigger + If CC1 is an output: CC1IF flag is set, Corresponding interrupt or DMA request is sent if enabled. If CC1 is an input: The current value of the counter is captured in TIMx_CCR1 register. + 1 + + + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2CE + OC2CE + 15 + 1 + + + OC2M + OC2M + 12 + 3 + + + + OC2PE + OC2PE + 11 + 1 + + OC2PE + read-write + + Disabled + Preload register on CCR2 disabled. New values written to CCR2 are taken into account immediately + 0 + + + Enabled + Preload register on CCR2 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC2FE + OC2FE + 10 + 1 + + + CC2S + CC2S + 8 + 2 + + CC2S + read-write + + Output + CC2 channel is configured as output + 0 + + + + + OC1CE + OC1CE + 7 + 1 + + + OC1M + OC1M + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + OC1PE + 3 + 1 + + OC1PE + read-write + + Disabled + Preload register on CCR1 disabled. New values written to CCR1 are taken into account immediately + 0 + + + Enabled + Preload register on CCR1 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC1FE + OC1FE + 2 + 1 + + + CC1S + CC1S + 0 + 2 + + CC1S + read-write + + Output + CC1 channel is configured as output + 0 + + + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 4 + + + 0 + 15 + + + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + TI2 + CC2 channel is configured as input, IC2 is mapped on TI2 + 1 + + + TI1 + CC2 channel is configured as input, IC2 is mapped on TI1 + 2 + + + TRC + CC2 channel is configured as input, IC2 is mapped on TRC + 3 + + + + + IC1F + Input capture 1 filter + 4 + 4 + + IC1F + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + TI1 + CC1 channel is configured as input, IC1 is mapped on TI1 + 1 + + + TI2 + CC1 channel is configured as input, IC1 is mapped on TI2 + 2 + + + TRC + CC1 channel is configured as input, IC1 is mapped on TRC + 3 + + + + + + + CCMR2_Output + CCMR2_Output + capture/compare mode register 2 (output + mode) + 0x1C + 0x20 + read-write + 0x00000000 + + + OC4CE + O24CE + 15 + 1 + + + OC4M + OC4M + 12 + 3 + + + + OC4PE + OC4PE + 11 + 1 + + OC4PE + read-write + + Disabled + Preload register on CCR4 disabled. New values written to CCR4 are taken into account immediately + 0 + + + Enabled + Preload register on CCR4 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC4FE + OC4FE + 10 + 1 + + + CC4S + CC4S + 8 + 2 + + CC4S + read-write + + Output + CC4 channel is configured as output + 0 + + + + + OC3CE + OC3CE + 7 + 1 + + + OC3M + OC3M + 4 + 3 + + OC3M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC3PE + OC3PE + 3 + 1 + + OC3PE + read-write + + Disabled + Preload register on CCR3 disabled. New values written to CCR3 are taken into account immediately + 0 + + + Enabled + Preload register on CCR3 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC3FE + OC3FE + 2 + 1 + + + CC3S + CC3S + 0 + 2 + + CC3S + read-write + + Output + CC3 channel is configured as output + 0 + + + + + + + CCMR2_Input + CCMR2_Input + capture/compare mode register 2 (input + mode) + CCMR2_Output + 0x1C + 0x20 + read-write + 0x00000000 + + + IC4F + Input capture 4 filter + 12 + 4 + + + 0 + 15 + + + + + IC4PSC + Input capture 4 prescaler + 10 + 2 + + + 0 + 3 + + + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + TI4 + CC4 channel is configured as input, IC4 is mapped on TI4 + 1 + + + TI3 + CC4 channel is configured as input, IC4 is mapped on TI3 + 2 + + + TRC + CC4 channel is configured as input, IC4 is mapped on TRC + 3 + + + + + IC3F + Input capture 3 filter + 4 + 4 + + + 0 + 15 + + + + + IC3PSC + Input capture 3 prescaler + 2 + 2 + + + 0 + 3 + + + + + CC3S + Capture/compare 3 + selection + 0 + 2 + + CC3S + read-write + + TI3 + CC3 channel is configured as input, IC3 is mapped on TI3 + 1 + + + TI4 + CC3 channel is configured as input, IC3 is mapped on TI4 + 2 + + + TRC + CC3 channel is configured as input, IC3 is mapped on TRC + 3 + + + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC4NP + Capture/Compare 4 output + Polarity + 15 + 1 + + + CC4P + Capture/Compare 3 output + Polarity + 13 + 1 + + + CC4E + Capture/Compare 4 output + enable + 12 + 1 + + + CC3NP + Capture/Compare 3 output + Polarity + 11 + 1 + + + CC3P + Capture/Compare 3 output + Polarity + 9 + 1 + + + CC3E + Capture/Compare 3 output + enable + 8 + 1 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + Counter value + 0 + 16 + + + 0 + 65535 + + + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + 0 + 65535 + + + + + + + 4 + 0x4 + 1-4 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + 0 + 65535 + + + + + + + DCR + DCR + DMA control register + 0x48 + 0x20 + read-write + 0x00000000 + + + DBL + DMA burst length + 8 + 5 + + + 0 + 18 + + + + + DBA + DMA base address + 0 + 5 + + + 0 + 31 + + + + + + + DMAR + DMAR + DMA address for full transfer + 0x4C + 0x20 + read-write + 0x00000000 + + + DMAB + DMA register for burst + accesses + 0 + 16 + + + + + + + TIM4 + TIM + 0x40000800 + + + TIM5 + General-purpose-timers + TIM + 0x40000C00 + + 0x0 + 0x400 + registers + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + CMS + Center-aligned mode + selection + 5 + 2 + + CMS + read-write + + EdgeAligned + The counter counts up or down depending on the direction bit + 0 + + + CenterAligned1 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting down. + 1 + + + CenterAligned2 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting up. + 2 + + + CenterAligned3 + The counter counts up and down alternatively. Output compare interrupt flags are set both when the counter is counting up or down. + 3 + + + + + DIR + Direction + 4 + 1 + + DIR + read-write + + Up + Counter used as upcounter + 0 + + + Down + Counter used as downcounter + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + TI1S + TI1 selection + 7 + 1 + + TI1S + read-write + + Normal + The TIMx_CH1 pin is connected to TI1 input + 0 + + + XOR + The TIMx_CH1, CH2, CH3 pins are connected to TI1 input + 1 + + + + + MMS + Master mode selection + 4 + 3 + + MMS + read-write + + Reset + The UG bit from the TIMx_EGR register is used as trigger output + 0 + + + Enable + The counter enable signal, CNT_EN, is used as trigger output + 1 + + + Update + The update event is selected as trigger output + 2 + + + ComparePulse + The trigger output send a positive pulse when the CC1IF flag it to be set, as soon as a capture or a compare match occurred + 3 + + + CompareOC1 + OC1REF signal is used as trigger output + 4 + + + CompareOC2 + OC2REF signal is used as trigger output + 5 + + + CompareOC3 + OC3REF signal is used as trigger output + 6 + + + CompareOC4 + OC4REF signal is used as trigger output + 7 + + + + + CCDS + Capture/compare DMA + selection + 3 + 1 + + CCDS + read-write + + OnCompare + CCx DMA request sent when CCx event occurs + 0 + + + OnUpdate + CCx DMA request sent when update event occurs + 1 + + + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + ETP + External trigger polarity + 15 + 1 + + ETP + read-write + + NotInverted + ETR is noninverted, active at high level or rising edge + 0 + + + Inverted + ETR is inverted, active at low level or falling edge + 1 + + + + + ECE + External clock enable + 14 + 1 + + ECE + read-write + + Disabled + External clock mode 2 disabled + 0 + + + Enabled + External clock mode 2 enabled. The counter is clocked by any active edge on the ETRF signal. + 1 + + + + + ETPS + External trigger prescaler + 12 + 2 + + ETPS + read-write + + Div1 + Prescaler OFF + 0 + + + Div2 + ETRP frequency divided by 2 + 1 + + + Div4 + ETRP frequency divided by 4 + 2 + + + Div8 + ETRP frequency divided by 8 + 3 + + + + + ETF + External trigger filter + 8 + 4 + + ETF + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + MSM + Master/Slave mode + 7 + 1 + + MSM + read-write + + NoSync + No action + 0 + + + Sync + The effect of an event on the trigger input (TRGI) is delayed to allow a perfect synchronization between the current timer and its slaves (through TRGO). It is useful if we want to synchronize several timers on a single external event. + 1 + + + + + TS + Trigger selection + 4 + 3 + + TS + read-write + + ITR0 + Internal Trigger 0 (ITR0) + 0 + + + ITR1 + Internal Trigger 1 (ITR1) + 1 + + + ITR2 + Internal Trigger 2 (ITR2) + 2 + + + TI1F_ED + TI1 Edge Detector (TI1F_ED) + 4 + + + TI1FP1 + Filtered Timer Input 1 (TI1FP1) + 5 + + + TI2FP2 + Filtered Timer Input 2 (TI2FP2) + 6 + + + ETRF + External Trigger input (ETRF) + 7 + + + + + SMS + Slave mode selection + 0 + 3 + + SMS + read-write + + Disabled + Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal clock. + 0 + + + Encoder_Mode_1 + Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending on TI1FP2 level. + 1 + + + Encoder_Mode_2 + Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level. + 2 + + + Encoder_Mode_3 + Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. + 3 + + + Reset_Mode + Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and generates an update of the registers. + 4 + + + Gated_Mode + Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of the counter are controlled. + 5 + + + Trigger_Mode + Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not reset). Only the start of the counter is controlled. + 6 + + + Ext_Clock_Mode + External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter. + 7 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TDE + Trigger DMA request enable + 14 + 1 + + TDE + read-write + + Disabled + Trigger DMA request disabled + 0 + + + Enabled + Trigger DMA request enabled + 1 + + + + + CC4DE + Capture/Compare 4 DMA request + enable + 12 + 1 + + + + CC3DE + Capture/Compare 3 DMA request + enable + 11 + 1 + + + + CC2DE + Capture/Compare 2 DMA request + enable + 10 + 1 + + + + CC1DE + Capture/Compare 1 DMA request + enable + 9 + 1 + + CC1DE + read-write + + Disabled + CCx DMA request disabled + 0 + + + Enabled + CCx DMA request enabled + 1 + + + + + UDE + Update DMA request enable + 8 + 1 + + UDE + read-write + + Disabled + Update DMA request disabled + 0 + + + Enabled + Update DMA request enabled + 1 + + + + + TIE + Trigger interrupt enable + 6 + 1 + + TIE + read-write + + Disabled + Trigger interrupt disabled + 0 + + + Enabled + Trigger interrupt enabled + 1 + + + + + CC4IE + Capture/Compare 4 interrupt + enable + 4 + 1 + + + + CC3IE + Capture/Compare 3 interrupt + enable + 3 + 1 + + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + CC1IE + read-write + + Disabled + CCx interrupt disabled + 0 + + + Enabled + CCx interrupt enabled + 1 + + + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC4OF + Capture/Compare 4 overcapture + flag + 12 + 1 + zeroToClear + + read + + + write + + + + CC3OF + Capture/Compare 3 overcapture + flag + 11 + 1 + zeroToClear + + read + + + write + + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + zeroToClear + + read + + + write + + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + zeroToClear + + CC1OFR + read + + Overcapture + The counter value has been captured in TIMx_CCRx register while CCxIF flag was already set + 1 + + + + CC1OFW + write + + Clear + Clear flag + 0 + + + + + TIF + Trigger interrupt flag + 6 + 1 + zeroToClear + + TIFR + read + + NoTrigger + No trigger event occurred + 0 + + + Trigger + Trigger interrupt pending + 1 + + + + TIFW + write + + Clear + Clear flag + 0 + + + + + CC4IF + Capture/Compare 4 interrupt + flag + 4 + 1 + zeroToClear + + read + + + write + + + + CC3IF + Capture/Compare 3 interrupt + flag + 3 + 1 + zeroToClear + + read + + + write + + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + zeroToClear + + read + + + write + + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + zeroToClear + + CC1IFR + read + + Match + If CC1 is an output: The content of the counter TIMx_CNT matches the content of the TIMx_CCR1 register. If CC1 is an input: The counter value has been captured in TIMx_CCR1 register. + 1 + + + + CC1IFW + write + + Clear + Clear flag + 0 + + + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + TG + Trigger generation + 6 + 1 + + TGW + write + + Trigger + The TIF flag is set in TIMx_SR register. Related interrupt or DMA transfer can occur if enabled. + 1 + + + + + CC4G + Capture/compare 4 + generation + 4 + 1 + + + + CC3G + Capture/compare 3 + generation + 3 + 1 + + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + CC1GW + write + + Trigger + If CC1 is an output: CC1IF flag is set, Corresponding interrupt or DMA request is sent if enabled. If CC1 is an input: The current value of the counter is captured in TIMx_CCR1 register. + 1 + + + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2CE + OC2CE + 15 + 1 + + + OC2M + OC2M + 12 + 3 + + + + OC2PE + OC2PE + 11 + 1 + + OC2PE + read-write + + Disabled + Preload register on CCR2 disabled. New values written to CCR2 are taken into account immediately + 0 + + + Enabled + Preload register on CCR2 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC2FE + OC2FE + 10 + 1 + + + CC2S + CC2S + 8 + 2 + + CC2S + read-write + + Output + CC2 channel is configured as output + 0 + + + + + OC1CE + OC1CE + 7 + 1 + + + OC1M + OC1M + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + OC1PE + 3 + 1 + + OC1PE + read-write + + Disabled + Preload register on CCR1 disabled. New values written to CCR1 are taken into account immediately + 0 + + + Enabled + Preload register on CCR1 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC1FE + OC1FE + 2 + 1 + + + CC1S + CC1S + 0 + 2 + + CC1S + read-write + + Output + CC1 channel is configured as output + 0 + + + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 4 + + + 0 + 15 + + + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + TI2 + CC2 channel is configured as input, IC2 is mapped on TI2 + 1 + + + TI1 + CC2 channel is configured as input, IC2 is mapped on TI1 + 2 + + + TRC + CC2 channel is configured as input, IC2 is mapped on TRC + 3 + + + + + IC1F + Input capture 1 filter + 4 + 4 + + IC1F + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + TI1 + CC1 channel is configured as input, IC1 is mapped on TI1 + 1 + + + TI2 + CC1 channel is configured as input, IC1 is mapped on TI2 + 2 + + + TRC + CC1 channel is configured as input, IC1 is mapped on TRC + 3 + + + + + + + CCMR2_Output + CCMR2_Output + capture/compare mode register 2 (output + mode) + 0x1C + 0x20 + read-write + 0x00000000 + + + OC4CE + O24CE + 15 + 1 + + + OC4M + OC4M + 12 + 3 + + + + OC4PE + OC4PE + 11 + 1 + + OC4PE + read-write + + Disabled + Preload register on CCR4 disabled. New values written to CCR4 are taken into account immediately + 0 + + + Enabled + Preload register on CCR4 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC4FE + OC4FE + 10 + 1 + + + CC4S + CC4S + 8 + 2 + + CC4S + read-write + + Output + CC4 channel is configured as output + 0 + + + + + OC3CE + OC3CE + 7 + 1 + + + OC3M + OC3M + 4 + 3 + + OC3M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC3PE + OC3PE + 3 + 1 + + OC3PE + read-write + + Disabled + Preload register on CCR3 disabled. New values written to CCR3 are taken into account immediately + 0 + + + Enabled + Preload register on CCR3 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC3FE + OC3FE + 2 + 1 + + + CC3S + CC3S + 0 + 2 + + CC3S + read-write + + Output + CC3 channel is configured as output + 0 + + + + + + + CCMR2_Input + CCMR2_Input + capture/compare mode register 2 (input + mode) + CCMR2_Output + 0x1C + 0x20 + read-write + 0x00000000 + + + IC4F + Input capture 4 filter + 12 + 4 + + + 0 + 15 + + + + + IC4PSC + Input capture 4 prescaler + 10 + 2 + + + 0 + 3 + + + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + TI4 + CC4 channel is configured as input, IC4 is mapped on TI4 + 1 + + + TI3 + CC4 channel is configured as input, IC4 is mapped on TI3 + 2 + + + TRC + CC4 channel is configured as input, IC4 is mapped on TRC + 3 + + + + + IC3F + Input capture 3 filter + 4 + 4 + + + 0 + 15 + + + + + IC3PSC + Input capture 3 prescaler + 2 + 2 + + + 0 + 3 + + + + + CC3S + Capture/compare 3 + selection + 0 + 2 + + CC3S + read-write + + TI3 + CC3 channel is configured as input, IC3 is mapped on TI3 + 1 + + + TI4 + CC3 channel is configured as input, IC3 is mapped on TI4 + 2 + + + TRC + CC3 channel is configured as input, IC3 is mapped on TRC + 3 + + + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC4NP + Capture/Compare 4 output + Polarity + 15 + 1 + + + CC4P + Capture/Compare 3 output + Polarity + 13 + 1 + + + CC4E + Capture/Compare 4 output + enable + 12 + 1 + + + CC3NP + Capture/Compare 3 output + Polarity + 11 + 1 + + + CC3P + Capture/Compare 3 output + Polarity + 9 + 1 + + + CC3E + Capture/Compare 3 output + enable + 8 + 1 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + Counter value + 0 + 32 + + + 0 + 4294967295 + + + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 32 + + + 0 + 4294967295 + + + + + + + 4 + 0x4 + 1-4 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 32 + + + 0 + 4294967295 + + + + + + + DCR + DCR + DMA control register + 0x48 + 0x20 + read-write + 0x00000000 + + + DBL + DMA burst length + 8 + 5 + + + 0 + 18 + + + + + DBA + DMA base address + 0 + 5 + + + 0 + 31 + + + + + + + DMAR + DMAR + DMA address for full transfer + 0x4C + 0x20 + read-write + 0x00000000 + + + DMAB + DMA register for burst + accesses + 0 + 16 + + + + + OR + OR + TIM5 option register + 0x50 + 0x20 + read-write + 0x00000000 + + + IT4_RMP + Timer Input 4 remap + 6 + 2 + + + + + + + TIM9 + General purpose timers + TIM + 0x40014000 + + 0x0 + 0x400 + registers + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + MMS + Master mode selection + 4 + 3 + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + MSM + Master/Slave mode + 7 + 1 + + + TS + Trigger selection + 4 + 3 + + + SMS + Slave mode selection + 0 + 3 + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TIE + Trigger interrupt enable + 6 + 1 + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + + + TIF + Trigger interrupt flag + 6 + 1 + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + TG + Trigger generation + 6 + 1 + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2M + Output Compare 2 mode + 12 + 3 + + + + OC2PE + Output Compare 2 preload + enable + 11 + 1 + + + OC2FE + Output Compare 2 fast + enable + 10 + 1 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + + OC1M + Output Compare 1 mode + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + Output Compare 1 preload + enable + 3 + 1 + + + OC1FE + Output Compare 1 fast + enable + 2 + 1 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 3 + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + + IC1F + Input capture 1 filter + 4 + 3 + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + counter value + 0 + 16 + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + + + 2 + 0x4 + 1-2 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + + + + + USART1 + Universal synchronous asynchronous receiver + transmitter + USART + 0x40011000 + + 0x0 + 0x400 + registers + + + OTG_FS_WKUP + USB On-The-Go FS Wakeup through EXTI line + interrupt + 42 + + + OTG_FS + USB On The Go FS global + interrupt + 67 + + + USART1 + USART1 global interrupt + 37 + + + USART2 + USART2 global interrupt + 38 + + + USART6 + USART6 global interrupt + 71 + + + + SR + SR + Status register + 0x0 + 0x20 + 0x00C00000 + + + CTS + CTS flag + 9 + 1 + read-write + + + LBD + LIN break detection flag + 8 + 1 + read-write + + + TXE + Transmit data register + empty + 7 + 1 + read-only + + + TC + Transmission complete + 6 + 1 + read-write + + + RXNE + Read data register not + empty + 5 + 1 + read-write + + + IDLE + IDLE line detected + 4 + 1 + read-only + + + ORE + Overrun error + 3 + 1 + read-only + + + NF + Noise detected flag + 2 + 1 + read-only + + + FE + Framing error + 1 + 1 + read-only + + + PE + Parity error + 0 + 1 + read-only + + + + + DR + DR + Data register + 0x4 + 0x20 + read-write + 0x00000000 + + + DR + Data value + 0 + 9 + + + 0 + 511 + + + + + + + BRR + BRR + Baud rate register + 0x8 + 0x20 + read-write + 0x00000000 + + + DIV_Mantissa + mantissa of USARTDIV + 4 + 12 + + + 0 + 4095 + + + + + DIV_Fraction + fraction of USARTDIV + 0 + 4 + + + 0 + 15 + + + + + + + CR1 + CR1 + Control register 1 + 0xC + 0x20 + read-write + 0x00000000 + + + OVER8 + Oversampling mode + 15 + 1 + + OVER8 + read-write + + Oversample16 + Oversampling by 16 + 0 + + + Oversample8 + Oversampling by 8 + 1 + + + + + UE + USART enable + 13 + 1 + + UE + read-write + + Disabled + USART prescaler and outputs disabled + 0 + + + Enabled + USART enabled + 1 + + + + + M + Word length + 12 + 1 + + M + read-write + + M8 + 8 data bits + 0 + + + M9 + 9 data bits + 1 + + + + + WAKE + Wakeup method + 11 + 1 + + WAKE + read-write + + IdleLine + USART wakeup on idle line + 0 + + + AddressMark + USART wakeup on address mark + 1 + + + + + PCE + Parity control enable + 10 + 1 + + PCE + read-write + + Disabled + Parity control disabled + 0 + + + Enabled + Parity control enabled + 1 + + + + + PS + Parity selection + 9 + 1 + + PS + read-write + + Even + Even parity + 0 + + + Odd + Odd parity + 1 + + + + + PEIE + PE interrupt enable + 8 + 1 + + PEIE + read-write + + Disabled + PE interrupt disabled + 0 + + + Enabled + PE interrupt enabled + 1 + + + + + TXEIE + TXE interrupt enable + 7 + 1 + + TXEIE + read-write + + Disabled + TXE interrupt disabled + 0 + + + Enabled + TXE interrupt enabled + 1 + + + + + TCIE + Transmission complete interrupt + enable + 6 + 1 + + TCIE + read-write + + Disabled + TC interrupt disabled + 0 + + + Enabled + TC interrupt enabled + 1 + + + + + RXNEIE + RXNE interrupt enable + 5 + 1 + + RXNEIE + read-write + + Disabled + RXNE interrupt disabled + 0 + + + Enabled + RXNE interrupt enabled + 1 + + + + + IDLEIE + IDLE interrupt enable + 4 + 1 + + IDLEIE + read-write + + Disabled + IDLE interrupt disabled + 0 + + + Enabled + IDLE interrupt enabled + 1 + + + + + TE + Transmitter enable + 3 + 1 + + TE + read-write + + Disabled + Transmitter disabled + 0 + + + Enabled + Transmitter enabled + 1 + + + + + RE + Receiver enable + 2 + 1 + + RE + read-write + + Disabled + Receiver disabled + 0 + + + Enabled + Receiver enabled + 1 + + + + + RWU + Receiver wakeup + 1 + 1 + + RWU + read-write + + Active + Receiver in active mode + 0 + + + Mute + Receiver in mute mode + 1 + + + + + SBK + Send break + 0 + 1 + + SBK + read-write + + NoBreak + No break character is transmitted + 0 + + + Break + Break character transmitted + 1 + + + + + + + CR2 + CR2 + Control register 2 + 0x10 + 0x20 + read-write + 0x00000000 + + + LINEN + LIN mode enable + 14 + 1 + + LINEN + read-write + + Disabled + LIN mode disabled + 0 + + + Enabled + LIN mode enabled + 1 + + + + + STOP + STOP bits + 12 + 2 + + STOP + read-write + + Stop1 + 1 stop bit + 0 + + + Stop0p5 + 0.5 stop bits + 1 + + + Stop2 + 2 stop bits + 2 + + + Stop1p5 + 1.5 stop bits + 3 + + + + + CLKEN + Clock enable + 11 + 1 + + CLKEN + read-write + + Disabled + CK pin disabled + 0 + + + Enabled + CK pin enabled + 1 + + + + + CPOL + Clock polarity + 10 + 1 + + CPOL + read-write + + Low + Steady low value on CK pin outside transmission window + 0 + + + High + Steady high value on CK pin outside transmission window + 1 + + + + + CPHA + Clock phase + 9 + 1 + + CPHA + read-write + + First + The first clock transition is the first data capture edge + 0 + + + Second + The second clock transition is the first data capture edge + 1 + + + + + LBCL + Last bit clock pulse + 8 + 1 + + + LBDIE + LIN break detection interrupt + enable + 6 + 1 + + LBDIE + read-write + + Disabled + LIN break detection interrupt disabled + 0 + + + Enabled + LIN break detection interrupt enabled + 1 + + + + + LBDL + lin break detection length + 5 + 1 + + LBDL + read-write + + LBDL10 + 10-bit break detection + 0 + + + LBDL11 + 11-bit break detection + 1 + + + + + ADD + Address of the USART node + 0 + 4 + + + 0 + 15 + + + + + + + CR3 + CR3 + Control register 3 + 0x14 + 0x20 + read-write + 0x00000000 + + + ONEBIT + One sample bit method + enable + 11 + 1 + + ONEBIT + read-write + + Sample3 + Three sample bit method + 0 + + + Sample1 + One sample bit method + 1 + + + + + CTSIE + CTS interrupt enable + 10 + 1 + + CTSIE + read-write + + Disabled + CTS interrupt disabled + 0 + + + Enabled + CTS interrupt enabled + 1 + + + + + CTSE + CTS enable + 9 + 1 + + CTSE + read-write + + Disabled + CTS hardware flow control disabled + 0 + + + Enabled + CTS hardware flow control enabled + 1 + + + + + RTSE + RTS enable + 8 + 1 + + RTSE + read-write + + Disabled + RTS hardware flow control disabled + 0 + + + Enabled + RTS hardware flow control enabled + 1 + + + + + DMAT + DMA enable transmitter + 7 + 1 + + DMAT + read-write + + Disabled + DMA mode is disabled for transmission + 0 + + + Enabled + DMA mode is enabled for transmission + 1 + + + + + DMAR + DMA enable receiver + 6 + 1 + + DMAR + read-write + + Disabled + DMA mode is disabled for reception + 0 + + + Enabled + DMA mode is enabled for reception + 1 + + + + + SCEN + Smartcard mode enable + 5 + 1 + + SCEN + read-write + + Disabled + Smartcard mode disabled + 0 + + + Enabled + Smartcard mode enabled + 1 + + + + + NACK + Smartcard NACK enable + 4 + 1 + + NACK + read-write + + Disabled + NACK transmission in case of parity error is disabled + 0 + + + Enabled + NACK transmission during parity error is enabled + 1 + + + + + HDSEL + Half-duplex selection + 3 + 1 + + HDSEL + read-write + + FullDuplex + Half duplex mode is not selected + 0 + + + HalfDuplex + Half duplex mode is selected + 1 + + + + + IRLP + IrDA low-power + 2 + 1 + + IRLP + read-write + + Normal + Normal mode + 0 + + + LowPower + Low-power mode + 1 + + + + + IREN + IrDA mode enable + 1 + 1 + + IREN + read-write + + Disabled + IrDA disabled + 0 + + + Enabled + IrDA enabled + 1 + + + + + EIE + Error interrupt enable + 0 + 1 + + EIE + read-write + + Disabled + Error interrupt disabled + 0 + + + Enabled + Error interrupt enabled + 1 + + + + + + + GTPR + GTPR + Guard time and prescaler + register + 0x18 + 0x20 + read-write + 0x00000000 + + + GT + Guard time value + 8 + 8 + + + PSC + Prescaler value + 0 + 8 + + + + + + + USART2 + 0x40004400 + + + USART6 + 0x40011400 + + + WWDG + Window watchdog + WWDG + 0x40002C00 + + 0x0 + 0x400 + registers + + + PVD + PVD through EXTI line detection + interrupt + 1 + + + + CR + CR + Control register + 0x0 + 0x20 + read-write + 0x0000007F + + + WDGA + Activation bit + 7 + 1 + + WDGA + read-write + + Disabled + Watchdog disabled + 0 + + + Enabled + Watchdog enabled + 1 + + + + + T + 7-bit counter (MSB to LSB) + 0 + 7 + + + 0 + 127 + + + + + + + CFR + CFR + Configuration register + 0x4 + 0x20 + read-write + 0x0000007F + + + EWI + Early wakeup interrupt + 9 + 1 + + EWIW + write + + Enable + interrupt occurs whenever the counter reaches the value 0x40 + 1 + + + + + W + 7-bit window value + 0 + 7 + + + 0 + 127 + + + + + WDGTB + Timer base + 7 + 2 + + WDGTB + read-write + + Div1 + Counter clock (PCLK1 div 4096) div 1 + 0 + + + Div2 + Counter clock (PCLK1 div 4096) div 2 + 1 + + + Div4 + Counter clock (PCLK1 div 4096) div 4 + 2 + + + Div8 + Counter clock (PCLK1 div 4096) div 8 + 3 + + + + + + + SR + SR + Status register + 0x8 + 0x20 + read-write + 0x00000000 + + + EWIF + Early wakeup interrupt + flag + 0 + 1 + zeroToClear + + EWIFR + read + + Finished + The EWI Interrupt Service Routine has been serviced + 0 + + + Pending + The EWI Interrupt Service Routine has been triggered + 1 + + + + EWIFW + write + + Finished + The EWI Interrupt Service Routine has been serviced + 0 + + + + + + + + + DMA2 + DMA controller + DMA + 0x40026400 + + 0x0 + 0x400 + registers + + + RCC + RCC global interrupt + 5 + + + DMA1_STREAM0 + DMA1_STREAM0 global interrupt + 11 + + + DMA1_STREAM1 + DMA1_STREAM1 global interrupt + 12 + + + DMA1_STREAM2 + DMA1_STREAM2 global interrupt + 13 + + + DMA1_STREAM3 + DMA1_STREAM3 global interrupt + 14 + + + DMA1_STREAM4 + DMA1_STREAM4 global interrupt + 15 + + + DMA1_STREAM5 + DMA1_STREAM5 global interrupt + 16 + + + DMA1_STREAM6 + DMA1_STREAM6 global interrupt + 17 + + + DMA1_STREAM7 + DMA1_STREAM7 global interrupt + 47 + + + DMA2_STREAM0 + DMA2_STREAM0 global interrupt + 56 + + + DMA2_STREAM1 + DMA2_STREAM1 global interrupt + 57 + + + DMA2_STREAM2 + DMA2_STREAM2 global interrupt + 58 + + + DMA2_STREAM3 + DMA2_STREAM3 global interrupt + 59 + + + DMA2_STREAM4 + DMA2_STREAM4 global interrupt + 60 + + + DMA2_STREAM5 + DMA2_STREAM5 global interrupt + 68 + + + DMA2_STREAM6 + DMA2_STREAM6 global interrupt + 69 + + + DMA2_STREAM7 + DMA2_STREAM7 global interrupt + 70 + + + + LISR + LISR + low interrupt status register + 0x0 + 0x20 + read-only + 0x00000000 + + + TCIF3 + Stream x transfer complete interrupt + flag (x = 3..0) + 27 + 1 + + + + HTIF3 + Stream x half transfer interrupt flag + (x=3..0) + 26 + 1 + + + + TEIF3 + Stream x transfer error interrupt flag + (x=3..0) + 25 + 1 + + + + DMEIF3 + Stream x direct mode error interrupt + flag (x=3..0) + 24 + 1 + + + + FEIF3 + Stream x FIFO error interrupt flag + (x=3..0) + 22 + 1 + + + + TCIF2 + Stream x transfer complete interrupt + flag (x = 3..0) + 21 + 1 + + + + HTIF2 + Stream x half transfer interrupt flag + (x=3..0) + 20 + 1 + + + + TEIF2 + Stream x transfer error interrupt flag + (x=3..0) + 19 + 1 + + + + DMEIF2 + Stream x direct mode error interrupt + flag (x=3..0) + 18 + 1 + + + + FEIF2 + Stream x FIFO error interrupt flag + (x=3..0) + 16 + 1 + + + + TCIF1 + Stream x transfer complete interrupt + flag (x = 3..0) + 11 + 1 + + + + HTIF1 + Stream x half transfer interrupt flag + (x=3..0) + 10 + 1 + + + + TEIF1 + Stream x transfer error interrupt flag + (x=3..0) + 9 + 1 + + + + DMEIF1 + Stream x direct mode error interrupt + flag (x=3..0) + 8 + 1 + + + + FEIF1 + Stream x FIFO error interrupt flag + (x=3..0) + 6 + 1 + + + + TCIF0 + Stream x transfer complete interrupt + flag (x = 3..0) + 5 + 1 + + TCIF0 + read + + NotComplete + No transfer complete event on stream x + 0 + + + Complete + A transfer complete event occurred on stream x + 1 + + + + + HTIF0 + Stream x half transfer interrupt flag + (x=3..0) + 4 + 1 + + HTIF0 + read + + NotHalf + No half transfer event on stream x + 0 + + + Half + A half transfer event occurred on stream x + 1 + + + + + TEIF0 + Stream x transfer error interrupt flag + (x=3..0) + 3 + 1 + + TEIF0 + read + + NoError + No transfer error on stream x + 0 + + + Error + A transfer error occurred on stream x + 1 + + + + + DMEIF0 + Stream x direct mode error interrupt + flag (x=3..0) + 2 + 1 + + DMEIF0 + read + + NoError + No Direct Mode error on stream x + 0 + + + Error + A Direct Mode error occurred on stream x + 1 + + + + + FEIF0 + Stream x FIFO error interrupt flag + (x=3..0) + 0 + 1 + + FEIF0 + read + + NoError + No FIFO error event on stream x + 0 + + + Error + A FIFO error event occurred on stream x + 1 + + + + + + + HISR + HISR + high interrupt status register + 0x4 + 0x20 + read-only + 0x00000000 + + + TCIF7 + Stream x transfer complete interrupt + flag (x=7..4) + 27 + 1 + + + + HTIF7 + Stream x half transfer interrupt flag + (x=7..4) + 26 + 1 + + + + TEIF7 + Stream x transfer error interrupt flag + (x=7..4) + 25 + 1 + + + + DMEIF7 + Stream x direct mode error interrupt + flag (x=7..4) + 24 + 1 + + + + FEIF7 + Stream x FIFO error interrupt flag + (x=7..4) + 22 + 1 + + + + TCIF6 + Stream x transfer complete interrupt + flag (x=7..4) + 21 + 1 + + + + HTIF6 + Stream x half transfer interrupt flag + (x=7..4) + 20 + 1 + + + + TEIF6 + Stream x transfer error interrupt flag + (x=7..4) + 19 + 1 + + + + DMEIF6 + Stream x direct mode error interrupt + flag (x=7..4) + 18 + 1 + + + + FEIF6 + Stream x FIFO error interrupt flag + (x=7..4) + 16 + 1 + + + + TCIF5 + Stream x transfer complete interrupt + flag (x=7..4) + 11 + 1 + + + + HTIF5 + Stream x half transfer interrupt flag + (x=7..4) + 10 + 1 + + + + TEIF5 + Stream x transfer error interrupt flag + (x=7..4) + 9 + 1 + + + + DMEIF5 + Stream x direct mode error interrupt + flag (x=7..4) + 8 + 1 + + + + FEIF5 + Stream x FIFO error interrupt flag + (x=7..4) + 6 + 1 + + + + TCIF4 + Stream x transfer complete interrupt + flag (x=7..4) + 5 + 1 + + TCIF4 + read + + NotComplete + No transfer complete event on stream x + 0 + + + Complete + A transfer complete event occurred on stream x + 1 + + + + + HTIF4 + Stream x half transfer interrupt flag + (x=7..4) + 4 + 1 + + HTIF4 + read + + NotHalf + No half transfer event on stream x + 0 + + + Half + A half transfer event occurred on stream x + 1 + + + + + TEIF4 + Stream x transfer error interrupt flag + (x=7..4) + 3 + 1 + + TEIF4 + read + + NoError + No transfer error on stream x + 0 + + + Error + A transfer error occurred on stream x + 1 + + + + + DMEIF4 + Stream x direct mode error interrupt + flag (x=7..4) + 2 + 1 + + DMEIF4 + read + + NoError + No Direct Mode error on stream x + 0 + + + Error + A Direct Mode error occurred on stream x + 1 + + + + + FEIF4 + Stream x FIFO error interrupt flag + (x=7..4) + 0 + 1 + + FEIF4 + read + + NoError + No FIFO error event on stream x + 0 + + + Error + A FIFO error event occurred on stream x + 1 + + + + + + + LIFCR + LIFCR + low interrupt flag clear + register + 0x8 + 0x20 + write-only + 0x00000000 + + + CTCIF3 + Stream x clear transfer complete + interrupt flag (x = 3..0) + 27 + 1 + + + + CHTIF3 + Stream x clear half transfer interrupt + flag (x = 3..0) + 26 + 1 + + + + CTEIF3 + Stream x clear transfer error interrupt + flag (x = 3..0) + 25 + 1 + + + + CDMEIF3 + Stream x clear direct mode error + interrupt flag (x = 3..0) + 24 + 1 + + + + CFEIF3 + Stream x clear FIFO error interrupt flag + (x = 3..0) + 22 + 1 + + + + CTCIF2 + Stream x clear transfer complete + interrupt flag (x = 3..0) + 21 + 1 + + + + CHTIF2 + Stream x clear half transfer interrupt + flag (x = 3..0) + 20 + 1 + + + + CTEIF2 + Stream x clear transfer error interrupt + flag (x = 3..0) + 19 + 1 + + + + CDMEIF2 + Stream x clear direct mode error + interrupt flag (x = 3..0) + 18 + 1 + + + + CFEIF2 + Stream x clear FIFO error interrupt flag + (x = 3..0) + 16 + 1 + + + + CTCIF1 + Stream x clear transfer complete + interrupt flag (x = 3..0) + 11 + 1 + + + + CHTIF1 + Stream x clear half transfer interrupt + flag (x = 3..0) + 10 + 1 + + + + CTEIF1 + Stream x clear transfer error interrupt + flag (x = 3..0) + 9 + 1 + + + + CDMEIF1 + Stream x clear direct mode error + interrupt flag (x = 3..0) + 8 + 1 + + + + CFEIF1 + Stream x clear FIFO error interrupt flag + (x = 3..0) + 6 + 1 + + + + CTCIF0 + Stream x clear transfer complete + interrupt flag (x = 3..0) + 5 + 1 + + CTCIF0 + write + + Clear + Clear the corresponding TCIFx flag + 1 + + + + + CHTIF0 + Stream x clear half transfer interrupt + flag (x = 3..0) + 4 + 1 + + CHTIF0 + write + + Clear + Clear the corresponding HTIFx flag + 1 + + + + + CTEIF0 + Stream x clear transfer error interrupt + flag (x = 3..0) + 3 + 1 + + CTEIF0 + write + + Clear + Clear the corresponding TEIFx flag + 1 + + + + + CDMEIF0 + Stream x clear direct mode error + interrupt flag (x = 3..0) + 2 + 1 + + CDMEIF0 + write + + Clear + Clear the corresponding DMEIFx flag + 1 + + + + + CFEIF0 + Stream x clear FIFO error interrupt flag + (x = 3..0) + 0 + 1 + + CFEIF0 + write + + Clear + Clear the corresponding CFEIFx flag + 1 + + + + + + + HIFCR + HIFCR + high interrupt flag clear + register + 0xC + 0x20 + write-only + 0x00000000 + + + CTCIF7 + Stream x clear transfer complete + interrupt flag (x = 7..4) + 27 + 1 + + + + CHTIF7 + Stream x clear half transfer interrupt + flag (x = 7..4) + 26 + 1 + + + + CTEIF7 + Stream x clear transfer error interrupt + flag (x = 7..4) + 25 + 1 + + + + CDMEIF7 + Stream x clear direct mode error + interrupt flag (x = 7..4) + 24 + 1 + + + + CFEIF7 + Stream x clear FIFO error interrupt flag + (x = 7..4) + 22 + 1 + + + + CTCIF6 + Stream x clear transfer complete + interrupt flag (x = 7..4) + 21 + 1 + + + + CHTIF6 + Stream x clear half transfer interrupt + flag (x = 7..4) + 20 + 1 + + + + CTEIF6 + Stream x clear transfer error interrupt + flag (x = 7..4) + 19 + 1 + + + + CDMEIF6 + Stream x clear direct mode error + interrupt flag (x = 7..4) + 18 + 1 + + + + CFEIF6 + Stream x clear FIFO error interrupt flag + (x = 7..4) + 16 + 1 + + + + CTCIF5 + Stream x clear transfer complete + interrupt flag (x = 7..4) + 11 + 1 + + + + CHTIF5 + Stream x clear half transfer interrupt + flag (x = 7..4) + 10 + 1 + + + + CTEIF5 + Stream x clear transfer error interrupt + flag (x = 7..4) + 9 + 1 + + + + CDMEIF5 + Stream x clear direct mode error + interrupt flag (x = 7..4) + 8 + 1 + + + + CFEIF5 + Stream x clear FIFO error interrupt flag + (x = 7..4) + 6 + 1 + + + + CTCIF4 + Stream x clear transfer complete + interrupt flag (x = 7..4) + 5 + 1 + + CTCIF4 + write + + Clear + Clear the corresponding TCIFx flag + 1 + + + + + CHTIF4 + Stream x clear half transfer interrupt + flag (x = 7..4) + 4 + 1 + + CHTIF4 + write + + Clear + Clear the corresponding HTIFx flag + 1 + + + + + CTEIF4 + Stream x clear transfer error interrupt + flag (x = 7..4) + 3 + 1 + + CTEIF4 + write + + Clear + Clear the corresponding TEIFx flag + 1 + + + + + CDMEIF4 + Stream x clear direct mode error + interrupt flag (x = 7..4) + 2 + 1 + + CDMEIF4 + write + + Clear + Clear the corresponding DMEIFx flag + 1 + + + + + CFEIF4 + Stream x clear FIFO error interrupt flag + (x = 7..4) + 0 + 1 + + CFEIF4 + write + + Clear + Clear the corresponding CFEIFx flag + 1 + + + + + + + 8 + 0x18 + 0-7 + ST%s + Stream cluster: S?CR, S?NDTR, S?M0AR, S?M1AR and S?FCR registers + 0x10 + + CR + S0CR + stream x configuration + register + 0x0 + 0x20 + read-write + 0x00000000 + + + CHSEL + Channel selection + 25 + 3 + + + 0 + 7 + + + + + MBURST + Memory burst transfer + configuration + 23 + 2 + + + + PBURST + Peripheral burst transfer + configuration + 21 + 2 + + PBURST + read-write + + Single + Single transfer + 0 + + + INCR4 + Incremental burst of 4 beats + 1 + + + INCR8 + Incremental burst of 8 beats + 2 + + + INCR16 + Incremental burst of 16 beats + 3 + + + + + CT + Current target (only in double buffer + mode) + 19 + 1 + + CT + read-write + + Memory0 + The current target memory is Memory 0 + 0 + + + Memory1 + The current target memory is Memory 1 + 1 + + + + + DBM + Double buffer mode + 18 + 1 + + DBM + read-write + + Disabled + No buffer switching at the end of transfer + 0 + + + Enabled + Memory target switched at the end of the DMA transfer + 1 + + + + + PL + Priority level + 16 + 2 + + PL + read-write + + Low + Low + 0 + + + Medium + Medium + 1 + + + High + High + 2 + + + VeryHigh + Very high + 3 + + + + + PINCOS + Peripheral increment offset + size + 15 + 1 + + PINCOS + read-write + + PSIZE + The offset size for the peripheral address calculation is linked to the PSIZE + 0 + + + Fixed4 + The offset size for the peripheral address calculation is fixed to 4 (32-bit alignment) + 1 + + + + + MSIZE + Memory data size + 13 + 2 + + + + PSIZE + Peripheral data size + 11 + 2 + + PSIZE + read-write + + Bits8 + Byte (8-bit) + 0 + + + Bits16 + Half-word (16-bit) + 1 + + + Bits32 + Word (32-bit) + 2 + + + + + MINC + Memory increment mode + 10 + 1 + + + + PINC + Peripheral increment mode + 9 + 1 + + PINC + read-write + + Fixed + Address pointer is fixed + 0 + + + Incremented + Address pointer is incremented after each data transfer + 1 + + + + + CIRC + Circular mode + 8 + 1 + + CIRC + read-write + + Disabled + Circular mode disabled + 0 + + + Enabled + Circular mode enabled + 1 + + + + + DIR + Data transfer direction + 6 + 2 + + DIR + read-write + + PeripheralToMemory + Peripheral-to-memory + 0 + + + MemoryToPeripheral + Memory-to-peripheral + 1 + + + MemoryToMemory + Memory-to-memory + 2 + + + + + PFCTRL + Peripheral flow controller + 5 + 1 + + PFCTRL + read-write + + DMA + The DMA is the flow controller + 0 + + + Peripheral + The peripheral is the flow controller + 1 + + + + + TCIE + Transfer complete interrupt + enable + 4 + 1 + + TCIE + read-write + + Disabled + TC interrupt disabled + 0 + + + Enabled + TC interrupt enabled + 1 + + + + + HTIE + Half transfer interrupt + enable + 3 + 1 + + HTIE + read-write + + Disabled + HT interrupt disabled + 0 + + + Enabled + HT interrupt enabled + 1 + + + + + TEIE + Transfer error interrupt + enable + 2 + 1 + + TEIE + read-write + + Disabled + TE interrupt disabled + 0 + + + Enabled + TE interrupt enabled + 1 + + + + + DMEIE + Direct mode error interrupt + enable + 1 + 1 + + DMEIE + read-write + + Disabled + DME interrupt disabled + 0 + + + Enabled + DME interrupt enabled + 1 + + + + + EN + Stream enable / flag stream ready when + read low + 0 + 1 + + EN + read-write + + Disabled + Stream disabled + 0 + + + Enabled + Stream enabled + 1 + + + + + + + NDTR + S0NDTR + stream x number of data + register + 0x4 + 0x20 + read-write + 0x00000000 + + + NDT + Number of data items to + transfer + 0 + 16 + + + 0 + 65535 + + + + + + + PAR + S0PAR + stream x peripheral address + register + 0x8 + 0x20 + read-write + 0x00000000 + + + PA + Peripheral address + 0 + 32 + + + + + M0AR + S0M0AR + stream x memory 0 address + register + 0xC + 0x20 + read-write + 0x00000000 + + + M0A + Memory 0 address + 0 + 32 + + + + + M1AR + S0M1AR + stream x memory 1 address + register + 0x10 + 0x20 + read-write + 0x00000000 + + + M1A + Memory 1 address (used in case of Double + buffer mode) + 0 + 32 + + + + + FCR + S0FCR + stream x FIFO control register + 0x14 + 0x20 + 0x00000021 + + + FEIE + FIFO error interrupt + enable + 7 + 1 + read-write + + FEIE + read-write + + Disabled + FE interrupt disabled + 0 + + + Enabled + FE interrupt enabled + 1 + + + + + FS + FIFO status + 3 + 3 + read-only + + FS + read + + Quarter1 + 0 < fifo_level < 1/4 + 0 + + + Quarter2 + 1/4 <= fifo_level < 1/2 + 1 + + + Quarter3 + 1/2 <= fifo_level < 3/4 + 2 + + + Quarter4 + 3/4 <= fifo_level < full + 3 + + + Empty + FIFO is empty + 4 + + + Full + FIFO is full + 5 + + + + + DMDIS + Direct mode disable + 2 + 1 + read-write + + DMDIS + read-write + + Enabled + Direct mode is enabled + 0 + + + Disabled + Direct mode is disabled + 1 + + + + + FTH + FIFO threshold selection + 0 + 2 + read-write + + FTH + read-write + + Quarter + 1/4 full FIFO + 0 + + + Half + 1/2 full FIFO + 1 + + + ThreeQuarters + 3/4 full FIFO + 2 + + + Full + Full FIFO + 3 + + + + + + + + + + DMA1 + 0x40026000 + + RTC_WKUP + RTC Wakeup interrupt through the EXTI + line + 3 + + + RTC_Alarm + RTC Alarms (A and B) through EXTI line + interrupt + 41 + + + + GPIOH + General-purpose I/Os + GPIO + 0x40021C00 + + 0x0 + 0x400 + registers + + + SDIO + SDIO global interrupt + 49 + + + + MODER + MODER + GPIO port mode register + 0x0 + 0x20 + read-write + 0x00000000 + + + MODER15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + MODER14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + MODER13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + MODER12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + MODER11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + MODER10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + MODER9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + MODER8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + MODER7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + MODER6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + MODER5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + MODER4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + MODER3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + MODER2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + MODER1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + MODER0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + MODER0 + read-write + + Input + Input mode (reset state) + 0 + + + Output + General purpose output mode + 1 + + + Alternate + Alternate function mode + 2 + + + Analog + Analog mode + 3 + + + + + + + OTYPER + OTYPER + GPIO port output type register + 0x4 + 0x20 + read-write + 0x00000000 + + + OT15 + Port x configuration bits (y = + 0..15) + 15 + 1 + + + + OT14 + Port x configuration bits (y = + 0..15) + 14 + 1 + + + + OT13 + Port x configuration bits (y = + 0..15) + 13 + 1 + + + + OT12 + Port x configuration bits (y = + 0..15) + 12 + 1 + + + + OT11 + Port x configuration bits (y = + 0..15) + 11 + 1 + + + + OT10 + Port x configuration bits (y = + 0..15) + 10 + 1 + + + + OT9 + Port x configuration bits (y = + 0..15) + 9 + 1 + + + + OT8 + Port x configuration bits (y = + 0..15) + 8 + 1 + + + + OT7 + Port x configuration bits (y = + 0..15) + 7 + 1 + + + + OT6 + Port x configuration bits (y = + 0..15) + 6 + 1 + + + + OT5 + Port x configuration bits (y = + 0..15) + 5 + 1 + + + + OT4 + Port x configuration bits (y = + 0..15) + 4 + 1 + + + + OT3 + Port x configuration bits (y = + 0..15) + 3 + 1 + + + + OT2 + Port x configuration bits (y = + 0..15) + 2 + 1 + + + + OT1 + Port x configuration bits (y = + 0..15) + 1 + 1 + + + + OT0 + Port x configuration bits (y = + 0..15) + 0 + 1 + + OT0 + read-write + + PushPull + Output push-pull (reset state) + 0 + + + OpenDrain + Output open-drain + 1 + + + + + + + OSPEEDR + OSPEEDR + GPIO port output speed + register + 0x8 + 0x20 + read-write + 0x00000000 + + + OSPEEDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + OSPEEDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + OSPEEDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + OSPEEDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + OSPEEDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + OSPEEDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + OSPEEDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + OSPEEDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + OSPEEDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + OSPEEDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + OSPEEDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + OSPEEDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + OSPEEDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + OSPEEDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + OSPEEDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + OSPEEDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + OSPEEDR0 + read-write + + LowSpeed + Low speed + 0 + + + MediumSpeed + Medium speed + 1 + + + HighSpeed + High speed + 2 + + + VeryHighSpeed + Very high speed + 3 + + + + + + + PUPDR + PUPDR + GPIO port pull-up/pull-down + register + 0xC + 0x20 + read-write + 0x00000000 + + + PUPDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + PUPDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + PUPDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + PUPDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + PUPDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + PUPDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + PUPDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + PUPDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + PUPDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + PUPDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + PUPDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + PUPDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + PUPDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + PUPDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + PUPDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + PUPDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + PUPDR0 + read-write + + Floating + No pull-up, pull-down + 0 + + + PullUp + Pull-up + 1 + + + PullDown + Pull-down + 2 + + + + + + + IDR + IDR + GPIO port input data register + 0x10 + 0x20 + read-only + 0x00000000 + + + IDR15 + Port input data (y = + 0..15) + 15 + 1 + + + + IDR14 + Port input data (y = + 0..15) + 14 + 1 + + + + IDR13 + Port input data (y = + 0..15) + 13 + 1 + + + + IDR12 + Port input data (y = + 0..15) + 12 + 1 + + + + IDR11 + Port input data (y = + 0..15) + 11 + 1 + + + + IDR10 + Port input data (y = + 0..15) + 10 + 1 + + + + IDR9 + Port input data (y = + 0..15) + 9 + 1 + + + + IDR8 + Port input data (y = + 0..15) + 8 + 1 + + + + IDR7 + Port input data (y = + 0..15) + 7 + 1 + + + + IDR6 + Port input data (y = + 0..15) + 6 + 1 + + + + IDR5 + Port input data (y = + 0..15) + 5 + 1 + + + + IDR4 + Port input data (y = + 0..15) + 4 + 1 + + + + IDR3 + Port input data (y = + 0..15) + 3 + 1 + + + + IDR2 + Port input data (y = + 0..15) + 2 + 1 + + + + IDR1 + Port input data (y = + 0..15) + 1 + 1 + + + + IDR0 + Port input data (y = + 0..15) + 0 + 1 + + IDR0 + read + + Low + Input is logic low + 0 + + + High + Input is logic high + 1 + + + + + + + ODR + ODR + GPIO port output data register + 0x14 + 0x20 + read-write + 0x00000000 + + + ODR15 + Port output data (y = + 0..15) + 15 + 1 + + + + ODR14 + Port output data (y = + 0..15) + 14 + 1 + + + + ODR13 + Port output data (y = + 0..15) + 13 + 1 + + + + ODR12 + Port output data (y = + 0..15) + 12 + 1 + + + + ODR11 + Port output data (y = + 0..15) + 11 + 1 + + + + ODR10 + Port output data (y = + 0..15) + 10 + 1 + + + + ODR9 + Port output data (y = + 0..15) + 9 + 1 + + + + ODR8 + Port output data (y = + 0..15) + 8 + 1 + + + + ODR7 + Port output data (y = + 0..15) + 7 + 1 + + + + ODR6 + Port output data (y = + 0..15) + 6 + 1 + + + + ODR5 + Port output data (y = + 0..15) + 5 + 1 + + + + ODR4 + Port output data (y = + 0..15) + 4 + 1 + + + + ODR3 + Port output data (y = + 0..15) + 3 + 1 + + + + ODR2 + Port output data (y = + 0..15) + 2 + 1 + + + + ODR1 + Port output data (y = + 0..15) + 1 + 1 + + + + ODR0 + Port output data (y = + 0..15) + 0 + 1 + + ODR0 + read-write + + Low + Set output to logic low + 0 + + + High + Set output to logic high + 1 + + + + + + + BSRR + BSRR + GPIO port bit set/reset + register + 0x18 + 0x20 + write-only + 0x00000000 + + + BR15 + Port x reset bit y (y = + 0..15) + 31 + 1 + + + + BR14 + Port x reset bit y (y = + 0..15) + 30 + 1 + + + + BR13 + Port x reset bit y (y = + 0..15) + 29 + 1 + + + + BR12 + Port x reset bit y (y = + 0..15) + 28 + 1 + + + + BR11 + Port x reset bit y (y = + 0..15) + 27 + 1 + + + + BR10 + Port x reset bit y (y = + 0..15) + 26 + 1 + + + + BR9 + Port x reset bit y (y = + 0..15) + 25 + 1 + + + + BR8 + Port x reset bit y (y = + 0..15) + 24 + 1 + + + + BR7 + Port x reset bit y (y = + 0..15) + 23 + 1 + + + + BR6 + Port x reset bit y (y = + 0..15) + 22 + 1 + + + + BR5 + Port x reset bit y (y = + 0..15) + 21 + 1 + + + + BR4 + Port x reset bit y (y = + 0..15) + 20 + 1 + + + + BR3 + Port x reset bit y (y = + 0..15) + 19 + 1 + + + + BR2 + Port x reset bit y (y = + 0..15) + 18 + 1 + + + + BR1 + Port x reset bit y (y = + 0..15) + 17 + 1 + + + + BR0 + Port x set bit y (y= + 0..15) + 16 + 1 + + BR0W + write + + Reset + Resets the corresponding ODRx bit + 1 + + + + + BS15 + Port x set bit y (y= + 0..15) + 15 + 1 + + + + BS14 + Port x set bit y (y= + 0..15) + 14 + 1 + + + + BS13 + Port x set bit y (y= + 0..15) + 13 + 1 + + + + BS12 + Port x set bit y (y= + 0..15) + 12 + 1 + + + + BS11 + Port x set bit y (y= + 0..15) + 11 + 1 + + + + BS10 + Port x set bit y (y= + 0..15) + 10 + 1 + + + + BS9 + Port x set bit y (y= + 0..15) + 9 + 1 + + + + BS8 + Port x set bit y (y= + 0..15) + 8 + 1 + + + + BS7 + Port x set bit y (y= + 0..15) + 7 + 1 + + + + BS6 + Port x set bit y (y= + 0..15) + 6 + 1 + + + + BS5 + Port x set bit y (y= + 0..15) + 5 + 1 + + + + BS4 + Port x set bit y (y= + 0..15) + 4 + 1 + + + + BS3 + Port x set bit y (y= + 0..15) + 3 + 1 + + + + BS2 + Port x set bit y (y= + 0..15) + 2 + 1 + + + + BS1 + Port x set bit y (y= + 0..15) + 1 + 1 + + + + BS0 + Port x set bit y (y= + 0..15) + 0 + 1 + + BS0W + write + + Set + Sets the corresponding ODRx bit + 1 + + + + + + + LCKR + LCKR + GPIO port configuration lock + register + 0x1C + 0x20 + read-write + 0x00000000 + + + LCKK + Port x lock bit y (y= + 0..15) + 16 + 1 + + LCKK + read-write + + NotActive + Port configuration lock key not active + 0 + + + Active + Port configuration lock key active + 1 + + + + + LCK15 + Port x lock bit y (y= + 0..15) + 15 + 1 + + + + LCK14 + Port x lock bit y (y= + 0..15) + 14 + 1 + + + + LCK13 + Port x lock bit y (y= + 0..15) + 13 + 1 + + + + LCK12 + Port x lock bit y (y= + 0..15) + 12 + 1 + + + + LCK11 + Port x lock bit y (y= + 0..15) + 11 + 1 + + + + LCK10 + Port x lock bit y (y= + 0..15) + 10 + 1 + + + + LCK9 + Port x lock bit y (y= + 0..15) + 9 + 1 + + + + LCK8 + Port x lock bit y (y= + 0..15) + 8 + 1 + + + + LCK7 + Port x lock bit y (y= + 0..15) + 7 + 1 + + + + LCK6 + Port x lock bit y (y= + 0..15) + 6 + 1 + + + + LCK5 + Port x lock bit y (y= + 0..15) + 5 + 1 + + + + LCK4 + Port x lock bit y (y= + 0..15) + 4 + 1 + + + + LCK3 + Port x lock bit y (y= + 0..15) + 3 + 1 + + + + LCK2 + Port x lock bit y (y= + 0..15) + 2 + 1 + + + + LCK1 + Port x lock bit y (y= + 0..15) + 1 + 1 + + + + LCK0 + Port x lock bit y (y= + 0..15) + 0 + 1 + + LCK0 + read-write + + Unlocked + Port configuration not locked + 0 + + + Locked + Port configuration locked + 1 + + + + + + + AFRL + AFRL + GPIO alternate function low + register + 0x20 + 0x20 + read-write + 0x00000000 + + + AFRL7 + Alternate function selection for port x + bit y (y = 0..7) + 28 + 4 + + + + AFRL6 + Alternate function selection for port x + bit y (y = 0..7) + 24 + 4 + + + + AFRL5 + Alternate function selection for port x + bit y (y = 0..7) + 20 + 4 + + + + AFRL4 + Alternate function selection for port x + bit y (y = 0..7) + 16 + 4 + + + + AFRL3 + Alternate function selection for port x + bit y (y = 0..7) + 12 + 4 + + + + AFRL2 + Alternate function selection for port x + bit y (y = 0..7) + 8 + 4 + + + + AFRL1 + Alternate function selection for port x + bit y (y = 0..7) + 4 + 4 + + + + AFRL0 + Alternate function selection for port x + bit y (y = 0..7) + 0 + 4 + + AFRL0 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + AFRH + AFRH + GPIO alternate function high + register + 0x24 + 0x20 + read-write + 0x00000000 + + + AFRH15 + Alternate function selection for port x + bit y (y = 8..15) + 28 + 4 + + + + AFRH14 + Alternate function selection for port x + bit y (y = 8..15) + 24 + 4 + + + + AFRH13 + Alternate function selection for port x + bit y (y = 8..15) + 20 + 4 + + + + AFRH12 + Alternate function selection for port x + bit y (y = 8..15) + 16 + 4 + + + + AFRH11 + Alternate function selection for port x + bit y (y = 8..15) + 12 + 4 + + + + AFRH10 + Alternate function selection for port x + bit y (y = 8..15) + 8 + 4 + + + + AFRH9 + Alternate function selection for port x + bit y (y = 8..15) + 4 + 4 + + + + AFRH8 + Alternate function selection for port x + bit y (y = 8..15) + 0 + 4 + + AFRH8 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + + + GPIOE + 0x40021000 + + + GPIOD + 0x40020C00 + + TIM1_BRK_TIM9 + TIM1 Break interrupt and TIM9 global + interrupt + 24 + + + TIM1_UP_TIM10 + TIM1 Update interrupt and TIM10 global + interrupt + 25 + + + TIM1_TRG_COM_TIM11 + TIM1 Trigger and Commutation interrupts and + TIM11 global interrupt + 26 + + + TIM1_CC + TIM1 Capture Compare interrupt + 27 + + + + GPIOC + 0x40020800 + + TIM1_UP_TIM10 + TIM1 Update interrupt and TIM10 global + interrupt + 25 + + + + GPIOB + General-purpose I/Os + GPIO + 0x40020400 + + 0x0 + 0x400 + registers + + + TIM1_TRG_COM_TIM11 + TIM1 Trigger and Commutation interrupts and + TIM11 global interrupt + 26 + + + + MODER + MODER + GPIO port mode register + 0x0 + 0x20 + read-write + 0x00000280 + + + MODER15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + MODER14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + MODER13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + MODER12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + MODER11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + MODER10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + MODER9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + MODER8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + MODER7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + MODER6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + MODER5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + MODER4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + MODER3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + MODER2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + MODER1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + MODER0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + MODER0 + read-write + + Input + Input mode (reset state) + 0 + + + Output + General purpose output mode + 1 + + + Alternate + Alternate function mode + 2 + + + Analog + Analog mode + 3 + + + + + + + OTYPER + OTYPER + GPIO port output type register + 0x4 + 0x20 + read-write + 0x00000000 + + + OT15 + Port x configuration bits (y = + 0..15) + 15 + 1 + + + + OT14 + Port x configuration bits (y = + 0..15) + 14 + 1 + + + + OT13 + Port x configuration bits (y = + 0..15) + 13 + 1 + + + + OT12 + Port x configuration bits (y = + 0..15) + 12 + 1 + + + + OT11 + Port x configuration bits (y = + 0..15) + 11 + 1 + + + + OT10 + Port x configuration bits (y = + 0..15) + 10 + 1 + + + + OT9 + Port x configuration bits (y = + 0..15) + 9 + 1 + + + + OT8 + Port x configuration bits (y = + 0..15) + 8 + 1 + + + + OT7 + Port x configuration bits (y = + 0..15) + 7 + 1 + + + + OT6 + Port x configuration bits (y = + 0..15) + 6 + 1 + + + + OT5 + Port x configuration bits (y = + 0..15) + 5 + 1 + + + + OT4 + Port x configuration bits (y = + 0..15) + 4 + 1 + + + + OT3 + Port x configuration bits (y = + 0..15) + 3 + 1 + + + + OT2 + Port x configuration bits (y = + 0..15) + 2 + 1 + + + + OT1 + Port x configuration bits (y = + 0..15) + 1 + 1 + + + + OT0 + Port x configuration bits (y = + 0..15) + 0 + 1 + + OT0 + read-write + + PushPull + Output push-pull (reset state) + 0 + + + OpenDrain + Output open-drain + 1 + + + + + + + OSPEEDR + OSPEEDR + GPIO port output speed + register + 0x8 + 0x20 + read-write + 0x000000C0 + + + OSPEEDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + OSPEEDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + OSPEEDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + OSPEEDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + OSPEEDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + OSPEEDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + OSPEEDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + OSPEEDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + OSPEEDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + OSPEEDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + OSPEEDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + OSPEEDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + OSPEEDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + OSPEEDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + OSPEEDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + OSPEEDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + OSPEEDR0 + read-write + + LowSpeed + Low speed + 0 + + + MediumSpeed + Medium speed + 1 + + + HighSpeed + High speed + 2 + + + VeryHighSpeed + Very high speed + 3 + + + + + + + PUPDR + PUPDR + GPIO port pull-up/pull-down + register + 0xC + 0x20 + read-write + 0x00000100 + + + PUPDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + PUPDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + PUPDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + PUPDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + PUPDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + PUPDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + PUPDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + PUPDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + PUPDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + PUPDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + PUPDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + PUPDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + PUPDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + PUPDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + PUPDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + PUPDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + PUPDR0 + read-write + + Floating + No pull-up, pull-down + 0 + + + PullUp + Pull-up + 1 + + + PullDown + Pull-down + 2 + + + + + + + IDR + IDR + GPIO port input data register + 0x10 + 0x20 + read-only + 0x00000000 + + + IDR15 + Port input data (y = + 0..15) + 15 + 1 + + + + IDR14 + Port input data (y = + 0..15) + 14 + 1 + + + + IDR13 + Port input data (y = + 0..15) + 13 + 1 + + + + IDR12 + Port input data (y = + 0..15) + 12 + 1 + + + + IDR11 + Port input data (y = + 0..15) + 11 + 1 + + + + IDR10 + Port input data (y = + 0..15) + 10 + 1 + + + + IDR9 + Port input data (y = + 0..15) + 9 + 1 + + + + IDR8 + Port input data (y = + 0..15) + 8 + 1 + + + + IDR7 + Port input data (y = + 0..15) + 7 + 1 + + + + IDR6 + Port input data (y = + 0..15) + 6 + 1 + + + + IDR5 + Port input data (y = + 0..15) + 5 + 1 + + + + IDR4 + Port input data (y = + 0..15) + 4 + 1 + + + + IDR3 + Port input data (y = + 0..15) + 3 + 1 + + + + IDR2 + Port input data (y = + 0..15) + 2 + 1 + + + + IDR1 + Port input data (y = + 0..15) + 1 + 1 + + + + IDR0 + Port input data (y = + 0..15) + 0 + 1 + + IDR0 + read + + Low + Input is logic low + 0 + + + High + Input is logic high + 1 + + + + + + + ODR + ODR + GPIO port output data register + 0x14 + 0x20 + read-write + 0x00000000 + + + ODR15 + Port output data (y = + 0..15) + 15 + 1 + + + + ODR14 + Port output data (y = + 0..15) + 14 + 1 + + + + ODR13 + Port output data (y = + 0..15) + 13 + 1 + + + + ODR12 + Port output data (y = + 0..15) + 12 + 1 + + + + ODR11 + Port output data (y = + 0..15) + 11 + 1 + + + + ODR10 + Port output data (y = + 0..15) + 10 + 1 + + + + ODR9 + Port output data (y = + 0..15) + 9 + 1 + + + + ODR8 + Port output data (y = + 0..15) + 8 + 1 + + + + ODR7 + Port output data (y = + 0..15) + 7 + 1 + + + + ODR6 + Port output data (y = + 0..15) + 6 + 1 + + + + ODR5 + Port output data (y = + 0..15) + 5 + 1 + + + + ODR4 + Port output data (y = + 0..15) + 4 + 1 + + + + ODR3 + Port output data (y = + 0..15) + 3 + 1 + + + + ODR2 + Port output data (y = + 0..15) + 2 + 1 + + + + ODR1 + Port output data (y = + 0..15) + 1 + 1 + + + + ODR0 + Port output data (y = + 0..15) + 0 + 1 + + ODR0 + read-write + + Low + Set output to logic low + 0 + + + High + Set output to logic high + 1 + + + + + + + BSRR + BSRR + GPIO port bit set/reset + register + 0x18 + 0x20 + write-only + 0x00000000 + + + BR15 + Port x reset bit y (y = + 0..15) + 31 + 1 + + + + BR14 + Port x reset bit y (y = + 0..15) + 30 + 1 + + + + BR13 + Port x reset bit y (y = + 0..15) + 29 + 1 + + + + BR12 + Port x reset bit y (y = + 0..15) + 28 + 1 + + + + BR11 + Port x reset bit y (y = + 0..15) + 27 + 1 + + + + BR10 + Port x reset bit y (y = + 0..15) + 26 + 1 + + + + BR9 + Port x reset bit y (y = + 0..15) + 25 + 1 + + + + BR8 + Port x reset bit y (y = + 0..15) + 24 + 1 + + + + BR7 + Port x reset bit y (y = + 0..15) + 23 + 1 + + + + BR6 + Port x reset bit y (y = + 0..15) + 22 + 1 + + + + BR5 + Port x reset bit y (y = + 0..15) + 21 + 1 + + + + BR4 + Port x reset bit y (y = + 0..15) + 20 + 1 + + + + BR3 + Port x reset bit y (y = + 0..15) + 19 + 1 + + + + BR2 + Port x reset bit y (y = + 0..15) + 18 + 1 + + + + BR1 + Port x reset bit y (y = + 0..15) + 17 + 1 + + + + BR0 + Port x set bit y (y= + 0..15) + 16 + 1 + + BR0W + write + + Reset + Resets the corresponding ODRx bit + 1 + + + + + BS15 + Port x set bit y (y= + 0..15) + 15 + 1 + + + + BS14 + Port x set bit y (y= + 0..15) + 14 + 1 + + + + BS13 + Port x set bit y (y= + 0..15) + 13 + 1 + + + + BS12 + Port x set bit y (y= + 0..15) + 12 + 1 + + + + BS11 + Port x set bit y (y= + 0..15) + 11 + 1 + + + + BS10 + Port x set bit y (y= + 0..15) + 10 + 1 + + + + BS9 + Port x set bit y (y= + 0..15) + 9 + 1 + + + + BS8 + Port x set bit y (y= + 0..15) + 8 + 1 + + + + BS7 + Port x set bit y (y= + 0..15) + 7 + 1 + + + + BS6 + Port x set bit y (y= + 0..15) + 6 + 1 + + + + BS5 + Port x set bit y (y= + 0..15) + 5 + 1 + + + + BS4 + Port x set bit y (y= + 0..15) + 4 + 1 + + + + BS3 + Port x set bit y (y= + 0..15) + 3 + 1 + + + + BS2 + Port x set bit y (y= + 0..15) + 2 + 1 + + + + BS1 + Port x set bit y (y= + 0..15) + 1 + 1 + + + + BS0 + Port x set bit y (y= + 0..15) + 0 + 1 + + BS0W + write + + Set + Sets the corresponding ODRx bit + 1 + + + + + + + LCKR + LCKR + GPIO port configuration lock + register + 0x1C + 0x20 + read-write + 0x00000000 + + + LCKK + Port x lock bit y (y= + 0..15) + 16 + 1 + + LCKK + read-write + + NotActive + Port configuration lock key not active + 0 + + + Active + Port configuration lock key active + 1 + + + + + LCK15 + Port x lock bit y (y= + 0..15) + 15 + 1 + + + + LCK14 + Port x lock bit y (y= + 0..15) + 14 + 1 + + + + LCK13 + Port x lock bit y (y= + 0..15) + 13 + 1 + + + + LCK12 + Port x lock bit y (y= + 0..15) + 12 + 1 + + + + LCK11 + Port x lock bit y (y= + 0..15) + 11 + 1 + + + + LCK10 + Port x lock bit y (y= + 0..15) + 10 + 1 + + + + LCK9 + Port x lock bit y (y= + 0..15) + 9 + 1 + + + + LCK8 + Port x lock bit y (y= + 0..15) + 8 + 1 + + + + LCK7 + Port x lock bit y (y= + 0..15) + 7 + 1 + + + + LCK6 + Port x lock bit y (y= + 0..15) + 6 + 1 + + + + LCK5 + Port x lock bit y (y= + 0..15) + 5 + 1 + + + + LCK4 + Port x lock bit y (y= + 0..15) + 4 + 1 + + + + LCK3 + Port x lock bit y (y= + 0..15) + 3 + 1 + + + + LCK2 + Port x lock bit y (y= + 0..15) + 2 + 1 + + + + LCK1 + Port x lock bit y (y= + 0..15) + 1 + 1 + + + + LCK0 + Port x lock bit y (y= + 0..15) + 0 + 1 + + LCK0 + read-write + + Unlocked + Port configuration not locked + 0 + + + Locked + Port configuration locked + 1 + + + + + + + AFRL + AFRL + GPIO alternate function low + register + 0x20 + 0x20 + read-write + 0x00000000 + + + AFRL7 + Alternate function selection for port x + bit y (y = 0..7) + 28 + 4 + + + + AFRL6 + Alternate function selection for port x + bit y (y = 0..7) + 24 + 4 + + + + AFRL5 + Alternate function selection for port x + bit y (y = 0..7) + 20 + 4 + + + + AFRL4 + Alternate function selection for port x + bit y (y = 0..7) + 16 + 4 + + + + AFRL3 + Alternate function selection for port x + bit y (y = 0..7) + 12 + 4 + + + + AFRL2 + Alternate function selection for port x + bit y (y = 0..7) + 8 + 4 + + + + AFRL1 + Alternate function selection for port x + bit y (y = 0..7) + 4 + 4 + + + + AFRL0 + Alternate function selection for port x + bit y (y = 0..7) + 0 + 4 + + AFRL0 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + AFRH + AFRH + GPIO alternate function high + register + 0x24 + 0x20 + read-write + 0x00000000 + + + AFRH15 + Alternate function selection for port x + bit y (y = 8..15) + 28 + 4 + + + + AFRH14 + Alternate function selection for port x + bit y (y = 8..15) + 24 + 4 + + + + AFRH13 + Alternate function selection for port x + bit y (y = 8..15) + 20 + 4 + + + + AFRH12 + Alternate function selection for port x + bit y (y = 8..15) + 16 + 4 + + + + AFRH11 + Alternate function selection for port x + bit y (y = 8..15) + 12 + 4 + + + + AFRH10 + Alternate function selection for port x + bit y (y = 8..15) + 8 + 4 + + + + AFRH9 + Alternate function selection for port x + bit y (y = 8..15) + 4 + 4 + + + + AFRH8 + Alternate function selection for port x + bit y (y = 8..15) + 0 + 4 + + AFRH8 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + + + GPIOA + General-purpose I/Os + GPIO + 0x40020000 + + 0x0 + 0x400 + registers + + + TIM2 + TIM2 global interrupt + 28 + + + + MODER + MODER + GPIO port mode register + 0x0 + 0x20 + read-write + 0xA8000000 + + + MODER15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + MODER14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + MODER13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + MODER12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + MODER11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + MODER10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + MODER9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + MODER8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + MODER7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + MODER6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + MODER5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + MODER4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + MODER3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + MODER2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + MODER1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + MODER0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + MODER0 + read-write + + Input + Input mode (reset state) + 0 + + + Output + General purpose output mode + 1 + + + Alternate + Alternate function mode + 2 + + + Analog + Analog mode + 3 + + + + + + + OTYPER + OTYPER + GPIO port output type register + 0x4 + 0x20 + read-write + 0x00000000 + + + OT15 + Port x configuration bits (y = + 0..15) + 15 + 1 + + + + OT14 + Port x configuration bits (y = + 0..15) + 14 + 1 + + + + OT13 + Port x configuration bits (y = + 0..15) + 13 + 1 + + + + OT12 + Port x configuration bits (y = + 0..15) + 12 + 1 + + + + OT11 + Port x configuration bits (y = + 0..15) + 11 + 1 + + + + OT10 + Port x configuration bits (y = + 0..15) + 10 + 1 + + + + OT9 + Port x configuration bits (y = + 0..15) + 9 + 1 + + + + OT8 + Port x configuration bits (y = + 0..15) + 8 + 1 + + + + OT7 + Port x configuration bits (y = + 0..15) + 7 + 1 + + + + OT6 + Port x configuration bits (y = + 0..15) + 6 + 1 + + + + OT5 + Port x configuration bits (y = + 0..15) + 5 + 1 + + + + OT4 + Port x configuration bits (y = + 0..15) + 4 + 1 + + + + OT3 + Port x configuration bits (y = + 0..15) + 3 + 1 + + + + OT2 + Port x configuration bits (y = + 0..15) + 2 + 1 + + + + OT1 + Port x configuration bits (y = + 0..15) + 1 + 1 + + + + OT0 + Port x configuration bits (y = + 0..15) + 0 + 1 + + OT0 + read-write + + PushPull + Output push-pull (reset state) + 0 + + + OpenDrain + Output open-drain + 1 + + + + + + + OSPEEDR + OSPEEDR + GPIO port output speed + register + 0x8 + 0x20 + read-write + 0x00000000 + + + OSPEEDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + OSPEEDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + OSPEEDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + OSPEEDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + OSPEEDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + OSPEEDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + OSPEEDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + OSPEEDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + OSPEEDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + OSPEEDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + OSPEEDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + OSPEEDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + OSPEEDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + OSPEEDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + OSPEEDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + OSPEEDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + OSPEEDR0 + read-write + + LowSpeed + Low speed + 0 + + + MediumSpeed + Medium speed + 1 + + + HighSpeed + High speed + 2 + + + VeryHighSpeed + Very high speed + 3 + + + + + + + PUPDR + PUPDR + GPIO port pull-up/pull-down + register + 0xC + 0x20 + read-write + 0x64000000 + + + PUPDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + PUPDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + PUPDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + PUPDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + PUPDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + PUPDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + PUPDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + PUPDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + PUPDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + PUPDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + PUPDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + PUPDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + PUPDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + PUPDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + PUPDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + PUPDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + PUPDR0 + read-write + + Floating + No pull-up, pull-down + 0 + + + PullUp + Pull-up + 1 + + + PullDown + Pull-down + 2 + + + + + + + IDR + IDR + GPIO port input data register + 0x10 + 0x20 + read-only + 0x00000000 + + + IDR15 + Port input data (y = + 0..15) + 15 + 1 + + + + IDR14 + Port input data (y = + 0..15) + 14 + 1 + + + + IDR13 + Port input data (y = + 0..15) + 13 + 1 + + + + IDR12 + Port input data (y = + 0..15) + 12 + 1 + + + + IDR11 + Port input data (y = + 0..15) + 11 + 1 + + + + IDR10 + Port input data (y = + 0..15) + 10 + 1 + + + + IDR9 + Port input data (y = + 0..15) + 9 + 1 + + + + IDR8 + Port input data (y = + 0..15) + 8 + 1 + + + + IDR7 + Port input data (y = + 0..15) + 7 + 1 + + + + IDR6 + Port input data (y = + 0..15) + 6 + 1 + + + + IDR5 + Port input data (y = + 0..15) + 5 + 1 + + + + IDR4 + Port input data (y = + 0..15) + 4 + 1 + + + + IDR3 + Port input data (y = + 0..15) + 3 + 1 + + + + IDR2 + Port input data (y = + 0..15) + 2 + 1 + + + + IDR1 + Port input data (y = + 0..15) + 1 + 1 + + + + IDR0 + Port input data (y = + 0..15) + 0 + 1 + + IDR0 + read + + Low + Input is logic low + 0 + + + High + Input is logic high + 1 + + + + + + + ODR + ODR + GPIO port output data register + 0x14 + 0x20 + read-write + 0x00000000 + + + ODR15 + Port output data (y = + 0..15) + 15 + 1 + + + + ODR14 + Port output data (y = + 0..15) + 14 + 1 + + + + ODR13 + Port output data (y = + 0..15) + 13 + 1 + + + + ODR12 + Port output data (y = + 0..15) + 12 + 1 + + + + ODR11 + Port output data (y = + 0..15) + 11 + 1 + + + + ODR10 + Port output data (y = + 0..15) + 10 + 1 + + + + ODR9 + Port output data (y = + 0..15) + 9 + 1 + + + + ODR8 + Port output data (y = + 0..15) + 8 + 1 + + + + ODR7 + Port output data (y = + 0..15) + 7 + 1 + + + + ODR6 + Port output data (y = + 0..15) + 6 + 1 + + + + ODR5 + Port output data (y = + 0..15) + 5 + 1 + + + + ODR4 + Port output data (y = + 0..15) + 4 + 1 + + + + ODR3 + Port output data (y = + 0..15) + 3 + 1 + + + + ODR2 + Port output data (y = + 0..15) + 2 + 1 + + + + ODR1 + Port output data (y = + 0..15) + 1 + 1 + + + + ODR0 + Port output data (y = + 0..15) + 0 + 1 + + ODR0 + read-write + + Low + Set output to logic low + 0 + + + High + Set output to logic high + 1 + + + + + + + BSRR + BSRR + GPIO port bit set/reset + register + 0x18 + 0x20 + write-only + 0x00000000 + + + BR15 + Port x reset bit y (y = + 0..15) + 31 + 1 + + + + BR14 + Port x reset bit y (y = + 0..15) + 30 + 1 + + + + BR13 + Port x reset bit y (y = + 0..15) + 29 + 1 + + + + BR12 + Port x reset bit y (y = + 0..15) + 28 + 1 + + + + BR11 + Port x reset bit y (y = + 0..15) + 27 + 1 + + + + BR10 + Port x reset bit y (y = + 0..15) + 26 + 1 + + + + BR9 + Port x reset bit y (y = + 0..15) + 25 + 1 + + + + BR8 + Port x reset bit y (y = + 0..15) + 24 + 1 + + + + BR7 + Port x reset bit y (y = + 0..15) + 23 + 1 + + + + BR6 + Port x reset bit y (y = + 0..15) + 22 + 1 + + + + BR5 + Port x reset bit y (y = + 0..15) + 21 + 1 + + + + BR4 + Port x reset bit y (y = + 0..15) + 20 + 1 + + + + BR3 + Port x reset bit y (y = + 0..15) + 19 + 1 + + + + BR2 + Port x reset bit y (y = + 0..15) + 18 + 1 + + + + BR1 + Port x reset bit y (y = + 0..15) + 17 + 1 + + + + BR0 + Port x set bit y (y= + 0..15) + 16 + 1 + + BR0W + write + + Reset + Resets the corresponding ODRx bit + 1 + + + + + BS15 + Port x set bit y (y= + 0..15) + 15 + 1 + + + + BS14 + Port x set bit y (y= + 0..15) + 14 + 1 + + + + BS13 + Port x set bit y (y= + 0..15) + 13 + 1 + + + + BS12 + Port x set bit y (y= + 0..15) + 12 + 1 + + + + BS11 + Port x set bit y (y= + 0..15) + 11 + 1 + + + + BS10 + Port x set bit y (y= + 0..15) + 10 + 1 + + + + BS9 + Port x set bit y (y= + 0..15) + 9 + 1 + + + + BS8 + Port x set bit y (y= + 0..15) + 8 + 1 + + + + BS7 + Port x set bit y (y= + 0..15) + 7 + 1 + + + + BS6 + Port x set bit y (y= + 0..15) + 6 + 1 + + + + BS5 + Port x set bit y (y= + 0..15) + 5 + 1 + + + + BS4 + Port x set bit y (y= + 0..15) + 4 + 1 + + + + BS3 + Port x set bit y (y= + 0..15) + 3 + 1 + + + + BS2 + Port x set bit y (y= + 0..15) + 2 + 1 + + + + BS1 + Port x set bit y (y= + 0..15) + 1 + 1 + + + + BS0 + Port x set bit y (y= + 0..15) + 0 + 1 + + BS0W + write + + Set + Sets the corresponding ODRx bit + 1 + + + + + + + LCKR + LCKR + GPIO port configuration lock + register + 0x1C + 0x20 + read-write + 0x00000000 + + + LCKK + Port x lock bit y (y= + 0..15) + 16 + 1 + + LCKK + read-write + + NotActive + Port configuration lock key not active + 0 + + + Active + Port configuration lock key active + 1 + + + + + LCK15 + Port x lock bit y (y= + 0..15) + 15 + 1 + + + + LCK14 + Port x lock bit y (y= + 0..15) + 14 + 1 + + + + LCK13 + Port x lock bit y (y= + 0..15) + 13 + 1 + + + + LCK12 + Port x lock bit y (y= + 0..15) + 12 + 1 + + + + LCK11 + Port x lock bit y (y= + 0..15) + 11 + 1 + + + + LCK10 + Port x lock bit y (y= + 0..15) + 10 + 1 + + + + LCK9 + Port x lock bit y (y= + 0..15) + 9 + 1 + + + + LCK8 + Port x lock bit y (y= + 0..15) + 8 + 1 + + + + LCK7 + Port x lock bit y (y= + 0..15) + 7 + 1 + + + + LCK6 + Port x lock bit y (y= + 0..15) + 6 + 1 + + + + LCK5 + Port x lock bit y (y= + 0..15) + 5 + 1 + + + + LCK4 + Port x lock bit y (y= + 0..15) + 4 + 1 + + + + LCK3 + Port x lock bit y (y= + 0..15) + 3 + 1 + + + + LCK2 + Port x lock bit y (y= + 0..15) + 2 + 1 + + + + LCK1 + Port x lock bit y (y= + 0..15) + 1 + 1 + + + + LCK0 + Port x lock bit y (y= + 0..15) + 0 + 1 + + LCK0 + read-write + + Unlocked + Port configuration not locked + 0 + + + Locked + Port configuration locked + 1 + + + + + + + AFRL + AFRL + GPIO alternate function low + register + 0x20 + 0x20 + read-write + 0x00000000 + + + AFRL7 + Alternate function selection for port x + bit y (y = 0..7) + 28 + 4 + + + + AFRL6 + Alternate function selection for port x + bit y (y = 0..7) + 24 + 4 + + + + AFRL5 + Alternate function selection for port x + bit y (y = 0..7) + 20 + 4 + + + + AFRL4 + Alternate function selection for port x + bit y (y = 0..7) + 16 + 4 + + + + AFRL3 + Alternate function selection for port x + bit y (y = 0..7) + 12 + 4 + + + + AFRL2 + Alternate function selection for port x + bit y (y = 0..7) + 8 + 4 + + + + AFRL1 + Alternate function selection for port x + bit y (y = 0..7) + 4 + 4 + + + + AFRL0 + Alternate function selection for port x + bit y (y = 0..7) + 0 + 4 + + AFRL0 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + AFRH + AFRH + GPIO alternate function high + register + 0x24 + 0x20 + read-write + 0x00000000 + + + AFRH15 + Alternate function selection for port x + bit y (y = 8..15) + 28 + 4 + + + + AFRH14 + Alternate function selection for port x + bit y (y = 8..15) + 24 + 4 + + + + AFRH13 + Alternate function selection for port x + bit y (y = 8..15) + 20 + 4 + + + + AFRH12 + Alternate function selection for port x + bit y (y = 8..15) + 16 + 4 + + + + AFRH11 + Alternate function selection for port x + bit y (y = 8..15) + 12 + 4 + + + + AFRH10 + Alternate function selection for port x + bit y (y = 8..15) + 8 + 4 + + + + AFRH9 + Alternate function selection for port x + bit y (y = 8..15) + 4 + 4 + + + + AFRH8 + Alternate function selection for port x + bit y (y = 8..15) + 0 + 4 + + AFRH8 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + + + I2C3 + 0x40005C00 + + TIM3 + TIM3 global interrupt + 29 + + + + I2C2 + 0x40005800 + + I2C3_EV + I2C3 event interrupt + 72 + + + I2C3_ER + I2C3 error interrupt + 73 + + + + I2C1 + Inter-integrated circuit + I2C + 0x40005400 + + 0x0 + 0x400 + registers + + + I2C2_EV + I2C2 event interrupt + 33 + + + I2C2_ER + I2C2 error interrupt + 34 + + + + CR1 + CR1 + Control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + SWRST + Software reset + 15 + 1 + + SWRST + read-write + + NotReset + I2C peripheral not under reset + 0 + + + Reset + I2C peripheral under reset + 1 + + + + + ALERT + SMBus alert + 13 + 1 + + ALERT + read-write + + Release + SMBA pin released high + 0 + + + Drive + SMBA pin driven low + 1 + + + + + PEC + Packet error checking + 12 + 1 + + PEC + read-write + + Disabled + No PEC transfer + 0 + + + Enabled + PEC transfer + 1 + + + + + POS + Acknowledge/PEC Position (for data + reception) + 11 + 1 + + POS + read-write + + Current + ACK bit controls the (N)ACK of the current byte being received + 0 + + + Next + ACK bit controls the (N)ACK of the next byte to be received + 1 + + + + + ACK + Acknowledge enable + 10 + 1 + + ACK + read-write + + NAK + No acknowledge returned + 0 + + + ACK + Acknowledge returned after a byte is received + 1 + + + + + STOP + Stop generation + 9 + 1 + + STOP + read-write + + NoStop + No Stop generation + 0 + + + Stop + In master mode: stop generation after current byte/start, in slave mode: release SCL and SDA after current byte + 1 + + + + + START + Start generation + 8 + 1 + + START + read-write + + NoStart + No Start generation + 0 + + + Start + In master mode: repeated start generation, in slave mode: start generation when bus is free + 1 + + + + + NOSTRETCH + Clock stretching disable (Slave + mode) + 7 + 1 + + NOSTRETCH + read-write + + Enabled + Clock stretching enabled + 0 + + + Disabled + Clock stretching disabled + 1 + + + + + ENGC + General call enable + 6 + 1 + + ENGC + read-write + + Disabled + General call disabled + 0 + + + Enabled + General call enabled + 1 + + + + + ENPEC + PEC enable + 5 + 1 + + ENPEC + read-write + + Disabled + PEC calculation disabled + 0 + + + Enabled + PEC calculation enabled + 1 + + + + + ENARP + ARP enable + 4 + 1 + + ENARP + read-write + + Disabled + ARP disabled + 0 + + + Enabled + ARP enabled + 1 + + + + + SMBTYPE + SMBus type + 3 + 1 + + SMBTYPE + read-write + + Device + SMBus Device + 0 + + + Host + SMBus Host + 1 + + + + + SMBUS + SMBus mode + 1 + 1 + + SMBUS + read-write + + I2C + I2C Mode + 0 + + + SMBus + SMBus + 1 + + + + + PE + Peripheral enable + 0 + 1 + + PE + read-write + + Disabled + Peripheral disabled + 0 + + + Enabled + Peripheral enabled + 1 + + + + + + + CR2 + CR2 + Control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + LAST + DMA last transfer + 12 + 1 + + LAST + read-write + + NotLast + Next DMA EOT is not the last transfer + 0 + + + Last + Next DMA EOT is the last transfer + 1 + + + + + DMAEN + DMA requests enable + 11 + 1 + + DMAEN + read-write + + Disabled + DMA requests disabled + 0 + + + Enabled + DMA request enabled when TxE=1 or RxNE=1 + 1 + + + + + ITBUFEN + Buffer interrupt enable + 10 + 1 + + ITBUFEN + read-write + + Disabled + TxE=1 or RxNE=1 does not generate any interrupt + 0 + + + Enabled + TxE=1 or RxNE=1 generates Event interrupt + 1 + + + + + ITEVTEN + Event interrupt enable + 9 + 1 + + ITEVTEN + read-write + + Disabled + Event interrupt disabled + 0 + + + Enabled + Event interrupt enabled + 1 + + + + + ITERREN + Error interrupt enable + 8 + 1 + + ITERREN + read-write + + Disabled + Error interrupt disabled + 0 + + + Enabled + Error interrupt enabled + 1 + + + + + FREQ + Peripheral clock frequency + 0 + 6 + + + 2 + 50 + + + + + + + OAR1 + OAR1 + Own address register 1 + 0x8 + 0x20 + read-write + 0x00000000 + + + ADDMODE + Addressing mode (slave + mode) + 15 + 1 + + ADDMODE + read-write + + ADD7 + 7-bit slave address + 0 + + + ADD10 + 10-bit slave address + 1 + + + + + ADD + Interface address + 0 + 10 + + + 0 + 1023 + + + + + + + OAR2 + OAR2 + Own address register 2 + 0xC + 0x20 + read-write + 0x00000000 + + + ADD2 + Interface address + 1 + 7 + + + 0 + 127 + + + + + ENDUAL + Dual addressing mode + enable + 0 + 1 + + ENDUAL + read-write + + Single + Single addressing mode + 0 + + + Dual + Dual addressing mode + 1 + + + + + + + DR + DR + Data register + 0x10 + 0x20 + read-write + 0x00000000 + + + DR + 8-bit data register + 0 + 8 + + + 0 + 255 + + + + + + + SR1 + SR1 + Status register 1 + 0x14 + 0x20 + 0x00000000 + + + SMBALERT + SMBus alert + 15 + 1 + read-write + zeroToClear + + SMBALERTR + read + + NoAlert + No SMBALERT occured + 0 + + + Alert + SMBALERT occurred + 1 + + + + SMBALERTW + write + + Clear + Clear flag + 0 + + + + + TIMEOUT + Timeout or Tlow error + 14 + 1 + read-write + zeroToClear + + TIMEOUTR + read + + NoTimeout + No Timeout error + 0 + + + Timeout + SCL remained LOW for 25 ms + 1 + + + + TIMEOUTW + write + + Clear + Clear flag + 0 + + + + + PECERR + PEC Error in reception + 12 + 1 + read-write + zeroToClear + + PECERRR + read + + NoError + no PEC error: receiver returns ACK after PEC reception (if ACK=1) + 0 + + + Error + PEC error: receiver returns NACK after PEC reception (whatever ACK) + 1 + + + + PECERRW + write + + Clear + Clear flag + 0 + + + + + OVR + Overrun/Underrun + 11 + 1 + read-write + zeroToClear + + OVRR + read + + NoOverrun + No overrun/underrun occured + 0 + + + Overrun + Overrun/underrun occured + 1 + + + + OVRW + write + + Clear + Clear flag + 0 + + + + + AF + Acknowledge failure + 10 + 1 + read-write + zeroToClear + + AFR + read + + NoFailure + No acknowledge failure + 0 + + + Failure + Acknowledge failure + 1 + + + + AFW + write + + Clear + Clear flag + 0 + + + + + ARLO + Arbitration lost (master + mode) + 9 + 1 + read-write + zeroToClear + + ARLOR + read + + NoLost + No Arbitration Lost detected + 0 + + + Lost + Arbitration Lost detected + 1 + + + + ARLOW + write + + Clear + Clear flag + 0 + + + + + BERR + Bus error + 8 + 1 + read-write + zeroToClear + + BERRR + read + + NoError + No misplaced Start or Stop condition + 0 + + + Error + Misplaced Start or Stop condition + 1 + + + + BERRW + write + + Clear + Clear flag + 0 + + + + + TxE + Data register empty + (transmitters) + 7 + 1 + read-only + + TxE + read + + NotEmpty + Data register not empty + 0 + + + Empty + Data register empty + 1 + + + + + RxNE + Data register not empty + (receivers) + 6 + 1 + read-only + + RxNE + read + + Empty + Data register empty + 0 + + + NotEmpty + Data register not empty + 1 + + + + + STOPF + Stop detection (slave + mode) + 4 + 1 + read-only + + STOPF + read + + NoStop + No Stop condition detected + 0 + + + Stop + Stop condition detected + 1 + + + + + ADD10 + 10-bit header sent (Master + mode) + 3 + 1 + read-only + + + BTF + Byte transfer finished + 2 + 1 + read-only + + BTF + read + + NotFinished + Data byte transfer not done + 0 + + + Finished + Data byte transfer successful + 1 + + + + + ADDR + Address sent (master mode)/matched + (slave mode) + 1 + 1 + read-only + + ADDR + read + + NotMatch + Adress mismatched or not received + 0 + + + Match + Received slave address matched with one of the enabled slave addresses + 1 + + + + + SB + Start bit (Master mode) + 0 + 1 + read-only + + SB + read + + NoStart + No Start condition + 0 + + + Start + Start condition generated + 1 + + + + + + + SR2 + SR2 + Status register 2 + 0x18 + 0x20 + read-only + 0x00000000 + + + PEC + acket error checking + register + 8 + 8 + + + DUALF + Dual flag (Slave mode) + 7 + 1 + + + SMBHOST + SMBus host header (Slave + mode) + 6 + 1 + + + SMBDEFAULT + SMBus device default address (Slave + mode) + 5 + 1 + + + GENCALL + General call address (Slave + mode) + 4 + 1 + + + TRA + Transmitter/receiver + 2 + 1 + + + BUSY + Bus busy + 1 + 1 + + + MSL + Master/slave + 0 + 1 + + + + + CCR + CCR + Clock control register + 0x1C + 0x20 + read-write + 0x00000000 + + + F_S + I2C master mode selection + 15 + 1 + + F_S + read-write + + Standard + Standard mode I2C + 0 + + + Fast + Fast mode I2C + 1 + + + + + DUTY + Fast mode duty cycle + 14 + 1 + + DUTY + read-write + + Duty2_1 + Duty cycle t_low/t_high = 2/1 + 0 + + + Duty16_9 + Duty cycle t_low/t_high = 16/9 + 1 + + + + + CCR + Clock control register in Fast/Standard + mode (Master mode) + 0 + 12 + + + 1 + 4095 + + + + + + + TRISE + TRISE + TRISE register + 0x20 + 0x20 + read-write + 0x00000002 + + + TRISE + Maximum rise time in Fast/Standard mode + (Master mode) + 0 + 6 + + + 0 + 63 + + + + + + + FLTR + FLTR register + 0x24 + read-write + 0x00000000 + + + ANOFF + Analog noise filter + 4 + 1 + + ANOFF + read-write + + Enabled + Analog noise filter enabled + 0 + + + Disabled + Analog noise filter disabled + 1 + + + + + DNF + Digital noise filter + 0 + 4 + + DNF + read-write + + NoFilter + Digital filter disabled + 0 + + + Filter1 + Digital filter enabled and filtering capability up to 1 tI2CCLK + 1 + + + Filter2 + Digital filter enabled and filtering capability up to 2 tI2CCLK + 2 + + + Filter3 + Digital filter enabled and filtering capability up to 3 tI2CCLK + 3 + + + Filter4 + Digital filter enabled and filtering capability up to 4 tI2CCLK + 4 + + + Filter5 + Digital filter enabled and filtering capability up to 5 tI2CCLK + 5 + + + Filter6 + Digital filter enabled and filtering capability up to 6 tI2CCLK + 6 + + + Filter7 + Digital filter enabled and filtering capability up to 7 tI2CCLK + 7 + + + Filter8 + Digital filter enabled and filtering capability up to 8 tI2CCLK + 8 + + + Filter9 + Digital filter enabled and filtering capability up to 9 tI2CCLK + 9 + + + Filter10 + Digital filter enabled and filtering capability up to 10 tI2CCLK + 10 + + + Filter11 + Digital filter enabled and filtering capability up to 11 tI2CCLK + 11 + + + Filter12 + Digital filter enabled and filtering capability up to 12 tI2CCLK + 12 + + + Filter13 + Digital filter enabled and filtering capability up to 13 tI2CCLK + 13 + + + Filter14 + Digital filter enabled and filtering capability up to 14 tI2CCLK + 14 + + + Filter15 + Digital filter enabled and filtering capability up to 15 tI2CCLK + 15 + + + + + + + + + I2S2ext + 0x40003400 + + I2C1_EV + I2C1 event interrupt + 31 + + + I2C1_ER + I2C1 error interrupt + 32 + + + + I2S3ext + 0x40004000 + + + SPI1 + Serial peripheral interface + SPI + 0x40013000 + + 0x0 + 0x400 + registers + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + BIDIMODE + Bidirectional data mode + enable + 15 + 1 + + BIDIMODE + read-write + + Unidirectional + 2-line unidirectional data mode selected + 0 + + + Bidirectional + 1-line bidirectional data mode selected + 1 + + + + + BIDIOE + Output enable in bidirectional + mode + 14 + 1 + + BIDIOE + read-write + + OutputDisabled + Output disabled (receive-only mode) + 0 + + + OutputEnabled + Output enabled (transmit-only mode) + 1 + + + + + CRCEN + Hardware CRC calculation + enable + 13 + 1 + + CRCEN + read-write + + Disabled + CRC calculation disabled + 0 + + + Enabled + CRC calculation enabled + 1 + + + + + CRCNEXT + CRC transfer next + 12 + 1 + + CRCNEXT + read-write + + TxBuffer + Next transmit value is from Tx buffer + 0 + + + CRC + Next transmit value is from Tx CRC register + 1 + + + + + DFF + Data frame format + 11 + 1 + + DFF + read-write + + EightBit + 8-bit data frame format is selected for transmission/reception + 0 + + + SixteenBit + 16-bit data frame format is selected for transmission/reception + 1 + + + + + RXONLY + Receive only + 10 + 1 + + RXONLY + read-write + + FullDuplex + Full duplex (Transmit and receive) + 0 + + + OutputDisabled + Output disabled (Receive-only mode) + 1 + + + + + SSM + Software slave management + 9 + 1 + + SSM + read-write + + Disabled + Software slave management disabled + 0 + + + Enabled + Software slave management enabled + 1 + + + + + SSI + Internal slave select + 8 + 1 + + SSI + read-write + + SlaveSelected + 0 is forced onto the NSS pin and the I/O value of the NSS pin is ignored + 0 + + + SlaveNotSelected + 1 is forced onto the NSS pin and the I/O value of the NSS pin is ignored + 1 + + + + + LSBFIRST + Frame format + 7 + 1 + + LSBFIRST + read-write + + MSBFirst + Data is transmitted/received with the MSB first + 0 + + + LSBFirst + Data is transmitted/received with the LSB first + 1 + + + + + SPE + SPI enable + 6 + 1 + + SPE + read-write + + Disabled + Peripheral disabled + 0 + + + Enabled + Peripheral enabled + 1 + + + + + BR + Baud rate control + 3 + 3 + + BR + read-write + + Div2 + f_PCLK / 2 + 0 + + + Div4 + f_PCLK / 4 + 1 + + + Div8 + f_PCLK / 8 + 2 + + + Div16 + f_PCLK / 16 + 3 + + + Div32 + f_PCLK / 32 + 4 + + + Div64 + f_PCLK / 64 + 5 + + + Div128 + f_PCLK / 128 + 6 + + + Div256 + f_PCLK / 256 + 7 + + + + + MSTR + Master selection + 2 + 1 + + MSTR + read-write + + Slave + Slave configuration + 0 + + + Master + Master configuration + 1 + + + + + CPOL + Clock polarity + 1 + 1 + + CPOL + read-write + + IdleLow + CK to 0 when idle + 0 + + + IdleHigh + CK to 1 when idle + 1 + + + + + CPHA + Clock phase + 0 + 1 + + CPHA + read-write + + FirstEdge + The first clock transition is the first data capture edge + 0 + + + SecondEdge + The second clock transition is the first data capture edge + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + TXEIE + Tx buffer empty interrupt + enable + 7 + 1 + + TXEIE + read-write + + Masked + TXE interrupt masked + 0 + + + NotMasked + TXE interrupt not masked + 1 + + + + + RXNEIE + RX buffer not empty interrupt + enable + 6 + 1 + + RXNEIE + read-write + + Masked + RXE interrupt masked + 0 + + + NotMasked + RXE interrupt not masked + 1 + + + + + ERRIE + Error interrupt enable + 5 + 1 + + ERRIE + read-write + + Masked + Error interrupt masked + 0 + + + NotMasked + Error interrupt not masked + 1 + + + + + FRF + Frame format + 4 + 1 + + FRF + read-write + + Motorola + SPI Motorola mode + 0 + + + TI + SPI TI mode + 1 + + + + + SSOE + SS output enable + 2 + 1 + + SSOE + read-write + + Disabled + SS output is disabled in master mode + 0 + + + Enabled + SS output is enabled in master mode + 1 + + + + + TXDMAEN + Tx buffer DMA enable + 1 + 1 + + TXDMAEN + read-write + + Disabled + Tx buffer DMA disabled + 0 + + + Enabled + Tx buffer DMA enabled + 1 + + + + + RXDMAEN + Rx buffer DMA enable + 0 + 1 + + RXDMAEN + read-write + + Disabled + Rx buffer DMA disabled + 0 + + + Enabled + Rx buffer DMA enabled + 1 + + + + + + + SR + SR + status register + 0x8 + 0x20 + 0x00000002 + + + FRE + TI frame format error + 8 + 1 + read-only + + FRER + read + + NoError + No frame format error + 0 + + + Error + A frame format error occurred + 1 + + + + + BSY + Busy flag + 7 + 1 + read-only + + BSYR + read + + NotBusy + SPI not busy + 0 + + + Busy + SPI busy + 1 + + + + + OVR + Overrun flag + 6 + 1 + read-only + + OVRR + read + + NoOverrun + No overrun occurred + 0 + + + Overrun + Overrun occurred + 1 + + + + + MODF + Mode fault + 5 + 1 + read-only + + MODFR + read + + NoFault + No mode fault occurred + 0 + + + Fault + Mode fault occurred + 1 + + + + + CRCERR + CRC error flag + 4 + 1 + read-write + zeroToClear + + CRCERRR + read + + Match + CRC value received matches the SPIx_RXCRCR value + 0 + + + NoMatch + CRC value received does not match the SPIx_RXCRCR value + 1 + + + + CRCERRW + write + + Clear + Clear flag + 0 + + + + + UDR + Underrun flag + 3 + 1 + read-only + + UDRR + read + + NoUnderrun + No underrun occurred + 0 + + + Underrun + Underrun occurred + 1 + + + + + CHSIDE + Channel side + 2 + 1 + read-only + + CHSIDE + read + + Left + Channel left has to be transmitted or has been received + 0 + + + Right + Channel right has to be transmitted or has been received + 1 + + + + + TXE + Transmit buffer empty + 1 + 1 + read-only + + TXE + read + + NotEmpty + Tx buffer not empty + 0 + + + Empty + Tx buffer empty + 1 + + + + + RXNE + Receive buffer not empty + 0 + 1 + read-only + + RXNE + read + + Empty + Rx buffer empty + 0 + + + NotEmpty + Rx buffer not empty + 1 + + + + + + + DR + DR + data register + 0xC + 0x20 + read-write + 0x00000000 + + + DR + Data register + 0 + 16 + + + 0 + 65535 + + + + + + + CRCPR + CRCPR + CRC polynomial register + 0x10 + 0x20 + read-write + 0x00000007 + + + CRCPOLY + CRC polynomial register + 0 + 16 + + + 0 + 65535 + + + + + + + RXCRCR + RXCRCR + RX CRC register + 0x14 + 0x20 + read-only + 0x00000000 + + + RxCRC + Rx CRC register + 0 + 16 + + + 0 + 65535 + + + + + + + TXCRCR + TXCRCR + TX CRC register + 0x18 + 0x20 + read-only + 0x00000000 + + + TxCRC + Tx CRC register + 0 + 16 + + + 0 + 65535 + + + + + + + I2SCFGR + I2SCFGR + I2S configuration register + 0x1C + 0x20 + read-write + 0x00000000 + + + I2SMOD + I2S mode selection + 11 + 1 + + I2SMOD + read-write + + SPIMode + SPI mode is selected + 0 + + + I2SMode + I2S mode is selected + 1 + + + + + I2SE + I2S Enable + 10 + 1 + + I2SE + read-write + + Disabled + I2S peripheral is disabled + 0 + + + Enabled + I2S peripheral is enabled + 1 + + + + + I2SCFG + I2S configuration mode + 8 + 2 + + I2SCFG + read-write + + SlaveTx + Slave - transmit + 0 + + + SlaveRx + Slave - receive + 1 + + + MasterTx + Master - transmit + 2 + + + MasterRx + Master - receive + 3 + + + + + PCMSYNC + PCM frame synchronization + 7 + 1 + + PCMSYNC + read-write + + Short + Short frame synchronisation + 0 + + + Long + Long frame synchronisation + 1 + + + + + I2SSTD + I2S standard selection + 4 + 2 + + I2SSTD + read-write + + Philips + I2S Philips standard + 0 + + + MSB + MSB justified standard + 1 + + + LSB + LSB justified standard + 2 + + + PCM + PCM standard + 3 + + + + + CKPOL + Steady state clock + polarity + 3 + 1 + + CKPOL + read-write + + IdleLow + I2S clock inactive state is low level + 0 + + + IdleHigh + I2S clock inactive state is high level + 1 + + + + + DATLEN + Data length to be + transferred + 1 + 2 + + DATLEN + read-write + + SixteenBit + 16-bit data length + 0 + + + TwentyFourBit + 24-bit data length + 1 + + + ThirtyTwoBit + 32-bit data length + 2 + + + + + CHLEN + Channel length (number of bits per audio + channel) + 0 + 1 + + CHLEN + read-write + + SixteenBit + 16-bit wide + 0 + + + ThirtyTwoBit + 32-bit wide + 1 + + + + + + + I2SPR + I2SPR + I2S prescaler register + 0x20 + 0x20 + read-write + 0x0000000A + + + MCKOE + Master clock output enable + 9 + 1 + + MCKOE + read-write + + Disabled + Master clock output is disabled + 0 + + + Enabled + Master clock output is enabled + 1 + + + + + ODD + Odd factor for the + prescaler + 8 + 1 + + ODD + read-write + + Even + Real divider value is I2SDIV * 2 + 0 + + + Odd + Real divider value is (I2SDIV * 2) + 1 + 1 + + + + + I2SDIV + I2S Linear prescaler + 0 + 8 + + + 2 + 255 + + + + + + + + + SPI2 + 0x40003800 + + SPI1 + SPI1 global interrupt + 35 + + + + SPI3 + 0x40003C00 + + SPI2 + SPI2 global interrupt + 36 + + + + SPI4 + 0x40013400 + + SPI3 + SPI3 global interrupt + 51 + + + + NVIC + Nested Vectored Interrupt + Controller + NVIC + 0xE000E100 + + 0x0 + 0x351 + registers + + + + ISER0 + ISER0 + Interrupt Set-Enable Register + 0x0 + 0x20 + read-write + 0x00000000 + + + SETENA + SETENA + 0 + 32 + + + + + ISER1 + ISER1 + Interrupt Set-Enable Register + 0x4 + 0x20 + read-write + 0x00000000 + + + SETENA + SETENA + 0 + 32 + + + + + ISER2 + ISER2 + Interrupt Set-Enable Register + 0x8 + 0x20 + read-write + 0x00000000 + + + SETENA + SETENA + 0 + 32 + + + + + ICER0 + ICER0 + Interrupt Clear-Enable + Register + 0x80 + 0x20 + read-write + 0x00000000 + + + CLRENA + CLRENA + 0 + 32 + + + + + ICER1 + ICER1 + Interrupt Clear-Enable + Register + 0x84 + 0x20 + read-write + 0x00000000 + + + CLRENA + CLRENA + 0 + 32 + + + + + ICER2 + ICER2 + Interrupt Clear-Enable + Register + 0x88 + 0x20 + read-write + 0x00000000 + + + CLRENA + CLRENA + 0 + 32 + + + + + ISPR0 + ISPR0 + Interrupt Set-Pending Register + 0x100 + 0x20 + read-write + 0x00000000 + + + SETPEND + SETPEND + 0 + 32 + + + + + ISPR1 + ISPR1 + Interrupt Set-Pending Register + 0x104 + 0x20 + read-write + 0x00000000 + + + SETPEND + SETPEND + 0 + 32 + + + + + ISPR2 + ISPR2 + Interrupt Set-Pending Register + 0x108 + 0x20 + read-write + 0x00000000 + + + SETPEND + SETPEND + 0 + 32 + + + + + ICPR0 + ICPR0 + Interrupt Clear-Pending + Register + 0x180 + 0x20 + read-write + 0x00000000 + + + CLRPEND + CLRPEND + 0 + 32 + + + + + ICPR1 + ICPR1 + Interrupt Clear-Pending + Register + 0x184 + 0x20 + read-write + 0x00000000 + + + CLRPEND + CLRPEND + 0 + 32 + + + + + ICPR2 + ICPR2 + Interrupt Clear-Pending + Register + 0x188 + 0x20 + read-write + 0x00000000 + + + CLRPEND + CLRPEND + 0 + 32 + + + + + IABR0 + IABR0 + Interrupt Active Bit Register + 0x200 + 0x20 + read-only + 0x00000000 + + + ACTIVE + ACTIVE + 0 + 32 + + + + + IABR1 + IABR1 + Interrupt Active Bit Register + 0x204 + 0x20 + read-only + 0x00000000 + + + ACTIVE + ACTIVE + 0 + 32 + + + + + IABR2 + IABR2 + Interrupt Active Bit Register + 0x208 + 0x20 + read-only + 0x00000000 + + + ACTIVE + ACTIVE + 0 + 32 + + + + + IPR0 + IPR0 + Interrupt Priority Register + 0x300 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR1 + IPR1 + Interrupt Priority Register + 0x304 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR2 + IPR2 + Interrupt Priority Register + 0x308 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR3 + IPR3 + Interrupt Priority Register + 0x30C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR4 + IPR4 + Interrupt Priority Register + 0x310 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR5 + IPR5 + Interrupt Priority Register + 0x314 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR6 + IPR6 + Interrupt Priority Register + 0x318 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR7 + IPR7 + Interrupt Priority Register + 0x31C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR8 + IPR8 + Interrupt Priority Register + 0x320 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR9 + IPR9 + Interrupt Priority Register + 0x324 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR10 + IPR10 + Interrupt Priority Register + 0x328 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR11 + IPR11 + Interrupt Priority Register + 0x32C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR12 + IPR12 + Interrupt Priority Register + 0x330 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR13 + IPR13 + Interrupt Priority Register + 0x334 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR14 + IPR14 + Interrupt Priority Register + 0x338 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR15 + IPR15 + Interrupt Priority Register + 0x33C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR16 + IPR16 + Interrupt Priority Register + 0x340 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR17 + IPR17 + Interrupt Priority Register + 0x344 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR18 + IPR18 + Interrupt Priority Register + 0x348 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR19 + IPR19 + Interrupt Priority Register + 0x34C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + + + FPU + Floting point unit + FPU + 0xE000EF34 + + 0x0 + 0xD + registers + + + FPU + Floating point unit interrupt + 81 + + + + FPCCR + FPCCR + Floating-point context control + register + 0x0 + 0x20 + read-write + 0x00000000 + + + LSPACT + LSPACT + 0 + 1 + + + USER + USER + 1 + 1 + + + THREAD + THREAD + 3 + 1 + + + HFRDY + HFRDY + 4 + 1 + + + MMRDY + MMRDY + 5 + 1 + + + BFRDY + BFRDY + 6 + 1 + + + MONRDY + MONRDY + 8 + 1 + + + LSPEN + LSPEN + 30 + 1 + + + ASPEN + ASPEN + 31 + 1 + + + + + FPCAR + FPCAR + Floating-point context address + register + 0x4 + 0x20 + read-write + 0x00000000 + + + ADDRESS + Location of unpopulated + floating-point + 3 + 29 + + + + + FPSCR + FPSCR + Floating-point status control + register + 0x8 + 0x20 + read-write + 0x00000000 + + + IOC + Invalid operation cumulative exception + bit + 0 + 1 + + + DZC + Division by zero cumulative exception + bit. + 1 + 1 + + + OFC + Overflow cumulative exception + bit + 2 + 1 + + + UFC + Underflow cumulative exception + bit + 3 + 1 + + + IXC + Inexact cumulative exception + bit + 4 + 1 + + + IDC + Input denormal cumulative exception + bit. + 7 + 1 + + + RMode + Rounding Mode control + field + 22 + 2 + + + FZ + Flush-to-zero mode control + bit: + 24 + 1 + + + DN + Default NaN mode control + bit + 25 + 1 + + + AHP + Alternative half-precision control + bit + 26 + 1 + + + V + Overflow condition code + flag + 28 + 1 + + + C + Carry condition code flag + 29 + 1 + + + Z + Zero condition code flag + 30 + 1 + + + N + Negative condition code + flag + 31 + 1 + + + + + + + MPU + Memory protection unit + MPU + 0xE000ED90 + + 0x0 + 0x15 + registers + + + + TYPER + TYPER + MPU type register + 0x0 + 0x20 + read-only + 0x00000800 + + + SEPARATE + Separate flag + 0 + 1 + + + DREGION + Number of MPU data regions + 8 + 8 + + + IREGION + Number of MPU instruction + regions + 16 + 8 + + + + + CTRL + CTRL + MPU control register + 0x4 + 0x20 + read-only + 0x00000000 + + + ENABLE + Enables the MPU + 0 + 1 + + + HFNMIENA + Enables the operation of MPU during hard + fault + 1 + 1 + + + PRIVDEFENA + Enable priviliged software access to + default memory map + 2 + 1 + + + + + RNR + RNR + MPU region number register + 0x8 + 0x20 + read-write + 0x00000000 + + + REGION + MPU region + 0 + 8 + + + + + RBAR + RBAR + MPU region base address + register + 0xC + 0x20 + read-write + 0x00000000 + + + REGION + MPU region field + 0 + 4 + + + VALID + MPU region number valid + 4 + 1 + + + ADDR + Region base address field + 5 + 27 + + + + + RASR + RASR + MPU region attribute and size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + ENABLE + Region enable bit. + 0 + 1 + + + SIZE + Size of the MPU protection + region + 1 + 5 + + + SRD + Subregion disable bits + 8 + 8 + + + B + memory attribute + 16 + 1 + + + C + memory attribute + 17 + 1 + + + S + Shareable memory attribute + 18 + 1 + + + TEX + memory attribute + 19 + 3 + + + AP + Access permission + 24 + 3 + + + XN + Instruction access disable + bit + 28 + 1 + + + + + + + STK + SysTick timer + STK + 0xE000E010 + + 0x0 + 0x11 + registers + + + + CTRL + CTRL + SysTick control and status + register + 0x0 + 0x20 + read-write + 0x00000000 + + + ENABLE + Counter enable + 0 + 1 + + + TICKINT + SysTick exception request + enable + 1 + 1 + + + CLKSOURCE + Clock source selection + 2 + 1 + + + COUNTFLAG + COUNTFLAG + 16 + 1 + + + + + LOAD + LOAD + SysTick reload value register + 0x4 + 0x20 + read-write + 0x00000000 + + + RELOAD + RELOAD value + 0 + 24 + + + + + VAL + VAL + SysTick current value register + 0x8 + 0x20 + read-write + 0x00000000 + + + CURRENT + Current counter value + 0 + 24 + + + + + CALIB + CALIB + SysTick calibration value + register + 0xC + 0x20 + read-write + 0x00000000 + + + TENMS + Calibration value + 0 + 24 + + + SKEW + SKEW flag: Indicates whether the TENMS + value is exact + 30 + 1 + + + NOREF + NOREF flag. Reads as zero + 31 + 1 + + + + + + + SCB + System control block + SCB + 0xE000ED00 + + 0x0 + 0x41 + registers + + + + CPUID + CPUID + CPUID base register + 0x0 + 0x20 + read-only + 0x410FC241 + + + Revision + Revision number + 0 + 4 + + + PartNo + Part number of the + processor + 4 + 12 + + + Constant + Reads as 0xF + 16 + 4 + + + Variant + Variant number + 20 + 4 + + + Implementer + Implementer code + 24 + 8 + + + + + ICSR + ICSR + Interrupt control and state + register + 0x4 + 0x20 + read-write + 0x00000000 + + + VECTACTIVE + Active vector + 0 + 9 + + + RETTOBASE + Return to base level + 11 + 1 + + + VECTPENDING + Pending vector + 12 + 7 + + + ISRPENDING + Interrupt pending flag + 22 + 1 + + + PENDSTCLR + SysTick exception clear-pending + bit + 25 + 1 + + + PENDSTSET + SysTick exception set-pending + bit + 26 + 1 + + + PENDSVCLR + PendSV clear-pending bit + 27 + 1 + + + PENDSVSET + PendSV set-pending bit + 28 + 1 + + + NMIPENDSET + NMI set-pending bit. + 31 + 1 + + + + + VTOR + VTOR + Vector table offset register + 0x8 + 0x20 + read-write + 0x00000000 + + + TBLOFF + Vector table base offset + field + 9 + 21 + + + + + AIRCR + AIRCR + Application interrupt and reset control + register + 0xC + 0x20 + read-write + 0x00000000 + + + VECTRESET + VECTRESET + 0 + 1 + + + VECTCLRACTIVE + VECTCLRACTIVE + 1 + 1 + + + SYSRESETREQ + SYSRESETREQ + 2 + 1 + + + PRIGROUP + PRIGROUP + 8 + 3 + + + ENDIANESS + ENDIANESS + 15 + 1 + + + VECTKEYSTAT + Register key + 16 + 16 + + + + + SCR + SCR + System control register + 0x10 + 0x20 + read-write + 0x00000000 + + + SLEEPONEXIT + SLEEPONEXIT + 1 + 1 + + + SLEEPDEEP + SLEEPDEEP + 2 + 1 + + + SEVEONPEND + Send Event on Pending bit + 4 + 1 + + + + + CCR + CCR + Configuration and control + register + 0x14 + 0x20 + read-write + 0x00000000 + + + NONBASETHRDENA + Configures how the processor enters + Thread mode + 0 + 1 + + + USERSETMPEND + USERSETMPEND + 1 + 1 + + + UNALIGN__TRP + UNALIGN_ TRP + 3 + 1 + + + DIV_0_TRP + DIV_0_TRP + 4 + 1 + + + BFHFNMIGN + BFHFNMIGN + 8 + 1 + + + STKALIGN + STKALIGN + 9 + 1 + + + + + SHPR1 + SHPR1 + System handler priority + registers + 0x18 + 0x20 + read-write + 0x00000000 + + + PRI_4 + Priority of system handler + 4 + 0 + 8 + + + PRI_5 + Priority of system handler + 5 + 8 + 8 + + + PRI_6 + Priority of system handler + 6 + 16 + 8 + + + + + SHPR2 + SHPR2 + System handler priority + registers + 0x1C + 0x20 + read-write + 0x00000000 + + + PRI_11 + Priority of system handler + 11 + 24 + 8 + + + + + SHPR3 + SHPR3 + System handler priority + registers + 0x20 + 0x20 + read-write + 0x00000000 + + + PRI_14 + Priority of system handler + 14 + 16 + 8 + + + PRI_15 + Priority of system handler + 15 + 24 + 8 + + + + + SHCRS + SHCRS + System handler control and state + register + 0x24 + 0x20 + read-write + 0x00000000 + + + MEMFAULTACT + Memory management fault exception active + bit + 0 + 1 + + + BUSFAULTACT + Bus fault exception active + bit + 1 + 1 + + + USGFAULTACT + Usage fault exception active + bit + 3 + 1 + + + SVCALLACT + SVC call active bit + 7 + 1 + + + MONITORACT + Debug monitor active bit + 8 + 1 + + + PENDSVACT + PendSV exception active + bit + 10 + 1 + + + SYSTICKACT + SysTick exception active + bit + 11 + 1 + + + USGFAULTPENDED + Usage fault exception pending + bit + 12 + 1 + + + MEMFAULTPENDED + Memory management fault exception + pending bit + 13 + 1 + + + BUSFAULTPENDED + Bus fault exception pending + bit + 14 + 1 + + + SVCALLPENDED + SVC call pending bit + 15 + 1 + + + MEMFAULTENA + Memory management fault enable + bit + 16 + 1 + + + BUSFAULTENA + Bus fault enable bit + 17 + 1 + + + USGFAULTENA + Usage fault enable bit + 18 + 1 + + + + + CFSR_UFSR_BFSR_MMFSR + CFSR_UFSR_BFSR_MMFSR + Configurable fault status + register + 0x28 + 0x20 + read-write + 0x00000000 + + + IACCVIOL + Instruction access violation + flag + 1 + 1 + + + MUNSTKERR + Memory manager fault on unstacking for a + return from exception + 3 + 1 + + + MSTKERR + Memory manager fault on stacking for + exception entry. + 4 + 1 + + + MLSPERR + MLSPERR + 5 + 1 + + + MMARVALID + Memory Management Fault Address Register + (MMAR) valid flag + 7 + 1 + + + IBUSERR + Instruction bus error + 8 + 1 + + + PRECISERR + Precise data bus error + 9 + 1 + + + IMPRECISERR + Imprecise data bus error + 10 + 1 + + + UNSTKERR + Bus fault on unstacking for a return + from exception + 11 + 1 + + + STKERR + Bus fault on stacking for exception + entry + 12 + 1 + + + LSPERR + Bus fault on floating-point lazy state + preservation + 13 + 1 + + + BFARVALID + Bus Fault Address Register (BFAR) valid + flag + 15 + 1 + + + UNDEFINSTR + Undefined instruction usage + fault + 16 + 1 + + + INVSTATE + Invalid state usage fault + 17 + 1 + + + INVPC + Invalid PC load usage + fault + 18 + 1 + + + NOCP + No coprocessor usage + fault. + 19 + 1 + + + UNALIGNED + Unaligned access usage + fault + 24 + 1 + + + DIVBYZERO + Divide by zero usage fault + 25 + 1 + + + + + HFSR + HFSR + Hard fault status register + 0x2C + 0x20 + read-write + 0x00000000 + + + VECTTBL + Vector table hard fault + 1 + 1 + + + FORCED + Forced hard fault + 30 + 1 + + + DEBUG_VT + Reserved for Debug use + 31 + 1 + + + + + MMFAR + MMFAR + Memory management fault address + register + 0x34 + 0x20 + read-write + 0x00000000 + + + MMFAR + Memory management fault + address + 0 + 32 + + + + + BFAR + BFAR + Bus fault address register + 0x38 + 0x20 + read-write + 0x00000000 + + + BFAR + Bus fault address + 0 + 32 + + + + + AFSR + AFSR + Auxiliary fault status + register + 0x3C + 0x20 + read-write + 0x00000000 + + + IMPDEF + Implementation defined + 0 + 32 + + + + + + + NVIC_STIR + Nested vectored interrupt + controller + NVIC + 0xE000EF00 + + 0x0 + 0x5 + registers + + + + STIR + STIR + Software trigger interrupt + register + 0x0 + 0x20 + read-write + 0x00000000 + + + INTID + Software generated interrupt + ID + 0 + 9 + + + + + + + FPU_CPACR + Floating point unit CPACR + FPU + 0xE000ED88 + + 0x0 + 0x5 + registers + + + + CPACR + CPACR + Coprocessor access control + register + 0x0 + 0x20 + read-write + 0x00000000 + + + CP + CP + 20 + 4 + + + + + + + SCB_ACTRL + System control block ACTLR + SCB + 0xE000E008 + + 0x0 + 0x5 + registers + + + + ACTRL + ACTRL + Auxiliary control register + 0x0 + 0x20 + read-write + 0x00000000 + + + DISMCYCINT + DISMCYCINT + 0 + 1 + + + DISDEFWBUF + DISDEFWBUF + 1 + 1 + + + DISFOLD + DISFOLD + 2 + 1 + + + DISFPCA + DISFPCA + 8 + 1 + + + DISOOFP + DISOOFP + 9 + 1 + + + + + + + \ No newline at end of file From 9375728218576fab971aa200eab524c531749248 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 10 Jun 2024 15:30:37 +0200 Subject: [PATCH 130/687] clippy run --- sensor-nodes/bed-sensors/src/channel.rs | 2 +- sensor-nodes/bed-sensors/src/error_cache.rs | 12 ++++++------ sensor-nodes/bed-sensors/src/main.rs | 2 +- sensor-nodes/bed-sensors/src/rng.rs | 4 ++-- sensor-nodes/bed-sensors/src/sensors.rs | 4 ++-- sensor-nodes/bed-sensors/src/sensors/fast.rs | 4 ++-- sensor-nodes/bed-sensors/src/sensors/retry.rs | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/sensor-nodes/bed-sensors/src/channel.rs b/sensor-nodes/bed-sensors/src/channel.rs index 88f9b2c7..ce4073c9 100644 --- a/sensor-nodes/bed-sensors/src/channel.rs +++ b/sensor-nodes/bed-sensors/src/channel.rs @@ -32,7 +32,7 @@ impl Queues { } pub async fn clear(&self) { - while let Ok(_) = self.sensor_queue.try_receive() {} + while self.sensor_queue.try_receive().is_ok() {} self.recent_errors.lock().await.clear(); } diff --git a/sensor-nodes/bed-sensors/src/error_cache.rs b/sensor-nodes/bed-sensors/src/error_cache.rs index 526016e7..83edb813 100644 --- a/sensor-nodes/bed-sensors/src/error_cache.rs +++ b/sensor-nodes/bed-sensors/src/error_cache.rs @@ -12,9 +12,9 @@ pub enum SensorError { Max44(max44009::Error), } -impl Into for SensorError { - fn into(self) -> bed::SensorError { - match self { +impl From for bed::SensorError { + fn from(val: SensorError) -> Self { + match val { SensorError::Mhz14(e) => bed::SensorError::Mhz14(make_error_string(e)), SensorError::Sps30(e) => bed::SensorError::Sps30(make_error_string(e)), SensorError::Sht31(e) => bed::SensorError::Sht31(make_error_string(e)), @@ -32,9 +32,9 @@ pub enum Error { SetupTimedOut(Device), } -impl Into for Error { - fn into(self) -> bed::Error { - match self { +impl From for bed::Error { + fn from(val: Error) -> Self { + match val { Error::Running(e) => bed::Error::Running(e.into()), Error::Setup(e) => bed::Error::Setup(e.into()), Error::Timeout(dev) => bed::Error::Timeout(dev), diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index 11cb16a4..41e5cb18 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -242,7 +242,7 @@ async fn main(spawner: Spawner) { send_published.await; // if this takes too long the dog will get us } -async fn keep_dog_happy<'a>(mut dog: IndependentWatchdog<'a, IWDG>) { +async fn keep_dog_happy(mut dog: IndependentWatchdog<'_, IWDG>) { loop { dog.unleash(); Timer::after_secs(8).await; diff --git a/sensor-nodes/bed-sensors/src/rng.rs b/sensor-nodes/bed-sensors/src/rng.rs index db82b817..de60a0ba 100644 --- a/sensor-nodes/bed-sensors/src/rng.rs +++ b/sensor-nodes/bed-sensors/src/rng.rs @@ -74,8 +74,8 @@ pub fn generate_seed_blocking() -> u64 { // while not status register end of conversion bit is set while !p.ADC1.sr.read().eoc().bit_is_set() {} - let value = p.ADC1.dr.read().bits(); - value + + p.ADC1.dr.read().bits() }; let mut seed = [0u8; 16]; diff --git a/sensor-nodes/bed-sensors/src/sensors.rs b/sensor-nodes/bed-sensors/src/sensors.rs index ae852d66..62a70d78 100644 --- a/sensor-nodes/bed-sensors/src/sensors.rs +++ b/sensor-nodes/bed-sensors/src/sensors.rs @@ -63,8 +63,8 @@ pub async fn init_then_measure( .map_err(SensorError::Sps30) .map_err(Error::Setup)?; - let sensors_fast = fast::read(max44009, /*buttons,*/ &publish); - let sensors_slow = slow::read(sht, bme, mhz, sps30, &publish); + let sensors_fast = fast::read(max44009, /*buttons,*/ publish); + let sensors_slow = slow::read(sht, bme, mhz, sps30, publish); join::join(sensors_fast, sensors_slow).await; defmt::unreachable!(); diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed-sensors/src/sensors/fast.rs index a38bda8f..8adb7b7f 100644 --- a/sensor-nodes/bed-sensors/src/sensors/fast.rs +++ b/sensor-nodes/bed-sensors/src/sensors/fast.rs @@ -25,7 +25,7 @@ async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues) { let lux = match max44.try_measure().await { Ok(lux) => lux, Err(err) if last_lux.elapsed() > MIN_INTERVAL => { - let _ignore = publish.queue_error(err); + publish.queue_error(err); continue; } Err(_) => continue, @@ -62,7 +62,7 @@ async fn watch_button( continue; }; let event = (event)(protocol::Press(press)); - let _ignore_full = channel.send_p2(Reading::Button(event)); + channel.send_p2(Reading::Button(event)); } } else { input.wait_for_rising_edge().await; diff --git a/sensor-nodes/bed-sensors/src/sensors/retry.rs b/sensor-nodes/bed-sensors/src/sensors/retry.rs index 626360f6..eecfdd6f 100644 --- a/sensor-nodes/bed-sensors/src/sensors/retry.rs +++ b/sensor-nodes/bed-sensors/src/sensors/retry.rs @@ -155,7 +155,7 @@ impl ReInitOnErrorDriver { Err(err) => { let new_self = Self::Uninit { parts }; let err = Error::Running(err); - return (new_self, Err(err)); + (new_self, Err(err)) } } } From 3d8aad6e6ceeccb98bb3ff1b49a34fab2539c50d Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 13 Jun 2024 15:56:49 +0200 Subject: [PATCH 131/687] move protocol from Result to own enum --- Cargo.toml | 2 + crates/data-server/src/lib.rs | 80 ++++++++++++++++++--------------- crates/data-server/src/main.rs | 72 ++++++++++++++--------------- crates/desk-sensors/src/main.rs | 17 +++---- crates/protocol/src/lib.rs | 65 ++++++++++++++++++++------- crates/sensor-tui/src/main.rs | 5 ++- 6 files changed, 143 insertions(+), 98 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bf1f3520..18803183 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,5 @@ edition = "2021" license = "GPLv3" authors = ["David Kleingeld & Eva van Houten"] +[profile.release] +debug = true diff --git a/crates/data-server/src/lib.rs b/crates/data-server/src/lib.rs index 6379afd4..0151b394 100644 --- a/crates/data-server/src/lib.rs +++ b/crates/data-server/src/lib.rs @@ -1,18 +1,22 @@ use std::io::{BufRead, BufReader}; use std::net::{TcpStream, ToSocketAddrs}; +use std::vec; -use protocol::{DecodeError, SensorMessage}; +use protocol::{DecodeError, Msg}; use tokio::io::AsyncBufReadExt; use tracing::trace; +pub enum SubMessage { + Reading(protocol::Reading), + ErrorReport(protocol::Error), +} + pub struct Subscriber { reader: BufReader, buf: Vec, - values: std::vec::IntoIter, + values: vec::IntoIter, } -type Msg = Result; - impl Subscriber { pub fn connect(addr: impl ToSocketAddrs) -> Result { let conn = TcpStream::connect(addr).map_err(SubscribeError::ConnFailed)?; @@ -26,38 +30,24 @@ impl Subscriber { }) } - pub fn next(&mut self) -> Result { + pub fn next(&mut self) -> Result { if let Some(val) = self.values.next() { return Ok(val); } + self.buf.clear(); let n_read = self .reader .read_until(0, &mut self.buf) .map_err(SubscribeError::ConnFailed)?; - - if n_read == 0 { - return Err(SubscribeError::ConnEnded)?; - } - - self.buf.resize(n_read, 0); // ensure stop delimiter in bytes - let msg = &mut self.buf[0..n_read]; - trace!("{:?}", &msg); - let msg = SensorMessage::<50>::decode(msg).map_err(SubscribeError::DecodeFailed)?; - self.buf.clear(); - - self.values = msg.values.to_vec().into_iter(); - Ok(self - .values - .next() - .expect("min values in sensormessage is one")) + decode_buffer_and_return_first(n_read, &mut self.buf, &mut self.values) } } pub struct AsyncSubscriber { reader: tokio::io::BufReader, buf: Vec, - values: std::vec::IntoIter, + values: vec::IntoIter, } impl AsyncSubscriber { @@ -75,7 +65,7 @@ impl AsyncSubscriber { }) } - pub async fn next(&mut self) -> Result { + pub async fn next(&mut self) -> Result { if let Some(val) = self.values.next() { return Ok(val); } @@ -85,23 +75,41 @@ impl AsyncSubscriber { .read_until(0, &mut self.buf) .await .map_err(SubscribeError::ConnFailed)?; + decode_buffer_and_return_first(n_read, &mut self.buf, &mut self.values) + } +} - if n_read == 0 { - return Err(SubscribeError::ConnEnded)?; - } +fn decode_buffer_and_return_first( + n_read: usize, + buf: &mut Vec, + buffer: &mut vec::IntoIter, +) -> Result { + assert!(buffer.next().is_none()); - self.buf.resize(n_read, 0); // ensure stop delimiter in bytes - let msg = &mut self.buf[0..n_read]; - trace!("{:?}", &msg); - let msg = SensorMessage::<50>::decode(msg).map_err(SubscribeError::DecodeFailed)?; - self.buf.clear(); + if n_read == 0 { + return Err(SubscribeError::ConnEnded)?; + } - self.values = msg.values.to_vec().into_iter(); - Ok(self - .values - .next() - .expect("min values in sensormessage is one")) + buf.resize(n_read, 0); // ensure stop delimiter in bytes + let bytes = &mut buf[0..n_read]; + trace!("{:?}", &bytes); + let decoded: Msg<50> = Msg::decode(bytes).map_err(SubscribeError::DecodeFailed)?; + match decoded { + Msg::Readings(readings) => { + *buffer = readings + .values + .iter() + .map(Clone::clone) + .map(|v| SubMessage::Reading(v)) + .collect::>() + .into_iter(); + } + Msg::ErrorReport(report) => { + *buffer = vec![SubMessage::ErrorReport(report.error)].into_iter() + } } + + Ok(buffer.next().expect("min values in sensormessage is one")) } #[derive(Debug, thiserror::Error)] diff --git a/crates/data-server/src/main.rs b/crates/data-server/src/main.rs index 8e5a72d1..837537f8 100644 --- a/crates/data-server/src/main.rs +++ b/crates/data-server/src/main.rs @@ -30,6 +30,7 @@ async fn handle_client(stream: TcpStream, tx: Sender) { let mut reader = BufStream::new(stream); let mut buf = Vec::new(); loop { + buf.clear(); let n_read = match reader.read_until(0, &mut buf).await { Err(e) => { warn!("Connection failed/closed: {e}"); @@ -37,20 +38,31 @@ async fn handle_client(stream: TcpStream, tx: Sender) { } Ok(bytes) => bytes, }; - let msg = &mut buf[0..n_read]; - let msg = match SensorMessage::<6>::decode(msg) { + + let bytes = &mut buf[0..n_read]; + if bytes.is_empty() { //eof + warn!("end of stream"); + return; + } + + tracing::trace!("{:?}", &bytes); + let decoded = match protocol::Msg::<50>::decode(bytes) { Ok(msg) => msg, Err(e) => { warn!("decode failed: {e:?}"); return; } }; - let values = msg.values; - for value in values.into_iter() { - tx.send(Event::NewReading(value)).await.unwrap(); + match decoded { + protocol::Msg::Readings(readings) => { + for value in readings.values { + tx.send(Event::NewReading(Ok(value))).await.unwrap(); + } + } + protocol::Msg::ErrorReport(report) => { + tx.send(Event::NewReading(Err(report.error))).await.unwrap() + } } - - buf.clear(); } } @@ -59,42 +71,30 @@ enum Event { NewReading(Result), } -async fn spread_updates( - mut events: mpsc::Receiver, - events_tx: &mpsc::Sender, -) -> Result<()> { +async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { let mut subscribers = Vec::new(); while let Some(event) = events.recv().await { - let reading = match event { + let msg = match event { Event::NewSub(sub) => { subscribers.push(sub); continue; } - Event::NewReading(reading) => reading, - }; - - let mut msg: SensorMessage<50> = SensorMessage::new(); - msg.values.push(reading).expect("capacity should be > 0"); - - while let Ok(event) = events.try_recv() { - match event { - Event::NewSub(sub) => { - subscribers.push(sub); - continue; - } - Event::NewReading(reading) => { - if let Err(failed_to_push) = msg.values.push(reading) { - // re queue - events_tx - .send(Event::NewReading(failed_to_push)) - .await - .unwrap(); - break; - } - } + Event::NewReading(Ok(reading)) => { + // TODO use futures-util's peekable with next_if + // to get up to 49 extra messages for efficiency + let mut readings: SensorMessage<50> = SensorMessage::new(); + readings + .values + .push(reading) + .expect("capacity should be > 0"); + protocol::Msg::Readings(readings) } - } + Event::NewReading(Err(err)) => { + let report = protocol::ErrorReport::new(err); + protocol::Msg::ErrorReport(report) + } + }; let bytes = msg.encode(); let subs = mem::take(&mut subscribers); @@ -171,7 +171,7 @@ async fn main() -> Result<()> { select! { e = register_subs(subscribe_port, &tx) => e, e = handle_data_sources(update_port, &tx) => e, - e = spread_updates(rx, &tx) => e, + e = spread_updates(rx) => e, } } diff --git a/crates/desk-sensors/src/main.rs b/crates/desk-sensors/src/main.rs index c73cff00..8854c2f5 100644 --- a/crates/desk-sensors/src/main.rs +++ b/crates/desk-sensors/src/main.rs @@ -1,5 +1,6 @@ use clap::Parser; use color_eyre::Result; +use protocol::{Msg, SensorMessage}; use std::io::{ErrorKind, Write}; use std::net::{SocketAddr, TcpStream}; use std::sync::mpsc::{self, Sender}; @@ -31,7 +32,6 @@ fn main() { send_error(&tx, error); } - let mut msg: protocol::SensorMessage<20> = protocol::SensorMessage::new(); let addr = SocketAddr::from(([127, 0, 0, 1], cli.update_port)); info!("connecting to dataserver on: {}", cli.update_port); @@ -47,15 +47,16 @@ fn main() { }; loop { - msg.values.clear(); let result = rx.recv().unwrap(); - msg.values.push(result).expect("capacity > 0"); - while let Ok(result) = rx.try_recv() { - let res = msg.values.push(result); - if res.is_err() { - break; + let msg = match result { + Ok(reading) => { + let mut readings = SensorMessage::<1>::new(); + readings.values.push(reading).expect("capacity allows one push"); + Msg::Readings(readings) } - } + Err(report) => Msg::ErrorReport(protocol::ErrorReport::new(report)), + }; + debug!("Sending message: {msg:?}"); let bytes = msg.encode(); if stream.write_all(&bytes).is_err() { diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 424a8671..3f0312f9 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -191,22 +191,50 @@ pub struct ErrorReport { pub version: u8, } -pub const SENSOR_MSG: u8 = 0; -pub const ERROR_REPORT: u8 = 1; - -pub fn decode( - mut bytes: impl AsMut<[u8]>, -) -> Result, ErrorReport>, DecodeError> { - let bytes = bytes.as_mut(); - let msg_type = bytes[0]; - let bytes = &mut bytes[1..]; - - if msg_type == SENSOR_MSG { - Ok(Ok(SensorMessage::::decode(&mut bytes[1..])?)) - } else if msg_type == ERROR_REPORT { - Ok(Err(ErrorReport::decode(&mut bytes[1..])?)) - } else { - Err(DecodeError::IncorrectMsgType(msg_type)) +#[derive(Debug)] +pub enum Msg { + Readings(SensorMessage), + ErrorReport(ErrorReport), +} + +impl Msg { + pub const READINGS: u8 = 1; + pub const ERROR_REPORT: u8 = 2; + + pub fn header(&self) -> u8 { + let header = match self { + Msg::Readings(_) => Self::READINGS, + Msg::ErrorReport(_) => Self::ERROR_REPORT, + }; + assert_ne!(header, 0, "0 is reserved for cobs encoding"); + header + } + + pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { + let bytes = bytes.as_mut(); + assert!(!bytes.is_empty(), "can not decode nothing (zero bytes)"); + + let msg_type = bytes[0]; + let mut bytes = &mut bytes[1..]; + + if msg_type == Self::READINGS { + Ok(Self::Readings(SensorMessage::::decode(&mut bytes)?)) + } else if msg_type == Self::ERROR_REPORT { + Ok(Self::ErrorReport(ErrorReport::decode(&mut bytes)?)) + } else { + Err(DecodeError::IncorrectMsgType(msg_type)) + } + } + + #[cfg(feature = "alloc")] + pub fn encode(&self) -> Vec { + let mut bytes = match self { + Msg::Readings(readings) => readings.encode(), + Msg::ErrorReport(report) => report.encode(), + }; + + bytes.insert(0, self.header()); + bytes } } @@ -269,6 +297,11 @@ impl ErrorReport { Self { error, version: 0 } } + #[cfg(feature = "alloc")] + pub fn encode(&self) -> Vec { + postcard::to_allocvec_cobs(self).expect("Encoding should not fail") + } + /// Buffer should be at least Self::ENCODED_SIZE long. The returned slice contains /// the serialized data. It can be shorter then the input buffer. pub fn encode_slice<'a>(&self, buf: &'a mut [u8]) -> &'a mut [u8] { diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index 8ce66f3f..2d3b060c 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -4,6 +4,7 @@ use std::thread; use color_eyre::eyre::WrapErr; use color_eyre::{Help, Result}; +use data_server::SubMessage; mod tui; @@ -27,8 +28,8 @@ fn main() -> Result<()> { .next() .wrap_err("Error getting next reading from server")? { - Ok(reading) => Update::Reading(reading), - Err(error) => Update::Error(error), + SubMessage::Reading(reading) => Update::Reading(reading), + SubMessage::ErrorReport(error) => Update::Error(error), }; tx.send(update).unwrap(); From ec6f03d89f944e6ef9f1f8380d047afc79dcd13c Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 14 Jun 2024 13:53:02 +0200 Subject: [PATCH 132/687] adds method to find readings affected by errors --- crates/protocol/src/button.rs | 100 +++++++++++++ crates/protocol/src/error_tomato.rs | 39 +++++ crates/protocol/src/large_bedroom.rs | 36 ++++- crates/protocol/src/large_bedroom/bed.rs | 91 ++++++++---- crates/protocol/src/large_bedroom/desk.rs | 74 +++++----- crates/protocol/src/lib.rs | 171 ++++------------------ crates/protocol/src/tomato.rs | 39 +++++ 7 files changed, 341 insertions(+), 209 deletions(-) create mode 100644 crates/protocol/src/button.rs create mode 100644 crates/protocol/src/error_tomato.rs create mode 100644 crates/protocol/src/tomato.rs diff --git a/crates/protocol/src/button.rs b/crates/protocol/src/button.rs new file mode 100644 index 00000000..79f7fb6f --- /dev/null +++ b/crates/protocol/src/button.rs @@ -0,0 +1,100 @@ +use serde::{Deserialize, Serialize}; + +// Duration of the press in milliseconds +#[derive( + Clone, + Copy, + Debug, + Serialize, + Deserialize, + postcard::experimental::max_size::MaxSize, + defmt::Format, +)] +pub struct Press(pub u16); + +impl Press { + pub fn is_long(&self) -> bool { + if self.0 > 300 { + true + } else { + false + } + } +} + +/// turns an enum of empty variants into one with [`Press`](crate::Press) inside each variant also +/// adds a method `press(&self)` that returns an instance of [`Press`](crate::Press). It can be +/// used to quickly find out if a button event is a long or short press. +/// +/// Example: +/// +/// button_enum! { +/// DeskButton { +/// OneOfFour, +/// TwoOfFour, +/// } +/// } +/// +macro_rules! button_enum { + ( + $(#[$outer:meta])* + $name:ident {$($variant:ident,)*}) => { + #[derive(strum::VariantNames)] + #[derive( + Clone, + Copy, + Debug, + serde::Serialize, + serde::Deserialize, + defmt::Format, + postcard::experimental::max_size::MaxSize + )] + $(#[$outer])* // docs + /// SAFETY: must be repr(u8) or id fn will create undefined behaviour + #[repr(u8)] + pub enum $name { + $($variant(crate::button::Press),)* + } + + impl $name { + pub fn press(&self) -> crate::button::Press { + match self { + $(Self::$variant(d) => *d,)* + } + } + } + + impl Into for $name { + fn into(self) -> f32 { + match self { + $(Self::$variant(p) if p.is_long() => 2.0,)* + $(Self::$variant(_) => 1.0,)* + } + } + } + + #[cfg(feature = "alloc")] + impl crate::tomato::Tomato for $name { + fn inner<'a>(&'a self) -> crate::tomato::TomatoItem<'a> { + crate::tomato::TomatoItem::Leaf((*self).into()) + } + fn name(&self) -> String { + let dbg_repr = format!("{:?}", self); + dbg_repr + .split_once('(') + .map(|(name, _)| name) + .unwrap_or("-") + .to_string() + } + fn id(&self) -> crate::tomato::TomatoId { + // SAFETY: Because `Self` is marked `repr(u8)`, its layout is a + // `repr(C)` `union` between `repr(C)` structs, each of which + // has the `u8` discriminant as its first field, so we can read + // the discriminant without offsetting the pointer. + let discriminant = unsafe { *<*const _>::from(self).cast::() }; + discriminant as crate::tomato::TomatoId + } + } + }; +} +pub(crate) use button_enum; diff --git a/crates/protocol/src/error_tomato.rs b/crates/protocol/src/error_tomato.rs new file mode 100644 index 00000000..034d12ed --- /dev/null +++ b/crates/protocol/src/error_tomato.rs @@ -0,0 +1,39 @@ +pub type ErrorTomatoId = u8; +#[derive(Debug)] +pub enum ErrorTomatoItem<'a> { + Leaf(String), + Node(&'a dyn ErrorTomato), +} + +pub trait ErrorTomato: core::fmt::Debug { + fn inner<'a>(&'a self) -> ErrorTomatoItem<'a>; + fn name(&self) -> String { + let dbg_repr = format!("{:?}", self); + dbg_repr + .split_once('(') + .map(|(name, _)| name) + .unwrap_or("-") + .to_string() + } + fn id(&self) -> ErrorTomatoId; +} + +macro_rules! error_all_nodes { + ($name:ident; $variant:ident; $($var:ident),*) => { + impl crate::error_tomato::ErrorTomato for $name { + fn inner<'a>(&'a self) -> crate::error_tomato::ErrorTomatoItem<'a> { + match self { + $( + $name::$var(inner) => crate::error_tomato::ErrorTomatoItem::Node(inner as &dyn crate::error_tomato::ErrorTomato) + ),* + } + } + + fn id(&self) -> crate::error_tomato::ErrorTomatoId { + $variant::from(self) as crate::error_tomato::ErrorTomatoId + } + } + }; +} + +pub(crate) use error_all_nodes; diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index 96bcd1ce..ed235d03 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -2,7 +2,7 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; #[cfg(feature = "alloc")] -use crate::{all_nodes, Tomato}; +use crate::all_nodes; pub mod bed; pub mod desk; @@ -19,12 +19,44 @@ pub enum Reading { #[cfg(feature = "alloc")] all_nodes! {Reading; ReadingDiscriminants; Bed, Desk} -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +#[derive( + strum::EnumDiscriminants, + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + Eq, + PartialEq, +)] pub enum Error { Bed(bed::Error), Desk(desk::Error), } +impl Error { + pub fn broken_readings(&self) -> impl Iterator { + match self { + Error::Bed(error) => error + .affected_readings() + .into_iter() + .cloned() + .map(Reading::Bed), + Error::Desk(_) => todo!(), + } + } +} + +impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Error::Bed(error) => write!(f, "{}", error), + Error::Desk(error) => write!(f, "{}", error), + } + } +} + #[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] pub enum Device { Bed(bed::Device), diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index eaafad00..1e65c5c2 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -1,6 +1,6 @@ use crate::button_enum; #[cfg(feature = "alloc")] -use crate::{Tomato, TomatoItem}; +use crate::tomato::{Tomato, TomatoId, TomatoItem}; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -96,8 +96,8 @@ impl Tomato for Reading { TomatoItem::Leaf(val) } - fn id(&self) -> crate::TomatoId { - ReadingDiscriminants::from(self) as crate::TomatoId + fn id(&self) -> TomatoId { + ReadingDiscriminants::from(self) as TomatoId } } @@ -110,10 +110,22 @@ pub enum Error { } impl Error { - pub fn broken_readings(&self) -> &[ReadingDiscriminants] { + pub fn affected_readings(&self) -> &'static [Reading] { match self { - Self::Running(sensor_err) | Self::Setup(sensor_err) => sensor_err.broken_readings(), - Self::SetupTimedOut(device) | Self::Timeout(device) => device.broken_readings(), + Self::Running(sensor_err) | Self::Setup(sensor_err) => sensor_err.device(), + Self::SetupTimedOut(device) | Self::Timeout(device) => device.clone(), + } + .broken_readings() + } +} + +impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Error::Running(e) => write!(f, "{} ran into error: {e}", e.device()), + Error::Setup(e) => write!(f, "{} errored during setup: {e}", e.device()), + Error::SetupTimedOut(d) => write!(f, "{d} timed out during setup"), + Error::Timeout(d) => write!(f, "{d} timed out running"), } } } @@ -127,20 +139,31 @@ pub enum SensorError { Sps30(heapless::String<200>), } +impl core::fmt::Display for SensorError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + SensorError::Sht31(e) => write!(f, "{e}"), + SensorError::Bme680(e) => write!(f, "{e}"), + SensorError::Max44(e) => write!(f, "{e}"), + SensorError::Mhz14(e) => write!(f, "{e}"), + SensorError::Sps30(e) => write!(f, "{e}"), + } + } +} + impl MaxSize for SensorError { const POSTCARD_MAX_SIZE: usize = 201; } impl SensorError { - pub fn broken_readings(&self) -> &[ReadingDiscriminants] { - let device = match self { + pub fn device(&self) -> Device { + match self { SensorError::Sht31(_) => Device::Sht31, SensorError::Bme680(_) => Device::Bme680, SensorError::Max44(_) => Device::Max44, SensorError::Mhz14(_) => Device::Mhz14, SensorError::Sps30(_) => Device::Sps30, - }; - device.broken_readings() + } } } @@ -153,30 +176,36 @@ pub enum Device { Sps30, } +impl core::fmt::Display for Device { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Device::Sht31 => write!(f, "Sht31"), + Device::Bme680 => write!(f, "Bme680"), + Device::Max44 => write!(f, "Max44"), + Device::Mhz14 => write!(f, "Mhz14"), + Device::Sps30 => write!(f, "Sps30"), + } + } +} + impl Device { - pub fn broken_readings(&self) -> &'static [ReadingDiscriminants] { + pub fn broken_readings(&self) -> &'static [Reading] { match self { - Device::Sht31 => &[ - ReadingDiscriminants::Temperature, - ReadingDiscriminants::Humidity, - ], - Device::Bme680 => &[ - ReadingDiscriminants::GassResistance, - ReadingDiscriminants::Pressure, - ], - Device::Max44 => &[ReadingDiscriminants::Brightness], - Device::Mhz14 => &[ReadingDiscriminants::Co2], + Device::Sht31 => &[Reading::Temperature(0.0), Reading::Humidity(0.0)], + Device::Bme680 => &[Reading::GassResistance(0.0), Reading::Pressure(0.0)], + Device::Max44 => &[Reading::Brightness(0.0)], + Device::Mhz14 => &[Reading::Co2(0)], Device::Sps30 => &[ - ReadingDiscriminants::MassPm1_0, - ReadingDiscriminants::MassPm2_5, - ReadingDiscriminants::MassPm4_0, - ReadingDiscriminants::MassPm10, - ReadingDiscriminants::MassPm0_5, - ReadingDiscriminants::NumberPm1_0, - ReadingDiscriminants::NumberPm2_5, - ReadingDiscriminants::NumberPm4_0, - ReadingDiscriminants::NumberPm10, - ReadingDiscriminants::TypicalParticleSize, + Reading::MassPm1_0(0.0), + Reading::MassPm2_5(0.0), + Reading::MassPm4_0(0.0), + Reading::MassPm10(0.0), + Reading::MassPm0_5(0.0), + Reading::NumberPm1_0(0.0), + Reading::NumberPm2_5(0.0), + Reading::NumberPm4_0(0.0), + Reading::NumberPm10(0.0), + Reading::TypicalParticleSize(0.0), ], } } diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index 76a66d36..1c9a5220 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use crate::button_enum; #[cfg(feature = "alloc")] -use crate::{Tomato, TomatoItem}; +use crate::tomato::{Tomato, TomatoItem}; button_enum! { /// No these are not borg, these are buttons on a string of cat5. @@ -42,38 +42,38 @@ impl Tomato for Reading { TomatoItem::Leaf(val) } - fn id(&self) -> crate::TomatoId { - ReadingDiscriminants::from(self) as crate::TomatoId + fn id(&self) -> crate::tomato::TomatoId { + ReadingDiscriminants::from(self) as crate::tomato::TomatoId } } #[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] pub enum Error { Running(SensorError), - Setup(SetupError), + Setup(SensorError), SetupTimedOut(Device), Timeout(Device), } impl Error { - pub fn broken_readings(&self) -> &[ReadingDiscriminants] { + pub fn affected_readings(&self) -> &'static [Reading] { match self { - Self::Running(sensor_err) => sensor_err.broken_readings(), - Self::Setup(sensor_err) => sensor_err.broken_readings(), - Self::SetupTimedOut(device) | Self::Timeout(device) => device.broken_readings(), + Self::Running(sensor_err) => sensor_err.device().affected_readings(), + Self::Setup(sensor_err) => sensor_err.device().affected_readings(), + Self::SetupTimedOut(device) | Self::Timeout(device) => device.affected_readings(), } } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, Eq, PartialEq)] -pub enum SetupError { - BmeError(heapless::String<200>), - Gpio(heapless::String<200>), - I2c(heapless::String<200>), -} - -impl MaxSize for SetupError { - const POSTCARD_MAX_SIZE: usize = 200+1; +impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Error::Running(e) => write!(f, "{} ran into error: {e}", e.device()), + Error::Setup(e) => write!(f, "{} errored during setup: {e}", e.device()), + Error::SetupTimedOut(d) => write!(f, "{d} timed out during setup"), + Error::Timeout(d) => write!(f, "{d} timed out while running"), + } + } } #[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, Eq, PartialEq)] @@ -83,28 +83,24 @@ pub enum SensorError { } impl MaxSize for SensorError { - const POSTCARD_MAX_SIZE: usize = 200+1; + const POSTCARD_MAX_SIZE: usize = 200 + 1; } impl SensorError { - pub fn broken_readings(&self) -> &'static [ReadingDiscriminants] { - let device = match self { + pub fn device(&self) -> Device { + match self { SensorError::BmeError(_) => Device::Bme280, SensorError::Gpio(_) => Device::Gpio, - }; - - device.broken_readings() + } } } -impl SetupError { - pub fn broken_readings(&self) -> &'static [ReadingDiscriminants] { - let device = match self { - SetupError::BmeError(_) | SetupError::I2c(_) => Device::Bme280, - SetupError::Gpio(_) => Device::Gpio, - }; - - device.broken_readings() +impl core::fmt::Display for SensorError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + SensorError::BmeError(e) => write!(f, "{e}"), + SensorError::Gpio(e) => write!(f, "{e}"), + } } } @@ -114,13 +110,19 @@ pub enum Device { Gpio, } +impl core::fmt::Display for Device { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Device::Bme280 => write!(f, "Bme280"), + Device::Gpio => write!(f, "Gpio"), + } + } +} + impl Device { - pub fn broken_readings(&self) -> &'static [ReadingDiscriminants] { + pub fn affected_readings(&self) -> &'static [Reading] { match self { - Device::Bme280 => &[ - ReadingDiscriminants::Temperature, - ReadingDiscriminants::Humidity, - ], + Device::Bme280 => &[Reading::Temperature(0.0), Reading::Humidity(0.0)], Device::Gpio => todo!(), } } diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 3f0312f9..1b4fc397 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -6,148 +6,37 @@ use serde::{Deserialize, Serialize}; pub mod large_bedroom; pub mod small_bedroom; -/// turns an enum of empty variants into one with [`Press`](crate::Press) inside each variant also -/// adds a method `press(&self)` that returns an instance of [`Press`](crate::Press). It can be -/// used to quickly find out if a button event is a long or short press. -/// -/// Example: -/// -/// button_enum! { -/// DeskButton { -/// OneOfFour, -/// TwoOfFour, -/// } -/// } -/// -macro_rules! button_enum { - ( - $(#[$outer:meta])* - $name:ident {$($variant:ident,)*}) => { - #[derive(strum::VariantNames)] - #[derive( - Clone, - Copy, - Debug, - serde::Serialize, - serde::Deserialize, - defmt::Format, - postcard::experimental::max_size::MaxSize - )] - $(#[$outer])* // docs - /// SAFETY: must be repr(u8) or id fn will create undefined behaviour - #[repr(u8)] - pub enum $name { - $($variant(crate::Press),)* - } - - impl $name { - pub fn press(&self) -> crate::Press { - match self { - $(Self::$variant(d) => *d,)* - } - } - } +pub mod button; +pub(crate) use button::button_enum; - impl Into for $name { - fn into(self) -> f32 { - match self { - $(Self::$variant(p) if p.is_long() => 2.0,)* - $(Self::$variant(_) => 1.0,)* - } - } - } - - #[cfg(feature = "alloc")] - impl crate::Tomato for $name { - fn inner<'a>(&'a self) -> crate::TomatoItem<'a> { - crate::TomatoItem::Leaf((*self).into()) - } - fn name(&self) -> String { - let dbg_repr = format!("{:?}", self); - dbg_repr - .split_once('(') - .map(|(name, _)| name) - .unwrap_or("-") - .to_string() - } - fn id(&self) -> crate::TomatoId { - // SAFETY: Because `Self` is marked `repr(u8)`, its layout is a - // `repr(C)` `union` between `repr(C)` structs, each of which - // has the `u8` discriminant as its first field, so we can read - // the discriminant without offsetting the pointer. - let discriminant = unsafe { *<*const _>::from(self).cast::() }; - discriminant as crate::TomatoId - } - } - }; -} -pub(crate) use button_enum; +#[cfg(feature = "alloc")] +pub mod tomato; +#[cfg(feature = "alloc")] +pub(crate) use tomato::all_nodes; -// Duration of the press in milliseconds #[derive( + strum::EnumDiscriminants, + strum::VariantNames, Clone, - Copy, Debug, + defmt::Format, Serialize, Deserialize, - postcard::experimental::max_size::MaxSize, - defmt::Format, + MaxSize, )] -pub struct Press(pub u16); - -impl Press { - pub fn is_long(&self) -> bool { - if self.0 > 300 { - true - } else { - false - } - } -} - -#[cfg(feature = "alloc")] -type TomatoId = u8; -#[cfg(feature = "alloc")] -#[derive(Debug)] -pub enum TomatoItem<'a> { - Leaf(f32), - Node(&'a dyn Tomato), +#[strum_discriminants(derive(Hash))] +pub enum Reading { + LargeBedroom(large_bedroom::Reading), + // SmallBedroom(small_bedroom::Reading), + // Test, } -#[cfg(feature = "alloc")] -pub trait Tomato: core::fmt::Debug { - fn inner<'a>(&'a self) -> TomatoItem<'a>; - fn name(&self) -> String { - let dbg_repr = format!("{:?}", self); - dbg_repr - .split_once('(') - .map(|(name, _)| name) - .unwrap_or("-") - .to_string() +impl Reading { + pub fn version() -> u8 { + 0u8 } - fn id(&self) -> TomatoId; } -#[cfg(feature = "alloc")] -macro_rules! all_nodes { - ($name:ident; $variant:ident; $($var:ident),*) => { - impl Tomato for $name { - fn inner<'a>(&'a self) -> crate::TomatoItem<'a> { - match self { - $( - $name::$var(inner) => crate::TomatoItem::Node(inner as &dyn Tomato) - ),* - } - } - - fn id(&self) -> crate::TomatoId { - $variant::from(self) as crate::TomatoId - } - } - }; -} -#[cfg(feature = "alloc")] -pub(crate) use all_nodes; #[cfg(feature = "alloc")] all_nodes! {Reading; ReadingDiscriminants; LargeBedroom} //, Test} @@ -161,21 +50,23 @@ all_nodes! {Reading; ReadingDiscriminants; LargeBedroom} //, Test} Deserialize, MaxSize, )] -#[strum_discriminants(derive(Hash))] -pub enum Reading { - LargeBedroom(large_bedroom::Reading), - // SmallBedroom(small_bedroom::Reading), - // Test, -} - -#[derive(strum::VariantNames, Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] pub enum Error { LargeBedroom(large_bedroom::Error), } -impl Reading { - pub fn version() -> u8 { - 0u8 +impl Error { + pub fn affected_readings(&self) -> impl Iterator { + match self { + Error::LargeBedroom(error) => error.broken_readings().map(Reading::LargeBedroom), + } + } +} + +impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Error::LargeBedroom(error) => write!(f, "{}", error), + } } } diff --git a/crates/protocol/src/tomato.rs b/crates/protocol/src/tomato.rs new file mode 100644 index 00000000..aa378808 --- /dev/null +++ b/crates/protocol/src/tomato.rs @@ -0,0 +1,39 @@ +pub type TomatoId = u8; +#[derive(Debug)] +pub enum TomatoItem<'a> { + Leaf(f32), + Node(&'a dyn Tomato), +} + +pub trait Tomato: core::fmt::Debug { + fn inner<'a>(&'a self) -> TomatoItem<'a>; + fn name(&self) -> String { + let dbg_repr = format!("{:?}", self); + dbg_repr + .split_once('(') + .map(|(name, _)| name) + .unwrap_or("-") + .to_string() + } + fn id(&self) -> TomatoId; +} + +macro_rules! all_nodes { + ($name:ident; $variant:ident; $($var:ident),*) => { + impl crate::tomato::Tomato for $name { + fn inner<'a>(&'a self) -> crate::tomato::TomatoItem<'a> { + match self { + $( + $name::$var(inner) => crate::tomato::TomatoItem::Node(inner as &dyn crate::tomato::Tomato) + ),* + } + } + + fn id(&self) -> crate::tomato::TomatoId { + $variant::from(self) as crate::tomato::TomatoId + } + } + }; +} + +pub(crate) use all_nodes; From b8ee45839b0bcb2df4d66aea27655393f68e35a6 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 14 Jun 2024 13:53:23 +0200 Subject: [PATCH 133/687] updated tui to report errors --- crates/sensor-tui/src/tui.rs | 2 +- crates/sensor-tui/src/tui/reading.rs | 64 +++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index a486e0bb..5ecdc083 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -128,7 +128,7 @@ pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { readings.add(reading); } Ok(Update::Error(err)) => { - tracing::warn!("sensor error: {err:?}"); + readings.add_error(err) } _ => (), } diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index 2370aece..b8660464 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -1,6 +1,6 @@ use histogram::Histogram; -use protocol::large_bedroom::Error; -use protocol::{Reading, Tomato, TomatoItem}; +use protocol::Error; +use protocol::{tomato::Tomato, tomato::TomatoItem, Reading}; use ratatui::{text::Line, widgets::Bar}; use std::collections::HashMap; use std::{collections::VecDeque, time::Instant}; @@ -11,6 +11,7 @@ pub struct SensorInfo { timing: Histogram, history: VecDeque<(Instant, f32)>, condition: Result<(), Error>, + log: Vec<(Instant, Error)>, } impl SensorInfo { @@ -53,8 +54,7 @@ pub struct Readings { pub data: HashMap, } -fn add_leaf(name: String, val: f32, tree: &mut TreeItem<'static, TreeKey>, key: TreeKey) { - let text = format!("{}: {}", name, val); +fn add_leaf(text: String, tree: &mut TreeItem<'static, TreeKey>, key: TreeKey) { let new_item = TreeItem::new_leaf(key, text.clone()); // todo is exists its fine handle that let _ignore_existing = tree.add_child(new_item); // errors when identifier already exists @@ -127,6 +127,33 @@ impl Readings { self.record_data(reading); } + pub fn add_error(&mut self, error: Error) { + self.update_tree_err(&error); + self.record_error(error); + } + + fn record_error(&mut self, error: Error) { + for broken in error.affected_readings() { + let (key, name, _) = extract_leaf_info(&broken); + + if let Some(info) = self.data.get_mut(&key) { + info.condition = Err(error.clone()); + info.log.push((Instant::now(), error.clone())); + } else { + self.data.insert( + key, + SensorInfo { + name, + timing: Histogram::new(4, 24).unwrap(), + history: VecDeque::new(), + condition: Err(error.clone()), + log: vec![(Instant::now(), error.clone())], + }, + ); + } + } + } + fn record_data(&mut self, reading: Reading) { let (key, name, val) = extract_leaf_info(&reading); @@ -148,6 +175,7 @@ impl Readings { timing: Histogram::new(4, 24).unwrap(), history, condition: Ok(()), + log: Vec::new(), }, ); } @@ -164,7 +192,8 @@ impl Readings { loop { match tomato.inner() { TomatoItem::Leaf(val) => { - add_leaf(tomato.name(), val, tree, key); + let text = format!("{}: {}", tomato.name(), val); + add_leaf(text, tree, key); return; } TomatoItem::Node(inner) => { @@ -175,6 +204,31 @@ impl Readings { } } + fn update_tree_err(&mut self, error: &Error) { + for broken in error.affected_readings() { + let (key, _, _) = extract_leaf_info(&broken); + + let mut tree = add_root(&broken as &dyn Tomato, &mut self.ground); + let mut tomato = match broken.inner() { + TomatoItem::Leaf(_) => unreachable!("no values at level 0"), + TomatoItem::Node(inner) => inner, + }; + loop { + match tomato.inner() { + TomatoItem::Leaf(_) => { + let text = format!("{}: {:?}", tomato.name(), error); + add_leaf(text, tree, key); + return; + } + TomatoItem::Node(inner) => { + tree = add_node(tomato, tree); + tomato = inner; + } + }; + } + } + } + pub fn histogram_all(&self) -> Vec { let mut all = Histogram::new(4, 24).unwrap(); for (_, val) in self.data.iter() { From 5b6ab7a92ed11f18e5f89375b88a4de2ef8cde96 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 14 Jun 2024 13:54:14 +0200 Subject: [PATCH 134/687] fixes network + robust sensor drivers (auto re-init timeout etc) --- sensor-nodes/bed-sensors/.cargo/config.toml | 2 +- sensor-nodes/bed-sensors/src/channel.rs | 3 +- sensor-nodes/bed-sensors/src/main.rs | 43 +---- sensor-nodes/bed-sensors/src/network.rs | 51 ++++-- sensor-nodes/bed-sensors/src/sensors.rs | 61 +++++-- sensor-nodes/bed-sensors/src/sensors/fast.rs | 11 +- sensor-nodes/bed-sensors/src/sensors/retry.rs | 149 +++++------------- .../src/sensors/retry/reinit_on_error.rs | 110 +++++++++++++ .../src/sensors/retry/reset_on_error.rs | 54 +++++++ .../src/sensors/retry/retry_init.rs | 67 ++++++++ sensor-nodes/bed-sensors/src/sensors/slow.rs | 138 +++++++--------- sensor-nodes/setup.sh | 53 +++++++ 12 files changed, 480 insertions(+), 262 deletions(-) create mode 100644 sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs create mode 100644 sensor-nodes/bed-sensors/src/sensors/retry/reset_on_error.rs create mode 100644 sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs create mode 100755 sensor-nodes/setup.sh diff --git a/sensor-nodes/bed-sensors/.cargo/config.toml b/sensor-nodes/bed-sensors/.cargo/config.toml index 590ccd28..72829582 100644 --- a/sensor-nodes/bed-sensors/.cargo/config.toml +++ b/sensor-nodes/bed-sensors/.cargo/config.toml @@ -10,7 +10,7 @@ target = "thumbv7em-none-eabihf" [env] DEFMT_LOG = "debug,sps30_async=info,bosch_bme680=info" -EMBASSY_EXECUTOR_TASK_ARENA_SIZE="8000" +EMBASSY_EXECUTOR_TASK_ARENA_SIZE="9000" # [unstable] # build-std = ["core"] diff --git a/sensor-nodes/bed-sensors/src/channel.rs b/sensor-nodes/bed-sensors/src/channel.rs index ce4073c9..f88318a2 100644 --- a/sensor-nodes/bed-sensors/src/channel.rs +++ b/sensor-nodes/bed-sensors/src/channel.rs @@ -57,6 +57,7 @@ impl Queues { } pub fn queue_error(&self, error: error_cache::Error) { + defmt::debug!("queueing error: {:?}", error); // unwrap safe: is not used in interrupts let mut recent_errors = defmt::unwrap!(self.recent_errors.try_lock()); if self.recent_is_since.elapsed() > Duration::from_secs(60 * 5) { @@ -69,7 +70,7 @@ impl Queues { let Ok(()) = self.error_queue.try_send(error.clone()) else { return; }; - recent_errors.write(error) + recent_errors.write(error); } pub fn send_p0(&self, value: Reading) { diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index 41e5cb18..7d71106d 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -10,7 +10,6 @@ use embassy_net_wiznet::{chip::W5500, Device, Runner, State}; use embassy_stm32::exti::ExtiInput; use embassy_stm32::gpio::{Level, Output, Pull, Speed}; use embassy_stm32::i2c::{self, I2c}; -use embassy_stm32::interrupt; use embassy_stm32::mode::Async; use embassy_stm32::peripherals::IWDG; use embassy_stm32::spi::{Config as SpiConfig, Spi}; @@ -42,40 +41,6 @@ embassy_stm32::bind_interrupts!(struct Irqs { USART2 => embassy_stm32::usart::InterruptHandler; }); -use embassy_executor::InterruptExecutor; -static EXECUTOR_HIGH: InterruptExecutor = InterruptExecutor::new(); - -use embassy_stm32::interrupt::InterruptExt; -#[interrupt] -unsafe fn USART6() { - EXECUTOR_HIGH.on_interrupt() -} - -#[embassy_executor::task] -async fn print_if_running_task() -> ! { - // use embassy_time::Instant; - // loop { - // let mut now = Instant::now(); - // let mut biggest = 0; - // for _ in 0..1000 { - // Timer::after_millis(1).await; - // let new_now = Instant::now(); - // let elapsed = (new_now - now).as_millis(); - // now = new_now; - // - // if elapsed > biggest { - // biggest = elapsed; - // } - // } - // defmt::info!("still running, largest delay was: {}ms", biggest); - // } - - loop { - Timer::after_secs(1).await; - defmt::info!("still running"); - } -} - type EthernetSPI = ExclusiveDevice, Output<'static>, Delay>; #[embassy_executor::task] async fn ethernet_task( @@ -139,7 +104,7 @@ async fn main(spawner: Spawner) { )); let mut usart_config = usart::Config::default(); - usart_config.baudrate = 115200; + usart_config.baudrate = 115_200; usart_config.data_bits = DataBits::DataBits8; usart_config.stop_bits = StopBits::STOP1; // usart_config.parity = Parity::ParityEven; @@ -217,10 +182,6 @@ async fn main(spawner: Spawner) { // Launch network task unwrap!(spawner.spawn(net_task(stack))); - embassy_stm32::interrupt::USART6.set_priority(embassy_stm32::interrupt::Priority::P6); - let spawner = EXECUTOR_HIGH.start(embassy_stm32::interrupt::USART6); - unwrap!(spawner.spawn(print_if_running_task())); - let publish = Queues::new(); let send_published = network::send_published(stack, &publish); pin_mut!(send_published); @@ -231,7 +192,7 @@ async fn main(spawner: Spawner) { let init_then_measure = sensors::init_then_measure(&publish, i2c, usart_mhz, usart_sps30); let res = select::select(send_and_pet_dog, init_then_measure).await; let unrecoverable_err = match res { - Either::First(_) => defmt::unreachable!(), + Either::First(network::ConnDownTooLong) => cortex_m::peripheral::SCB::sys_reset(), Either::Second(Ok(())) => defmt::unreachable!(), Either::Second(Err(err)) => err, }; diff --git a/sensor-nodes/bed-sensors/src/network.rs b/sensor-nodes/bed-sensors/src/network.rs index 885ce02b..da336e5a 100644 --- a/sensor-nodes/bed-sensors/src/network.rs +++ b/sensor-nodes/bed-sensors/src/network.rs @@ -1,4 +1,4 @@ -use defmt::{debug, info, unwrap, warn}; +use defmt::{debug, error, info, unwrap, warn}; use embassy_net::driver::Driver; use embassy_net::tcp::TcpSocket; use embassy_net::{Ipv4Address, Stack}; @@ -6,11 +6,11 @@ use embassy_time::{with_timeout, Duration, Instant, Timer}; use embedded_io_async::Write; use protocol::{ErrorReport, SensorMessage}; -use crate::channel::{QueueItem, PriorityValue, Queues}; +use crate::channel::{PriorityValue, QueueItem, Queues}; type Msg = SensorMessage<10>; -async fn collect_pending(publish: &Queues, reading: PriorityValue) -> Msg { +async fn collect_pending(publish: &Queues, reading: PriorityValue) -> SensorMessage<10> { let mut msg = Msg::new(); let low_priority = reading.low_priority(); unwrap!(msg.values.push(reading.value)); @@ -46,12 +46,16 @@ async fn get_messages<'a>(publish: &Queues, buf: &'a mut [u8]) -> &'a [u8] { match next { QueueItem::Reading(reading) => { let msg = collect_pending(publish, reading).await; - msg.encode_slice(buf) + let encoded_len = msg.encode_slice(&mut buf[1..]).len(); + buf[0] = protocol::Msg::<0>::READINGS; + &buf[..=encoded_len] } QueueItem::Error(error) => { let error = protocol::large_bedroom::Error::Bed(error.into()); let error = protocol::Error::LargeBedroom(error); - ErrorReport::new(error).encode_slice(buf) + let encoded_len = ErrorReport::new(error).encode_slice(&mut buf[1..]).len(); + buf[0] = protocol::Msg::<0>::ERROR_REPORT; + &buf[..=encoded_len] } } } @@ -60,34 +64,55 @@ const fn max(a: usize, b: usize) -> usize { [a, b][(a < b) as usize] } -pub async fn send_published(stack: &Stack, publish: &Queues) { +pub struct ConnDownTooLong; +pub async fn send_published(stack: &Stack, publish: &Queues) -> ConnDownTooLong { let mut rx_buffer = [0; 1024]; let mut tx_buffer = [0; max(Msg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE) * 2]; let mut encoded_msg_buffer = [0; max(Msg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE)]; let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); - // socket.set_timeout(Some(Duration::from_secs(5))); - let host_addr = Ipv4Address::new(192, 168, 1, 46); + socket.set_timeout(Some(Duration::from_secs(5))); + let host_addr = Ipv4Address::new(192, 168, 1, 43); let host_port = 1234; + // connection sometimes does not recover from going down + // track how long it has been down and reset the chip if + // it has been down too long. + let mut since_last_connection: Option = None; + let mut connected = false; + debug!("Configured socket and connecting"); loop { - let connected = socket.remote_endpoint().is_some(); + if !connected { + match since_last_connection { + Some(went_down) if went_down.elapsed() > Duration::from_secs(20) => { + error!("connection down to long, might have gotten stuck: resetting"); + return ConnDownTooLong; + } + Some(_) => (), + None => { + since_last_connection = Some(Instant::now()); + warn!("warning connection down, resetting if not up soon"); + } + } + } + if !connected { if let Err(e) = socket.connect((host_addr, host_port)).await { warn!("connect error: {:?}", e); Timer::after_secs(1).await; continue; - } else { - info!("(re-)connected"); - // prevent out-dated data from being send - publish.clear().await; } + info!("(re-)connected"); + connected = true; + // prevent out-dated data from being send + publish.clear().await; } let to_send = get_messages(publish, &mut encoded_msg_buffer).await; if let Err(e) = socket.write_all(to_send).await { warn!("write error: {:?}", e); + connected = false; } } } diff --git a/sensor-nodes/bed-sensors/src/sensors.rs b/sensor-nodes/bed-sensors/src/sensors.rs index 62a70d78..8c12c6be 100644 --- a/sensor-nodes/bed-sensors/src/sensors.rs +++ b/sensor-nodes/bed-sensors/src/sensors.rs @@ -6,18 +6,20 @@ use embassy_stm32::mode::Async; use embassy_stm32::usart::Uart; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; -use embassy_time::{with_timeout, Delay, Duration}; +use embassy_time::Delay; use mhzx::MHZ; use protocol::large_bedroom::bed::Device; use sps30_async::Sps30; use crate::channel::Queues; use crate::error_cache::{Error, SensorError}; -use crate::sensors::retry::{Bme680Driver, Max44Driver, Sht31Driver}; +use crate::sensors::retry::{Bme680Driver, Max44Driver, Sht31Driver, Sps30Driver}; + +use self::retry::Driver; pub mod fast; -pub mod slow; pub mod retry; +pub mod slow; // Todo make failed init not critical. Keep trying init in background // while we are measuring @@ -38,6 +40,9 @@ pub mod concrete_types { pub type ConcreteRx<'a> = RingBufferedUartRx<'a>; } +const SPS30_UART_BUF_SIZE: usize = 100; +const SPS30_DRIVER_BUF_SIZE: usize = 2 * SPS30_UART_BUF_SIZE; + pub async fn init_then_measure( publish: &Queues, i2c: Mutex>, @@ -45,9 +50,9 @@ pub async fn init_then_measure( usart_sps: Uart<'static, Async>, ) -> Result<(), Error> { info!("initializing sensors"); - let bme = Bme680Driver::new(&i2c); - let max44009 = Max44Driver::new(&i2c); - let sht = Sht31Driver::new(&i2c); + let bme = Bme680Driver::new(&i2c, Device::Bme680); + let max44009 = Max44Driver::new(&i2c, Device::Max44); + let sht = Sht31Driver::new(&i2c, Device::Sht31); let (tx, rx) = usart_mhz.split(); let mut usart_buf = [0u8; 9 * 10]; // 9 byte messages @@ -55,13 +60,9 @@ pub async fn init_then_measure( let mhz = MHZ::from_tx_rx(tx, rx); let (tx, rx) = usart_sps.split(); - let mut usart_buf = [0u8; 100]; + let mut usart_buf = [0u8; SPS30_UART_BUF_SIZE]; let rx = rx.into_ring_buffered(&mut usart_buf); - let sps30 = with_timeout(Duration::from_millis(100), Sps30::from_tx_rx(tx, rx, Delay)) - .await - .map_err(|_| Error::SetupTimedOut(Device::Sps30))? - .map_err(SensorError::Sps30) - .map_err(Error::Setup)?; + let sps30 = Sps30Driver::init(tx, rx); let sensors_fast = fast::read(max44009, /*buttons,*/ publish); let sensors_slow = slow::read(sht, bme, mhz, sps30, publish); @@ -69,3 +70,39 @@ pub async fn init_then_measure( defmt::unreachable!(); } + +use concrete_types::ConcreteRx as Rx; +use concrete_types::ConcreteTx as Tx; +impl<'a> Driver for MHZ, Rx<'a>> { + type Measurement = mhzx::Measurement; + + #[inline(always)] + async fn try_measure(&mut self) -> Result { + self.read_co2() + .await + .map_err(SensorError::Mhz14) + .map_err(Error::Running) + } + + #[inline(always)] + fn device(&self) -> protocol::large_bedroom::bed::Device { + Device::Mhz14 + } +} + +impl<'a> Driver for Sps30, Rx<'a>, Delay> { + type Measurement = sps30_async::Measurement; + + #[inline(always)] + async fn try_measure(&mut self) -> Result { + self.read_measurement() + .await + .map_err(SensorError::Sps30) + .map_err(Error::Running) + } + + #[inline(always)] + fn device(&self) -> protocol::large_bedroom::bed::Device { + Device::Sps30 + } +} diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed-sensors/src/sensors/fast.rs index 8adb7b7f..725dce3d 100644 --- a/sensor-nodes/bed-sensors/src/sensors/fast.rs +++ b/sensor-nodes/bed-sensors/src/sensors/fast.rs @@ -15,9 +15,10 @@ fn sig_lux_diff(old: f32, new: f32) -> bool { } async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues) { + const MIN_INTERVAL: Duration = Duration::from_secs(1); + let mut prev_lux = f32::MAX; let mut last_lux = Instant::now(); - const MIN_INTERVAL: Duration = Duration::from_secs(1); // todo!("reinit devices after error"); loop { @@ -32,9 +33,9 @@ async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues) { }; if sig_lux_diff(prev_lux, lux) { - publish.send_p2(Reading::Brightness(lux)) + publish.send_p2(Reading::Brightness(lux)); } else if last_lux.elapsed() > MIN_INTERVAL { - publish.send_p1(Reading::Brightness(lux)) + publish.send_p1(Reading::Brightness(lux)); } else { yield_now().await; continue; @@ -48,7 +49,7 @@ async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues) { #[allow(dead_code)] async fn watch_button( mut input: ExtiInput<'static>, - event: impl Fn(protocol::Press) -> Button, + event: impl Fn(protocol::button::Press) -> Button, channel: &Queues, ) { let mut went_high_at: Option = None; @@ -61,7 +62,7 @@ async fn watch_button( warn!("extremely long button press registered, skipping"); continue; }; - let event = (event)(protocol::Press(press)); + let event = (event)(protocol::button::Press(press)); channel.send_p2(Reading::Button(event)); } } else { diff --git a/sensor-nodes/bed-sensors/src/sensors/retry.rs b/sensor-nodes/bed-sensors/src/sensors/retry.rs index eecfdd6f..413959da 100644 --- a/sensor-nodes/bed-sensors/src/sensors/retry.rs +++ b/sensor-nodes/bed-sensors/src/sensors/retry.rs @@ -10,38 +10,42 @@ use sht31::mode::SingleShot; use sht31::SHT31; use super::concrete_types::ConcreteSharedI2c; -use crate::error_cache::{Error, SensorError}; +use crate::error_cache::SensorError; -impl<'a> Driver for Max44009> { +mod reinit_on_error; +pub use reinit_on_error::{Bme680Driver, Max44Driver, Sht31Driver}; + +mod retry_init; +pub use retry_init::Sps30Driver; + +impl<'a> ReInitableDriver for SHT31> { type Parts = &'a Mutex>; - type Measurement = f32; + type Measurement = sht31::Reading; - #[inline(always)] async fn init(parts: Self::Parts) -> Result { let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); - // wrap these two into something returning Ok or Err - // then make it a generic arg, maybe Driverfactory::init - let mut driver = Max44009::new(shared_i2c, SlaveAddr::default()); - driver - .set_measurement_mode(max44009::MeasurementMode::Continuous) - .await - .map_err(SensorError::Max44)?; - Ok(driver) + Ok(SHT31::new(shared_i2c, Delay) + .with_mode(SingleShot) + .with_unit(sht31::TemperatureUnit::Celsius) + .with_accuracy(sht31::Accuracy::High)) } - #[inline(always)] async fn measure(&mut self) -> Result { - self.read_lux().await.map_err(SensorError::Max44) + use sht31::mode::Sht31Measure; + use sht31::mode::Sht31Reader; + + Sht31Measure::measure(self) + .await + .map_err(SensorError::Sht31)?; + Timer::after_secs(1).await; + self.read().await.map_err(SensorError::Sht31) } } -pub type Max44Driver<'a> = ReInitOnErrorDriver>>; - -impl<'a> Driver for Bme680, Delay> { +impl<'a> ReInitableDriver for Bme680, Delay> { type Parts = &'a Mutex>; type Measurement = bosch_bme680::MeasurementData; - #[inline(always)] async fn init(parts: Self::Parts) -> Result { let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); Bme680::new( @@ -55,43 +59,33 @@ impl<'a> Driver for Bme680, Delay> { .map_err(SensorError::Bme680) } - #[inline(always)] async fn measure(&mut self) -> Result { self.measure().await.map_err(SensorError::Bme680) } } -pub type Bme680Driver<'a> = ReInitOnErrorDriver, Delay>>; - -impl<'a> Driver for SHT31> { +impl<'a> ReInitableDriver for Max44009> { type Parts = &'a Mutex>; - type Measurement = sht31::Reading; + type Measurement = f32; - #[inline(always)] async fn init(parts: Self::Parts) -> Result { let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); - Ok(SHT31::new(shared_i2c, Delay) - .with_mode(SingleShot) - .with_unit(sht31::TemperatureUnit::Celsius) - .with_accuracy(sht31::Accuracy::High)) + // wrap these two into something returning Ok or Err + // then make it a generic arg, maybe Driverfactory::init + let mut driver = Max44009::new(shared_i2c, SlaveAddr::default()); + driver + .set_measurement_mode(max44009::MeasurementMode::Continuous) + .await + .map_err(SensorError::Max44)?; + Ok(driver) } - - #[inline(always)] async fn measure(&mut self) -> Result { - use sht31::mode::Sht31Measure; - use sht31::mode::Sht31Reader; - - Sht31Measure::measure(self) - .await - .map_err(SensorError::Sht31)?; - Timer::after_secs(1).await; - self.read().await.map_err(SensorError::Sht31) + self.read_lux().await.map_err(SensorError::Max44) } } -pub type Sht31Driver<'a> = ReInitOnErrorDriver>>; - -pub trait Driver: Sized { +/// a driver that can be re-initialized from copyable parts +pub trait ReInitableDriver: Sized { type Parts: Clone; type Measurement; @@ -99,73 +93,8 @@ pub trait Driver: Sized { async fn measure(&mut self) -> Result; } -pub enum ReInitOnErrorDriver -where - D: Driver, -{ - Ready { driver: D, parts: D::Parts }, - Uninit { parts: D::Parts }, -} - -impl ReInitOnErrorDriver { - pub fn new(parts: D::Parts) -> Self { - Self::Uninit { parts } - } - - pub async fn try_measure(&mut self) -> Result { - let parts = match self { - Self::Ready { parts, .. } => parts, - Self::Uninit { parts } => parts, - } - .clone(); - - let mut owned_self = Self::Uninit { parts }; - core::mem::swap(&mut owned_self, self); - let (mut new_self, res) = owned_self.advance_state().await; - core::mem::swap(&mut new_self, self); - res - } - - #[inline(always)] - async fn advance_state(self) -> (Self, Result) { - match self { - Self::Ready { - mut driver, - parts, - // make a trait over driver that has a measure method - } => match driver.measure().await { - Ok(val) => { - let new_self = Self::Ready { driver, parts }; - (new_self, Ok(val)) - } - Err(err) => { - let new_self = Self::Uninit { parts }; - (new_self, Err(Error::Running(err))) - } - }, - Self::Uninit { parts } => { - match D::init(parts.clone()).await { - Ok(mut driver) => { - // uses driver::measure again, make that return a SensorError - match driver.measure().await { - Ok(val) => { - let new_self = Self::Ready { driver, parts }; - (new_self, Ok(val)) - } - Err(err) => { - let new_self = Self::Uninit { parts }; - let err = Error::Running(err); - (new_self, Err(err)) - } - } - } - Err(err) => { - let new_self = Self::Uninit { parts }; - let err = Error::Setup(err); - (new_self, Err(err)) - } - } - } - } - } +pub trait Driver { + type Measurement; + async fn try_measure(&mut self) -> Result; + fn device(&self) -> protocol::large_bedroom::bed::Device; } diff --git a/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs b/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs new file mode 100644 index 00000000..c4a2a38a --- /dev/null +++ b/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs @@ -0,0 +1,110 @@ +use bosch_bme680::Bme680; +use embassy_time::Delay; +use max44009::Max44009; +use protocol::large_bedroom::bed::Device; +use sht31::mode::SingleShot; +use sht31::SHT31; + +use super::super::concrete_types::ConcreteSharedI2c; +use super::ReInitableDriver; +use crate::error_cache::Error; + +pub type Max44Driver<'a> = ReInitOnErrorDriver>>; +pub type Bme680Driver<'a> = ReInitOnErrorDriver, Delay>>; +pub type Sht31Driver<'a> = ReInitOnErrorDriver>>; + +enum State { + Ready { driver: D }, + Uninit, +} + +pub struct ReInitOnErrorDriver +where + D: ReInitableDriver, +{ + state: State, + parts: D::Parts, + device: Device, +} + +impl super::Driver for ReInitOnErrorDriver { + type Measurement = D::Measurement; + + #[inline(always)] + async fn try_measure(&mut self) -> Result { + self.try_measure().await + } + + #[inline(always)] + fn device(&self) -> Device { + self.device.clone() + } +} + +impl ReInitOnErrorDriver +where + D: ReInitableDriver, +{ + #[inline(always)] + pub fn new(parts: D::Parts, device: Device) -> Self { + Self { + state: State::Uninit, + parts, + device, + } + } + + #[inline(always)] + pub async fn try_measure(&mut self) -> Result { + let mut owned_self = State::Uninit; + core::mem::swap(&mut owned_self, &mut self.state); + let (mut new_self, res) = advance_state(owned_self, &self.parts).await; + core::mem::swap(&mut new_self, &mut self.state); + res + } +} + +#[inline(always)] +async fn advance_state( + state: State, + parts: &D::Parts, +) -> (State, Result) { + match state { + State::Ready { + mut driver, + // make a trait over driver that has a measure method + } => match driver.measure().await { + Ok(val) => { + let new_state = State::Ready { driver }; + (new_state, Ok(val)) + } + Err(err) => { + let new_state = State::Uninit; + (new_state, Err(Error::Running(err))) + } + }, + State::Uninit => { + match D::init(parts.clone()).await { + Ok(mut driver) => { + // uses driver::measure again, make that return a SensorError + match driver.measure().await { + Ok(val) => { + let new_state = State::Ready { driver }; + (new_state, Ok(val)) + } + Err(err) => { + let new_state = State::Uninit; + let err = Error::Running(err); + (new_state, Err(err)) + } + } + } + Err(err) => { + let new_state = State::Uninit; + let err = Error::Setup(err); + (new_state, Err(err)) + } + } + } + } +} diff --git a/sensor-nodes/bed-sensors/src/sensors/retry/reset_on_error.rs b/sensor-nodes/bed-sensors/src/sensors/retry/reset_on_error.rs new file mode 100644 index 00000000..0f4f40d7 --- /dev/null +++ b/sensor-nodes/bed-sensors/src/sensors/retry/reset_on_error.rs @@ -0,0 +1,54 @@ +// use bosch_bme680::Bme680; +// use embassy_embedded_hal::shared_bus; +// use embassy_stm32::i2c::I2c; +// use embassy_stm32::mode::Async; +// use embassy_sync::blocking_mutex::raw::NoopRawMutex; +// use embassy_sync::mutex::Mutex; +// use embassy_time::{Delay, Timer}; +// use max44009::{Max44009, SlaveAddr}; +// use sht31::mode::SingleShot; +// use sht31::SHT31; +// +use super::super::concrete_types::{ConcreteRx, ConcreteTx}; + +use crate::error_cache::{Error, SensorError}; + +pub trait ResettableDriver: Sized { + type Measurement; + + async fn reset(&mut self) -> Result; + async fn measure(&mut self) -> Result; +} + +pub struct ResetOnErrorDriver +where + D: ResettableDriver, +{ + driver: D, +} + +impl ResetOnErrorDriver { + pub fn new(driver: D) -> Self { + Self { driver } + } + + pub async fn try_measure(&mut self) -> Result { + let res = self.driver.measure().await.map_err(Error::Running); + if res.is_err() { + self.driver.reset().await.map_err(Error::Setup)?; + } + res + } +} + +impl<'a> ResettableDriver for mhzx::MHZ, ConcreteRx<'a>> { + type Measurement = f32; + + async fn reset(&mut self) -> Result { + self. + } + + async fn measure(&mut self) -> Result { + todo!() + } +} diff --git a/sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs b/sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs new file mode 100644 index 00000000..b08b0a39 --- /dev/null +++ b/sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs @@ -0,0 +1,67 @@ +use embassy_time::Delay; +use sps30_async::Sps30; + +use crate::error_cache::{Error, SensorError}; +use crate::sensors::concrete_types::{ConcreteRx, ConcreteTx}; +use crate::sensors::SPS30_UART_BUF_SIZE; + +use super::Driver; + +pub struct Sps30Driver<'a> { + is_init: bool, + driver: Sps30, ConcreteRx<'a>, Delay>, +} + +impl<'a> Sps30Driver<'a> { + pub fn init(tx: ConcreteTx<'a>, rx: ConcreteRx<'a>) -> Self { + let driver = Sps30::from_tx_rx_uninit(tx, rx, Delay); + Self { + is_init: false, + driver, + } + } + + async fn measure(&mut self) -> Result { + if self.is_init { + return self + .driver + .read_measurement() + .await + .map_err(SensorError::Sps30) + .map_err(Error::Running); + } + + defmt::info!("initializing sps30"); + self.driver + .reset() + .await + .map_err(SensorError::Sps30) + .map_err(Error::Setup)?; + self.driver + .start_measurement() + .await + .map_err(SensorError::Sps30) + .map_err(Error::Setup)?; + + defmt::debug!("sps30 init complete"); + self.is_init = true; + self.driver + .read_measurement() + .await + .map_err(SensorError::Sps30) + .map_err(Error::Running) + } + +} + +impl<'a> Driver for Sps30Driver<'a> { + type Measurement = sps30_async::Measurement; + + async fn try_measure(&mut self) -> Result { + self.measure().await + } + + fn device(&self) -> protocol::large_bedroom::bed::Device { + protocol::large_bedroom::bed::Device::Sps30 + } +} diff --git a/sensor-nodes/bed-sensors/src/sensors/slow.rs b/sensor-nodes/bed-sensors/src/sensors/slow.rs index b2834e14..24cdf2ba 100644 --- a/sensor-nodes/bed-sensors/src/sensors/slow.rs +++ b/sensor-nodes/bed-sensors/src/sensors/slow.rs @@ -1,64 +1,74 @@ use defmt::unwrap; -use embassy_futures::join; -use embassy_time::{with_timeout, Delay, Duration}; -use embassy_time::{Instant, Timer}; +use embassy_futures::join::join5; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_time::Timer; +use embassy_time::{with_timeout, Duration}; use mhzx::MHZ; -use protocol::large_bedroom::bed::{Device, Reading}; +use protocol::large_bedroom::bed::Reading; use bosch_bme680::MeasurementData; use sps30_async as sps30; -use sps30_async::Sps30; use crate::channel::Queues; use crate::error_cache::Error; -use crate::error_cache::SensorError; -use super::retry::{Bme680Driver, Sht31Driver}; -use super::UartError; - -const SPS30_UART_BUF_SIZE: usize = 100; -const SPS30_DRIVER_BUF_SIZE: usize = 2 * SPS30_UART_BUF_SIZE; +use super::retry::{Bme680Driver, Driver, Sht31Driver, Sps30Driver}; use super::concrete_types::ConcreteRx as Rx; use super::concrete_types::ConcreteTx as Tx; +type Signal = embassy_sync::signal::Signal; #[inline(always)] -pub async fn read( - mut sht: Sht31Driver<'_>, - mut bme: Bme680Driver<'_>, - mut mhz: MHZ, Rx<'_>>, - mut sps: Sps30, Rx<'_>, Delay>, - publish: &'_ Queues, -) { - let mut next_sample = Instant::now(); +async fn measure_and_send_on_signal(mut driver: D, send: F, signal: &Signal) +where + D: Driver, + F: Fn(Result) -> (), +{ + let timeout = Duration::from_secs(15); loop { - Timer::at(next_sample).await; - next_sample = Instant::now() + Duration::from_secs(1); - - let sht_read = with_timeout(Duration::from_millis(100), sht.try_measure()); - let bme_measure = bme.try_measure(); // can not hang - let mhz_measure = with_timeout(Duration::from_millis(100), mhz.read_co2()); - let sps_measure = with_timeout(Duration::from_millis(100), sps.read_measurement()); - let (bme_res, sht_res, mhz_res, sps_res) = - join::join4(bme_measure, sht_read, mhz_measure, sps_measure).await; + signal.wait().await; + let try_measure = Driver::try_measure(&mut driver); + let res = match with_timeout(timeout, try_measure).await { + Ok(res) => res, + Err(_) => Err(Error::Timeout(driver.device())), + }; + send(res); + } +} - publish_bme_result(bme_res, publish); - publish_sht_result(sht_res, publish); - publish_mhz_result(mhz_res, publish); - publish_sps_result(sps_res, publish); +async fn order_measurements_every_second(signals: &[Signal]) { + loop { + for signal in signals { + signal.signal(()); + } + Timer::after_secs(1).await; } } -fn publish_sps_result( - sps_res: Result< - Result, sps30::Error>, - embassy_time::TimeoutError, - >, - publish: &Queues, +#[inline(always)] +pub async fn read( + sht: Sht31Driver<'_>, + bme: Bme680Driver<'_>, + mhz: MHZ, Rx<'_>>, + sps: Sps30Driver<'_>, + publish: &'_ Queues, ) { + let signals = [const { Signal::new() }; 4]; + + join5( + order_measurements_every_second(&signals), + measure_and_send_on_signal(sht, |res| publish_sht_result(res, &publish), &signals[0]), + measure_and_send_on_signal(bme, |res| publish_bme_result(res, &publish), &signals[1]), + measure_and_send_on_signal(mhz, |res| publish_mhz_result(res, &publish), &signals[2]), + measure_and_send_on_signal(sps, |res| publish_sps_result(res, &publish), &signals[3]), + ) + .await; +} + +fn publish_sps_result(sps_res: Result, publish: &Queues) { match sps_res { - Ok(Ok(Some(sps30::Measurement { + Ok(sps30::Measurement { mass_pm1_0, mass_pm2_5, mass_pm4_0, @@ -69,7 +79,7 @@ fn publish_sps_result( number_pm4_0, number_pm10, typical_particle_size, - }))) => { + }) => { publish.send_p0(Reading::MassPm1_0(mass_pm1_0)); publish.send_p0(Reading::MassPm2_5(mass_pm2_5)); publish.send_p0(Reading::MassPm4_0(mass_pm4_0)); @@ -81,61 +91,31 @@ fn publish_sps_result( publish.send_p0(Reading::NumberPm10(number_pm10)); publish.send_p0(Reading::TypicalParticleSize(typical_particle_size)); } - Ok(Ok(None)) => { - defmt::todo!("no idea when we hit this"); - } - Ok(Err(err)) => { - let err = SensorError::Sps30(err); - let err = Error::Running(err); - publish.queue_error(err) - } - Err(_timeout) => { - let err = Error::Timeout(Device::Sps30); - publish.queue_error(err) - } + Err(err) => publish.queue_error(err), } } -fn publish_mhz_result( - mhz_res: Result< - Result>, - embassy_time::TimeoutError, - >, - publish: &Queues, -) { +fn publish_mhz_result(mhz_res: Result, publish: &Queues) { match mhz_res { - Ok(Ok(mhzx::Measurement { co2, .. })) => { + Ok(mhzx::Measurement { co2, .. }) => { publish.send_p0(Reading::Co2(co2)); } - Ok(Err(err)) => { - let err = SensorError::Mhz14(err); - let err = Error::Running(err); - publish.queue_error(err) - } - Err(_timeout) => { - let err = Error::Timeout(Device::Mhz14); - publish.queue_error(err) + Err(err) => { + publish.queue_error(err); } } } -fn publish_sht_result( - sht_res: Result, embassy_time::TimeoutError>, - publish: &Queues, -) { +fn publish_sht_result(sht_res: Result, publish: &Queues) { match sht_res { - Ok(Ok(sht31::Reading { + Ok(sht31::Reading { temperature, humidity, - })) => { + }) => { publish.send_p0(Reading::Temperature(temperature)); publish.send_p0(Reading::Humidity(humidity)); } - Ok(Err(err)) => publish.queue_error(err), - Err(_timeout) => { - let err = Error::Timeout(Device::Sht31); - publish.queue_error(err) - } + Err(err) => publish.queue_error(err), } } diff --git a/sensor-nodes/setup.sh b/sensor-nodes/setup.sh new file mode 100755 index 00000000..225ea53b --- /dev/null +++ b/sensor-nodes/setup.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +set -e + +# for newer or different prorammers edit idVendor and idProduct (use lsusb to find these) +UDEV_FILE=/etc/udev/rules.d/70-programmer.rules +UDEV_RULE1='# ST-LINK/V2' +UDEV_RULE2='ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", TAG+="uaccess"' +UDEV_RULE3='# ST-LINK/V2-1' +UDEV_RULE4='ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", TAG+="uaccess"' +UDEV_RULE5='# CMSIS_DAP compatible adapter' +UDEV_RULE6='ATTRS{product}=="*CMSIS-DAP*", MODE="660", GROUP="plugdev", TAG+="uaccess"' +UDEV_RULE5='# CMSIS_DAP compatible misspelled adapter' +UDEV_RULE6='ATTRS{product}=="*CMSIS_DAP*", MODE="660", GROUP="plugdev", TAG+="uaccess"' + + +function install_tools { + echo "installing tools" + rustup override set nightly + rustup target add thumbv7em-none-eabihf + + # # workaround for issue: https://github.com/knurling-rs/probe-run/issues/289 + # sudo apt remove libusb-dev libusb-0.1-4 + + # sudo apt install -y libusb-1.0-0-dev libudev-dev + curl --proto '=https' --tlsv1.2 -LsSf https://github.com/probe-rs/probe-rs/releases/latest/download/probe-rs-tools-installer.sh | sh + cargo install flip-link # linker with stack overflow protection + # rustup component add llvm-tools-preview +} + +# add udev rules if they do not yet exist +function fix_udev_rules { + sudo groupadd dialout || true + sudo usermod -a -G dialout $USER + + if [ ! -f "${UDEV_FILE}" ]; then + echo "${UDEV_RULE1}" | sudo tee -a $UDEV_FILE > /dev/null + echo "${UDEV_RULE2}" | sudo tee -a $UDEV_FILE > /dev/null + echo "${UDEV_RULE3}" | sudo tee -a $UDEV_FILE > /dev/null + echo "${UDEV_RULE4}" | sudo tee -a $UDEV_FILE > /dev/null + echo "${UDEV_RULE5}" | sudo tee -a $UDEV_FILE > /dev/null + echo "${UDEV_RULE6}" | sudo tee -a $UDEV_FILE > /dev/null + sudo udevadm control --reload-rules + sudo udevadm trigger + echo "created udev rules: $UDEV_FILE" + fi +} + +install_tools +echo $(fix_udev_rules) # without the echo $() this does not work.. bash magic... + +printf "\x1b[31mdo please manually check lsub and udev/rules-d for probe rule\x1b[0m\n"; +printf "\x1b[31mdo NOT FORGET to DISCONNECT and RECONNECT the programmer\x1b[0m\n"; +printf "\x1b[31mdo NOT FORGET to RE-LOGIN the shell to reload groups\x1b[0m\n"; From a813de9cece5f917dea53b023098ba77c2010022 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 14 Jun 2024 13:57:43 +0200 Subject: [PATCH 135/687] remove no longer needed debugging statements --- crates/protocol/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 1b4fc397..59042930 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -209,11 +209,9 @@ pub type ErrorString = heapless::String<200>; // https://github.com/rust-lang/rust/issues/103765 // at that point try switching this to fmt::Display pub fn make_error_string(e: impl core::fmt::Debug) -> ErrorString { - defmt::info!("making error string"); use core::fmt::Write; let mut s = ErrorString::new(); core::write!(s, "{e:?}").ok(); - defmt::info!("done"); s } From a4df562bd8818262067986addd027e3528cb87a2 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 16 Jun 2024 15:56:25 +0200 Subject: [PATCH 136/687] add TreeLeaf (now still called TomatoLeaf) --- Cargo.lock | 237 +++++++++++++++++++++- crates/protocol/src/button.rs | 6 +- crates/protocol/src/large_bedroom/bed.rs | 116 ++++++++--- crates/protocol/src/large_bedroom/desk.rs | 27 ++- crates/protocol/src/tomato.rs | 23 ++- 5 files changed, 359 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a653dfe0..c433df3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -108,6 +108,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "arraydeque" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" + [[package]] name = "async-attributes" version = "1.1.2" @@ -454,6 +460,20 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +[[package]] +name = "bitspec" +version = "0.1.0" +source = "git+https://github.com/dvdsk/bitspec#42f02afed6dbf94e05e7c38f6dd5b6e091c20ef1" +dependencies = [ + "log", + "num", + "rand 0.5.6", + "serde", + "serde_derive", + "serde_yaml 0.8.26", + "text_io", +] + [[package]] name = "bitvec" version = "1.0.1" @@ -509,9 +529,9 @@ dependencies = [ "hueclient", "mpd", "protocol", - "rand", + "rand 0.8.5", "serde", - "serde_yaml", + "serde_yaml 0.9.34+deprecated", "sled", "strum", "thiserror", @@ -547,6 +567,18 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +[[package]] +name = "byteseries" +version = "0.4.0" +dependencies = [ + "arraydeque", + "byteorder", + "num-traits", + "thiserror", + "time", + "tracing", +] + [[package]] name = "cassowary" version = "0.3.0" @@ -641,6 +673,15 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "cobs" version = "0.2.3" @@ -810,6 +851,23 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "data-store" +version = "0.1.0" +dependencies = [ + "bitspec", + "byteseries", + "clap", + "color-eyre", + "data-server", + "futures-concurrency", + "protocol", + "tokio", + "tracing", + "tracing-error", + "tracing-subscriber", +] + [[package]] name = "defmt" version = "0.3.8" @@ -1047,6 +1105,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "funty" version = "2.0.0" @@ -1068,6 +1132,17 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-buffered" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02dcae03ee5afa5ea17b1aebc793806b8ddfc6dc500e0b8e8e1eb30b9dad22c0" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", +] + [[package]] name = "futures-channel" version = "0.3.30" @@ -1080,11 +1155,12 @@ dependencies = [ [[package]] name = "futures-concurrency" -version = "7.6.0" +version = "7.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51ee14e256b9143bfafbf2fddeede6f396650bacf95d06fc1b3f2b503df129a0" +checksum = "4b14ac911e85d57c5ea6eef76d7b4d4a3177ecd15f4bea2e61927e9e3823e19f" dependencies = [ "bitvec", + "futures-buffered", "futures-core", "futures-lite 1.13.0", "pin-project", @@ -1288,6 +1364,12 @@ dependencies = [ "byteorder", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.5" @@ -1504,6 +1586,16 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + [[package]] name = "indexmap" version = "2.2.6" @@ -1511,7 +1603,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -1607,6 +1699,12 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "linux-embedded-hal" version = "0.4.0" @@ -1662,7 +1760,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" dependencies = [ - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -1842,12 +1940,78 @@ dependencies = [ "winapi", ] +[[package]] +name = "num" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" +dependencies = [ + "num-traits", +] + [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -2148,6 +2312,19 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "rand" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "winapi", +] + [[package]] name = "rand" version = "0.8.5" @@ -2156,7 +2333,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -2166,9 +2343,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", ] +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + [[package]] name = "rand_core" version = "0.6.4" @@ -2420,13 +2612,25 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" +dependencies = [ + "indexmap 1.9.3", + "ryu", + "serde", + "yaml-rust", +] + [[package]] name = "serde_yaml" version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap", + "indexmap 2.2.6", "itoa", "ryu", "serde", @@ -2672,6 +2876,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "text_io" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f0c8eb2ad70c12a6a69508f499b3051c924f4b1cfeae85bfad96e6bc5bba46" + [[package]] name = "thiserror" version = "1.0.61" @@ -3315,6 +3525,15 @@ dependencies = [ "tap", ] +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "zerocopy" version = "0.7.34" diff --git a/crates/protocol/src/button.rs b/crates/protocol/src/button.rs index 79f7fb6f..990e9e51 100644 --- a/crates/protocol/src/button.rs +++ b/crates/protocol/src/button.rs @@ -76,7 +76,11 @@ macro_rules! button_enum { #[cfg(feature = "alloc")] impl crate::tomato::Tomato for $name { fn inner<'a>(&'a self) -> crate::tomato::TomatoItem<'a> { - crate::tomato::TomatoItem::Leaf((*self).into()) + crate::tomato::TomatoItem::Leaf(crate::tomato::TomatoLeaf { + val: (*self).into(), + device: "GPIO", + from_same_device: &[], // TODO + }) } fn name(&self) -> String { let dbg_repr = format!("{:?}", self); diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 1e65c5c2..23fdd82d 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -1,6 +1,7 @@ +use crate::button::Press; use crate::button_enum; #[cfg(feature = "alloc")] -use crate::tomato::{Tomato, TomatoId, TomatoItem}; +use crate::tomato::{Tomato, TomatoId, TomatoItem, TomatoLeaf}; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -69,31 +70,60 @@ pub enum Reading { TypicalParticleSize(f32), } +#[cfg(feature = "alloc")] +macro_rules! put_in_tree { + ([$($reading:expr),+]) => { + [$(crate::Reading::LargeBedroom( + crate::large_bedroom::Reading::Bed($reading), + )),+] + }; +} + +#[cfg(feature = "alloc")] +fn leaf(val: &f32, device: Device, from_same_device: &'static [crate::Reading]) -> TomatoLeaf { + TomatoLeaf { + val: *val, + device: device.as_str(), + from_same_device, + } +} + #[cfg(feature = "alloc")] impl Tomato for Reading { fn inner<'a>(&'a self) -> TomatoItem<'a> { - let val = match self { - Reading::Brightness(val) => *val, - Reading::Temperature(val) => *val, - Reading::Humidity(val) => *val, - Reading::GassResistance(val) => *val, - Reading::Pressure(val) => *val, - Reading::Co2(val) => *val as f32, - Reading::WeightLeft(val) => *val as f32, - Reading::WeightRight(val) => *val as f32, - Reading::Button(val) => (*val).into(), - Reading::MassPm1_0(val) => *val, - Reading::MassPm2_5(val) => *val, - Reading::MassPm4_0(val) => *val, - Reading::MassPm10(val) => *val, - Reading::MassPm0_5(val) => *val, - Reading::NumberPm1_0(val) => *val, - Reading::NumberPm2_5(val) => *val, - Reading::NumberPm4_0(val) => *val, - Reading::NumberPm10(val) => *val, - Reading::TypicalParticleSize(val) => *val, + let (val, device) = match self { + Reading::Brightness(val) => (*val, Device::Max44), + Reading::Temperature(val) => (*val, Device::Sht31), + Reading::Humidity(val) => (*val, Device::Sht31), + Reading::GassResistance(val) => (*val, Device::Bme680), + Reading::Pressure(val) => (*val, Device::Bme680), + Reading::Co2(val) => (*val as f32, Device::Mhz14), + Reading::WeightLeft(val) => (*val as f32, Device::Nau7802Left), + Reading::WeightRight(val) => (*val as f32, Device::Nau7802Right), + Reading::Button(val) => ((*val).into(), Device::Gpio), + Reading::MassPm1_0(val) => (*val, Device::Sps30), + Reading::MassPm2_5(val) => (*val, Device::Sps30), + Reading::MassPm4_0(val) => (*val, Device::Sps30), + Reading::MassPm10(val) => (*val, Device::Sps30), + Reading::MassPm0_5(val) => (*val, Device::Sps30), + Reading::NumberPm1_0(val) => (*val, Device::Sps30), + Reading::NumberPm2_5(val) => (*val, Device::Sps30), + Reading::NumberPm4_0(val) => (*val, Device::Sps30), + Reading::NumberPm10(val) => (*val, Device::Sps30), + Reading::TypicalParticleSize(val) => (*val, Device::Sps30), }; - TomatoItem::Leaf(val) + + // let related = todo!(); + + // Reading::Brightness(val) => leaf(val, Device::Max44, &[]), + // Reading::Temperature(val) => { + // leaf(val, Device::Sht31, &put_in_tree!([Reading::Humidity(0.0)])) + // } + TomatoItem::Leaf(TomatoLeaf { + val, + device: device.as_str(), + from_same_device: todo!(), + }) } fn id(&self) -> TomatoId { @@ -137,6 +167,8 @@ pub enum SensorError { Max44(heapless::String<200>), Mhz14(heapless::String<200>), Sps30(heapless::String<200>), + Nau7802Left(heapless::String<200>), + Nau7802Right(heapless::String<200>), } impl core::fmt::Display for SensorError { @@ -147,6 +179,8 @@ impl core::fmt::Display for SensorError { SensorError::Max44(e) => write!(f, "{e}"), SensorError::Mhz14(e) => write!(f, "{e}"), SensorError::Sps30(e) => write!(f, "{e}"), + SensorError::Nau7802Left(e) => write!(f, "{e}"), + SensorError::Nau7802Right(e) => write!(f, "{e}"), } } } @@ -163,6 +197,8 @@ impl SensorError { SensorError::Max44(_) => Device::Max44, SensorError::Mhz14(_) => Device::Mhz14, SensorError::Sps30(_) => Device::Sps30, + SensorError::Nau7802Left(_) => Device::Nau7802Left, + SensorError::Nau7802Right(_) => Device::Nau7802Right, } } } @@ -174,21 +210,31 @@ pub enum Device { Max44, Mhz14, Sps30, + Nau7802Left, + Nau7802Right, + Gpio, } impl core::fmt::Display for Device { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - Device::Sht31 => write!(f, "Sht31"), - Device::Bme680 => write!(f, "Bme680"), - Device::Max44 => write!(f, "Max44"), - Device::Mhz14 => write!(f, "Mhz14"), - Device::Sps30 => write!(f, "Sps30"), - } + write!(f, "{}", self.as_str()) } } impl Device { + pub fn as_str(&self) -> &'static str { + match self { + Device::Sht31 => "Sht31", + Device::Bme680 => "Bme680", + Device::Max44 => "Max44", + Device::Mhz14 => "Mhz14", + Device::Sps30 => "Sps30", + Device::Nau7802Left => "Nau7802Left", + Device::Nau7802Right => "Nau7802Right", + Device::Gpio => "Gpio", + } + } + pub fn broken_readings(&self) -> &'static [Reading] { match self { Device::Sht31 => &[Reading::Temperature(0.0), Reading::Humidity(0.0)], @@ -207,6 +253,18 @@ impl Device { Reading::NumberPm10(0.0), Reading::TypicalParticleSize(0.0), ], + Device::Nau7802Left => &[Reading::WeightLeft(0)], + Device::Nau7802Right => &[Reading::WeightRight(0)], + Device::Gpio => &[ + Reading::Button(Button::TopLeft(Press(0))), + Reading::Button(Button::TopRight(Press(0))), + Reading::Button(Button::MiddleInner(Press(0))), + Reading::Button(Button::MiddleCenter(Press(0))), + Reading::Button(Button::MiddleOuter(Press(0))), + Reading::Button(Button::LowerInner(Press(0))), + Reading::Button(Button::LowerCenter(Press(0))), + Reading::Button(Button::LowerOuter(Press(0))), + ], } } } diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index 1c9a5220..a887a688 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use crate::button_enum; #[cfg(feature = "alloc")] -use crate::tomato::{Tomato, TomatoItem}; +use crate::tomato::{Tomato, TomatoItem, TomatoLeaf}; button_enum! { /// No these are not borg, these are buttons on a string of cat5. @@ -33,13 +33,17 @@ pub enum Reading { #[cfg(feature = "alloc")] impl Tomato for Reading { fn inner<'a>(&'a self) -> TomatoItem<'a> { - let val = match self { - Reading::Temperature(val) => *val, - Reading::Humidity(val) => *val, - Reading::Pressure(val) => *val, + let (val, device) = match self { + Reading::Temperature(val) => (*val, Device::Bme280), + Reading::Humidity(val) => (*val, Device::Bme280), + Reading::Pressure(val) => (*val, Device::Bme280), Reading::Button(val) => return TomatoItem::Node(val), }; - TomatoItem::Leaf(val) + TomatoItem::Leaf(TomatoLeaf { + val, + device: device.as_str(), + from_same_device: &[], // TODO + }) } fn id(&self) -> crate::tomato::TomatoId { @@ -112,14 +116,17 @@ pub enum Device { impl core::fmt::Display for Device { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - Device::Bme280 => write!(f, "Bme280"), - Device::Gpio => write!(f, "Gpio"), - } + write!(f, "{}", self.as_str()) } } impl Device { + pub fn as_str(&self) -> &'static str { + match self { + Device::Bme280 => "Bme280", + Device::Gpio => "Gpio", + } + } pub fn affected_readings(&self) -> &'static [Reading] { match self { Device::Bme280 => &[Reading::Temperature(0.0), Reading::Humidity(0.0)], diff --git a/crates/protocol/src/tomato.rs b/crates/protocol/src/tomato.rs index aa378808..b014c2d6 100644 --- a/crates/protocol/src/tomato.rs +++ b/crates/protocol/src/tomato.rs @@ -1,12 +1,31 @@ +#[derive(Debug)] +pub struct TomatoLeaf { + pub val: f32, + pub device: &'static str, + pub from_same_device: &'static [Reading], +} + pub type TomatoId = u8; #[derive(Debug)] pub enum TomatoItem<'a> { - Leaf(f32), + Leaf(TomatoLeaf), Node(&'a dyn Tomato), } pub trait Tomato: core::fmt::Debug { fn inner<'a>(&'a self) -> TomatoItem<'a>; + fn leaf<'a>(&'a self) -> TomatoLeaf + where + Self: Sized, + { + let mut current = self as &dyn Tomato; + loop { + match current.inner() { + TomatoItem::Node(node) => current = node, + TomatoItem::Leaf(leaf) => return leaf, + } + } + } fn name(&self) -> String { let dbg_repr = format!("{:?}", self); dbg_repr @@ -37,3 +56,5 @@ macro_rules! all_nodes { } pub(crate) use all_nodes; + +use crate::Reading; From b04d5df82f2c2f101da3759682723eb7061d9957 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 5 Jul 2024 18:04:04 +0200 Subject: [PATCH 137/687] adds units to readings + adds a device tree --- Cargo.lock | 562 +++++++++++----------- crates/protocol/src/button.rs | 29 +- crates/protocol/src/device_tree.rs | 0 crates/protocol/src/large_bedroom.rs | 41 +- crates/protocol/src/large_bedroom/bed.rs | 263 +++++++--- crates/protocol/src/large_bedroom/desk.rs | 85 +++- crates/protocol/src/lib.rs | 68 ++- crates/protocol/src/reading_tree.rs | 69 +++ crates/protocol/src/small_bedroom.rs | 70 ++- crates/protocol/src/tomato.rs | 60 --- crates/sensor-tui/src/tui/reading.rs | 2 +- 11 files changed, 790 insertions(+), 459 deletions(-) create mode 100644 crates/protocol/src/device_tree.rs create mode 100644 crates/protocol/src/reading_tree.rs delete mode 100644 crates/protocol/src/tomato.rs diff --git a/Cargo.lock b/Cargo.lock index c433df3a..3cc24712 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -91,9 +91,9 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ "windows-sys 0.52.0", ] @@ -207,7 +207,7 @@ dependencies = [ "futures-io", "futures-lite 2.3.0", "parking", - "polling 3.7.1", + "polling 3.7.2", "rustix 0.38.34", "slab", "tracing", @@ -253,9 +253,9 @@ dependencies = [ [[package]] name = "async-signal" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "329972aa325176e89114919f2a80fdae4f4c040f66a370b1a1159c6c0f94e7aa" +checksum = "794f185324c2f00e771cd9f1ae8b5ac68be2ca7abb129a87afd6e86d228bc54d" dependencies = [ "async-io 2.3.3", "async-lock 3.4.0", @@ -332,7 +332,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -415,7 +415,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -433,6 +433,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "base64" version = "0.22.1" @@ -456,22 +462,22 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] [[package]] name = "bitspec" version = "0.1.0" -source = "git+https://github.com/dvdsk/bitspec#42f02afed6dbf94e05e7c38f6dd5b6e091c20ef1" dependencies = [ "log", "num", - "rand 0.5.6", + "rand", "serde", "serde_derive", - "serde_yaml 0.8.26", - "text_io", ] [[package]] @@ -529,9 +535,9 @@ dependencies = [ "hueclient", "mpd", "protocol", - "rand 0.8.5", + "rand", "serde", - "serde_yaml 0.9.34+deprecated", + "serde_yaml", "sled", "strum", "thiserror", @@ -570,12 +576,15 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "byteseries" version = "0.4.0" +source = "git+https://github.com/dvdsk/byteseries#75e1bd67ab2f0c8bbca5cb84930f5cf885b41e27" dependencies = [ "arraydeque", - "byteorder", + "itertools 0.13.0", "num-traits", + "ron", + "serde", + "smallvec 2.0.0-alpha.6", "thiserror", - "time", "tracing", ] @@ -593,18 +602,18 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "castaway" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a17ed5635fc8536268e5d4de1e22e81ac34419e5f052d4d51f4e01dcc263fcc" +checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5" dependencies = [ "rustversion", ] [[package]] name = "cc" -version = "1.0.98" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" +checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" [[package]] name = "cfg-if" @@ -630,14 +639,14 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] name = "clap" -version = "4.5.4" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" dependencies = [ "clap_builder", "clap_derive", @@ -645,9 +654,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" dependencies = [ "anstream", "anstyle", @@ -657,30 +666,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.4" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] name = "clap_lex" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" - -[[package]] -name = "cloudabi" -version = "0.0.3" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags 1.3.2", -] +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "cobs" @@ -817,7 +817,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "crossterm_winapi", "libc", "mio", @@ -860,9 +860,16 @@ dependencies = [ "clap", "color-eyre", "data-server", + "futures", "futures-concurrency", "protocol", + "serde", + "smallvec 2.0.0-alpha.6", + "thiserror", + "time", "tokio", + "tokio-serde", + "tokio-util", "tracing", "tracing-error", "tracing-subscriber", @@ -888,7 +895,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -907,19 +914,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version", - "syn 1.0.109", + "syn 2.0.68", ] [[package]] @@ -950,11 +958,23 @@ dependencies = [ "quick-error", ] +[[package]] +name = "educe" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4bd92664bf78c4d3dba9b7cdafce6fa15b13ed3ed16175218196942e99168a8" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "either" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "embedded-hal" @@ -987,6 +1007,26 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" +[[package]] +name = "enum-ordinalize" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -1105,12 +1145,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "funty" version = "2.0.0" @@ -1165,7 +1199,7 @@ dependencies = [ "futures-lite 1.13.0", "pin-project", "slab", - "smallvec", + "smallvec 1.13.2", ] [[package]] @@ -1227,7 +1261,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1304,7 +1338,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09831ec59b80be69e75d29cf36e16afbbe5fd1af9c1bf4689ad91c77db5aa6a6" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", "nix 0.27.1", ] @@ -1340,7 +1374,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a02357253f833a6ce4e93f17e8dd3e169c941ea71b83d442ed9c55f784045204" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "ioctl-sys", "libc", "thiserror", @@ -1364,12 +1398,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "hashbrown" version = "0.14.5" @@ -1424,11 +1452,17 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + [[package]] name = "histogram" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd81cb9a629d0a868f2092937332fca5fd985971d2155bf6fcc225ef8a6be2c" +checksum = "cfe0e7d1b57c929216545b6aa17aff4798bc432b7065ac16a3e03b8dd63d8643" dependencies = [ "thiserror", ] @@ -1456,12 +1490,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", + "futures-util", "http", "http-body", "pin-project-lite", @@ -1469,9 +1503,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -1497,9 +1531,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +checksum = "c4fe55fb7a772d59a5ff1dfbff4fe0258d19b89fec4b233e75d35d5d2316badc" dependencies = [ "bytes", "futures-channel", @@ -1510,16 +1544,16 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "smallvec", + "smallvec 1.13.2", "tokio", "want", ] [[package]] name = "hyper-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" +checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" dependencies = [ "bytes", "futures-channel", @@ -1537,11 +1571,11 @@ dependencies = [ [[package]] name = "i2cdev" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597f56d08cebc0fb3e67d49f48124f49e1c7ac297a21d60bc90a28b9482fb35c" +checksum = "a01f563561b53e2def844167c92984da13779a53ca409e948a03400633cb8228" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "byteorder", "libc", "nix 0.26.4", @@ -1586,16 +1620,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - [[package]] name = "indexmap" version = "2.2.6" @@ -1603,7 +1627,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown", ] [[package]] @@ -1631,7 +1655,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", "windows-sys 0.48.0", ] @@ -1663,6 +1687,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -1689,9 +1722,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" @@ -1699,12 +1732,6 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - [[package]] name = "linux-embedded-hal" version = "0.4.0" @@ -1747,9 +1774,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" dependencies = [ "value-bag", ] @@ -1760,7 +1787,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" dependencies = [ - "hashbrown 0.14.5", + "hashbrown", ] [[package]] @@ -1789,9 +1816,9 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "maybe-async-cfg" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21fb8fac02158b9b529eb692491895d8459dbac939f3bc6e32159969646ffe55" +checksum = "a1e083394889336bc66a4eaf1011ffbfa74893e910f902a9f271fa624c61e1b2" dependencies = [ "proc-macro-error", "proc-macro2", @@ -1818,9 +1845,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -1848,9 +1875,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] @@ -1925,7 +1952,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if 1.0.0", "libc", ] @@ -1942,9 +1969,9 @@ dependencies = [ [[package]] name = "num" -version = "0.3.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ "num-bigint", "num-complex", @@ -1956,20 +1983,19 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.3.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-complex" -version = "0.3.1" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] @@ -2002,11 +2028,10 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.3.2" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", "num-bigint", "num-integer", "num-traits", @@ -2027,7 +2052,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] @@ -2095,7 +2120,7 @@ dependencies = [ "instant", "libc", "redox_syscall 0.2.16", - "smallvec", + "smallvec 1.13.2", "winapi", ] @@ -2107,9 +2132,9 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.5.1", - "smallvec", - "windows-targets 0.52.5", + "redox_syscall 0.5.2", + "smallvec 1.13.2", + "windows-targets 0.52.6", ] [[package]] @@ -2141,7 +2166,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -2185,13 +2210,13 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.1" +version = "3.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6a007746f34ed64099e88783b0ae369eaa3da6392868ba262e2af9b8fbaea1" +checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" dependencies = [ "cfg-if 1.0.0", "concurrent-queue", - "hermit-abi", + "hermit-abi 0.4.0", "pin-project-lite", "rustix 0.38.34", "tracing", @@ -2261,9 +2286,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -2282,11 +2307,11 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.9.6" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" +checksum = "8746739f11d39ce5ad5c2520a9b75285310dbfe78c541ccf832d38615765aec0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "memchr", "unicase", ] @@ -2312,19 +2337,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" -[[package]] -name = "rand" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "winapi", -] - [[package]] name = "rand" version = "0.8.5" @@ -2333,7 +2345,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -2343,24 +2355,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", + "rand_core", ] -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.6.4" @@ -2376,11 +2373,11 @@ version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f44c9e68fd46eda15c646fbb85e1040b657a58cdc8c98db1d97a55930d991eef" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cassowary", "compact_str", "crossterm", - "itertools", + "itertools 0.12.1", "lru", "paste", "stability", @@ -2401,23 +2398,23 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.3", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] @@ -2431,13 +2428,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.3", + "regex-syntax 0.8.4", ] [[package]] @@ -2448,17 +2445,17 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "reqwest" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-core", "futures-util", @@ -2477,7 +2474,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.1", "tokio", "tower-service", "url", @@ -2487,6 +2484,18 @@ dependencies = [ "winreg", ] +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64 0.21.7", + "bitflags 2.6.0", + "serde", + "serde_derive", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -2522,7 +2531,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys 0.4.14", @@ -2586,14 +2595,14 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "itoa", "ryu", @@ -2612,25 +2621,13 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_yaml" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" -dependencies = [ - "indexmap 1.9.3", - "ryu", - "serde", - "yaml-rust", -] - [[package]] name = "serde_yaml" version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.2.6", + "indexmap", "itoa", "ryu", "serde", @@ -2639,11 +2636,11 @@ dependencies = [ [[package]] name = "serialport" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f5a15d0be940df84846264b09b51b10b931fb2f275becb80934e3568a016828" +checksum = "de7c4f0cce25b9b3518eea99618112f9ee4549f974480c8f43d3c06f03c131a0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if 1.0.0", "core-foundation-sys", "io-kit-sys", @@ -2725,6 +2722,12 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "smallvec" +version = "2.0.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66778689f64ae4f4e9365890e55048783afc0bb07a8e214b0bcfe7b88e6bb2bf" + [[package]] name = "socket2" version = "0.4.10" @@ -2751,7 +2754,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2800c129338c77998c1dcb6d4200447e018beb7d29959eb104cba2d45f83c1a" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", "nix 0.26.4", ] @@ -2772,7 +2775,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ff9eaf853dec4c8802325d8b6d3dffa86cc707fd7a1a4cdbf416e13b061787a" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -2795,24 +2798,24 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.26.3" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7993a8e3a9e88a00351486baae9522c91b123a088f76469e5bd5cc17198ea87" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", "rustversion", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -2828,9 +2831,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -2876,12 +2879,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" -[[package]] -name = "text_io" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f0c8eb2ad70c12a6a69508f499b3051c924f4b1cfeae85bfad96e6bc5bba46" - [[package]] name = "thiserror" version = "1.0.61" @@ -2899,7 +2896,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -2944,9 +2941,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" dependencies = [ "tinyvec_macros", ] @@ -2984,7 +2981,22 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", +] + +[[package]] +name = "tokio-serde" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf600e7036b17782571dd44fa0a5cea3c82f60db5137f774a325a76a0d6852b" +dependencies = [ + "bincode", + "bytes", + "educe", + "futures-core", + "futures-sink", + "pin-project", + "serde", ] [[package]] @@ -2998,6 +3010,19 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-util" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + [[package]] name = "tower" version = "0.4.13" @@ -3044,7 +3069,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3100,7 +3125,7 @@ dependencies = [ "once_cell", "regex", "sharded-slab", - "smallvec", + "smallvec 1.13.2", "thread_local", "tracing", "tracing-core", @@ -3133,9 +3158,9 @@ dependencies = [ [[package]] name = "unescaper" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0adf6ad32eb5b3cadff915f7b770faaac8f7ff0476633aa29eb0d9584d889d34" +checksum = "c878a167baa8afd137494101a688ef8c67125089ff2249284bd2b5f9bfedb815" dependencies = [ "thiserror", ] @@ -3182,15 +3207,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5fbabedabe362c618c714dbefda9927b5afc8e2a8102f47f081089a9019226" dependencies = [ - "itertools", + "itertools 0.12.1", "unicode-width", ] [[package]] name = "unicode-width" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" @@ -3206,9 +3231,9 @@ checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -3217,9 +3242,9 @@ dependencies = [ [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "valuable" @@ -3281,7 +3306,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "wasm-bindgen-shared", ] @@ -3315,7 +3340,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3364,7 +3389,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -3382,7 +3407,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -3402,18 +3427,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -3424,9 +3449,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -3436,9 +3461,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -3448,15 +3473,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -3466,9 +3491,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -3478,9 +3503,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -3490,9 +3515,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -3502,9 +3527,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winreg" @@ -3525,31 +3550,22 @@ dependencies = [ "tap", ] -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] diff --git a/crates/protocol/src/button.rs b/crates/protocol/src/button.rs index 990e9e51..19a84832 100644 --- a/crates/protocol/src/button.rs +++ b/crates/protocol/src/button.rs @@ -9,6 +9,8 @@ use serde::{Deserialize, Serialize}; Deserialize, postcard::experimental::max_size::MaxSize, defmt::Format, + PartialEq, + Eq, )] pub struct Press(pub u16); @@ -38,7 +40,9 @@ impl Press { macro_rules! button_enum { ( $(#[$outer:meta])* - $name:ident {$($variant:ident,)*}) => { + $name:ident {$($variant:ident,)*} + $device:expr; + ) => { #[derive(strum::VariantNames)] #[derive( Clone, @@ -47,7 +51,9 @@ macro_rules! button_enum { serde::Serialize, serde::Deserialize, defmt::Format, - postcard::experimental::max_size::MaxSize + postcard::experimental::max_size::MaxSize, + PartialEq, + Eq, )] $(#[$outer])* // docs /// SAFETY: must be repr(u8) or id fn will create undefined behaviour @@ -74,12 +80,15 @@ macro_rules! button_enum { } #[cfg(feature = "alloc")] - impl crate::tomato::Tomato for $name { - fn inner<'a>(&'a self) -> crate::tomato::TomatoItem<'a> { - crate::tomato::TomatoItem::Leaf(crate::tomato::TomatoLeaf { - val: (*self).into(), - device: "GPIO", - from_same_device: &[], // TODO + impl crate::reading_tree::Tree for $name { + fn inner<'a>(&'a self) -> crate::reading_tree::Item<'a> { + crate::reading_tree::Item::Leaf(crate::reading_tree::ReadingInfo { + val: (*self).into(), + device: $device, + description: "button", + range: 0.0..3.0, + resolution: 1.0, + unit: crate::Unit::None, }) } fn name(&self) -> String { @@ -90,13 +99,13 @@ macro_rules! button_enum { .unwrap_or("-") .to_string() } - fn id(&self) -> crate::tomato::TomatoId { + fn id(&self) -> crate::reading_tree::Id { // SAFETY: Because `Self` is marked `repr(u8)`, its layout is a // `repr(C)` `union` between `repr(C)` structs, each of which // has the `u8` discriminant as its first field, so we can read // the discriminant without offsetting the pointer. let discriminant = unsafe { *<*const _>::from(self).cast::() }; - discriminant as crate::tomato::TomatoId + discriminant as crate::reading_tree::Id } } }; diff --git a/crates/protocol/src/device_tree.rs b/crates/protocol/src/device_tree.rs new file mode 100644 index 00000000..e69de29b diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index ed235d03..4bf6202a 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -2,13 +2,21 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; #[cfg(feature = "alloc")] -use crate::all_nodes; +use crate::reading_tree; pub mod bed; pub mod desk; #[derive( - strum::EnumDiscriminants, Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, )] #[strum_discriminants(derive(Hash))] pub enum Reading { @@ -17,7 +25,7 @@ pub enum Reading { } #[cfg(feature = "alloc")] -all_nodes! {Reading; ReadingDiscriminants; Bed, Desk} +reading_tree::all_nodes! {Reading; ReadingDiscriminants; Bed, Desk} #[derive( strum::EnumDiscriminants, @@ -36,14 +44,10 @@ pub enum Error { } impl Error { - pub fn broken_readings(&self) -> impl Iterator { + pub fn device(&self) -> Device { match self { - Error::Bed(error) => error - .affected_readings() - .into_iter() - .cloned() - .map(Reading::Bed), - Error::Desk(_) => todo!(), + Error::Bed(error) => Device::Bed(error.device()), + Error::Desk(error) => Device::Desk(error.device()), } } } @@ -57,11 +61,26 @@ impl core::fmt::Display for Error { } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq, Hash)] pub enum Device { Bed(bed::Device), Desk(desk::Device), } +impl Device { + pub(crate) fn affected_readings(&self) -> &'static [crate::Reading] { + match self { + Self::Bed(dev) => dev.affected_readings(), + Self::Desk(dev) => dev.affected_readings(), + } + } + + pub(crate) fn as_str(&self) -> &'static str { + match self { + Self::Bed(dev) => dev.as_str(), + Self::Desk(dev) => dev.as_str(), + } + } +} #[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] pub enum Actuator { diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 23fdd82d..2e5c0730 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -1,7 +1,9 @@ use crate::button::Press; use crate::button_enum; #[cfg(feature = "alloc")] -use crate::tomato::{Tomato, TomatoId, TomatoItem, TomatoLeaf}; +use crate::reading_tree::{Id, Item, ReadingInfo, Tree}; +#[cfg(feature = "alloc")] +use crate::Unit; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -28,10 +30,11 @@ button_enum! { LowerCenter, LowerOuter, } + crate::Device::LargeBedroom(crate::large_bedroom::Device::Bed(Device::Gpio)); } #[derive( - strum::EnumDiscriminants, Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, + strum::EnumDiscriminants, Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, PartialEq, )] #[strum_discriminants(derive(Hash))] pub enum Reading { @@ -57,7 +60,7 @@ pub enum Reading { /// Mass Concentration PM10 \[μg/m³\] MassPm10(f32), /// Number Concentration PM0.5 \[#/cm³\] - MassPm0_5(f32), + NumberPm0_5(f32), /// Number Concentration PM1.0 \[#/cm³\] NumberPm1_0(f32), /// Number Concentration PM2.5 \[#/cm³\] @@ -71,63 +74,172 @@ pub enum Reading { } #[cfg(feature = "alloc")] -macro_rules! put_in_tree { - ([$($reading:expr),+]) => { - [$(crate::Reading::LargeBedroom( - crate::large_bedroom::Reading::Bed($reading), - )),+] - }; -} - -#[cfg(feature = "alloc")] -fn leaf(val: &f32, device: Device, from_same_device: &'static [crate::Reading]) -> TomatoLeaf { - TomatoLeaf { - val: *val, - device: device.as_str(), - from_same_device, - } -} - -#[cfg(feature = "alloc")] -impl Tomato for Reading { - fn inner<'a>(&'a self) -> TomatoItem<'a> { - let (val, device) = match self { - Reading::Brightness(val) => (*val, Device::Max44), - Reading::Temperature(val) => (*val, Device::Sht31), - Reading::Humidity(val) => (*val, Device::Sht31), - Reading::GassResistance(val) => (*val, Device::Bme680), - Reading::Pressure(val) => (*val, Device::Bme680), - Reading::Co2(val) => (*val as f32, Device::Mhz14), - Reading::WeightLeft(val) => (*val as f32, Device::Nau7802Left), - Reading::WeightRight(val) => (*val as f32, Device::Nau7802Right), - Reading::Button(val) => ((*val).into(), Device::Gpio), - Reading::MassPm1_0(val) => (*val, Device::Sps30), - Reading::MassPm2_5(val) => (*val, Device::Sps30), - Reading::MassPm4_0(val) => (*val, Device::Sps30), - Reading::MassPm10(val) => (*val, Device::Sps30), - Reading::MassPm0_5(val) => (*val, Device::Sps30), - Reading::NumberPm1_0(val) => (*val, Device::Sps30), - Reading::NumberPm2_5(val) => (*val, Device::Sps30), - Reading::NumberPm4_0(val) => (*val, Device::Sps30), - Reading::NumberPm10(val) => (*val, Device::Sps30), - Reading::TypicalParticleSize(val) => (*val, Device::Sps30), +impl Tree for Reading { + fn inner<'a>(&'a self) -> Item<'a> { + let (val, device, range, resolution, unit, description) = match self { + Reading::Brightness(val) => ( + *val, + Device::Max44.rooted(), + 0.045..188.000, + 0.045, + Unit::Lux, + "Brightness", + ), + Reading::Temperature(val) => ( + *val, + Device::Sht31.rooted(), + -10.0..45.0, + 0.01, + Unit::C, + "Temperature", + ), + Reading::Humidity(val) => ( + *val, + Device::Sht31.rooted(), + 0.0..100.0, + 0.01, + Unit::RH, + "Relative humidity", + ), + // air quality: comp_gas = log(R_gas[ohm]) + 0.04 log(Ohm)/%rh * hum[%rh] + Reading::GassResistance(val) => ( + *val, + Device::Bme680.rooted(), + 0.0..1_000_000.0, + 1.0, + Unit::Ohm, + "Gass resistance", + ), + // record air pressure + // - 1.081hPa (dead sea 430 below normal sea level) + // - 870hPa (middle of a tornado) + Reading::Pressure(val) => ( + *val, + Device::Bme680.rooted(), + 87_000.0..108_100.0, + 0.18, + Unit::Pa, + "Air pressure", + ), + Reading::Co2(val) => ( + *val as f32, + Device::Mhz14.rooted(), + 400.0..2_000.0, + 1.0, + Unit::Ppm, + "Co2 concentration", + ), + Reading::WeightLeft(val) => ( + *val as f32, + Device::Nau7802Left.rooted(), + 0.0..2.0_f32.exp2(), + 1.0, + Unit::Ohm, + "Left weight sensor resistance", + ), + Reading::WeightRight(val) => ( + *val as f32, + Device::Nau7802Right.rooted(), + 0.0..2.0_f32.exp2(), + 1.0, + Unit::Ohm, + "Right weight sensor resistance", + ), + Reading::Button(button) => return button.inner(), + Reading::MassPm1_0(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..1000.0, + 0.1, + Unit::MicrogramPerM3, + "Mass concentration particles between 0.3 to 1.0 μm", + ), + Reading::MassPm2_5(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..1000.0, + 0.1, + Unit::MicrogramPerM3, + "Mass concentration particles between 0.3 to 2.5 μm", + ), + Reading::MassPm4_0(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..1000.0, + 0.1, + Unit::MicrogramPerM3, + "Mass concentration particles between 0.3 to 4.0 μm", + ), + Reading::MassPm10(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..1000.0, + 0.1, + Unit::MicrogramPerM3, + "Mass concentration particles between 0.3 to 10.0 μm", + ), + Reading::NumberPm0_5(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..3000.0, + 0.1, + Unit::NumberPerCm3, + "Concentration of particles between 0.3 to 0.5 μm", + ), + Reading::NumberPm1_0(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..3000.0, + 0.1, + Unit::NumberPerCm3, + "Concentration of particles between 0.3 to 1.0 μm", + ), + Reading::NumberPm2_5(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..3000.0, + 0.1, + Unit::NumberPerCm3, + "Concentration of particles between 0.3 to 2.5 μm", + ), + Reading::NumberPm4_0(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..3000.0, + 0.1, + Unit::NumberPerCm3, + "Concentration of particles between 0.3 to 4.0 μm", + ), + Reading::NumberPm10(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..3000.0, + 0.1, + Unit::NumberPerCm3, + "Concentration of particles between 0.3 to 10.5 μm", + ), + Reading::TypicalParticleSize(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..10_000.0, + 0.5, + Unit::NanoMeter, + "Typical particle size", + ), }; - // let related = todo!(); - - // Reading::Brightness(val) => leaf(val, Device::Max44, &[]), - // Reading::Temperature(val) => { - // leaf(val, Device::Sht31, &put_in_tree!([Reading::Humidity(0.0)])) - // } - TomatoItem::Leaf(TomatoLeaf { + Item::Leaf(ReadingInfo { val, - device: device.as_str(), - from_same_device: todo!(), + device, + resolution, + range, + unit, + description, }) } - fn id(&self) -> TomatoId { - ReadingDiscriminants::from(self) as TomatoId + fn id(&self) -> Id { + ReadingDiscriminants::from(self) as Id } } @@ -140,12 +252,11 @@ pub enum Error { } impl Error { - pub fn affected_readings(&self) -> &'static [Reading] { + pub(crate) fn device(&self) -> Device { match self { Self::Running(sensor_err) | Self::Setup(sensor_err) => sensor_err.device(), Self::SetupTimedOut(device) | Self::Timeout(device) => device.clone(), } - .broken_readings() } } @@ -203,7 +314,7 @@ impl SensorError { } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq, Hash)] pub enum Device { Sht31, Bme680, @@ -221,6 +332,14 @@ impl core::fmt::Display for Device { } } +macro_rules! tree { + [$($reading:expr),+] => { + [$(crate::Reading::LargeBedroom( + crate::large_bedroom::Reading::Bed($reading), + )),+] + }; +} + impl Device { pub fn as_str(&self) -> &'static str { match self { @@ -235,27 +354,29 @@ impl Device { } } - pub fn broken_readings(&self) -> &'static [Reading] { + /// Note the order in which these occur is the order in which + /// they will be stored, do not change it! + pub fn affected_readings(&self) -> &'static [crate::Reading] { match self { - Device::Sht31 => &[Reading::Temperature(0.0), Reading::Humidity(0.0)], - Device::Bme680 => &[Reading::GassResistance(0.0), Reading::Pressure(0.0)], - Device::Max44 => &[Reading::Brightness(0.0)], - Device::Mhz14 => &[Reading::Co2(0)], - Device::Sps30 => &[ + Device::Sht31 => &tree![Reading::Temperature(0.0), Reading::Humidity(0.0)], + Device::Bme680 => &tree![Reading::GassResistance(0.0), Reading::Pressure(0.0)], + Device::Max44 => &tree![Reading::Brightness(0.0)], + Device::Mhz14 => &tree![Reading::Co2(0)], + Device::Sps30 => &tree![ Reading::MassPm1_0(0.0), Reading::MassPm2_5(0.0), Reading::MassPm4_0(0.0), Reading::MassPm10(0.0), - Reading::MassPm0_5(0.0), + Reading::NumberPm0_5(0.0), Reading::NumberPm1_0(0.0), Reading::NumberPm2_5(0.0), Reading::NumberPm4_0(0.0), Reading::NumberPm10(0.0), - Reading::TypicalParticleSize(0.0), + Reading::TypicalParticleSize(0.0) ], - Device::Nau7802Left => &[Reading::WeightLeft(0)], - Device::Nau7802Right => &[Reading::WeightRight(0)], - Device::Gpio => &[ + Device::Nau7802Left => &tree![Reading::WeightLeft(0)], + Device::Nau7802Right => &tree![Reading::WeightRight(0)], + Device::Gpio => &tree![ Reading::Button(Button::TopLeft(Press(0))), Reading::Button(Button::TopRight(Press(0))), Reading::Button(Button::MiddleInner(Press(0))), @@ -263,8 +384,12 @@ impl Device { Reading::Button(Button::MiddleOuter(Press(0))), Reading::Button(Button::LowerInner(Press(0))), Reading::Button(Button::LowerCenter(Press(0))), - Reading::Button(Button::LowerOuter(Press(0))), + Reading::Button(Button::LowerOuter(Press(0))) ], } } + + fn rooted(self) -> crate::Device { + crate::Device::LargeBedroom(crate::large_bedroom::Device::Bed(self)) + } } diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index a887a688..8739caa7 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -1,9 +1,9 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; -use crate::button_enum; #[cfg(feature = "alloc")] -use crate::tomato::{Tomato, TomatoItem, TomatoLeaf}; +use crate::reading_tree::{Item, ReadingInfo, Tree}; +use crate::{button_enum, Unit}; button_enum! { /// No these are not borg, these are buttons on a string of cat5. @@ -17,10 +17,19 @@ button_enum! { TwoOfThree, ThreeOfThree, } + crate::Device::LargeBedroom(crate::large_bedroom::Device::Desk(Device::Gpio)); } #[derive( - strum::EnumDiscriminants, Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, )] #[strum_discriminants(derive(Hash))] pub enum Reading { @@ -31,23 +40,40 @@ pub enum Reading { } #[cfg(feature = "alloc")] -impl Tomato for Reading { - fn inner<'a>(&'a self) -> TomatoItem<'a> { - let (val, device) = match self { - Reading::Temperature(val) => (*val, Device::Bme280), - Reading::Humidity(val) => (*val, Device::Bme280), - Reading::Pressure(val) => (*val, Device::Bme280), - Reading::Button(val) => return TomatoItem::Node(val), +impl Tree for Reading { + fn inner<'a>(&'a self) -> Item<'a> { + let leaf = match self { + Reading::Temperature(val) => ReadingInfo { + val: *val, + device: Device::Bme280.rooted(), + resolution: 0.01, + range: -10.0..45.0, + unit: Unit::C, + description: "Temperature", + }, + Reading::Humidity(val) => ReadingInfo { + val: *val, + device: Device::Bme280.rooted(), + resolution: 0.008, + range: 0.0..100.0, + unit: Unit::RH, + description: "Temperature", + }, + Reading::Pressure(val) => ReadingInfo { + val: *val, + device: Device::Bme280.rooted(), + range: 87_000.0..108_100.0, + resolution: 0.18, + unit: Unit::Pa, + description: "Air pressure", + }, + Reading::Button(val) => return Item::Node(val as &dyn Tree), }; - TomatoItem::Leaf(TomatoLeaf { - val, - device: device.as_str(), - from_same_device: &[], // TODO - }) + Item::Leaf(leaf) } - fn id(&self) -> crate::tomato::TomatoId { - ReadingDiscriminants::from(self) as crate::tomato::TomatoId + fn id(&self) -> crate::reading_tree::Id { + ReadingDiscriminants::from(self) as crate::reading_tree::Id } } @@ -60,11 +86,11 @@ pub enum Error { } impl Error { - pub fn affected_readings(&self) -> &'static [Reading] { + pub fn device(&self) -> Device { match self { - Self::Running(sensor_err) => sensor_err.device().affected_readings(), - Self::Setup(sensor_err) => sensor_err.device().affected_readings(), - Self::SetupTimedOut(device) | Self::Timeout(device) => device.affected_readings(), + Self::Running(sensor_err) => sensor_err.device(), + Self::Setup(sensor_err) => sensor_err.device(), + Self::SetupTimedOut(device) | Self::Timeout(device) => device.clone(), } } } @@ -108,7 +134,7 @@ impl core::fmt::Display for SensorError { } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq, Hash)] pub enum Device { Bme280, Gpio, @@ -120,16 +146,27 @@ impl core::fmt::Display for Device { } } +macro_rules! rtree { + [$($reading:expr),+] => { + [$(crate::Reading::LargeBedroom( + crate::large_bedroom::Reading::Desk($reading), + )),+] + }; +} + impl Device { + pub fn rooted(self) -> crate::Device { + crate::Device::LargeBedroom(crate::large_bedroom::Device::Desk(self)) + } pub fn as_str(&self) -> &'static str { match self { Device::Bme280 => "Bme280", Device::Gpio => "Gpio", } } - pub fn affected_readings(&self) -> &'static [Reading] { + pub fn affected_readings(&self) -> &'static [crate::Reading] { match self { - Device::Bme280 => &[Reading::Temperature(0.0), Reading::Humidity(0.0)], + Device::Bme280 => &rtree![Reading::Temperature(0.0), Reading::Humidity(0.0)], Device::Gpio => todo!(), } } diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 59042930..03363743 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -9,10 +9,24 @@ pub mod small_bedroom; pub mod button; pub(crate) use button::button_enum; +// #[cfg(feature = "alloc")] +// pub mod device_tree; #[cfg(feature = "alloc")] -pub mod tomato; -#[cfg(feature = "alloc")] -pub(crate) use tomato::all_nodes; +pub mod reading_tree; + +#[derive(Debug)] +pub enum Unit { + Pa, + C, + RH, + Lux, + Ohm, + Ppm, + MicrogramPerM3, + NumberPerCm3, + NanoMeter, + None, // for buttons +} #[derive( strum::EnumDiscriminants, @@ -23,14 +37,34 @@ pub(crate) use tomato::all_nodes; Serialize, Deserialize, MaxSize, + PartialEq, )] #[strum_discriminants(derive(Hash))] pub enum Reading { LargeBedroom(large_bedroom::Reading), - // SmallBedroom(small_bedroom::Reading), + SmallBedroom(small_bedroom::Reading), // Test, } +#[cfg(feature = "alloc")] +impl Reading { + pub fn from_same_device(&self) -> &'static [Reading] { + use reading_tree::Tree; + self.leaf().from_same_device() + } + pub fn range(&self) -> core::ops::Range { + use reading_tree::Tree; + self.leaf().range + } + pub fn resolution(&self) -> f32 { + use reading_tree::Tree; + self.leaf().resolution + } + pub fn device(&self) -> Device { + use reading_tree::Tree; + self.leaf().device + } +} impl Reading { pub fn version() -> u8 { 0u8 @@ -38,7 +72,7 @@ impl Reading { } #[cfg(feature = "alloc")] -all_nodes! {Reading; ReadingDiscriminants; LargeBedroom} //, Test} +reading_tree::all_nodes! {Reading; ReadingDiscriminants; LargeBedroom, SmallBedroom} #[derive( strum::EnumDiscriminants, @@ -54,10 +88,30 @@ pub enum Error { LargeBedroom(large_bedroom::Error), } +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, PartialEq, Eq, Hash)] +pub enum Device { + LargeBedroom(large_bedroom::Device), + SmallBedroom(small_bedroom::Device), +} +impl Device { + pub fn affected_readings(&self) -> &'static [Reading] { + match self { + Device::LargeBedroom(dev) => dev.affected_readings(), + Device::SmallBedroom(dev) => dev.affected_readings(), + } + } + pub fn as_str(&self) -> &'static str { + match self { + Device::LargeBedroom(dev) => dev.as_str(), + Device::SmallBedroom(dev) => dev.as_str(), + } + } +} + impl Error { - pub fn affected_readings(&self) -> impl Iterator { + pub fn device(&self) -> Device { match self { - Error::LargeBedroom(error) => error.broken_readings().map(Reading::LargeBedroom), + Error::LargeBedroom(error) => Device::LargeBedroom(error.device()), } } } diff --git a/crates/protocol/src/reading_tree.rs b/crates/protocol/src/reading_tree.rs new file mode 100644 index 00000000..cd793e36 --- /dev/null +++ b/crates/protocol/src/reading_tree.rs @@ -0,0 +1,69 @@ +use crate::{Device, Reading, Unit}; + +#[derive(Debug)] +pub struct ReadingInfo { + pub val: f32, + pub device: Device, + pub resolution: f32, + pub range: core::ops::Range, + pub unit: Unit, + pub description: &'static str, +} + +impl ReadingInfo { + pub fn from_same_device(&self) -> &'static [Reading] { + self.device.affected_readings() + } +} + +pub type Id = u8; +#[derive(Debug)] +pub enum Item<'a> { + Leaf(ReadingInfo), + Node(&'a dyn Tree), +} + +pub trait Tree: core::fmt::Debug { + fn inner<'a>(&'a self) -> Item<'a>; + fn leaf<'a>(&'a self) -> ReadingInfo + where + Self: Sized, + { + let mut current = self as &dyn Tree; + loop { + match current.inner() { + Item::Node(node) => current = node, + Item::Leaf(leaf) => return leaf, + } + } + } + fn name(&self) -> String { + let dbg_repr = format!("{:?}", self); + dbg_repr + .split_once('(') + .map(|(name, _)| name) + .unwrap_or("-") + .to_string() + } + fn id(&self) -> Id; +} + +macro_rules! all_nodes { + ($name:ident; $variant:ident; $($var:ident),*) => { + impl crate::reading_tree::Tree for $name { + fn inner<'a>(&'a self) -> crate::reading_tree::Item<'a> { + match self { + $( + $name::$var(inner) => crate::reading_tree::Item::Node(inner as &dyn crate::reading_tree::Tree) + ),* + } + } + + fn id(&self) -> crate::reading_tree::Id { + $variant::from(self) as crate::reading_tree::Id + } + } + }; +} + +pub(crate) use all_nodes; diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index 216dda9e..9c6585eb 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -1,5 +1,8 @@ -use serde::{Deserialize, Serialize}; use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +use crate::button::Press; +use crate::reading_tree::{Item, Tree}; crate::button_enum! { /// +-----------------------------------------+ @@ -15,9 +18,68 @@ crate::button_enum! { BottomMiddle, BOttomRight, } + crate::Device::SmallBedroom(crate::small_bedroom::Device::Gpio); +} + +#[derive( + strum::EnumDiscriminants, Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, PartialEq, +)] +pub enum Reading { + ButtonPanel(ButtonPanel), } -#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] -pub enum SmallBedroom { - Desk(ButtonPanel), +impl Tree for Reading { + fn inner<'a>(&'a self) -> Item<'a> { + match self { + Reading::ButtonPanel(inner) => return Item::Node(inner), + } + } + + fn id(&self) -> crate::reading_tree::Id { + ReadingDiscriminants::from(self) as crate::reading_tree::Id + } +} + +#[derive( + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + Hash, + PartialEq, + Eq, +)] +pub enum Device { + Gpio, +} + +macro_rules! tree { + [$($button:expr),+] => { + [$(crate::Reading::SmallBedroom( + crate::small_bedroom::Reading::ButtonPanel($button), + )),+] + }; +} + +impl Device { + pub(crate) fn affected_readings(&self) -> &'static [crate::Reading] { + match self { + Device::Gpio => &tree![ + ButtonPanel::TopLeft(Press(0)), + ButtonPanel::TopMiddle(Press(0)), + ButtonPanel::TopRight(Press(0)), + ButtonPanel::BottomLeft(Press(0)), + ButtonPanel::BottomMiddle(Press(0)), + ButtonPanel::BOttomRight(Press(0)) + ], + } + } + + pub(crate) fn as_str(&self) -> &'static str { + match self { + Device::Gpio => "Gpio", + } + } } diff --git a/crates/protocol/src/tomato.rs b/crates/protocol/src/tomato.rs deleted file mode 100644 index b014c2d6..00000000 --- a/crates/protocol/src/tomato.rs +++ /dev/null @@ -1,60 +0,0 @@ -#[derive(Debug)] -pub struct TomatoLeaf { - pub val: f32, - pub device: &'static str, - pub from_same_device: &'static [Reading], -} - -pub type TomatoId = u8; -#[derive(Debug)] -pub enum TomatoItem<'a> { - Leaf(TomatoLeaf), - Node(&'a dyn Tomato), -} - -pub trait Tomato: core::fmt::Debug { - fn inner<'a>(&'a self) -> TomatoItem<'a>; - fn leaf<'a>(&'a self) -> TomatoLeaf - where - Self: Sized, - { - let mut current = self as &dyn Tomato; - loop { - match current.inner() { - TomatoItem::Node(node) => current = node, - TomatoItem::Leaf(leaf) => return leaf, - } - } - } - fn name(&self) -> String { - let dbg_repr = format!("{:?}", self); - dbg_repr - .split_once('(') - .map(|(name, _)| name) - .unwrap_or("-") - .to_string() - } - fn id(&self) -> TomatoId; -} - -macro_rules! all_nodes { - ($name:ident; $variant:ident; $($var:ident),*) => { - impl crate::tomato::Tomato for $name { - fn inner<'a>(&'a self) -> crate::tomato::TomatoItem<'a> { - match self { - $( - $name::$var(inner) => crate::tomato::TomatoItem::Node(inner as &dyn crate::tomato::Tomato) - ),* - } - } - - fn id(&self) -> crate::tomato::TomatoId { - $variant::from(self) as crate::tomato::TomatoId - } - } - }; -} - -pub(crate) use all_nodes; - -use crate::Reading; diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index b8660464..356a13bb 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -1,6 +1,6 @@ use histogram::Histogram; use protocol::Error; -use protocol::{tomato::Tomato, tomato::TomatoItem, Reading}; +use protocol::{ReadingTree::Tomato, ReadingTree::TomatoItem, Reading}; use ratatui::{text::Line, widgets::Bar}; use std::collections::HashMap; use std::{collections::VecDeque, time::Instant}; From c293e6f6eb28180a65177a83a24f91289842e5dd Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 5 Jul 2024 18:04:24 +0200 Subject: [PATCH 138/687] adds data-store a timeseries database working via the protocol --- crates/data-store/Cargo.toml | 34 +++ crates/data-store/src/api.rs | 34 +++ crates/data-store/src/api/client.rs | 92 ++++++ crates/data-store/src/lib.rs | 3 + crates/data-store/src/main.rs | 38 +++ crates/data-store/src/server.rs | 25 ++ crates/data-store/src/server/clients.rs | 77 +++++ crates/data-store/src/server/db.rs | 70 +++++ crates/data-store/src/server/db/series.rs | 264 ++++++++++++++++++ .../src/server/db/series/resampler.rs | 50 ++++ crates/data-store/tests/list_data.rs | 64 +++++ 11 files changed, 751 insertions(+) create mode 100644 crates/data-store/Cargo.toml create mode 100644 crates/data-store/src/api.rs create mode 100644 crates/data-store/src/api/client.rs create mode 100644 crates/data-store/src/lib.rs create mode 100644 crates/data-store/src/main.rs create mode 100644 crates/data-store/src/server.rs create mode 100644 crates/data-store/src/server/clients.rs create mode 100644 crates/data-store/src/server/db.rs create mode 100644 crates/data-store/src/server/db/series.rs create mode 100644 crates/data-store/src/server/db/series/resampler.rs create mode 100644 crates/data-store/tests/list_data.rs diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml new file mode 100644 index 00000000..c03a14d5 --- /dev/null +++ b/crates/data-store/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "data-store" +version = "0.1.0" +rust-version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true + +[dependencies] +clap = { version = "4", features = ["derive"] } +color-eyre = "0.6.3" +tracing = "0.1.40" +tracing-error = "0.2.0" +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +time = { version = "0.3", features = ["serde"] } + +protocol = { path = "../protocol", features = ["alloc"] } +data-server = { path = "../data-server" } + +# bitspec = { git = "https://github.com/dvdsk/bitspec" } +bitspec = { path = "/home/david/Documents/bitspec" } +byteseries = { git = "https://github.com/dvdsk/byteseries", features = ["smallvec"] } +# byteseries = { path = "/home/david/Documents/byteseries" } +tokio = { version = "1.38.0", features = ["fs", "net", "rt-multi-thread", "sync"] } +futures-concurrency = "7.6.1" +tokio-serde = { version = "0.9.0", features = ["bincode"] } +tokio-util = { version = "0.7.11", features = ["codec"] } +serde = { version = "1.0.203", features = ["derive"] } +thiserror = "1.0.61" +futures = "0.3.30" +smallvec = "2.0.0-alpha.6" + +[dev-dependencies] +futures-concurrency = "7.6.1" diff --git a/crates/data-store/src/api.rs b/crates/data-store/src/api.rs new file mode 100644 index 00000000..16200e38 --- /dev/null +++ b/crates/data-store/src/api.rs @@ -0,0 +1,34 @@ +use protocol::Reading; + +use serde::{Serialize, Deserialize}; +use time::OffsetDateTime; + +mod client; +pub use client::Client; + +// 8 MB +pub(crate) const MAX_PACKAGE_SIZE: usize = 8*1024*1024; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub(crate) enum Request { + ListData, + GetData { + reading: Reading, + start: OffsetDateTime, + end: OffsetDateTime, + n: usize, + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, thiserror::Error)] +pub enum ServerError { + #[error("We do not have any data for this reading: {reading:?}")] + NotInStore { reading: Reading }, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub(crate) enum Response { + ListData(Vec), + GetData(Vec<(OffsetDateTime, f32)>), + Error(ServerError), +} diff --git a/crates/data-store/src/api/client.rs b/crates/data-store/src/api/client.rs new file mode 100644 index 00000000..fcd42e0a --- /dev/null +++ b/crates/data-store/src/api/client.rs @@ -0,0 +1,92 @@ +use futures::{SinkExt, TryStreamExt}; +use tokio::net::TcpStream; +use tokio::net::ToSocketAddrs; +use tokio_serde::formats::Bincode; +use tokio_util::codec::{Framed, LengthDelimitedCodec}; + +use time::OffsetDateTime; + +pub struct Client { + stream: tokio_serde::Framed< + Framed, + super::Response, + super::Request, + Bincode, + >, +} + +#[derive(Debug, thiserror::Error)] +#[error("Error while connecting to data server: {0}")] +pub struct ConnectError(std::io::Error); + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Got unexpected response response to request {request:?}")] + IncorrectResponse { request: String, response: String }, + #[error("Error while sending request: {0}")] + Sending(std::io::Error), + #[error("Error while sending request: {0}")] + Receiving(std::io::Error), + #[error("Server ran into an error while processing our request: {0}")] + ServerError(super::ServerError), + #[error("Server closed connection before it awnserd")] + ConnectionClosed, +} + +impl Client { + pub async fn connect(addr: impl ToSocketAddrs) -> Result { + let stream = TcpStream::connect(addr).await.map_err(ConnectError)?; + + let length_delimited = Framed::new( + stream, + LengthDelimitedCodec::builder() + .max_frame_length(super::MAX_PACKAGE_SIZE) + .new_codec(), + ); + + let stream = tokio_serde::Framed::new(length_delimited, Bincode::default()); + Ok(Self { stream }) + } + + async fn send_receive(&mut self, request: super::Request) -> Result { + self.stream.send(request).await.map_err(Error::Sending)?; + match self.stream.try_next().await.map_err(Error::Receiving)? { + Some(super::Response::Error(e)) => Err(Error::ServerError(e)), + Some(response) => Ok(response), + None => Err(Error::ConnectionClosed), + } + } + + pub async fn list_data(&mut self) -> Result, Error> { + let request = super::Request::ListData; + match self.send_receive(request.clone()).await? { + super::Response::ListData(list) => return Ok(list), + response => Err(Error::IncorrectResponse { + request: format!("{request:?}"), + response: format!("{response:?}"), + }), + } + } + + pub async fn get_data( + &mut self, + start: OffsetDateTime, + end: OffsetDateTime, + reading: protocol::Reading, + n: usize, + ) -> Result, Error> { + let request = super::Request::GetData { + reading, + start, + end, + n, + }; + match self.send_receive(request.clone()).await? { + super::Response::GetData(data) => return Ok(data), + response => Err(Error::IncorrectResponse { + request: format!("{request:?}"), + response: format!("{response:?}"), + }), + } + } +} diff --git a/crates/data-store/src/lib.rs b/crates/data-store/src/lib.rs new file mode 100644 index 00000000..247f3b05 --- /dev/null +++ b/crates/data-store/src/lib.rs @@ -0,0 +1,3 @@ +pub mod api; + +pub mod server; diff --git a/crates/data-store/src/main.rs b/crates/data-store/src/main.rs new file mode 100644 index 00000000..07d62674 --- /dev/null +++ b/crates/data-store/src/main.rs @@ -0,0 +1,38 @@ +use std::net::SocketAddr; + +use clap::Parser; +use color_eyre::eyre::Result; + + +#[derive(Parser)] +#[command(name = "data server")] +#[command(version = "1.0")] +#[command(about = "Receives sensor events and spreads those to subscribed services")] +struct Cli { + #[arg(short, long)] + data_server: SocketAddr, + + #[arg(short, long)] + client_port: u16, +} + +#[tokio::main] +async fn main() -> Result<()> { + setup_tracing().unwrap(); + let cli = Cli::parse(); + data_store::server::run(cli.data_server, cli.client_port).await +} + +fn setup_tracing() -> Result<()> { + use tracing_error::ErrorLayer; + use tracing_subscriber::EnvFilter; + use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt}; + + color_eyre::install().unwrap(); + + tracing_subscriber::registry() + .with(EnvFilter::from_default_env()) + .with(ErrorLayer::default()) + .init(); + Ok(()) +} diff --git a/crates/data-store/src/server.rs b/crates/data-store/src/server.rs new file mode 100644 index 00000000..e562be5d --- /dev/null +++ b/crates/data-store/src/server.rs @@ -0,0 +1,25 @@ +use std::collections::HashMap; +use std::net::SocketAddr; +use std::sync::Arc; +use color_eyre::Result; +use futures_concurrency::future::Race; +use tokio::sync::Mutex; + +mod clients; +mod db; + +// used from tests +pub async fn run(data_server: SocketAddr, client_port: u16) -> Result<()> { + let data = db::Data(Arc::new(Mutex::new(HashMap::new()))); + let error = ( + db::run(data_server, data.clone()), + clients::handle(client_port, data), + ) + .race() + .await; + assert!( + error.is_err(), + "db::run and client::handle never return unless an error happens" + ); + error +} diff --git a/crates/data-store/src/server/clients.rs b/crates/data-store/src/server/clients.rs new file mode 100644 index 00000000..1344c4fc --- /dev/null +++ b/crates/data-store/src/server/clients.rs @@ -0,0 +1,77 @@ +use color_eyre::eyre::Context; +use color_eyre::Section; +use futures::{SinkExt, TryStreamExt}; +use tokio::net::{TcpListener, TcpStream}; +use tokio_serde::formats::Bincode; +use tokio_util::codec::{Framed, LengthDelimitedCodec}; +use tracing::{debug, error, info, warn}; + +use super::db::Data; +use crate::api::{self, ServerError}; + +pub(crate) async fn handle(port: u16, data: Data) -> color_eyre::Result<()> { + let listener = TcpListener::bind(format!("0.0.0.0:{port}")) + .await + .wrap_err("Could not bind to address") + .with_note(|| format!("port: {port}"))?; + + loop { + let socket = match listener.accept().await { + Ok((socket, source)) => { + info!("client connected from source: {source}"); + socket + } + Err(e) => { + warn!("client could not connect: {e}"); + continue; + } + }; + + tokio::task::spawn(handle_client(socket, data.clone())); + } +} + +pub(crate) async fn handle_client(socket: TcpStream, data: Data) { + let length_delimited = Framed::new( + socket, + LengthDelimitedCodec::builder() + .max_frame_length(api::MAX_PACKAGE_SIZE) + .new_codec(), + ); + let mut stream: tokio_serde::Framed<_, api::Request, api::Response, _> = + tokio_serde::Framed::new(length_delimited, Bincode::default()); + + loop { + let request = match stream.try_next().await { + Ok(Some(request)) => request, + Ok(None) => { + debug!("Connection ended"); + return; + } + Err(e) => { + error!("Could not receive request: {e:?}"); + return; + } + }; + let response = match perform_request(request, &data).await { + Err(err) => api::Response::Error(err), + Ok(r) => r, + }; + if let Err(e) = stream.send(response).await { + error!("Error sending response to client: {e:?}"); + return; + } + } +} + +async fn perform_request(request: api::Request, data: &Data) -> Result { + Ok(match request { + api::Request::ListData => api::Response::ListData(data.list().await), + api::Request::GetData { + reading, + start, + end, + n, + } => api::Response::GetData(data.get(reading, start, end, n).await?), + }) +} diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs new file mode 100644 index 00000000..6ad7a606 --- /dev/null +++ b/crates/data-store/src/server/db.rs @@ -0,0 +1,70 @@ +use std::collections::HashMap; +use std::net::SocketAddr; +use std::sync::Arc; + +use time::OffsetDateTime; +use tokio::sync::Mutex; + +use color_eyre::eyre::WrapErr; +use color_eyre::{Result, Section}; +use data_server::{AsyncSubscriber, SubMessage}; + +mod series; +use series::Series; + +use crate::api; + +// TODO make resistant to data_server going down +pub(crate) async fn run(data_server_addr: SocketAddr, data: Data) -> Result<()> { + let mut sub = AsyncSubscriber::connect(data_server_addr) + .await + .wrap_err("failed to connect") + .with_suggestion(|| format!("verify the server is listening on: {data_server_addr}"))?; + + loop { + let res = match sub + .next() + .await + .wrap_err("Error getting next reading from server")? + { + SubMessage::Reading(reading) => series::store(&data, &reading).await, + SubMessage::ErrorReport(_) => continue, + }; + + if let Err(e) = res { + tracing::error!("Error processing new reading: {e}"); + } + } +} + +#[derive(Debug, Clone)] +pub(crate) struct Data(pub(crate) Arc>>); + +impl Data { + pub(crate) async fn list(&self) -> Vec { + self.0 + .lock() + .await + .keys() + .flat_map(|device| device.affected_readings()) + .cloned() + .collect() + } + pub(crate) async fn get( + &self, + reading: protocol::Reading, + start: OffsetDateTime, + end: OffsetDateTime, + n: usize, + ) -> Result, api::ServerError> { + let key = reading.device(); + let series = self.0 + .lock() + .await + .get_mut(&key) + .ok_or(api::ServerError::NotInStore { reading })?; + + // series. + + } +} diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs new file mode 100644 index 00000000..a0a56c92 --- /dev/null +++ b/crates/data-store/src/server/db/series.rs @@ -0,0 +1,264 @@ +use std::io; +use std::path::PathBuf; +use std::time::Instant; + +use byteseries::{downsample, series, ByteSeries}; +use color_eyre::eyre::{eyre, WrapErr}; +use color_eyre::{Result, Section}; +use protocol::reading_tree::{Item, ReadingInfo, Tree}; +use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; +use tracing::info; + +mod resampler; +use crate::api; + +use self::resampler::Resampler; + +use super::Data; + +#[derive(Debug)] +pub(crate) struct Series { + line: Vec, + field_set_at: Vec, + fields: Vec>, + byteseries: ByteSeries, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +struct Header { + readings: Vec, + encoding: Vec>, +} + +impl Series { + fn open_or_create(reading: &protocol::Reading) -> Result { + let path = base_path(reading); + let readings = reading.device().affected_readings(); + let specs = to_speclist(readings); + + let fields = bitspec::speclist_to_fields(specs); + let payload_size = fields + .iter() + .map(|spec| spec.length as usize) + .sum::() + / 8; + let resampler = Resampler::from_fields(fields.clone(), payload_size); + let resample_configs = vec![downsample::Config { + max_gap: None, + bucket_size: 10, + }]; + let res = ByteSeries::open_existing_with_resampler::( + &path, + payload_size, + resampler.clone(), + resample_configs.clone(), + ); + + use byteseries::file::OpenError as FileOpenError; + use series::data::OpenError as DataOpenError; + use series::Error::Open; + + let expected_header = Header { + readings: readings.to_vec(), + encoding: fields.clone(), + }; + + let byteseries = match res { + Ok((byteseries, opened_file_header)) => { + if opened_file_header == expected_header { + byteseries + } else { + return Err(eyre!("header in file does not match readings")) + .with_note(|| { + format!( + "header in the just existing (opened) byteseries: {:?}", + opened_file_header + ) + }) + .with_note(|| { + format!( + "header for the data we want to write: {:?}", + expected_header + ) + }); + } + } + Err(Open(DataOpenError::File(FileOpenError::Io(e)))) + if e.kind() == io::ErrorKind::NotFound => + { + info!("creating new byteseries"); + ByteSeries::new_with_resamplers( + path, + payload_size, + expected_header, + resampler, + resample_configs, + ) + .wrap_err("Could not create new byteseries")? + } + Err(e) => return Err(e).wrap_err("Could not open existing byteseries")?, + }; + + Ok(Self { + line: vec![0; payload_size], + field_set_at: Vec::new(), + byteseries, + fields, + }) + } + + fn append(&mut self, reading: &protocol::Reading) -> Result<()> { + let index = reading + .device() + .affected_readings() + .iter() + .map(Tree::id) + .position(|local_id| local_id == reading.id()) + .expect("series are grouped by devices, elements come from affected_readings"); + + let field = &self.fields[index]; + field.encode::(reading.leaf().val, &mut self.line); + self.field_set_at[index] = Instant::now(); + + if self + .field_set_at + .iter() + .all(|set| set.elapsed().as_millis() < 500) + { + let time = OffsetDateTime::now_utc() - self.field_set_at[0].elapsed(); + self.byteseries + .push_line(time.unix_timestamp() as u64, &self.line) + .wrap_err("Could not write to timeseries on disk")?; + } + + Ok(()) + } + + fn read( + &mut self, + reading: &protocol::Reading, + start: OffsetDateTime, + end: OffsetDateTime, + n: usize, + ) -> Result<(Vec, Vec>), api::ServerError> { + let range = start.unix_timestamp() as u64..=end.unix_timestamp() as u64; + let mut resampler = Resampler::from_fields(self.fields.clone(), self.line.len()); + + let mut timestamps = Vec::with_capacity(n * 2); + let mut interleaved_data = Vec::with_capacity(n * 2); + self.byteseries.read_n( + n, + range, + &mut resampler, + &mut timestamps, + &mut interleaved_data, + ); + let time = timestamps + .into_iter() + .map(|ts| { + OffsetDateTime::from_unix_timestamp(ts as i64) + .expect("only valid timestamps are stored in byteseries") + }) + .collect(); + + let len = interleaved_data + .first() + .expect("read returns an error if there is not data") + .len(); + let mut data = vec![Vec::new(); len]; + for interleaved in interleaved_data { + for (interleaved, data) in interleaved.into_iter().zip(data.iter_mut()) { + data.push(interleaved) + } + } + Ok((time, data)) + } +} + +pub(crate) async fn store(data: &Data, reading: &protocol::Reading) -> Result<()> { + let mut data = data.0.lock().await; + + let key = reading.device(); + if let Some(series) = data.get_mut(&key) { + series + .append(reading) + .wrap_err("failed to append to existing timeseries")?; + } else { + let mut series = Series::open_or_create(&reading) + .wrap_err("Could not open new series") + .with_note(|| format!("reading was: {reading:?}"))?; + series + .append(reading) + .wrap_err("failed to newly created timeseries")?; + let existing = data.insert(key, series); + assert!(existing.is_none(), "should not race we still hold the lock"); + } + + Ok(()) +} + +fn to_speclist(readings: &[protocol::Reading]) -> Vec { + readings + .iter() + .map(|r| bitspec::RangeWithRes { + range: r.range(), + resolution: r.resolution(), + }) + .map(bitspec::LengthWithOps::from) + .collect() +} + +/// relative path without extension +fn base_path(reading: &protocol::Reading) -> PathBuf { + let mut parts = Vec::new(); + let mut current = reading as &dyn Tree; + loop { + match current.inner() { + Item::Leaf(ReadingInfo { device, .. }) => { + parts.push(device.as_str().to_lowercase()); + break; + } + Item::Node(inner) => { + parts.push(current.name().to_lowercase()); + current = inner; + continue; + } + } + } + parts.into_iter().collect() +} + +#[cfg(test)] +mod test { + use super::*; + use protocol::large_bedroom::{bed, desk}; + use protocol::{large_bedroom, Reading}; + + #[test] + fn readings_from_same_device_have_same_path() { + let reading_a = + Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::Temperature(0.0))); + let reading_b = + Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::Humidity(0.0))); + + assert_eq!(base_path(&reading_a), base_path(&reading_b)); + } + + #[test] + fn reading_path_different_between_locations() { + let reading_a = + Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::Humidity(0.0))); + let reading_b = + Reading::LargeBedroom(large_bedroom::Reading::Desk(desk::Reading::Humidity(0.0))); + + assert_ne!(base_path(&reading_a), base_path(&reading_b)); + } + + #[test] + fn reading_path_is_expected() { + let reading = + Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::Humidity(0.0))); + assert_eq!(base_path(&reading), PathBuf::from("largebedroom/bed/sht31")); + } +} diff --git a/crates/data-store/src/server/db/series/resampler.rs b/crates/data-store/src/server/db/series/resampler.rs new file mode 100644 index 00000000..198f2c15 --- /dev/null +++ b/crates/data-store/src/server/db/series/resampler.rs @@ -0,0 +1,50 @@ +use smallvec::smallvec; + +#[derive(Debug, Clone)] +pub(crate) struct Resampler { + pub(crate) fields: Vec>, + pub(crate) payload_size: usize, +} + +impl Resampler { + pub(crate) fn from_fields(fields: Vec>, payload_size: usize) -> Self { + Self { + payload_size, + fields, + } + } +} + +impl byteseries::Resampler for Resampler { + type State = smallvec::SmallVec; + + fn state(&self) -> Self::State { + smallvec![0f32; self.fields.len()] + } +} + +impl byteseries::Decoder for Resampler { + type Item = smallvec::SmallVec; + + // PERF: make item a smallVec <05-07-24, dvdsk noreply@davidsk.dev> + fn decode_payload(&mut self, payload: &[u8]) -> Self::Item { + self.fields + .iter() + .map(|field| field.decode(payload)) + .collect() + } +} + +impl byteseries::Encoder for Resampler { + type Item = smallvec::SmallVec; + + // PERF: should probably take a &mut[u8] instead of returning vec + // + fn encode_item(&mut self, item: &Self::Item) -> Vec { + let mut encoded = vec![0u8; self.payload_size]; + for (field, item) in self.fields.iter().zip(item) { + field.encode::(*item, &mut encoded); + } + encoded + } +} diff --git a/crates/data-store/tests/list_data.rs b/crates/data-store/tests/list_data.rs new file mode 100644 index 00000000..1835b679 --- /dev/null +++ b/crates/data-store/tests/list_data.rs @@ -0,0 +1,64 @@ +use std::iter; +use std::net::SocketAddr; +use std::time::{Duration, Instant}; + +use protocol::SensorMessage; +use tokio::io::AsyncWriteExt; +use tokio::net::TcpListener; +use tokio::time; + +async fn fake_data_server(addr: SocketAddr) { + let listener = TcpListener::bind(addr).await.unwrap(); + + let (mut socket, _) = listener.accept().await.unwrap(); + + let start = Instant::now(); + let pattern = iter::from_fn(move || { + let x = start.elapsed().as_secs() % 180; + let y = x as f32 * 0.5; + Some(y) + }); + let mut readings = pattern.map(|y| { + protocol::Reading::LargeBedroom(protocol::large_bedroom::Reading::Bed( + protocol::large_bedroom::bed::Reading::Temperature(y), + )) + }); + + loop { + time::sleep(Duration::from_secs(1)).await; + let new = readings.next().unwrap(); + let mut msg = SensorMessage::<5>::new(); + msg.values.push(new); + let bytes = msg.encode(); + socket.write_all(&bytes).await.unwrap(); + } +} + +async fn test(data_store_addr: SocketAddr) { + let mut client = data_store::Client::connect(data_store_addr).await.unwrap(); + let list = client.list_data().await.unwrap(); + + assert!(list.iter().any(|r| { + if let protocol::Reading::LargeBedroom(protocol::large_bedroom::Reading::Bed( + protocol::large_bedroom::bed::Reading::Temperature(_), + )) = r + { + true + } else { + false + } + })) +} + +#[tokio::test] +async fn main() { + let data_server_addr = SocketAddr::from(([127, 0, 0, 1], 3384)); + let data_store_addr = SocketAddr::from(([127, 0, 0, 1], 1294)); + + let run_data_server = fake_data_server(data_server_addr); + let run_data_store = data_store::run(data_server_addr, data_store_addr.port()); + let run_test = test(data_store_addr); + + use futures_concurrency::*; + let res = (run_test, run_data_store, run_data_server).race().await; +} From 498cb9f216bdc3b5d16787206f87ef1a27e9337a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 6 Jul 2024 15:58:44 +0200 Subject: [PATCH 139/687] add integration tests to data-server --- crates/data-server/Cargo.toml | 3 + crates/data-server/src/lib.rs | 125 +---------------------- crates/data-server/src/main.rs | 151 ++-------------------------- crates/data-server/src/server.rs | 139 +++++++++++++++++++++++++ crates/data-server/src/subscribe.rs | 126 +++++++++++++++++++++++ crates/data-server/tests/api.rs | 70 +++++++++++++ 6 files changed, 350 insertions(+), 264 deletions(-) create mode 100644 crates/data-server/src/server.rs create mode 100644 crates/data-server/src/subscribe.rs create mode 100644 crates/data-server/tests/api.rs diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index dbcfe41a..640a44ea 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -15,3 +15,6 @@ protocol = { path = "/home/david/Documents/HomeAutomation/crates/protocol", feat tokio = { version = "1.37.0", features = ["rt", "macros", "net", "sync", "io-util"] } tokio-stream = { version = "0.1.15", features = ["net"] } thiserror = "1.0.61" + +[dev-dependencies] +reserve-port = "2" diff --git a/crates/data-server/src/lib.rs b/crates/data-server/src/lib.rs index 0151b394..9ce56761 100644 --- a/crates/data-server/src/lib.rs +++ b/crates/data-server/src/lib.rs @@ -1,123 +1,4 @@ -use std::io::{BufRead, BufReader}; -use std::net::{TcpStream, ToSocketAddrs}; -use std::vec; +pub mod subscribe; +pub use subscribe::{Subscriber, AsyncSubscriber}; -use protocol::{DecodeError, Msg}; -use tokio::io::AsyncBufReadExt; -use tracing::trace; - -pub enum SubMessage { - Reading(protocol::Reading), - ErrorReport(protocol::Error), -} - -pub struct Subscriber { - reader: BufReader, - buf: Vec, - values: vec::IntoIter, -} - -impl Subscriber { - pub fn connect(addr: impl ToSocketAddrs) -> Result { - let conn = TcpStream::connect(addr).map_err(SubscribeError::ConnFailed)?; - let reader = BufReader::new(conn); - let buf = Vec::new(); - - Ok(Self { - reader, - buf, - values: vec![].into_iter(), - }) - } - - pub fn next(&mut self) -> Result { - if let Some(val) = self.values.next() { - return Ok(val); - } - - self.buf.clear(); - let n_read = self - .reader - .read_until(0, &mut self.buf) - .map_err(SubscribeError::ConnFailed)?; - decode_buffer_and_return_first(n_read, &mut self.buf, &mut self.values) - } -} - -pub struct AsyncSubscriber { - reader: tokio::io::BufReader, - buf: Vec, - values: vec::IntoIter, -} - -impl AsyncSubscriber { - pub async fn connect(addr: impl tokio::net::ToSocketAddrs) -> Result { - let conn = tokio::net::TcpStream::connect(addr) - .await - .map_err(SubscribeError::ConnFailed)?; - let reader = tokio::io::BufReader::new(conn); - let buf = Vec::new(); - - Ok(Self { - reader, - buf, - values: vec![].into_iter(), - }) - } - - pub async fn next(&mut self) -> Result { - if let Some(val) = self.values.next() { - return Ok(val); - } - - let n_read = self - .reader - .read_until(0, &mut self.buf) - .await - .map_err(SubscribeError::ConnFailed)?; - decode_buffer_and_return_first(n_read, &mut self.buf, &mut self.values) - } -} - -fn decode_buffer_and_return_first( - n_read: usize, - buf: &mut Vec, - buffer: &mut vec::IntoIter, -) -> Result { - assert!(buffer.next().is_none()); - - if n_read == 0 { - return Err(SubscribeError::ConnEnded)?; - } - - buf.resize(n_read, 0); // ensure stop delimiter in bytes - let bytes = &mut buf[0..n_read]; - trace!("{:?}", &bytes); - let decoded: Msg<50> = Msg::decode(bytes).map_err(SubscribeError::DecodeFailed)?; - match decoded { - Msg::Readings(readings) => { - *buffer = readings - .values - .iter() - .map(Clone::clone) - .map(|v| SubMessage::Reading(v)) - .collect::>() - .into_iter(); - } - Msg::ErrorReport(report) => { - *buffer = vec![SubMessage::ErrorReport(report.error)].into_iter() - } - } - - Ok(buffer.next().expect("min values in sensormessage is one")) -} - -#[derive(Debug, thiserror::Error)] -pub enum SubscribeError { - #[error("The connection to the subscribe server failed, error: {0}")] - ConnFailed(std::io::Error), - #[error("Could not decode message, is protocol lib up to date on server and client? Decoderror: {0:?}")] - DecodeFailed(DecodeError), - #[error("Connection ended")] - ConnEnded, -} +pub mod server; diff --git a/crates/data-server/src/main.rs b/crates/data-server/src/main.rs index 837537f8..fe8f8519 100644 --- a/crates/data-server/src/main.rs +++ b/crates/data-server/src/main.rs @@ -1,16 +1,11 @@ -use color_eyre::eyre::Context; -use std::mem; -use std::net::SocketAddr; -use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufStream}; -use tokio::net::{TcpListener, TcpStream}; -use tokio::sync::mpsc::{self, Sender}; - -use color_eyre::{Result, Section}; -use protocol::{Reading, SensorMessage}; +use tokio::sync::mpsc; +use tokio::select; +use color_eyre::Result; +use tracing::info; use clap::Parser; -use tokio::select; -use tracing::{info, warn}; + +use data_server::server; #[derive(Parser)] #[command(name = "data server")] @@ -26,134 +21,6 @@ struct Cli { update_port: u16, } -async fn handle_client(stream: TcpStream, tx: Sender) { - let mut reader = BufStream::new(stream); - let mut buf = Vec::new(); - loop { - buf.clear(); - let n_read = match reader.read_until(0, &mut buf).await { - Err(e) => { - warn!("Connection failed/closed: {e}"); - return; - } - Ok(bytes) => bytes, - }; - - let bytes = &mut buf[0..n_read]; - if bytes.is_empty() { //eof - warn!("end of stream"); - return; - } - - tracing::trace!("{:?}", &bytes); - let decoded = match protocol::Msg::<50>::decode(bytes) { - Ok(msg) => msg, - Err(e) => { - warn!("decode failed: {e:?}"); - return; - } - }; - match decoded { - protocol::Msg::Readings(readings) => { - for value in readings.values { - tx.send(Event::NewReading(Ok(value))).await.unwrap(); - } - } - protocol::Msg::ErrorReport(report) => { - tx.send(Event::NewReading(Err(report.error))).await.unwrap() - } - } - } -} - -enum Event { - NewSub(TcpStream), - NewReading(Result), -} - -async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { - let mut subscribers = Vec::new(); - - while let Some(event) = events.recv().await { - let msg = match event { - Event::NewSub(sub) => { - subscribers.push(sub); - continue; - } - Event::NewReading(Ok(reading)) => { - // TODO use futures-util's peekable with next_if - // to get up to 49 extra messages for efficiency - let mut readings: SensorMessage<50> = SensorMessage::new(); - readings - .values - .push(reading) - .expect("capacity should be > 0"); - protocol::Msg::Readings(readings) - } - Event::NewReading(Err(err)) => { - let report = protocol::ErrorReport::new(err); - protocol::Msg::ErrorReport(report) - } - }; - - let bytes = msg.encode(); - let subs = mem::take(&mut subscribers); - for mut sub in subs.into_iter() { - if let Err(e) = sub.write_all(&bytes).await { - warn!("Error writing to subscriber: {e}"); - } else { - subscribers.push(sub); - } - } - } - - Ok(()) -} - -async fn handle_data_sources(port: u16, share: &mpsc::Sender) -> Result<()> { - let addr = SocketAddr::from(([0, 0, 0, 0], port)); - let listener = TcpListener::bind(addr) - .await - .wrap_err("Could not start listening for new subscribers") - .with_note(|| format!("trying to listen on port: {port}"))?; - - loop { - let res = listener.accept().await; - match res { - Ok((stream, source)) => { - info!("new data source connected from: {source}"); - tokio::spawn(handle_client(stream, share.clone())); - } - Err(e) => { - println!("new connection failed: {e}"); - continue; - } - }; - } -} - -async fn register_subs(port: u16, tx: &mpsc::Sender) -> Result<()> { - let addr = SocketAddr::from(([0, 0, 0, 0], port)); - let listener = TcpListener::bind(addr) - .await - .wrap_err("Could not start receiving updates") - .with_note(|| format!("trying to listen on port: {port}"))?; - - loop { - let res = listener.accept().await; - match res { - Ok((stream, source)) => { - info!("new subscriber connected from: {source}"); - tx.send(Event::NewSub(stream)).await.unwrap(); - } - Err(e) => { - warn!("new connection failed: {e}"); - continue; - } - }; - } -} - #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { setup_tracing().unwrap(); @@ -169,9 +36,9 @@ async fn main() -> Result<()> { let (tx, rx) = mpsc::channel(2000); select! { - e = register_subs(subscribe_port, &tx) => e, - e = handle_data_sources(update_port, &tx) => e, - e = spread_updates(rx) => e, + e = server::register_subs(subscribe_port, &tx) => e, + e = server::handle_data_sources(update_port, &tx) => e, + e = server::spread_updates(rx) => e, } } diff --git a/crates/data-server/src/server.rs b/crates/data-server/src/server.rs new file mode 100644 index 00000000..d5c0e51d --- /dev/null +++ b/crates/data-server/src/server.rs @@ -0,0 +1,139 @@ +use color_eyre::eyre::Context; +use std::mem; +use std::net::SocketAddr; +use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufStream}; +use tokio::net::{TcpListener, TcpStream}; +use tokio::sync::mpsc::{self, Sender}; + +use color_eyre::{Result, Section}; +use protocol::{Reading, SensorMessage}; + +use tracing::{info, warn}; + +pub async fn handle_client(stream: TcpStream, tx: Sender) { + let mut reader = BufStream::new(stream); + let mut buf = Vec::new(); + loop { + buf.clear(); + let n_read = match reader.read_until(0, &mut buf).await { + Err(e) => { + warn!("Connection failed/closed: {e}"); + return; + } + Ok(bytes) => bytes, + }; + + let bytes = &mut buf[0..n_read]; + if bytes.is_empty() { //eof + warn!("end of stream"); + return; + } + + tracing::trace!("{:?}", &bytes); + let decoded = match protocol::Msg::<50>::decode(bytes) { + Ok(msg) => msg, + Err(e) => { + warn!("decode failed: {e:?}"); + return; + } + }; + match decoded { + protocol::Msg::Readings(readings) => { + for value in readings.values { + tx.send(Event::NewReading(Ok(value))).await.unwrap(); + } + } + protocol::Msg::ErrorReport(report) => { + tx.send(Event::NewReading(Err(report.error))).await.unwrap() + } + } + } +} + +pub enum Event { + NewSub(TcpStream), + NewReading(Result), +} + +pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { + let mut subscribers = Vec::new(); + + while let Some(event) = events.recv().await { + let msg = match event { + Event::NewSub(sub) => { + subscribers.push(sub); + continue; + } + Event::NewReading(Ok(reading)) => { + // TODO use futures-util's peekable with next_if + // to get up to 49 extra messages for efficiency + let mut readings: SensorMessage<50> = SensorMessage::new(); + readings + .values + .push(reading) + .expect("capacity should be > 0"); + protocol::Msg::Readings(readings) + } + Event::NewReading(Err(err)) => { + let report = protocol::ErrorReport::new(err); + protocol::Msg::ErrorReport(report) + } + }; + + let bytes = msg.encode(); + let subs = mem::take(&mut subscribers); + for mut sub in subs.into_iter() { + if let Err(e) = sub.write_all(&bytes).await { + warn!("Error writing to subscriber: {e}"); + } else { + subscribers.push(sub); + } + } + } + + Ok(()) +} + +pub async fn handle_data_sources(port: u16, share: &mpsc::Sender) -> Result<()> { + let addr = SocketAddr::from(([0, 0, 0, 0], port)); + let listener = TcpListener::bind(addr) + .await + .wrap_err("Could not start listening for new subscribers") + .with_note(|| format!("trying to listen on port: {port}"))?; + + loop { + let res = listener.accept().await; + match res { + Ok((stream, source)) => { + info!("new data source connected from: {source}"); + tokio::spawn(handle_client(stream, share.clone())); + } + Err(e) => { + println!("new connection failed: {e}"); + continue; + } + }; + } +} + +pub async fn register_subs(port: u16, tx: &mpsc::Sender) -> Result<()> { + let addr = SocketAddr::from(([0, 0, 0, 0], port)); + let listener = TcpListener::bind(addr) + .await + .wrap_err("Could not start receiving updates") + .with_note(|| format!("trying to listen on port: {port}"))?; + + loop { + let res = listener.accept().await; + match res { + Ok((stream, source)) => { + info!("new subscriber connected from: {source}"); + tx.send(Event::NewSub(stream)).await.unwrap(); + } + Err(e) => { + warn!("new connection failed: {e}"); + continue; + } + }; + } +} diff --git a/crates/data-server/src/subscribe.rs b/crates/data-server/src/subscribe.rs new file mode 100644 index 00000000..611a69ad --- /dev/null +++ b/crates/data-server/src/subscribe.rs @@ -0,0 +1,126 @@ +use std::io::{BufRead, BufReader}; +use std::net::{TcpStream, ToSocketAddrs}; +use std::vec; + +use protocol::{DecodeError, Msg}; +use tokio::io::AsyncBufReadExt; +use tracing::trace; + +#[derive(Debug)] +pub enum SubMessage { + Reading(protocol::Reading), + ErrorReport(protocol::Error), +} + +pub struct Subscriber { + reader: BufReader, + buf: Vec, + values: vec::IntoIter, +} + +impl Subscriber { + pub fn connect(addr: impl ToSocketAddrs) -> Result { + let conn = TcpStream::connect(addr).map_err(SubscribeError::ConnFailed)?; + let reader = BufReader::new(conn); + let buf = Vec::new(); + + Ok(Self { + reader, + buf, + values: vec![].into_iter(), + }) + } + + pub fn next(&mut self) -> Result { + if let Some(val) = self.values.next() { + return Ok(val); + } + + self.buf.clear(); + let n_read = self + .reader + .read_until(0, &mut self.buf) + .map_err(SubscribeError::ConnFailed)?; + decode_buffer_and_return_first(n_read, &mut self.buf, &mut self.values) + } +} + +pub struct AsyncSubscriber { + reader: tokio::io::BufReader, + buf: Vec, + values: vec::IntoIter, +} + +impl AsyncSubscriber { + pub async fn connect(addr: impl tokio::net::ToSocketAddrs) -> Result { + let conn = tokio::net::TcpStream::connect(addr) + .await + .map_err(SubscribeError::ConnFailed)?; + let reader = tokio::io::BufReader::new(conn); + let buf = Vec::new(); + + Ok(Self { + reader, + buf, + values: vec![].into_iter(), + }) + } + + pub async fn next(&mut self) -> Result { + if let Some(val) = self.values.next() { + return Ok(val); + } + + let n_read = self + .reader + .read_until(0, &mut self.buf) + .await + .map_err(SubscribeError::ConnFailed)?; + dbg!(n_read); + dbg!(&self.buf[..n_read]); + decode_buffer_and_return_first(n_read, &mut self.buf, &mut self.values) + } +} + +fn decode_buffer_and_return_first( + n_read: usize, + buf: &mut Vec, + buffer: &mut vec::IntoIter, +) -> Result { + assert!(buffer.next().is_none()); + + if n_read == 0 { + return Err(SubscribeError::ConnEnded)?; + } + + buf.resize(n_read, 0); // ensure stop delimiter in bytes + let bytes = &mut buf[0..n_read]; + trace!("{:?}", &bytes); + let decoded: Msg<50> = Msg::decode(bytes).map_err(SubscribeError::DecodeFailed)?; + match decoded { + Msg::Readings(readings) => { + *buffer = readings + .values + .iter() + .map(Clone::clone) + .map(|v| SubMessage::Reading(v)) + .collect::>() + .into_iter(); + } + Msg::ErrorReport(report) => { + *buffer = vec![SubMessage::ErrorReport(report.error)].into_iter() + } + } + + Ok(buffer.next().expect("min values in sensormessage is one")) +} + +#[derive(Debug, thiserror::Error)] +pub enum SubscribeError { + #[error("The connection to the subscribe server failed, error: {0}")] + ConnFailed(std::io::Error), + #[error("Could not decode message, is protocol lib up to date on server and client? Decoderror: {0:?}")] + DecodeFailed(DecodeError), + #[error("Connection ended")] + ConnEnded, +} diff --git a/crates/data-server/tests/api.rs b/crates/data-server/tests/api.rs new file mode 100644 index 00000000..efef1564 --- /dev/null +++ b/crates/data-server/tests/api.rs @@ -0,0 +1,70 @@ +use std::time::Duration; + +use color_eyre::Result; +use data_server::server; +use data_server::subscribe::SubMessage; +use protocol::large_bedroom; +use protocol::large_bedroom::bed; +use protocol::Reading; +use tokio::io::AsyncWriteExt; +use tokio::net::TcpStream; +use tokio::select; +use tokio::sync::mpsc; +use tokio::time::sleep; + +#[derive(Debug, PartialEq)] +enum Done { + RunServer, + SendValue, + Test, +} + +async fn run_server(sub_port: u16, data_port: u16) -> Result { + let (tx, rx) = mpsc::channel(2000); + select! { + e = server::register_subs(sub_port, &tx) => e?, + e = server::handle_data_sources(data_port, &tx) => e?, + e = server::spread_updates(rx) => e?, + }; + + Ok(Done::RunServer) +} + +const TEST_READING: Reading = + Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::Temperature(0.0))); + +async fn send_sensor_value(data_port: u16) -> Result { + tokio::time::sleep(Duration::from_millis(100)).await; + let mut sensor_msg = protocol::SensorMessage::<50>::new(); + sensor_msg.values.push(TEST_READING).unwrap(); + let encoded = protocol::Msg::Readings(sensor_msg).encode(); + + let mut conn = TcpStream::connect(("127.0.0.1", data_port)).await.unwrap(); + conn.write_all(&encoded).await.unwrap(); + sleep(Duration::from_secs(999)).await; + Ok(Done::SendValue) +} + +async fn subscribe_and_receive(sub_port: u16) -> Result { + tokio::time::sleep(Duration::from_millis(100)).await; + let mut sub = data_server::AsyncSubscriber::connect(("127.0.0.1", sub_port)) + .await + .unwrap(); + let received = sub.next().await.unwrap(); + dbg!(&received); + assert!(matches!(received, SubMessage::Reading(TEST_READING))); + + Ok(Done::Test) +} + +#[tokio::test] +async fn main() { + let sub_port = reserve_port::ReservedPort::random().unwrap(); + let data_port = reserve_port::ReservedPort::random().unwrap(); + let res = select! { + e = run_server(sub_port.port(), data_port.port()) => e, + e = send_sensor_value(data_port.port()) => e, + e = subscribe_and_receive(sub_port.port()) => e, + }; + assert_eq!(res.unwrap(), Done::Test); +} From 1c872c4f6aff1c3b1fb9a8702b9b712e2f8ffc9b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 7 Jul 2024 23:05:44 +0200 Subject: [PATCH 140/687] vendors in bitspec, bugfixes to list data and get data --- Cargo.lock | 33 +-- crates/data-server/Cargo.toml | 5 + crates/data-server/src/lib.rs | 7 +- crates/data-server/src/server.rs | 1 - .../src/{subscribe.rs => subscriber.rs} | 13 +- crates/data-server/tests/api.rs | 2 +- crates/data-store/Cargo.toml | 14 +- crates/data-store/src/api.rs | 13 +- crates/data-store/src/api/client.rs | 4 +- crates/data-store/src/lib.rs | 3 +- crates/data-store/src/server.rs | 2 +- crates/data-store/src/server/clients.rs | 5 +- crates/data-store/src/server/db.rs | 33 ++- crates/data-store/src/server/db/series.rs | 92 ++++++-- .../src/server/db/series/bitspec.rs | 6 + .../server/db/series/bitspec/compression.rs | 195 ++++++++++++++++ .../src/server/db/series/bitspec/field.rs | 168 +++++++++++++ .../src/server/db/series/bitspec/spec.rs | 53 +++++ .../src/server/db/series/resampler.rs | 2 +- crates/data-store/tests/list_data.rs | 220 ++++++++++++++---- 20 files changed, 753 insertions(+), 118 deletions(-) rename crates/data-server/src/{subscribe.rs => subscriber.rs} (91%) create mode 100644 crates/data-store/src/server/db/series/bitspec.rs create mode 100644 crates/data-store/src/server/db/series/bitspec/compression.rs create mode 100644 crates/data-store/src/server/db/series/bitspec/field.rs create mode 100644 crates/data-store/src/server/db/series/bitspec/spec.rs diff --git a/Cargo.lock b/Cargo.lock index 3cc24712..21380383 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -469,17 +469,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bitspec" -version = "0.1.0" -dependencies = [ - "log", - "num", - "rand", - "serde", - "serde_derive", -] - [[package]] name = "bitvec" version = "1.0.1" @@ -576,7 +565,6 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "byteseries" version = "0.4.0" -source = "git+https://github.com/dvdsk/byteseries#75e1bd67ab2f0c8bbca5cb84930f5cf885b41e27" dependencies = [ "arraydeque", "itertools 0.13.0", @@ -843,6 +831,7 @@ dependencies = [ "clap", "color-eyre", "protocol", + "reserve-port", "thiserror", "tokio", "tokio-stream", @@ -855,16 +844,18 @@ dependencies = [ name = "data-store" version = "0.1.0" dependencies = [ - "bitspec", "byteseries", "clap", "color-eyre", "data-server", "futures", "futures-concurrency", + "num", "protocol", + "reserve-port", "serde", "smallvec 2.0.0-alpha.6", + "temp-dir", "thiserror", "time", "tokio", @@ -2484,6 +2475,16 @@ dependencies = [ "winreg", ] +[[package]] +name = "reserve-port" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9838134a2bfaa8e1f40738fcc972ac799de6e0e06b5157acb95fc2b05a0ea283" +dependencies = [ + "lazy_static", + "thiserror", +] + [[package]] name = "ron" version = "0.8.1" @@ -2879,6 +2880,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "temp-dir" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f227968ec00f0e5322f9b8173c7a0cbcff6181a0a5b28e9892491c286277231" + [[package]] name = "thiserror" version = "1.0.61" diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index 640a44ea..fb2cbbf9 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -4,6 +4,11 @@ edition.workspace = true license.workspace = true authors.workspace = true +[features] +api = [] +server = [] +default = ["api", "server"] + [dependencies] clap = { version = "4", features = ["derive"] } color-eyre = "0.6.3" diff --git a/crates/data-server/src/lib.rs b/crates/data-server/src/lib.rs index 9ce56761..5011852f 100644 --- a/crates/data-server/src/lib.rs +++ b/crates/data-server/src/lib.rs @@ -1,4 +1,7 @@ -pub mod subscribe; -pub use subscribe::{Subscriber, AsyncSubscriber}; +#[cfg(feature = "api")] +pub mod subscriber; +#[cfg(feature = "api")] +pub use subscriber::{Subscriber, AsyncSubscriber, SubMessage}; +#[cfg(feature = "server")] pub mod server; diff --git a/crates/data-server/src/server.rs b/crates/data-server/src/server.rs index d5c0e51d..db689274 100644 --- a/crates/data-server/src/server.rs +++ b/crates/data-server/src/server.rs @@ -29,7 +29,6 @@ pub async fn handle_client(stream: TcpStream, tx: Sender) { return; } - tracing::trace!("{:?}", &bytes); let decoded = match protocol::Msg::<50>::decode(bytes) { Ok(msg) => msg, Err(e) => { diff --git a/crates/data-server/src/subscribe.rs b/crates/data-server/src/subscriber.rs similarity index 91% rename from crates/data-server/src/subscribe.rs rename to crates/data-server/src/subscriber.rs index 611a69ad..dffee557 100644 --- a/crates/data-server/src/subscribe.rs +++ b/crates/data-server/src/subscriber.rs @@ -4,7 +4,7 @@ use std::vec; use protocol::{DecodeError, Msg}; use tokio::io::AsyncBufReadExt; -use tracing::trace; +use tracing::{instrument, trace}; #[derive(Debug)] pub enum SubMessage { @@ -71,17 +71,17 @@ impl AsyncSubscriber { return Ok(val); } + self.buf.clear(); let n_read = self .reader .read_until(0, &mut self.buf) .await .map_err(SubscribeError::ConnFailed)?; - dbg!(n_read); - dbg!(&self.buf[..n_read]); decode_buffer_and_return_first(n_read, &mut self.buf, &mut self.values) } } +#[instrument(level="trace")] fn decode_buffer_and_return_first( n_read: usize, buf: &mut Vec, @@ -95,7 +95,7 @@ fn decode_buffer_and_return_first( buf.resize(n_read, 0); // ensure stop delimiter in bytes let bytes = &mut buf[0..n_read]; - trace!("{:?}", &bytes); + trace!("New message from data-server to decode, bytes: {bytes:?}"); let decoded: Msg<50> = Msg::decode(bytes).map_err(SubscribeError::DecodeFailed)?; match decoded { Msg::Readings(readings) => { @@ -119,7 +119,10 @@ fn decode_buffer_and_return_first( pub enum SubscribeError { #[error("The connection to the subscribe server failed, error: {0}")] ConnFailed(std::io::Error), - #[error("Could not decode message, is protocol lib up to date on server and client? Decoderror: {0:?}")] + #[error( + "Could not decode message, is protocol lib up to date on server \ + and client? Or has the server crashed? Decoderror: {0:?}" + )] DecodeFailed(DecodeError), #[error("Connection ended")] ConnEnded, diff --git a/crates/data-server/tests/api.rs b/crates/data-server/tests/api.rs index efef1564..9c2e8db5 100644 --- a/crates/data-server/tests/api.rs +++ b/crates/data-server/tests/api.rs @@ -2,7 +2,7 @@ use std::time::Duration; use color_eyre::Result; use data_server::server; -use data_server::subscribe::SubMessage; +use data_server::subscriber::SubMessage; use protocol::large_bedroom; use protocol::large_bedroom::bed; use protocol::Reading; diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index c03a14d5..884fedca 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -6,6 +6,11 @@ edition.workspace = true license.workspace = true authors.workspace = true +[features] +api = [] +server = [] +default = ["api", "server"] + [dependencies] clap = { version = "4", features = ["derive"] } color-eyre = "0.6.3" @@ -17,10 +22,8 @@ time = { version = "0.3", features = ["serde"] } protocol = { path = "../protocol", features = ["alloc"] } data-server = { path = "../data-server" } -# bitspec = { git = "https://github.com/dvdsk/bitspec" } -bitspec = { path = "/home/david/Documents/bitspec" } -byteseries = { git = "https://github.com/dvdsk/byteseries", features = ["smallvec"] } -# byteseries = { path = "/home/david/Documents/byteseries" } +# byteseries = { git = "https://github.com/dvdsk/byteseries", features = ["smallvec"] } +byteseries = { path = "/home/david/Documents/byteseries" } tokio = { version = "1.38.0", features = ["fs", "net", "rt-multi-thread", "sync"] } futures-concurrency = "7.6.1" tokio-serde = { version = "0.9.0", features = ["bincode"] } @@ -29,6 +32,9 @@ serde = { version = "1.0.203", features = ["derive"] } thiserror = "1.0.61" futures = "0.3.30" smallvec = "2.0.0-alpha.6" +num = "0.4.3" [dev-dependencies] futures-concurrency = "7.6.1" +reserve-port = "2.0.1" +temp-dir = "0.1.13" diff --git a/crates/data-store/src/api.rs b/crates/data-store/src/api.rs index 16200e38..234ba817 100644 --- a/crates/data-store/src/api.rs +++ b/crates/data-store/src/api.rs @@ -1,13 +1,13 @@ use protocol::Reading; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use time::OffsetDateTime; mod client; pub use client::Client; // 8 MB -pub(crate) const MAX_PACKAGE_SIZE: usize = 8*1024*1024; +pub(crate) const MAX_PACKAGE_SIZE: usize = 8 * 1024 * 1024; #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) enum Request { @@ -17,18 +17,23 @@ pub(crate) enum Request { start: OffsetDateTime, end: OffsetDateTime, n: usize, - } + }, } #[derive(Debug, Clone, Serialize, Deserialize, thiserror::Error)] pub enum ServerError { #[error("We do not have any data for this reading: {reading:?}")] NotInStore { reading: Reading }, + #[error("Internal error while reading data, error: {0}")] + ReadingFromStore(String), } #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) enum Response { ListData(Vec), - GetData(Vec<(OffsetDateTime, f32)>), + GetData { + time: Vec, + data: Vec, + }, Error(ServerError), } diff --git a/crates/data-store/src/api/client.rs b/crates/data-store/src/api/client.rs index fcd42e0a..a1b5d2ba 100644 --- a/crates/data-store/src/api/client.rs +++ b/crates/data-store/src/api/client.rs @@ -74,7 +74,7 @@ impl Client { end: OffsetDateTime, reading: protocol::Reading, n: usize, - ) -> Result, Error> { + ) -> Result<(Vec, Vec), Error> { let request = super::Request::GetData { reading, start, @@ -82,7 +82,7 @@ impl Client { n, }; match self.send_receive(request.clone()).await? { - super::Response::GetData(data) => return Ok(data), + super::Response::GetData { time, data } => return Ok((time, data)), response => Err(Error::IncorrectResponse { request: format!("{request:?}"), response: format!("{response:?}"), diff --git a/crates/data-store/src/lib.rs b/crates/data-store/src/lib.rs index 247f3b05..441c7dc7 100644 --- a/crates/data-store/src/lib.rs +++ b/crates/data-store/src/lib.rs @@ -1,3 +1,4 @@ +#[cfg(feature = "api")] pub mod api; - +#[cfg(feature = "server")] pub mod server; diff --git a/crates/data-store/src/server.rs b/crates/data-store/src/server.rs index e562be5d..e7b4faaf 100644 --- a/crates/data-store/src/server.rs +++ b/crates/data-store/src/server.rs @@ -8,7 +8,7 @@ use tokio::sync::Mutex; mod clients; mod db; -// used from tests +// used from main and tests pub async fn run(data_server: SocketAddr, client_port: u16) -> Result<()> { let data = db::Data(Arc::new(Mutex::new(HashMap::new()))); let error = ( diff --git a/crates/data-store/src/server/clients.rs b/crates/data-store/src/server/clients.rs index 1344c4fc..e6ab4049 100644 --- a/crates/data-store/src/server/clients.rs +++ b/crates/data-store/src/server/clients.rs @@ -72,6 +72,9 @@ async fn perform_request(request: api::Request, data: &Data) -> Result api::Response::GetData(data.get(reading, start, end, n).await?), + } => { + let (time, data) = data.get(reading, start, end, n).await?; + api::Response::GetData { time, data } + } }) } diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index 6ad7a606..09a05491 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -18,21 +18,24 @@ use crate::api; pub(crate) async fn run(data_server_addr: SocketAddr, data: Data) -> Result<()> { let mut sub = AsyncSubscriber::connect(data_server_addr) .await - .wrap_err("failed to connect") - .with_suggestion(|| format!("verify the server is listening on: {data_server_addr}"))?; + .wrap_err("data-store server failed to subscribe with data-server") + .with_suggestion(|| { + format!("verify data data-server is listening on: {data_server_addr}") + })?; + tracing::info!("connected to data-server at: {data_server_addr:?}"); loop { let res = match sub .next() .await - .wrap_err("Error getting next reading from server")? + .wrap_err("Error getting next message from data-server")? { SubMessage::Reading(reading) => series::store(&data, &reading).await, SubMessage::ErrorReport(_) => continue, }; if let Err(e) = res { - tracing::error!("Error processing new reading: {e}"); + tracing::error!("Error processing new reading: {e:?}"); } } } @@ -56,15 +59,21 @@ impl Data { start: OffsetDateTime, end: OffsetDateTime, n: usize, - ) -> Result, api::ServerError> { + ) -> Result<(Vec, Vec), api::ServerError> { let key = reading.device(); - let series = self.0 - .lock() - .await + let mut all_series = self.0.lock().await; + let series = all_series .get_mut(&key) - .ok_or(api::ServerError::NotInStore { reading })?; - - // series. - + .ok_or_else(|| api::ServerError::NotInStore { + reading: reading.clone(), + })?; + + let (time, mut data) = series + .read(&[reading], start, end, n) + .map_err(|e| api::ServerError::ReadingFromStore(e.to_string()))?; + Ok(( + time, + data.pop().expect("one reading is put in so one comes out"), + )) } } diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index a0a56c92..fb5e034c 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -1,3 +1,4 @@ +use std::fs::create_dir_all; use std::io; use std::path::PathBuf; use std::time::Instant; @@ -8,20 +9,30 @@ use color_eyre::{Result, Section}; use protocol::reading_tree::{Item, ReadingInfo, Tree}; use serde::{Deserialize, Serialize}; use time::OffsetDateTime; -use tracing::info; +use tracing::{info, instrument}; + +use byteseries::file::OpenError as FileOpenError; +use series::data::OpenError as DataOpenError; +use series::Error::Open; mod resampler; -use crate::api; +mod bitspec; use self::resampler::Resampler; use super::Data; +#[derive(Debug)] +struct Meta { + reading: protocol::Reading, + field: bitspec::MetaField, + set_at: Instant, +} + #[derive(Debug)] pub(crate) struct Series { line: Vec, - field_set_at: Vec, - fields: Vec>, + meta: Vec, byteseries: ByteSeries, } @@ -36,13 +47,22 @@ impl Series { let path = base_path(reading); let readings = reading.device().affected_readings(); let specs = to_speclist(readings); - let fields = bitspec::speclist_to_fields(specs); + let meta = readings + .iter() + .zip(fields.iter()) + .map(|(reading, field)| Meta { + reading: reading.clone(), + field: field.clone(), + set_at: Instant::now(), + }) + .collect(); + let payload_size = fields .iter() .map(|spec| spec.length as usize) .sum::() - / 8; + .div_ceil(8); let resampler = Resampler::from_fields(fields.clone(), payload_size); let resample_configs = vec![downsample::Config { max_gap: None, @@ -55,10 +75,6 @@ impl Series { resample_configs.clone(), ); - use byteseries::file::OpenError as FileOpenError; - use series::data::OpenError as DataOpenError; - use series::Error::Open; - let expected_header = Header { readings: readings.to_vec(), encoding: fields.clone(), @@ -87,24 +103,30 @@ impl Series { Err(Open(DataOpenError::File(FileOpenError::Io(e)))) if e.kind() == io::ErrorKind::NotFound => { + if let Some(dirs) = path.parent() { + create_dir_all(dirs) + .wrap_err("Could not create dirs structure for reading") + .with_note(|| format!("dirs: {}", dirs.display()))? + } + // compile_error!("create directory structure"); info!("creating new byteseries"); ByteSeries::new_with_resamplers( - path, + &path, payload_size, expected_header, resampler, resample_configs, ) - .wrap_err("Could not create new byteseries")? + .wrap_err("Could not create new byteseries") + .with_note(|| format!("path: {}", path.display()))? } Err(e) => return Err(e).wrap_err("Could not open existing byteseries")?, }; Ok(Self { line: vec![0; payload_size], - field_set_at: Vec::new(), + meta, byteseries, - fields, }) } @@ -117,16 +139,19 @@ impl Series { .position(|local_id| local_id == reading.id()) .expect("series are grouped by devices, elements come from affected_readings"); - let field = &self.fields[index]; - field.encode::(reading.leaf().val, &mut self.line); - self.field_set_at[index] = Instant::now(); + { + let meta = &mut self.meta[index]; + meta.field.encode::(reading.leaf().val, &mut self.line); + meta.set_at = Instant::now(); + } if self - .field_set_at + .meta .iter() + .map(|Meta { set_at, .. }| set_at) .all(|set| set.elapsed().as_millis() < 500) { - let time = OffsetDateTime::now_utc() - self.field_set_at[0].elapsed(); + let time = OffsetDateTime::now_utc() - self.meta[index].set_at.elapsed(); self.byteseries .push_line(time.unix_timestamp() as u64, &self.line) .wrap_err("Could not write to timeseries on disk")?; @@ -135,25 +160,42 @@ impl Series { Ok(()) } - fn read( + /// # Panics + /// If any of the requested readings are not part of this series. + pub fn read( &mut self, - reading: &protocol::Reading, + readings: &[protocol::Reading], start: OffsetDateTime, end: OffsetDateTime, n: usize, - ) -> Result<(Vec, Vec>), api::ServerError> { + ) -> Result<(Vec, Vec>), byteseries::series::Error> { let range = start.unix_timestamp() as u64..=end.unix_timestamp() as u64; - let mut resampler = Resampler::from_fields(self.fields.clone(), self.line.len()); + let fields = readings + .iter() + .map(|requested| { + self.meta + .iter() + .find(|meta| *requested == meta.reading) + .map(|meta| meta.field.clone()) + .expect( + "caller of read makes sure all readings are\ + part of this series", + ) + }) + .collect(); + let mut resampler = Resampler::from_fields(fields, self.line.len()); let mut timestamps = Vec::with_capacity(n * 2); let mut interleaved_data = Vec::with_capacity(n * 2); + self.byteseries.read_n( n, range, &mut resampler, &mut timestamps, &mut interleaved_data, - ); + )?; + let time = timestamps .into_iter() .map(|ts| { @@ -176,7 +218,9 @@ impl Series { } } +#[instrument(level = "debug", skip(data))] pub(crate) async fn store(data: &Data, reading: &protocol::Reading) -> Result<()> { + tracing::debug!("storing received reading: {reading:?}"); let mut data = data.0.lock().await; let key = reading.device(); diff --git a/crates/data-store/src/server/db/series/bitspec.rs b/crates/data-store/src/server/db/series/bitspec.rs new file mode 100644 index 00000000..a77a916e --- /dev/null +++ b/crates/data-store/src/server/db/series/bitspec.rs @@ -0,0 +1,6 @@ +mod compression; +mod field; +mod spec; + +pub use field::MetaField; +pub use spec::{LengthWithOps, RangeWithRes, speclist_to_fields}; diff --git a/crates/data-store/src/server/db/series/bitspec/compression.rs b/crates/data-store/src/server/db/series/bitspec/compression.rs new file mode 100644 index 00000000..9fdd84ad --- /dev/null +++ b/crates/data-store/src/server/db/series/bitspec/compression.rs @@ -0,0 +1,195 @@ +#[inline] +pub fn decode(line: &[u8], bit_offset: u8, length: u8) -> u32 { + let start_byte = (bit_offset / 8) as usize; + let stop_byte = ((bit_offset + length) / 8) as usize; + + let start_mask: u8 = !0 >> (bit_offset % 8); + let used_bits = bit_offset + length - stop_byte as u8 * 8; + let stop_mask = !(!0 >> used_bits); + + //decode first bit (never needs shifting (lowest part is used)) + let mut decoded: u32 = (line[start_byte] & start_mask) as u32; + let mut bits_read = 8 - (bit_offset % 8); + //if we have more bits + if length > 8 { + //decode middle bits, no masking needed + for byte in &line[start_byte + 1..stop_byte] { + decoded |= (*byte as u32) << bits_read; + bits_read += 8; + } + } + let stop_byte = ((bit_offset + length).div_ceil(8) - 1) as usize; //starts at 0 + decoded |= ((line[stop_byte] & stop_mask) as u32) << (bits_read - (8 - used_bits)); + + decoded +} + +#[inline] +pub fn encode(to_encode: u32, line: &mut [u8], bit_offset: u8, length: u8) { + let start_mask = !0 >> (bit_offset % 8); + + let start_byte = (bit_offset / 8) as usize; + let stop_byte = ((bit_offset + length) / 8) as usize; + + //encode first bit (never needs shifting (lowest part is used)) + line[start_byte] |= (to_encode as u8) & start_mask; + let mut bits_written = 8 - (bit_offset % 8); + + if length > 8 { + //decode middle bits, no masking needed + for byte in line[start_byte + 1..stop_byte].iter_mut() { + *byte |= (to_encode >> bits_written) as u8; + bits_written += 8; + } + } + + let used_bits = bit_offset + length - stop_byte as u8 * 8; + let stop_mask = !(!0 >> used_bits); + let stop_byte = (bit_offset + length).div_ceil(8) as usize; //starts at 0 + line[stop_byte - 1] |= (to_encode >> (bits_written - (8 - used_bits))) as u8 & stop_mask; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn encode_and_decode_multiple_edge_case() { + let mut line = vec![0, 0, 0, 0, 0, 0, 0, 0]; + encode(1, &mut line, 0, 8); + + print!("binary repr: "); + for byte in &line { + print!("{:b}, ", byte); + } + println!(); + + encode(2, &mut line, 8, 8); + + print!("binary repr: "); + for byte in &line { + print!("{:b}, ", byte); + } + println!(); + + let decoded1 = decode(&line, 0, 8); + let decoded2 = decode(&line, 8, 8); + + println!("0-10 {} {:b}", decoded1, decoded1); + println!("10-20 {} {:b}", decoded2, decoded2); + assert_eq!(decoded1, 1); + assert_eq!(decoded2, 2); + } + + #[test] + fn encode_and_decode_edge_case() { + let test_case = u32::max_value(); + let mut line = vec![0, 0, 0, 0]; + encode(test_case, &mut line, 0, 32); + + print!("binary repr: "); + for byte in &line { + print!("{:b}, ", byte); + } + println!(); + + let decoded1 = decode(&line, 0, 32); + + println!("0-{} {} {:b}", 32, decoded1, decoded1); + assert_eq!(decoded1, test_case); + } + + #[test] + fn encode_and_decode_start_case() { + let test_case = 1023; + let mut line = vec![0, 0, 0, 0]; + encode(test_case, &mut line, 0, 10); + + print!("binary repr: "); + for byte in &line { + print!("{:b}, ", byte); + } + println!(); + + print!("array repr: "); + for byte in &line { + print!("{}, ", byte); + } + println!(); + + let decoded1 = decode(&line, 0, 10); + + println!("0-{} {} {:b}", 10, decoded1, decoded1); + assert_eq!(decoded1, test_case); + } + + #[test] + #[ignore = "takes 10 secs to run"] + fn encode_and_decode_multiple() { + for length in 8..33 { + for offset in 0..16 { + for _power1 in 0..length as u16 * 10 { + for _power2 in 0..length as u16 * 10 { + let power1 = _power1 as f32 * 0.1; + let power2 = _power2 as f32 * 0.1; + let mut array = vec![0; 12]; + let test_numb1 = 2f32.powf(power1) as u32; + let test_numb2 = 2f32.powf(power2) as u32; + encode(test_numb1, array.as_mut_slice(), offset, length); + encode(test_numb2, array.as_mut_slice(), offset + length, length); + + let decoded_test_numb1 = decode(array.as_slice(), offset, length); + let decoded_test_numb2 = decode(array.as_slice(), offset + length, length); + assert_eq!( + test_numb1, decoded_test_numb1, + "\n##### numb:1, \noffset: {},\nlength: {}, \nvalue1: {}, \nvalue2: {}", + offset, length, test_numb1, test_numb2 + ); + assert_eq!( + test_numb2, + decoded_test_numb2, + "\n##### numb:2, \noffset: {},\nlength: {}, \nvalue1: {}, \nvalue2: {}", + offset + length, + length, + test_numb1, + test_numb2 + ); + } + } + } + } + } + + fn print_vec_bin(array: Vec) -> String { + let mut outstr = String::from("binary repr: "); + for byte in &array { + outstr.push_str(&format!("{:b}, ", byte)); + } + outstr.push_str("\n"); + outstr + } + + #[test] + fn encode_and_decode() { + for length in 8..32 { + for offset in 0..16 { + for _power in 0..length as u16 * 10 { + let power = _power as f32 * 0.1; + let mut array = vec![0; 8]; + let test_numb = 2f32.powf(power) as u32; + encode(test_numb, array.as_mut_slice(), offset, length); + + let decoded_test_numb = decode(array.as_slice(), offset, length); + assert_eq!( + test_numb, + decoded_test_numb, + "offset: {}, length: {} {}", + offset, + length, + print_vec_bin(array) + ); + } + } + } + } +} diff --git a/crates/data-store/src/server/db/series/bitspec/field.rs b/crates/data-store/src/server/db/series/bitspec/field.rs new file mode 100644 index 00000000..54949a3c --- /dev/null +++ b/crates/data-store/src/server/db/series/bitspec/field.rs @@ -0,0 +1,168 @@ +use serde::{Deserialize, Serialize}; + +use super::compression; + +// TODO: metafield and field are the same? remove one of em +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +pub struct MetaField { + pub offset: u8, //bits + pub length: u8, //bits (max 32 bit variables) + + pub decode_scale: T, + pub decode_add: T, +} + +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +pub struct Field { + pub offset: u8, //bits + pub length: u8, //bits (max 32 bit variables) + + pub decode_scale: T, + pub decode_add: T, +} + +impl Into> for MetaField { + fn into(self) -> Field { + Field { + offset: self.offset, + length: self.length, + decode_scale: self.decode_scale, + decode_add: self.decode_add, + } + } +} + +impl MetaField +where + T: num::cast::NumCast + + std::fmt::Display + + std::ops::Add + + std::ops::SubAssign + + std::ops::DivAssign + + std::ops::MulAssign + + std::marker::Copy, +{ + pub fn decode(&self, line: &[u8]) -> D + where + D: num::cast::NumCast + + std::fmt::Display + + std::ops::Add + + std::ops::SubAssign + + std::ops::MulAssign + + std::ops::AddAssign, + { + let int_repr: u32 = compression::decode(line, self.offset, self.length); + let mut decoded: D = num::cast(int_repr).unwrap(); + + decoded *= num::cast(self.decode_scale).unwrap(); //FIXME flip decode scale / and * + decoded += num::cast(self.decode_add).unwrap(); + + decoded + } + #[allow(dead_code)] + pub fn encode(&self, mut numb: T, line: &mut [u8]) + where + D: num::cast::NumCast + + std::fmt::Display + + std::ops::Add + + std::ops::SubAssign + + std::ops::AddAssign + + std::ops::DivAssign, + { + numb -= num::cast(self.decode_add).unwrap(); + numb /= num::cast(self.decode_scale).unwrap(); + + let to_encode: u32 = num::cast(numb).unwrap(); + + compression::encode(to_encode, line, self.offset, self.length); + } +} + +#[allow(dead_code)] +impl Field +where + T: num::cast::NumCast + + std::fmt::Display + + std::ops::Add + + std::ops::SubAssign + + std::ops::DivAssign + + std::ops::MulAssign + + std::marker::Copy, +{ + pub fn decode(&self, line: &[u8]) -> D + where + D: num::cast::NumCast + + std::fmt::Display + + std::ops::Add + + std::ops::SubAssign + + std::ops::MulAssign + + std::ops::AddAssign, + { + let int_repr: u32 = compression::decode(line, self.offset, self.length); + let mut decoded: D = num::cast(int_repr).unwrap(); + + decoded *= num::cast(self.decode_scale).unwrap(); //FIXME flip decode scale / and * + decoded += num::cast(self.decode_add).unwrap(); + + decoded + } + pub fn encode(&self, mut numb: T, line: &mut [u8]) + where + T: num::cast::NumCast + + std::fmt::Display + + std::ops::Add + + std::ops::SubAssign + + std::ops::AddAssign + + std::ops::DivAssign, + { + //println!("org: {}",numb); + numb -= num::cast(self.decode_add).unwrap(); + numb /= num::cast(self.decode_scale).unwrap(); + //println!("scale: {}, add: {}, numb: {}", self.decode_scale, self.decode_add, numb); + + let to_encode: u32 = num::cast(numb).unwrap(); + + compression::encode(to_encode, line, self.offset, self.length); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + let fields = &[ + // Ble_reliability_testing_dataset + Field:: { + // Sine + decode_add: -5000.0000000000, + decode_scale: 1.0000000000, + length: 14, + offset: 0, + }, + Field:: { + // Triangle + decode_add: -10.0000000000, + decode_scale: 0.0500000007, + length: 10, + offset: 14, + }, + ]; + + for i in 0..100 { + let sine = -5000.0 + i as f32 * (5000.0 * 2.0) / 100.0; + let triangle = 20.0 - i as f32 * (20.0 + 10.0) / 100.0; + + let mut line = [0u8, 0, 0]; + fields[0].encode(sine, &mut line); + fields[1].encode(triangle, &mut line); + + let decoded_sine: f32 = fields[0].decode(&line); + let decoded_triangle: f32 = fields[1].decode(&line); + + assert!(sine - decoded_sine <= 1. + 0.001); + assert!(triangle - decoded_triangle <= 0.05 + 0.001); + } + } +} diff --git a/crates/data-store/src/server/db/series/bitspec/spec.rs b/crates/data-store/src/server/db/series/bitspec/spec.rs new file mode 100644 index 00000000..234916db --- /dev/null +++ b/crates/data-store/src/server/db/series/bitspec/spec.rs @@ -0,0 +1,53 @@ +use std::ops::Range; + +use serde::{Deserialize, Serialize}; + +use super::MetaField; + +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +pub struct RangeWithRes { + pub range: Range, + pub resolution: f32, +} + +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +pub struct LengthWithOps { + pub(crate) length: u8, + pub(crate) decode_scale: f32, + pub(crate) decode_add: f32, +} + +impl From for LengthWithOps { + fn from(field: RangeWithRes) -> Self { + let given_range = field.range.end - field.range.start; + let needed_range = given_range as f32 / field.resolution as f32; + let length = needed_range.log2().ceil() as u8; + let decode_scale = field.resolution; + + let decode_add = field.range.start; + LengthWithOps { + decode_scale, + length, + decode_add, + } + } +} + +pub fn speclist_to_fields(input: Vec) -> Vec> { + let mut res = Vec::new(); + + let mut start_bit = 0; + for field in input { + res.push(MetaField:: { + offset: start_bit, + length: field.length, + decode_scale: field.decode_scale, + decode_add: field.decode_add, + }); + start_bit = start_bit + .checked_add(field.length) + .expect("line longer the 256 bits are not supported"); + } + + res +} diff --git a/crates/data-store/src/server/db/series/resampler.rs b/crates/data-store/src/server/db/series/resampler.rs index 198f2c15..fa38d0ea 100644 --- a/crates/data-store/src/server/db/series/resampler.rs +++ b/crates/data-store/src/server/db/series/resampler.rs @@ -1,3 +1,4 @@ +use super::bitspec; use smallvec::smallvec; #[derive(Debug, Clone)] @@ -26,7 +27,6 @@ impl byteseries::Resampler for Resampler { impl byteseries::Decoder for Resampler { type Item = smallvec::SmallVec; - // PERF: make item a smallVec <05-07-24, dvdsk noreply@davidsk.dev> fn decode_payload(&mut self, payload: &[u8]) -> Self::Item { self.fields .iter() diff --git a/crates/data-store/tests/list_data.rs b/crates/data-store/tests/list_data.rs index 1835b679..e6bdaaa8 100644 --- a/crates/data-store/tests/list_data.rs +++ b/crates/data-store/tests/list_data.rs @@ -1,64 +1,192 @@ -use std::iter; use std::net::SocketAddr; -use std::time::{Duration, Instant}; +use std::sync::Once; +use std::time::Duration; -use protocol::SensorMessage; +use futures::FutureExt; +use futures_concurrency::future::Race; +use protocol::large_bedroom::bed; +use protocol::{large_bedroom, Reading}; +use temp_dir::TempDir; +use time::OffsetDateTime; use tokio::io::AsyncWriteExt; -use tokio::net::TcpListener; -use tokio::time; +use tokio::net::TcpStream; +use tokio::sync::{mpsc, Notify}; +use tokio::time::sleep; +use tracing_error::ErrorLayer; +use tracing_subscriber::layer::SubscriberExt; +use tracing_subscriber::util::SubscriberInitExt; -async fn fake_data_server(addr: SocketAddr) { - let listener = TcpListener::bind(addr).await.unwrap(); +const fn test_reading(v: f32) -> Reading { + Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::Temperature(v))) +} - let (mut socket, _) = listener.accept().await.unwrap(); +async fn data_server(sub_port: u16, data_port: u16) { + use data_server::server; - let start = Instant::now(); - let pattern = iter::from_fn(move || { - let x = start.elapsed().as_secs() % 180; - let y = x as f32 * 0.5; - Some(y) - }); - let mut readings = pattern.map(|y| { - protocol::Reading::LargeBedroom(protocol::large_bedroom::Reading::Bed( - protocol::large_bedroom::bed::Reading::Temperature(y), - )) - }); + let (tx, rx) = mpsc::channel(2000); + tokio::select! { + e = server::register_subs(sub_port, &tx) => e.unwrap(), + e = server::handle_data_sources(data_port, &tx) => e.unwrap(), + e = server::spread_updates(rx) => e.unwrap(), + }; +} - loop { - time::sleep(Duration::from_secs(1)).await; - let new = readings.next().unwrap(); - let mut msg = SensorMessage::<5>::new(); - msg.values.push(new); - let bytes = msg.encode(); - socket.write_all(&bytes).await.unwrap(); +async fn send_sensor_values(data_port: u16, values: &[f32], data_send: &Notify) { + let mut conn = TcpStream::connect(("127.0.0.1", data_port)).await.unwrap(); + for v in values { + let mut sensor_msg = protocol::SensorMessage::<50>::new(); + sensor_msg.values.push(test_reading(*v)).unwrap(); + let encoded = protocol::Msg::Readings(sensor_msg).encode(); + conn.write_all(&encoded).await.unwrap(); + sleep(Duration::from_secs_f32(1.1)).await; } + data_send.notify_waiters(); + sleep(Duration::from_secs(999)).await; } -async fn test(data_store_addr: SocketAddr) { - let mut client = data_store::Client::connect(data_store_addr).await.unwrap(); +async fn check_client_list_data(data_store_addr: SocketAddr, data_send: &Notify) { + data_send.notified().await; + sleep(Duration::from_secs_f32(0.1)).await; + + let mut client = data_store::api::Client::connect(data_store_addr) + .await + .unwrap(); let list = client.list_data().await.unwrap(); - assert!(list.iter().any(|r| { - if let protocol::Reading::LargeBedroom(protocol::large_bedroom::Reading::Bed( - protocol::large_bedroom::bed::Reading::Temperature(_), - )) = r - { - true - } else { - false - } - })) + assert!( + !list.is_empty(), + "list is empty, should contain one reading" + ); + assert!( + list.iter().any(|r| { + if let protocol::Reading::LargeBedroom(protocol::large_bedroom::Reading::Bed( + protocol::large_bedroom::bed::Reading::Temperature(_), + )) = r + { + true + } else { + false + } + }), + "list is missing expected reading bed::Reading::Temperature. \ + Full list is: {list:?}" + ) +} + +async fn check_client_get_data( + data_store_addr: SocketAddr, + sensor_values: &[f32], + data_send: &Notify, +) { + data_send.notified().await; + sleep(Duration::from_secs_f32(0.1)).await; + let mut client = data_store::api::Client::connect(data_store_addr) + .await + .unwrap(); + let (time, data) = client + .get_data( + OffsetDateTime::now_utc() - Duration::from_secs(10), + OffsetDateTime::now_utc() + Duration::from_secs(10), + test_reading(0.0), + 5, + ) + .await + .unwrap(); + + assert_eq!(time.len(), data.len()); + assert!(data + .into_iter() + .zip(sensor_values.into_iter().copied()) + .all(|(a, b)| a == b)) +} + +static SETUP_REPORTING: Once = Once::new(); + +fn setup_reporting() { + SETUP_REPORTING.call_once(|| { + color_eyre::install().unwrap(); + tracing_subscriber::registry() + .with(ErrorLayer::default()) + .with(tracing_subscriber::fmt::layer().pretty().with_test_writer()) + .init(); + }); } #[tokio::test] -async fn main() { - let data_server_addr = SocketAddr::from(([127, 0, 0, 1], 3384)); - let data_store_addr = SocketAddr::from(([127, 0, 0, 1], 1294)); +async fn list_data() { + const DATA_SERVER_STARTUP: Duration = Duration::from_millis(20); + const DATA_STORE_STARTUP: Duration = Duration::from_millis(20); + const FIRST_MSG_PROCESSED: Duration = Duration::from_millis(1000); + + setup_reporting(); + + let test_dir = TempDir::new().unwrap(); + std::env::set_current_dir(test_dir.path()).unwrap(); + + let sub_port = reserve_port::ReservedPort::random().unwrap(); + let data_port = reserve_port::ReservedPort::random().unwrap(); + let store_port = reserve_port::ReservedPort::random().unwrap(); + + let data_server_addr = SocketAddr::from(([127, 0, 0, 1], sub_port.port())); + let data_store_addr = SocketAddr::from(([127, 0, 0, 1], store_port.port())); + + let data_send = Notify::new(); + let run_data_server = data_server(sub_port.port(), data_port.port()); + let run_data_store = sleep(DATA_SERVER_STARTUP) + .then(|()| data_store::server::run(data_server_addr, data_store_addr.port())); + let send_sensor_value = sleep(DATA_SERVER_STARTUP + DATA_STORE_STARTUP) + .then(|()| send_sensor_values(data_port.port(), &[0.0], &data_send)); + let run_test = sleep(DATA_SERVER_STARTUP + DATA_STORE_STARTUP + FIRST_MSG_PROCESSED) + .then(|()| check_client_list_data(data_store_addr, &data_send)); + + let res = ( + run_test.map(Result::Ok), + send_sensor_value.map(Result::Ok), + run_data_store, + run_data_server.map(Result::Ok), + ) + .race() + .await; + + res.unwrap(); +} + +#[tokio::test] +async fn read_data() { + const DATA_SERVER_STARTUP: Duration = Duration::from_millis(20); + const DATA_STORE_STARTUP: Duration = Duration::from_millis(20); + const FIRST_MSG_PROCESSED: Duration = Duration::from_millis(1000); + + let test_dir = TempDir::new().unwrap(); + std::env::set_current_dir(test_dir.path()).unwrap(); + + setup_reporting(); + + let sub_port = reserve_port::ReservedPort::random().unwrap(); + let data_port = reserve_port::ReservedPort::random().unwrap(); + let store_port = reserve_port::ReservedPort::random().unwrap(); + + let data_server_addr = SocketAddr::from(([127, 0, 0, 1], sub_port.port())); + let data_store_addr = SocketAddr::from(([127, 0, 0, 1], store_port.port())); + + let data_send = Notify::new(); + let sensor_values = [0.0, 0.1, 0.2, 0.3]; + let run_data_server = data_server(sub_port.port(), data_port.port()); + let run_data_store = sleep(DATA_SERVER_STARTUP) + .then(|()| data_store::server::run(data_server_addr, data_store_addr.port())); + let send_sensor_value = sleep(DATA_SERVER_STARTUP + DATA_STORE_STARTUP) + .then(|()| send_sensor_values(data_port.port(), &sensor_values, &data_send)); + let run_test = sleep(DATA_SERVER_STARTUP + DATA_STORE_STARTUP + FIRST_MSG_PROCESSED) + .then(|()| check_client_get_data(data_store_addr, &sensor_values, &data_send)); - let run_data_server = fake_data_server(data_server_addr); - let run_data_store = data_store::run(data_server_addr, data_store_addr.port()); - let run_test = test(data_store_addr); + let res = ( + run_test.map(Result::Ok), + send_sensor_value.map(Result::Ok), + run_data_store, + run_data_server.map(Result::Ok), + ) + .race() + .await; - use futures_concurrency::*; - let res = (run_test, run_data_store, run_data_server).race().await; + res.unwrap(); } From 7f52d5301c5519b713d1dba8d708c044572a6a80 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 13 Jul 2024 11:18:41 +0200 Subject: [PATCH 141/687] fixes data-store --- crates/data-store/src/main.rs | 7 +- crates/data-store/src/server.rs | 5 +- crates/data-store/src/server/db.rs | 5 +- crates/data-store/src/server/db/series.rs | 149 +++++++++++------- .../src/server/db/series/bitspec/field.rs | 8 +- .../src/server/db/series/resampler.rs | 40 +++++ crates/data-store/tests/list_data.rs | 34 ++-- crates/protocol/src/button.rs | 3 +- crates/protocol/src/large_bedroom/bed.rs | 19 ++- crates/protocol/src/large_bedroom/desk.rs | 9 +- crates/protocol/src/lib.rs | 2 - crates/protocol/src/reading_tree.rs | 5 +- crates/protocol/src/small_bedroom.rs | 4 +- 13 files changed, 197 insertions(+), 93 deletions(-) diff --git a/crates/data-store/src/main.rs b/crates/data-store/src/main.rs index 07d62674..d926c673 100644 --- a/crates/data-store/src/main.rs +++ b/crates/data-store/src/main.rs @@ -1,9 +1,9 @@ use std::net::SocketAddr; +use std::path::PathBuf; use clap::Parser; use color_eyre::eyre::Result; - #[derive(Parser)] #[command(name = "data server")] #[command(version = "1.0")] @@ -14,13 +14,16 @@ struct Cli { #[arg(short, long)] client_port: u16, + + #[arg(short, long, default_value = ".")] + data_dir: PathBuf, } #[tokio::main] async fn main() -> Result<()> { setup_tracing().unwrap(); let cli = Cli::parse(); - data_store::server::run(cli.data_server, cli.client_port).await + data_store::server::run(cli.data_server, cli.client_port, &cli.data_dir).await } fn setup_tracing() -> Result<()> { diff --git a/crates/data-store/src/server.rs b/crates/data-store/src/server.rs index e7b4faaf..fdf2ed36 100644 --- a/crates/data-store/src/server.rs +++ b/crates/data-store/src/server.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; use std::net::SocketAddr; +use std::path::Path; use std::sync::Arc; use color_eyre::Result; use futures_concurrency::future::Race; @@ -9,10 +10,10 @@ mod clients; mod db; // used from main and tests -pub async fn run(data_server: SocketAddr, client_port: u16) -> Result<()> { +pub async fn run(data_server: SocketAddr, client_port: u16, data_dir: &Path) -> Result<()> { let data = db::Data(Arc::new(Mutex::new(HashMap::new()))); let error = ( - db::run(data_server, data.clone()), + db::run(data_server, data.clone(), data_dir), clients::handle(client_port, data), ) .race() diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index 09a05491..16e2b954 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; use std::net::SocketAddr; +use std::path::Path; use std::sync::Arc; use time::OffsetDateTime; @@ -15,7 +16,7 @@ use series::Series; use crate::api; // TODO make resistant to data_server going down -pub(crate) async fn run(data_server_addr: SocketAddr, data: Data) -> Result<()> { +pub(crate) async fn run(data_server_addr: SocketAddr, data: Data, data_dir: &Path) -> Result<()> { let mut sub = AsyncSubscriber::connect(data_server_addr) .await .wrap_err("data-store server failed to subscribe with data-server") @@ -30,7 +31,7 @@ pub(crate) async fn run(data_server_addr: SocketAddr, data: Data) -> Result<()> .await .wrap_err("Error getting next message from data-server")? { - SubMessage::Reading(reading) => series::store(&data, &reading).await, + SubMessage::Reading(reading) => series::store(&data, &reading, data_dir).await, SubMessage::ErrorReport(_) => continue, }; diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index fb5e034c..7a4e86b3 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -1,6 +1,6 @@ use std::fs::create_dir_all; use std::io; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::time::Instant; use byteseries::{downsample, series, ByteSeries}; @@ -15,8 +15,8 @@ use byteseries::file::OpenError as FileOpenError; use series::data::OpenError as DataOpenError; use series::Error::Open; -mod resampler; mod bitspec; +mod resampler; use self::resampler::Resampler; @@ -26,7 +26,7 @@ use super::Data; struct Meta { reading: protocol::Reading, field: bitspec::MetaField, - set_at: Instant, + set_at: Option, } #[derive(Debug)] @@ -43,8 +43,7 @@ struct Header { } impl Series { - fn open_or_create(reading: &protocol::Reading) -> Result { - let path = base_path(reading); + fn open_or_create(reading: &protocol::Reading, dir: &Path) -> Result { let readings = reading.device().affected_readings(); let specs = to_speclist(readings); let fields = bitspec::speclist_to_fields(specs); @@ -54,7 +53,7 @@ impl Series { .map(|(reading, field)| Meta { reading: reading.clone(), field: field.clone(), - set_at: Instant::now(), + set_at: None, }) .collect(); @@ -68,6 +67,9 @@ impl Series { max_gap: None, bucket_size: 10, }]; + + let path = base_path(reading); + let path = dir.join(path); let res = ByteSeries::open_existing_with_resampler::( &path, payload_size, @@ -80,48 +82,14 @@ impl Series { encoding: fields.clone(), }; - let byteseries = match res { - Ok((byteseries, opened_file_header)) => { - if opened_file_header == expected_header { - byteseries - } else { - return Err(eyre!("header in file does not match readings")) - .with_note(|| { - format!( - "header in the just existing (opened) byteseries: {:?}", - opened_file_header - ) - }) - .with_note(|| { - format!( - "header for the data we want to write: {:?}", - expected_header - ) - }); - } - } - Err(Open(DataOpenError::File(FileOpenError::Io(e)))) - if e.kind() == io::ErrorKind::NotFound => - { - if let Some(dirs) = path.parent() { - create_dir_all(dirs) - .wrap_err("Could not create dirs structure for reading") - .with_note(|| format!("dirs: {}", dirs.display()))? - } - // compile_error!("create directory structure"); - info!("creating new byteseries"); - ByteSeries::new_with_resamplers( - &path, - payload_size, - expected_header, - resampler, - resample_configs, - ) - .wrap_err("Could not create new byteseries") - .with_note(|| format!("path: {}", path.display()))? - } - Err(e) => return Err(e).wrap_err("Could not open existing byteseries")?, - }; + let byteseries = try_create_new_if_open_failed( + res, + expected_header, + path, + payload_size, + resampler, + resample_configs, + )?; Ok(Self { line: vec![0; payload_size], @@ -135,26 +103,31 @@ impl Series { .device() .affected_readings() .iter() - .map(Tree::id) - .position(|local_id| local_id == reading.id()) + .map(|r| r.leaf().branch_id) + .position(|local_id| local_id == reading.leaf().branch_id) .expect("series are grouped by devices, elements come from affected_readings"); - { - let meta = &mut self.meta[index]; - meta.field.encode::(reading.leaf().val, &mut self.line); - meta.set_at = Instant::now(); - } + let meta = &mut self.meta[index]; + meta.field.encode::(reading.leaf().val, &mut self.line); + meta.set_at = Some(Instant::now()); if self .meta .iter() .map(|Meta { set_at, .. }| set_at) - .all(|set| set.elapsed().as_millis() < 500) + .all(|set| set.map(|s| s.elapsed().as_millis() < 500).unwrap_or(false)) { - let time = OffsetDateTime::now_utc() - self.meta[index].set_at.elapsed(); + let time = OffsetDateTime::now_utc() + - self.meta[index] + .set_at + .take() + .expect("if any is None the if is false") + .elapsed(); + self.byteseries .push_line(time.unix_timestamp() as u64, &self.line) .wrap_err("Could not write to timeseries on disk")?; + tracing::debug!("encoded data stored in byteseries"); } Ok(()) @@ -162,6 +135,7 @@ impl Series { /// # Panics /// If any of the requested readings are not part of this series. + #[instrument(skip(self))] pub fn read( &mut self, readings: &[protocol::Reading], @@ -176,6 +150,7 @@ impl Series { self.meta .iter() .find(|meta| *requested == meta.reading) + .inspect(|meta| info!("meta used for decoding: {meta:?}")) .map(|meta| meta.field.clone()) .expect( "caller of read makes sure all readings are\ @@ -218,8 +193,64 @@ impl Series { } } +fn try_create_new_if_open_failed( + res: Result<(ByteSeries, Header), series::Error>, + expected_header: Header, + path: PathBuf, + payload_size: usize, + resampler: Resampler, + resample_configs: Vec, +) -> Result { + match res { + Ok((byteseries, opened_file_header)) => { + if opened_file_header == expected_header { + Ok(byteseries) + } else { + return Err(eyre!("header in file does not match readings")) + .with_note(|| { + format!( + "header in the just existing (opened) byteseries: {:?}", + opened_file_header + ) + }) + .with_note(|| { + format!( + "header for the data we want to write: {:?}", + expected_header + ) + }); + } + } + Err(Open(DataOpenError::File(FileOpenError::Io(e)))) + if e.kind() == io::ErrorKind::NotFound => + { + if let Some(dirs) = path.parent() { + create_dir_all(dirs) + .wrap_err("Could not create dirs structure for reading") + .with_note(|| format!("dirs: {}", dirs.display()))?; + std::fs::read_dir(dirs) + .unwrap() + .map(Result::unwrap) + .for_each(|p| println!("{p:?}")); + } + // compile_error!("create directory structure"); + info!("creating new byteseries"); + ByteSeries::new_with_resamplers( + &path, + payload_size, + expected_header, + resampler, + resample_configs, + ) + .wrap_err("Could not create new byteseries") + .with_note(|| format!("path: {}", path.display())) + } + Err(e) => return Err(e).wrap_err("Could not open existing byteseries")?, + } +} + #[instrument(level = "debug", skip(data))] -pub(crate) async fn store(data: &Data, reading: &protocol::Reading) -> Result<()> { +pub(crate) async fn store(data: &Data, reading: &protocol::Reading, data_dir: &Path) -> Result<()> { tracing::debug!("storing received reading: {reading:?}"); let mut data = data.0.lock().await; @@ -229,7 +260,7 @@ pub(crate) async fn store(data: &Data, reading: &protocol::Reading) -> Result<() .append(reading) .wrap_err("failed to append to existing timeseries")?; } else { - let mut series = Series::open_or_create(&reading) + let mut series = Series::open_or_create(&reading, data_dir) .wrap_err("Could not open new series") .with_note(|| format!("reading was: {reading:?}"))?; series diff --git a/crates/data-store/src/server/db/series/bitspec/field.rs b/crates/data-store/src/server/db/series/bitspec/field.rs index 54949a3c..ba17245c 100644 --- a/crates/data-store/src/server/db/series/bitspec/field.rs +++ b/crates/data-store/src/server/db/series/bitspec/field.rs @@ -40,7 +40,8 @@ where + std::ops::SubAssign + std::ops::DivAssign + std::ops::MulAssign - + std::marker::Copy, + + std::marker::Copy + + core::fmt::Debug, { pub fn decode(&self, line: &[u8]) -> D where @@ -49,7 +50,8 @@ where + std::ops::Add + std::ops::SubAssign + std::ops::MulAssign - + std::ops::AddAssign, + + std::ops::AddAssign + + core::fmt::Debug, { let int_repr: u32 = compression::decode(line, self.offset, self.length); let mut decoded: D = num::cast(int_repr).unwrap(); @@ -67,7 +69,7 @@ where + std::ops::Add + std::ops::SubAssign + std::ops::AddAssign - + std::ops::DivAssign, + + std::ops::DivAssign { numb -= num::cast(self.decode_add).unwrap(); numb /= num::cast(self.decode_scale).unwrap(); diff --git a/crates/data-store/src/server/db/series/resampler.rs b/crates/data-store/src/server/db/series/resampler.rs index fa38d0ea..3180c726 100644 --- a/crates/data-store/src/server/db/series/resampler.rs +++ b/crates/data-store/src/server/db/series/resampler.rs @@ -48,3 +48,43 @@ impl byteseries::Encoder for Resampler { encoded } } + +#[cfg(test)] +mod test { + use byteseries::{Decoder, Encoder}; + use smallvec::SmallVec; + + use super::*; + + #[test] + fn decoded_is_correct() { + let reading = protocol::Reading::LargeBedroom(protocol::large_bedroom::Reading::Bed( + protocol::large_bedroom::bed::Reading::Temperature(0.5), + )); + + let readings = reading.device().affected_readings(); + // dbg!(readings.iter().map(Tree::leaf).collect::>()); + let specs = crate::server::db::series::to_speclist(readings); + // dbg!(&specs); + let fields = bitspec::speclist_to_fields(specs); + + let payload_size = fields + .iter() + .map(|spec| spec.length as usize) + .sum::() + .div_ceil(8); + let mut resampler = Resampler::from_fields(fields.clone(), payload_size); + let mut item: SmallVec = SmallVec::new(); + item.push(0.5f32); + item.push(0.5f32); + let bytes = resampler.encode_item(&item); + let decoded = resampler.decode_payload(&bytes); + assert!( + decoded + .iter() + .zip(item.clone()) + .all(|(a, b)| (a - b).abs() < 0.01), + "decoded and original different, decoded: {decoded:?}, org: {item:?}" + ); + } +} diff --git a/crates/data-store/tests/list_data.rs b/crates/data-store/tests/list_data.rs index e6bdaaa8..cc40f8d6 100644 --- a/crates/data-store/tests/list_data.rs +++ b/crates/data-store/tests/list_data.rs @@ -16,8 +16,11 @@ use tracing_error::ErrorLayer; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; -const fn test_reading(v: f32) -> Reading { - Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::Temperature(v))) +const fn test_readings(v: f32) -> [Reading; 2] { + [ + Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::Temperature(v))), + Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::Humidity(v))), + ] } async fn data_server(sub_port: u16, data_port: u16) { @@ -35,7 +38,9 @@ async fn send_sensor_values(data_port: u16, values: &[f32], data_send: &Notify) let mut conn = TcpStream::connect(("127.0.0.1", data_port)).await.unwrap(); for v in values { let mut sensor_msg = protocol::SensorMessage::<50>::new(); - sensor_msg.values.push(test_reading(*v)).unwrap(); + for val in test_readings(*v) { + sensor_msg.values.push(val).unwrap(); + } let encoded = protocol::Msg::Readings(sensor_msg).encode(); conn.write_all(&encoded).await.unwrap(); sleep(Duration::from_secs_f32(1.1)).await; @@ -85,9 +90,9 @@ async fn check_client_get_data( .unwrap(); let (time, data) = client .get_data( - OffsetDateTime::now_utc() - Duration::from_secs(10), - OffsetDateTime::now_utc() + Duration::from_secs(10), - test_reading(0.0), + OffsetDateTime::now_utc() - Duration::from_secs(30), + OffsetDateTime::now_utc() + Duration::from_secs(30), + test_readings(0.0)[0].clone(), 5, ) .await @@ -97,7 +102,8 @@ async fn check_client_get_data( assert!(data .into_iter() .zip(sensor_values.into_iter().copied()) - .all(|(a, b)| a == b)) + .inspect(|r| println!("(got, expected): {r:?}")) + .all(|(a, b)| (a - b).abs() < 0.1)) } static SETUP_REPORTING: Once = Once::new(); @@ -121,7 +127,6 @@ async fn list_data() { setup_reporting(); let test_dir = TempDir::new().unwrap(); - std::env::set_current_dir(test_dir.path()).unwrap(); let sub_port = reserve_port::ReservedPort::random().unwrap(); let data_port = reserve_port::ReservedPort::random().unwrap(); @@ -132,8 +137,9 @@ async fn list_data() { let data_send = Notify::new(); let run_data_server = data_server(sub_port.port(), data_port.port()); - let run_data_store = sleep(DATA_SERVER_STARTUP) - .then(|()| data_store::server::run(data_server_addr, data_store_addr.port())); + let run_data_store = sleep(DATA_SERVER_STARTUP).then(|()| { + data_store::server::run(data_server_addr, data_store_addr.port(), test_dir.path()) + }); let send_sensor_value = sleep(DATA_SERVER_STARTUP + DATA_STORE_STARTUP) .then(|()| send_sensor_values(data_port.port(), &[0.0], &data_send)); let run_test = sleep(DATA_SERVER_STARTUP + DATA_STORE_STARTUP + FIRST_MSG_PROCESSED) @@ -170,10 +176,12 @@ async fn read_data() { let data_store_addr = SocketAddr::from(([127, 0, 0, 1], store_port.port())); let data_send = Notify::new(); - let sensor_values = [0.0, 0.1, 0.2, 0.3]; + let sensor_values = [0.5]; + // let sensor_values = [0.0, 0.1, 0.2, 0.3]; let run_data_server = data_server(sub_port.port(), data_port.port()); - let run_data_store = sleep(DATA_SERVER_STARTUP) - .then(|()| data_store::server::run(data_server_addr, data_store_addr.port())); + let run_data_store = sleep(DATA_SERVER_STARTUP).then(|()| { + data_store::server::run(data_server_addr, data_store_addr.port(), test_dir.path()) + }); let send_sensor_value = sleep(DATA_SERVER_STARTUP + DATA_STORE_STARTUP) .then(|()| send_sensor_values(data_port.port(), &sensor_values, &data_send)); let run_test = sleep(DATA_SERVER_STARTUP + DATA_STORE_STARTUP + FIRST_MSG_PROCESSED) diff --git a/crates/protocol/src/button.rs b/crates/protocol/src/button.rs index 19a84832..70d7fa8b 100644 --- a/crates/protocol/src/button.rs +++ b/crates/protocol/src/button.rs @@ -89,6 +89,7 @@ macro_rules! button_enum { range: 0.0..3.0, resolution: 1.0, unit: crate::Unit::None, + branch_id: self.branch_id(), }) } fn name(&self) -> String { @@ -99,7 +100,7 @@ macro_rules! button_enum { .unwrap_or("-") .to_string() } - fn id(&self) -> crate::reading_tree::Id { + fn branch_id(&self) -> crate::reading_tree::Id { // SAFETY: Because `Self` is marked `repr(u8)`, its layout is a // `repr(C)` `union` between `repr(C)` structs, each of which // has the `u8` discriminant as its first field, so we can read diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 2e5c0730..43fe0fc4 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -34,7 +34,15 @@ button_enum! { } #[derive( - strum::EnumDiscriminants, Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, PartialEq, + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, )] #[strum_discriminants(derive(Hash))] pub enum Reading { @@ -88,7 +96,8 @@ impl Tree for Reading { Reading::Temperature(val) => ( *val, Device::Sht31.rooted(), - -10.0..45.0, + 0.0..100.0, // FIXME revert + // -10.0..45.0, 0.01, Unit::C, "Temperature", @@ -235,10 +244,11 @@ impl Tree for Reading { range, unit, description, + branch_id: self.branch_id(), }) } - fn id(&self) -> Id { + fn branch_id(&self) -> Id { ReadingDiscriminants::from(self) as Id } } @@ -356,7 +366,7 @@ impl Device { /// Note the order in which these occur is the order in which /// they will be stored, do not change it! - pub fn affected_readings(&self) -> &'static [crate::Reading] { + pub const fn affected_readings(&self) -> &'static [crate::Reading] { match self { Device::Sht31 => &tree![Reading::Temperature(0.0), Reading::Humidity(0.0)], Device::Bme680 => &tree![Reading::GassResistance(0.0), Reading::Pressure(0.0)], @@ -389,6 +399,7 @@ impl Device { } } + #[cfg(feature = "alloc")] fn rooted(self) -> crate::Device { crate::Device::LargeBedroom(crate::large_bedroom::Device::Bed(self)) } diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index 8739caa7..34e7a47e 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -3,7 +3,9 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "alloc")] use crate::reading_tree::{Item, ReadingInfo, Tree}; -use crate::{button_enum, Unit}; +#[cfg(feature = "alloc")] +use crate::Unit; +use crate::button_enum; button_enum! { /// No these are not borg, these are buttons on a string of cat5. @@ -50,6 +52,7 @@ impl Tree for Reading { range: -10.0..45.0, unit: Unit::C, description: "Temperature", + branch_id: self.branch_id(), }, Reading::Humidity(val) => ReadingInfo { val: *val, @@ -58,6 +61,7 @@ impl Tree for Reading { range: 0.0..100.0, unit: Unit::RH, description: "Temperature", + branch_id: self.branch_id(), }, Reading::Pressure(val) => ReadingInfo { val: *val, @@ -66,13 +70,14 @@ impl Tree for Reading { resolution: 0.18, unit: Unit::Pa, description: "Air pressure", + branch_id: self.branch_id(), }, Reading::Button(val) => return Item::Node(val as &dyn Tree), }; Item::Leaf(leaf) } - fn id(&self) -> crate::reading_tree::Id { + fn branch_id(&self) -> crate::reading_tree::Id { ReadingDiscriminants::from(self) as crate::reading_tree::Id } } diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 03363743..cd5ff482 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -9,8 +9,6 @@ pub mod small_bedroom; pub mod button; pub(crate) use button::button_enum; -// #[cfg(feature = "alloc")] -// pub mod device_tree; #[cfg(feature = "alloc")] pub mod reading_tree; diff --git a/crates/protocol/src/reading_tree.rs b/crates/protocol/src/reading_tree.rs index cd793e36..4a099b23 100644 --- a/crates/protocol/src/reading_tree.rs +++ b/crates/protocol/src/reading_tree.rs @@ -8,6 +8,7 @@ pub struct ReadingInfo { pub range: core::ops::Range, pub unit: Unit, pub description: &'static str, + pub branch_id: u8, } impl ReadingInfo { @@ -45,7 +46,7 @@ pub trait Tree: core::fmt::Debug { .unwrap_or("-") .to_string() } - fn id(&self) -> Id; + fn branch_id(&self) -> Id; } macro_rules! all_nodes { @@ -59,7 +60,7 @@ macro_rules! all_nodes { } } - fn id(&self) -> crate::reading_tree::Id { + fn branch_id(&self) -> crate::reading_tree::Id { $variant::from(self) as crate::reading_tree::Id } } diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index 9c6585eb..8d2dfa31 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -2,6 +2,7 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; use crate::button::Press; +#[cfg(feature = "alloc")] use crate::reading_tree::{Item, Tree}; crate::button_enum! { @@ -28,6 +29,7 @@ pub enum Reading { ButtonPanel(ButtonPanel), } +#[cfg(feature = "alloc")] impl Tree for Reading { fn inner<'a>(&'a self) -> Item<'a> { match self { @@ -35,7 +37,7 @@ impl Tree for Reading { } } - fn id(&self) -> crate::reading_tree::Id { + fn branch_id(&self) -> crate::reading_tree::Id { ReadingDiscriminants::from(self) as crate::reading_tree::Id } } From d0f4ae0c3c5816227fec6d086e1a4e8ed140d87e Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 13 Jul 2024 12:11:56 +0200 Subject: [PATCH 142/687] cargo clippy pedantic fixes --- crates/data-server/src/lib.rs | 2 + crates/data-server/src/server.rs | 18 ++--- crates/data-server/src/subscriber.rs | 13 ++-- crates/data-store/src/api/client.rs | 8 +-- crates/data-store/src/lib.rs | 2 + crates/data-store/src/server/db.rs | 2 +- crates/data-store/src/server/db/series.rs | 26 ++++--- .../src/server/db/series/bitspec.rs | 2 +- .../server/db/series/bitspec/compression.rs | 10 +-- .../src/server/db/series/bitspec/field.rs | 71 ------------------- .../src/server/db/series/bitspec/spec.rs | 14 ++-- .../src/server/db/series/resampler.rs | 8 +-- crates/data-store/tests/list_data.rs | 2 +- crates/protocol/src/button.rs | 23 +++--- crates/protocol/src/large_bedroom.rs | 10 ++- crates/protocol/src/large_bedroom/bed.rs | 30 +++++--- crates/protocol/src/large_bedroom/desk.rs | 17 +++-- crates/protocol/src/lib.rs | 41 ++++++++--- crates/protocol/src/reading_tree.rs | 12 ++-- crates/protocol/src/small_bedroom.rs | 2 +- crates/sensor-tui/src/main.rs | 2 +- 21 files changed, 145 insertions(+), 170 deletions(-) diff --git a/crates/data-server/src/lib.rs b/crates/data-server/src/lib.rs index 5011852f..57c5dba5 100644 --- a/crates/data-server/src/lib.rs +++ b/crates/data-server/src/lib.rs @@ -1,3 +1,5 @@ +#![allow(clippy::missing_panics_doc, clippy::missing_errors_doc)] + #[cfg(feature = "api")] pub mod subscriber; #[cfg(feature = "api")] diff --git a/crates/data-server/src/server.rs b/crates/data-server/src/server.rs index db689274..012956f6 100644 --- a/crates/data-server/src/server.rs +++ b/crates/data-server/src/server.rs @@ -24,7 +24,8 @@ pub async fn handle_client(stream: TcpStream, tx: Sender) { }; let bytes = &mut buf[0..n_read]; - if bytes.is_empty() { //eof + if bytes.is_empty() { + //eof warn!("end of stream"); return; } @@ -42,16 +43,17 @@ pub async fn handle_client(stream: TcpStream, tx: Sender) { tx.send(Event::NewReading(Ok(value))).await.unwrap(); } } - protocol::Msg::ErrorReport(report) => { - tx.send(Event::NewReading(Err(report.error))).await.unwrap() - } + protocol::Msg::ErrorReport(report) => tx + .send(Event::NewReading(Err(Box::new(report.error)))) + .await + .unwrap(), } } } pub enum Event { NewSub(TcpStream), - NewReading(Result), + NewReading(Result>), } pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { @@ -66,7 +68,7 @@ pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { Event::NewReading(Ok(reading)) => { // TODO use futures-util's peekable with next_if // to get up to 49 extra messages for efficiency - let mut readings: SensorMessage<50> = SensorMessage::new(); + let mut readings: SensorMessage<50> = SensorMessage::default(); readings .values .push(reading) @@ -74,14 +76,14 @@ pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { protocol::Msg::Readings(readings) } Event::NewReading(Err(err)) => { - let report = protocol::ErrorReport::new(err); + let report = protocol::ErrorReport::new(*err); protocol::Msg::ErrorReport(report) } }; let bytes = msg.encode(); let subs = mem::take(&mut subscribers); - for mut sub in subs.into_iter() { + for mut sub in subs { if let Err(e) = sub.write_all(&bytes).await { warn!("Error writing to subscriber: {e}"); } else { diff --git a/crates/data-server/src/subscriber.rs b/crates/data-server/src/subscriber.rs index dffee557..6510340d 100644 --- a/crates/data-server/src/subscriber.rs +++ b/crates/data-server/src/subscriber.rs @@ -9,7 +9,7 @@ use tracing::{instrument, trace}; #[derive(Debug)] pub enum SubMessage { Reading(protocol::Reading), - ErrorReport(protocol::Error), + ErrorReport(Box), } pub struct Subscriber { @@ -31,7 +31,7 @@ impl Subscriber { }) } - pub fn next(&mut self) -> Result { + pub fn next_msg(&mut self) -> Result { if let Some(val) = self.values.next() { return Ok(val); } @@ -45,6 +45,7 @@ impl Subscriber { } } +#[allow(clippy::module_name_repetitions)] pub struct AsyncSubscriber { reader: tokio::io::BufReader, buf: Vec, @@ -81,7 +82,7 @@ impl AsyncSubscriber { } } -#[instrument(level="trace")] +#[instrument(level = "trace")] fn decode_buffer_and_return_first( n_read: usize, buf: &mut Vec, @@ -90,7 +91,7 @@ fn decode_buffer_and_return_first( assert!(buffer.next().is_none()); if n_read == 0 { - return Err(SubscribeError::ConnEnded)?; + return Err(SubscribeError::ConnEnded); } buf.resize(n_read, 0); // ensure stop delimiter in bytes @@ -103,12 +104,12 @@ fn decode_buffer_and_return_first( .values .iter() .map(Clone::clone) - .map(|v| SubMessage::Reading(v)) + .map(SubMessage::Reading) .collect::>() .into_iter(); } Msg::ErrorReport(report) => { - *buffer = vec![SubMessage::ErrorReport(report.error)].into_iter() + *buffer = vec![SubMessage::ErrorReport(Box::new(report.error))].into_iter(); } } diff --git a/crates/data-store/src/api/client.rs b/crates/data-store/src/api/client.rs index a1b5d2ba..7fa25bd3 100644 --- a/crates/data-store/src/api/client.rs +++ b/crates/data-store/src/api/client.rs @@ -28,7 +28,7 @@ pub enum Error { #[error("Error while sending request: {0}")] Receiving(std::io::Error), #[error("Server ran into an error while processing our request: {0}")] - ServerError(super::ServerError), + Server(super::ServerError), #[error("Server closed connection before it awnserd")] ConnectionClosed, } @@ -51,7 +51,7 @@ impl Client { async fn send_receive(&mut self, request: super::Request) -> Result { self.stream.send(request).await.map_err(Error::Sending)?; match self.stream.try_next().await.map_err(Error::Receiving)? { - Some(super::Response::Error(e)) => Err(Error::ServerError(e)), + Some(super::Response::Error(e)) => Err(Error::Server(e)), Some(response) => Ok(response), None => Err(Error::ConnectionClosed), } @@ -60,7 +60,7 @@ impl Client { pub async fn list_data(&mut self) -> Result, Error> { let request = super::Request::ListData; match self.send_receive(request.clone()).await? { - super::Response::ListData(list) => return Ok(list), + super::Response::ListData(list) => Ok(list), response => Err(Error::IncorrectResponse { request: format!("{request:?}"), response: format!("{response:?}"), @@ -82,7 +82,7 @@ impl Client { n, }; match self.send_receive(request.clone()).await? { - super::Response::GetData { time, data } => return Ok((time, data)), + super::Response::GetData { time, data } => Ok((time, data)), response => Err(Error::IncorrectResponse { request: format!("{request:?}"), response: format!("{response:?}"), diff --git a/crates/data-store/src/lib.rs b/crates/data-store/src/lib.rs index 441c7dc7..3ca113c0 100644 --- a/crates/data-store/src/lib.rs +++ b/crates/data-store/src/lib.rs @@ -1,3 +1,5 @@ +#![allow(clippy::missing_errors_doc, clippy::missing_panics_doc)] + #[cfg(feature = "api")] pub mod api; #[cfg(feature = "server")] diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index 16e2b954..95b97d99 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -50,7 +50,7 @@ impl Data { .lock() .await .keys() - .flat_map(|device| device.affected_readings()) + .flat_map(protocol::Device::affected_readings) .cloned() .collect() } diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index 7a4e86b3..aaf8224a 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -25,7 +25,7 @@ use super::Data; #[derive(Debug)] struct Meta { reading: protocol::Reading, - field: bitspec::MetaField, + field: bitspec::Field, set_at: Option, } @@ -39,7 +39,7 @@ pub(crate) struct Series { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] struct Header { readings: Vec, - encoding: Vec>, + encoding: Vec>, } impl Series { @@ -85,7 +85,7 @@ impl Series { let byteseries = try_create_new_if_open_failed( res, expected_header, - path, + &path, payload_size, resampler, resample_configs, @@ -108,7 +108,7 @@ impl Series { .expect("series are grouped by devices, elements come from affected_readings"); let meta = &mut self.meta[index]; - meta.field.encode::(reading.leaf().val, &mut self.line); + meta.field.encode(reading.leaf().val, &mut self.line); meta.set_at = Some(Instant::now()); if self @@ -186,7 +186,7 @@ impl Series { let mut data = vec![Vec::new(); len]; for interleaved in interleaved_data { for (interleaved, data) in interleaved.into_iter().zip(data.iter_mut()) { - data.push(interleaved) + data.push(interleaved); } } Ok((time, data)) @@ -196,7 +196,7 @@ impl Series { fn try_create_new_if_open_failed( res: Result<(ByteSeries, Header), series::Error>, expected_header: Header, - path: PathBuf, + path: &Path, payload_size: usize, resampler: Resampler, resample_configs: Vec, @@ -206,19 +206,17 @@ fn try_create_new_if_open_failed( if opened_file_header == expected_header { Ok(byteseries) } else { - return Err(eyre!("header in file does not match readings")) + Err(eyre!("header in file does not match readings")) .with_note(|| { format!( - "header in the just existing (opened) byteseries: {:?}", - opened_file_header + "header in the just existing (opened) byteseries: {opened_file_header:?}", ) }) .with_note(|| { format!( - "header for the data we want to write: {:?}", - expected_header + "header for the data we want to write: {expected_header:?}", ) - }); + }) } } Err(Open(DataOpenError::File(FileOpenError::Io(e)))) @@ -245,7 +243,7 @@ fn try_create_new_if_open_failed( .wrap_err("Could not create new byteseries") .with_note(|| format!("path: {}", path.display())) } - Err(e) => return Err(e).wrap_err("Could not open existing byteseries")?, + Err(e) => Err(e).wrap_err("Could not open existing byteseries")?, } } @@ -260,7 +258,7 @@ pub(crate) async fn store(data: &Data, reading: &protocol::Reading, data_dir: &P .append(reading) .wrap_err("failed to append to existing timeseries")?; } else { - let mut series = Series::open_or_create(&reading, data_dir) + let mut series = Series::open_or_create(reading, data_dir) .wrap_err("Could not open new series") .with_note(|| format!("reading was: {reading:?}"))?; series diff --git a/crates/data-store/src/server/db/series/bitspec.rs b/crates/data-store/src/server/db/series/bitspec.rs index a77a916e..d8c7756f 100644 --- a/crates/data-store/src/server/db/series/bitspec.rs +++ b/crates/data-store/src/server/db/series/bitspec.rs @@ -2,5 +2,5 @@ mod compression; mod field; mod spec; -pub use field::MetaField; +pub use field::Field; pub use spec::{LengthWithOps, RangeWithRes, speclist_to_fields}; diff --git a/crates/data-store/src/server/db/series/bitspec/compression.rs b/crates/data-store/src/server/db/series/bitspec/compression.rs index 9fdd84ad..d92e2ddf 100644 --- a/crates/data-store/src/server/db/series/bitspec/compression.rs +++ b/crates/data-store/src/server/db/series/bitspec/compression.rs @@ -1,4 +1,5 @@ #[inline] +#[allow(clippy::cast_possible_truncation)] pub fn decode(line: &[u8], bit_offset: u8, length: u8) -> u32 { let start_byte = (bit_offset / 8) as usize; let stop_byte = ((bit_offset + length) / 8) as usize; @@ -8,23 +9,24 @@ pub fn decode(line: &[u8], bit_offset: u8, length: u8) -> u32 { let stop_mask = !(!0 >> used_bits); //decode first bit (never needs shifting (lowest part is used)) - let mut decoded: u32 = (line[start_byte] & start_mask) as u32; + let mut decoded: u32 = u32::from(line[start_byte] & start_mask); let mut bits_read = 8 - (bit_offset % 8); //if we have more bits if length > 8 { //decode middle bits, no masking needed for byte in &line[start_byte + 1..stop_byte] { - decoded |= (*byte as u32) << bits_read; + decoded |= u32::from(*byte) << bits_read; bits_read += 8; } } let stop_byte = ((bit_offset + length).div_ceil(8) - 1) as usize; //starts at 0 - decoded |= ((line[stop_byte] & stop_mask) as u32) << (bits_read - (8 - used_bits)); + decoded |= u32::from(line[stop_byte] & stop_mask) << (bits_read - (8 - used_bits)); decoded } #[inline] +#[allow(clippy::cast_possible_truncation)] pub fn encode(to_encode: u32, line: &mut [u8], bit_offset: u8, length: u8) { let start_mask = !0 >> (bit_offset % 8); @@ -37,7 +39,7 @@ pub fn encode(to_encode: u32, line: &mut [u8], bit_offset: u8, length: u8) { if length > 8 { //decode middle bits, no masking needed - for byte in line[start_byte + 1..stop_byte].iter_mut() { + for byte in &mut line[start_byte + 1..stop_byte] { *byte |= (to_encode >> bits_written) as u8; bits_written += 8; } diff --git a/crates/data-store/src/server/db/series/bitspec/field.rs b/crates/data-store/src/server/db/series/bitspec/field.rs index ba17245c..9086624c 100644 --- a/crates/data-store/src/server/db/series/bitspec/field.rs +++ b/crates/data-store/src/server/db/series/bitspec/field.rs @@ -2,16 +2,6 @@ use serde::{Deserialize, Serialize}; use super::compression; -// TODO: metafield and field are the same? remove one of em -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -pub struct MetaField { - pub offset: u8, //bits - pub length: u8, //bits (max 32 bit variables) - - pub decode_scale: T, - pub decode_add: T, -} - #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub struct Field { pub offset: u8, //bits @@ -21,65 +11,6 @@ pub struct Field { pub decode_add: T, } -impl Into> for MetaField { - fn into(self) -> Field { - Field { - offset: self.offset, - length: self.length, - decode_scale: self.decode_scale, - decode_add: self.decode_add, - } - } -} - -impl MetaField -where - T: num::cast::NumCast - + std::fmt::Display - + std::ops::Add - + std::ops::SubAssign - + std::ops::DivAssign - + std::ops::MulAssign - + std::marker::Copy - + core::fmt::Debug, -{ - pub fn decode(&self, line: &[u8]) -> D - where - D: num::cast::NumCast - + std::fmt::Display - + std::ops::Add - + std::ops::SubAssign - + std::ops::MulAssign - + std::ops::AddAssign - + core::fmt::Debug, - { - let int_repr: u32 = compression::decode(line, self.offset, self.length); - let mut decoded: D = num::cast(int_repr).unwrap(); - - decoded *= num::cast(self.decode_scale).unwrap(); //FIXME flip decode scale / and * - decoded += num::cast(self.decode_add).unwrap(); - - decoded - } - #[allow(dead_code)] - pub fn encode(&self, mut numb: T, line: &mut [u8]) - where - D: num::cast::NumCast - + std::fmt::Display - + std::ops::Add - + std::ops::SubAssign - + std::ops::AddAssign - + std::ops::DivAssign - { - numb -= num::cast(self.decode_add).unwrap(); - numb /= num::cast(self.decode_scale).unwrap(); - - let to_encode: u32 = num::cast(numb).unwrap(); - - compression::encode(to_encode, line, self.offset, self.length); - } -} - #[allow(dead_code)] impl Field where @@ -117,10 +48,8 @@ where + std::ops::AddAssign + std::ops::DivAssign, { - //println!("org: {}",numb); numb -= num::cast(self.decode_add).unwrap(); numb /= num::cast(self.decode_scale).unwrap(); - //println!("scale: {}, add: {}, numb: {}", self.decode_scale, self.decode_add, numb); let to_encode: u32 = num::cast(numb).unwrap(); diff --git a/crates/data-store/src/server/db/series/bitspec/spec.rs b/crates/data-store/src/server/db/series/bitspec/spec.rs index 234916db..d7ffca2c 100644 --- a/crates/data-store/src/server/db/series/bitspec/spec.rs +++ b/crates/data-store/src/server/db/series/bitspec/spec.rs @@ -2,7 +2,7 @@ use std::ops::Range; use serde::{Deserialize, Serialize}; -use super::MetaField; +use super::field::Field; #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub struct RangeWithRes { @@ -18,27 +18,29 @@ pub struct LengthWithOps { } impl From for LengthWithOps { + #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] fn from(field: RangeWithRes) -> Self { let given_range = field.range.end - field.range.start; - let needed_range = given_range as f32 / field.resolution as f32; - let length = needed_range.log2().ceil() as u8; + let needed_range = given_range / field.resolution; + let length = needed_range.log2().ceil() as u32; + let length = length.try_into().expect("max field length is 256 bits"); let decode_scale = field.resolution; let decode_add = field.range.start; LengthWithOps { - decode_scale, length, + decode_scale, decode_add, } } } -pub fn speclist_to_fields(input: Vec) -> Vec> { +pub fn speclist_to_fields(input: Vec) -> Vec> { let mut res = Vec::new(); let mut start_bit = 0; for field in input { - res.push(MetaField:: { + res.push(Field:: { offset: start_bit, length: field.length, decode_scale: field.decode_scale, diff --git a/crates/data-store/src/server/db/series/resampler.rs b/crates/data-store/src/server/db/series/resampler.rs index 3180c726..0d026c46 100644 --- a/crates/data-store/src/server/db/series/resampler.rs +++ b/crates/data-store/src/server/db/series/resampler.rs @@ -3,15 +3,15 @@ use smallvec::smallvec; #[derive(Debug, Clone)] pub(crate) struct Resampler { - pub(crate) fields: Vec>, + pub(crate) fields: Vec>, pub(crate) payload_size: usize, } impl Resampler { - pub(crate) fn from_fields(fields: Vec>, payload_size: usize) -> Self { + pub(crate) fn from_fields(fields: Vec>, payload_size: usize) -> Self { Self { - payload_size, fields, + payload_size, } } } @@ -43,7 +43,7 @@ impl byteseries::Encoder for Resampler { fn encode_item(&mut self, item: &Self::Item) -> Vec { let mut encoded = vec![0u8; self.payload_size]; for (field, item) in self.fields.iter().zip(item) { - field.encode::(*item, &mut encoded); + field.encode(*item, &mut encoded); } encoded } diff --git a/crates/data-store/tests/list_data.rs b/crates/data-store/tests/list_data.rs index cc40f8d6..f8d7fe9a 100644 --- a/crates/data-store/tests/list_data.rs +++ b/crates/data-store/tests/list_data.rs @@ -37,7 +37,7 @@ async fn data_server(sub_port: u16, data_port: u16) { async fn send_sensor_values(data_port: u16, values: &[f32], data_send: &Notify) { let mut conn = TcpStream::connect(("127.0.0.1", data_port)).await.unwrap(); for v in values { - let mut sensor_msg = protocol::SensorMessage::<50>::new(); + let mut sensor_msg = protocol::SensorMessage::<50>::default(); for val in test_readings(*v) { sensor_msg.values.push(val).unwrap(); } diff --git a/crates/protocol/src/button.rs b/crates/protocol/src/button.rs index 70d7fa8b..10326171 100644 --- a/crates/protocol/src/button.rs +++ b/crates/protocol/src/button.rs @@ -15,12 +15,9 @@ use serde::{Deserialize, Serialize}; pub struct Press(pub u16); impl Press { + #[must_use] pub fn is_long(&self) -> bool { - if self.0 > 300 { - true - } else { - false - } + self.0 > 300 } } @@ -29,13 +26,14 @@ impl Press { /// used to quickly find out if a button event is a long or short press. /// /// Example: -/// +/// ``` /// button_enum! { /// DeskButton { /// OneOfFour, /// TwoOfFour, /// } /// } +/// ``` /// macro_rules! button_enum { ( @@ -63,6 +61,7 @@ macro_rules! button_enum { } impl $name { + #[must_use] pub fn press(&self) -> crate::button::Press { match self { $(Self::$variant(d) => *d,)* @@ -70,18 +69,18 @@ macro_rules! button_enum { } } - impl Into for $name { - fn into(self) -> f32 { - match self { - $(Self::$variant(p) if p.is_long() => 2.0,)* - $(Self::$variant(_) => 1.0,)* + impl From<$name> for f32 { + fn from(val: $name) -> Self { + match val { + $($name::$variant(p) if p.is_long() => 2.0,)* + $($name::$variant(_) => 1.0,)* } } } #[cfg(feature = "alloc")] impl crate::reading_tree::Tree for $name { - fn inner<'a>(&'a self) -> crate::reading_tree::Item<'a> { + fn inner(&self) -> crate::reading_tree::Item<'_> { crate::reading_tree::Item::Leaf(crate::reading_tree::ReadingInfo { val: (*self).into(), device: $device, diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index 4bf6202a..a2be830d 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -44,6 +44,7 @@ pub enum Error { } impl Error { + #[must_use] pub fn device(&self) -> Device { match self { Error::Bed(error) => Device::Bed(error.device()), @@ -55,8 +56,8 @@ impl Error { impl core::fmt::Display for Error { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - Error::Bed(error) => write!(f, "{}", error), - Error::Desk(error) => write!(f, "{}", error), + Error::Bed(error) => write!(f, "{error}"), + Error::Desk(error) => write!(f, "{error}"), } } } @@ -90,12 +91,14 @@ pub enum Actuator { impl Actuator { #[cfg(feature = "alloc")] + #[must_use] pub fn encode(&self) -> Vec { postcard::to_allocvec_cobs(self).expect("Encoding should not fail") } - /// Buffer should be at least Self::ENCODED_SIZE long. The returned slice contains + /// Buffer should be at least `Self::ENCODED_SIZE` long. The returned slice contains /// the serialized data. It can be shorter then the input buffer. + #[must_use] pub fn encode_slice<'a>(&self, buf: &'a mut [u8]) -> &'a mut [u8] { postcard::to_slice_cobs(self, buf).expect("Encoding should not fail") } @@ -104,6 +107,7 @@ impl Actuator { postcard::from_bytes_cobs(bytes.as_mut()).map_err(crate::DecodeError::CorruptEncoding) } + #[must_use] pub fn version(&self) -> u8 { 0 } diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 43fe0fc4..09dba205 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -83,7 +83,10 @@ pub enum Reading { #[cfg(feature = "alloc")] impl Tree for Reading { - fn inner<'a>(&'a self) -> Item<'a> { + #[must_use] + #[allow(clippy::too_many_lines)] + #[allow(clippy::cast_precision_loss)] + fn inner(&self) -> Item<'_> { let (val, device, range, resolution, unit, description) = match self { Reading::Brightness(val) => ( *val, @@ -96,8 +99,7 @@ impl Tree for Reading { Reading::Temperature(val) => ( *val, Device::Sht31.rooted(), - 0.0..100.0, // FIXME revert - // -10.0..45.0, + -10.0..45.0, 0.01, Unit::C, "Temperature", @@ -131,7 +133,7 @@ impl Tree for Reading { "Air pressure", ), Reading::Co2(val) => ( - *val as f32, + f32::from(*val), Device::Mhz14.rooted(), 400.0..2_000.0, 1.0, @@ -248,6 +250,7 @@ impl Tree for Reading { }) } + #[must_use] fn branch_id(&self) -> Id { ReadingDiscriminants::from(self) as Id } @@ -262,6 +265,7 @@ pub enum Error { } impl Error { + #[must_use] pub(crate) fn device(&self) -> Device { match self { Self::Running(sensor_err) | Self::Setup(sensor_err) => sensor_err.device(), @@ -295,13 +299,13 @@ pub enum SensorError { impl core::fmt::Display for SensorError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - SensorError::Sht31(e) => write!(f, "{e}"), - SensorError::Bme680(e) => write!(f, "{e}"), - SensorError::Max44(e) => write!(f, "{e}"), - SensorError::Mhz14(e) => write!(f, "{e}"), - SensorError::Sps30(e) => write!(f, "{e}"), - SensorError::Nau7802Left(e) => write!(f, "{e}"), - SensorError::Nau7802Right(e) => write!(f, "{e}"), + SensorError::Sht31(e) + | SensorError::Bme680(e) + | SensorError::Max44(e) + | SensorError::Mhz14(e) + | SensorError::Sps30(e) + | SensorError::Nau7802Left(e) + | SensorError::Nau7802Right(e) => write!(f, "{e}"), } } } @@ -311,6 +315,7 @@ impl MaxSize for SensorError { } impl SensorError { + #[must_use] pub fn device(&self) -> Device { match self { SensorError::Sht31(_) => Device::Sht31, @@ -351,6 +356,7 @@ macro_rules! tree { } impl Device { + #[must_use] pub fn as_str(&self) -> &'static str { match self { Device::Sht31 => "Sht31", @@ -366,6 +372,7 @@ impl Device { /// Note the order in which these occur is the order in which /// they will be stored, do not change it! + #[must_use] pub const fn affected_readings(&self) -> &'static [crate::Reading] { match self { Device::Sht31 => &tree![Reading::Temperature(0.0), Reading::Humidity(0.0)], @@ -400,6 +407,7 @@ impl Device { } #[cfg(feature = "alloc")] + #[must_use] fn rooted(self) -> crate::Device { crate::Device::LargeBedroom(crate::large_bedroom::Device::Bed(self)) } diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index 34e7a47e..0250cdbb 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -1,11 +1,11 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; +use crate::button_enum; #[cfg(feature = "alloc")] use crate::reading_tree::{Item, ReadingInfo, Tree}; #[cfg(feature = "alloc")] use crate::Unit; -use crate::button_enum; button_enum! { /// No these are not borg, these are buttons on a string of cat5. @@ -43,7 +43,8 @@ pub enum Reading { #[cfg(feature = "alloc")] impl Tree for Reading { - fn inner<'a>(&'a self) -> Item<'a> { + #[must_use] + fn inner(&self) -> Item<'_> { let leaf = match self { Reading::Temperature(val) => ReadingInfo { val: *val, @@ -77,6 +78,7 @@ impl Tree for Reading { Item::Leaf(leaf) } + #[must_use] fn branch_id(&self) -> crate::reading_tree::Id { ReadingDiscriminants::from(self) as crate::reading_tree::Id } @@ -91,10 +93,10 @@ pub enum Error { } impl Error { + #[must_use] pub fn device(&self) -> Device { match self { - Self::Running(sensor_err) => sensor_err.device(), - Self::Setup(sensor_err) => sensor_err.device(), + Self::Running(sensor_err) | Self::Setup(sensor_err) => sensor_err.device(), Self::SetupTimedOut(device) | Self::Timeout(device) => device.clone(), } } @@ -122,6 +124,7 @@ impl MaxSize for SensorError { } impl SensorError { + #[must_use] pub fn device(&self) -> Device { match self { SensorError::BmeError(_) => Device::Bme280, @@ -133,8 +136,7 @@ impl SensorError { impl core::fmt::Display for SensorError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - SensorError::BmeError(e) => write!(f, "{e}"), - SensorError::Gpio(e) => write!(f, "{e}"), + SensorError::BmeError(e) | SensorError::Gpio(e) => write!(f, "{e}"), } } } @@ -160,15 +162,18 @@ macro_rules! rtree { } impl Device { + #[must_use] pub fn rooted(self) -> crate::Device { crate::Device::LargeBedroom(crate::large_bedroom::Device::Desk(self)) } + #[must_use] pub fn as_str(&self) -> &'static str { match self { Device::Bme280 => "Bme280", Device::Gpio => "Gpio", } } + #[must_use] pub fn affected_readings(&self) -> &'static [crate::Reading] { match self { Device::Bme280 => &rtree![Reading::Temperature(0.0), Reading::Humidity(0.0)], diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index cd5ff482..5c2df948 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(not(feature = "alloc"), no_std)] +#![allow(clippy::missing_panics_doc, clippy::missing_errors_doc)] use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -46,24 +47,29 @@ pub enum Reading { #[cfg(feature = "alloc")] impl Reading { + #[must_use] pub fn from_same_device(&self) -> &'static [Reading] { use reading_tree::Tree; self.leaf().from_same_device() } + #[must_use] pub fn range(&self) -> core::ops::Range { use reading_tree::Tree; self.leaf().range } + #[must_use] pub fn resolution(&self) -> f32 { use reading_tree::Tree; self.leaf().resolution } + #[must_use] pub fn device(&self) -> Device { use reading_tree::Tree; self.leaf().device } } impl Reading { + #[must_use] pub fn version() -> u8 { 0u8 } @@ -92,12 +98,14 @@ pub enum Device { SmallBedroom(small_bedroom::Device), } impl Device { + #[must_use] pub fn affected_readings(&self) -> &'static [Reading] { match self { Device::LargeBedroom(dev) => dev.affected_readings(), Device::SmallBedroom(dev) => dev.affected_readings(), } } + #[must_use] pub fn as_str(&self) -> &'static str { match self { Device::LargeBedroom(dev) => dev.as_str(), @@ -107,6 +115,7 @@ impl Device { } impl Error { + #[must_use] pub fn device(&self) -> Device { match self { Error::LargeBedroom(error) => Device::LargeBedroom(error.device()), @@ -117,7 +126,7 @@ impl Error { impl core::fmt::Display for Error { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - Error::LargeBedroom(error) => write!(f, "{}", error), + Error::LargeBedroom(error) => write!(f, "{error}"), } } } @@ -128,6 +137,7 @@ pub struct SensorMessage { pub version: u8, } +#[allow(clippy::large_enum_variant)] // can not use Box on embedded #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ErrorReport { pub error: Error, @@ -135,6 +145,7 @@ pub struct ErrorReport { } #[derive(Debug)] +#[allow(clippy::large_enum_variant)] // can not use Box on embedded pub enum Msg { Readings(SensorMessage), ErrorReport(ErrorReport), @@ -144,6 +155,7 @@ impl Msg { pub const READINGS: u8 = 1; pub const ERROR_REPORT: u8 = 2; + #[must_use] pub fn header(&self) -> u8 { let header = match self { Msg::Readings(_) => Self::READINGS, @@ -170,6 +182,7 @@ impl Msg { } #[cfg(feature = "alloc")] + #[must_use] pub fn encode(&self) -> Vec { let mut bytes = match self { Msg::Readings(readings) => readings.encode(), @@ -193,30 +206,34 @@ pub enum DecodeError { IncorrectMsgType(u8), } -impl SensorMessage { - /// the 2x is the max overhead from COBS encoding the encoded data - /// +2 is for the version - /// +4 covers the length of the heapless list - pub const ENCODED_SIZE: usize = 2 * (MAX_ITEMS * Reading::POSTCARD_MAX_SIZE + 2 + 4); - - pub fn new() -> Self { +impl Default for SensorMessage { + fn default() -> Self { Self { values: heapless::Vec::new(), version: 0, } } +} +impl SensorMessage { + /// the 2x is the max overhead from COBS encoding the encoded data + /// +2 is for the version + /// +4 covers the length of the heapless list + pub const ENCODED_SIZE: usize = 2 * (MAX_ITEMS * Reading::POSTCARD_MAX_SIZE + 2 + 4); + #[must_use] pub fn space_left(&self) -> bool { self.values.len() < self.values.capacity() } #[cfg(feature = "alloc")] + #[must_use] pub fn encode(&self) -> Vec { postcard::to_allocvec_cobs(self).expect("Encoding should not fail") } - /// Buffer should be at least Self::ENCODED_SIZE long. The returned slice contains + /// Buffer should be at least `Self::ENCODED_SIZE` long. The returned slice contains /// the serialized data. It can be shorter then the input buffer. + #[must_use] pub fn encode_slice<'a>(&self, buf: &'a mut [u8]) -> &'a mut [u8] { postcard::to_slice_cobs(self, buf).expect("Encoding should not fail") } @@ -225,6 +242,7 @@ impl SensorMessage { postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeError::CorruptEncoding) } + #[must_use] pub fn version(&self) -> u8 { self.version } @@ -236,17 +254,20 @@ impl ErrorReport { /// +4 covers the length of the heapless list pub const ENCODED_SIZE: usize = 2 * (Error::POSTCARD_MAX_SIZE + 2); + #[must_use] pub fn new(error: Error) -> Self { Self { error, version: 0 } } #[cfg(feature = "alloc")] + #[must_use] pub fn encode(&self) -> Vec { postcard::to_allocvec_cobs(self).expect("Encoding should not fail") } - /// Buffer should be at least Self::ENCODED_SIZE long. The returned slice contains + /// Buffer should be at least `Self::ENCODED_SIZE` long. The returned slice contains /// the serialized data. It can be shorter then the input buffer. + #[must_use] pub fn encode_slice<'a>(&self, buf: &'a mut [u8]) -> &'a mut [u8] { postcard::to_slice_cobs(self, buf).expect("Encoding should not fail") } diff --git a/crates/protocol/src/reading_tree.rs b/crates/protocol/src/reading_tree.rs index 4a099b23..202b71d7 100644 --- a/crates/protocol/src/reading_tree.rs +++ b/crates/protocol/src/reading_tree.rs @@ -12,6 +12,7 @@ pub struct ReadingInfo { } impl ReadingInfo { + #[must_use] pub fn from_same_device(&self) -> &'static [Reading] { self.device.affected_readings() } @@ -25,8 +26,8 @@ pub enum Item<'a> { } pub trait Tree: core::fmt::Debug { - fn inner<'a>(&'a self) -> Item<'a>; - fn leaf<'a>(&'a self) -> ReadingInfo + fn inner(&self) -> Item<'_>; + fn leaf(&self) -> ReadingInfo where Self: Sized, { @@ -39,11 +40,10 @@ pub trait Tree: core::fmt::Debug { } } fn name(&self) -> String { - let dbg_repr = format!("{:?}", self); + let dbg_repr = format!("{self:?}"); dbg_repr .split_once('(') - .map(|(name, _)| name) - .unwrap_or("-") + .map_or("_", |(name, _)| name) .to_string() } fn branch_id(&self) -> Id; @@ -52,7 +52,7 @@ pub trait Tree: core::fmt::Debug { macro_rules! all_nodes { ($name:ident; $variant:ident; $($var:ident),*) => { impl crate::reading_tree::Tree for $name { - fn inner<'a>(&'a self) -> crate::reading_tree::Item<'a> { + fn inner(&self) -> crate::reading_tree::Item<'_> { match self { $( $name::$var(inner) => crate::reading_tree::Item::Node(inner as &dyn crate::reading_tree::Tree) diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index 8d2dfa31..7b29b6c4 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -31,7 +31,7 @@ pub enum Reading { #[cfg(feature = "alloc")] impl Tree for Reading { - fn inner<'a>(&'a self) -> Item<'a> { + fn inner(&self) -> Item<'_> { match self { Reading::ButtonPanel(inner) => return Item::Node(inner), } diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index 2d3b060c..5d8af8e6 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -25,7 +25,7 @@ fn main() -> Result<()> { loop { let update = match sub - .next() + .next_msg() .wrap_err("Error getting next reading from server")? { SubMessage::Reading(reading) => Update::Reading(reading), From 4abea36ff1e7c8957756d2d447645f0d3feb0871 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 13 Jul 2024 12:47:40 +0200 Subject: [PATCH 143/687] fixes protocol renames + clippy run --- crates/brain/src/input/sensors.rs | 9 +++-- crates/brain/src/system.rs | 1 + crates/data-server/src/subscriber.rs | 2 +- crates/data-server/tests/api.rs | 4 +- crates/data-store/src/server/db.rs | 2 +- crates/desk-sensors/src/buttons.rs | 4 +- crates/desk-sensors/src/main.rs | 4 +- crates/desk-sensors/src/sensors.rs | 6 +-- crates/protocol/src/button.rs | 11 ------ crates/sensor-tui/src/main.rs | 2 +- crates/sensor-tui/src/tui/reading.rs | 59 +++++++++++++++------------- 11 files changed, 48 insertions(+), 56 deletions(-) diff --git a/crates/brain/src/input/sensors.rs b/crates/brain/src/input/sensors.rs index 7eb1606d..3daf994f 100644 --- a/crates/brain/src/input/sensors.rs +++ b/crates/brain/src/input/sensors.rs @@ -1,6 +1,7 @@ use std::net::SocketAddr; -use data_server::{AsyncSubscriber, SubscribeError}; +use data_server::subscriber::SubscribeError; +use data_server::{AsyncSubscriber, SubMessage}; use std::time::Duration; use tokio::sync::broadcast; use tracing::{error, warn}; @@ -24,11 +25,11 @@ pub async fn subscribe(event_tx: broadcast::Sender, data_server: SocketAd }; loop { - match sub.next().await { - Ok(Ok(reading)) => { + match sub.next_msg().await { + Ok(SubMessage::Reading(reading)) => { event_tx.send(Event::Sensor(reading)).unwrap(); } - Ok(Err(_)) => continue, + Ok(SubMessage::ErrorReport(_)) => continue, Err(e) => { warn!("Error while subscribed to sensor readings: {e}, retrying..."); break; diff --git a/crates/brain/src/system.rs b/crates/brain/src/system.rs index a31f4e53..63dc964e 100644 --- a/crates/brain/src/system.rs +++ b/crates/brain/src/system.rs @@ -8,6 +8,7 @@ use crate::input::jobs::Jobs; #[derive(Debug, Clone)] pub struct System { + #[allow(dead_code)] pub jobs: Jobs, pub lights: Lighting, // pub mpd: Mpd, diff --git a/crates/data-server/src/subscriber.rs b/crates/data-server/src/subscriber.rs index 6510340d..6375e5ee 100644 --- a/crates/data-server/src/subscriber.rs +++ b/crates/data-server/src/subscriber.rs @@ -67,7 +67,7 @@ impl AsyncSubscriber { }) } - pub async fn next(&mut self) -> Result { + pub async fn next_msg(&mut self) -> Result { if let Some(val) = self.values.next() { return Ok(val); } diff --git a/crates/data-server/tests/api.rs b/crates/data-server/tests/api.rs index 9c2e8db5..1f4e9182 100644 --- a/crates/data-server/tests/api.rs +++ b/crates/data-server/tests/api.rs @@ -35,7 +35,7 @@ const TEST_READING: Reading = async fn send_sensor_value(data_port: u16) -> Result { tokio::time::sleep(Duration::from_millis(100)).await; - let mut sensor_msg = protocol::SensorMessage::<50>::new(); + let mut sensor_msg = protocol::SensorMessage::<50>::default(); sensor_msg.values.push(TEST_READING).unwrap(); let encoded = protocol::Msg::Readings(sensor_msg).encode(); @@ -50,7 +50,7 @@ async fn subscribe_and_receive(sub_port: u16) -> Result { let mut sub = data_server::AsyncSubscriber::connect(("127.0.0.1", sub_port)) .await .unwrap(); - let received = sub.next().await.unwrap(); + let received = sub.next_msg().await.unwrap(); dbg!(&received); assert!(matches!(received, SubMessage::Reading(TEST_READING))); diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index 95b97d99..ee7e0c7e 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -27,7 +27,7 @@ pub(crate) async fn run(data_server_addr: SocketAddr, data: Data, data_dir: &Pat loop { let res = match sub - .next() + .next_msg() .await .wrap_err("Error getting next message from data-server")? { diff --git a/crates/desk-sensors/src/buttons.rs b/crates/desk-sensors/src/buttons.rs index d56b23c8..3b74e0e9 100644 --- a/crates/desk-sensors/src/buttons.rs +++ b/crates/desk-sensors/src/buttons.rs @@ -1,12 +1,12 @@ use embedded_hal_async::digital::Wait; -use protocol::{make_error_string, Press, Reading}; +use protocol::{make_error_string, button::Press, Reading}; use std::sync::mpsc::Sender; use std::time::{Duration, Instant}; use tracing::{debug, error, info, trace}; use std::thread; -use protocol::large_bedroom::desk::{Button, SetupError}; +use protocol::large_bedroom::desk::Button; use crate::{send_error, send_reading}; diff --git a/crates/desk-sensors/src/main.rs b/crates/desk-sensors/src/main.rs index 8854c2f5..54867f1e 100644 --- a/crates/desk-sensors/src/main.rs +++ b/crates/desk-sensors/src/main.rs @@ -7,7 +7,6 @@ use std::sync::mpsc::{self, Sender}; use std::time::Duration; use tracing::{debug, info, warn}; -mod buttons; mod sensors; #[derive(Parser)] @@ -27,7 +26,6 @@ fn main() { setup_tracing().unwrap(); let (tx, rx) = mpsc::channel(); - buttons::start_monitoring(tx.clone()); if let Err(error) = sensors::start_monitoring(tx.clone()) { send_error(&tx, error); } @@ -50,7 +48,7 @@ fn main() { let result = rx.recv().unwrap(); let msg = match result { Ok(reading) => { - let mut readings = SensorMessage::<1>::new(); + let mut readings = SensorMessage::<1>::default(); readings.values.push(reading).expect("capacity allows one push"); Msg::Readings(readings) } diff --git a/crates/desk-sensors/src/sensors.rs b/crates/desk-sensors/src/sensors.rs index cacdd7ae..ba1b75cd 100644 --- a/crates/desk-sensors/src/sensors.rs +++ b/crates/desk-sensors/src/sensors.rs @@ -9,7 +9,7 @@ use std::thread; use std::time::{Duration, Instant}; use protocol::large_bedroom::desk::Reading as DeskReading; -use protocol::large_bedroom::desk::{Error, SensorError, SetupError}; +use protocol::large_bedroom::desk::{Error, SensorError}; use protocol::{make_error_string, Reading}; use crate::{send_error, send_reading}; @@ -18,14 +18,14 @@ pub fn init() -> Result, Error> { let i2c_bus = I2cdev::new("/dev/i2c-1") .inspect_err(|e| tracing::error!("Could not open i2c bus: {e}")) .map_err(|e| protocol::make_error_string(e)) - .map_err(|e| Error::Setup(SetupError::I2c(e)))?; + .map_err(|e| Error::Setup(SensorError::BmeError(e)))?; let mut bme280 = Bme280::new_primary(i2c_bus); bme280 .init(&mut Delay) .inspect_err(|e| tracing::error!("Could not init bme280 sensor: {e}")) .map_err(|e| protocol::make_error_string(e)) - .map_err(|e| Error::Setup(SetupError::BmeError(e)))?; + .map_err(|e| Error::Setup(SensorError::BmeError(e)))?; Ok(bme280) } diff --git a/crates/protocol/src/button.rs b/crates/protocol/src/button.rs index 10326171..b9594b82 100644 --- a/crates/protocol/src/button.rs +++ b/crates/protocol/src/button.rs @@ -24,17 +24,6 @@ impl Press { /// turns an enum of empty variants into one with [`Press`](crate::Press) inside each variant also /// adds a method `press(&self)` that returns an instance of [`Press`](crate::Press). It can be /// used to quickly find out if a button event is a long or short press. -/// -/// Example: -/// ``` -/// button_enum! { -/// DeskButton { -/// OneOfFour, -/// TwoOfFour, -/// } -/// } -/// ``` -/// macro_rules! button_enum { ( $(#[$outer:meta])* diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index 5d8af8e6..7f414942 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -10,7 +10,7 @@ mod tui; enum Update { Reading(protocol::Reading), - Error(protocol::Error), + Error(Box), } fn main() -> Result<()> { diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index 356a13bb..2e9da113 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -1,6 +1,9 @@ use histogram::Histogram; +use protocol::reading_tree::ReadingInfo; +use protocol::reading_tree::{Item, Tree}; use protocol::Error; -use protocol::{ReadingTree::Tomato, ReadingTree::TomatoItem, Reading}; +use protocol::Reading; + use ratatui::{text::Line, widgets::Bar}; use std::collections::HashMap; use std::{collections::VecDeque, time::Instant}; @@ -10,12 +13,12 @@ pub struct SensorInfo { name: String, timing: Histogram, history: VecDeque<(Instant, f32)>, - condition: Result<(), Error>, + condition: Result<(), Box>, log: Vec<(Instant, Error)>, } impl SensorInfo { - fn last_at(&self) -> Result { + fn last_at(&self) -> Result> { self.condition.clone()?; let last = self @@ -69,10 +72,10 @@ fn add_leaf(text: String, tree: &mut TreeItem<'static, TreeKey>, key: TreeKey) { } fn add_root<'a>( - tomato: &dyn Tomato, + tomato: &dyn Tree, ground: &'a mut Vec>, ) -> &'a mut TreeItem<'static, TreeKey> { - let key = [tomato.id(); 6]; + let key = [tomato.branch_id(); 6]; let exists = ground.iter().any(|item| *item.identifier() == key); if !exists { let new_root = TreeItem::new(key, tomato.name(), vec![]).unwrap(); @@ -86,10 +89,10 @@ fn add_root<'a>( } fn add_node<'a>( - tomato: &dyn Tomato, + tomato: &dyn Tree, tree: &'a mut TreeItem<'static, TreeKey>, ) -> &'a mut TreeItem<'static, TreeKey> { - let key = [tomato.id(); 6]; + let key = [tomato.branch_id(); 6]; let new_item = TreeItem::new(key, tomato.name(), Vec::new()).unwrap(); // add just in case it was not there yet let _ignore_existing = tree.add_child(new_item); @@ -103,16 +106,16 @@ fn add_node<'a>( fn extract_leaf_info(reading: &Reading) -> (TreeKey, String, f32) { let mut key = [0u8; 6]; - key[0] = reading.id(); + key[0] = reading.branch_id(); - let mut reading = reading as &dyn Tomato; + let mut reading = reading as &dyn Tree; for byte in &mut key[1..] { reading = match reading.inner() { - TomatoItem::Node(inner) => { - *byte = inner.id(); + Item::Node(inner) => { + *byte = inner.branch_id(); inner } - TomatoItem::Leaf(val) => { + Item::Leaf(ReadingInfo { val, .. }) => { let name = reading.name(); return (key, name, val); } @@ -127,18 +130,18 @@ impl Readings { self.record_data(reading); } - pub fn add_error(&mut self, error: Error) { + pub fn add_error(&mut self, error: Box) { self.update_tree_err(&error); self.record_error(error); } - fn record_error(&mut self, error: Error) { - for broken in error.affected_readings() { + fn record_error(&mut self, error: Box) { + for broken in error.device().affected_readings() { let (key, name, _) = extract_leaf_info(&broken); if let Some(info) = self.data.get_mut(&key) { info.condition = Err(error.clone()); - info.log.push((Instant::now(), error.clone())); + info.log.push((Instant::now(), (*error).clone())); } else { self.data.insert( key, @@ -147,7 +150,7 @@ impl Readings { timing: Histogram::new(4, 24).unwrap(), history: VecDeque::new(), condition: Err(error.clone()), - log: vec![(Instant::now(), error.clone())], + log: vec![(Instant::now(), (*error).clone())], }, ); } @@ -184,19 +187,19 @@ impl Readings { fn update_tree(&mut self, reading: &Reading) { let (key, _, _) = extract_leaf_info(reading); - let mut tree = add_root(reading as &dyn Tomato, &mut self.ground); + let mut tree = add_root(reading as &dyn Tree, &mut self.ground); let mut tomato = match reading.inner() { - TomatoItem::Leaf(_) => unreachable!("no values at level 0"), - TomatoItem::Node(inner) => inner, + Item::Leaf(_) => unreachable!("no values at level 0"), + Item::Node(inner) => inner, }; loop { match tomato.inner() { - TomatoItem::Leaf(val) => { + Item::Leaf(ReadingInfo { val, .. }) => { let text = format!("{}: {}", tomato.name(), val); add_leaf(text, tree, key); return; } - TomatoItem::Node(inner) => { + Item::Node(inner) => { tree = add_node(tomato, tree); tomato = inner; } @@ -205,22 +208,22 @@ impl Readings { } fn update_tree_err(&mut self, error: &Error) { - for broken in error.affected_readings() { + for broken in error.device().affected_readings() { let (key, _, _) = extract_leaf_info(&broken); - let mut tree = add_root(&broken as &dyn Tomato, &mut self.ground); + let mut tree = add_root(broken as &dyn Tree, &mut self.ground); let mut tomato = match broken.inner() { - TomatoItem::Leaf(_) => unreachable!("no values at level 0"), - TomatoItem::Node(inner) => inner, + Item::Leaf(_) => unreachable!("no values at level 0"), + Item::Node(inner) => inner, }; loop { match tomato.inner() { - TomatoItem::Leaf(_) => { + Item::Leaf(_) => { let text = format!("{}: {:?}", tomato.name(), error); add_leaf(text, tree, key); return; } - TomatoItem::Node(inner) => { + Item::Node(inner) => { tree = add_node(tomato, tree); tomato = inner; } From 16e5e7c8538b1ed1f32a2b3ac0fdb68da005005c Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 13 Jul 2024 12:50:38 +0200 Subject: [PATCH 144/687] adds deploy script to data-store --- crates/data-server/deploy.sh | 2 +- crates/data-store/deploy.sh | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100755 crates/data-store/deploy.sh diff --git a/crates/data-server/deploy.sh b/crates/data-server/deploy.sh index 4ee670ce..c2c4d614 100755 --- a/crates/data-server/deploy.sh +++ b/crates/data-server/deploy.sh @@ -13,7 +13,7 @@ rsync -vh --progress \ cmds=" sudo mv /tmp/$NAME /home/ha/$NAME sudo chown ha:ha /home/ha/$NAME -sudo systemctl restart data-server.service +sudo systemctl restart $NAME.service " ssh -t sgc "$cmds" diff --git a/crates/data-store/deploy.sh b/crates/data-store/deploy.sh new file mode 100755 index 00000000..b9d23e54 --- /dev/null +++ b/crates/data-store/deploy.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -e + +BUILD_ARG=--release +SERVER="sgc" # ssh config name or full address +NAME=data-store + +cargo build --target=aarch64-unknown-linux-musl $BUILD_ARG +rsync -vh --progress \ + ../../target/aarch64-unknown-linux-musl/release/$NAME \ + $SERVER:/tmp/ + +cmds=" +sudo mv /tmp/$NAME /home/ha/$NAME +sudo chown ha:ha /home/ha/$NAME +sudo systemctl restart $NAME.service +" + +ssh -t sgc "$cmds" From 5617893ede9a71a60de7f6f10fcc14d30241a2bd Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 13 Jul 2024 13:31:28 +0200 Subject: [PATCH 145/687] use workspace dependencies and new deploy all script --- Cargo.lock | 100 ++++++++++++++------------- Cargo.toml | 7 +- crates/brain/Cargo.toml | 4 +- crates/data-server/Cargo.toml | 2 +- crates/data-store/.cargo/config.toml | 2 + crates/data-store/Cargo.toml | 4 +- crates/desk-sensors/Cargo.toml | 2 +- crates/sensor-tui/Cargo.toml | 5 +- deploy_all.sh | 7 ++ 9 files changed, 75 insertions(+), 58 deletions(-) create mode 100644 crates/data-store/.cargo/config.toml create mode 100755 deploy_all.sh diff --git a/Cargo.lock b/Cargo.lock index 21380383..f3a574b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -326,13 +326,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.80" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -415,7 +415,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -558,9 +558,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" [[package]] name = "byteseries" @@ -599,9 +599,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.104" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" +checksum = "47de7e88bbbd467951ae7f5a6f34f70d1b4d9cfce53d5fd70f74ebe118b3db56" [[package]] name = "cfg-if" @@ -632,9 +632,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.8" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" +checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" dependencies = [ "clap_builder", "clap_derive", @@ -642,9 +642,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.8" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" +checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" dependencies = [ "anstream", "anstyle", @@ -661,7 +661,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -886,7 +886,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -918,7 +918,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -958,7 +958,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -1015,7 +1015,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -1252,7 +1252,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -1471,9 +1471,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http", @@ -1522,9 +1522,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4fe55fb7a772d59a5ff1dfbff4fe0258d19b89fec4b233e75d35d5d2316badc" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", @@ -2157,7 +2157,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -2570,6 +2570,7 @@ dependencies = [ "color-eyre", "crossterm", "data-server", + "data-store", "histogram", "protocol", "ratatui", @@ -2581,22 +2582,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -2771,12 +2772,12 @@ dependencies = [ [[package]] name = "stability" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ff9eaf853dec4c8802325d8b6d3dffa86cc707fd7a1a4cdbf416e13b061787a" +checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" dependencies = [ "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -2816,7 +2817,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -2832,9 +2833,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.68" +version = "2.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" +checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" dependencies = [ "proc-macro2", "quote", @@ -2888,22 +2889,22 @@ checksum = "1f227968ec00f0e5322f9b8173c7a0cbcff6181a0a5b28e9892491c286277231" [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -2948,9 +2949,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -2988,7 +2989,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -3076,7 +3077,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -3210,11 +3211,12 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-truncate" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5fbabedabe362c618c714dbefda9927b5afc8e2a8102f47f081089a9019226" +checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" dependencies = [ - "itertools 0.12.1", + "itertools 0.13.0", + "unicode-segmentation", "unicode-width", ] @@ -3313,7 +3315,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", "wasm-bindgen-shared", ] @@ -3347,7 +3349,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3574,5 +3576,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] diff --git a/Cargo.toml b/Cargo.toml index 18803183..6f466016 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,12 @@ [workspace] resolver = "2" members = ["crates/*"] -exclude = ["sensor-nodes/bed-sensors"] +exclude = ["sensor-nodes/*"] + +[workspace.dependencies] +data-server = { path = "crates/data-server" } +data-store = { path = "crates/data-store" } +protocol = { path = "crates/protocol" } [workspace.package] rust-version = "1.78" diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 090cc4d4..7534c9f6 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -7,8 +7,8 @@ license.workspace = true authors.workspace = true [dependencies] -protocol = { path = "../protocol" } -data-server = { path = "../data-server" } +protocol = { workspace = true, features = ["alloc"] } +data-server = { workspace = true } futures = "0.3" tokio = { version = "1", features = ["full"] } diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index fb2cbbf9..5cb2c1e1 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -16,7 +16,7 @@ tracing = "0.1.40" tracing-error = "0.2.0" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -protocol = { path = "/home/david/Documents/HomeAutomation/crates/protocol", features = ["alloc"] } +protocol = { workspace = true, features = ["alloc"] } tokio = { version = "1.37.0", features = ["rt", "macros", "net", "sync", "io-util"] } tokio-stream = { version = "0.1.15", features = ["net"] } thiserror = "1.0.61" diff --git a/crates/data-store/.cargo/config.toml b/crates/data-store/.cargo/config.toml new file mode 100644 index 00000000..1002fed4 --- /dev/null +++ b/crates/data-store/.cargo/config.toml @@ -0,0 +1,2 @@ +[target.aarch64-unknown-linux-musl] +rustflags = ["-Clinker=rust-lld"] diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index 884fedca..7488ee49 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -19,8 +19,8 @@ tracing-error = "0.2.0" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } time = { version = "0.3", features = ["serde"] } -protocol = { path = "../protocol", features = ["alloc"] } -data-server = { path = "../data-server" } +protocol = { workspace = true, features = ["alloc"] } +data-server = { workspace = true } # byteseries = { git = "https://github.com/dvdsk/byteseries", features = ["smallvec"] } byteseries = { path = "/home/david/Documents/byteseries" } diff --git a/crates/desk-sensors/Cargo.toml b/crates/desk-sensors/Cargo.toml index 99335bab..cb23044f 100644 --- a/crates/desk-sensors/Cargo.toml +++ b/crates/desk-sensors/Cargo.toml @@ -16,7 +16,7 @@ tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } tracing-error = "0.2.0" -protocol = { path = "../protocol", features = ["alloc"] } +protocol = { workspace = true, features = ["alloc"] } tokio = { version = "1.37.0", features = ["rt", "time", "macros"] } embedded-hal-async = "1.0.0" heapless = "0.8.0" diff --git a/crates/sensor-tui/Cargo.toml b/crates/sensor-tui/Cargo.toml index b77a6d68..278068d7 100644 --- a/crates/sensor-tui/Cargo.toml +++ b/crates/sensor-tui/Cargo.toml @@ -16,5 +16,6 @@ tracing-error = "0.2.0" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } tui-tree-widget = { version = "0.20.0", git = "https://github.com/dvdsk/tui-rs-tree-widget" } -protocol = { path = "/home/david/Documents/HomeAutomation/crates/protocol" } -data-server = { path = "/home/david/Documents/HomeAutomation/crates/data-server" } +protocol = { workspace = true, features = ["alloc"] } +data-server = { workspace = true } +data-store = { workspace = true } diff --git a/deploy_all.sh b/deploy_all.sh new file mode 100755 index 00000000..f5646053 --- /dev/null +++ b/deploy_all.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -e + +for script in `find . -type f -name "deploy.sh"`; do + $script +done From 07fd841201bf89e5a84526df979b26307f8df041 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 13 Jul 2024 13:36:17 +0200 Subject: [PATCH 146/687] update deps --- Cargo.lock | 28 ++++++++++------------------ crates/sensor-tui/Cargo.toml | 6 +++--- crates/sensor-tui/src/tui/reading.rs | 2 ++ 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f3a574b3..bfb3e2c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -567,7 +567,7 @@ name = "byteseries" version = "0.4.0" dependencies = [ "arraydeque", - "itertools 0.13.0", + "itertools", "num-traits", "ron", "serde", @@ -1451,9 +1451,9 @@ checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "histogram" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe0e7d1b57c929216545b6aa17aff4798bc432b7065ac16a3e03b8dd63d8643" +checksum = "b62b8d85713ddc62e5e78db13bf9f9305610d0419276faa845076a68b7165872" dependencies = [ "thiserror", ] @@ -1669,15 +1669,6 @@ version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -2360,19 +2351,20 @@ dependencies = [ [[package]] name = "ratatui" -version = "0.26.3" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f44c9e68fd46eda15c646fbb85e1040b657a58cdc8c98db1d97a55930d991eef" +checksum = "d16546c5b5962abf8ce6e2881e722b4e0ae3b6f1a08a26ae3573c55853ca68d3" dependencies = [ "bitflags 2.6.0", "cassowary", "compact_str", "crossterm", - "itertools 0.12.1", + "itertools", "lru", "paste", "stability", "strum", + "strum_macros", "unicode-segmentation", "unicode-truncate", "unicode-width", @@ -3148,8 +3140,8 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tui-tree-widget" -version = "0.20.0" -source = "git+https://github.com/dvdsk/tui-rs-tree-widget#4da570ec5761b51bcd4c667dc66da1b197fe9b22" +version = "0.21.0" +source = "git+https://github.com/dvdsk/tui-rs-tree-widget#5db19b1895383f79d63810ea8a798dc9ccd89805" dependencies = [ "ratatui", "unicode-width", @@ -3215,7 +3207,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" dependencies = [ - "itertools 0.13.0", + "itertools", "unicode-segmentation", "unicode-width", ] diff --git a/crates/sensor-tui/Cargo.toml b/crates/sensor-tui/Cargo.toml index 278068d7..3cfd9f94 100644 --- a/crates/sensor-tui/Cargo.toml +++ b/crates/sensor-tui/Cargo.toml @@ -9,12 +9,12 @@ authors.workspace = true [dependencies] color-eyre = "0.6.3" crossterm = "0.27.0" -histogram = "0.10.1" -ratatui = "0.26.2" +histogram = "0.11" +ratatui = "0.27" tracing = "0.1.40" tracing-error = "0.2.0" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -tui-tree-widget = { version = "0.20.0", git = "https://github.com/dvdsk/tui-rs-tree-widget" } +tui-tree-widget = { version = "0.21.0", git = "https://github.com/dvdsk/tui-rs-tree-widget" } protocol = { workspace = true, features = ["alloc"] } data-server = { workspace = true } diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index 2e9da113..7702ca8c 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -249,7 +249,9 @@ pub struct ChartParts<'a> { fn histogram_bars(hist: &Histogram) -> Vec> { let percentiles = hist .percentiles(&[25.0, 50.0, 75.0, 90.0, 95.0, 100.0]) + .unwrap() .unwrap(); + percentiles .into_iter() .map(|(p, bucket)| { From 8502800a48dcedadf99df12a359b9131699712f3 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 14 Jul 2024 14:59:01 +0200 Subject: [PATCH 147/687] moved more deps to workspace deps --- Cargo.toml | 9 +++++++++ crates/brain/Cargo.toml | 8 ++++---- crates/data-server/Cargo.toml | 12 ++++++------ crates/data-store/Cargo.toml | 16 ++++++++-------- crates/desk-sensors/Cargo.toml | 12 ++++++------ crates/protocol/Cargo.toml | 2 +- crates/sensor-tui/Cargo.toml | 11 +++++++---- 7 files changed, 41 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6f466016..6b723fe0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,15 @@ data-server = { path = "crates/data-server" } data-store = { path = "crates/data-store" } protocol = { path = "crates/protocol" } +tokio = "1.38" +color-eyre = "0.6.3" +tracing = "0.1.40" +tracing-error = "0.2.0" +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +time = "0.3.36" +clap = "4" +thiserror = "1" + [workspace.package] rust-version = "1.78" edition = "2021" diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 7534c9f6..2a7f8893 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -11,7 +11,7 @@ protocol = { workspace = true, features = ["alloc"] } data-server = { workspace = true } futures = "0.3" -tokio = { version = "1", features = ["full"] } +tokio = { workspace = true, features = ["full"] } axum = { version = "0.7.4", default-features = false, features = ["tokio", "http1"] } axum-macros = "0.4.1" @@ -24,7 +24,7 @@ bincode = "1.3" thiserror = "1.0" chrono = { version = "0.4", features = ["serde"] } -time = { version = "0.3.36", features = ["macros"] } +time = { workspace = true, features = ["macros"] } tz-rs = "0.6.14" bytes = "1.5" @@ -36,8 +36,8 @@ mpd = "0.1" rand = "0.8" futures-util = "0.3.30" -tracing = "0.1.40" -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +tracing = {workspace = true} +tracing-subscriber = { workspace = true, features = ["env-filter"] } tracing-journald = "0.3.0" clap = { version = "4.5.4", features = ["derive"] } futures-concurrency = "7.5.0" diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index 5cb2c1e1..b8001b67 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -10,14 +10,14 @@ server = [] default = ["api", "server"] [dependencies] -clap = { version = "4", features = ["derive"] } -color-eyre = "0.6.3" -tracing = "0.1.40" -tracing-error = "0.2.0" -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +clap = { workspace = true, features = ["derive"] } +color-eyre = { workspace = true } +tracing = { workspace = true } +tracing-error = { workspace = true } +tracing-subscriber = { workspace = true, features = ["env-filter"] } protocol = { workspace = true, features = ["alloc"] } -tokio = { version = "1.37.0", features = ["rt", "macros", "net", "sync", "io-util"] } +tokio = { workspace = true, features = ["rt", "macros", "net", "sync", "io-util"] } tokio-stream = { version = "0.1.15", features = ["net"] } thiserror = "1.0.61" diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index 7488ee49..6f4ec69d 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -12,24 +12,24 @@ server = [] default = ["api", "server"] [dependencies] -clap = { version = "4", features = ["derive"] } -color-eyre = "0.6.3" -tracing = "0.1.40" -tracing-error = "0.2.0" -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -time = { version = "0.3", features = ["serde"] } +clap = { workspace = true, features = ["derive"] } +color-eyre = { workspace = true } +tracing = { workspace = true } +tracing-error = { workspace = true } +tracing-subscriber = { workspace = true, features = ["env-filter"] } +time = { workspace = true, features = ["serde"] } protocol = { workspace = true, features = ["alloc"] } data-server = { workspace = true } # byteseries = { git = "https://github.com/dvdsk/byteseries", features = ["smallvec"] } byteseries = { path = "/home/david/Documents/byteseries" } -tokio = { version = "1.38.0", features = ["fs", "net", "rt-multi-thread", "sync"] } +tokio = { workspace = true, features = ["fs", "net", "rt-multi-thread", "sync"] } futures-concurrency = "7.6.1" tokio-serde = { version = "0.9.0", features = ["bincode"] } tokio-util = { version = "0.7.11", features = ["codec"] } serde = { version = "1.0.203", features = ["derive"] } -thiserror = "1.0.61" +thiserror = { workspace = true } futures = "0.3.30" smallvec = "2.0.0-alpha.6" num = "0.4.3" diff --git a/crates/desk-sensors/Cargo.toml b/crates/desk-sensors/Cargo.toml index cb23044f..77ae84e4 100644 --- a/crates/desk-sensors/Cargo.toml +++ b/crates/desk-sensors/Cargo.toml @@ -10,13 +10,13 @@ linux-embedded-hal = "0.4" gpiocdev-embedded-hal = { version = "0.1.1", features = ["async_tokio"] } bme280 = { version = "0.5", git = "https://github.com/dvdsk/bme280-rs", features = ["postcard", "serde", "with_std"] } -clap = { version = "4.5.4", features = ["derive"] } -color-eyre = "0.6.3" -tracing = "0.1.40" -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -tracing-error = "0.2.0" +clap = { workspace = true, features = ["derive"] } +color-eyre = { workspace = true } +tracing = { workspace = true } +tracing-subscriber = { workspace =true, features = ["env-filter"] } +tracing-error = { workspace = true } protocol = { workspace = true, features = ["alloc"] } -tokio = { version = "1.37.0", features = ["rt", "time", "macros"] } +tokio = { workspace = true, features = ["rt", "time", "macros"] } embedded-hal-async = "1.0.0" heapless = "0.8.0" diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index 36d1210b..6e6dae2f 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -13,7 +13,7 @@ serde = { version = "1.0", features = ["derive"], default-features = false } postcard = { version = "1.0", features = ["experimental-derive"] } heapless = { version = "0.8.0", features = ["serde", "defmt-03"] } strum = { version = "0.26.2", default-features = false, features = ["derive"] } -thiserror = { version = "1.0", optional = true } +thiserror = { workspace = true, optional = true } defmt = "0.3.6" [features] diff --git a/crates/sensor-tui/Cargo.toml b/crates/sensor-tui/Cargo.toml index 3cfd9f94..5d64fe23 100644 --- a/crates/sensor-tui/Cargo.toml +++ b/crates/sensor-tui/Cargo.toml @@ -7,15 +7,18 @@ authors.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -color-eyre = "0.6.3" +color-eyre = { workspace = true } crossterm = "0.27.0" histogram = "0.11" ratatui = "0.27" -tracing = "0.1.40" -tracing-error = "0.2.0" -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } tui-tree-widget = { version = "0.21.0", git = "https://github.com/dvdsk/tui-rs-tree-widget" } +tokio = { workspace = true} +tracing = {workspace = true} +tracing-error = { workspace = true } +tracing-subscriber = { workspace =true, features = ["env-filter"] } + protocol = { workspace = true, features = ["alloc"] } data-server = { workspace = true } data-store = { workspace = true } +time = { workspace = true } From f61714544e1f609939e922a99e59d4b196e9e2fa Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 15 Jul 2024 17:53:51 +0200 Subject: [PATCH 148/687] reconnect to subscriber on error --- crates/data-store/Cargo.toml | 4 +- crates/data-store/src/main.rs | 13 +++-- crates/data-store/src/server/db.rs | 28 +++++----- .../data-store/src/server/db/reconnecting.rs | 52 +++++++++++++++++++ crates/data-store/src/server/db/series.rs | 26 +++++++--- 5 files changed, 96 insertions(+), 27 deletions(-) create mode 100644 crates/data-store/src/server/db/reconnecting.rs diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index 6f4ec69d..ece76e32 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -12,14 +12,14 @@ server = [] default = ["api", "server"] [dependencies] -clap = { workspace = true, features = ["derive"] } +clap = { workspace = true } color-eyre = { workspace = true } tracing = { workspace = true } tracing-error = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } time = { workspace = true, features = ["serde"] } -protocol = { workspace = true, features = ["alloc"] } +protocol = { workspace = true, features = ["alloc", "thiserror"] } data-server = { workspace = true } # byteseries = { git = "https://github.com/dvdsk/byteseries", features = ["smallvec"] } diff --git a/crates/data-store/src/main.rs b/crates/data-store/src/main.rs index d926c673..262fe85b 100644 --- a/crates/data-store/src/main.rs +++ b/crates/data-store/src/main.rs @@ -9,13 +9,14 @@ use color_eyre::eyre::Result; #[command(version = "1.0")] #[command(about = "Receives sensor events and spreads those to subscribed services")] struct Cli { + /// data server #[arg(short, long)] data_server: SocketAddr, #[arg(short, long)] client_port: u16, - #[arg(short, long, default_value = ".")] + #[arg(long, default_value = ".")] data_dir: PathBuf, } @@ -28,13 +29,19 @@ async fn main() -> Result<()> { fn setup_tracing() -> Result<()> { use tracing_error::ErrorLayer; - use tracing_subscriber::EnvFilter; + use tracing_subscriber::filter; use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt}; color_eyre::install().unwrap(); + let filter = filter::EnvFilter::builder().from_env().unwrap(); + let fmt = tracing_subscriber::fmt::layer() + .pretty() + .with_line_number(true); + tracing_subscriber::registry() - .with(EnvFilter::from_default_env()) + .with(filter) + .with(fmt) .with(ErrorLayer::default()) .init(); Ok(()) diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index ee7e0c7e..3e85d28c 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -6,35 +6,31 @@ use std::sync::Arc; use time::OffsetDateTime; use tokio::sync::Mutex; -use color_eyre::eyre::WrapErr; -use color_eyre::{Result, Section}; -use data_server::{AsyncSubscriber, SubMessage}; +use color_eyre::Result; +use data_server::SubMessage; mod series; use series::Series; use crate::api; -// TODO make resistant to data_server going down +mod reconnecting; +use reconnecting::ReconnectingSubscriber; + pub(crate) async fn run(data_server_addr: SocketAddr, data: Data, data_dir: &Path) -> Result<()> { - let mut sub = AsyncSubscriber::connect(data_server_addr) - .await - .wrap_err("data-store server failed to subscribe with data-server") - .with_suggestion(|| { - format!("verify data data-server is listening on: {data_server_addr}") - })?; - tracing::info!("connected to data-server at: {data_server_addr:?}"); + tracing::warn!("testing"); + let mut sub = ReconnectingSubscriber::new(data_server_addr); loop { - let res = match sub - .next_msg() - .await - .wrap_err("Error getting next message from data-server")? - { + let msg = sub.next_msg().await; + tracing::trace!("got msg: {msg:?}"); + + let res = match msg { SubMessage::Reading(reading) => series::store(&data, &reading, data_dir).await, SubMessage::ErrorReport(_) => continue, }; + if let Err(e) = res { tracing::error!("Error processing new reading: {e:?}"); } diff --git a/crates/data-store/src/server/db/reconnecting.rs b/crates/data-store/src/server/db/reconnecting.rs new file mode 100644 index 00000000..45ebbec3 --- /dev/null +++ b/crates/data-store/src/server/db/reconnecting.rs @@ -0,0 +1,52 @@ +use data_server::subscriber::SubscribeError; +use tokio::time::sleep; +use tracing::warn; +use std::time::Duration; +use data_server::{AsyncSubscriber, SubMessage}; +use std::net::SocketAddr; + +pub(crate) struct ReconnectingSubscriber { + pub(crate) connection: Option, + pub(crate) addr: SocketAddr, +} + +impl ReconnectingSubscriber { + pub(crate) fn new(addr: SocketAddr) -> Self { + Self { + connection: None, + addr, + } + } + + pub(crate) async fn next_msg(&mut self) -> SubMessage { + loop { + let mut retry_period = Duration::from_millis(50); + let mut conn = loop { + if let Some(conn) = self.connection.take() { + break conn; + } + + match AsyncSubscriber::connect(self.addr).await { + Ok(conn) => break conn, + Err(e) => warn!("Failed to (re)connect: {e}"), + } + sleep(retry_period).await; + retry_period = (retry_period * 2).min(Duration::from_secs(5)); + }; + + match conn.next_msg().await { + Ok(msg) => { + self.connection = Some(conn); + return msg; + } + Err(SubscribeError::DecodeFailed(e)) => { + panic!("Critical error while receiving msg from data-server: {e}") + } + Err(issue) => { + warn!("reconnecting, conn issue while getting next_msg: {issue}") + } + }; + } + } +} + diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index aaf8224a..4903ecec 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -63,10 +63,20 @@ impl Series { .sum::() .div_ceil(8); let resampler = Resampler::from_fields(fields.clone(), payload_size); - let resample_configs = vec![downsample::Config { - max_gap: None, - bucket_size: 10, - }]; + let resample_configs = vec![ + downsample::Config { + max_gap: None, + bucket_size: 10, + }, + downsample::Config { + max_gap: None, + bucket_size: 100, + }, + downsample::Config { + max_gap: None, + bucket_size: 1000, + }, + ]; let path = base_path(reading); let path = dir.join(path); @@ -104,8 +114,11 @@ impl Series { .affected_readings() .iter() .map(|r| r.leaf().branch_id) - .position(|local_id| local_id == reading.leaf().branch_id) - .expect("series are grouped by devices, elements come from affected_readings"); + .position(|id_in_list| id_in_list == reading.leaf().branch_id) + .expect( + "reading.device.affected_readings() is a list that contains \ + reading.branch_id()", + ); let meta = &mut self.meta[index]; meta.field.encode(reading.leaf().val, &mut self.line); @@ -204,6 +217,7 @@ fn try_create_new_if_open_failed( match res { Ok((byteseries, opened_file_header)) => { if opened_file_header == expected_header { + info!("Opened existing byteseries from: {}", path.display()); Ok(byteseries) } else { Err(eyre!("header in file does not match readings")) From 345c79ef29ad7542d1898118dcc4ff42f2e07d1a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 15 Jul 2024 17:54:39 +0200 Subject: [PATCH 149/687] load more data from data-store if possible --- crates/sensor-tui/Cargo.toml | 1 + crates/sensor-tui/src/main.rs | 67 ++++++++++++--- crates/sensor-tui/src/tui.rs | 51 ++++++----- crates/sensor-tui/src/tui/reading.rs | 124 ++++++++++++++++++++++----- crates/sensor-tui/src/tui/render.rs | 4 +- 5 files changed, 186 insertions(+), 61 deletions(-) diff --git a/crates/sensor-tui/Cargo.toml b/crates/sensor-tui/Cargo.toml index 5d64fe23..25fa6691 100644 --- a/crates/sensor-tui/Cargo.toml +++ b/crates/sensor-tui/Cargo.toml @@ -12,6 +12,7 @@ crossterm = "0.27.0" histogram = "0.11" ratatui = "0.27" tui-tree-widget = { version = "0.21.0", git = "https://github.com/dvdsk/tui-rs-tree-widget" } +clap = { workspace = true } tokio = { workspace = true} tracing = {workspace = true} diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index 7f414942..47d098a5 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -2,6 +2,7 @@ use std::net::SocketAddr; use std::sync::mpsc; use std::thread; +use clap::Parser; use color_eyre::eyre::WrapErr; use color_eyre::{Help, Result}; use data_server::SubMessage; @@ -11,28 +12,68 @@ mod tui; enum Update { Reading(protocol::Reading), Error(Box), + Shutdown, +} + +fn receive_data( + mut sub: data_server::Subscriber, + tx: mpsc::Sender>, +) { + loop { + let update = sub + .next_msg() + .wrap_err("Error getting next reading from server") + .map(|msg| match msg { + SubMessage::Reading(reading) => Update::Reading(reading), + SubMessage::ErrorReport(error) => Update::Error(error), + }); + + let err = update.is_err(); + tx.send(update).unwrap(); + if err { + break; + } + } +} + +#[derive(Parser)] +#[command(name = "sensor tui")] +#[command(version = "1.0")] +#[command(about = "View sensor values")] +struct Cli { + /// server where we can subscribe for sensor data updates + #[arg(short, long, default_value_t = SocketAddr::from(([192,168,1,43], 1235)))] + data_server: SocketAddr, + + /// server where we can fetch historical sensor data + #[arg(short='s', long, default_value_t = SocketAddr::from(([127,0,0,1], 1236)))] + data_store: SocketAddr, } fn main() -> Result<()> { setup_tracing().unwrap(); - let addr = SocketAddr::from(([192, 168, 1, 43], 1235)); - let mut sub = data_server::Subscriber::connect(addr) + + let Cli { + data_server, + data_store, + } = Cli::parse(); + let sub = data_server::Subscriber::connect(data_server) .wrap_err("failed to connect") - .with_suggestion(|| format!("verify the server is listening on: {addr}"))?; + .with_suggestion(|| format!("verify the server is listening on: {data_server}"))?; - let (tx, rx) = mpsc::channel(); - thread::spawn(|| tui::run(rx)); + let (tx1, rx1) = mpsc::channel(); + let (tx2, rx2) = mpsc::channel(); + + let tx1_clone = tx1.clone(); + thread::spawn(move || receive_data(sub, tx1_clone)); + thread::spawn(move || tui::run(rx2, tx1, data_store)); loop { - let update = match sub - .next_msg() - .wrap_err("Error getting next reading from server")? - { - SubMessage::Reading(reading) => Update::Reading(reading), - SubMessage::ErrorReport(error) => Update::Error(error), + let update = rx1.recv()??; + if let Update::Shutdown = update { + break Ok(()); }; - - tx.send(update).unwrap(); + tx2.send(update).unwrap() } } diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index 5ecdc083..feabe126 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -8,13 +8,13 @@ use ratatui::{ style::{Color, Style}, widgets::ListState, }; -use std::{collections::HashMap, io::stdout, sync::mpsc, time::Duration}; +use std::{collections::HashMap, io::stdout, net::SocketAddr, sync::mpsc, time::Duration}; use tui_tree_widget::TreeState; mod reading; use reading::Readings; mod render; -use crate::Update; +use crate::{trace_dbg, Update}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum ActiveList { @@ -31,15 +31,19 @@ impl ActiveList { } } - // fn swap(self) -> Self { - // match self { - // Self::Readings => Self::Actuators, - // Self::Actuators => Self::Readings, - // } - // } + fn swap(self) -> Self { + match self { + Self::Readings => Self::Actuators, + Self::Actuators => Self::Readings, + } + } } -pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { +pub fn run( + rx: mpsc::Receiver, + shutdown_tx: mpsc::Sender>, + data_store: SocketAddr +) -> Result<(), std::io::Error> { let mut readings = Readings { ground: Vec::new(), data: HashMap::new(), @@ -50,7 +54,7 @@ pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; terminal.clear()?; - let active_list = ActiveList::Readings; + let mut active_list = ActiveList::Readings; let mut reading_list_state = TreeState::default(); let mut actuator_list_state = ListState::default(); let actuators = vec![ @@ -61,14 +65,12 @@ pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { let mut plot_buf = Vec::new(); loop { - let data = reading_list_state - .selected() - .first() - .map(|key| readings.data.get(key)) - .flatten(); + let data = reading_list_state.selected() + .last() // unique leaf id + .and_then(|key| readings.data.get_mut(key)); let (chart, histogram) = if let Some(data) = data { - (data.chart(&mut plot_buf), data.histogram()) + (data.chart(&mut plot_buf, data_store), data.histogram()) } else { (None, readings.histogram_all()) }; @@ -103,12 +105,10 @@ pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { break; } if key.code == KeyCode::Left { - reading_list_state.key_left(); - // active_list = active_list.swap(); + active_list = active_list.swap(); } if key.code == KeyCode::Right { - reading_list_state.key_right(); - // active_list = active_list.swap(); + active_list = active_list.swap(); } if key.code == KeyCode::Down { reading_list_state.key_down(); @@ -116,9 +116,9 @@ pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { if key.code == KeyCode::Up { reading_list_state.key_up(); } - // if key.code == KeyCode::Enter { - // reading_list_state. - // } + if key.code == KeyCode::Enter { + reading_list_state.toggle_selected(); + } } } } @@ -127,14 +127,13 @@ pub fn run(rx: mpsc::Receiver) -> Result<(), std::io::Error> { Ok(Update::Reading(reading)) => { readings.add(reading); } - Ok(Update::Error(err)) => { - readings.add_error(err) - } + Ok(Update::Error(err)) => readings.add_error(err), _ => (), } } stdout().execute(LeaveAlternateScreen)?; disable_raw_mode()?; + shutdown_tx.send(Ok(Update::Shutdown)).unwrap(); Ok(()) } diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index 7702ca8c..a577d4d6 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -6,24 +6,63 @@ use protocol::Reading; use ratatui::{text::Line, widgets::Bar}; use std::collections::HashMap; -use std::{collections::VecDeque, time::Instant}; +use std::net::SocketAddr; +use std::sync::{Arc, Mutex, TryLockError}; +use std::thread; +use std::time::Instant; +use time::OffsetDateTime; use tui_tree_widget::TreeItem; +use crate::trace_dbg; + +#[derive(Debug)] pub struct SensorInfo { name: String, timing: Histogram, - history: VecDeque<(Instant, f32)>, + reading: Reading, + recent_history: Vec<(OffsetDateTime, f32)>, + old_history: Arc>>, + fetching: Option>, condition: Result<(), Box>, log: Vec<(Instant, Error)>, } +fn fetch_history( + history: Arc>>, + reading: Reading, + addr: SocketAddr, +) { + let rt = tokio::runtime::Builder::new_current_thread() + .enable_io() + .build() + .unwrap(); + + let data = rt.block_on(async { + let mut api = data_store::api::Client::connect(addr).await.unwrap(); + trace_dbg!(api.list_data().await); + trace_dbg!(api.get_data( + OffsetDateTime::now_utc() - time::Duration::minutes(15), + OffsetDateTime::now_utc(), + reading, + 300, + ) + .await) + .unwrap() + }); + + let mut history = history.lock().unwrap(); + for (t, y) in data.0.into_iter().zip(data.1) { + history.push((t, y)) + } +} + impl SensorInfo { - fn last_at(&self) -> Result> { + fn last_at(&self) -> Result> { self.condition.clone()?; let last = self - .history - .front() + .recent_history + .last() .expect("Items are put in the map when they arrive with a value"); Ok(last.0) } @@ -32,17 +71,51 @@ impl SensorInfo { histogram_bars(&self.timing) } - pub fn chart<'a>(&self, plot_buf: &'a mut Vec<(f64, f64)>) -> Option> { + pub fn chart<'a>( + &mut self, + plot_buf: &'a mut Vec<(f64, f64)>, + data_store: SocketAddr, + ) -> Option> { + let guard = match self.old_history.try_lock() { + Ok(list) => Some(list), + Err(TryLockError::WouldBlock) => None, + Err(other) => panic!( + "fetching sensor history from data-store \ + panicked: {other}" + ), + }; + let empty = Vec::new(); + let old_history = guard.as_deref().unwrap_or(&empty); + + let reference = old_history + .first() + .map(|(t, _)| t) + .or_else(|| self.recent_history.first().map(|(t, _)| t))?; + + let first_recent = self + .recent_history + .first() + .map(|(t, _)| t) + .cloned() + .unwrap_or(OffsetDateTime::from_unix_timestamp(0).unwrap()); plot_buf.clear(); - for xy in self - .history + for xy in old_history .iter() - .map(|(x, y)| (x.elapsed().as_secs_f64(), *y as f64)) + .take_while(|(t, _)| *t < first_recent) + .chain(self.recent_history.iter()) + .map(|(x, y)| ((*x - *reference).as_seconds_f64(), *y as f64)) { plot_buf.push(xy); } + if old_history.is_empty() && self.fetching.is_none() { + let old_history = self.old_history.clone(); + let reading = self.reading.clone(); + let handle = thread::spawn(move || fetch_history(old_history, reading, data_store)); + self.fetching = Some(handle); + } + Some(ChartParts { name: self.name.clone(), data: plot_buf, @@ -50,6 +123,9 @@ impl SensorInfo { } } +/// Guaranteed to be unique for a leaf, +/// the path to the leaf (through branch-id's) is +/// encoded with the last byte byte being the leaf's id pub type TreeKey = [u8; 6]; pub struct Readings { // in the ground there are multiple trees @@ -137,7 +213,7 @@ impl Readings { fn record_error(&mut self, error: Box) { for broken in error.device().affected_readings() { - let (key, name, _) = extract_leaf_info(&broken); + let (key, name, _) = extract_leaf_info(broken); if let Some(info) = self.data.get_mut(&key) { info.condition = Err(error.clone()); @@ -147,10 +223,13 @@ impl Readings { key, SensorInfo { name, + reading: broken.clone(), timing: Histogram::new(4, 24).unwrap(), - history: VecDeque::new(), + recent_history: Vec::new(), condition: Err(error.clone()), log: vec![(Instant::now(), (*error).clone())], + old_history: Arc::new(Mutex::new(Vec::new())), + fetching: None, }, ); } @@ -159,26 +238,29 @@ impl Readings { fn record_data(&mut self, reading: Reading) { let (key, name, val) = extract_leaf_info(&reading); + let time = OffsetDateTime::now_utc(); if let Some(info) = self.data.get_mut(&key) { if let Ok(last_reading) = info.last_at() { info.timing - .increment(last_reading.elapsed().as_millis() as u64) + .increment((time - last_reading).whole_milliseconds() as u64) .unwrap(); } - info.history.push_front((Instant::now(), val)); + info.recent_history.push((time, val)); info.condition = Ok(()); } else { - let mut history = VecDeque::new(); - history.push_front((Instant::now(), val)); + let history = vec![(time, val)]; self.data.insert( key, SensorInfo { name, + reading, timing: Histogram::new(4, 24).unwrap(), - history, + recent_history: history, + old_history: Arc::new(Mutex::new(Vec::new())), condition: Ok(()), log: Vec::new(), + fetching: None, }, ); } @@ -209,7 +291,7 @@ impl Readings { fn update_tree_err(&mut self, error: &Error) { for broken in error.device().affected_readings() { - let (key, _, _) = extract_leaf_info(&broken); + let (key, _, _) = extract_leaf_info(broken); let mut tree = add_root(broken as &dyn Tree, &mut self.ground); let mut tomato = match broken.inner() { @@ -221,7 +303,7 @@ impl Readings { Item::Leaf(_) => { let text = format!("{}: {:?}", tomato.name(), error); add_leaf(text, tree, key); - return; + break; } Item::Node(inner) => { tree = add_node(tomato, tree); @@ -247,10 +329,12 @@ pub struct ChartParts<'a> { } fn histogram_bars(hist: &Histogram) -> Vec> { - let percentiles = hist + let Some(percentiles) = hist .percentiles(&[25.0, 50.0, 75.0, 90.0, 95.0, 100.0]) .unwrap() - .unwrap(); + else { + return Vec::new(); + }; percentiles .into_iter() diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs index 1ae1f786..0ea13b71 100644 --- a/crates/sensor-tui/src/tui/render.rs +++ b/crates/sensor-tui/src/tui/render.rs @@ -77,7 +77,7 @@ fn detail_view(frame: &mut Frame, layout: Rect, chart: ChartParts, histogram: &[ let y_margin = f64::max(y_range * 0.5, 0.001 * y_bounds[0].abs()); let y_bounds = [y_bounds[0] - y_margin, y_bounds[1] + y_margin]; - let x_labels = vec!["0".into(), format_time(x_bounds[1]).into()]; + let x_labels = vec![format_time(x_bounds[1]).into(), "0".into()]; let y_labels = vec![ format!("{:.3}", y_bounds[0]).into(), format!("{:.3}", y_bounds[1]).into(), @@ -133,7 +133,7 @@ pub(crate) fn render_top( .areas(layout); frame.render_stateful_widget( - Tree::new(&readings) + Tree::new(readings) .expect("all item identifiers should be unique") .block( Block::default() From 564512f107153e38444963c2f1e3d64aa0cb407c Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 15 Jul 2024 17:55:13 +0200 Subject: [PATCH 150/687] fixes deploy_all.sh + renames/tiny refactors --- Cargo.lock | 7 +++++-- Cargo.toml | 2 +- crates/brain/Cargo.toml | 2 +- crates/data-server/Cargo.toml | 2 +- crates/desk-sensors/Cargo.toml | 2 +- crates/protocol/src/large_bedroom/desk.rs | 6 +++++- crates/protocol/src/lib.rs | 2 +- deploy_all.sh | 6 +++++- 8 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bfb3e2c1..ae347342 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -599,9 +599,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47de7e88bbbd467951ae7f5a6f34f70d1b4d9cfce53d5fd70f74ebe118b3db56" +checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052" [[package]] name = "cfg-if" @@ -2559,6 +2559,7 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" name = "sensor-tui" version = "0.0.0" dependencies = [ + "clap", "color-eyre", "crossterm", "data-server", @@ -2566,6 +2567,8 @@ dependencies = [ "histogram", "protocol", "ratatui", + "time", + "tokio", "tracing", "tracing-error", "tracing-subscriber", diff --git a/Cargo.toml b/Cargo.toml index 6b723fe0..1ab9bf81 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ tracing = "0.1.40" tracing-error = "0.2.0" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } time = "0.3.36" -clap = "4" +clap = { version = "4", features = ["derive"]} thiserror = "1" [workspace.package] diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 2a7f8893..71125435 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -39,6 +39,6 @@ futures-util = "0.3.30" tracing = {workspace = true} tracing-subscriber = { workspace = true, features = ["env-filter"] } tracing-journald = "0.3.0" -clap = { version = "4.5.4", features = ["derive"] } +clap = { workspace = true } futures-concurrency = "7.5.0" strum = { version = "0.26.2", default-features = false, features = ["derive"] } diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index b8001b67..6ee9d04a 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -10,7 +10,7 @@ server = [] default = ["api", "server"] [dependencies] -clap = { workspace = true, features = ["derive"] } +clap = { workspace = true } color-eyre = { workspace = true } tracing = { workspace = true } tracing-error = { workspace = true } diff --git a/crates/desk-sensors/Cargo.toml b/crates/desk-sensors/Cargo.toml index 77ae84e4..a63a10c9 100644 --- a/crates/desk-sensors/Cargo.toml +++ b/crates/desk-sensors/Cargo.toml @@ -10,7 +10,7 @@ linux-embedded-hal = "0.4" gpiocdev-embedded-hal = { version = "0.1.1", features = ["async_tokio"] } bme280 = { version = "0.5", git = "https://github.com/dvdsk/bme280-rs", features = ["postcard", "serde", "with_std"] } -clap = { workspace = true, features = ["derive"] } +clap = { workspace = true} color-eyre = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace =true, features = ["env-filter"] } diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index 0250cdbb..43dee952 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -176,7 +176,11 @@ impl Device { #[must_use] pub fn affected_readings(&self) -> &'static [crate::Reading] { match self { - Device::Bme280 => &rtree![Reading::Temperature(0.0), Reading::Humidity(0.0)], + Device::Bme280 => &rtree![ + Reading::Temperature(0.0), + Reading::Humidity(0.0), + Reading::Pressure(0.0) + ], Device::Gpio => todo!(), } } diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 5c2df948..6ddb5310 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -201,7 +201,7 @@ pub enum DecodeError { CorruptEncoding(postcard::Error), #[cfg_attr( feature = "thiserror", - error("Got an unknown message type, expected zero or one got: {}") + error("Got an unknown message type, expected zero or one got: {0}") )] IncorrectMsgType(u8), } diff --git a/deploy_all.sh b/deploy_all.sh index f5646053..67addb4f 100755 --- a/deploy_all.sh +++ b/deploy_all.sh @@ -3,5 +3,9 @@ set -e for script in `find . -type f -name "deploy.sh"`; do - $script + dir=`dirname "$script"` + cd "$dir" + # the deploy scripts need to run in the right working directory + . `basename "$script"` + cd - done From ca66cf545123c15d40752949777cee2254f4a3cd Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 16 Jul 2024 12:35:59 +0200 Subject: [PATCH 151/687] replace unwraps with expects(readon why not possible) --- crates/data-server/src/main.rs | 5 ++--- crates/data-server/src/server.rs | 24 ++++++++++++++++-------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/crates/data-server/src/main.rs b/crates/data-server/src/main.rs index fe8f8519..fa8671c2 100644 --- a/crates/data-server/src/main.rs +++ b/crates/data-server/src/main.rs @@ -23,7 +23,7 @@ struct Cli { #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { - setup_tracing().unwrap(); + setup_tracing(); let Cli { subscribe_port, @@ -42,7 +42,7 @@ async fn main() -> Result<()> { } } -fn setup_tracing() -> Result<()> { +fn setup_tracing() { use tracing_error::ErrorLayer; use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt, Layer}; @@ -58,5 +58,4 @@ fn setup_tracing() -> Result<()> { .with(file_subscriber) .with(ErrorLayer::default()) .init(); - Ok(()) } diff --git a/crates/data-server/src/server.rs b/crates/data-server/src/server.rs index 012956f6..0d563403 100644 --- a/crates/data-server/src/server.rs +++ b/crates/data-server/src/server.rs @@ -10,7 +10,7 @@ use protocol::{Reading, SensorMessage}; use tracing::{info, warn}; -pub async fn handle_client(stream: TcpStream, tx: Sender) { +pub async fn handle_client(stream: TcpStream, queue: Sender) { let mut reader = BufStream::new(stream); let mut buf = Vec::new(); loop { @@ -40,13 +40,16 @@ pub async fn handle_client(stream: TcpStream, tx: Sender) { match decoded { protocol::Msg::Readings(readings) => { for value in readings.values { - tx.send(Event::NewReading(Ok(value))).await.unwrap(); + queue + .send(Event::NewReading(Ok(value))) + .await + .expect("fn spread_updates should stay running"); } } - protocol::Msg::ErrorReport(report) => tx + protocol::Msg::ErrorReport(report) => queue .send(Event::NewReading(Err(Box::new(report.error)))) .await - .unwrap(), + .expect("fn spread_updates should stay running"), } } } @@ -59,7 +62,12 @@ pub enum Event { pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { let mut subscribers = Vec::new(); - while let Some(event) = events.recv().await { + loop { + let event = events + .recv() + .await + .expect("queue is kept open by register_subs"); + let msg = match event { Event::NewSub(sub) => { subscribers.push(sub); @@ -91,8 +99,6 @@ pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { } } } - - Ok(()) } pub async fn handle_data_sources(port: u16, share: &mpsc::Sender) -> Result<()> { @@ -129,7 +135,9 @@ pub async fn register_subs(port: u16, tx: &mpsc::Sender) -> Result<()> { match res { Ok((stream, source)) => { info!("new subscriber connected from: {source}"); - tx.send(Event::NewSub(stream)).await.unwrap(); + tx.send(Event::NewSub(stream)) + .await + .expect("spread_updates (rx) never ends"); } Err(e) => { warn!("new connection failed: {e}"); From 6ee6b0b76c98b27d332ba8370fdc603251df6c01 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 16 Jul 2024 12:36:15 +0200 Subject: [PATCH 152/687] data-store improve logging --- crates/data-store/src/server/db/reconnecting.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/data-store/src/server/db/reconnecting.rs b/crates/data-store/src/server/db/reconnecting.rs index 45ebbec3..4e43bc51 100644 --- a/crates/data-store/src/server/db/reconnecting.rs +++ b/crates/data-store/src/server/db/reconnecting.rs @@ -1,6 +1,6 @@ use data_server::subscriber::SubscribeError; use tokio::time::sleep; -use tracing::warn; +use tracing::{info, warn}; use std::time::Duration; use data_server::{AsyncSubscriber, SubMessage}; use std::net::SocketAddr; @@ -27,7 +27,10 @@ impl ReconnectingSubscriber { } match AsyncSubscriber::connect(self.addr).await { - Ok(conn) => break conn, + Ok(conn) => { + info!("Successfully (re)connected to data-server"); + break conn; + } Err(e) => warn!("Failed to (re)connect: {e}"), } sleep(retry_period).await; @@ -43,7 +46,7 @@ impl ReconnectingSubscriber { panic!("Critical error while receiving msg from data-server: {e}") } Err(issue) => { - warn!("reconnecting, conn issue while getting next_msg: {issue}") + warn!("Conn issue while getting next_msg: {issue}, reconnecting") } }; } From e62f69900013cda844acb2bb38f9fac8513451ce Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 16 Jul 2024 12:52:13 +0200 Subject: [PATCH 153/687] adds timeout to data-server subscriber client --- crates/data-server/src/subscriber.rs | 8 +++++--- crates/sensor-tui/src/main.rs | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/data-server/src/subscriber.rs b/crates/data-server/src/subscriber.rs index 6375e5ee..ce43f897 100644 --- a/crates/data-server/src/subscriber.rs +++ b/crates/data-server/src/subscriber.rs @@ -1,5 +1,6 @@ use std::io::{BufRead, BufReader}; -use std::net::{TcpStream, ToSocketAddrs}; +use std::net::{SocketAddr, TcpStream, ToSocketAddrs}; +use std::time::Duration; use std::vec; use protocol::{DecodeError, Msg}; @@ -19,8 +20,9 @@ pub struct Subscriber { } impl Subscriber { - pub fn connect(addr: impl ToSocketAddrs) -> Result { - let conn = TcpStream::connect(addr).map_err(SubscribeError::ConnFailed)?; + pub fn connect(addr: impl Into) -> Result { + let conn = TcpStream::connect_timeout(&addr.into(), Duration::from_millis(400)) + .map_err(SubscribeError::ConnFailed)?; let reader = BufReader::new(conn); let buf = Vec::new(); diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index 47d098a5..e0986dc4 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -57,6 +57,7 @@ fn main() -> Result<()> { data_server, data_store, } = Cli::parse(); + let sub = data_server::Subscriber::connect(data_server) .wrap_err("failed to connect") .with_suggestion(|| format!("verify the server is listening on: {data_server}"))?; From 05b481fe5a941fa83efd26083ab2e3abbe3fa1ac Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 16 Jul 2024 16:54:30 +0200 Subject: [PATCH 154/687] add name to subscribers --- crates/brain/src/input/sensors.rs | 2 +- crates/data-server/src/main.rs | 28 ++++--- crates/data-server/src/server.rs | 82 +++++++++++++++---- crates/data-server/src/subscriber.rs | 41 ++++++++-- .../src/subscriber}/reconnecting.rs | 42 ++++++---- crates/data-server/tests/api.rs | 19 +++-- crates/data-store/src/main.rs | 4 +- crates/data-store/src/server/db.rs | 8 +- crates/data-store/tests/list_data.rs | 16 ++-- crates/sensor-tui/src/main.rs | 2 +- 10 files changed, 171 insertions(+), 73 deletions(-) rename crates/{data-store/src/server/db => data-server/src/subscriber}/reconnecting.rs (55%) diff --git a/crates/brain/src/input/sensors.rs b/crates/brain/src/input/sensors.rs index 3daf994f..fc0974d7 100644 --- a/crates/brain/src/input/sensors.rs +++ b/crates/brain/src/input/sensors.rs @@ -11,7 +11,7 @@ use crate::controller::Event; pub async fn subscribe(event_tx: broadcast::Sender, data_server: SocketAddr) { loop { let mut sub = loop { - match AsyncSubscriber::connect(data_server).await { + match AsyncSubscriber::connect(data_server, "ha-brain").await { Ok(sub) => break sub, Err(SubscribeError::DecodeFailed(e)) => { error!("Decode failed: {e:?}. is protocol lib up to date? Exiting"); diff --git a/crates/data-server/src/main.rs b/crates/data-server/src/main.rs index fa8671c2..bfe9dcea 100644 --- a/crates/data-server/src/main.rs +++ b/crates/data-server/src/main.rs @@ -1,9 +1,11 @@ -use tokio::sync::mpsc; +use std::net::SocketAddr; + use tokio::select; +use tokio::sync::mpsc; +use clap::Parser; use color_eyre::Result; use tracing::info; -use clap::Parser; use data_server::server; @@ -12,13 +14,13 @@ use data_server::server; #[command(version = "1.0")] #[command(about = "Receives sensor events and spreads those to subscribed services")] struct Cli { - /// Optional name to operate on + /// addr to which subscribers can connect #[arg(short, long)] - subscribe_port: u16, + subscribe_addr: SocketAddr, - /// Sets a custom config file + /// addr to which data-source can supply msg's #[arg(short, long)] - update_port: u16, + update_addr: SocketAddr, } #[tokio::main(flavor = "current_thread")] @@ -26,18 +28,18 @@ async fn main() -> Result<()> { setup_tracing(); let Cli { - subscribe_port, - update_port, + subscribe_addr, + update_addr, } = Cli::parse(); - assert_ne!(subscribe_port, update_port); + assert_ne!(subscribe_addr, update_addr); - info!("listening for updates on port: {update_port}"); - info!("serving subscribers on port: {subscribe_port}"); + info!("listening for updates on: {update_addr}"); + info!("serving subscribers on: {subscribe_addr}"); let (tx, rx) = mpsc::channel(2000); select! { - e = server::register_subs(subscribe_port, &tx) => e, - e = server::handle_data_sources(update_port, &tx) => e, + e = server::register_subs(subscribe_addr, &tx) => e, + e = server::handle_data_sources(update_addr, &tx) => e, e = server::spread_updates(rx) => e, } } diff --git a/crates/data-server/src/server.rs b/crates/data-server/src/server.rs index 0d563403..86e17e2f 100644 --- a/crates/data-server/src/server.rs +++ b/crates/data-server/src/server.rs @@ -1,16 +1,19 @@ use color_eyre::eyre::Context; use std::mem; use std::net::SocketAddr; -use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufStream}; +use std::sync::Arc; +use std::time::Duration; +use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufStream}; use tokio::net::{TcpListener, TcpStream}; use tokio::sync::mpsc::{self, Sender}; +use tokio::time::timeout; use color_eyre::{Result, Section}; use protocol::{Reading, SensorMessage}; use tracing::{info, warn}; -pub async fn handle_client(stream: TcpStream, queue: Sender) { +pub async fn handle_data_source(stream: TcpStream, queue: Sender) { let mut reader = BufStream::new(stream); let mut buf = Vec::new(); loop { @@ -59,6 +62,16 @@ pub enum Event { NewReading(Result>), } +pub async fn handle_sub_conn(mut sub: TcpStream, mut tx: mpsc::Receiver>) { + loop { + let msg = tx.recv().await.expect("updates always keep coming"); + if let Err(e) = timeout(Duration::from_secs(2), sub.write_all(&msg)).await { + warn!("Subscriber connection failed: {e}"); + break; + } + } +} + pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { let mut subscribers = Vec::new(); @@ -70,11 +83,14 @@ pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { let msg = match event { Event::NewSub(sub) => { - subscribers.push(sub); + let (tx, rx) = tokio::sync::mpsc::channel(100); + tokio::spawn(handle_sub_conn(sub, rx)); + subscribers.push(tx); continue; } Event::NewReading(Ok(reading)) => { - // TODO use futures-util's peekable with next_if + // PERF: + // use futures-util's peekable with next_if // to get up to 49 extra messages for efficiency let mut readings: SensorMessage<50> = SensorMessage::default(); readings @@ -90,30 +106,29 @@ pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { }; let bytes = msg.encode(); + let bytes: Arc<[u8]> = Arc::from(bytes.into_boxed_slice()); + let subs = mem::take(&mut subscribers); - for mut sub in subs { - if let Err(e) = sub.write_all(&bytes).await { - warn!("Error writing to subscriber: {e}"); - } else { + for sub in subs { + if sub.try_send(bytes.clone()).is_ok() { subscribers.push(sub); } } } } -pub async fn handle_data_sources(port: u16, share: &mpsc::Sender) -> Result<()> { - let addr = SocketAddr::from(([0, 0, 0, 0], port)); +pub async fn handle_data_sources(addr: SocketAddr, share: &mpsc::Sender) -> Result<()> { let listener = TcpListener::bind(addr) .await .wrap_err("Could not start listening for new subscribers") - .with_note(|| format!("trying to listen on port: {port}"))?; + .with_note(|| format!("trying to listen on: {addr}"))?; loop { let res = listener.accept().await; match res { Ok((stream, source)) => { info!("new data source connected from: {source}"); - tokio::spawn(handle_client(stream, share.clone())); + tokio::spawn(handle_data_source(stream, share.clone())); } Err(e) => { println!("new connection failed: {e}"); @@ -123,18 +138,26 @@ pub async fn handle_data_sources(port: u16, share: &mpsc::Sender) -> Resu } } -pub async fn register_subs(port: u16, tx: &mpsc::Sender) -> Result<()> { - let addr = SocketAddr::from(([0, 0, 0, 0], port)); +pub async fn register_subs(addr: SocketAddr, tx: &mpsc::Sender) -> Result<()> { let listener = TcpListener::bind(addr) .await .wrap_err("Could not start receiving updates") - .with_note(|| format!("trying to listen on port: {port}"))?; + .with_note(|| format!("trying to listen on: {addr}"))?; loop { let res = listener.accept().await; match res { - Ok((stream, source)) => { - info!("new subscriber connected from: {source}"); + Ok((mut stream, source)) => { + match check_sub(&mut stream).await { + Ok(name) => info!("new subscriber '{name}' connected from: {source}"), + Err(e) => { + warn!( + "newly connected subscriber from: {source} failed to\ + pass check: {e}, disconnecting" + ); + continue; + } + } tx.send(Event::NewSub(stream)) .await .expect("spread_updates (rx) never ends"); @@ -146,3 +169,28 @@ pub async fn register_subs(port: u16, tx: &mpsc::Sender) -> Result<()> { }; } } + +#[derive(Debug, thiserror::Error)] +pub enum CheckErr { + #[error("Could not read name length: {0}")] + ReadLen(std::io::Error), + #[error("Timed out reading subscriber name")] + Timeout, + #[error("Name could not be parsed: {0}")] + ParseName(std::string::FromUtf8Error), +} + +async fn check_sub(stream: &mut TcpStream) -> Result { + let name_len = timeout(Duration::from_millis(200), stream.read_u8()) + .await + .map_err(|_| CheckErr::Timeout)? + .map_err(CheckErr::ReadLen)?; + let mut buf = vec![0; name_len as usize]; + timeout(Duration::from_millis(200), stream.read_exact(&mut buf)) + .await + .map_err(|_| CheckErr::Timeout)? + .map_err(CheckErr::ReadLen)?; + + let name = String::from_utf8(buf).map_err(CheckErr::ParseName)?; + Ok(name) +} diff --git a/crates/data-server/src/subscriber.rs b/crates/data-server/src/subscriber.rs index ce43f897..86c305ea 100644 --- a/crates/data-server/src/subscriber.rs +++ b/crates/data-server/src/subscriber.rs @@ -1,12 +1,14 @@ -use std::io::{BufRead, BufReader}; -use std::net::{SocketAddr, TcpStream, ToSocketAddrs}; +use std::io::{BufRead, BufReader, Write}; +use std::net::{SocketAddr, TcpStream}; use std::time::Duration; use std::vec; use protocol::{DecodeError, Msg}; -use tokio::io::AsyncBufReadExt; +use tokio::io::{AsyncBufReadExt, AsyncWriteExt}; use tracing::{instrument, trace}; +pub mod reconnecting; + #[derive(Debug)] pub enum SubMessage { Reading(protocol::Reading), @@ -20,9 +22,17 @@ pub struct Subscriber { } impl Subscriber { - pub fn connect(addr: impl Into) -> Result { - let conn = TcpStream::connect_timeout(&addr.into(), Duration::from_millis(400)) + pub fn connect(addr: impl Into, name: &str) -> Result { + let mut conn = TcpStream::connect_timeout(&addr.into(), Duration::from_millis(400)) .map_err(SubscribeError::ConnFailed)?; + let name_len: u8 = name + .len() + .try_into() + .map_err(|_| SubscribeError::NameTooLong)?; + conn.write_all(&[name_len]) + .map_err(SubscribeError::FailedToWriteName)?; + conn.write_all(name.as_bytes()) + .map_err(SubscribeError::FailedToWriteName)?; let reader = BufReader::new(conn); let buf = Vec::new(); @@ -55,10 +65,23 @@ pub struct AsyncSubscriber { } impl AsyncSubscriber { - pub async fn connect(addr: impl tokio::net::ToSocketAddrs) -> Result { - let conn = tokio::net::TcpStream::connect(addr) + pub async fn connect( + addr: impl tokio::net::ToSocketAddrs, + name: &str, + ) -> Result { + let mut conn = tokio::net::TcpStream::connect(addr) .await .map_err(SubscribeError::ConnFailed)?; + let name_len: u8 = name + .len() + .try_into() + .map_err(|_| SubscribeError::NameTooLong)?; + conn.write_all(&[name_len]) + .await + .map_err(SubscribeError::FailedToWriteName)?; + conn.write_all(name.as_bytes()) + .await + .map_err(SubscribeError::FailedToWriteName)?; let reader = tokio::io::BufReader::new(conn); let buf = Vec::new(); @@ -129,4 +152,8 @@ pub enum SubscribeError { DecodeFailed(DecodeError), #[error("Connection ended")] ConnEnded, + #[error("A subscribers name must be smaller then 256 bytes long")] + NameTooLong, + #[error("Could not send name to data-server: {0}")] + FailedToWriteName(std::io::Error), } diff --git a/crates/data-store/src/server/db/reconnecting.rs b/crates/data-server/src/subscriber/reconnecting.rs similarity index 55% rename from crates/data-store/src/server/db/reconnecting.rs rename to crates/data-server/src/subscriber/reconnecting.rs index 4e43bc51..0a783cf9 100644 --- a/crates/data-store/src/server/db/reconnecting.rs +++ b/crates/data-server/src/subscriber/reconnecting.rs @@ -1,24 +1,25 @@ -use data_server::subscriber::SubscribeError; -use tokio::time::sleep; -use tracing::{info, warn}; -use std::time::Duration; -use data_server::{AsyncSubscriber, SubMessage}; +use super::{AsyncSubscriber, SubMessage, SubscribeError}; use std::net::SocketAddr; +use std::time::Duration; +use tokio::time::{sleep, timeout}; +use tracing::{info, warn}; -pub(crate) struct ReconnectingSubscriber { - pub(crate) connection: Option, - pub(crate) addr: SocketAddr, +pub struct Subscriber { + connection: Option, + addr: SocketAddr, + name: String, } -impl ReconnectingSubscriber { - pub(crate) fn new(addr: SocketAddr) -> Self { +impl Subscriber { + pub fn new(addr: SocketAddr, name: String) -> Self { Self { connection: None, addr, + name, } } - pub(crate) async fn next_msg(&mut self) -> SubMessage { + pub async fn next_msg(&mut self) -> SubMessage { loop { let mut retry_period = Duration::from_millis(50); let mut conn = loop { @@ -26,12 +27,24 @@ impl ReconnectingSubscriber { break conn; } - match AsyncSubscriber::connect(self.addr).await { - Ok(conn) => { + match timeout( + Duration::from_millis(500), + AsyncSubscriber::connect(self.addr, &self.name), + ) + .await + { + Ok(Ok(conn)) => { info!("Successfully (re)connected to data-server"); break conn; } - Err(e) => warn!("Failed to (re)connect: {e}"), + Ok(Err(e)) => warn!( + "Failed to (re)connect: {e}\n\ + retrying in {retry_period:?}" + ), + Err(_) => warn!( + "Failed to (re)connect, timed out.\n\ + retrying in {retry_period:?}" + ), } sleep(retry_period).await; retry_period = (retry_period * 2).min(Duration::from_secs(5)); @@ -52,4 +65,3 @@ impl ReconnectingSubscriber { } } } - diff --git a/crates/data-server/tests/api.rs b/crates/data-server/tests/api.rs index 1f4e9182..973a0b48 100644 --- a/crates/data-server/tests/api.rs +++ b/crates/data-server/tests/api.rs @@ -1,3 +1,4 @@ +use std::net::SocketAddr; use std::time::Duration; use color_eyre::Result; @@ -19,11 +20,14 @@ enum Done { Test, } -async fn run_server(sub_port: u16, data_port: u16) -> Result { +async fn run_server( + sub_port: impl Into, + data_port: impl Into, +) -> Result { let (tx, rx) = mpsc::channel(2000); select! { - e = server::register_subs(sub_port, &tx) => e?, - e = server::handle_data_sources(data_port, &tx) => e?, + e = server::register_subs(sub_port.into(), &tx) => e?, + e = server::handle_data_sources(data_port.into(), &tx) => e?, e = server::spread_updates(rx) => e?, }; @@ -47,9 +51,10 @@ async fn send_sensor_value(data_port: u16) -> Result { async fn subscribe_and_receive(sub_port: u16) -> Result { tokio::time::sleep(Duration::from_millis(100)).await; - let mut sub = data_server::AsyncSubscriber::connect(("127.0.0.1", sub_port)) - .await - .unwrap(); + let mut sub = + data_server::AsyncSubscriber::connect(("127.0.0.1", sub_port), "api_integration_tests") + .await + .unwrap(); let received = sub.next_msg().await.unwrap(); dbg!(&received); assert!(matches!(received, SubMessage::Reading(TEST_READING))); @@ -62,7 +67,7 @@ async fn main() { let sub_port = reserve_port::ReservedPort::random().unwrap(); let data_port = reserve_port::ReservedPort::random().unwrap(); let res = select! { - e = run_server(sub_port.port(), data_port.port()) => e, + e = run_server(([127,0,0,1], sub_port.port()), ([127,0,0,1], data_port.port())) => e, e = send_sensor_value(data_port.port()) => e, e = subscribe_and_receive(sub_port.port()) => e, }; diff --git a/crates/data-store/src/main.rs b/crates/data-store/src/main.rs index 262fe85b..2af935d9 100644 --- a/crates/data-store/src/main.rs +++ b/crates/data-store/src/main.rs @@ -4,7 +4,7 @@ use std::path::PathBuf; use clap::Parser; use color_eyre::eyre::Result; -#[derive(Parser)] +#[derive(Parser, Debug)] #[command(name = "data server")] #[command(version = "1.0")] #[command(about = "Receives sensor events and spreads those to subscribed services")] @@ -24,6 +24,8 @@ struct Cli { async fn main() -> Result<()> { setup_tracing().unwrap(); let cli = Cli::parse(); + tracing::info!("started data-server, args: {cli:?}"); + data_store::server::run(cli.data_server, cli.client_port, &cli.data_dir).await } diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index 3e85d28c..41cfc1da 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -3,6 +3,7 @@ use std::net::SocketAddr; use std::path::Path; use std::sync::Arc; +use data_server::subscriber::reconnecting; use time::OffsetDateTime; use tokio::sync::Mutex; @@ -14,12 +15,8 @@ use series::Series; use crate::api; -mod reconnecting; -use reconnecting::ReconnectingSubscriber; - pub(crate) async fn run(data_server_addr: SocketAddr, data: Data, data_dir: &Path) -> Result<()> { - tracing::warn!("testing"); - let mut sub = ReconnectingSubscriber::new(data_server_addr); + let mut sub = reconnecting::Subscriber::new(data_server_addr, "ha-data-store".to_string()); loop { let msg = sub.next_msg().await; @@ -30,7 +27,6 @@ pub(crate) async fn run(data_server_addr: SocketAddr, data: Data, data_dir: &Pat SubMessage::ErrorReport(_) => continue, }; - if let Err(e) = res { tracing::error!("Error processing new reading: {e:?}"); } diff --git a/crates/data-store/tests/list_data.rs b/crates/data-store/tests/list_data.rs index f8d7fe9a..801ef6b1 100644 --- a/crates/data-store/tests/list_data.rs +++ b/crates/data-store/tests/list_data.rs @@ -23,13 +23,13 @@ const fn test_readings(v: f32) -> [Reading; 2] { ] } -async fn data_server(sub_port: u16, data_port: u16) { +async fn data_server(sub_port: impl Into, data_port: impl Into) { use data_server::server; let (tx, rx) = mpsc::channel(2000); tokio::select! { - e = server::register_subs(sub_port, &tx) => e.unwrap(), - e = server::handle_data_sources(data_port, &tx) => e.unwrap(), + e = server::register_subs(sub_port.into(), &tx) => e.unwrap(), + e = server::handle_data_sources(data_port.into(), &tx) => e.unwrap(), e = server::spread_updates(rx) => e.unwrap(), }; } @@ -136,7 +136,10 @@ async fn list_data() { let data_store_addr = SocketAddr::from(([127, 0, 0, 1], store_port.port())); let data_send = Notify::new(); - let run_data_server = data_server(sub_port.port(), data_port.port()); + let run_data_server = data_server( + ([127, 0, 0, 1], sub_port.port()), + ([127, 0, 0, 1], data_port.port()), + ); let run_data_store = sleep(DATA_SERVER_STARTUP).then(|()| { data_store::server::run(data_server_addr, data_store_addr.port(), test_dir.path()) }); @@ -178,7 +181,10 @@ async fn read_data() { let data_send = Notify::new(); let sensor_values = [0.5]; // let sensor_values = [0.0, 0.1, 0.2, 0.3]; - let run_data_server = data_server(sub_port.port(), data_port.port()); + let run_data_server = data_server( + ([127, 0, 0, 1], sub_port.port()), + ([127, 0, 0, 1], data_port.port()), + ); let run_data_store = sleep(DATA_SERVER_STARTUP).then(|()| { data_store::server::run(data_server_addr, data_store_addr.port(), test_dir.path()) }); diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index e0986dc4..a72b865a 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -58,7 +58,7 @@ fn main() -> Result<()> { data_store, } = Cli::parse(); - let sub = data_server::Subscriber::connect(data_server) + let sub = data_server::Subscriber::connect(data_server, "ha-tui") .wrap_err("failed to connect") .with_suggestion(|| format!("verify the server is listening on: {data_server}"))?; From 2e28d2c173cbcb57691b58764bd18bb02ab484e0 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 16 Jul 2024 16:56:15 +0200 Subject: [PATCH 155/687] add missing feature --- crates/data-server/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index 6ee9d04a..fe3535bb 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -16,7 +16,7 @@ tracing = { workspace = true } tracing-error = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } -protocol = { workspace = true, features = ["alloc"] } +protocol = { workspace = true, features = ["alloc", "thiserror"] } tokio = { workspace = true, features = ["rt", "macros", "net", "sync", "io-util"] } tokio-stream = { version = "0.1.15", features = ["net"] } thiserror = "1.0.61" From c81898473917e8985db78fc40645ad8012ed1ee4 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 16 Jul 2024 18:31:48 +0200 Subject: [PATCH 156/687] replaces comparing 'zeroed' readings with method --- crates/data-store/src/server/db/series.rs | 11 ++++---- crates/protocol/src/button.rs | 9 +++++++ crates/protocol/src/large_bedroom/bed.rs | 27 +++++++++++++++++++ crates/protocol/src/large_bedroom/desk.rs | 13 +++++++++ crates/protocol/src/reading_tree.rs | 19 +++++++++++++- crates/protocol/src/small_bedroom.rs | 32 ++++++++++++++--------- 6 files changed, 92 insertions(+), 19 deletions(-) diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index 4903ecec..0bab2e73 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -162,13 +162,14 @@ impl Series { .map(|requested| { self.meta .iter() - .find(|meta| *requested == meta.reading) + .find(|meta| requested.is_same_as(&meta.reading)) .inspect(|meta| info!("meta used for decoding: {meta:?}")) .map(|meta| meta.field.clone()) - .expect( - "caller of read makes sure all readings are\ - part of this series", - ) + .expect(&format!( + "caller of read makes sure all readings are part of this \ + series.\n\tseries: {:?},\n\trequested: {:?}", + self.meta, readings + )) }) .collect(); let mut resampler = Resampler::from_fields(fields, self.line.len()); diff --git a/crates/protocol/src/button.rs b/crates/protocol/src/button.rs index b9594b82..18fc919f 100644 --- a/crates/protocol/src/button.rs +++ b/crates/protocol/src/button.rs @@ -97,6 +97,15 @@ macro_rules! button_enum { discriminant as crate::reading_tree::Id } } + + impl $name { + pub fn is_same_as(&self, other: &Self) -> bool { + match (self, other) { + $(($name::$variant(_), $name::$variant(_)) => true,)* + (_, _) => false, + } + } + } }; } pub(crate) use button_enum; diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 09dba205..46dad32a 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -256,6 +256,33 @@ impl Tree for Reading { } } +impl Reading { + pub fn is_same_as(&self, other: &Self) -> bool { + match (self, other) { + (Self::Brightness(_), Self::Brightness(_)) => true, + (Self::Temperature(_), Self::Temperature(_)) => true, + (Self::Humidity(_), Self::Humidity(_)) => true, + (Self::GassResistance(_), Self::GassResistance(_)) => true, + (Self::Pressure(_), Self::Pressure(_)) => true, + (Self::Co2(_), Self::Co2(_)) => true, + (Self::WeightLeft(_), Self::WeightLeft(0)) => true, + (Self::WeightRight(_), Self::WeightRight(0)) => true, + (Self::MassPm1_0(_), Self::MassPm1_0(_)) => true, + (Self::MassPm2_5(_), Self::MassPm2_5(_)) => true, + (Self::MassPm4_0(_), Self::MassPm4_0(_)) => true, + (Self::MassPm10(_), Self::MassPm10(_)) => true, + (Self::NumberPm0_5(_), Self::NumberPm0_5(_)) => true, + (Self::NumberPm1_0(_), Self::NumberPm1_0(_)) => true, + (Self::NumberPm2_5(_), Self::NumberPm2_5(_)) => true, + (Self::NumberPm4_0(_), Self::NumberPm4_0(_)) => true, + (Self::NumberPm10(_), Self::NumberPm10(_)) => true, + (Self::TypicalParticleSize(_), Self::TypicalParticleSize(_)) => true, + (Self::Button(a), Self::Button(b)) => a.is_same_as(b), + _ => false, + } + } +} + #[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] pub enum Error { Running(SensorError), diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index 43dee952..8a0005bd 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -84,6 +84,19 @@ impl Tree for Reading { } } +impl Reading { + #[must_use] + pub fn is_same_as(&self, other: &Self) -> bool { + match (self, other) { + (Reading::Temperature(_), Self::Temperature(_)) => true, + (Reading::Humidity(_), Self::Humidity(_)) => true, + (Reading::Pressure(_), Self::Pressure(_)) => true, + (Reading::Button(a), Self::Button(b)) => a.is_same_as(b), + _ => false, + } + } +} + #[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] pub enum Error { Running(SensorError), diff --git a/crates/protocol/src/reading_tree.rs b/crates/protocol/src/reading_tree.rs index 202b71d7..e8c4def9 100644 --- a/crates/protocol/src/reading_tree.rs +++ b/crates/protocol/src/reading_tree.rs @@ -49,6 +49,22 @@ pub trait Tree: core::fmt::Debug { fn branch_id(&self) -> Id; } +macro_rules! impl_zero { + ($name:ident; $($var:ident),*) => { + impl $name { + #[must_use] + pub fn is_same_as(&self, other: &Self) -> bool { + match (self, other) { + $(($name::$var(a), $name::$var(b)) => a.is_same_as(b),)* + (_, _) => false, + } + } + } + + }; +} +pub(crate) use impl_zero; + macro_rules! all_nodes { ($name:ident; $variant:ident; $($var:ident),*) => { impl crate::reading_tree::Tree for $name { @@ -63,8 +79,9 @@ macro_rules! all_nodes { fn branch_id(&self) -> crate::reading_tree::Id { $variant::from(self) as crate::reading_tree::Id } + } + crate::reading_tree::impl_zero!{$name; $($var),*} }; } - pub(crate) use all_nodes; diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index 7b29b6c4..168f7c22 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -23,7 +23,15 @@ crate::button_enum! { } #[derive( - strum::EnumDiscriminants, Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, PartialEq, + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, )] pub enum Reading { ButtonPanel(ButtonPanel), @@ -42,17 +50,15 @@ impl Tree for Reading { } } -#[derive( - Clone, - Debug, - defmt::Format, - Serialize, - Deserialize, - MaxSize, - Hash, - PartialEq, - Eq, -)] +impl Reading { + pub fn is_same_as(&self, other: &Self) -> bool { + match (self, other) { + (Self::ButtonPanel(a), Self::ButtonPanel(b)) => a.is_same_as(b) + } + } +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Hash, PartialEq, Eq)] pub enum Device { Gpio, } @@ -75,7 +81,7 @@ impl Device { ButtonPanel::BottomLeft(Press(0)), ButtonPanel::BottomMiddle(Press(0)), ButtonPanel::BOttomRight(Press(0)) - ], + ] } } From 2bd7729afbe3e33dd32abbbb40d40cc5e83210b2 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 17 Jul 2024 22:39:20 +0200 Subject: [PATCH 157/687] add example that fetches data from last 15m --- Cargo.lock | 53 +++++++++++++++++++++ crates/data-store/Cargo.toml | 2 + crates/data-store/examples/last_15m.rs | 65 ++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 crates/data-store/examples/last_15m.rs diff --git a/Cargo.lock b/Cargo.lock index ae347342..586b6263 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -784,6 +784,16 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + [[package]] name = "crossbeam-epoch" version = "0.9.18" @@ -850,6 +860,8 @@ dependencies = [ "data-server", "futures", "futures-concurrency", + "nucleo", + "nucleo-matcher", "num", "protocol", "reserve-port", @@ -1949,6 +1961,27 @@ dependencies = [ "winapi", ] +[[package]] +name = "nucleo" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5262af4c94921c2646c5ac6ff7900c2af9cbb08dc26a797e18130a7019c039d4" +dependencies = [ + "nucleo-matcher", + "parking_lot 0.12.3", + "rayon", +] + +[[package]] +name = "nucleo-matcher" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf33f538733d1a5a3494b836ba913207f14d9d4a1d3cd67030c5061bdd2cac85" +dependencies = [ + "memchr", + "unicode-segmentation", +] + [[package]] name = "num" version = "0.4.3" @@ -2370,6 +2403,26 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.2.16" diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index ece76e32..be537d96 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -33,8 +33,10 @@ thiserror = { workspace = true } futures = "0.3.30" smallvec = "2.0.0-alpha.6" num = "0.4.3" +nucleo-matcher = "0.3.1" [dev-dependencies] futures-concurrency = "7.6.1" +nucleo = "0.5.0" reserve-port = "2.0.1" temp-dir = "0.1.13" diff --git a/crates/data-store/examples/last_15m.rs b/crates/data-store/examples/last_15m.rs new file mode 100644 index 00000000..6a8a4c85 --- /dev/null +++ b/crates/data-store/examples/last_15m.rs @@ -0,0 +1,65 @@ +use nucleo_matcher::pattern::Pattern; +use protocol::Reading; +use std::net::SocketAddr; + +use data_store::api::Client; +use nucleo::pattern::{AtomKind, CaseMatching, Normalization}; +use time::{Duration, OffsetDateTime}; + +use clap::Parser; + +#[derive(Parser)] +#[command(version, about, long_about = None)] +struct Cli { + /// the address of the store + #[arg(short, long, default_value_t = SocketAddr::from(([127,0,0,1], 1236)))] + addr: SocketAddr, + reading: String, +} + +fn to_path(reading: &Reading) -> String { + let path = format!("{:?}", reading); + let (path, _) = path.rsplit_once('(').unwrap(); + let path = path.replace('(', " "); + path +} + +#[tokio::main] +async fn main() { + let cli = Cli::parse(); + let mut client = Client::connect(cli.addr).await.unwrap(); + let readings = client.list_data().await.unwrap(); + + let mut matcher = nucleo_matcher::Matcher::new(nucleo_matcher::Config::DEFAULT); + let pattern = Pattern::new( + &cli.reading, + CaseMatching::Ignore, + Normalization::Smart, + AtomKind::Fuzzy, + ); + + let mut buf = Vec::new(); + let best_scored = readings + .into_iter() + .map(|r| { + ( + pattern.score( + nucleo::Utf32Str::new(to_path(&r).as_str(), &mut buf), + &mut matcher, + ), + r, + ) + }) + .max_by_key(|(score, _)| score.unwrap_or(0)) + .unwrap() + .1; + + println!("Showing results for: {best_scored:?}"); + let now = OffsetDateTime::now_utc(); + let data = client + .get_data(now - Duration::minutes(60), now, best_scored, 10) + .await + .unwrap(); + + dbg!(data); +} From 0531a73497df241da349efb50cf2b55787195e69 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 17 Jul 2024 22:48:55 +0200 Subject: [PATCH 158/687] fix encoding (line was not cleared) --- crates/data-server/src/subscriber.rs | 3 +-- crates/data-store/src/server/db.rs | 2 -- crates/data-store/src/server/db/series.rs | 3 +-- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/crates/data-server/src/subscriber.rs b/crates/data-server/src/subscriber.rs index 86c305ea..5e0f0a1b 100644 --- a/crates/data-server/src/subscriber.rs +++ b/crates/data-server/src/subscriber.rs @@ -5,7 +5,7 @@ use std::vec; use protocol::{DecodeError, Msg}; use tokio::io::{AsyncBufReadExt, AsyncWriteExt}; -use tracing::{instrument, trace}; +use tracing::instrument; pub mod reconnecting; @@ -121,7 +121,6 @@ fn decode_buffer_and_return_first( buf.resize(n_read, 0); // ensure stop delimiter in bytes let bytes = &mut buf[0..n_read]; - trace!("New message from data-server to decode, bytes: {bytes:?}"); let decoded: Msg<50> = Msg::decode(bytes).map_err(SubscribeError::DecodeFailed)?; match decoded { Msg::Readings(readings) => { diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index 41cfc1da..f906d72c 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -20,8 +20,6 @@ pub(crate) async fn run(data_server_addr: SocketAddr, data: Data, data_dir: &Pat loop { let msg = sub.next_msg().await; - tracing::trace!("got msg: {msg:?}"); - let res = match msg { SubMessage::Reading(reading) => series::store(&data, &reading, data_dir).await, SubMessage::ErrorReport(_) => continue, diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index 0bab2e73..1a75f5f7 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -140,7 +140,7 @@ impl Series { self.byteseries .push_line(time.unix_timestamp() as u64, &self.line) .wrap_err("Could not write to timeseries on disk")?; - tracing::debug!("encoded data stored in byteseries"); + self.line.fill(0); } Ok(()) @@ -264,7 +264,6 @@ fn try_create_new_if_open_failed( #[instrument(level = "debug", skip(data))] pub(crate) async fn store(data: &Data, reading: &protocol::Reading, data_dir: &Path) -> Result<()> { - tracing::debug!("storing received reading: {reading:?}"); let mut data = data.0.lock().await; let key = reading.device(); From 127c071022863213e6c2418a6296f9feb8d48ea6 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 18 Jul 2024 23:50:59 +0200 Subject: [PATCH 159/687] add precision method to reading_tree::Item and make Unit printable --- Cargo.lock | 94 +++++++++++--------------- crates/data-store/Cargo.toml | 3 +- crates/data-store/examples/last_15m.rs | 2 +- crates/protocol/src/lib.rs | 19 ++++++ crates/protocol/src/reading_tree.rs | 23 +++++++ 5 files changed, 82 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 586b6263..31e91fc5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -149,9 +149,9 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8828ec6e544c02b0d6691d21ed9f9218d0384a82542855073c2a3f58304aaf0" +checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" dependencies = [ "async-task", "concurrent-queue", @@ -253,9 +253,9 @@ dependencies = [ [[package]] name = "async-signal" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "794f185324c2f00e771cd9f1ae8b5ac68be2ca7abb129a87afd6e86d228bc54d" +checksum = "dfb3634b73397aa844481f814fad23bbf07fdb0eabec10f2eb95e58944b1ec32" dependencies = [ "async-io 2.3.3", "async-lock 3.4.0", @@ -564,7 +564,7 @@ checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" [[package]] name = "byteseries" -version = "0.4.0" +version = "0.5.0" dependencies = [ "arraydeque", "itertools", @@ -784,16 +784,6 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - [[package]] name = "crossbeam-epoch" version = "0.9.18" @@ -860,7 +850,6 @@ dependencies = [ "data-server", "futures", "futures-concurrency", - "nucleo", "nucleo-matcher", "num", "protocol", @@ -1306,6 +1295,16 @@ dependencies = [ "byteorder", ] +[[package]] +name = "gethostname" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc3655aa6818d65bc620d6911f05aa7b6aeb596291e1e9f79e52df85583d1e30" +dependencies = [ + "rustix 0.38.34", + "windows-targets 0.52.6", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -1961,17 +1960,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "nucleo" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5262af4c94921c2646c5ac6ff7900c2af9cbb08dc26a797e18130a7019c039d4" -dependencies = [ - "nucleo-matcher", - "parking_lot 0.12.3", - "rayon", -] - [[package]] name = "nucleo-matcher" version = "0.3.1" @@ -2147,7 +2135,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.5.2", + "redox_syscall 0.5.3", "smallvec 1.13.2", "windows-targets 0.52.6", ] @@ -2403,26 +2391,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - [[package]] name = "redox_syscall" version = "0.2.16" @@ -2434,9 +2402,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ "bitflags 2.6.0", ] @@ -2935,20 +2903,34 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f227968ec00f0e5322f9b8173c7a0cbcff6181a0a5b28e9892491c286277231" +[[package]] +name = "text-widget" +version = "0.1.0" +dependencies = [ + "clap", + "color-eyre", + "data-server", + "data-store", + "gethostname", + "nucleo-matcher", + "protocol", + "tokio", +] + [[package]] name = "thiserror" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", @@ -3012,9 +2994,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.0" +version = "1.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" dependencies = [ "backtrace", "bytes", diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index be537d96..b9a662fe 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -33,10 +33,9 @@ thiserror = { workspace = true } futures = "0.3.30" smallvec = "2.0.0-alpha.6" num = "0.4.3" -nucleo-matcher = "0.3.1" [dev-dependencies] futures-concurrency = "7.6.1" -nucleo = "0.5.0" +nucleo-matcher = "0.3.1" reserve-port = "2.0.1" temp-dir = "0.1.13" diff --git a/crates/data-store/examples/last_15m.rs b/crates/data-store/examples/last_15m.rs index 6a8a4c85..6562339e 100644 --- a/crates/data-store/examples/last_15m.rs +++ b/crates/data-store/examples/last_15m.rs @@ -57,7 +57,7 @@ async fn main() { println!("Showing results for: {best_scored:?}"); let now = OffsetDateTime::now_utc(); let data = client - .get_data(now - Duration::minutes(60), now, best_scored, 10) + .get_data(now - Duration::minutes(5), now, best_scored, 10) .await .unwrap(); diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 6ddb5310..10fc2f75 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -1,6 +1,8 @@ #![cfg_attr(not(feature = "alloc"), no_std)] #![allow(clippy::missing_panics_doc, clippy::missing_errors_doc)] +use core::fmt::Display; + use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -27,6 +29,23 @@ pub enum Unit { None, // for buttons } +impl Display for Unit { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Unit::Pa => f.write_str("Pa"), + Unit::C => f.write_str("°C"), + Unit::RH => f.write_str("%RH"), + Unit::Lux => f.write_str("lx"), + Unit::Ohm => f.write_str("Ω"), + Unit::Ppm => f.write_str("ppm"), + Unit::MicrogramPerM3 => f.write_str("µg/m³"), + Unit::NumberPerCm3 => f.write_str("#/cm³"), + Unit::NanoMeter => f.write_str("nm"), + Unit::None => f.write_str(""), + } + } +} + #[derive( strum::EnumDiscriminants, strum::VariantNames, diff --git a/crates/protocol/src/reading_tree.rs b/crates/protocol/src/reading_tree.rs index e8c4def9..4ec1ca95 100644 --- a/crates/protocol/src/reading_tree.rs +++ b/crates/protocol/src/reading_tree.rs @@ -4,6 +4,7 @@ use crate::{Device, Reading, Unit}; pub struct ReadingInfo { pub val: f32, pub device: Device, + /// smallest step size the data can make pub resolution: f32, pub range: core::ops::Range, pub unit: Unit, @@ -16,6 +17,28 @@ impl ReadingInfo { pub fn from_same_device(&self) -> &'static [Reading] { self.device.affected_readings() } + + /// useful for printing/formatting floats + /// # Example + /// ```rust + /// use crate::Reading; + /// use crate::large_bedroom; + /// use crate::large_bedroom::desk; + /// + /// let reading = + /// Reading::LargeBedroom(large_bedroom::Reading(desk::Reading::Temperature(22.428124); + /// + /// let info = reading.leaf(); + /// let printed = format!("{0:.1$}", info.val, info.precision()); + /// assert_eq!(printed, "22.42"); + /// ``` + pub fn precision(&self) -> usize { + if self.resolution > 1.0 { + 0 + } else { + self.resolution.log10().abs() as usize + } + } } pub type Id = u8; From 1645b43a543a374fc59b48c7d1908eb9d5606cc5 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 18 Jul 2024 23:51:15 +0200 Subject: [PATCH 160/687] sway bar app that shows any reading (fuzzy find) --- crates/text-widget/Cargo.toml | 17 +++++ crates/text-widget/src/main.rs | 112 +++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 crates/text-widget/Cargo.toml create mode 100644 crates/text-widget/src/main.rs diff --git a/crates/text-widget/Cargo.toml b/crates/text-widget/Cargo.toml new file mode 100644 index 00000000..e9d76a79 --- /dev/null +++ b/crates/text-widget/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "text-widget" +version = "0.1.0" +rust-version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true + +[dependencies] +clap.workspace = true +color-eyre = { workspace = true } +protocol = { workspace = true, features = ["alloc", "thiserror"] } +data-server = { workspace = true } +data-store = { workspace = true } +nucleo-matcher = "0.3.1" +tokio = { workspace = true} +gethostname = "0.5.0" diff --git a/crates/text-widget/src/main.rs b/crates/text-widget/src/main.rs new file mode 100644 index 00000000..a2d73cdd --- /dev/null +++ b/crates/text-widget/src/main.rs @@ -0,0 +1,112 @@ +use data_server::subscriber::reconnecting; +use data_server::SubMessage; +use gethostname::gethostname; +use nucleo_matcher::pattern::Pattern; +use protocol::reading_tree::Tree; +use protocol::Reading; +use std::net::SocketAddr; + +use data_store::api::Client; +use nucleo_matcher::pattern::{AtomKind, CaseMatching, Normalization}; + +use clap::Parser; + +#[derive(Parser)] +#[command(version, about, long_about = None)] +struct Cli { + /// the address of the store + #[arg(long, default_value_t = SocketAddr::from(([127,0,0,1], 1236)))] + store: SocketAddr, + + /// the address of the store + #[arg(long, default_value_t = SocketAddr::from(([127,0,0,1], 1235)))] + server: SocketAddr, + + /// print json format: {"msg": "reading value"} + #[arg(short, long)] + json: bool, + + /// String describing the reading. Something like temp can resolve to + /// `large_bedroom desk temperature` + reading: String, + + /// prints the resolved string + #[arg(short, long)] + debug: bool, +} + +fn to_path(reading: &Reading) -> String { + let path = format!("{:?}", reading); + let (path, _) = path + .rsplit_once('(') + .expect("Reading is tree with at least deph 2"); + let path = path.replace('(', " "); + path +} + +fn resolve_argument(description: &str, options: &[Reading]) -> Reading { + let mut matcher = nucleo_matcher::Matcher::new(nucleo_matcher::Config::DEFAULT); + let pattern = Pattern::new( + description, + CaseMatching::Ignore, + Normalization::Smart, + AtomKind::Fuzzy, + ); + + let mut buf = Vec::new(); + let best_scored = options + .into_iter() + .map(|r| { + ( + pattern.score( + nucleo_matcher::Utf32Str::new(to_path(&r).as_str(), &mut buf), + &mut matcher, + ), + r, + ) + }) + .max_by_key(|(score, _)| score.unwrap_or(0)) + .unwrap() + .1; + best_scored.clone() +} + +async fn wait_for_update(client: &mut reconnecting::Subscriber, needed: &Reading) -> Reading { + loop { + let SubMessage::Reading(r) = client.next_msg().await else { + continue; + }; + if r.is_same_as(needed) { + return r; + } + } +} + +#[tokio::main] +async fn main() { + let cli = Cli::parse(); + let mut client = Client::connect(cli.store).await.unwrap(); + let readings = client.list_data().await.unwrap(); + + let reading = resolve_argument(&cli.reading, &readings); + if cli.debug { + eprintln!("Will be showing: {reading:?}"); + } + + let host = gethostname(); + let host = host.to_string_lossy(); + let name = format!("text-widget@{host}"); + let mut client = reconnecting::Subscriber::new(cli.server, name); + + loop { + let new = wait_for_update(&mut client, &reading).await; + let info = new.leaf(); + let to_print = format!("{0:.1$}{2}", info.val, info.precision(), info.unit); + let use_json = cli.json; + if use_json { + println!("{{\"msg\": \"{to_print}\"}}"); + } else { + println!("{to_print}"); + } + } +} From c5982f45ff45e18264f2a5cead274997bb63dbb3 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 20 Jul 2024 22:20:56 +0200 Subject: [PATCH 161/687] tui graph x bounds can be changed using 'b' --- Cargo.lock | 1 + crates/sensor-tui/Cargo.toml | 1 + crates/sensor-tui/src/main.rs | 2 +- crates/sensor-tui/src/tui.rs | 249 ++++++++++++------ crates/sensor-tui/src/tui/history_len.rs | 113 ++++++++ .../src/tui/history_len/parse_duration.rs | 106 ++++++++ crates/sensor-tui/src/tui/reading.rs | 84 ++---- crates/sensor-tui/src/tui/reading/fetch.rs | 154 +++++++++++ crates/sensor-tui/src/tui/render.rs | 49 ++-- crates/text-widget/src/main.rs | 2 +- 10 files changed, 590 insertions(+), 171 deletions(-) create mode 100644 crates/sensor-tui/src/tui/history_len.rs create mode 100644 crates/sensor-tui/src/tui/history_len/parse_duration.rs create mode 100644 crates/sensor-tui/src/tui/reading/fetch.rs diff --git a/Cargo.lock b/Cargo.lock index 31e91fc5..e381a225 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2588,6 +2588,7 @@ dependencies = [ "histogram", "protocol", "ratatui", + "thiserror", "time", "tokio", "tracing", diff --git a/crates/sensor-tui/Cargo.toml b/crates/sensor-tui/Cargo.toml index 25fa6691..f9bf77b1 100644 --- a/crates/sensor-tui/Cargo.toml +++ b/crates/sensor-tui/Cargo.toml @@ -23,3 +23,4 @@ protocol = { workspace = true, features = ["alloc"] } data-server = { workspace = true } data-store = { workspace = true } time = { workspace = true } +thiserror.workspace = true diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index a72b865a..59d41798 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -46,7 +46,7 @@ struct Cli { data_server: SocketAddr, /// server where we can fetch historical sensor data - #[arg(short='s', long, default_value_t = SocketAddr::from(([127,0,0,1], 1236)))] + #[arg(short='s', long, default_value_t = SocketAddr::from(([192,168,1,43], 1236)))] data_store: SocketAddr, } diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index feabe126..2f451915 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -1,5 +1,5 @@ use crossterm::{ - event::{self, KeyCode, KeyEventKind, KeyModifiers}, + event::{self, KeyCode, KeyEvent, KeyEventKind, KeyModifiers}, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, ExecutableCommand, }; @@ -14,10 +14,16 @@ use tui_tree_widget::TreeState; mod reading; use reading::Readings; mod render; -use crate::{trace_dbg, Update}; +use crate::Update; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +mod history_len; +use history_len::HistoryLen; + +use self::reading::TreeKey; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] enum ActiveList { + #[default] Readings, Actuators, } @@ -39,101 +45,176 @@ impl ActiveList { } } +#[derive(Debug, Default, Clone, Copy)] +enum InputMode { + #[default] + Normal, + EditingBounds, +} + pub fn run( rx: mpsc::Receiver, shutdown_tx: mpsc::Sender>, - data_store: SocketAddr + data_store: SocketAddr, ) -> Result<(), std::io::Error> { - let mut readings = Readings { - ground: Vec::new(), - data: HashMap::new(), - }; - - stdout().execute(EnterAlternateScreen)?; - enable_raw_mode()?; - let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; - terminal.clear()?; - - let mut active_list = ActiveList::Readings; - let mut reading_list_state = TreeState::default(); - let mut actuator_list_state = ListState::default(); - let actuators = vec![ - "placeholder 1".to_owned(), - "placeholder 2".to_owned(), - "placeholder 3".to_owned(), - ]; - let mut plot_buf = Vec::new(); - - loop { - let data = reading_list_state.selected() - .last() // unique leaf id - .and_then(|key| readings.data.get_mut(key)); - - let (chart, histogram) = if let Some(data) = data { - (data.chart(&mut plot_buf, data_store), data.histogram()) - } else { - (None, readings.histogram_all()) + App::default().run(rx, shutdown_tx, data_store) +} + +#[derive(Default)] +struct App { + input_mode: InputMode, + active_list: ActiveList, + show_histogram: bool, + reading_list_state: TreeState, + history_length: HistoryLen, +} + +impl App { + pub fn run( + &mut self, + rx: mpsc::Receiver, + shutdown_tx: mpsc::Sender>, + data_store: SocketAddr, + ) -> Result<(), std::io::Error> { + let mut readings = Readings { + ground: Vec::new(), + data: HashMap::new(), }; - terminal.draw(|frame| { - render::all( - frame, - &readings.ground, - &mut reading_list_state, - actuators.clone(), - &mut actuator_list_state, - active_list, - &histogram, - chart, - ); - })?; - - if reading_list_state.selected().is_empty() { - reading_list_state.select_first(); - } + stdout().execute(EnterAlternateScreen)?; + enable_raw_mode()?; + let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; + terminal.clear()?; - if event::poll(Duration::from_millis(16))? { - if let event::Event::Key(key) = event::read()? { - tracing::trace!("key pressed: {key:?}"); - if key.kind == KeyEventKind::Press { - if key.code == KeyCode::Char('q') { - break; - } - if key.code == KeyCode::Char('c') - && key.modifiers.contains(KeyModifiers::CONTROL) - { - break; - } - if key.code == KeyCode::Left { - active_list = active_list.swap(); - } - if key.code == KeyCode::Right { - active_list = active_list.swap(); - } - if key.code == KeyCode::Down { - reading_list_state.key_down(); - } - if key.code == KeyCode::Up { - reading_list_state.key_up(); - } - if key.code == KeyCode::Enter { - reading_list_state.toggle_selected(); + let mut actuator_list_state = ListState::default(); + let actuators = vec![ + "placeholder 1".to_owned(), + "placeholder 2".to_owned(), + "placeholder 3".to_owned(), + ]; + let mut plot_buf = Vec::new(); + + loop { + let data = self + .reading_list_state + .selected() + .last() // unique leaf id + .and_then(|key| readings.data.get_mut(key)); + + let plot_open = data.is_some(); + let (chart, histogram) = if let Some(data) = data { + data.stored_history.update_if_needed( + data_store, + data.reading.clone(), + &mut self.history_length, + ); + (data.chart(&mut plot_buf), data.histogram()) + } else { + (None, readings.histogram_all()) + }; + + terminal.draw(|frame| { + render::all( + frame, + &readings.ground, + &mut self.reading_list_state, + actuators.clone(), + &mut actuator_list_state, + self.active_list, + &histogram, + chart, + &self.history_length, + ); + })?; + + if self.reading_list_state.selected().is_empty() { + self.reading_list_state.select_first(); + } + + if event::poll(Duration::from_millis(16))? { + if let event::Event::Key(key) = event::read()? { + tracing::trace!("key pressed: {key:?}"); + if key.kind == KeyEventKind::Press { + let res = match self.input_mode { + InputMode::Normal => self.handle_key_normal_mode(key, plot_open), + InputMode::EditingBounds => self.handle_key_bounds_mode(key), + }; + + if let ShouldExit::Yes = res { + break; + } } } + }; + + match rx.try_recv() { + Ok(Update::Reading(reading)) => { + readings.add(reading); + } + Ok(Update::Error(err)) => readings.add_error(err), + _ => (), } } - match rx.try_recv() { - Ok(Update::Reading(reading)) => { - readings.add(reading); + stdout().execute(LeaveAlternateScreen)?; + disable_raw_mode()?; + shutdown_tx.send(Ok(Update::Shutdown)).unwrap(); + Ok(()) + } + + fn handle_key_normal_mode(&mut self, key: KeyEvent, plot_open: bool) -> ShouldExit { + match key.code { + KeyCode::Char('q') => { + return ShouldExit::Yes; + } + KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => { + return ShouldExit::Yes; + } + KeyCode::Left => { + self.active_list = self.active_list.swap(); + } + KeyCode::Right => { + self.active_list = self.active_list.swap(); + } + KeyCode::Down => { + self.reading_list_state.key_down(); + } + KeyCode::Up => { + self.reading_list_state.key_up(); } - Ok(Update::Error(err)) => readings.add_error(err), - _ => (), + KeyCode::Enter => { + self.reading_list_state.toggle_selected(); + } + KeyCode::Char('b') => { + if plot_open { + self.history_length.start_editing(); + self.input_mode = InputMode::EditingBounds; + } + } + KeyCode::Char('h') => { + self.show_histogram = !self.show_histogram; + } + _other => (), + } + ShouldExit::No + } + + fn handle_key_bounds_mode(&mut self, key: KeyEvent) -> ShouldExit { + match key.code { + KeyCode::Esc => { + self.history_length.exit_editing(); + self.input_mode = InputMode::Normal; + } + KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => { + return ShouldExit::Yes; + } + other => self.history_length.process(other), } + ShouldExit::No } +} - stdout().execute(LeaveAlternateScreen)?; - disable_raw_mode()?; - shutdown_tx.send(Ok(Update::Shutdown)).unwrap(); - Ok(()) +enum ShouldExit { + Yes, + No, } diff --git a/crates/sensor-tui/src/tui/history_len.rs b/crates/sensor-tui/src/tui/history_len.rs new file mode 100644 index 00000000..e4cde187 --- /dev/null +++ b/crates/sensor-tui/src/tui/history_len.rs @@ -0,0 +1,113 @@ +use crossterm::event::KeyCode; +use ratatui::{ + style::{Color, Modifier, Style}, + text::Span, +}; +use std::time::Duration; + +mod parse_duration; +use parse_duration::parse_duration; + +use self::parse_duration::fmt_dur; + +#[derive(Debug, Clone, Copy)] +pub enum State { + Empty, + Invalid, + Valid, + Fetching, + Fetched, +} + +pub struct HistoryLen { + pub text_input: String, + pub editing: bool, + pub state: State, + pub dur: Duration, +} + +impl Default for HistoryLen { + fn default() -> Self { + let dur = Duration::from_secs(15 * 60); + let text_input = fmt_dur(dur); + Self { + text_input, + editing: false, + state: State::Empty, + dur, + } + } +} + +impl HistoryLen { + pub(crate) fn process(&mut self, key: KeyCode) { + match key { + KeyCode::Char(c) => { + self.text_input.push(c); + } + KeyCode::Backspace => { + self.text_input.pop(); + } + _other => (), + } + + if let Ok(dur) = parse_duration(&self.text_input) { + self.state = State::Valid; + self.dur = dur; + } else if self.text_input.is_empty() { + self.state = State::Empty; + } else { + self.state = State::Invalid; + } + } + + pub(crate) fn render_x_label(&self, upper_x_bound: f64) -> Span { + let mut text = self.text_input.clone(); + if self.editing { + text.push_str("_"); + } + match self.state { + State::Empty => { + let style = Style::default() + .fg(Color::Red) + .add_modifier(Modifier::SLOW_BLINK); + Span::raw(text).style(style) + } + State::Invalid => { + let style = Style::default() + .fg(Color::Red) + .add_modifier(Modifier::ITALIC); + Span::raw(text).style(style) + } + State::Valid => { + let style = Style::default().add_modifier(Modifier::ITALIC); + Span::raw(text).style(style) + } + State::Fetching => { + let style = Style::default().add_modifier(Modifier::ITALIC); + text.push_str(" (fetching)"); + Span::raw(text).style(style) + } + State::Fetched => { + if self.editing { + Span::raw(text) + } else { + Span::raw(fmt_dur(Duration::from_secs_f64(upper_x_bound))) + } + } + } + } + + pub(crate) fn exit_editing(&mut self) { + self.editing = false; + self.state = match self.state { + State::Empty | State::Invalid => State::Fetched, + State::Valid | State::Fetching | State::Fetched => self.state, + } + } + + pub(crate) fn start_editing(&mut self) { + self.editing = true; + self.text_input.clear(); + } +} diff --git a/crates/sensor-tui/src/tui/history_len/parse_duration.rs b/crates/sensor-tui/src/tui/history_len/parse_duration.rs new file mode 100644 index 00000000..afbb2f00 --- /dev/null +++ b/crates/sensor-tui/src/tui/history_len/parse_duration.rs @@ -0,0 +1,106 @@ +use std::num::ParseFloatError; +use std::time::Duration; + +#[derive(Debug, thiserror::Error)] +pub enum ParseError { + #[error("Could not parse the seconds, input: {1}, error: {0}")] + Second(ParseFloatError, String), + #[error("Could not parse the minutes, input: {1}, error: {0}")] + Minute(ParseFloatError, String), + #[error("Could not parse the hours, input: {1}, error: {0}")] + Hour(ParseFloatError, String), + #[error("Durations need a suffix or one `:`")] + NoColonOrUnit(String), +} + +fn second_err(e: ParseFloatError, s: &str) -> ParseError { + ParseError::Second(e, s.to_owned()) +} +fn minute_err(e: ParseFloatError, s: &str) -> ParseError { + ParseError::Minute(e, s.to_owned()) +} +fn hour_err(e: ParseFloatError, s: &str) -> ParseError { + ParseError::Hour(e, s.to_owned()) +} + +/// Parses a string in format +/// hh:mm:ss, +/// mm:ss, +/// :ss, +pub(crate) fn parse_colon_duration(arg: &str) -> Result { + let Some((rest, seconds)) = arg.rsplit_once(':') else { + return Err(ParseError::NoColonOrUnit(arg.to_string())); + }; + + let mut seconds = seconds.parse().map_err(|e| second_err(e, arg))?; + if rest.is_empty() { + return Ok(seconds); + } + + let Some((hours, minutes)) = rest.rsplit_once(':') else { + let minutes: f32 = rest.parse().map_err(|e| minute_err(e, arg))?; + seconds += 60.0 * minutes; + return Ok(seconds); + }; + seconds += 60.0 * minutes.parse::().map_err(|e| minute_err(e, minutes))?; + if hours.is_empty() { + return Ok(seconds); + }; + seconds += 60.0 * 60.0 * hours.parse::().map_err(|e| hour_err(e, hours))?; + Ok(seconds) +} + +/// Parse a string in two different formats to a `Duration`. The formats are: +/// - 10h +/// - 15m +/// - 30s +/// - hh:mm:ss, +/// - mm:ss, +/// - :ss, +/// +/// suffixes like d (days), w (weeks) and y (years) are also supported +pub(crate) fn parse_duration(arg: &str) -> Result { + let suffix_and_factor = [ + ('y', 365 * 24 * 60 * 60), + ('w', 7 * 24 * 60 * 60), + ('d', 24 * 60 * 60), + ('h', 60 * 60), + ('m', 60), + ('s', 1), + ]; + + for (suffix, factor) in suffix_and_factor { + if let Some(num) = arg.strip_suffix(suffix) { + let num = num.parse::().map_err(|e| hour_err(e, num))?; + return Ok(std::time::Duration::from_secs_f32(num * factor as f32)); + } + } + let seconds = parse_colon_duration(arg)?; + Ok(std::time::Duration::from_secs_f32(seconds)) +} + +fn fmt_mm_hh(dur: Duration) -> String { + let mm = (dur.as_secs_f32() / 60.0).round() as u8 % 60; + let hh = (dur.as_secs_f32() / 60.0 / 60.0).round() as u8; + let days = (dur.as_secs_f32() / 60.0 / 60.0 / 24.0).round() as usize; + let weeks = (dur.as_secs_f32() / 60.0 / 60.0 / 24.0 / 7.0).round() as usize; + + if days > 21 { + format!("{weeks} weeks") + } else if hh > 72 { + format!("{days} days") + } else if hh == 0 { + format!("{mm}m") + } else { + format!("{hh}h:{mm}m") + } +} + +pub fn fmt_dur(dur: Duration) -> String { + let seconds = dur.as_secs(); + if seconds > 60 { + fmt_mm_hh(dur) + } else { + return format!("{seconds}s"); + } +} diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index a577d4d6..ab964868 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -6,56 +6,24 @@ use protocol::Reading; use ratatui::{text::Line, widgets::Bar}; use std::collections::HashMap; -use std::net::SocketAddr; -use std::sync::{Arc, Mutex, TryLockError}; -use std::thread; +use std::sync::TryLockError; use std::time::Instant; use time::OffsetDateTime; use tui_tree_widget::TreeItem; -use crate::trace_dbg; +mod fetch; +use fetch::StoredHistory; #[derive(Debug)] pub struct SensorInfo { - name: String, timing: Histogram, - reading: Reading, + pub reading: Reading, recent_history: Vec<(OffsetDateTime, f32)>, - old_history: Arc>>, - fetching: Option>, + pub stored_history: StoredHistory, condition: Result<(), Box>, log: Vec<(Instant, Error)>, } -fn fetch_history( - history: Arc>>, - reading: Reading, - addr: SocketAddr, -) { - let rt = tokio::runtime::Builder::new_current_thread() - .enable_io() - .build() - .unwrap(); - - let data = rt.block_on(async { - let mut api = data_store::api::Client::connect(addr).await.unwrap(); - trace_dbg!(api.list_data().await); - trace_dbg!(api.get_data( - OffsetDateTime::now_utc() - time::Duration::minutes(15), - OffsetDateTime::now_utc(), - reading, - 300, - ) - .await) - .unwrap() - }); - - let mut history = history.lock().unwrap(); - for (t, y) in data.0.into_iter().zip(data.1) { - history.push((t, y)) - } -} - impl SensorInfo { fn last_at(&self) -> Result> { self.condition.clone()?; @@ -71,12 +39,8 @@ impl SensorInfo { histogram_bars(&self.timing) } - pub fn chart<'a>( - &mut self, - plot_buf: &'a mut Vec<(f64, f64)>, - data_store: SocketAddr, - ) -> Option> { - let guard = match self.old_history.try_lock() { + pub fn chart<'a>(&mut self, plot_buf: &'a mut Vec<(f64, f64)>) -> Option> { + let guard = match self.stored_history.data.try_lock() { Ok(list) => Some(list), Err(TryLockError::WouldBlock) => None, Err(other) => panic!( @@ -91,6 +55,7 @@ impl SensorInfo { .first() .map(|(t, _)| t) .or_else(|| self.recent_history.first().map(|(t, _)| t))?; + tracing::debug!("reference: {reference:?}"); let first_recent = self .recent_history @@ -109,15 +74,8 @@ impl SensorInfo { plot_buf.push(xy); } - if old_history.is_empty() && self.fetching.is_none() { - let old_history = self.old_history.clone(); - let reading = self.reading.clone(); - let handle = thread::spawn(move || fetch_history(old_history, reading, data_store)); - self.fetching = Some(handle); - } - Some(ChartParts { - name: self.name.clone(), + reading: self.reading.clone(), data: plot_buf, }) } @@ -213,7 +171,7 @@ impl Readings { fn record_error(&mut self, error: Box) { for broken in error.device().affected_readings() { - let (key, name, _) = extract_leaf_info(broken); + let (key, _, _) = extract_leaf_info(broken); if let Some(info) = self.data.get_mut(&key) { info.condition = Err(error.clone()); @@ -222,14 +180,12 @@ impl Readings { self.data.insert( key, SensorInfo { - name, reading: broken.clone(), timing: Histogram::new(4, 24).unwrap(), recent_history: Vec::new(), + stored_history: StoredHistory::new(), condition: Err(error.clone()), log: vec![(Instant::now(), (*error).clone())], - old_history: Arc::new(Mutex::new(Vec::new())), - fetching: None, }, ); } @@ -237,7 +193,7 @@ impl Readings { } fn record_data(&mut self, reading: Reading) { - let (key, name, val) = extract_leaf_info(&reading); + let (key, _, val) = extract_leaf_info(&reading); let time = OffsetDateTime::now_utc(); if let Some(info) = self.data.get_mut(&key) { @@ -253,14 +209,12 @@ impl Readings { self.data.insert( key, SensorInfo { - name, reading, timing: Histogram::new(4, 24).unwrap(), recent_history: history, - old_history: Arc::new(Mutex::new(Vec::new())), + stored_history: StoredHistory::new(), condition: Ok(()), log: Vec::new(), - fetching: None, }, ); } @@ -276,8 +230,14 @@ impl Readings { }; loop { match tomato.inner() { - Item::Leaf(ReadingInfo { val, .. }) => { - let text = format!("{}: {}", tomato.name(), val); + Item::Leaf(info) => { + let text = format!( + "{0}: {1:.2$} {3}", + tomato.name(), + info.val, + info.precision(), + info.unit + ); add_leaf(text, tree, key); return; } @@ -324,7 +284,7 @@ impl Readings { } pub struct ChartParts<'a> { - pub name: String, + pub reading: Reading, pub data: &'a [(f64, f64)], } diff --git a/crates/sensor-tui/src/tui/reading/fetch.rs b/crates/sensor-tui/src/tui/reading/fetch.rs new file mode 100644 index 00000000..0e9b6088 --- /dev/null +++ b/crates/sensor-tui/src/tui/reading/fetch.rs @@ -0,0 +1,154 @@ +use protocol::Reading; + +use std::net::SocketAddr; +use std::sync::{Arc, Mutex}; +use std::thread; +use std::time::Duration; +use time::OffsetDateTime; +use tokio::sync::Notify; +use tokio::time::sleep; +use tracing::{debug, warn}; + +use crate::tui::history_len::{self, HistoryLen}; + + +#[derive(Debug)] +struct Fetching { + handle: thread::JoinHandle<()>, + cancel: Arc, + history_length: Duration, +} + +type Data = Arc>>; + +#[derive(Debug)] +pub struct StoredHistory { + fetching: Option, + curr_hist_dur: Duration, + pub data: Data, +} + +impl StoredHistory { + pub fn new() -> Self { + Self { + fetching: None, + curr_hist_dur: Duration::ZERO, + data: Arc::new(Mutex::new(Vec::new())), + } + } + + fn start_update(&mut self, reading: Reading, new_length: Duration, data_store: SocketAddr) { + if let Some(in_progress) = self.fetching.take() { + in_progress.cancel.notify_one(); + let _ = in_progress.handle.join(); + debug!("Canceled running stored-history update"); + } + + let reading = reading.clone(); + let cancel = Arc::new(Notify::new()); + let cancelled = cancel.clone(); + let data = self.data.clone(); + let handle = + thread::spawn(move || fetch_history(data, reading, data_store, new_length, cancelled)); + self.fetching = Some(Fetching { + handle, + cancel, + history_length: new_length, + }); + } + + pub fn update_if_needed( + &mut self, + data_store: SocketAddr, + reading: Reading, + needed_hist: &mut HistoryLen, + ) { + if let Some(in_progress) = &mut self.fetching { + if in_progress.history_length != needed_hist.dur { + self.start_update(reading, needed_hist.dur, data_store); + needed_hist.state = history_len::State::Fetching; + } + } else { + if self.curr_hist_dur != needed_hist.dur { + self.start_update(reading, needed_hist.dur, data_store); + needed_hist.state = history_len::State::Fetching; + } + } + + if let Some(in_progress) = &self.fetching { + if in_progress.handle.is_finished() { + needed_hist.state = history_len::State::Fetched + } + } + } +} + +fn fetch_history( + history: Arc>>, + reading: Reading, + addr: SocketAddr, + length: Duration, + cancelled: Arc, +) { + let rt = tokio::runtime::Builder::new_current_thread() + .enable_io() + .enable_time() + .build() + .unwrap(); + + let Some(data) = rt.block_on(async { + tokio::select! { + data = connect_and_get_data(addr, length, reading) => Some(data), + _ = cancelled.notified() => None, + } + }) else { + debug!("Canceled data fetch"); + return; + }; + + debug!("got data from {:?} till {:?}", data.0.first(), data.0.last()); + let mut history = history.lock().unwrap(); + history.clear(); + for (t, y) in data.0.into_iter().zip(data.1) { + history.push((t, y)) + } + debug!("done fetching {length:?}!"); +} + +async fn connect_and_get_data( + addr: SocketAddr, + length: Duration, + reading: Reading, +) -> (Vec, Vec) { + let mut retry_period = Duration::ZERO; + loop { + sleep(retry_period).await; + retry_period = Duration::from_secs(5) + .min(retry_period * 2) + .min(Duration::from_millis(100)); + + let mut api = match data_store::api::Client::connect(addr).await { + Ok(api) => api, + Err(e) => { + warn!("Could not connect to data_store (at {addr}): {e}"); + continue; + } + }; + + match api + .get_data( + OffsetDateTime::now_utc() - length, + OffsetDateTime::now_utc(), + reading.clone(), + 300, + ) + .await + { + Ok(res) => return res, + Err(e) => { + warn!("Error getting data from data-store, reconnecting: {e}"); + continue; + } + }; + } +} diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs index 0ea13b71..46e296f5 100644 --- a/crates/sensor-tui/src/tui/render.rs +++ b/crates/sensor-tui/src/tui/render.rs @@ -1,3 +1,4 @@ +use protocol::reading_tree::Tree as _; use ratatui::{ self, layout::{Constraint, Layout, Rect}, @@ -12,7 +13,7 @@ use tui_tree_widget::{Tree, TreeItem, TreeState}; use super::{ reading::{ChartParts, TreeKey}, - ActiveList, + ActiveList, HistoryLen, }; pub(crate) fn all( @@ -24,6 +25,7 @@ pub(crate) fn all( active_list: ActiveList, histogram: &[Bar], chart: Option, + history_len: &HistoryLen, ) { let area = frame.size(); let [top, bottom] = Layout::vertical([Constraint::Min(10), Constraint::Min(10)]) @@ -39,23 +41,35 @@ pub(crate) fn all( actuator_list_state, active_list, ); - render_lower(frame, bottom, histogram, chart); + render_lower(frame, bottom, histogram, chart, history_len); } -fn render_lower(frame: &mut Frame, layout: Rect, histogram: &[Bar], chart: Option) { +fn render_lower( + frame: &mut Frame, + layout: Rect, + histogram: &[Bar], + chart: Option, + history_len: &HistoryLen, +) { match chart { - Some(chart) => detail_view(frame, layout, chart, histogram), + Some(chart) => detail_view(frame, layout, chart, histogram, history_len), None => global_view(frame, layout, histogram), } } -fn detail_view(frame: &mut Frame, layout: Rect, chart: ChartParts, histogram: &[Bar]) { +fn detail_view( + frame: &mut Frame, + layout: Rect, + chart: ChartParts, + histogram: &[Bar], + history_len: &HistoryLen, +) { let [top, lower] = Layout::vertical([Constraint::Percentage(65), Constraint::Percentage(35)]) .flex(ratatui::layout::Flex::Legacy) .areas(layout); let dataset = Dataset::default() - .name(chart.name) + .name(chart.reading.name()) .marker(symbols::Marker::Dot) .graph_type(GraphType::Line) .style(Style::default()) @@ -77,10 +91,12 @@ fn detail_view(frame: &mut Frame, layout: Rect, chart: ChartParts, histogram: &[ let y_margin = f64::max(y_range * 0.5, 0.001 * y_bounds[0].abs()); let y_bounds = [y_bounds[0] - y_margin, y_bounds[1] + y_margin]; - let x_labels = vec![format_time(x_bounds[1]).into(), "0".into()]; + let left_x_label = history_len.render_x_label(x_bounds[1]); + let x_labels = vec![left_x_label, "0".into()]; + let y_labels = vec![ - format!("{:.3}", y_bounds[0]).into(), - format!("{:.3}", y_bounds[1]).into(), + format!("{0:.1$}", y_bounds[0], chart.reading.leaf().precision()).into(), + format!("{0:.1$}", y_bounds[1], chart.reading.leaf().precision()).into(), ]; let x_axis = Axis::default() @@ -89,7 +105,7 @@ fn detail_view(frame: &mut Frame, layout: Rect, chart: ChartParts, histogram: &[ .bounds(x_bounds) .labels(x_labels); let y_axis = Axis::default() - .title("Value") + .title(chart.reading.leaf().unit.to_string()) .style(Style::default()) .bounds(y_bounds) .labels(y_labels); @@ -165,16 +181,3 @@ pub(crate) fn render_top( actuator_list_state, ); } - -fn format_time(seconds: f64) -> String { - let seconds = seconds as u32; - if seconds < 60 { - format!("{}s ago", seconds) - } else if seconds < 600 { - let m = seconds / 60; - let s = seconds % 60; - format!("{m}:{s:0>1} ago") - } else { - format!("{}m ago", seconds / 60) - } -} diff --git a/crates/text-widget/src/main.rs b/crates/text-widget/src/main.rs index a2d73cdd..fe82b3fe 100644 --- a/crates/text-widget/src/main.rs +++ b/crates/text-widget/src/main.rs @@ -101,7 +101,7 @@ async fn main() { loop { let new = wait_for_update(&mut client, &reading).await; let info = new.leaf(); - let to_print = format!("{0:.1$}{2}", info.val, info.precision(), info.unit); + let to_print = format!("{0:.1$} {2}", info.val, info.precision(), info.unit); let use_json = cli.json; if use_json { println!("{{\"msg\": \"{to_print}\"}}"); From 2bc214085f6fc1e27556dc5b4a802ee9d638e27d Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 20 Jul 2024 22:55:40 +0200 Subject: [PATCH 162/687] refactor tui + make histogram showing optional --- crates/data-store/examples/last_15m.rs | 4 +- crates/sensor-tui/src/tui.rs | 12 +- crates/sensor-tui/src/tui/render.rs | 179 ++++++++++++------------- 3 files changed, 89 insertions(+), 106 deletions(-) diff --git a/crates/data-store/examples/last_15m.rs b/crates/data-store/examples/last_15m.rs index 6562339e..cd1ec9cb 100644 --- a/crates/data-store/examples/last_15m.rs +++ b/crates/data-store/examples/last_15m.rs @@ -3,7 +3,7 @@ use protocol::Reading; use std::net::SocketAddr; use data_store::api::Client; -use nucleo::pattern::{AtomKind, CaseMatching, Normalization}; +use nucleo_matcher::pattern::{AtomKind, CaseMatching, Normalization}; use time::{Duration, OffsetDateTime}; use clap::Parser; @@ -44,7 +44,7 @@ async fn main() { .map(|r| { ( pattern.score( - nucleo::Utf32Str::new(to_path(&r).as_str(), &mut buf), + nucleo_matcher::Utf32Str::new(to_path(&r).as_str(), &mut buf), &mut matcher, ), r, diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index 2f451915..3bddd314 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -114,17 +114,7 @@ impl App { }; terminal.draw(|frame| { - render::all( - frame, - &readings.ground, - &mut self.reading_list_state, - actuators.clone(), - &mut actuator_list_state, - self.active_list, - &histogram, - chart, - &self.history_length, - ); + render::app(frame, self, &readings.ground, chart, &histogram); })?; if self.reading_list_state.selected().is_empty() { diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs index 46e296f5..0ad750a5 100644 --- a/crates/sensor-tui/src/tui/render.rs +++ b/crates/sensor-tui/src/tui/render.rs @@ -1,80 +1,72 @@ use protocol::reading_tree::Tree as _; use ratatui::{ self, - layout::{Constraint, Layout, Rect}, + layout::{Constraint, Flex, Layout, Rect}, style::{Modifier, Style}, symbols, - widgets::{ - Axis, Bar, BarChart, BarGroup, Block, Borders, Chart, Dataset, GraphType, List, ListState, - }, + text::Span, + widgets::{Axis, Bar, BarChart, BarGroup, Block, Borders, Chart, Dataset, GraphType}, Frame, }; -use tui_tree_widget::{Tree, TreeItem, TreeState}; +use tui_tree_widget::{Tree, TreeItem}; use super::{ reading::{ChartParts, TreeKey}, - ActiveList, HistoryLen, + ActiveList, }; -pub(crate) fn all( +pub(crate) fn app( frame: &mut Frame, + app: &mut super::App, readings: &[TreeItem<'static, TreeKey>], - reading_state: &mut TreeState, - actuators: Vec, - actuator_list_state: &mut ListState, - active_list: ActiveList, - histogram: &[Bar], chart: Option, - history_len: &HistoryLen, + histogram: &[Bar], ) { let area = frame.size(); let [top, bottom] = Layout::vertical([Constraint::Min(10), Constraint::Min(10)]) - .flex(ratatui::layout::Flex::Legacy) + .flex(Flex::Legacy) .areas(area); - render_top( - frame, - top, - readings, - reading_state, - actuators, - actuator_list_state, - active_list, - ); - render_lower(frame, bottom, histogram, chart, history_len); + render_readings_and_actuators(frame, top, app, readings); + render_graphs(frame, bottom, app, histogram, chart); } -fn render_lower( +fn render_graphs( frame: &mut Frame, layout: Rect, + app: &mut super::App, histogram: &[Bar], chart: Option, - history_len: &HistoryLen, ) { - match chart { - Some(chart) => detail_view(frame, layout, chart, histogram, history_len), - None => global_view(frame, layout, histogram), + match (chart, app.show_histogram) { + (None, true) => render_histogram(frame, layout, histogram), + (None, false) => (), + (Some(chart), true) => { + let [top, lower] = + Layout::vertical([Constraint::Percentage(65), Constraint::Percentage(35)]) + .flex(Flex::Legacy) + .areas(layout); + render_chart(frame, top, app, chart); + render_histogram(frame, lower, histogram); + } + (Some(chart), false) => { + render_chart(frame, layout, app, chart); + } } } -fn detail_view( - frame: &mut Frame, - layout: Rect, - chart: ChartParts, - histogram: &[Bar], - history_len: &HistoryLen, -) { - let [top, lower] = Layout::vertical([Constraint::Percentage(65), Constraint::Percentage(35)]) - .flex(ratatui::layout::Flex::Legacy) - .areas(layout); - - let dataset = Dataset::default() - .name(chart.reading.name()) - .marker(symbols::Marker::Dot) - .graph_type(GraphType::Line) - .style(Style::default()) - .data(chart.data); +fn render_histogram(frame: &mut Frame, lower: Rect, histogram: &[Bar]) { + let barchart = BarChart::default() + .block(Block::bordered().title("Histogram")) + .data(BarGroup::default().bars(histogram)) + .bar_width(12) + .bar_style(Style::default()) + .value_style(Style::default()); + frame.render_widget(barchart, lower) +} +type Bounds = [f64; 2]; +fn bounds(chart: &ChartParts) -> (Bounds, Bounds) { let x_bounds = [ 0f64, chart.data.last().map(|(x, _)| x).copied().unwrap_or(0f64), @@ -90,14 +82,36 @@ fn detail_view( let y_range = y_bounds[1] - y_bounds[0]; let y_margin = f64::max(y_range * 0.5, 0.001 * y_bounds[0].abs()); let y_bounds = [y_bounds[0] - y_margin, y_bounds[1] + y_margin]; + (x_bounds, y_bounds) +} - let left_x_label = history_len.render_x_label(x_bounds[1]); +type Labels<'a> = Vec>; +fn labels<'a>( + app: &'a mut super::App, + chart: &ChartParts, + x: Bounds, + y: Bounds, +) -> (Labels<'a>, Labels<'a>) { + let left_x_label = app.history_length.render_x_label(x[1]); let x_labels = vec![left_x_label, "0".into()]; let y_labels = vec![ - format!("{0:.1$}", y_bounds[0], chart.reading.leaf().precision()).into(), - format!("{0:.1$}", y_bounds[1], chart.reading.leaf().precision()).into(), + format!("{0:.1$}", y[0], chart.reading.leaf().precision()).into(), + format!("{0:.1$}", y[1], chart.reading.leaf().precision()).into(), ]; + (x_labels, y_labels) +} + +fn render_chart(frame: &mut Frame, layout: Rect, app: &mut super::App, chart: ChartParts) { + let dataset = Dataset::default() + .name(chart.reading.name()) + .marker(symbols::Marker::Dot) + .graph_type(GraphType::Line) + .style(Style::default()) + .data(chart.data); + + let (x_bounds, y_bounds) = bounds(&chart); + let (x_labels, y_labels) = labels(app, &chart, x_bounds, y_bounds); let x_axis = Axis::default() .title("Time") @@ -113,39 +127,18 @@ fn detail_view( .block(Block::bordered().title("History")) .x_axis(x_axis) .y_axis(y_axis); - frame.render_widget(linechart, top); - - let barchart = BarChart::default() - .block(Block::bordered().title("Histogram")) - .data(BarGroup::default().bars(histogram)) - .bar_width(12) - .bar_style(Style::default()) - .value_style(Style::default()); - frame.render_widget(barchart, lower) + frame.render_widget(linechart, layout); } -fn global_view(frame: &mut Frame, layout: Rect, histogram: &[Bar]) { - let barchart = BarChart::default() - .block(Block::bordered().title("Histogram")) - .data(BarGroup::default().bars(histogram)) - .bar_width(12) - .bar_style(Style::default()) - .value_style(Style::default()); - frame.render_widget(barchart, layout) -} - -pub(crate) fn render_top( +pub(crate) fn render_readings_and_actuators( frame: &mut Frame, layout: Rect, + app: &mut super::App, readings: &[TreeItem<'static, TreeKey>], - reading_list_state: &mut TreeState, - actuators: Vec, - actuator_list_state: &mut ListState, - active_list: ActiveList, ) { let horizontal: [_; 2] = Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]) - .flex(ratatui::layout::Flex::Legacy) + .flex(Flex::Legacy) .areas(layout); frame.render_stateful_widget( @@ -155,29 +148,29 @@ pub(crate) fn render_top( Block::default() .title("Sensor readings") .borders(Borders::ALL) - .border_style(active_list.style(ActiveList::Readings)), + .border_style(app.active_list.style(ActiveList::Readings)), ) - .style(active_list.style(ActiveList::Readings)) + .style(app.active_list.style(ActiveList::Readings)) .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) .highlight_symbol(">>"), horizontal[0], - reading_list_state, + &mut app.reading_list_state, ); - frame.render_stateful_widget( - List::new(actuators) - .block( - Block::default() - .title("Actuators") - .borders(Borders::ALL) - .border_style(active_list.style(ActiveList::Actuators)), - ) - .style(active_list.style(ActiveList::Actuators)) - .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) - .highlight_symbol(">>") - .repeat_highlight_symbol(false) - .direction(ratatui::widgets::ListDirection::TopToBottom), - horizontal[1], - actuator_list_state, - ); + // frame.render_stateful_widget( + // List::new(app.actuators) + // .block( + // Block::default() + // .title("Actuators") + // .borders(Borders::ALL) + // .border_style(app.active_list.style(ActiveList::Actuators)), + // ) + // .style(app.active_list.style(ActiveList::Actuators)) + // .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) + // .highlight_symbol(">>") + // .repeat_highlight_symbol(false) + // .direction(ratatui::widgets::ListDirection::TopToBottom), + // horizontal[1], + // app.actuator_list_state, + // ); } From 2b4486dedc70ac9fe02d9da2962768f2f4ed53b8 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 21 Jul 2024 15:24:47 +0200 Subject: [PATCH 163/687] improves chart labels (time formatting mostly) --- Cargo.lock | 1 + crates/protocol/src/large_bedroom.rs | 4 +- crates/sensor-tui/Cargo.toml | 1 + crates/sensor-tui/src/tui.rs | 10 +- crates/sensor-tui/src/tui/history_len.rs | 4 +- crates/sensor-tui/src/tui/render.rs | 84 ++---------- crates/sensor-tui/src/tui/render/chart.rs | 68 ++++++++++ .../sensor-tui/src/tui/render/chart/labels.rs | 128 ++++++++++++++++++ 8 files changed, 220 insertions(+), 80 deletions(-) create mode 100644 crates/sensor-tui/src/tui/render/chart.rs create mode 100644 crates/sensor-tui/src/tui/render/chart/labels.rs diff --git a/Cargo.lock b/Cargo.lock index e381a225..0f256b41 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2586,6 +2586,7 @@ dependencies = [ "data-server", "data-store", "histogram", + "itertools", "protocol", "ratatui", "thiserror", diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index a2be830d..12d43032 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -84,12 +84,12 @@ impl Device { } #[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] -pub enum Actuator { +pub enum Affector { CleanSensor, CalibrateCo2, } -impl Actuator { +impl Affector { #[cfg(feature = "alloc")] #[must_use] pub fn encode(&self) -> Vec { diff --git a/crates/sensor-tui/Cargo.toml b/crates/sensor-tui/Cargo.toml index f9bf77b1..ac93b1af 100644 --- a/crates/sensor-tui/Cargo.toml +++ b/crates/sensor-tui/Cargo.toml @@ -24,3 +24,4 @@ data-server = { workspace = true } data-store = { workspace = true } time = { workspace = true } thiserror.workspace = true +itertools = "0.13.0" diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index 3bddd314..0174ae5e 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -25,7 +25,7 @@ use self::reading::TreeKey; enum ActiveList { #[default] Readings, - Actuators, + Affectors, } impl ActiveList { @@ -39,8 +39,8 @@ impl ActiveList { fn swap(self) -> Self { match self { - Self::Readings => Self::Actuators, - Self::Actuators => Self::Readings, + Self::Readings => Self::Affectors, + Self::Affectors => Self::Readings, } } } @@ -86,8 +86,8 @@ impl App { let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; terminal.clear()?; - let mut actuator_list_state = ListState::default(); - let actuators = vec![ + let mut affectors_list_state = ListState::default(); + let affectors = vec![ "placeholder 1".to_owned(), "placeholder 2".to_owned(), "placeholder 3".to_owned(), diff --git a/crates/sensor-tui/src/tui/history_len.rs b/crates/sensor-tui/src/tui/history_len.rs index e4cde187..0d61a858 100644 --- a/crates/sensor-tui/src/tui/history_len.rs +++ b/crates/sensor-tui/src/tui/history_len.rs @@ -61,7 +61,7 @@ impl HistoryLen { } } - pub(crate) fn render_x_label(&self, upper_x_bound: f64) -> Span { + pub(crate) fn style_left_x_label(&self, org_label: Span<'static>) -> Span<'static> { let mut text = self.text_input.clone(); if self.editing { text.push_str("_"); @@ -92,7 +92,7 @@ impl HistoryLen { if self.editing { Span::raw(text) } else { - Span::raw(fmt_dur(Duration::from_secs_f64(upper_x_bound))) + org_label } } } diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs index 0ad750a5..93f9c803 100644 --- a/crates/sensor-tui/src/tui/render.rs +++ b/crates/sensor-tui/src/tui/render.rs @@ -1,4 +1,7 @@ -use protocol::reading_tree::Tree as _; +use std::iter; + +use itertools::Itertools; +use protocol::reading_tree::{ReadingInfo, Tree as _}; use ratatui::{ self, layout::{Constraint, Flex, Layout, Rect}, @@ -8,16 +11,19 @@ use ratatui::{ widgets::{Axis, Bar, BarChart, BarGroup, Block, Borders, Chart, Dataset, GraphType}, Frame, }; +use tracing_subscriber::fmt::format; use tui_tree_widget::{Tree, TreeItem}; use super::{ reading::{ChartParts, TreeKey}, - ActiveList, + ActiveList, App, }; +mod chart; + pub(crate) fn app( frame: &mut Frame, - app: &mut super::App, + app: &mut App, readings: &[TreeItem<'static, TreeKey>], chart: Option, histogram: &[Bar], @@ -34,7 +40,7 @@ pub(crate) fn app( fn render_graphs( frame: &mut Frame, layout: Rect, - app: &mut super::App, + app: &mut App, histogram: &[Bar], chart: Option, ) { @@ -46,11 +52,11 @@ fn render_graphs( Layout::vertical([Constraint::Percentage(65), Constraint::Percentage(35)]) .flex(Flex::Legacy) .areas(layout); - render_chart(frame, top, app, chart); + chart::render(frame, top, app, chart); render_histogram(frame, lower, histogram); } (Some(chart), false) => { - render_chart(frame, layout, app, chart); + chart::render(frame, layout, app, chart); } } } @@ -65,75 +71,11 @@ fn render_histogram(frame: &mut Frame, lower: Rect, histogram: &[Bar]) { frame.render_widget(barchart, lower) } -type Bounds = [f64; 2]; -fn bounds(chart: &ChartParts) -> (Bounds, Bounds) { - let x_bounds = [ - 0f64, - chart.data.last().map(|(x, _)| x).copied().unwrap_or(0f64), - ]; - - let y_bounds = chart - .data - .iter() - .map(|(_, y)| y) - .fold([f64::MAX, f64::MIN], |[start, end], y| { - [start.min(*y), end.max(*y)] - }); - let y_range = y_bounds[1] - y_bounds[0]; - let y_margin = f64::max(y_range * 0.5, 0.001 * y_bounds[0].abs()); - let y_bounds = [y_bounds[0] - y_margin, y_bounds[1] + y_margin]; - (x_bounds, y_bounds) -} - -type Labels<'a> = Vec>; -fn labels<'a>( - app: &'a mut super::App, - chart: &ChartParts, - x: Bounds, - y: Bounds, -) -> (Labels<'a>, Labels<'a>) { - let left_x_label = app.history_length.render_x_label(x[1]); - let x_labels = vec![left_x_label, "0".into()]; - - let y_labels = vec![ - format!("{0:.1$}", y[0], chart.reading.leaf().precision()).into(), - format!("{0:.1$}", y[1], chart.reading.leaf().precision()).into(), - ]; - (x_labels, y_labels) -} - -fn render_chart(frame: &mut Frame, layout: Rect, app: &mut super::App, chart: ChartParts) { - let dataset = Dataset::default() - .name(chart.reading.name()) - .marker(symbols::Marker::Dot) - .graph_type(GraphType::Line) - .style(Style::default()) - .data(chart.data); - - let (x_bounds, y_bounds) = bounds(&chart); - let (x_labels, y_labels) = labels(app, &chart, x_bounds, y_bounds); - - let x_axis = Axis::default() - .title("Time") - .style(Style::default()) - .bounds(x_bounds) - .labels(x_labels); - let y_axis = Axis::default() - .title(chart.reading.leaf().unit.to_string()) - .style(Style::default()) - .bounds(y_bounds) - .labels(y_labels); - let linechart = Chart::new(vec![dataset]) - .block(Block::bordered().title("History")) - .x_axis(x_axis) - .y_axis(y_axis); - frame.render_widget(linechart, layout); -} pub(crate) fn render_readings_and_actuators( frame: &mut Frame, layout: Rect, - app: &mut super::App, + app: &mut App, readings: &[TreeItem<'static, TreeKey>], ) { let horizontal: [_; 2] = diff --git a/crates/sensor-tui/src/tui/render/chart.rs b/crates/sensor-tui/src/tui/render/chart.rs new file mode 100644 index 00000000..97dcb2e8 --- /dev/null +++ b/crates/sensor-tui/src/tui/render/chart.rs @@ -0,0 +1,68 @@ +use protocol::reading_tree::Tree; +use ratatui::{ + layout::{Alignment, Rect}, + style::Style, + symbols, + widgets::{Axis, Block, Chart, Dataset, GraphType}, + Frame, +}; + +use crate::tui::reading::ChartParts; + +use super::App; + +mod labels; +use labels::labels; + +pub fn render(frame: &mut Frame, layout: Rect, app: &mut App, chart: ChartParts) { + let dataset = Dataset::default() + .name(chart.reading.name()) + .marker(symbols::Marker::Dot) + .graph_type(GraphType::Line) + .style(Style::default()) + .data(chart.data); + + let (x_bounds, y_bounds) = bounds(&chart); + let (mut x_labels, y_labels) = labels(&chart, layout, x_bounds, y_bounds); + + let borrowed = x_labels.first_mut().expect("min labels is 2"); + let owned = std::mem::take(borrowed); + x_labels[0] = app.history_length.style_left_x_label(owned); + + let x_axis = Axis::default() + .title("Time") + .style(Style::default()) + .bounds(x_bounds) + .labels(x_labels) + .labels_alignment(Alignment::Center); + let y_axis = Axis::default() + .title(chart.reading.leaf().unit.to_string()) + .style(Style::default()) + .bounds(y_bounds) + .labels(y_labels); + let linechart = Chart::new(vec![dataset]) + .block(Block::bordered().title("History")) + .x_axis(x_axis) + .y_axis(y_axis); + frame.render_widget(linechart, layout); +} + +type Bounds = [f64; 2]; +fn bounds(chart: &ChartParts) -> (Bounds, Bounds) { + let x_bounds = [ + 0f64, + chart.data.last().map(|(x, _)| x).copied().unwrap_or(0f64), + ]; + + let y_bounds = chart + .data + .iter() + .map(|(_, y)| y) + .fold([f64::MAX, f64::MIN], |[start, end], y| { + [start.min(*y), end.max(*y)] + }); + let y_range = y_bounds[1] - y_bounds[0]; + let y_margin = f64::max(y_range * 0.5, 0.001 * y_bounds[0].abs()); + let y_bounds = [y_bounds[0] - y_margin, y_bounds[1] + y_margin]; + (x_bounds, y_bounds) +} diff --git a/crates/sensor-tui/src/tui/render/chart/labels.rs b/crates/sensor-tui/src/tui/render/chart/labels.rs new file mode 100644 index 00000000..d6bcde2f --- /dev/null +++ b/crates/sensor-tui/src/tui/render/chart/labels.rs @@ -0,0 +1,128 @@ +use protocol::reading_tree::{ReadingInfo, Tree}; +use ratatui::layout::Rect; +use ratatui::text::Span; + +use crate::tui::reading::ChartParts; + +use super::Bounds; + +type Labels = Vec>; + +pub fn labels<'a>( + chart: &ChartParts, + layout: Rect, + x_bounds: Bounds, + y_bounds: Bounds, +) -> (Labels, Labels) { + let y_label_spacing = 10; + let info = chart.reading.leaf(); + + // characters are about twice as high as wide + let x = evenly_spaced_labels(layout.width / y_label_spacing / 2, &info, x_bounds) + .rev() + .map(fmt_x_label) + .map(Into::into) + .collect(); + let y = evenly_spaced_labels(layout.height / y_label_spacing, &info, y_bounds) + .map(|y| format!("{0:.1$}", y, info.precision()).into()) + .collect(); + + (x, y) +} + +fn evenly_spaced_labels( + max_labels: u16, + reading: &ReadingInfo, + bounds: Bounds, +) -> impl DoubleEndedIterator { + let resolution = reading.resolution as f64; + let steps_in_data = (bounds[1] - bounds[0]) / resolution; + + let n_labels = max_labels.min(steps_in_data as u16).max(2); + + let y_spacing = (bounds[1] - bounds[0]) / n_labels as f64; + (0..=n_labels) + .into_iter() + .map(move |i| bounds[0] + y_spacing * i as f64) +} + +struct FmtOption { + unit: &'static str, + factor: usize, + /// at a max display this numb of items + /// before going to the bigger FmtOption + next: usize, +} + +impl FmtOption { + fn scale(&self, seconds: f64) -> usize { + (seconds / self.factor as f64).floor() as usize + } +} + +fn fmt_x_label(secs: f64) -> String { + #[rustfmt::skip] + let mut options = [ + // next is purposefully set wrong, we set it in a loop below + FmtOption{unit: "s", factor: 1, next: 0}, + FmtOption{unit: "m", factor: 60, next: 0}, + FmtOption{unit: "h", factor: 60 * 60, next: 0}, + FmtOption{unit: "d", factor: 60 * 60 * 24, next: 0}, + FmtOption{unit: "w", factor: 60 * 60 * 24 * 7, next: 0}, + FmtOption{unit: "y", factor: 60 * 60 * 24 * 365, next: 0}, + ]; + + let mut next = usize::MAX; + for fmt in options.iter_mut().rev() { + fmt.next = next; + next = fmt.factor; + } + + let mut small = &options[0]; + for big in &options[1..] { + if big.scale(secs) == 0 { + return format!("{}{}", small.scale(secs), small.unit); + } + + if secs >= big.next as f64 { + small = big; + continue; + } + + if small.scale(secs % small.next as f64) == 0 { + return format!("{}{}", big.scale(secs), big.unit); + } + + return format!( + "{}{}{}{}", + big.scale(secs), + big.unit, + small.scale(secs % small.next as f64), + small.unit + ); + } + + unreachable!() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_fmt_x() { + let cases = [ + (5, "5s"), + (92, "1m32s"), + (60 * 60 * 12, "12h"), + (60 * 60 * 24 * 2, "2d"), + (60 * 60 * 24 * 7, "1w"), + (60 * 60 * 24 * 366, "1y"), + (60 * 60 * 24 * 365 * 14 + 60 * 60 * 24 * 7 * 6, "14y6w"), + ]; + + for (input, correct_output) in cases { + assert_eq!(fmt_x_label(input as f64), correct_output); + } + } +} From bd3c36195f80fb41d655b3e265036050937686f0 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 21 Jul 2024 16:19:43 +0200 Subject: [PATCH 164/687] improve graph bounds --- crates/sensor-tui/src/tui/render.rs | 45 +++++++++++++++++------ crates/sensor-tui/src/tui/render/chart.rs | 8 ++-- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs index 93f9c803..a0649193 100644 --- a/crates/sensor-tui/src/tui/render.rs +++ b/crates/sensor-tui/src/tui/render.rs @@ -1,17 +1,11 @@ -use std::iter; - -use itertools::Itertools; -use protocol::reading_tree::{ReadingInfo, Tree as _}; use ratatui::{ self, layout::{Constraint, Flex, Layout, Rect}, style::{Modifier, Style}, - symbols, - text::Span, - widgets::{Axis, Bar, BarChart, BarGroup, Block, Borders, Chart, Dataset, GraphType}, + text::Text, + widgets::{Bar, BarChart, BarGroup, Block, Borders}, Frame, }; -use tracing_subscriber::fmt::format; use tui_tree_widget::{Tree, TreeItem}; use super::{ @@ -28,13 +22,41 @@ pub(crate) fn app( chart: Option, histogram: &[Bar], ) { + let [list_constraint, graph_constraint] = if chart.is_some() { + let list_height = 2 + app.reading_list_state.flatten(readings).len(); + if (frame.size().height as f32) / 3. > list_height as f32 { + [Constraint::Min(list_height as u16), Constraint::Percentage(100)] + } else { + [Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)] + } + } else { + [Constraint::Percentage(100), Constraint::Percentage(100)] + }; + let area = frame.size(); - let [top, bottom] = Layout::vertical([Constraint::Min(10), Constraint::Min(10)]) - .flex(Flex::Legacy) - .areas(area); + let [top, bottom, footer] = + Layout::vertical([list_constraint, graph_constraint, Constraint::Min(1)]) + .flex(Flex::Legacy) + .areas(area); render_readings_and_actuators(frame, top, app, readings); render_graphs(frame, bottom, app, histogram, chart); + render_footer(frame, footer, app); +} + +fn render_footer(frame: &mut Frame, layout: Rect, app: &mut App) { + let text = if app.history_length.editing { + "ESC: stop bound editing" + } else { + if app.show_histogram { + "b: edit graph start, h: hide histogram" + } else { + "b: edit graph start, h: show histogram" + } + }; + + let text = Text::raw(text); + frame.render_widget(text, layout) } fn render_graphs( @@ -71,7 +93,6 @@ fn render_histogram(frame: &mut Frame, lower: Rect, histogram: &[Bar]) { frame.render_widget(barchart, lower) } - pub(crate) fn render_readings_and_actuators( frame: &mut Frame, layout: Rect, diff --git a/crates/sensor-tui/src/tui/render/chart.rs b/crates/sensor-tui/src/tui/render/chart.rs index 97dcb2e8..a4ded93c 100644 --- a/crates/sensor-tui/src/tui/render/chart.rs +++ b/crates/sensor-tui/src/tui/render/chart.rs @@ -16,13 +16,12 @@ use labels::labels; pub fn render(frame: &mut Frame, layout: Rect, app: &mut App, chart: ChartParts) { let dataset = Dataset::default() - .name(chart.reading.name()) .marker(symbols::Marker::Dot) .graph_type(GraphType::Line) .style(Style::default()) .data(chart.data); - let (x_bounds, y_bounds) = bounds(&chart); + let (x_bounds, y_bounds) = bounds(&chart, chart.reading.resolution() as f64, layout); let (mut x_labels, y_labels) = labels(&chart, layout, x_bounds, y_bounds); let borrowed = x_labels.first_mut().expect("min labels is 2"); @@ -48,7 +47,7 @@ pub fn render(frame: &mut Frame, layout: Rect, app: &mut App, chart: ChartParts) } type Bounds = [f64; 2]; -fn bounds(chart: &ChartParts) -> (Bounds, Bounds) { +fn bounds(chart: &ChartParts, resolution: f64, layout: Rect) -> (Bounds, Bounds) { let x_bounds = [ 0f64, chart.data.last().map(|(x, _)| x).copied().unwrap_or(0f64), @@ -62,7 +61,8 @@ fn bounds(chart: &ChartParts) -> (Bounds, Bounds) { [start.min(*y), end.max(*y)] }); let y_range = y_bounds[1] - y_bounds[0]; - let y_margin = f64::max(y_range * 0.5, 0.001 * y_bounds[0].abs()); + let margin = 5.0 / layout.height as f64; + let y_margin = f64::max(y_range * margin, resolution / 2.0); let y_bounds = [y_bounds[0] - y_margin, y_bounds[1] + y_margin]; (x_bounds, y_bounds) } From fbbcbebcc41d93d532aea2868cb4138f8ea3cc96 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 23 Jul 2024 12:56:44 +0200 Subject: [PATCH 165/687] lower spammy trace from info to trace level --- crates/data-store/src/server/db/series.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index 1a75f5f7..3704897d 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -9,7 +9,7 @@ use color_eyre::{Result, Section}; use protocol::reading_tree::{Item, ReadingInfo, Tree}; use serde::{Deserialize, Serialize}; use time::OffsetDateTime; -use tracing::{info, instrument}; +use tracing::{info, instrument, trace}; use byteseries::file::OpenError as FileOpenError; use series::data::OpenError as DataOpenError; @@ -163,7 +163,7 @@ impl Series { self.meta .iter() .find(|meta| requested.is_same_as(&meta.reading)) - .inspect(|meta| info!("meta used for decoding: {meta:?}")) + .inspect(|meta| trace!("meta used for decoding: {meta:?}")) .map(|meta| meta.field.clone()) .expect(&format!( "caller of read makes sure all readings are part of this \ From c573eeab8204d424e819626ebd721ceab691aac8 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 23 Jul 2024 20:51:28 +0200 Subject: [PATCH 166/687] only read slow sensors every 5 seconds --- sensor-nodes/bed-sensors/Cargo.lock | 20 ++++++++++-- sensor-nodes/bed-sensors/Cargo.toml | 32 +++++++++---------- sensor-nodes/bed-sensors/src/channel.rs | 2 +- sensor-nodes/bed-sensors/src/main.rs | 8 ++--- sensor-nodes/bed-sensors/src/network.rs | 2 +- .../src/sensors/retry/retry_init.rs | 3 -- sensor-nodes/bed-sensors/src/sensors/slow.rs | 11 ++++--- 7 files changed, 46 insertions(+), 32 deletions(-) diff --git a/sensor-nodes/bed-sensors/Cargo.lock b/sensor-nodes/bed-sensors/Cargo.lock index ffd6c526..3f6a0e17 100644 --- a/sensor-nodes/bed-sensors/Cargo.lock +++ b/sensor-nodes/bed-sensors/Cargo.lock @@ -288,6 +288,7 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" dependencies = [ "defmt", "embassy-futures", @@ -304,6 +305,7 @@ dependencies = [ [[package]] name = "embassy-executor" version = "0.5.0" +source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" dependencies = [ "cortex-m", "critical-section", @@ -317,6 +319,7 @@ dependencies = [ [[package]] name = "embassy-executor-macros" version = "0.4.1" +source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" dependencies = [ "darling", "proc-macro2", @@ -327,10 +330,12 @@ dependencies = [ [[package]] name = "embassy-futures" version = "0.1.1" +source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" [[package]] name = "embassy-hal-internal" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" dependencies = [ "cortex-m", "critical-section", @@ -341,6 +346,7 @@ dependencies = [ [[package]] name = "embassy-net" version = "0.4.0" +source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" dependencies = [ "defmt", "document-features", @@ -357,6 +363,7 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" dependencies = [ "defmt", ] @@ -364,6 +371,7 @@ dependencies = [ [[package]] name = "embassy-net-driver-channel" version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" dependencies = [ "embassy-futures", "embassy-net-driver", @@ -373,6 +381,7 @@ dependencies = [ [[package]] name = "embassy-net-wiznet" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" dependencies = [ "defmt", "embassy-futures", @@ -385,6 +394,7 @@ dependencies = [ [[package]] name = "embassy-stm32" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" dependencies = [ "bit_field", "bitflags 2.5.0", @@ -428,6 +438,7 @@ dependencies = [ [[package]] name = "embassy-sync" version = "0.6.0" +source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" dependencies = [ "cfg-if", "critical-section", @@ -439,7 +450,8 @@ dependencies = [ [[package]] name = "embassy-time" -version = "0.3.0" +version = "0.3.1" +source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" dependencies = [ "cfg-if", "critical-section", @@ -457,6 +469,7 @@ dependencies = [ [[package]] name = "embassy-time-driver" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" dependencies = [ "document-features", ] @@ -464,10 +477,12 @@ dependencies = [ [[package]] name = "embassy-time-queue-driver" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" [[package]] name = "embassy-usb-driver" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" dependencies = [ "defmt", ] @@ -475,6 +490,7 @@ dependencies = [ [[package]] name = "embassy-usb-synopsys-otg" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" dependencies = [ "critical-section", "embassy-sync", @@ -1080,7 +1096,7 @@ dependencies = [ [[package]] name = "stm32-metapac" version = "15.0.0" -source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-59b1f65bd109c3ef35782e6c44062208d0ef3d0e#2ad339796e0f40bd6fa784dbfe30a071d93cc886" +source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-e0cfd165fd8fffaa0df66a35eeca83b228496645#bf02c35d063e1823a156468497b448ae3350a255" dependencies = [ "cortex-m", "cortex-m-rt", diff --git a/sensor-nodes/bed-sensors/Cargo.toml b/sensor-nodes/bed-sensors/Cargo.toml index aa2bc8a6..4baf653a 100644 --- a/sensor-nodes/bed-sensors/Cargo.toml +++ b/sensor-nodes/bed-sensors/Cargo.toml @@ -52,23 +52,23 @@ rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } # fasthash = { version = "0.4.0", default-features = false } [patch.crates-io] -# embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } -# embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } -# embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } -# embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } -# embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } -# embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } -# embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } -# embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "039d8ed" } +embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "2537fc6" } +embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "2537fc6" } +embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "2537fc6" } +embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "2537fc6" } +embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "2537fc6" } +embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "2537fc6" } +embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "2537fc6" } +embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "2537fc6" } -embassy-stm32 = {path = "../../../embassy/embassy-stm32" } -embassy-net = {path = "../../../embassy/embassy-net" } -embassy-net-wiznet = {path = "../../../embassy/embassy-net-wiznet" } -embassy-sync = {path = "../../../embassy/embassy-sync" } -embassy-executor = {path = "../../../embassy/embassy-executor" } -embassy-embedded-hal = {path = "../../../embassy/embassy-embedded-hal" } -embassy-time = {path = "../../../embassy/embassy-time" } -embassy-futures = {path = "../../../embassy/embassy-futures" } +# embassy-stm32 = {path = "../../../embassy/embassy-stm32" } +# embassy-net = {path = "../../../embassy/embassy-net" } +# embassy-net-wiznet = {path = "../../../embassy/embassy-net-wiznet" } +# embassy-sync = {path = "../../../embassy/embassy-sync" } +# embassy-executor = {path = "../../../embassy/embassy-executor" } +# embassy-embedded-hal = {path = "../../../embassy/embassy-embedded-hal" } +# embassy-time = {path = "../../../embassy/embassy-time" } +# embassy-futures = {path = "../../../embassy/embassy-futures" } [profile.dev] opt-level = "s" diff --git a/sensor-nodes/bed-sensors/src/channel.rs b/sensor-nodes/bed-sensors/src/channel.rs index f88318a2..f263c26c 100644 --- a/sensor-nodes/bed-sensors/src/channel.rs +++ b/sensor-nodes/bed-sensors/src/channel.rs @@ -57,7 +57,6 @@ impl Queues { } pub fn queue_error(&self, error: error_cache::Error) { - defmt::debug!("queueing error: {:?}", error); // unwrap safe: is not used in interrupts let mut recent_errors = defmt::unwrap!(self.recent_errors.try_lock()); if self.recent_is_since.elapsed() > Duration::from_secs(60 * 5) { @@ -67,6 +66,7 @@ impl Queues { return; } + defmt::debug!("queueing error: {:?}", error); let Ok(()) = self.error_queue.try_send(error.clone()) else { return; }; diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index 7d71106d..ff1da392 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -158,7 +158,7 @@ async fn main(spawner: Spawner) { static STATE: StaticCell> = StaticCell::new(); let state = STATE.init(State::<3, 2>::new()); let (device, runner) = - embassy_net_wiznet::new(mac_addr, state, spi, w5500_int, w5500_reset).await; + unwrap!(embassy_net_wiznet::new(mac_addr, state, spi, w5500_int, w5500_reset).await); unwrap!(spawner.spawn(ethernet_task(runner))); // Init network stack @@ -167,15 +167,15 @@ async fn main(spawner: Spawner) { unwrap!(dns_servers.push(Ipv4Address([192, 168, 1, 1]))); unwrap!(dns_servers.push(Ipv4Address([192, 168, 1, 1]))); static STACK: StaticCell> = StaticCell::new(); - static RESOURCES: StaticCell> = StaticCell::new(); + static RESOURCES: StaticCell> = StaticCell::new(); let stack = &*STACK.init(Stack::new( device, embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { - address: Ipv4Cidr::new(Ipv4Address([192, 168, 1, 6]), 24), + address: Ipv4Cidr::new(Ipv4Address([192, 168, 1, 7]), 24), gateway: Some(Ipv4Address([192, 168, 1, 1])), dns_servers, }), - RESOURCES.init(StackResources::<2>::new()), + RESOURCES.init(StackResources::<3>::new()), seed, )); diff --git a/sensor-nodes/bed-sensors/src/network.rs b/sensor-nodes/bed-sensors/src/network.rs index da336e5a..9f4330a5 100644 --- a/sensor-nodes/bed-sensors/src/network.rs +++ b/sensor-nodes/bed-sensors/src/network.rs @@ -11,7 +11,7 @@ use crate::channel::{PriorityValue, QueueItem, Queues}; type Msg = SensorMessage<10>; async fn collect_pending(publish: &Queues, reading: PriorityValue) -> SensorMessage<10> { - let mut msg = Msg::new(); + let mut msg = Msg::default(); let low_priority = reading.low_priority(); unwrap!(msg.values.push(reading.value)); diff --git a/sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs b/sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs index b08b0a39..86592990 100644 --- a/sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs +++ b/sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs @@ -31,7 +31,6 @@ impl<'a> Sps30Driver<'a> { .map_err(Error::Running); } - defmt::info!("initializing sps30"); self.driver .reset() .await @@ -43,7 +42,6 @@ impl<'a> Sps30Driver<'a> { .map_err(SensorError::Sps30) .map_err(Error::Setup)?; - defmt::debug!("sps30 init complete"); self.is_init = true; self.driver .read_measurement() @@ -51,7 +49,6 @@ impl<'a> Sps30Driver<'a> { .map_err(SensorError::Sps30) .map_err(Error::Running) } - } impl<'a> Driver for Sps30Driver<'a> { diff --git a/sensor-nodes/bed-sensors/src/sensors/slow.rs b/sensor-nodes/bed-sensors/src/sensors/slow.rs index 24cdf2ba..a9987907 100644 --- a/sensor-nodes/bed-sensors/src/sensors/slow.rs +++ b/sensor-nodes/bed-sensors/src/sensors/slow.rs @@ -37,12 +37,12 @@ where } } -async fn order_measurements_every_second(signals: &[Signal]) { +async fn order_measurements_every_period(signals: &[Signal]) { loop { for signal in signals { signal.signal(()); } - Timer::after_secs(1).await; + Timer::after_secs(5).await; } } @@ -57,7 +57,7 @@ pub async fn read( let signals = [const { Signal::new() }; 4]; join5( - order_measurements_every_second(&signals), + order_measurements_every_period(&signals), measure_and_send_on_signal(sht, |res| publish_sht_result(res, &publish), &signals[0]), measure_and_send_on_signal(bme, |res| publish_bme_result(res, &publish), &signals[1]), measure_and_send_on_signal(mhz, |res| publish_mhz_result(res, &publish), &signals[2]), @@ -73,18 +73,19 @@ fn publish_sps_result(sps_res: Result, publish: &Queu mass_pm2_5, mass_pm4_0, mass_pm10, - mass_pm0_5, number_pm1_0, number_pm2_5, number_pm4_0, number_pm10, typical_particle_size, + .. + // mass_pm0_5, }) => { publish.send_p0(Reading::MassPm1_0(mass_pm1_0)); publish.send_p0(Reading::MassPm2_5(mass_pm2_5)); publish.send_p0(Reading::MassPm4_0(mass_pm4_0)); publish.send_p0(Reading::MassPm10(mass_pm10)); - publish.send_p0(Reading::MassPm0_5(mass_pm0_5)); + // publish.send_p0(Reading::MassPm0_5(mass_pm0_5)); publish.send_p0(Reading::NumberPm1_0(number_pm1_0)); publish.send_p0(Reading::NumberPm2_5(number_pm2_5)); publish.send_p0(Reading::NumberPm4_0(number_pm4_0)); From 3a5ac7e2a7b7a2d35c9668203227fb359f51ad0b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 23 Jul 2024 20:52:15 +0200 Subject: [PATCH 167/687] refactor keycode handling --- crates/sensor-tui/src/tui.rs | 31 ++++++++++++++++------------ crates/sensor-tui/src/tui/reading.rs | 1 - crates/sensor-tui/src/tui/render.rs | 13 ++++++++---- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index 0174ae5e..cfe95f97 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -125,6 +125,7 @@ impl App { if let event::Event::Key(key) = event::read()? { tracing::trace!("key pressed: {key:?}"); if key.kind == KeyEventKind::Press { + self.handle_key_all_modes(key); let res = match self.input_mode { InputMode::Normal => self.handle_key_normal_mode(key, plot_open), InputMode::EditingBounds => self.handle_key_bounds_mode(key), @@ -157,24 +158,12 @@ impl App { KeyCode::Char('q') => { return ShouldExit::Yes; } - KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => { - return ShouldExit::Yes; - } KeyCode::Left => { self.active_list = self.active_list.swap(); } KeyCode::Right => { self.active_list = self.active_list.swap(); } - KeyCode::Down => { - self.reading_list_state.key_down(); - } - KeyCode::Up => { - self.reading_list_state.key_up(); - } - KeyCode::Enter => { - self.reading_list_state.toggle_selected(); - } KeyCode::Char('b') => { if plot_open { self.history_length.start_editing(); @@ -195,10 +184,26 @@ impl App { self.history_length.exit_editing(); self.input_mode = InputMode::Normal; } + other => self.history_length.process(other), + } + ShouldExit::No + } + + fn handle_key_all_modes(&mut self, key: KeyEvent) -> ShouldExit { + match key.code { + KeyCode::Down => { + self.reading_list_state.key_down(); + } + KeyCode::Up => { + self.reading_list_state.key_up(); + } + KeyCode::Enter => { + self.reading_list_state.toggle_selected(); + } KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => { return ShouldExit::Yes; } - other => self.history_length.process(other), + _other => (), } ShouldExit::No } diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index ab964868..d43dbcb9 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -55,7 +55,6 @@ impl SensorInfo { .first() .map(|(t, _)| t) .or_else(|| self.recent_history.first().map(|(t, _)| t))?; - tracing::debug!("reference: {reference:?}"); let first_recent = self .recent_history diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs index a0649193..01ccaa50 100644 --- a/crates/sensor-tui/src/tui/render.rs +++ b/crates/sensor-tui/src/tui/render.rs @@ -8,6 +8,8 @@ use ratatui::{ }; use tui_tree_widget::{Tree, TreeItem}; +use crate::trace_dbg; + use super::{ reading::{ChartParts, TreeKey}, ActiveList, App, @@ -22,10 +24,13 @@ pub(crate) fn app( chart: Option, histogram: &[Bar], ) { - let [list_constraint, graph_constraint] = if chart.is_some() { + let [list_constraint, graph_constraint] = if chart.is_some() | app.show_histogram { let list_height = 2 + app.reading_list_state.flatten(readings).len(); if (frame.size().height as f32) / 3. > list_height as f32 { - [Constraint::Min(list_height as u16), Constraint::Percentage(100)] + [ + Constraint::Min(list_height as u16), + Constraint::Percentage(100), + ] } else { [Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)] } @@ -40,7 +45,7 @@ pub(crate) fn app( .areas(area); render_readings_and_actuators(frame, top, app, readings); - render_graphs(frame, bottom, app, histogram, chart); + render_graph_and_hist(frame, bottom, app, histogram, chart); render_footer(frame, footer, app); } @@ -59,7 +64,7 @@ fn render_footer(frame: &mut Frame, layout: Rect, app: &mut App) { frame.render_widget(text, layout) } -fn render_graphs( +fn render_graph_and_hist( frame: &mut Frame, layout: Rect, app: &mut App, From 75aa80c9a785515511f56b5c461f884513acc2c5 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 23 Jul 2024 20:52:47 +0200 Subject: [PATCH 168/687] adds logging to panic --- Cargo.lock | 83 ++++++++++--------- Cargo.toml | 2 +- .../src/server/db/series/bitspec/field.rs | 37 +++++---- crates/protocol/src/lib.rs | 1 + 4 files changed, 64 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0f256b41..357c7ea3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -332,7 +332,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -415,7 +415,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -599,9 +599,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052" +checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" [[package]] name = "cfg-if" @@ -661,7 +661,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -808,7 +808,7 @@ dependencies = [ "bitflags 2.6.0", "crossterm_winapi", "libc", - "mio", + "mio 0.8.11", "parking_lot 0.12.3", "signal-hook", "signal-hook-mio", @@ -887,7 +887,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -919,7 +919,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -959,7 +959,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -1016,7 +1016,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -1253,7 +1253,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -1887,6 +1887,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mio" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "wasi", + "windows-sys 0.52.0", +] + [[package]] name = "mpd" version = "0.1.0" @@ -2049,16 +2061,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.9", - "libc", -] - [[package]] name = "object" version = "0.32.2" @@ -2169,7 +2171,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2615,7 +2617,7 @@ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2698,7 +2700,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" dependencies = [ "libc", - "mio", + "mio 0.8.11", "signal-hook", ] @@ -2795,7 +2797,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" dependencies = [ "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2835,7 +2837,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2851,9 +2853,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.71" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -2936,7 +2938,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2996,32 +2998,31 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.1" +version = "1.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" +checksum = "9c3318c4fc7126c339a40fbc025927d0328ca32259f68bfe4321660644c1f626" dependencies = [ "backtrace", "bytes", "libc", - "mio", - "num_cpus", + "mio 1.0.1", "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", "socket2 0.5.7", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -3109,7 +3110,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -3347,7 +3348,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", "wasm-bindgen-shared", ] @@ -3381,7 +3382,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3608,5 +3609,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] diff --git a/Cargo.toml b/Cargo.toml index 1ab9bf81..a2d7b4ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [workspace] resolver = "2" members = ["crates/*"] -exclude = ["sensor-nodes/*"] +exclude = ["sensor-nodes/bed-sensors"] [workspace.dependencies] data-server = { path = "crates/data-server" } diff --git a/crates/data-store/src/server/db/series/bitspec/field.rs b/crates/data-store/src/server/db/series/bitspec/field.rs index 9086624c..9f77beb2 100644 --- a/crates/data-store/src/server/db/series/bitspec/field.rs +++ b/crates/data-store/src/server/db/series/bitspec/field.rs @@ -15,21 +15,22 @@ pub struct Field { impl Field where T: num::cast::NumCast - + std::fmt::Display - + std::ops::Add - + std::ops::SubAssign - + std::ops::DivAssign - + std::ops::MulAssign - + std::marker::Copy, + + core::ops::Add + + core::ops::SubAssign + + core::ops::DivAssign + + core::ops::MulAssign + + core::marker::Copy + + core::fmt::Display + + core::fmt::Debug, { pub fn decode(&self, line: &[u8]) -> D where D: num::cast::NumCast - + std::fmt::Display - + std::ops::Add - + std::ops::SubAssign - + std::ops::MulAssign - + std::ops::AddAssign, + + core::fmt::Display + + core::ops::Add + + core::ops::SubAssign + + core::ops::MulAssign + + core::ops::AddAssign, { let int_repr: u32 = compression::decode(line, self.offset, self.length); let mut decoded: D = num::cast(int_repr).unwrap(); @@ -42,16 +43,18 @@ where pub fn encode(&self, mut numb: T, line: &mut [u8]) where T: num::cast::NumCast - + std::fmt::Display - + std::ops::Add - + std::ops::SubAssign - + std::ops::AddAssign - + std::ops::DivAssign, + + core::fmt::Display + + core::ops::Add + + core::ops::SubAssign + + core::ops::AddAssign + + core::ops::DivAssign, { numb -= num::cast(self.decode_add).unwrap(); numb /= num::cast(self.decode_scale).unwrap(); - let to_encode: u32 = num::cast(numb).unwrap(); + let to_encode: u32 = num::cast(numb).expect(&format!( + "could not cast numb to u32, numb: {numb}, field: {self:?}", + )); compression::encode(to_encode, line, self.offset, self.length); } diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 10fc2f75..9eb538ab 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -77,6 +77,7 @@ impl Reading { self.leaf().range } #[must_use] + /// the step between the two closest datapoints that are not the same pub fn resolution(&self) -> f32 { use reading_tree::Tree; self.leaf().resolution From 9ce418639f521c73770da155d87e6c7485f708cf Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 23 Jul 2024 23:04:02 +0200 Subject: [PATCH 169/687] clippy + add temporal resolution & min sample interval to protocol::ReadingInfo --- crates/protocol/src/button.rs | 3 + crates/protocol/src/large_bedroom/bed.rs | 62 ++++++++++++-------- crates/protocol/src/large_bedroom/desk.rs | 15 ++++- crates/protocol/src/reading_tree.rs | 4 ++ crates/protocol/src/small_bedroom.rs | 1 + sensor-nodes/bed-sensors/src/sensors/fast.rs | 6 +- 6 files changed, 59 insertions(+), 32 deletions(-) diff --git a/crates/protocol/src/button.rs b/crates/protocol/src/button.rs index 18fc919f..427eb9b9 100644 --- a/crates/protocol/src/button.rs +++ b/crates/protocol/src/button.rs @@ -78,6 +78,8 @@ macro_rules! button_enum { resolution: 1.0, unit: crate::Unit::None, branch_id: self.branch_id(), + min_sample_interval: core::time::Duration::from_millis(2), + temporal_resolution: core::time::Duration::from_millis(1), }) } fn name(&self) -> String { @@ -99,6 +101,7 @@ macro_rules! button_enum { } impl $name { + #[must_use] pub fn is_same_as(&self, other: &Self) -> bool { match (self, other) { $(($name::$variant(_), $name::$variant(_)) => true,)* diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 46dad32a..fd553c07 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -87,15 +87,22 @@ impl Tree for Reading { #[allow(clippy::too_many_lines)] #[allow(clippy::cast_precision_loss)] fn inner(&self) -> Item<'_> { + // temporal resolution should be 1 + let mut min_sample_interval = Duration::from_secs(5); + let mut temporal_resolution = Duration::from_millis(1); let (val, device, range, resolution, unit, description) = match self { - Reading::Brightness(val) => ( - *val, - Device::Max44.rooted(), - 0.045..188.000, - 0.045, - Unit::Lux, - "Brightness", - ), + Reading::Brightness(val) => { + min_sample_interval = Duration::from_millis(50); + temporal_resolution = Duration::from_millis(50); + ( + *val, + Device::Max44.rooted(), + 0.045..188.000, + 0.045, + Unit::Lux, + "Brightness", + ) + } Reading::Temperature(val) => ( *val, Device::Sht31.rooted(), @@ -247,6 +254,8 @@ impl Tree for Reading { unit, description, branch_id: self.branch_id(), + temporal_resolution, + min_sample_interval, }) } @@ -257,26 +266,27 @@ impl Tree for Reading { } impl Reading { + #[must_use] pub fn is_same_as(&self, other: &Self) -> bool { match (self, other) { - (Self::Brightness(_), Self::Brightness(_)) => true, - (Self::Temperature(_), Self::Temperature(_)) => true, - (Self::Humidity(_), Self::Humidity(_)) => true, - (Self::GassResistance(_), Self::GassResistance(_)) => true, - (Self::Pressure(_), Self::Pressure(_)) => true, - (Self::Co2(_), Self::Co2(_)) => true, - (Self::WeightLeft(_), Self::WeightLeft(0)) => true, - (Self::WeightRight(_), Self::WeightRight(0)) => true, - (Self::MassPm1_0(_), Self::MassPm1_0(_)) => true, - (Self::MassPm2_5(_), Self::MassPm2_5(_)) => true, - (Self::MassPm4_0(_), Self::MassPm4_0(_)) => true, - (Self::MassPm10(_), Self::MassPm10(_)) => true, - (Self::NumberPm0_5(_), Self::NumberPm0_5(_)) => true, - (Self::NumberPm1_0(_), Self::NumberPm1_0(_)) => true, - (Self::NumberPm2_5(_), Self::NumberPm2_5(_)) => true, - (Self::NumberPm4_0(_), Self::NumberPm4_0(_)) => true, - (Self::NumberPm10(_), Self::NumberPm10(_)) => true, - (Self::TypicalParticleSize(_), Self::TypicalParticleSize(_)) => true, + (Self::Brightness(_), Self::Brightness(_)) + | (Self::Temperature(_), Self::Temperature(_)) + | (Self::Humidity(_), Self::Humidity(_)) + | (Self::GassResistance(_), Self::GassResistance(_)) + | (Self::Pressure(_), Self::Pressure(_)) + | (Self::Co2(_), Self::Co2(_)) + | (Self::WeightLeft(_), Self::WeightLeft(0)) + | (Self::WeightRight(_), Self::WeightRight(0)) + | (Self::MassPm1_0(_), Self::MassPm1_0(_)) + | (Self::MassPm2_5(_), Self::MassPm2_5(_)) + | (Self::MassPm4_0(_), Self::MassPm4_0(_)) + | (Self::MassPm10(_), Self::MassPm10(_)) + | (Self::NumberPm0_5(_), Self::NumberPm0_5(_)) + | (Self::NumberPm1_0(_), Self::NumberPm1_0(_)) + | (Self::NumberPm2_5(_), Self::NumberPm2_5(_)) + | (Self::NumberPm4_0(_), Self::NumberPm4_0(_)) + | (Self::NumberPm10(_), Self::NumberPm10(_)) + | (Self::TypicalParticleSize(_), Self::TypicalParticleSize(_)) => true, (Self::Button(a), Self::Button(b)) => a.is_same_as(b), _ => false, } diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index 8a0005bd..2dbd16ed 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -1,3 +1,6 @@ +#[cfg(feature = "alloc")] +use core::time::Duration; + use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -54,6 +57,8 @@ impl Tree for Reading { unit: Unit::C, description: "Temperature", branch_id: self.branch_id(), + min_sample_interval: Duration::from_secs(5), + temporal_resolution: Duration::from_secs(1), }, Reading::Humidity(val) => ReadingInfo { val: *val, @@ -63,6 +68,8 @@ impl Tree for Reading { unit: Unit::RH, description: "Temperature", branch_id: self.branch_id(), + min_sample_interval: Duration::from_secs(5), + temporal_resolution: Duration::from_secs(1), }, Reading::Pressure(val) => ReadingInfo { val: *val, @@ -72,6 +79,8 @@ impl Tree for Reading { unit: Unit::Pa, description: "Air pressure", branch_id: self.branch_id(), + min_sample_interval: Duration::from_secs(5), + temporal_resolution: Duration::from_secs(1), }, Reading::Button(val) => return Item::Node(val as &dyn Tree), }; @@ -88,9 +97,9 @@ impl Reading { #[must_use] pub fn is_same_as(&self, other: &Self) -> bool { match (self, other) { - (Reading::Temperature(_), Self::Temperature(_)) => true, - (Reading::Humidity(_), Self::Humidity(_)) => true, - (Reading::Pressure(_), Self::Pressure(_)) => true, + (Reading::Temperature(_), Self::Temperature(_)) + | (Reading::Humidity(_), Self::Humidity(_)) + | (Reading::Pressure(_), Self::Pressure(_)) => true, (Reading::Button(a), Self::Button(b)) => a.is_same_as(b), _ => false, } diff --git a/crates/protocol/src/reading_tree.rs b/crates/protocol/src/reading_tree.rs index 4ec1ca95..2694a5b1 100644 --- a/crates/protocol/src/reading_tree.rs +++ b/crates/protocol/src/reading_tree.rs @@ -1,3 +1,5 @@ +use core::time::Duration; + use crate::{Device, Reading, Unit}; #[derive(Debug)] @@ -6,6 +8,8 @@ pub struct ReadingInfo { pub device: Device, /// smallest step size the data can make pub resolution: f32, + pub temporal_resolution: Duration, + pub min_sample_interval: Duration, pub range: core::ops::Range, pub unit: Unit, pub description: &'static str, diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index 168f7c22..f7fdf31a 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -51,6 +51,7 @@ impl Tree for Reading { } impl Reading { + #[must_use] pub fn is_same_as(&self, other: &Self) -> bool { match (self, other) { (Self::ButtonPanel(a), Self::ButtonPanel(b)) => a.is_same_as(b) diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed-sensors/src/sensors/fast.rs index 725dce3d..64e53945 100644 --- a/sensor-nodes/bed-sensors/src/sensors/fast.rs +++ b/sensor-nodes/bed-sensors/src/sensors/fast.rs @@ -15,7 +15,7 @@ fn sig_lux_diff(old: f32, new: f32) -> bool { } async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues) { - const MIN_INTERVAL: Duration = Duration::from_secs(1); + const MAX_INTERVAL: Duration = Duration::from_secs(1); let mut prev_lux = f32::MAX; let mut last_lux = Instant::now(); @@ -25,7 +25,7 @@ async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues) { Timer::after_millis(50).await; let lux = match max44.try_measure().await { Ok(lux) => lux, - Err(err) if last_lux.elapsed() > MIN_INTERVAL => { + Err(err) if last_lux.elapsed() > MAX_INTERVAL => { publish.queue_error(err); continue; } @@ -34,7 +34,7 @@ async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues) { if sig_lux_diff(prev_lux, lux) { publish.send_p2(Reading::Brightness(lux)); - } else if last_lux.elapsed() > MIN_INTERVAL { + } else if last_lux.elapsed() > MAX_INTERVAL { publish.send_p1(Reading::Brightness(lux)); } else { yield_now().await; From 8dce9ab10fb83389e5e8347c383264f9e16b15eb Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 25 Jul 2024 00:53:42 +0200 Subject: [PATCH 170/687] refactor introduce DeviceInfo analogous to ReadingInfo, move temporal_resolution & min_interval to DeviceInfo --- crates/protocol/src/button.rs | 2 - crates/protocol/src/large_bedroom.rs | 15 +-- crates/protocol/src/large_bedroom/bed.rs | 145 +++++++++++++--------- crates/protocol/src/large_bedroom/desk.rs | 33 ++--- crates/protocol/src/lib.rs | 22 ++-- crates/protocol/src/reading_tree.rs | 6 +- crates/protocol/src/small_bedroom.rs | 36 +++--- 7 files changed, 134 insertions(+), 125 deletions(-) diff --git a/crates/protocol/src/button.rs b/crates/protocol/src/button.rs index 427eb9b9..240d872a 100644 --- a/crates/protocol/src/button.rs +++ b/crates/protocol/src/button.rs @@ -78,8 +78,6 @@ macro_rules! button_enum { resolution: 1.0, unit: crate::Unit::None, branch_id: self.branch_id(), - min_sample_interval: core::time::Duration::from_millis(2), - temporal_resolution: core::time::Duration::from_millis(1), }) } fn name(&self) -> String { diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index 12d43032..5082ea60 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -67,18 +67,13 @@ pub enum Device { Bed(bed::Device), Desk(desk::Device), } -impl Device { - pub(crate) fn affected_readings(&self) -> &'static [crate::Reading] { - match self { - Self::Bed(dev) => dev.affected_readings(), - Self::Desk(dev) => dev.affected_readings(), - } - } - pub(crate) fn as_str(&self) -> &'static str { +impl Device { + #[must_use] + pub const fn info(&self) -> crate::DeviceInfo { match self { - Self::Bed(dev) => dev.as_str(), - Self::Desk(dev) => dev.as_str(), + Self::Bed(dev) => dev.info(), + Self::Desk(dev) => dev.info(), } } } diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index fd553c07..82414d24 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -1,3 +1,5 @@ +use core::time::Duration; + use crate::button::Press; use crate::button_enum; #[cfg(feature = "alloc")] @@ -87,22 +89,15 @@ impl Tree for Reading { #[allow(clippy::too_many_lines)] #[allow(clippy::cast_precision_loss)] fn inner(&self) -> Item<'_> { - // temporal resolution should be 1 - let mut min_sample_interval = Duration::from_secs(5); - let mut temporal_resolution = Duration::from_millis(1); let (val, device, range, resolution, unit, description) = match self { - Reading::Brightness(val) => { - min_sample_interval = Duration::from_millis(50); - temporal_resolution = Duration::from_millis(50); - ( - *val, - Device::Max44.rooted(), - 0.045..188.000, - 0.045, - Unit::Lux, - "Brightness", - ) - } + Reading::Brightness(val) => ( + *val, + Device::Max44.rooted(), + 0.045..188.000, + 0.045, + Unit::Lux, + "Brightness", + ), Reading::Temperature(val) => ( *val, Device::Sht31.rooted(), @@ -254,8 +249,6 @@ impl Tree for Reading { unit, description, branch_id: self.branch_id(), - temporal_resolution, - min_sample_interval, }) } @@ -380,7 +373,7 @@ pub enum Device { impl core::fmt::Display for Device { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "{}", self.as_str()) + write!(f, "{}", self.info().name) } } @@ -393,53 +386,81 @@ macro_rules! tree { } impl Device { - #[must_use] - pub fn as_str(&self) -> &'static str { - match self { - Device::Sht31 => "Sht31", - Device::Bme680 => "Bme680", - Device::Max44 => "Max44", - Device::Mhz14 => "Mhz14", - Device::Sps30 => "Sps30", - Device::Nau7802Left => "Nau7802Left", - Device::Nau7802Right => "Nau7802Right", - Device::Gpio => "Gpio", - } - } - - /// Note the order in which these occur is the order in which + /// Note the order in which the affects_readings occur is the order in which /// they will be stored, do not change it! #[must_use] - pub const fn affected_readings(&self) -> &'static [crate::Reading] { + pub const fn info(&self) -> crate::DeviceInfo { + let min_sample_interval = Duration::from_secs(5); + let temporal_resolution = Duration::from_millis(1); match self { - Device::Sht31 => &tree![Reading::Temperature(0.0), Reading::Humidity(0.0)], - Device::Bme680 => &tree![Reading::GassResistance(0.0), Reading::Pressure(0.0)], - Device::Max44 => &tree![Reading::Brightness(0.0)], - Device::Mhz14 => &tree![Reading::Co2(0)], - Device::Sps30 => &tree![ - Reading::MassPm1_0(0.0), - Reading::MassPm2_5(0.0), - Reading::MassPm4_0(0.0), - Reading::MassPm10(0.0), - Reading::NumberPm0_5(0.0), - Reading::NumberPm1_0(0.0), - Reading::NumberPm2_5(0.0), - Reading::NumberPm4_0(0.0), - Reading::NumberPm10(0.0), - Reading::TypicalParticleSize(0.0) - ], - Device::Nau7802Left => &tree![Reading::WeightLeft(0)], - Device::Nau7802Right => &tree![Reading::WeightRight(0)], - Device::Gpio => &tree![ - Reading::Button(Button::TopLeft(Press(0))), - Reading::Button(Button::TopRight(Press(0))), - Reading::Button(Button::MiddleInner(Press(0))), - Reading::Button(Button::MiddleCenter(Press(0))), - Reading::Button(Button::MiddleOuter(Press(0))), - Reading::Button(Button::LowerInner(Press(0))), - Reading::Button(Button::LowerCenter(Press(0))), - Reading::Button(Button::LowerOuter(Press(0))) - ], + Device::Sht31 => crate::DeviceInfo { + name: "Sht31", + affects_readings: &tree![Reading::Temperature(0.0), Reading::Humidity(0.0)], + temporal_resolution, + min_sample_interval, + }, + Device::Bme680 => crate::DeviceInfo { + name: "Bme680", + affects_readings: &tree![Reading::GassResistance(0.0), Reading::Pressure(0.0)], + temporal_resolution, + min_sample_interval, + }, + Device::Max44 => crate::DeviceInfo { + name: "Max44", + affects_readings: &tree![Reading::Brightness(0.0)], + temporal_resolution: Duration::from_millis(50), + min_sample_interval: Duration::from_millis(50), + }, + Device::Mhz14 => crate::DeviceInfo { + name: "Mhz14", + affects_readings: &tree![Reading::Co2(0)], + temporal_resolution, + min_sample_interval, + }, + Device::Sps30 => crate::DeviceInfo { + name: "Sps30", + affects_readings: &tree![ + Reading::MassPm1_0(0.0), + Reading::MassPm2_5(0.0), + Reading::MassPm4_0(0.0), + Reading::MassPm10(0.0), + Reading::NumberPm0_5(0.0), + Reading::NumberPm1_0(0.0), + Reading::NumberPm2_5(0.0), + Reading::NumberPm4_0(0.0), + Reading::NumberPm10(0.0), + Reading::TypicalParticleSize(0.0) + ], + temporal_resolution, + min_sample_interval, + }, + Device::Nau7802Left => crate::DeviceInfo { + name: "Nau7802Left", + affects_readings: &tree![Reading::WeightLeft(0)], + temporal_resolution: Duration::from_millis(100), + min_sample_interval: Duration::from_millis(100), + }, + Device::Nau7802Right => crate::DeviceInfo { + name: "Nau7802Right", + affects_readings: &tree![Reading::WeightRight(0)], + temporal_resolution, + min_sample_interval, + }, + Device::Gpio => crate::DeviceInfo { + name: "Gpio", + affects_readings: &tree![ + Reading::Button(Button::TopLeft(Press(0))), + Reading::Button(Button::TopRight(Press(0))), + Reading::Button(Button::MiddleInner(Press(0))), + Reading::Button(Button::MiddleCenter(Press(0))), + Reading::Button(Button::MiddleOuter(Press(0))), + Reading::Button(Button::LowerInner(Press(0))), + Reading::Button(Button::LowerCenter(Press(0))), + Reading::Button(Button::LowerOuter(Press(0))) + ], + temporal_resolution: Duration::from_millis(1), + min_sample_interval: Duration::from_millis(2), + }, } } diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index 2dbd16ed..9a0aad05 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -57,8 +57,6 @@ impl Tree for Reading { unit: Unit::C, description: "Temperature", branch_id: self.branch_id(), - min_sample_interval: Duration::from_secs(5), - temporal_resolution: Duration::from_secs(1), }, Reading::Humidity(val) => ReadingInfo { val: *val, @@ -68,8 +66,6 @@ impl Tree for Reading { unit: Unit::RH, description: "Temperature", branch_id: self.branch_id(), - min_sample_interval: Duration::from_secs(5), - temporal_resolution: Duration::from_secs(1), }, Reading::Pressure(val) => ReadingInfo { val: *val, @@ -79,8 +75,6 @@ impl Tree for Reading { unit: Unit::Pa, description: "Air pressure", branch_id: self.branch_id(), - min_sample_interval: Duration::from_secs(5), - temporal_resolution: Duration::from_secs(1), }, Reading::Button(val) => return Item::Node(val as &dyn Tree), }; @@ -171,7 +165,7 @@ pub enum Device { impl core::fmt::Display for Device { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "{}", self.as_str()) + write!(f, "{}", self.info().name) } } @@ -188,21 +182,20 @@ impl Device { pub fn rooted(self) -> crate::Device { crate::Device::LargeBedroom(crate::large_bedroom::Device::Desk(self)) } + #[must_use] - pub fn as_str(&self) -> &'static str { - match self { - Device::Bme280 => "Bme280", - Device::Gpio => "Gpio", - } - } - #[must_use] - pub fn affected_readings(&self) -> &'static [crate::Reading] { + pub const fn info(&self) -> crate::DeviceInfo { match self { - Device::Bme280 => &rtree![ - Reading::Temperature(0.0), - Reading::Humidity(0.0), - Reading::Pressure(0.0) - ], + Device::Bme280 => crate::DeviceInfo { + name: "Bme280", + affects_readings: &rtree![ + Reading::Temperature(0.0), + Reading::Humidity(0.0), + Reading::Pressure(0.0) + ], + min_sample_interval: Duration::from_secs(5), + temporal_resolution: Duration::from_secs(1), + }, Device::Gpio => todo!(), } } diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 9eb538ab..bbc9d983 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -2,6 +2,7 @@ #![allow(clippy::missing_panics_doc, clippy::missing_errors_doc)] use core::fmt::Display; +use core::time::Duration; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -119,21 +120,22 @@ pub enum Device { } impl Device { #[must_use] - pub fn affected_readings(&self) -> &'static [Reading] { + pub const fn info(&self) -> DeviceInfo { match self { - Device::LargeBedroom(dev) => dev.affected_readings(), - Device::SmallBedroom(dev) => dev.affected_readings(), - } - } - #[must_use] - pub fn as_str(&self) -> &'static str { - match self { - Device::LargeBedroom(dev) => dev.as_str(), - Device::SmallBedroom(dev) => dev.as_str(), + Device::LargeBedroom(dev) => dev.info(), + Device::SmallBedroom(dev) => dev.info(), } } } +pub struct DeviceInfo { + pub name: &'static str, + pub affects_readings: &'static [Reading], + pub min_sample_interval: Duration, + pub temporal_resolution: Duration, +} + + impl Error { #[must_use] pub fn device(&self) -> Device { diff --git a/crates/protocol/src/reading_tree.rs b/crates/protocol/src/reading_tree.rs index 2694a5b1..34c17bba 100644 --- a/crates/protocol/src/reading_tree.rs +++ b/crates/protocol/src/reading_tree.rs @@ -1,5 +1,3 @@ -use core::time::Duration; - use crate::{Device, Reading, Unit}; #[derive(Debug)] @@ -8,8 +6,6 @@ pub struct ReadingInfo { pub device: Device, /// smallest step size the data can make pub resolution: f32, - pub temporal_resolution: Duration, - pub min_sample_interval: Duration, pub range: core::ops::Range, pub unit: Unit, pub description: &'static str, @@ -19,7 +15,7 @@ pub struct ReadingInfo { impl ReadingInfo { #[must_use] pub fn from_same_device(&self) -> &'static [Reading] { - self.device.affected_readings() + self.device.info().affects_readings } /// useful for printing/formatting floats diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index f7fdf31a..3656c179 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -1,3 +1,5 @@ +use core::time::Duration; + use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -54,7 +56,7 @@ impl Reading { #[must_use] pub fn is_same_as(&self, other: &Self) -> bool { match (self, other) { - (Self::ButtonPanel(a), Self::ButtonPanel(b)) => a.is_same_as(b) + (Self::ButtonPanel(a), Self::ButtonPanel(b)) => a.is_same_as(b), } } } @@ -73,22 +75,24 @@ macro_rules! tree { } impl Device { - pub(crate) fn affected_readings(&self) -> &'static [crate::Reading] { - match self { - Device::Gpio => &tree![ - ButtonPanel::TopLeft(Press(0)), - ButtonPanel::TopMiddle(Press(0)), - ButtonPanel::TopRight(Press(0)), - ButtonPanel::BottomLeft(Press(0)), - ButtonPanel::BottomMiddle(Press(0)), - ButtonPanel::BOttomRight(Press(0)) - ] - } - } - - pub(crate) fn as_str(&self) -> &'static str { + /// Note the order in which the affects_readings occur is the order in which + /// they will be stored, do not change it! + #[must_use] + pub const fn info(&self) -> crate::DeviceInfo { match self { - Device::Gpio => "Gpio", + Device::Gpio => crate::DeviceInfo { + name: "Gpio", + affects_readings: &tree![ + ButtonPanel::TopLeft(Press(0)), + ButtonPanel::TopMiddle(Press(0)), + ButtonPanel::TopRight(Press(0)), + ButtonPanel::BottomLeft(Press(0)), + ButtonPanel::BottomMiddle(Press(0)), + ButtonPanel::BOttomRight(Press(0)) + ], + temporal_resolution: Duration::from_millis(1), + min_sample_interval: Duration::from_millis(2), + }, } } } From c78faf7180ff4705af6709c90839be38b41a18c7 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 25 Jul 2024 01:54:52 +0200 Subject: [PATCH 171/687] move from time to jiff, add support for millisecond temporal resolution --- Cargo.lock | 31 +++++++- Cargo.toml | 1 + crates/data-store/Cargo.toml | 2 +- crates/data-store/examples/last_15m.rs | 6 +- crates/data-store/src/api.rs | 7 +- crates/data-store/src/api/client.rs | 8 +- crates/data-store/src/server/db.rs | 21 +++-- crates/data-store/src/server/db/series.rs | 79 +++++++++++++++---- .../src/server/db/series/resampler.rs | 2 +- crates/data-store/tests/list_data.rs | 5 +- crates/protocol/src/large_bedroom/bed.rs | 2 +- crates/protocol/src/lib.rs | 1 + crates/sensor-tui/Cargo.toml | 2 +- crates/sensor-tui/src/tui/reading.rs | 24 +++--- crates/sensor-tui/src/tui/reading/fetch.rs | 19 +++-- 15 files changed, 148 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 357c7ea3..d13a6b89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -850,6 +850,7 @@ dependencies = [ "data-server", "futures", "futures-concurrency", + "jiff", "nucleo-matcher", "num", "protocol", @@ -858,7 +859,6 @@ dependencies = [ "smallvec 2.0.0-alpha.6", "temp-dir", "thiserror", - "time", "tokio", "tokio-serde", "tokio-util", @@ -906,7 +906,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", - "serde", ] [[package]] @@ -1695,6 +1694,32 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "jiff" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fbd74d242eb38b2f0d73c9ad5e7e4371525d856e64018939874380494ce4ed6" +dependencies = [ + "jiff-tzdb-platform", + "serde", + "windows-sys 0.52.0", +] + +[[package]] +name = "jiff-tzdb" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05fac328b3df1c0f18a3c2ab6cb7e06e4e549f366017d796e3e66b6d6889abe6" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8da387d5feaf355954c2c122c194d6df9c57d865125a67984bb453db5336940" +dependencies = [ + "jiff-tzdb", +] + [[package]] name = "js-sys" version = "0.3.69" @@ -2589,10 +2614,10 @@ dependencies = [ "data-store", "histogram", "itertools", + "jiff", "protocol", "ratatui", "thiserror", - "time", "tokio", "tracing", "tracing-error", diff --git a/Cargo.toml b/Cargo.toml index a2d7b4ef..e07a3c52 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ tracing = "0.1.40" tracing-error = "0.2.0" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } time = "0.3.36" +jiff = "0.1" clap = { version = "4", features = ["derive"]} thiserror = "1" diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index b9a662fe..c7a41943 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -17,7 +17,7 @@ color-eyre = { workspace = true } tracing = { workspace = true } tracing-error = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } -time = { workspace = true, features = ["serde"] } +jiff = { workspace =true, features = ["serde"] } protocol = { workspace = true, features = ["alloc", "thiserror"] } data-server = { workspace = true } diff --git a/crates/data-store/examples/last_15m.rs b/crates/data-store/examples/last_15m.rs index cd1ec9cb..7ac26f9d 100644 --- a/crates/data-store/examples/last_15m.rs +++ b/crates/data-store/examples/last_15m.rs @@ -1,10 +1,10 @@ +use jiff::ToSpan; use nucleo_matcher::pattern::Pattern; use protocol::Reading; use std::net::SocketAddr; use data_store::api::Client; use nucleo_matcher::pattern::{AtomKind, CaseMatching, Normalization}; -use time::{Duration, OffsetDateTime}; use clap::Parser; @@ -55,9 +55,9 @@ async fn main() { .1; println!("Showing results for: {best_scored:?}"); - let now = OffsetDateTime::now_utc(); + let now = jiff::Timestamp::now(); let data = client - .get_data(now - Duration::minutes(5), now, best_scored, 10) + .get_data(now - 5.minutes(), now, best_scored, 10) .await .unwrap(); diff --git a/crates/data-store/src/api.rs b/crates/data-store/src/api.rs index 234ba817..93431a8f 100644 --- a/crates/data-store/src/api.rs +++ b/crates/data-store/src/api.rs @@ -1,7 +1,6 @@ use protocol::Reading; use serde::{Deserialize, Serialize}; -use time::OffsetDateTime; mod client; pub use client::Client; @@ -14,8 +13,8 @@ pub(crate) enum Request { ListData, GetData { reading: Reading, - start: OffsetDateTime, - end: OffsetDateTime, + start: jiff::Timestamp, + end: jiff::Timestamp, n: usize, }, } @@ -32,7 +31,7 @@ pub enum ServerError { pub(crate) enum Response { ListData(Vec), GetData { - time: Vec, + time: Vec, data: Vec, }, Error(ServerError), diff --git a/crates/data-store/src/api/client.rs b/crates/data-store/src/api/client.rs index 7fa25bd3..cdbb95fe 100644 --- a/crates/data-store/src/api/client.rs +++ b/crates/data-store/src/api/client.rs @@ -4,8 +4,6 @@ use tokio::net::ToSocketAddrs; use tokio_serde::formats::Bincode; use tokio_util::codec::{Framed, LengthDelimitedCodec}; -use time::OffsetDateTime; - pub struct Client { stream: tokio_serde::Framed< Framed, @@ -70,11 +68,11 @@ impl Client { pub async fn get_data( &mut self, - start: OffsetDateTime, - end: OffsetDateTime, + start: jiff::Timestamp, + end: jiff::Timestamp, reading: protocol::Reading, n: usize, - ) -> Result<(Vec, Vec), Error> { + ) -> Result<(Vec, Vec), Error> { let request = super::Request::GetData { reading, start, diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index f906d72c..b9ac551b 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -2,9 +2,9 @@ use std::collections::HashMap; use std::net::SocketAddr; use std::path::Path; use std::sync::Arc; +use std::time::{Duration, Instant}; use data_server::subscriber::reconnecting; -use time::OffsetDateTime; use tokio::sync::Mutex; use color_eyre::Result; @@ -18,6 +18,7 @@ use crate::api; pub(crate) async fn run(data_server_addr: SocketAddr, data: Data, data_dir: &Path) -> Result<()> { let mut sub = reconnecting::Subscriber::new(data_server_addr, "ha-data-store".to_string()); + let mut recently_logged = (Instant::now(), String::new()); loop { let msg = sub.next_msg().await; let res = match msg { @@ -25,8 +26,16 @@ pub(crate) async fn run(data_server_addr: SocketAddr, data: Data, data_dir: &Pat SubMessage::ErrorReport(_) => continue, }; + const FIVE_MIN: Duration = Duration::from_secs(60 * 5); if let Err(e) = res { - tracing::error!("Error processing new reading: {e:?}"); + let e = e.to_string(); + tracing::warn!("test: {e}"); + if recently_logged.1 == e && recently_logged.0.elapsed() <= FIVE_MIN { + continue; + } else { + tracing::error!("Error processing new reading: {e}"); + recently_logged = (Instant::now(), e); + } } } } @@ -40,17 +49,17 @@ impl Data { .lock() .await .keys() - .flat_map(protocol::Device::affected_readings) + .flat_map(|dev| dev.info().affects_readings) .cloned() .collect() } pub(crate) async fn get( &self, reading: protocol::Reading, - start: OffsetDateTime, - end: OffsetDateTime, + start: jiff::Timestamp, + end: jiff::Timestamp, n: usize, - ) -> Result<(Vec, Vec), api::ServerError> { + ) -> Result<(Vec, Vec), api::ServerError> { let key = reading.device(); let mut all_series = self.0.lock().await; let series = all_series diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index 3704897d..24e0f63d 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -8,7 +8,6 @@ use color_eyre::eyre::{eyre, WrapErr}; use color_eyre::{Result, Section}; use protocol::reading_tree::{Item, ReadingInfo, Tree}; use serde::{Deserialize, Serialize}; -use time::OffsetDateTime; use tracing::{info, instrument, trace}; use byteseries::file::OpenError as FileOpenError; @@ -44,7 +43,7 @@ struct Header { impl Series { fn open_or_create(reading: &protocol::Reading, dir: &Path) -> Result { - let readings = reading.device().affected_readings(); + let readings = reading.device().info().affects_readings; let specs = to_speclist(readings); let fields = bitspec::speclist_to_fields(specs); let meta = readings @@ -111,7 +110,8 @@ impl Series { fn append(&mut self, reading: &protocol::Reading) -> Result<()> { let index = reading .device() - .affected_readings() + .info() + .affects_readings .iter() .map(|r| r.leaf().branch_id) .position(|id_in_list| id_in_list == reading.leaf().branch_id) @@ -130,15 +130,14 @@ impl Series { .map(|Meta { set_at, .. }| set_at) .all(|set| set.map(|s| s.elapsed().as_millis() < 500).unwrap_or(false)) { - let time = OffsetDateTime::now_utc() - - self.meta[index] - .set_at - .take() - .expect("if any is None the if is false") - .elapsed(); + let time = jiff::Timestamp::now(); + let device_info = reading.leaf().device.info(); + let scale_factor = millis_to_minimal_representation(dbg!(device_info)); + let scaled_time = time.as_millisecond() as u64 / scale_factor; + tracing::warn!("{scale_factor}, {}, {scaled_time}", time.as_millisecond()); self.byteseries - .push_line(time.unix_timestamp() as u64, &self.line) + .push_line(scaled_time, &self.line) .wrap_err("Could not write to timeseries on disk")?; self.line.fill(0); } @@ -152,11 +151,20 @@ impl Series { pub fn read( &mut self, readings: &[protocol::Reading], - start: OffsetDateTime, - end: OffsetDateTime, + start: jiff::Timestamp, + end: jiff::Timestamp, n: usize, - ) -> Result<(Vec, Vec>), byteseries::series::Error> { - let range = start.unix_timestamp() as u64..=end.unix_timestamp() as u64; + ) -> Result<(Vec, Vec>), byteseries::series::Error> { + let device_info = readings + .first() + .expect("There is at least one reading to read") + .leaf() + .device + .info(); + let scale_factor = millis_to_minimal_representation(device_info); + let start = start.as_millisecond() as u64 / scale_factor; + let end = end.as_millisecond() as u64 / scale_factor; + let range = start..=end; let fields = readings .iter() .map(|requested| { @@ -188,8 +196,9 @@ impl Series { let time = timestamps .into_iter() .map(|ts| { - OffsetDateTime::from_unix_timestamp(ts as i64) - .expect("only valid timestamps are stored in byteseries") + let millis = ts * scale_factor; + jiff::Timestamp::from_millisecond(millis as i64) + .expect("timestamps are between MIN and MAX times of Timestamp type") }) .collect(); @@ -207,6 +216,20 @@ impl Series { } } +/// Multiplying the time for this sample by this factor +/// allows you to save the whole number and retain the required +/// temporal_resolution and min_sample_interval. +pub fn millis_to_minimal_representation(device_info: protocol::DeviceInfo) -> u64 { + let needed_interval = device_info + .temporal_resolution + .min(device_info.min_sample_interval) + .as_secs_f32(); + let mul_factor = 0.001 / needed_interval; + let div_factor = 1. / mul_factor; + let div_factor = div_factor.round() as u64; + div_factor +} + fn try_create_new_if_open_failed( res: Result<(ByteSeries, Header), series::Error>, expected_header: Header, @@ -303,7 +326,7 @@ fn base_path(reading: &protocol::Reading) -> PathBuf { loop { match current.inner() { Item::Leaf(ReadingInfo { device, .. }) => { - parts.push(device.as_str().to_lowercase()); + parts.push(device.info().name.to_lowercase()); break; } Item::Node(inner) => { @@ -322,6 +345,28 @@ mod test { use protocol::large_bedroom::{bed, desk}; use protocol::{large_bedroom, Reading}; + #[test] + fn millis_to_minimal_representation_factor_makes_sense() { + let info = protocol::DeviceInfo { + name: "test", + affects_readings: &[], + min_sample_interval: std::time::Duration::from_secs(5), + temporal_resolution: std::time::Duration::from_secs(1), + }; + let factor = millis_to_minimal_representation(info); + dbg!(factor); + assert_eq!(5000 / factor, 5); + + let info = protocol::DeviceInfo { + name: "test", + affects_readings: &[], + min_sample_interval: std::time::Duration::from_secs(5), + temporal_resolution: std::time::Duration::from_millis(1), + }; + let factor = millis_to_minimal_representation(info); + assert_eq!(5005 / factor, 5005) + } + #[test] fn readings_from_same_device_have_same_path() { let reading_a = diff --git a/crates/data-store/src/server/db/series/resampler.rs b/crates/data-store/src/server/db/series/resampler.rs index 0d026c46..e067bf3a 100644 --- a/crates/data-store/src/server/db/series/resampler.rs +++ b/crates/data-store/src/server/db/series/resampler.rs @@ -62,7 +62,7 @@ mod test { protocol::large_bedroom::bed::Reading::Temperature(0.5), )); - let readings = reading.device().affected_readings(); + let readings = reading.device().info().affects_readings; // dbg!(readings.iter().map(Tree::leaf).collect::>()); let specs = crate::server::db::series::to_speclist(readings); // dbg!(&specs); diff --git a/crates/data-store/tests/list_data.rs b/crates/data-store/tests/list_data.rs index 801ef6b1..dcab6492 100644 --- a/crates/data-store/tests/list_data.rs +++ b/crates/data-store/tests/list_data.rs @@ -7,7 +7,6 @@ use futures_concurrency::future::Race; use protocol::large_bedroom::bed; use protocol::{large_bedroom, Reading}; use temp_dir::TempDir; -use time::OffsetDateTime; use tokio::io::AsyncWriteExt; use tokio::net::TcpStream; use tokio::sync::{mpsc, Notify}; @@ -90,8 +89,8 @@ async fn check_client_get_data( .unwrap(); let (time, data) = client .get_data( - OffsetDateTime::now_utc() - Duration::from_secs(30), - OffsetDateTime::now_utc() + Duration::from_secs(30), + jiff::Timestamp::now() - jiff::Span::default().seconds(30), + jiff::Timestamp::now() + jiff::Span::default().seconds(30), test_readings(0.0)[0].clone(), 5, ) diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 82414d24..3ef4357b 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -391,7 +391,7 @@ impl Device { #[must_use] pub const fn info(&self) -> crate::DeviceInfo { let min_sample_interval = Duration::from_secs(5); - let temporal_resolution = Duration::from_millis(1); + let temporal_resolution = Duration::from_secs(1); match self { Device::Sht31 => crate::DeviceInfo { name: "Sht31", diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index bbc9d983..c4b2dafb 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -128,6 +128,7 @@ impl Device { } } +#[derive(Debug)] pub struct DeviceInfo { pub name: &'static str, pub affects_readings: &'static [Reading], diff --git a/crates/sensor-tui/Cargo.toml b/crates/sensor-tui/Cargo.toml index ac93b1af..e13557de 100644 --- a/crates/sensor-tui/Cargo.toml +++ b/crates/sensor-tui/Cargo.toml @@ -22,6 +22,6 @@ tracing-subscriber = { workspace =true, features = ["env-filter"] } protocol = { workspace = true, features = ["alloc"] } data-server = { workspace = true } data-store = { workspace = true } -time = { workspace = true } +jiff = { workspace = true } thiserror.workspace = true itertools = "0.13.0" diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index d43dbcb9..30b9ba15 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -8,7 +8,6 @@ use ratatui::{text::Line, widgets::Bar}; use std::collections::HashMap; use std::sync::TryLockError; use std::time::Instant; -use time::OffsetDateTime; use tui_tree_widget::TreeItem; mod fetch; @@ -18,14 +17,14 @@ use fetch::StoredHistory; pub struct SensorInfo { timing: Histogram, pub reading: Reading, - recent_history: Vec<(OffsetDateTime, f32)>, + recent_history: Vec<(jiff::Timestamp, f32)>, pub stored_history: StoredHistory, condition: Result<(), Box>, log: Vec<(Instant, Error)>, } impl SensorInfo { - fn last_at(&self) -> Result> { + fn last_at(&self) -> Result> { self.condition.clone()?; let last = self @@ -61,14 +60,21 @@ impl SensorInfo { .first() .map(|(t, _)| t) .cloned() - .unwrap_or(OffsetDateTime::from_unix_timestamp(0).unwrap()); + .unwrap_or(jiff::Timestamp::default()); plot_buf.clear(); for xy in old_history .iter() .take_while(|(t, _)| *t < first_recent) .chain(self.recent_history.iter()) - .map(|(x, y)| ((*x - *reference).as_seconds_f64(), *y as f64)) + .map(|(x, y)| { + ( + (*x - *reference) + .total(jiff::Unit::Second) + .expect("unit is not a calander unit"), + *y as f64, + ) + }) { plot_buf.push(xy); } @@ -169,7 +175,7 @@ impl Readings { } fn record_error(&mut self, error: Box) { - for broken in error.device().affected_readings() { + for broken in error.device().info().affects_readings { let (key, _, _) = extract_leaf_info(broken); if let Some(info) = self.data.get_mut(&key) { @@ -193,12 +199,12 @@ impl Readings { fn record_data(&mut self, reading: Reading) { let (key, _, val) = extract_leaf_info(&reading); - let time = OffsetDateTime::now_utc(); + let time = jiff::Timestamp::now(); if let Some(info) = self.data.get_mut(&key) { if let Ok(last_reading) = info.last_at() { info.timing - .increment((time - last_reading).whole_milliseconds() as u64) + .increment((time - last_reading).get_milliseconds() as u64) .unwrap(); } info.recent_history.push((time, val)); @@ -249,7 +255,7 @@ impl Readings { } fn update_tree_err(&mut self, error: &Error) { - for broken in error.device().affected_readings() { + for broken in error.device().info().affects_readings { let (key, _, _) = extract_leaf_info(broken); let mut tree = add_root(broken as &dyn Tree, &mut self.ground); diff --git a/crates/sensor-tui/src/tui/reading/fetch.rs b/crates/sensor-tui/src/tui/reading/fetch.rs index 0e9b6088..35414e62 100644 --- a/crates/sensor-tui/src/tui/reading/fetch.rs +++ b/crates/sensor-tui/src/tui/reading/fetch.rs @@ -4,14 +4,12 @@ use std::net::SocketAddr; use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; -use time::OffsetDateTime; use tokio::sync::Notify; use tokio::time::sleep; use tracing::{debug, warn}; use crate::tui::history_len::{self, HistoryLen}; - #[derive(Debug)] struct Fetching { handle: thread::JoinHandle<()>, @@ -19,7 +17,7 @@ struct Fetching { history_length: Duration, } -type Data = Arc>>; +type Data = Arc>>; #[derive(Debug)] pub struct StoredHistory { @@ -84,7 +82,7 @@ impl StoredHistory { } fn fetch_history( - history: Arc>>, + history: Arc>>, reading: Reading, addr: SocketAddr, length: Duration, @@ -106,7 +104,11 @@ fn fetch_history( return; }; - debug!("got data from {:?} till {:?}", data.0.first(), data.0.last()); + debug!( + "got data from {:?} till {:?}", + data.0.first(), + data.0.last() + ); let mut history = history.lock().unwrap(); history.clear(); for (t, y) in data.0.into_iter().zip(data.1) { @@ -119,7 +121,7 @@ async fn connect_and_get_data( addr: SocketAddr, length: Duration, reading: Reading, -) -> (Vec, Vec) { +) -> (Vec, Vec) { let mut retry_period = Duration::ZERO; loop { sleep(retry_period).await; @@ -137,8 +139,9 @@ async fn connect_and_get_data( match api .get_data( - OffsetDateTime::now_utc() - length, - OffsetDateTime::now_utc(), + jiff::Timestamp::now() + - jiff::Span::default().milliseconds(length.as_millis() as i64), + jiff::Timestamp::now(), reading.clone(), 300, ) From 904d0b75aee4561976de0a9d0493203517682067 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 26 Jul 2024 17:31:41 +0200 Subject: [PATCH 172/687] add details to sensor tui + refactor render time code --- crates/protocol/src/large_bedroom/bed.rs | 8 +- crates/protocol/src/large_bedroom/desk.rs | 1 - crates/protocol/src/lib.rs | 35 +++--- crates/sensor-tui/src/main.rs | 1 + crates/sensor-tui/src/time.rs | 2 + crates/sensor-tui/src/time/format.rs | 81 +++++++++++++ .../parse_duration.rs => time/parse.rs} | 26 ----- crates/sensor-tui/src/tui.rs | 41 ++++--- crates/sensor-tui/src/tui/history_len.rs | 8 +- crates/sensor-tui/src/tui/reading.rs | 61 +++++++++- crates/sensor-tui/src/tui/render.rs | 110 ++++++++++++++---- .../sensor-tui/src/tui/render/chart/labels.rs | 83 +------------ crates/sensor-tui/src/tui/render/time.rs | 0 13 files changed, 280 insertions(+), 177 deletions(-) create mode 100644 crates/sensor-tui/src/time.rs create mode 100644 crates/sensor-tui/src/time/format.rs rename crates/sensor-tui/src/{tui/history_len/parse_duration.rs => time/parse.rs} (78%) create mode 100644 crates/sensor-tui/src/tui/render/time.rs diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 3ef4357b..ad112e48 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -307,10 +307,10 @@ impl Error { impl core::fmt::Display for Error { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - Error::Running(e) => write!(f, "{} ran into error: {e}", e.device()), - Error::Setup(e) => write!(f, "{} errored during setup: {e}", e.device()), - Error::SetupTimedOut(d) => write!(f, "{d} timed out during setup"), - Error::Timeout(d) => write!(f, "{d} timed out running"), + Error::Running(e) => write!(f, "{e}"), + Error::Setup(e) => write!(f, "setup: {e}"), + Error::SetupTimedOut(_) => write!(f, "setup timed out"), + Error::Timeout(_) => write!(f, "timed out running"), } } } diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index 9a0aad05..2e04940c 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -1,4 +1,3 @@ -#[cfg(feature = "alloc")] use core::time::Duration; use postcard::experimental::max_size::MaxSize; diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index c4b2dafb..e8a81883 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -113,6 +113,23 @@ pub enum Error { LargeBedroom(large_bedroom::Error), } +impl Error { + #[must_use] + pub fn device(&self) -> Device { + match self { + Error::LargeBedroom(error) => Device::LargeBedroom(error.device()), + } + } +} + +impl Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Error::LargeBedroom(error) => write!(f, "{error}"), + } + } +} + #[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, PartialEq, Eq, Hash)] pub enum Device { LargeBedroom(large_bedroom::Device), @@ -136,24 +153,6 @@ pub struct DeviceInfo { pub temporal_resolution: Duration, } - -impl Error { - #[must_use] - pub fn device(&self) -> Device { - match self { - Error::LargeBedroom(error) => Device::LargeBedroom(error.device()), - } - } -} - -impl core::fmt::Display for Error { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - Error::LargeBedroom(error) => write!(f, "{error}"), - } - } -} - #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SensorMessage { pub values: heapless::Vec, diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index 59d41798..d968d42f 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -8,6 +8,7 @@ use color_eyre::{Help, Result}; use data_server::SubMessage; mod tui; +mod time; enum Update { Reading(protocol::Reading), diff --git a/crates/sensor-tui/src/time.rs b/crates/sensor-tui/src/time.rs new file mode 100644 index 00000000..0d94d8f8 --- /dev/null +++ b/crates/sensor-tui/src/time.rs @@ -0,0 +1,2 @@ +pub mod format; +pub mod parse; diff --git a/crates/sensor-tui/src/time/format.rs b/crates/sensor-tui/src/time/format.rs new file mode 100644 index 00000000..bfb4ed40 --- /dev/null +++ b/crates/sensor-tui/src/time/format.rs @@ -0,0 +1,81 @@ +struct FmtOption { + unit: &'static str, + factor: usize, + /// at a max display this numb of items + /// before going to the bigger FmtOption + next: usize, +} + +impl FmtOption { + fn scale(&self, seconds: f64) -> usize { + (seconds / self.factor as f64).floor() as usize + } +} + +pub fn fmt_seconds(secs: f64) -> String { + #[rustfmt::skip] + let mut options = [ + // next is purposefully set wrong, we set it in a loop below + FmtOption{unit: "s", factor: 1, next: 0}, + FmtOption{unit: "m", factor: 60, next: 0}, + FmtOption{unit: "h", factor: 60 * 60, next: 0}, + FmtOption{unit: "d", factor: 60 * 60 * 24, next: 0}, + FmtOption{unit: "w", factor: 60 * 60 * 24 * 7, next: 0}, + FmtOption{unit: "y", factor: 60 * 60 * 24 * 365, next: 0}, + ]; + + let mut next = usize::MAX; + for fmt in options.iter_mut().rev() { + fmt.next = next; + next = fmt.factor; + } + + let mut small = &options[0]; + for big in &options[1..] { + if big.scale(secs) == 0 { + return format!("{}{}", small.scale(secs), small.unit); + } + + if secs >= big.next as f64 { + small = big; + continue; + } + + if small.scale(secs % small.next as f64) == 0 { + return format!("{}{}", big.scale(secs), big.unit); + } + + return format!( + "{}{}{}{}", + big.scale(secs), + big.unit, + small.scale(secs % small.next as f64), + small.unit + ); + } + + unreachable!() +} + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_fmt_x() { + let cases = [ + (5, "5s"), + (92, "1m32s"), + (60 * 60 * 12, "12h"), + (60 * 60 * 24 * 2, "2d"), + (60 * 60 * 24 * 7, "1w"), + (60 * 60 * 24 * 366, "1y"), + (60 * 60 * 24 * 365 * 14 + 60 * 60 * 24 * 7 * 6, "14y6w"), + ]; + + for (input, correct_output) in cases { + assert_eq!(fmt_seconds(input as f64), correct_output); + } + } +} diff --git a/crates/sensor-tui/src/tui/history_len/parse_duration.rs b/crates/sensor-tui/src/time/parse.rs similarity index 78% rename from crates/sensor-tui/src/tui/history_len/parse_duration.rs rename to crates/sensor-tui/src/time/parse.rs index afbb2f00..88032e50 100644 --- a/crates/sensor-tui/src/tui/history_len/parse_duration.rs +++ b/crates/sensor-tui/src/time/parse.rs @@ -78,29 +78,3 @@ pub(crate) fn parse_duration(arg: &str) -> Result { let seconds = parse_colon_duration(arg)?; Ok(std::time::Duration::from_secs_f32(seconds)) } - -fn fmt_mm_hh(dur: Duration) -> String { - let mm = (dur.as_secs_f32() / 60.0).round() as u8 % 60; - let hh = (dur.as_secs_f32() / 60.0 / 60.0).round() as u8; - let days = (dur.as_secs_f32() / 60.0 / 60.0 / 24.0).round() as usize; - let weeks = (dur.as_secs_f32() / 60.0 / 60.0 / 24.0 / 7.0).round() as usize; - - if days > 21 { - format!("{weeks} weeks") - } else if hh > 72 { - format!("{days} days") - } else if hh == 0 { - format!("{mm}m") - } else { - format!("{hh}h:{mm}m") - } -} - -pub fn fmt_dur(dur: Duration) -> String { - let seconds = dur.as_secs(); - if seconds > 60 { - fmt_mm_hh(dur) - } else { - return format!("{seconds}s"); - } -} diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index cfe95f97..ff338673 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -65,7 +65,8 @@ struct App { input_mode: InputMode, active_list: ActiveList, show_histogram: bool, - reading_list_state: TreeState, + reading_tree_state: TreeState, + affector_tree_state: TreeState, history_length: HistoryLen, } @@ -87,38 +88,46 @@ impl App { terminal.clear()?; let mut affectors_list_state = ListState::default(); - let affectors = vec![ - "placeholder 1".to_owned(), - "placeholder 2".to_owned(), - "placeholder 3".to_owned(), - ]; + let affectors = Vec::new(); let mut plot_buf = Vec::new(); loop { let data = self - .reading_list_state + .reading_tree_state .selected() .last() // unique leaf id .and_then(|key| readings.data.get_mut(key)); let plot_open = data.is_some(); - let (chart, histogram) = if let Some(data) = data { + let (chart, histogram, details) = if let Some(data) = data { data.stored_history.update_if_needed( data_store, data.reading.clone(), &mut self.history_length, ); - (data.chart(&mut plot_buf), data.histogram()) + ( + data.chart(&mut plot_buf), + data.histogram(), + Some(data.details()), + ) } else { - (None, readings.histogram_all()) + (None, readings.histogram_all(), None) }; terminal.draw(|frame| { - render::app(frame, self, &readings.ground, chart, &histogram); + render::app( + frame, + self, + &readings.ground, + &affectors, + details, + chart, + &histogram, + ); })?; - if self.reading_list_state.selected().is_empty() { - self.reading_list_state.select_first(); + if self.reading_tree_state.selected().is_empty() { + self.reading_tree_state.select_first(); } if event::poll(Duration::from_millis(16))? { @@ -192,13 +201,13 @@ impl App { fn handle_key_all_modes(&mut self, key: KeyEvent) -> ShouldExit { match key.code { KeyCode::Down => { - self.reading_list_state.key_down(); + self.reading_tree_state.key_down(); } KeyCode::Up => { - self.reading_list_state.key_up(); + self.reading_tree_state.key_up(); } KeyCode::Enter => { - self.reading_list_state.toggle_selected(); + self.reading_tree_state.toggle_selected(); } KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => { return ShouldExit::Yes; diff --git a/crates/sensor-tui/src/tui/history_len.rs b/crates/sensor-tui/src/tui/history_len.rs index 0d61a858..c1325faa 100644 --- a/crates/sensor-tui/src/tui/history_len.rs +++ b/crates/sensor-tui/src/tui/history_len.rs @@ -5,10 +5,8 @@ use ratatui::{ }; use std::time::Duration; -mod parse_duration; -use parse_duration::parse_duration; - -use self::parse_duration::fmt_dur; +use crate::time::format::fmt_seconds; +use crate::time::parse::parse_duration; #[derive(Debug, Clone, Copy)] pub enum State { @@ -29,7 +27,7 @@ pub struct HistoryLen { impl Default for HistoryLen { fn default() -> Self { let dur = Duration::from_secs(15 * 60); - let text_input = fmt_dur(dur); + let text_input = fmt_seconds(dur.as_secs_f64()); Self { text_input, editing: false, diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index 30b9ba15..f91a3799 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -7,7 +7,7 @@ use protocol::Reading; use ratatui::{text::Line, widgets::Bar}; use std::collections::HashMap; use std::sync::TryLockError; -use std::time::Instant; +use std::time::{Duration, Instant}; use tui_tree_widget::TreeItem; mod fetch; @@ -23,6 +23,45 @@ pub struct SensorInfo { log: Vec<(Instant, Error)>, } +pub struct NumErrorSince { + pub t5_min: usize, + pub t15_min: usize, + pub t30_min: usize, + pub t45_min: usize, + pub t60_min: usize, +} + +impl NumErrorSince { + fn from_log(log: &[(Instant, Error)]) -> Self { + let mut buckets = [5, 15, 30, 45, 60] + .map(|min| Duration::from_secs(60 * min)) + .map(|bound| (bound, 0)); + + for (occurred, _) in log.iter().rev() { + for (bound, count) in &mut buckets { + if occurred.elapsed() < *bound { + *count += 1; + } + } + } + + Self { + t5_min: buckets[0].1, + t15_min: buckets[1].1, + t30_min: buckets[2].1, + t45_min: buckets[3].1, + t60_min: buckets[4].1, + } + } +} + +pub struct Details { + pub last_reading: Option<(jiff::Timestamp, String)>, + pub condition: Result<(), Box>, + pub description: String, + pub errors_since: NumErrorSince, +} + impl SensorInfo { fn last_at(&self) -> Result> { self.condition.clone()?; @@ -34,6 +73,24 @@ impl SensorInfo { Ok(last.0) } + pub fn details(&self) -> Details { + let last_reading = self.recent_history.last().copied().map(|(ts, val)| { + let val = format!( + "{0:.1$} {2}", + val, + self.reading.leaf().precision(), + self.reading.leaf().unit + ); + (ts, val) + }); + Details { + last_reading, + condition: self.condition.clone(), + description: self.reading.leaf().description.to_owned(), + errors_since: NumErrorSince::from_log(&self.log), + } + } + pub fn histogram(&self) -> Vec { histogram_bars(&self.timing) } @@ -266,7 +323,7 @@ impl Readings { loop { match tomato.inner() { Item::Leaf(_) => { - let text = format!("{}: {:?}", tomato.name(), error); + let text = format!("{}: {}", tomato.name(), error); add_leaf(text, tree, key); break; } diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs index 01ccaa50..0b847c8e 100644 --- a/crates/sensor-tui/src/tui/render.rs +++ b/crates/sensor-tui/src/tui/render.rs @@ -1,9 +1,10 @@ +use jiff::Timestamp; use ratatui::{ self, layout::{Constraint, Flex, Layout, Rect}, style::{Modifier, Style}, text::Text, - widgets::{Bar, BarChart, BarGroup, Block, Borders}, + widgets::{self, Bar, BarChart, BarGroup, Block, Borders}, Frame, }; use tui_tree_widget::{Tree, TreeItem}; @@ -11,7 +12,7 @@ use tui_tree_widget::{Tree, TreeItem}; use crate::trace_dbg; use super::{ - reading::{ChartParts, TreeKey}, + reading::{ChartParts, Details, NumErrorSince, TreeKey}, ActiveList, App, }; @@ -21,11 +22,13 @@ pub(crate) fn app( frame: &mut Frame, app: &mut App, readings: &[TreeItem<'static, TreeKey>], + affectors: &[TreeItem<'static, TreeKey>], + details: Option
, chart: Option, histogram: &[Bar], ) { let [list_constraint, graph_constraint] = if chart.is_some() | app.show_histogram { - let list_height = 2 + app.reading_list_state.flatten(readings).len(); + let list_height = 2 + app.reading_tree_state.flatten(readings).len(); if (frame.size().height as f32) / 3. > list_height as f32 { [ Constraint::Min(list_height as u16), @@ -44,7 +47,7 @@ pub(crate) fn app( .flex(Flex::Legacy) .areas(area); - render_readings_and_actuators(frame, top, app, readings); + render_readings_and_actuators(frame, top, app, readings, affectors, details); render_graph_and_hist(frame, bottom, app, histogram, chart); render_footer(frame, footer, app); } @@ -103,8 +106,10 @@ pub(crate) fn render_readings_and_actuators( layout: Rect, app: &mut App, readings: &[TreeItem<'static, TreeKey>], + affectors: &[TreeItem<'static, TreeKey>], + details: Option
, ) { - let horizontal: [_; 2] = + let [left, right] = Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]) .flex(Flex::Legacy) .areas(layout); @@ -121,24 +126,83 @@ pub(crate) fn render_readings_and_actuators( .style(app.active_list.style(ActiveList::Readings)) .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) .highlight_symbol(">>"), - horizontal[0], - &mut app.reading_list_state, + left, + &mut app.reading_tree_state, ); - // frame.render_stateful_widget( - // List::new(app.actuators) - // .block( - // Block::default() - // .title("Actuators") - // .borders(Borders::ALL) - // .border_style(app.active_list.style(ActiveList::Actuators)), - // ) - // .style(app.active_list.style(ActiveList::Actuators)) - // .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) - // .highlight_symbol(">>") - // .repeat_highlight_symbol(false) - // .direction(ratatui::widgets::ListDirection::TopToBottom), - // horizontal[1], - // app.actuator_list_state, - // ); + if let (Some(details), ActiveList::Readings) = (details, app.active_list) { + let [top, bottom] = + Layout::vertical([Constraint::Percentage(30), Constraint::Percentage(70)]) + .flex(Flex::Legacy) + .areas(right); + render_affectors(frame, top, app, affectors); + render_details(frame, bottom, details); + } else { + render_affectors(frame, right, app, affectors) + } +} + +fn render_details(frame: &mut Frame, layout: Rect, details: Details) { + let Details { + last_reading, + condition, + description, + errors_since, + } = details; + let last_reading = match last_reading { + None => "last read: Never".to_owned(), + Some((ts, val)) => { + let seconds_ago = Timestamp::now() + .since(ts) + .expect("should make sense") + .get_seconds(); + let time_ago = crate::time::format::fmt_seconds(seconds_ago as f64); + format!("last read:\n {time_ago} ago, value: {val}") + } + }; + + let condition = match condition { + Ok(()) => String::new(), + Err(err) => format!("error: {err}"), + }; + + let NumErrorSince { + t5_min, + t15_min, + t30_min, + t45_min, + t60_min, + } = errors_since; + let errors_since = format!("errors in the past:\n5min: {t5_min}, 15min: {t15_min}, 30min: {t30_min}, 45min {t45_min}, 60m: {t60_min}"); + + let text = format!("{description}\n{last_reading}\n{condition}\n{errors_since}"); + frame.render_widget( + widgets::Paragraph::new(text) + .block(Block::bordered().title("Details")) + .wrap(widgets::Wrap { trim: true }), + layout, + ) +} + +fn render_affectors( + frame: &mut Frame, + layout: Rect, + app: &mut App, + affectors: &[TreeItem<'static, TreeKey>], +) { + frame.render_stateful_widget( + Tree::new(affectors) + .expect("all item identifiers should be unique") + .block( + Block::default() + .title("Controllable actuators") + .borders(Borders::ALL) + .border_style(app.active_list.style(ActiveList::Affectors)), + ) + .style(app.active_list.style(ActiveList::Affectors)) + .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) + .highlight_symbol(">>"), + layout, + &mut app.affector_tree_state, + ); } diff --git a/crates/sensor-tui/src/tui/render/chart/labels.rs b/crates/sensor-tui/src/tui/render/chart/labels.rs index d6bcde2f..51c85f85 100644 --- a/crates/sensor-tui/src/tui/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/render/chart/labels.rs @@ -20,7 +20,7 @@ pub fn labels<'a>( // characters are about twice as high as wide let x = evenly_spaced_labels(layout.width / y_label_spacing / 2, &info, x_bounds) .rev() - .map(fmt_x_label) + .map(crate::time::format::fmt_seconds) .map(Into::into) .collect(); let y = evenly_spaced_labels(layout.height / y_label_spacing, &info, y_bounds) @@ -45,84 +45,3 @@ fn evenly_spaced_labels( .into_iter() .map(move |i| bounds[0] + y_spacing * i as f64) } - -struct FmtOption { - unit: &'static str, - factor: usize, - /// at a max display this numb of items - /// before going to the bigger FmtOption - next: usize, -} - -impl FmtOption { - fn scale(&self, seconds: f64) -> usize { - (seconds / self.factor as f64).floor() as usize - } -} - -fn fmt_x_label(secs: f64) -> String { - #[rustfmt::skip] - let mut options = [ - // next is purposefully set wrong, we set it in a loop below - FmtOption{unit: "s", factor: 1, next: 0}, - FmtOption{unit: "m", factor: 60, next: 0}, - FmtOption{unit: "h", factor: 60 * 60, next: 0}, - FmtOption{unit: "d", factor: 60 * 60 * 24, next: 0}, - FmtOption{unit: "w", factor: 60 * 60 * 24 * 7, next: 0}, - FmtOption{unit: "y", factor: 60 * 60 * 24 * 365, next: 0}, - ]; - - let mut next = usize::MAX; - for fmt in options.iter_mut().rev() { - fmt.next = next; - next = fmt.factor; - } - - let mut small = &options[0]; - for big in &options[1..] { - if big.scale(secs) == 0 { - return format!("{}{}", small.scale(secs), small.unit); - } - - if secs >= big.next as f64 { - small = big; - continue; - } - - if small.scale(secs % small.next as f64) == 0 { - return format!("{}{}", big.scale(secs), big.unit); - } - - return format!( - "{}{}{}{}", - big.scale(secs), - big.unit, - small.scale(secs % small.next as f64), - small.unit - ); - } - - unreachable!() -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_fmt_x() { - let cases = [ - (5, "5s"), - (92, "1m32s"), - (60 * 60 * 12, "12h"), - (60 * 60 * 24 * 2, "2d"), - (60 * 60 * 24 * 7, "1w"), - (60 * 60 * 24 * 366, "1y"), - (60 * 60 * 24 * 365 * 14 + 60 * 60 * 24 * 7 * 6, "14y6w"), - ]; - - for (input, correct_output) in cases { - assert_eq!(fmt_x_label(input as f64), correct_output); - } - } -} diff --git a/crates/sensor-tui/src/tui/render/time.rs b/crates/sensor-tui/src/tui/render/time.rs new file mode 100644 index 00000000..e69de29b From 3075b37e2f8ace69bb928d63b67c40f1894a478a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 28 Jul 2024 13:52:17 +0200 Subject: [PATCH 173/687] data store collects error reports and histogram too --- Cargo.lock | 62 +++++++++++-- crates/data-store/Cargo.toml | 1 + crates/data-store/examples/last_15m.rs | 4 +- crates/data-store/src/api.rs | 16 ++++ crates/data-store/src/api/client.rs | 20 +++- crates/data-store/src/server.rs | 17 +++- crates/data-store/src/server/clients.rs | 70 +++++++++++--- crates/data-store/src/server/db.rs | 29 ++++-- crates/data-store/src/server/db/log.rs | 49 ++++++++++ crates/data-store/src/server/db/series.rs | 4 +- .../src/server/db/series/resampler.rs | 2 - crates/data-store/src/server/db/stats.rs | 65 +++++++++++++ crates/data-store/tests/list_data.rs | 14 +-- crates/sensor-tui/Cargo.toml | 3 +- crates/sensor-tui/src/tui.rs | 6 +- crates/sensor-tui/src/tui/reading.rs | 92 ++++++++++++------- crates/sensor-tui/src/tui/reading/fetch.rs | 5 +- crates/sensor-tui/src/tui/render.rs | 16 ++-- crates/sensor-tui/src/tui/render/chart.rs | 11 ++- crates/text-widget/src/main.rs | 10 +- 20 files changed, 390 insertions(+), 106 deletions(-) create mode 100644 crates/data-store/src/server/db/log.rs create mode 100644 crates/data-store/src/server/db/stats.rs diff --git a/Cargo.lock b/Cargo.lock index d13a6b89..50ada631 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -784,6 +784,15 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" +[[package]] +name = "crossbeam-channel" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-epoch" version = "0.9.18" @@ -850,6 +859,7 @@ dependencies = [ "data-server", "futures", "futures-concurrency", + "hdrhistogram", "jiff", "nucleo-matcher", "num", @@ -1111,6 +1121,16 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +[[package]] +name = "flate2" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1409,6 +1429,20 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hdrhistogram" +version = "7.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" +dependencies = [ + "base64 0.21.7", + "byteorder", + "crossbeam-channel", + "flate2", + "nom", + "num-traits", +] + [[package]] name = "heapless" version = "0.7.17" @@ -1459,15 +1493,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" -[[package]] -name = "histogram" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62b8d85713ddc62e5e78db13bf9f9305610d0419276faa845076a68b7165872" -dependencies = [ - "thiserror", -] - [[package]] name = "http" version = "1.1.0" @@ -1891,6 +1916,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.4" @@ -1987,6 +2018,16 @@ dependencies = [ "libc", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -2612,7 +2653,8 @@ dependencies = [ "crossterm", "data-server", "data-store", - "histogram", + "gethostname", + "hdrhistogram", "itertools", "jiff", "protocol", diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index c7a41943..ca1315ce 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -33,6 +33,7 @@ thiserror = { workspace = true } futures = "0.3.30" smallvec = "2.0.0-alpha.6" num = "0.4.3" +hdrhistogram = "7.5.4" [dev-dependencies] futures-concurrency = "7.6.1" diff --git a/crates/data-store/examples/last_15m.rs b/crates/data-store/examples/last_15m.rs index 7ac26f9d..28c3388c 100644 --- a/crates/data-store/examples/last_15m.rs +++ b/crates/data-store/examples/last_15m.rs @@ -27,7 +27,9 @@ fn to_path(reading: &Reading) -> String { #[tokio::main] async fn main() { let cli = Cli::parse(); - let mut client = Client::connect(cli.addr).await.unwrap(); + let mut client = Client::connect(cli.addr, "data_store_example".to_owned()) + .await + .unwrap(); let readings = client.list_data().await.unwrap(); let mut matcher = nucleo_matcher::Matcher::new(nucleo_matcher::Config::DEFAULT); diff --git a/crates/data-store/src/api.rs b/crates/data-store/src/api.rs index 93431a8f..fed003c0 100644 --- a/crates/data-store/src/api.rs +++ b/crates/data-store/src/api.rs @@ -10,6 +10,11 @@ pub(crate) const MAX_PACKAGE_SIZE: usize = 8 * 1024 * 1024; #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) enum Request { + Handshake { + name: String, + }, + GetLog(protocol::Device), + GetStats(protocol::Device), ListData, GetData { reading: Reading, @@ -25,14 +30,25 @@ pub enum ServerError { NotInStore { reading: Reading }, #[error("Internal error while reading data, error: {0}")] ReadingFromStore(String), + #[error("Connect request should only be send once")] + AlreadyConnected, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Percentile { + pub bucket_ends: u64, + pub percentile: f64, + pub count_in_bucket: u64, } #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) enum Response { + GetLog(Vec<(jiff::Timestamp, protocol::Error)>), ListData(Vec), GetData { time: Vec, data: Vec, }, + GetStats(Vec), Error(ServerError), } diff --git a/crates/data-store/src/api/client.rs b/crates/data-store/src/api/client.rs index cdbb95fe..47fbe5ff 100644 --- a/crates/data-store/src/api/client.rs +++ b/crates/data-store/src/api/client.rs @@ -4,6 +4,8 @@ use tokio::net::ToSocketAddrs; use tokio_serde::formats::Bincode; use tokio_util::codec::{Framed, LengthDelimitedCodec}; +use super::Request; + pub struct Client { stream: tokio_serde::Framed< Framed, @@ -14,8 +16,12 @@ pub struct Client { } #[derive(Debug, thiserror::Error)] -#[error("Error while connecting to data server: {0}")] -pub struct ConnectError(std::io::Error); +pub enum ConnectError { + #[error("Error while connecting to data server: {0}")] + Io(std::io::Error), + #[error("Could not send handshake: {0}")] + Sending(std::io::Error), +} #[derive(Debug, thiserror::Error)] pub enum Error { @@ -32,8 +38,8 @@ pub enum Error { } impl Client { - pub async fn connect(addr: impl ToSocketAddrs) -> Result { - let stream = TcpStream::connect(addr).await.map_err(ConnectError)?; + pub async fn connect(addr: impl ToSocketAddrs, name: String) -> Result { + let stream = TcpStream::connect(addr).await.map_err(ConnectError::Io)?; let length_delimited = Framed::new( stream, @@ -42,7 +48,11 @@ impl Client { .new_codec(), ); - let stream = tokio_serde::Framed::new(length_delimited, Bincode::default()); + let mut stream = tokio_serde::Framed::new(length_delimited, Bincode::default()); + stream + .send(Request::Handshake { name }) + .await + .map_err(ConnectError::Sending)?; Ok(Self { stream }) } diff --git a/crates/data-store/src/server.rs b/crates/data-store/src/server.rs index fdf2ed36..de70fd25 100644 --- a/crates/data-store/src/server.rs +++ b/crates/data-store/src/server.rs @@ -1,9 +1,9 @@ +use color_eyre::Result; +use futures_concurrency::future::Race; use std::collections::HashMap; use std::net::SocketAddr; use std::path::Path; use std::sync::Arc; -use color_eyre::Result; -use futures_concurrency::future::Race; use tokio::sync::Mutex; mod clients; @@ -12,9 +12,18 @@ mod db; // used from main and tests pub async fn run(data_server: SocketAddr, client_port: u16, data_dir: &Path) -> Result<()> { let data = db::Data(Arc::new(Mutex::new(HashMap::new()))); + let stats = db::Stats(Arc::new(Mutex::new(HashMap::new()))); + let logs = db::Logs(Arc::new(Mutex::new(HashMap::new()))); + let error = ( - db::run(data_server, data.clone(), data_dir), - clients::handle(client_port, data), + db::run( + data_server, + data.clone(), + stats.clone(), + logs.clone(), + data_dir, + ), + clients::handle(client_port, data, stats, logs), ) .race() .await; diff --git a/crates/data-store/src/server/clients.rs b/crates/data-store/src/server/clients.rs index e6ab4049..741a9425 100644 --- a/crates/data-store/src/server/clients.rs +++ b/crates/data-store/src/server/clients.rs @@ -1,3 +1,5 @@ +use std::net::SocketAddr; + use color_eyre::eyre::Context; use color_eyre::Section; use futures::{SinkExt, TryStreamExt}; @@ -6,34 +8,52 @@ use tokio_serde::formats::Bincode; use tokio_util::codec::{Framed, LengthDelimitedCodec}; use tracing::{debug, error, info, warn}; -use super::db::Data; +use super::db::{Data, Logs, Stats}; use crate::api::{self, ServerError}; -pub(crate) async fn handle(port: u16, data: Data) -> color_eyre::Result<()> { +type Conn = tokio_serde::Framed< + Framed, + api::Request, + api::Response, + Bincode, +>; + +pub(crate) async fn handle( + port: u16, + data: Data, + stats: Stats, + logs: Logs, +) -> color_eyre::Result<()> { let listener = TcpListener::bind(format!("0.0.0.0:{port}")) .await .wrap_err("Could not bind to address") .with_note(|| format!("port: {port}"))?; loop { - let socket = match listener.accept().await { - Ok((socket, source)) => { - info!("client connected from source: {source}"); - socket - } + let (socket, source) = match listener.accept().await { Err(e) => { warn!("client could not connect: {e}"); continue; } + Ok(res) => res, + }; + + let Some(conn) = handshake_and_log(socket, source).await else { + continue; }; - tokio::task::spawn(handle_client(socket, data.clone())); + tokio::task::spawn(handle_client( + conn, + data.clone(), + stats.clone(), + logs.clone(), + )); } } -pub(crate) async fn handle_client(socket: TcpStream, data: Data) { +async fn handshake_and_log(stream: TcpStream, source: SocketAddr) -> Option { let length_delimited = Framed::new( - socket, + stream, LengthDelimitedCodec::builder() .max_frame_length(api::MAX_PACKAGE_SIZE) .new_codec(), @@ -41,8 +61,22 @@ pub(crate) async fn handle_client(socket: TcpStream, data: Data) { let mut stream: tokio_serde::Framed<_, api::Request, api::Response, _> = tokio_serde::Framed::new(length_delimited, Bincode::default()); + match stream.try_next().await { + Ok(Some(api::Request::Handshake { name })) => { + info!("Client {name} connected from {source}"); + return Some(stream); + } + Ok(Some(other)) => warn!("client tried to connected without handshake, it send: {other:?}"), + Ok(None) => warn!("client closed connection immediately"), + Err(e) => warn!("connection or decoding issue while receiving handshake: {e:?}"), + } + + None +} + +async fn handle_client(mut conn: Conn, data: Data, stats: Stats, logs: Logs) { loop { - let request = match stream.try_next().await { + let request = match conn.try_next().await { Ok(Some(request)) => request, Ok(None) => { debug!("Connection ended"); @@ -53,19 +87,25 @@ pub(crate) async fn handle_client(socket: TcpStream, data: Data) { return; } }; - let response = match perform_request(request, &data).await { + let response = match perform_request(request, &data, &stats, &logs).await { Err(err) => api::Response::Error(err), Ok(r) => r, }; - if let Err(e) = stream.send(response).await { + if let Err(e) = conn.send(response).await { error!("Error sending response to client: {e:?}"); return; } } } -async fn perform_request(request: api::Request, data: &Data) -> Result { +async fn perform_request( + request: api::Request, + data: &Data, + stats: &Stats, + logs: &Logs, +) -> Result { Ok(match request { + api::Request::Handshake { .. } => return Err(ServerError::AlreadyConnected), api::Request::ListData => api::Response::ListData(data.list().await), api::Request::GetData { reading, @@ -76,5 +116,7 @@ async fn perform_request(request: api::Request, data: &Data) -> Result api::Response::GetLog(logs.get(&device).await), + api::Request::GetStats(device) => api::Response::GetStats(stats.get(&device).await), }) } diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index b9ac551b..e253ae7f 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -7,28 +7,45 @@ use std::time::{Duration, Instant}; use data_server::subscriber::reconnecting; use tokio::sync::Mutex; -use color_eyre::Result; +use color_eyre::{Result, Section}; use data_server::SubMessage; mod series; use series::Series; +mod log; +pub(crate) use log::Logs; + +mod stats; +pub(crate) use stats::Stats; + use crate::api; -pub(crate) async fn run(data_server_addr: SocketAddr, data: Data, data_dir: &Path) -> Result<()> { +pub(crate) async fn run( + data_server_addr: SocketAddr, + data: Data, + stats: Stats, + logs: Logs, + data_dir: &Path, +) -> Result<()> { let mut sub = reconnecting::Subscriber::new(data_server_addr, "ha-data-store".to_string()); let mut recently_logged = (Instant::now(), String::new()); loop { let msg = sub.next_msg().await; let res = match msg { - SubMessage::Reading(reading) => series::store(&data, &reading, data_dir).await, - SubMessage::ErrorReport(_) => continue, + SubMessage::Reading(reading) => { + series::store(&data, &reading, data_dir) + .await + .with_note(|| format!("reading: {reading:?}"))?; + stats.increment(reading.device()).await + } + SubMessage::ErrorReport(report) => logs.store(*report).await, }; const FIVE_MIN: Duration = Duration::from_secs(60 * 5); - if let Err(e) = res { - let e = e.to_string(); + if let Err(report) = res { + let e = format!("got error with report: {report:?}"); tracing::warn!("test: {e}"); if recently_logged.1 == e && recently_logged.0.elapsed() <= FIVE_MIN { continue; diff --git a/crates/data-store/src/server/db/log.rs b/crates/data-store/src/server/db/log.rs new file mode 100644 index 00000000..c897d2c6 --- /dev/null +++ b/crates/data-store/src/server/db/log.rs @@ -0,0 +1,49 @@ +use std::collections::{HashMap, VecDeque}; +use std::sync::Arc; + +use color_eyre::Result; +use tokio::sync::Mutex; + +#[derive(Debug)] +pub(crate) struct Log(VecDeque<(jiff::Timestamp, protocol::Error)>); + +impl Log { + pub fn new(first_report: protocol::Error) -> Self { + let mut this = Self(VecDeque::new()); + this.push(first_report); + this + } + + pub fn push(&mut self, report: protocol::Error) { + const MAX_LENGTH: usize = 100; + self.0.truncate(MAX_LENGTH - 1); + self.0.push_front((jiff::Timestamp::now(), report)) + } +} + +#[derive(Debug, Clone)] +pub(crate) struct Logs(pub(crate) Arc>>); + +impl Logs { + pub async fn store(&self, report: protocol::Error) -> Result<()> { + let mut map = self.0.lock().await; + if let Some(log) = map.get_mut(&report.device()) { + log.push(report); + } else { + map.insert(report.device(), Log::new(report)); + } + Ok(()) + } + + pub async fn get(&self, device: &protocol::Device) -> Vec<(jiff::Timestamp, protocol::Error)> { + let mut map = self.0.lock().await; + if let Some(log) = map.get_mut(device) { + let (logs, more_logs) = log.0.as_slices(); + let mut logs = logs.to_vec(); + logs.extend_from_slice(more_logs); + logs + } else { + Vec::new() + } + } +} diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index 24e0f63d..e0ee1e05 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -133,9 +133,8 @@ impl Series { let time = jiff::Timestamp::now(); let device_info = reading.leaf().device.info(); - let scale_factor = millis_to_minimal_representation(dbg!(device_info)); + let scale_factor = millis_to_minimal_representation(device_info); let scaled_time = time.as_millisecond() as u64 / scale_factor; - tracing::warn!("{scale_factor}, {}, {scaled_time}", time.as_millisecond()); self.byteseries .push_line(scaled_time, &self.line) .wrap_err("Could not write to timeseries on disk")?; @@ -354,7 +353,6 @@ mod test { temporal_resolution: std::time::Duration::from_secs(1), }; let factor = millis_to_minimal_representation(info); - dbg!(factor); assert_eq!(5000 / factor, 5); let info = protocol::DeviceInfo { diff --git a/crates/data-store/src/server/db/series/resampler.rs b/crates/data-store/src/server/db/series/resampler.rs index e067bf3a..328b4e3a 100644 --- a/crates/data-store/src/server/db/series/resampler.rs +++ b/crates/data-store/src/server/db/series/resampler.rs @@ -63,9 +63,7 @@ mod test { )); let readings = reading.device().info().affects_readings; - // dbg!(readings.iter().map(Tree::leaf).collect::>()); let specs = crate::server::db::series::to_speclist(readings); - // dbg!(&specs); let fields = bitspec::speclist_to_fields(specs); let payload_size = fields diff --git a/crates/data-store/src/server/db/stats.rs b/crates/data-store/src/server/db/stats.rs new file mode 100644 index 00000000..75baf1c3 --- /dev/null +++ b/crates/data-store/src/server/db/stats.rs @@ -0,0 +1,65 @@ +use color_eyre::eyre::WrapErr; +use color_eyre::{Result, Section}; +use std::collections::HashMap; +use std::sync::Arc; +use std::time::Instant; + +use tokio::sync::Mutex; + +use crate::api::Percentile; + +#[derive(Debug)] +pub(crate) struct Histogram { + last_reading: Instant, + histogram: hdrhistogram::Histogram, +} + +impl Histogram { + fn new() -> Result { + Ok(Self { + last_reading: Instant::now(), + histogram: hdrhistogram::Histogram::new_with_bounds(1, 24 * 60 * 60 * 1000, 2) + .wrap_err("Could not create empty histogram")?, + }) + } + fn increment(&mut self) -> Result<()> { + let val = self.last_reading.elapsed().as_millis(); + self.last_reading = Instant::now(); + self.histogram + .record(val as u64) + .wrap_err("Could not record event") + .with_note(|| format!("duration was: {val}ms")) + } +} + +#[derive(Debug, Clone)] +pub(crate) struct Stats(pub(crate) Arc>>); + +impl Stats { + pub async fn increment(&self, device: protocol::Device) -> Result<()> { + let mut map = self.0.lock().await; + if let Some(hist) = map.get_mut(&device) { + hist.increment()?; + } else { + map.insert(device, Histogram::new()?); + } + Ok(()) + } + + pub(crate) async fn get(&self, device: &protocol::Device) -> Vec { + let mut map = self.0.lock().await; + if let Some(timings) = map.get_mut(device) { + timings + .histogram + .iter_quantiles(1) + .map(|it| Percentile { + bucket_ends: it.value_iterated_to(), + percentile: it.percentile(), + count_in_bucket: it.count_at_value(), + }) + .collect() + } else { + Vec::new() + } + } +} diff --git a/crates/data-store/tests/list_data.rs b/crates/data-store/tests/list_data.rs index dcab6492..76447d8f 100644 --- a/crates/data-store/tests/list_data.rs +++ b/crates/data-store/tests/list_data.rs @@ -52,9 +52,10 @@ async fn check_client_list_data(data_store_addr: SocketAddr, data_send: &Notify) data_send.notified().await; sleep(Duration::from_secs_f32(0.1)).await; - let mut client = data_store::api::Client::connect(data_store_addr) - .await - .unwrap(); + let mut client = + data_store::api::Client::connect(data_store_addr, "data_store_example".to_owned()) + .await + .unwrap(); let list = client.list_data().await.unwrap(); assert!( @@ -84,9 +85,10 @@ async fn check_client_get_data( ) { data_send.notified().await; sleep(Duration::from_secs_f32(0.1)).await; - let mut client = data_store::api::Client::connect(data_store_addr) - .await - .unwrap(); + let mut client = + data_store::api::Client::connect(data_store_addr, "data_store_example".to_owned()) + .await + .unwrap(); let (time, data) = client .get_data( jiff::Timestamp::now() - jiff::Span::default().seconds(30), diff --git a/crates/sensor-tui/Cargo.toml b/crates/sensor-tui/Cargo.toml index e13557de..8212e296 100644 --- a/crates/sensor-tui/Cargo.toml +++ b/crates/sensor-tui/Cargo.toml @@ -9,7 +9,7 @@ authors.workspace = true [dependencies] color-eyre = { workspace = true } crossterm = "0.27.0" -histogram = "0.11" +hdrhistogram = "7.5" ratatui = "0.27" tui-tree-widget = { version = "0.21.0", git = "https://github.com/dvdsk/tui-rs-tree-widget" } clap = { workspace = true } @@ -25,3 +25,4 @@ data-store = { workspace = true } jiff = { workspace = true } thiserror.workspace = true itertools = "0.13.0" +gethostname = "0.5.0" diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index ff338673..7febb63d 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -6,7 +6,6 @@ use crossterm::{ use ratatui::{ prelude::{CrosstermBackend, Terminal}, style::{Color, Style}, - widgets::ListState, }; use std::{collections::HashMap, io::stdout, net::SocketAddr, sync::mpsc, time::Duration}; use tui_tree_widget::TreeState; @@ -87,7 +86,6 @@ impl App { let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; terminal.clear()?; - let mut affectors_list_state = ListState::default(); let affectors = Vec::new(); let mut plot_buf = Vec::new(); @@ -100,7 +98,7 @@ impl App { let plot_open = data.is_some(); let (chart, histogram, details) = if let Some(data) = data { - data.stored_history.update_if_needed( + data.history_from_store.update_if_needed( data_store, data.reading.clone(), &mut self.history_length, @@ -111,7 +109,7 @@ impl App { Some(data.details()), ) } else { - (None, readings.histogram_all(), None) + (None, Vec::new(), None) }; terminal.draw(|frame| { diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index f91a3799..b14a5739 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -1,4 +1,7 @@ -use histogram::Histogram; +use data_store::api::Percentile; +use hdrhistogram::Histogram; +use itertools::Itertools; +use jiff::Unit; use protocol::reading_tree::ReadingInfo; use protocol::reading_tree::{Item, Tree}; use protocol::Error; @@ -13,14 +16,18 @@ use tui_tree_widget::TreeItem; mod fetch; use fetch::StoredHistory; +use crate::trace_dbg; + #[derive(Debug)] pub struct SensorInfo { - timing: Histogram, pub reading: Reading, + timing: Histogram, + percentiles_from_store: Vec, recent_history: Vec<(jiff::Timestamp, f32)>, - pub stored_history: StoredHistory, + pub history_from_store: StoredHistory, condition: Result<(), Box>, log: Vec<(Instant, Error)>, + merged_log_from_store: bool, } pub struct NumErrorSince { @@ -92,11 +99,28 @@ impl SensorInfo { } pub fn histogram(&self) -> Vec { - histogram_bars(&self.timing) + let percentiles = if self.percentiles_from_store.is_empty() { + self.timing + .iter_quantiles(1) + .map(|it| data_store::api::Percentile { + percentile: it.percentile(), + bucket_ends: it.value_iterated_to(), + count_in_bucket: it.count_at_value(), + }) + .dedup_by(|a, b| { + a.bucket_ends == b.bucket_ends + && a.percentile.total_cmp(&b.percentile).is_eq() + && a.count_in_bucket == b.count_in_bucket + }) + .collect_vec() + } else { + self.percentiles_from_store.clone() + }; + histogram_bars(&percentiles) } pub fn chart<'a>(&mut self, plot_buf: &'a mut Vec<(f64, f64)>) -> Option> { - let guard = match self.stored_history.data.try_lock() { + let guard = match self.history_from_store.data.try_lock() { Ok(list) => Some(list), Err(TryLockError::WouldBlock) => None, Err(other) => panic!( @@ -243,11 +267,15 @@ impl Readings { key, SensorInfo { reading: broken.clone(), - timing: Histogram::new(4, 24).unwrap(), + timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), + percentiles_from_store: Vec::new(), + recent_history: Vec::new(), - stored_history: StoredHistory::new(), + history_from_store: StoredHistory::new(), + condition: Err(error.clone()), log: vec![(Instant::now(), (*error).clone())], + merged_log_from_store: false, }, ); } @@ -260,9 +288,10 @@ impl Readings { if let Some(info) = self.data.get_mut(&key) { if let Ok(last_reading) = info.last_at() { - info.timing - .increment((time - last_reading).get_milliseconds() as u64) - .unwrap(); + info.timing += trace_dbg!((time - last_reading) + .total(Unit::Millisecond) + .expect("no calander units involved") + as u64) } info.recent_history.push((time, val)); info.condition = Ok(()); @@ -272,11 +301,15 @@ impl Readings { key, SensorInfo { reading, - timing: Histogram::new(4, 24).unwrap(), + timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), + percentiles_from_store: Vec::new(), + recent_history: history, - stored_history: StoredHistory::new(), + history_from_store: StoredHistory::new(), + condition: Ok(()), log: Vec::new(), + merged_log_from_store: false, }, ); } @@ -335,14 +368,6 @@ impl Readings { } } } - - pub fn histogram_all(&self) -> Vec { - let mut all = Histogram::new(4, 24).unwrap(); - for (_, val) in self.data.iter() { - all = all.checked_add(&val.timing).unwrap(); - } - histogram_bars(&all) - } } pub struct ChartParts<'a> { @@ -350,21 +375,20 @@ pub struct ChartParts<'a> { pub data: &'a [(f64, f64)], } -fn histogram_bars(hist: &Histogram) -> Vec> { - let Some(percentiles) = hist - .percentiles(&[25.0, 50.0, 75.0, 90.0, 95.0, 100.0]) - .unwrap() - else { - return Vec::new(); - }; - +fn histogram_bars(percentiles: &[Percentile]) -> Vec> { percentiles .into_iter() - .map(|(p, bucket)| { - Bar::default() - .value(bucket.count()) - .text_value(format!("p{p}: {}", bucket.count())) - .label(Line::from(format!("{}..{}", bucket.start(), bucket.end()))) - }) + .map( + |Percentile { + bucket_ends, + percentile, + count_in_bucket, + }| { + Bar::default() + .value(*count_in_bucket) + .text_value(format!("p{percentile}: {}", count_in_bucket)) + .label(Line::from(format!("..{}", bucket_ends))) + }, + ) .collect() } diff --git a/crates/sensor-tui/src/tui/reading/fetch.rs b/crates/sensor-tui/src/tui/reading/fetch.rs index 35414e62..8519e62e 100644 --- a/crates/sensor-tui/src/tui/reading/fetch.rs +++ b/crates/sensor-tui/src/tui/reading/fetch.rs @@ -129,7 +129,10 @@ async fn connect_and_get_data( .min(retry_period * 2) .min(Duration::from_millis(100)); - let mut api = match data_store::api::Client::connect(addr).await { + let host = gethostname::gethostname(); + let host = host.to_string_lossy(); + let name = format!("sensor-tui@{host}"); + let mut api = match data_store::api::Client::connect(addr, name).await { Ok(api) => api, Err(e) => { warn!("Could not connect to data_store (at {addr}): {e}"); diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs index 0b847c8e..805bc000 100644 --- a/crates/sensor-tui/src/tui/render.rs +++ b/crates/sensor-tui/src/tui/render.rs @@ -9,8 +9,6 @@ use ratatui::{ }; use tui_tree_widget::{Tree, TreeItem}; -use crate::trace_dbg; - use super::{ reading::{ChartParts, Details, NumErrorSince, TreeKey}, ActiveList, App, @@ -27,7 +25,7 @@ pub(crate) fn app( chart: Option, histogram: &[Bar], ) { - let [list_constraint, graph_constraint] = if chart.is_some() | app.show_histogram { + let [list_constraint, graph_constraint] = if chart.is_some() { let list_height = 2 + app.reading_tree_state.flatten(readings).len(); if (frame.size().height as f32) / 3. > list_height as f32 { [ @@ -95,9 +93,9 @@ fn render_histogram(frame: &mut Frame, lower: Rect, histogram: &[Bar]) { let barchart = BarChart::default() .block(Block::bordered().title("Histogram")) .data(BarGroup::default().bars(histogram)) - .bar_width(12) - .bar_style(Style::default()) - .value_style(Style::default()); + .bar_width(12); + // .bar_style(Style::default()) + // .value_style(Style::default()); frame.render_widget(barchart, lower) } @@ -157,13 +155,13 @@ fn render_details(frame: &mut Frame, layout: Rect, details: Details) { .expect("should make sense") .get_seconds(); let time_ago = crate::time::format::fmt_seconds(seconds_ago as f64); - format!("last read:\n {time_ago} ago, value: {val}") + format!("last read: {time_ago} ago, value: {val}") } }; let condition = match condition { Ok(()) => String::new(), - Err(err) => format!("error: {err}"), + Err(err) => format!("error: {err}\n"), }; let NumErrorSince { @@ -175,7 +173,7 @@ fn render_details(frame: &mut Frame, layout: Rect, details: Details) { } = errors_since; let errors_since = format!("errors in the past:\n5min: {t5_min}, 15min: {t15_min}, 30min: {t30_min}, 45min {t45_min}, 60m: {t60_min}"); - let text = format!("{description}\n{last_reading}\n{condition}\n{errors_since}"); + let text = format!("{description}\n{last_reading}\n{condition}{errors_since}"); frame.render_widget( widgets::Paragraph::new(text) .block(Block::bordered().title("Details")) diff --git a/crates/sensor-tui/src/tui/render/chart.rs b/crates/sensor-tui/src/tui/render/chart.rs index a4ded93c..a3de6f99 100644 --- a/crates/sensor-tui/src/tui/render/chart.rs +++ b/crates/sensor-tui/src/tui/render/chart.rs @@ -21,7 +21,7 @@ pub fn render(frame: &mut Frame, layout: Rect, app: &mut App, chart: ChartParts) .style(Style::default()) .data(chart.data); - let (x_bounds, y_bounds) = bounds(&chart, chart.reading.resolution() as f64, layout); + let (x_bounds, y_bounds) = bounds(&chart, layout); let (mut x_labels, y_labels) = labels(&chart, layout, x_bounds, y_bounds); let borrowed = x_labels.first_mut().expect("min labels is 2"); @@ -47,7 +47,7 @@ pub fn render(frame: &mut Frame, layout: Rect, app: &mut App, chart: ChartParts) } type Bounds = [f64; 2]; -fn bounds(chart: &ChartParts, resolution: f64, layout: Rect) -> (Bounds, Bounds) { +fn bounds(chart: &ChartParts, layout: Rect) -> (Bounds, Bounds) { let x_bounds = [ 0f64, chart.data.last().map(|(x, _)| x).copied().unwrap_or(0f64), @@ -62,7 +62,14 @@ fn bounds(chart: &ChartParts, resolution: f64, layout: Rect) -> (Bounds, Bounds) }); let y_range = y_bounds[1] - y_bounds[0]; let margin = 5.0 / layout.height as f64; + + let range = chart.reading.leaf().range; + let resolution = chart.reading.resolution() as f64; let y_margin = f64::max(y_range * margin, resolution / 2.0); let y_bounds = [y_bounds[0] - y_margin, y_bounds[1] + y_margin]; + let y_bounds = [ + y_bounds[0].max(range.start as f64), + y_bounds[1].min(range.end as f64), + ]; (x_bounds, y_bounds) } diff --git a/crates/text-widget/src/main.rs b/crates/text-widget/src/main.rs index fe82b3fe..d6753ad8 100644 --- a/crates/text-widget/src/main.rs +++ b/crates/text-widget/src/main.rs @@ -85,7 +85,12 @@ async fn wait_for_update(client: &mut reconnecting::Subscriber, needed: &Reading #[tokio::main] async fn main() { let cli = Cli::parse(); - let mut client = Client::connect(cli.store).await.unwrap(); + + let host = gethostname(); + let host = host.to_string_lossy(); + let name = format!("text-widget@{host}"); + + let mut client = Client::connect(cli.store, name.clone()).await.unwrap(); let readings = client.list_data().await.unwrap(); let reading = resolve_argument(&cli.reading, &readings); @@ -93,9 +98,6 @@ async fn main() { eprintln!("Will be showing: {reading:?}"); } - let host = gethostname(); - let host = host.to_string_lossy(); - let name = format!("text-widget@{host}"); let mut client = reconnecting::Subscriber::new(cli.server, name); loop { From 547e57c5ae4a9f21e934541d3f6b10739d6985cc Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 29 Jul 2024 02:20:28 +0200 Subject: [PATCH 174/687] add ratelimiting to connecting --- crates/data-store/Cargo.toml | 1 + crates/data-store/src/api.rs | 5 ++++ crates/data-store/src/api/client.rs | 36 ++++++++++++++++++++----- crates/data-store/src/server/clients.rs | 26 +++++++++++++++--- 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index ca1315ce..c615d6f5 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -34,6 +34,7 @@ futures = "0.3.30" smallvec = "2.0.0-alpha.6" num = "0.4.3" hdrhistogram = "7.5.4" +governor = "0.6.3" [dev-dependencies] futures-concurrency = "7.6.1" diff --git a/crates/data-store/src/api.rs b/crates/data-store/src/api.rs index fed003c0..5bb01936 100644 --- a/crates/data-store/src/api.rs +++ b/crates/data-store/src/api.rs @@ -1,3 +1,5 @@ +use std::time::Duration; + use protocol::Reading; use serde::{Deserialize, Serialize}; @@ -32,6 +34,8 @@ pub enum ServerError { ReadingFromStore(String), #[error("Connect request should only be send once")] AlreadyConnected, + #[error("Too many requests, rate limited, next requested allowed in: {0:?}")] + TooManyRequests(Duration), } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -51,4 +55,5 @@ pub(crate) enum Response { }, GetStats(Vec), Error(ServerError), + Handshake, } diff --git a/crates/data-store/src/api/client.rs b/crates/data-store/src/api/client.rs index 47fbe5ff..fbe1a563 100644 --- a/crates/data-store/src/api/client.rs +++ b/crates/data-store/src/api/client.rs @@ -1,3 +1,5 @@ +use std::time::Duration; + use futures::{SinkExt, TryStreamExt}; use tokio::net::TcpStream; use tokio::net::ToSocketAddrs; @@ -5,13 +7,14 @@ use tokio_serde::formats::Bincode; use tokio_util::codec::{Framed, LengthDelimitedCodec}; use super::Request; +use super::Response; pub struct Client { stream: tokio_serde::Framed< Framed, - super::Response, + Response, super::Request, - Bincode, + Bincode, >, } @@ -21,6 +24,14 @@ pub enum ConnectError { Io(std::io::Error), #[error("Could not send handshake: {0}")] Sending(std::io::Error), + #[error("Timed out waiting for ")] + Timeout, + #[error("Server unexpectedly closed the connection")] + Closed, + #[error("Server send back an error: {0:?}")] + ServerError(super::ServerError), + #[error("Could not receive server response: {0:?}")] + Receiving(std::io::Error), } #[derive(Debug, thiserror::Error)] @@ -53,13 +64,24 @@ impl Client { .send(Request::Handshake { name }) .await .map_err(ConnectError::Sending)?; - Ok(Self { stream }) + + match tokio::time::timeout(Duration::from_secs(2), stream.try_next()).await { + Ok(Ok(Some(Response::Handshake))) => Ok(Self { stream }), + Ok(Ok(Some(Response::Error(e)))) => Err(ConnectError::ServerError(e)), + Ok(Ok(Some(other))) => unreachable!( + "Server should return handshake response or error after sending \ + first handshake, got impossible response: {other:?}" + ), + Ok(Ok(None)) => Err(ConnectError::Closed), + Ok(Err(e)) => Err(ConnectError::Receiving(e)), + Err(_) => Err(ConnectError::Timeout), + } } - async fn send_receive(&mut self, request: super::Request) -> Result { + async fn send_receive(&mut self, request: super::Request) -> Result { self.stream.send(request).await.map_err(Error::Sending)?; match self.stream.try_next().await.map_err(Error::Receiving)? { - Some(super::Response::Error(e)) => Err(Error::Server(e)), + Some(Response::Error(e)) => Err(Error::Server(e)), Some(response) => Ok(response), None => Err(Error::ConnectionClosed), } @@ -68,7 +90,7 @@ impl Client { pub async fn list_data(&mut self) -> Result, Error> { let request = super::Request::ListData; match self.send_receive(request.clone()).await? { - super::Response::ListData(list) => Ok(list), + Response::ListData(list) => Ok(list), response => Err(Error::IncorrectResponse { request: format!("{request:?}"), response: format!("{response:?}"), @@ -90,7 +112,7 @@ impl Client { n, }; match self.send_receive(request.clone()).await? { - super::Response::GetData { time, data } => Ok((time, data)), + Response::GetData { time, data } => Ok((time, data)), response => Err(Error::IncorrectResponse { request: format!("{request:?}"), response: format!("{response:?}"), diff --git a/crates/data-store/src/server/clients.rs b/crates/data-store/src/server/clients.rs index 741a9425..b31befa5 100644 --- a/crates/data-store/src/server/clients.rs +++ b/crates/data-store/src/server/clients.rs @@ -1,8 +1,12 @@ use std::net::SocketAddr; +use std::num::NonZeroU32; +use std::time::Duration; use color_eyre::eyre::Context; use color_eyre::Section; use futures::{SinkExt, TryStreamExt}; +use governor::clock::{Clock, DefaultClock}; +use governor::{Quota, RateLimiter}; use tokio::net::{TcpListener, TcpStream}; use tokio_serde::formats::Bincode; use tokio_util::codec::{Framed, LengthDelimitedCodec}; @@ -24,6 +28,10 @@ pub(crate) async fn handle( stats: Stats, logs: Logs, ) -> color_eyre::Result<()> { + let quota = Quota::with_period(Duration::from_secs(1)) + .unwrap() + .allow_burst(NonZeroU32::new(5u32).unwrap()); + let limiter = RateLimiter::keyed(quota); let listener = TcpListener::bind(format!("0.0.0.0:{port}")) .await .wrap_err("Could not bind to address") @@ -38,7 +46,19 @@ pub(crate) async fn handle( Ok(res) => res, }; - let Some(conn) = handshake_and_log(socket, source).await else { + let Some((mut conn, name)) = handshake_and_log(socket, source).await else { + continue; + }; + + if let Err(allowed_again) = limiter.check_key(&(source, name)) { + let allowed_in = allowed_again.wait_time_from(DefaultClock::default().now()); + let _ignore_err = conn.send(api::Response::Error(ServerError::TooManyRequests( + allowed_in, + ))); + continue; + } + + let Ok(()) = conn.send(api::Response::Handshake).await else { continue; }; @@ -51,7 +71,7 @@ pub(crate) async fn handle( } } -async fn handshake_and_log(stream: TcpStream, source: SocketAddr) -> Option { +async fn handshake_and_log(stream: TcpStream, source: SocketAddr) -> Option<(Conn, String)> { let length_delimited = Framed::new( stream, LengthDelimitedCodec::builder() @@ -64,7 +84,7 @@ async fn handshake_and_log(stream: TcpStream, source: SocketAddr) -> Option { info!("Client {name} connected from {source}"); - return Some(stream); + return Some((stream, name)); } Ok(Some(other)) => warn!("client tried to connected without handshake, it send: {other:?}"), Ok(None) => warn!("client closed connection immediately"), From 524cacb630241961c8a276183f2b916256ef41ac Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 29 Jul 2024 18:31:35 +0200 Subject: [PATCH 175/687] text-widget now requires setup first --- crates/text-widget/Cargo.toml | 10 +- crates/text-widget/deploy.sh | 5 + crates/text-widget/src/cache.rs | 57 +++++++++ crates/text-widget/src/main.rs | 152 ++++++++++++++---------- crates/text-widget/src/resolve.rs | 76 ++++++++++++ crates/text-widget/src/resolve/fetch.rs | 31 +++++ 6 files changed, 267 insertions(+), 64 deletions(-) create mode 100755 crates/text-widget/deploy.sh create mode 100644 crates/text-widget/src/cache.rs create mode 100644 crates/text-widget/src/resolve.rs create mode 100644 crates/text-widget/src/resolve/fetch.rs diff --git a/crates/text-widget/Cargo.toml b/crates/text-widget/Cargo.toml index e9d76a79..005435a9 100644 --- a/crates/text-widget/Cargo.toml +++ b/crates/text-widget/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "text-widget" +name = "ha-text-widget" version = "0.1.0" rust-version.workspace = true edition.workspace = true @@ -15,3 +15,11 @@ data-store = { workspace = true } nucleo-matcher = "0.3.1" tokio = { workspace = true} gethostname = "0.5.0" + +tracing.workspace = true +tracing-error.workspace = true +tracing-subscriber.workspace = true +dirs = "5.0.1" +serde = { version = "1.0.204", features = ["derive"] } +promptly = "0.3.1" +ron = "0.8.1" diff --git a/crates/text-widget/deploy.sh b/crates/text-widget/deploy.sh new file mode 100755 index 00000000..cc6441a8 --- /dev/null +++ b/crates/text-widget/deploy.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -e + +cargo install --path . diff --git a/crates/text-widget/src/cache.rs b/crates/text-widget/src/cache.rs new file mode 100644 index 00000000..207036a4 --- /dev/null +++ b/crates/text-widget/src/cache.rs @@ -0,0 +1,57 @@ +use std::collections::HashMap; +use std::io::ErrorKind; +use std::path::PathBuf; + +use color_eyre::eyre::Context; +use color_eyre::{Result, Section}; +use protocol::Reading; +use tokio::fs; + +pub(crate) async fn store_to_file(reading: Reading, query: String) -> Result<()> { + let mut entries = load_entries() + .await + .wrap_err("Could not load existing cache")? + .unwrap_or_default(); + + entries.insert(query, reading); + let serialized = + ron::to_string(&entries).wrap_err("Could not serialize query resolve result")?; + + let path = path()?; + fs::write(path, serialized.as_bytes()) + .await + .wrap_err("Could not update file") +} + +fn path() -> Result { + Ok(dirs::data_local_dir() + .ok_or(color_eyre::eyre::eyre!( + "Could not load where to load query from" + ))? + .join(concat!(env!("CARGO_PKG_NAME"), ".ron"))) +} + +type Query = String; +pub(crate) async fn load_entries() -> Result>> { + let path = path()?; + let entries = match fs::read_to_string(&path).await { + Ok(entries) => entries, + Err(e) if e.kind() == ErrorKind::NotFound => return Ok(None), + other_err => other_err + .wrap_err("Could not read cache to string") + .with_note(|| format!("path: {}", path.display()))?, + }; + Ok(Some( + ron::from_str(&entries) + .wrap_err("Could not deserialize resolve cache") + .with_note(|| format!("path: {}", path.display()))?, + )) +} + +pub(crate) async fn load_from_file(query: &Query) -> Result> { + let Some(mut entries) = load_entries().await? else { + return Ok(None); + }; + + Ok(entries.remove(query)) +} diff --git a/crates/text-widget/src/main.rs b/crates/text-widget/src/main.rs index d6753ad8..f09cfe39 100644 --- a/crates/text-widget/src/main.rs +++ b/crates/text-widget/src/main.rs @@ -1,24 +1,27 @@ +use color_eyre::eyre::{eyre, Context}; +use color_eyre::Result; use data_server::subscriber::reconnecting; use data_server::SubMessage; use gethostname::gethostname; -use nucleo_matcher::pattern::Pattern; use protocol::reading_tree::Tree; use protocol::Reading; use std::net::SocketAddr; - -use data_store::api::Client; -use nucleo_matcher::pattern::{AtomKind, CaseMatching, Normalization}; +use std::time::Duration; +use tokio::time::timeout; use clap::Parser; +mod cache; +mod resolve; + #[derive(Parser)] #[command(version, about, long_about = None)] struct Cli { - /// the address of the store - #[arg(long, default_value_t = SocketAddr::from(([127,0,0,1], 1236)))] - store: SocketAddr, + /// the address of the store, optional, speeds up resolving the argument + #[arg(long)] + store: Option, - /// the address of the store + /// the address of the data server #[arg(long, default_value_t = SocketAddr::from(([127,0,0,1], 1235)))] server: SocketAddr, @@ -35,42 +38,6 @@ struct Cli { debug: bool, } -fn to_path(reading: &Reading) -> String { - let path = format!("{:?}", reading); - let (path, _) = path - .rsplit_once('(') - .expect("Reading is tree with at least deph 2"); - let path = path.replace('(', " "); - path -} - -fn resolve_argument(description: &str, options: &[Reading]) -> Reading { - let mut matcher = nucleo_matcher::Matcher::new(nucleo_matcher::Config::DEFAULT); - let pattern = Pattern::new( - description, - CaseMatching::Ignore, - Normalization::Smart, - AtomKind::Fuzzy, - ); - - let mut buf = Vec::new(); - let best_scored = options - .into_iter() - .map(|r| { - ( - pattern.score( - nucleo_matcher::Utf32Str::new(to_path(&r).as_str(), &mut buf), - &mut matcher, - ), - r, - ) - }) - .max_by_key(|(score, _)| score.unwrap_or(0)) - .unwrap() - .1; - best_scored.clone() -} - async fn wait_for_update(client: &mut reconnecting::Subscriber, needed: &Reading) -> Reading { loop { let SubMessage::Reading(r) = client.next_msg().await else { @@ -82,33 +49,92 @@ async fn wait_for_update(client: &mut reconnecting::Subscriber, needed: &Reading } } +async fn setup(cli: &Cli, client: &mut reconnecting::Subscriber) -> Result { + let reading = match resolve::query(cli, client).await { + Ok(reading) => reading, + Err(e) => { + print(cli.json, "E"); + return Err(e); + } + }; + if promptly::prompt_default(format!("Is {reading:?} the correct sensor?"), false) + .wrap_err("Failed to read user confirmation")? + { + cache::store_to_file(reading.clone(), cli.reading.clone()).await?; + Ok(reading) + } else { + Err(eyre!("Exited, user indicated resolved sensor is incorrect")) + } +} + #[tokio::main] -async fn main() { +async fn main() -> Result<()> { let cli = Cli::parse(); + setup_tracing(cli.debug)?; - let host = gethostname(); - let host = host.to_string_lossy(); - let name = format!("text-widget@{host}"); - - let mut client = Client::connect(cli.store, name.clone()).await.unwrap(); - let readings = client.list_data().await.unwrap(); + let mut client = reconnecting::Subscriber::new(cli.server, name()); - let reading = resolve_argument(&cli.reading, &readings); - if cli.debug { - eprintln!("Will be showing: {reading:?}"); - } + let reading = match cache::load_from_file(&cli.reading).await { + Ok(Some(reading)) => reading, + Ok(None) => setup(&cli, &mut client).await?, + Err(e) => { + return Err(eyre!("Error, could not load resolved from file: {e:?}")); + } + }; - let mut client = reconnecting::Subscriber::new(cli.server, name); + tracing::debug!("Will be showing: {reading:?}"); + let timeout_dur = reading.leaf().device.info().max_sample_interval + Duration::from_secs(1); loop { - let new = wait_for_update(&mut client, &reading).await; + let get_update = wait_for_update(&mut client, &reading); + let Ok(new) = timeout(timeout_dur, get_update).await else { + print(cli.json, "X"); + continue; + }; + let info = new.leaf(); let to_print = format!("{0:.1$} {2}", info.val, info.precision(), info.unit); - let use_json = cli.json; - if use_json { - println!("{{\"msg\": \"{to_print}\"}}"); - } else { - println!("{to_print}"); - } + print(cli.json, &to_print); + } +} + +fn name() -> String { + let host = gethostname(); + let host = host.to_string_lossy(); + format!("text-widget@{host}") +} + +fn print(use_json: bool, msg: &str) { + if use_json { + println!("{{\"msg\": \"{msg}\"}}"); + } else { + println!("{msg}"); } } + +fn setup_tracing(debug: bool) -> Result<()> { + use tracing_error::ErrorLayer; + use tracing_subscriber::filter; + use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt}; + + color_eyre::install().unwrap(); + + let filter = filter::EnvFilter::builder().from_env().unwrap(); + let filter = if debug { + let directive = concat!(env!("CARGO_PKG_NAME"), "=debug").parse()?; + filter.add_directive(directive) + } else { + filter + }; + + let fmt = tracing_subscriber::fmt::layer() + .pretty() + .with_line_number(true); + + tracing_subscriber::registry() + .with(filter) + .with(fmt) + .with(ErrorLayer::default()) + .init(); + Ok(()) +} diff --git a/crates/text-widget/src/resolve.rs b/crates/text-widget/src/resolve.rs new file mode 100644 index 00000000..bf9095ca --- /dev/null +++ b/crates/text-widget/src/resolve.rs @@ -0,0 +1,76 @@ +use color_eyre::eyre::eyre; +use data_server::subscriber::reconnecting::Subscriber; +use nucleo_matcher::pattern::Pattern; +use protocol::Reading; +use std::time::Duration; +use tokio::time::timeout; + +use nucleo_matcher::pattern::{AtomKind, CaseMatching, Normalization}; + +mod fetch; + +pub async fn query( + cli: &crate::Cli, + client: &mut Subscriber, +) -> color_eyre::Result { + let mut list = if let Some(store_addr) = cli.store { + fetch::datalist_on_store(store_addr, crate::name()) + .await + .unwrap_or(Vec::new()) + } else { + Vec::new() + }; + if list.is_empty() { + let _ignore_res = timeout( + Duration::from_secs(7), + fetch::datalist_from_updates(client, &mut list), + ) + .await; + }; + + tracing::trace!("{:?}", list); + let Some(reading) = resolve_argument(&cli.reading, &list) else { + return Err(eyre!("Could not resolve argument")); + }; + + Ok(reading) +} + +fn to_path(reading: &Reading) -> String { + let path = format!("{:?}", reading); + let (path, _) = path + .rsplit_once('(') + .expect("Reading is tree with at least deph 2"); + path.replace('(', " ") +} + +fn resolve_argument(description: &str, options: &[Reading]) -> Option { + if options.is_empty() { + return None; + } + + let mut matcher = nucleo_matcher::Matcher::new(nucleo_matcher::Config::DEFAULT); + let pattern = Pattern::new( + description, + CaseMatching::Ignore, + Normalization::Smart, + AtomKind::Fuzzy, + ); + + let mut buf = Vec::new(); + let best_scored = options + .iter() + .map(|r| { + ( + pattern.score( + nucleo_matcher::Utf32Str::new(to_path(r).as_str(), &mut buf), + &mut matcher, + ), + r, + ) + }) + .max_by_key(|(score, _)| score.unwrap_or(0)) + .unwrap() + .1; + Some(best_scored.clone()) +} diff --git a/crates/text-widget/src/resolve/fetch.rs b/crates/text-widget/src/resolve/fetch.rs new file mode 100644 index 00000000..e3dc0a1c --- /dev/null +++ b/crates/text-widget/src/resolve/fetch.rs @@ -0,0 +1,31 @@ +use color_eyre::eyre::Context; +use data_server::subscriber::reconnecting; +use data_server::SubMessage; +use std::net::SocketAddr; + +use data_store::api::Client; + +pub(super) async fn datalist_on_store( + store: SocketAddr, + name: String, +) -> color_eyre::Result> { + Client::connect(store, name) + .await + .wrap_err("failed to connect to data store to list data")? + .list_data() + .await + .wrap_err("connected bu list data call failed") +} + +pub(super) async fn datalist_from_updates( + client: &mut reconnecting::Subscriber, + list: &mut Vec, +) { + loop { + if let SubMessage::Reading(new) = client.next_msg().await { + if !list.iter().any(|in_list| new.is_same_as(in_list)) { + list.push(new); + } + } + } +} From 32a3acdaaa6a9446b185d767e9a6410f1a546217 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 29 Jul 2024 18:32:08 +0200 Subject: [PATCH 176/687] adds max_reading_interval --- crates/protocol/src/large_bedroom/bed.rs | 13 +++++++++++-- crates/protocol/src/large_bedroom/desk.rs | 1 + crates/protocol/src/lib.rs | 7 ++++--- crates/protocol/src/small_bedroom.rs | 1 + 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index ad112e48..e051ab1f 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -391,6 +391,7 @@ impl Device { #[must_use] pub const fn info(&self) -> crate::DeviceInfo { let min_sample_interval = Duration::from_secs(5); + let max_sample_interval = Duration::from_secs(5); let temporal_resolution = Duration::from_secs(1); match self { Device::Sht31 => crate::DeviceInfo { @@ -398,24 +399,28 @@ impl Device { affects_readings: &tree![Reading::Temperature(0.0), Reading::Humidity(0.0)], temporal_resolution, min_sample_interval, + max_sample_interval, }, Device::Bme680 => crate::DeviceInfo { name: "Bme680", affects_readings: &tree![Reading::GassResistance(0.0), Reading::Pressure(0.0)], temporal_resolution, min_sample_interval, + max_sample_interval, }, Device::Max44 => crate::DeviceInfo { name: "Max44", affects_readings: &tree![Reading::Brightness(0.0)], temporal_resolution: Duration::from_millis(50), min_sample_interval: Duration::from_millis(50), + max_sample_interval, }, Device::Mhz14 => crate::DeviceInfo { name: "Mhz14", affects_readings: &tree![Reading::Co2(0)], temporal_resolution, min_sample_interval, + max_sample_interval, }, Device::Sps30 => crate::DeviceInfo { name: "Sps30", @@ -433,18 +438,21 @@ impl Device { ], temporal_resolution, min_sample_interval, + max_sample_interval, }, Device::Nau7802Left => crate::DeviceInfo { name: "Nau7802Left", affects_readings: &tree![Reading::WeightLeft(0)], temporal_resolution: Duration::from_millis(100), min_sample_interval: Duration::from_millis(100), + max_sample_interval, }, Device::Nau7802Right => crate::DeviceInfo { name: "Nau7802Right", affects_readings: &tree![Reading::WeightRight(0)], - temporal_resolution, - min_sample_interval, + temporal_resolution: Duration::from_millis(100), + min_sample_interval: Duration::from_millis(100), + max_sample_interval, }, Device::Gpio => crate::DeviceInfo { name: "Gpio", @@ -460,6 +468,7 @@ impl Device { ], temporal_resolution: Duration::from_millis(1), min_sample_interval: Duration::from_millis(2), + max_sample_interval: Duration::MAX, }, } } diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index 2e04940c..362a51a3 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -193,6 +193,7 @@ impl Device { Reading::Pressure(0.0) ], min_sample_interval: Duration::from_secs(5), + max_sample_interval: Duration::from_secs(5), temporal_resolution: Duration::from_secs(1), }, Device::Gpio => todo!(), diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index e8a81883..95f34a38 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -150,6 +150,7 @@ pub struct DeviceInfo { pub name: &'static str, pub affects_readings: &'static [Reading], pub min_sample_interval: Duration, + pub max_sample_interval: Duration, pub temporal_resolution: Duration, } @@ -192,12 +193,12 @@ impl Msg { assert!(!bytes.is_empty(), "can not decode nothing (zero bytes)"); let msg_type = bytes[0]; - let mut bytes = &mut bytes[1..]; + let bytes = &mut bytes[1..]; if msg_type == Self::READINGS { - Ok(Self::Readings(SensorMessage::::decode(&mut bytes)?)) + Ok(Self::Readings(SensorMessage::::decode(bytes)?)) } else if msg_type == Self::ERROR_REPORT { - Ok(Self::ErrorReport(ErrorReport::decode(&mut bytes)?)) + Ok(Self::ErrorReport(ErrorReport::decode(bytes)?)) } else { Err(DecodeError::IncorrectMsgType(msg_type)) } diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index 3656c179..38a913b1 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -92,6 +92,7 @@ impl Device { ], temporal_resolution: Duration::from_millis(1), min_sample_interval: Duration::from_millis(2), + max_sample_interval: Duration::MAX, }, } } From 8122a9789f54cda11b4f62664434955396b80983 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 29 Jul 2024 18:32:51 +0200 Subject: [PATCH 177/687] refactors reconnecting subscriber, makes it reconnect less fast --- crates/data-server/src/subscriber.rs | 1 + .../src/subscriber/reconnecting.rs | 67 +++++++++++-------- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/crates/data-server/src/subscriber.rs b/crates/data-server/src/subscriber.rs index 5e0f0a1b..7f6d95ad 100644 --- a/crates/data-server/src/subscriber.rs +++ b/crates/data-server/src/subscriber.rs @@ -58,6 +58,7 @@ impl Subscriber { } #[allow(clippy::module_name_repetitions)] +#[derive(Debug)] pub struct AsyncSubscriber { reader: tokio::io::BufReader, buf: Vec, diff --git a/crates/data-server/src/subscriber/reconnecting.rs b/crates/data-server/src/subscriber/reconnecting.rs index 0a783cf9..9f3e7697 100644 --- a/crates/data-server/src/subscriber/reconnecting.rs +++ b/crates/data-server/src/subscriber/reconnecting.rs @@ -4,7 +4,9 @@ use std::time::Duration; use tokio::time::{sleep, timeout}; use tracing::{info, warn}; +#[derive(Debug)] pub struct Subscriber { + retry_period: Duration, connection: Option, addr: SocketAddr, name: String, @@ -13,45 +15,28 @@ pub struct Subscriber { impl Subscriber { pub fn new(addr: SocketAddr, name: String) -> Self { Self { + retry_period: Duration::from_millis(200), connection: None, addr, name, } } + /// # Cancel safety + /// This is cancel safe however the connection will need to be re-established + /// the next time its called pub async fn next_msg(&mut self) -> SubMessage { loop { - let mut retry_period = Duration::from_millis(50); - let mut conn = loop { - if let Some(conn) = self.connection.take() { - break conn; - } - - match timeout( - Duration::from_millis(500), - AsyncSubscriber::connect(self.addr, &self.name), - ) - .await - { - Ok(Ok(conn)) => { - info!("Successfully (re)connected to data-server"); - break conn; - } - Ok(Err(e)) => warn!( - "Failed to (re)connect: {e}\n\ - retrying in {retry_period:?}" - ), - Err(_) => warn!( - "Failed to (re)connect, timed out.\n\ - retrying in {retry_period:?}" - ), - } - sleep(retry_period).await; - retry_period = (retry_period * 2).min(Duration::from_secs(5)); + let mut conn = if let Some(conn) = self.connection.take() { + conn + } else { + self.get_connection_or_reconnect().await }; match conn.next_msg().await { Ok(msg) => { + self.retry_period /= 2; + self.retry_period = self.retry_period.max(Duration::from_millis(200)); self.connection = Some(conn); return msg; } @@ -64,4 +49,32 @@ impl Subscriber { }; } } + + async fn get_connection_or_reconnect(&mut self) -> AsyncSubscriber { + loop { + match timeout( + Duration::from_millis(500), + AsyncSubscriber::connect(self.addr, &self.name), + ) + .await + { + Ok(Ok(conn)) => { + info!("Successfully (re)connected to data-server"); + return conn; + } + Ok(Err(e)) => warn!( + "Failed to (re)connect: {e}\n\ + retrying in {:?}", + self.retry_period + ), + Err(_) => warn!( + "Failed to (re)connect, timed out.\n\ + retrying in {:?}", + self.retry_period + ), + } + sleep(self.retry_period).await; + self.retry_period = (self.retry_period * 2).min(Duration::from_secs(5)); + } + } } From 41a735b0b782f0d798da06a68e8574be27eefa92 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 29 Jul 2024 18:33:14 +0200 Subject: [PATCH 178/687] clippy --- crates/data-store/src/api.rs | 2 +- crates/data-store/src/server/db/series.rs | 5 ++--- crates/data-store/src/server/db/series/bitspec/field.rs | 6 +++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/crates/data-store/src/api.rs b/crates/data-store/src/api.rs index 5bb01936..18dd7af1 100644 --- a/crates/data-store/src/api.rs +++ b/crates/data-store/src/api.rs @@ -4,7 +4,7 @@ use protocol::Reading; use serde::{Deserialize, Serialize}; -mod client; +pub mod client; pub use client::Client; // 8 MB diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index e0ee1e05..7d5c4b5c 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -172,7 +172,7 @@ impl Series { .find(|meta| requested.is_same_as(&meta.reading)) .inspect(|meta| trace!("meta used for decoding: {meta:?}")) .map(|meta| meta.field.clone()) - .expect(&format!( + .unwrap_or_else(|| panic!( "caller of read makes sure all readings are part of this \ series.\n\tseries: {:?},\n\trequested: {:?}", self.meta, readings @@ -225,8 +225,7 @@ pub fn millis_to_minimal_representation(device_info: protocol::DeviceInfo) -> u6 .as_secs_f32(); let mul_factor = 0.001 / needed_interval; let div_factor = 1. / mul_factor; - let div_factor = div_factor.round() as u64; - div_factor + div_factor.round() as u64 } fn try_create_new_if_open_failed( diff --git a/crates/data-store/src/server/db/series/bitspec/field.rs b/crates/data-store/src/server/db/series/bitspec/field.rs index 9f77beb2..3cb825cd 100644 --- a/crates/data-store/src/server/db/series/bitspec/field.rs +++ b/crates/data-store/src/server/db/series/bitspec/field.rs @@ -52,9 +52,9 @@ where numb -= num::cast(self.decode_add).unwrap(); numb /= num::cast(self.decode_scale).unwrap(); - let to_encode: u32 = num::cast(numb).expect(&format!( - "could not cast numb to u32, numb: {numb}, field: {self:?}", - )); + let to_encode: u32 = num::cast(numb).unwrap_or_else(|| { + panic!("could not cast numb to u32, numb: {numb}, field: {self:?}",) + }); compression::encode(to_encode, line, self.offset, self.length); } From ead5e36eb1999fca4c2024c3246e66abbb001354 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 29 Jul 2024 23:41:12 +0200 Subject: [PATCH 179/687] show error or runsetup in bar if setup needed or error occured --- crates/text-widget/src/main.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/text-widget/src/main.rs b/crates/text-widget/src/main.rs index f09cfe39..ba7f817a 100644 --- a/crates/text-widget/src/main.rs +++ b/crates/text-widget/src/main.rs @@ -76,8 +76,12 @@ async fn main() -> Result<()> { let reading = match cache::load_from_file(&cli.reading).await { Ok(Some(reading)) => reading, - Ok(None) => setup(&cli, &mut client).await?, + Ok(None) => { + print(cli.json, "RunSetup"); + setup(&cli, &mut client).await? + } Err(e) => { + print(cli.json, "Error"); return Err(eyre!("Error, could not load resolved from file: {e:?}")); } }; From 98e11f61b387a06fafbd755ff83603e034c0f563 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 29 Jul 2024 23:42:30 +0200 Subject: [PATCH 180/687] Split off log and timing tracking This decreases the chance data-store goes down. Has some overhead (clients need to connect to data-store and log-store if the need logs and data). Introduces some code duplication but this can hopefully be reduced later, in any case it is worth the better uptime for data-store. --- Cargo.lock | 319 +++++++++++++++++- crates/data-store/src/api.rs | 2 - crates/data-store/src/server.rs | 6 +- crates/data-store/src/server/clients.rs | 29 +- crates/data-store/src/server/db.rs | 25 +- crates/data-store/src/server/db/series.rs | 2 + crates/log-store/.cargo/config.toml | 2 + crates/log-store/Cargo.toml | 41 +++ crates/log-store/deploy.sh | 19 ++ crates/log-store/src/api.rs | 47 +++ crates/log-store/src/api/client.rs | 89 +++++ crates/log-store/src/lib.rs | 6 + crates/log-store/src/main.rs | 50 +++ crates/log-store/src/server.rs | 33 ++ crates/log-store/src/server/clients.rs | 129 +++++++ crates/log-store/src/server/db.rs | 44 +++ .../src/server/db/log.rs | 0 .../src/server/db/stats.rs | 0 crates/log-store/tests/list_data.rs | 207 ++++++++++++ 19 files changed, 986 insertions(+), 64 deletions(-) create mode 100644 crates/log-store/.cargo/config.toml create mode 100644 crates/log-store/Cargo.toml create mode 100755 crates/log-store/deploy.sh create mode 100644 crates/log-store/src/api.rs create mode 100644 crates/log-store/src/api/client.rs create mode 100644 crates/log-store/src/lib.rs create mode 100644 crates/log-store/src/main.rs create mode 100644 crates/log-store/src/server.rs create mode 100644 crates/log-store/src/server/clients.rs create mode 100644 crates/log-store/src/server/db.rs rename crates/{data-store => log-store}/src/server/db/log.rs (100%) rename crates/{data-store => log-store}/src/server/db/stats.rs (100%) create mode 100644 crates/log-store/tests/list_data.rs diff --git a/Cargo.lock b/Cargo.lock index 50ada631..0bdf4898 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -670,6 +670,17 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +[[package]] +name = "clipboard-win" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" +dependencies = [ + "error-code", + "str-buf", + "winapi", +] + [[package]] name = "cobs" version = "0.2.3" @@ -833,6 +844,19 @@ dependencies = [ "winapi", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if 1.0.0", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core 0.9.10", +] + [[package]] name = "data-server" version = "0.0.0" @@ -859,6 +883,7 @@ dependencies = [ "data-server", "futures", "futures-concurrency", + "governor", "hdrhistogram", "jiff", "nucleo-matcher", @@ -949,6 +974,48 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if 1.0.0", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "dns-parser" version = "0.8.0" @@ -1008,6 +1075,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + [[package]] name = "enum-ordinalize" version = "4.3.0" @@ -1058,6 +1131,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "error-code" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" +dependencies = [ + "libc", + "str-buf", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -1121,6 +1204,17 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +[[package]] +name = "fd-lock" +version = "3.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef033ed5e9bad94e55838ca0ca906db0e043f517adda0c8b79c7a8c66c93c1b5" +dependencies = [ + "cfg-if 1.0.0", + "rustix 0.38.34", + "windows-sys 0.48.0", +] + [[package]] name = "flate2" version = "1.0.30" @@ -1287,6 +1381,12 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + [[package]] name = "futures-util" version = "0.3.30" @@ -1353,6 +1453,26 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "governor" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b" +dependencies = [ + "cfg-if 1.0.0", + "dashmap", + "futures", + "futures-timer", + "no-std-compat", + "nonzero_ext", + "parking_lot 0.12.3", + "portable-atomic", + "quanta", + "rand", + "smallvec 1.13.2", + "spinning_top", +] + [[package]] name = "gpio-cdev" version = "0.6.0" @@ -1401,6 +1521,27 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ha-text-widget" +version = "0.1.0" +dependencies = [ + "clap", + "color-eyre", + "data-server", + "data-store", + "dirs", + "gethostname", + "nucleo-matcher", + "promptly", + "protocol", + "ron", + "serde", + "tokio", + "tracing", + "tracing-error", + "tracing-subscriber", +] + [[package]] name = "hash32" version = "0.2.1" @@ -1775,6 +1916,16 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", +] + [[package]] name = "linux-embedded-hal" version = "0.4.0" @@ -1824,6 +1975,34 @@ dependencies = [ "value-bag", ] +[[package]] +name = "log-store" +version = "0.1.0" +dependencies = [ + "clap", + "color-eyre", + "data-server", + "futures", + "futures-concurrency", + "governor", + "hdrhistogram", + "jiff", + "nucleo-matcher", + "num", + "protocol", + "reserve-port", + "serde", + "smallvec 2.0.0-alpha.6", + "temp-dir", + "thiserror", + "tokio", + "tokio-serde", + "tokio-util", + "tracing", + "tracing-error", + "tracing-subscriber", +] + [[package]] name = "lru" version = "0.12.3" @@ -1981,6 +2160,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec 1.13.2", +] + [[package]] name = "nix" version = "0.23.2" @@ -2018,6 +2206,12 @@ dependencies = [ "libc", ] +[[package]] +name = "no-std-compat" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" + [[package]] name = "nom" version = "7.1.3" @@ -2028,6 +2222,12 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nonzero_ext" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -2142,6 +2342,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "overload" version = "0.1.1" @@ -2294,6 +2500,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "portable-atomic" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" + [[package]] name = "postcard" version = "1.0.8" @@ -2364,6 +2576,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "promptly" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9acbc6c5a5b029fe58342f58445acb00ccfe24624e538894bc2f04ce112980ba" +dependencies = [ + "rustyline", +] + [[package]] name = "protocol" version = "0.1.0" @@ -2387,6 +2608,21 @@ dependencies = [ "unicase", ] +[[package]] +name = "quanta" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi", + "web-sys", + "winapi", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -2408,6 +2644,16 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + [[package]] name = "rand" version = "0.8.5" @@ -2459,6 +2705,15 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "raw-cpuid" +version = "11.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb9ee317cfe3fbd54b36a511efc1edd42e216903c9cd575e686dd68a2ba90d8d" +dependencies = [ + "bitflags 2.6.0", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -2477,6 +2732,17 @@ dependencies = [ "bitflags 2.6.0", ] +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "regex" version = "1.10.5" @@ -2626,6 +2892,30 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +[[package]] +name = "rustyline" +version = "9.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db7826789c0e25614b03e5a54a0717a86f9ff6e6e5247f92b369472869320039" +dependencies = [ + "bitflags 1.3.2", + "cfg-if 1.0.0", + "clipboard-win", + "dirs-next", + "fd-lock", + "libc", + "log", + "memchr", + "nix 0.23.2", + "radix_trie", + "scopeguard", + "smallvec 1.13.2", + "unicode-segmentation", + "unicode-width", + "utf8parse", + "winapi", +] + [[package]] name = "ryu" version = "1.0.18" @@ -2857,6 +3147,15 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spinning_top" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" +dependencies = [ + "lock_api", +] + [[package]] name = "stability" version = "0.2.1" @@ -2879,6 +3178,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "str-buf" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" + [[package]] name = "strsim" version = "0.11.1" @@ -2974,20 +3279,6 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f227968ec00f0e5322f9b8173c7a0cbcff6181a0a5b28e9892491c286277231" -[[package]] -name = "text-widget" -version = "0.1.0" -dependencies = [ - "clap", - "color-eyre", - "data-server", - "data-store", - "gethostname", - "nucleo-matcher", - "protocol", - "tokio", -] - [[package]] name = "thiserror" version = "1.0.63" diff --git a/crates/data-store/src/api.rs b/crates/data-store/src/api.rs index 18dd7af1..aa71c64e 100644 --- a/crates/data-store/src/api.rs +++ b/crates/data-store/src/api.rs @@ -15,8 +15,6 @@ pub(crate) enum Request { Handshake { name: String, }, - GetLog(protocol::Device), - GetStats(protocol::Device), ListData, GetData { reading: Reading, diff --git a/crates/data-store/src/server.rs b/crates/data-store/src/server.rs index de70fd25..88d0eb20 100644 --- a/crates/data-store/src/server.rs +++ b/crates/data-store/src/server.rs @@ -12,18 +12,14 @@ mod db; // used from main and tests pub async fn run(data_server: SocketAddr, client_port: u16, data_dir: &Path) -> Result<()> { let data = db::Data(Arc::new(Mutex::new(HashMap::new()))); - let stats = db::Stats(Arc::new(Mutex::new(HashMap::new()))); - let logs = db::Logs(Arc::new(Mutex::new(HashMap::new()))); let error = ( db::run( data_server, data.clone(), - stats.clone(), - logs.clone(), data_dir, ), - clients::handle(client_port, data, stats, logs), + clients::handle(client_port, data), ) .race() .await; diff --git a/crates/data-store/src/server/clients.rs b/crates/data-store/src/server/clients.rs index b31befa5..f4bd72e9 100644 --- a/crates/data-store/src/server/clients.rs +++ b/crates/data-store/src/server/clients.rs @@ -12,7 +12,7 @@ use tokio_serde::formats::Bincode; use tokio_util::codec::{Framed, LengthDelimitedCodec}; use tracing::{debug, error, info, warn}; -use super::db::{Data, Logs, Stats}; +use super::db::Data; use crate::api::{self, ServerError}; type Conn = tokio_serde::Framed< @@ -22,12 +22,7 @@ type Conn = tokio_serde::Framed< Bincode, >; -pub(crate) async fn handle( - port: u16, - data: Data, - stats: Stats, - logs: Logs, -) -> color_eyre::Result<()> { +pub(crate) async fn handle(port: u16, data: Data) -> color_eyre::Result<()> { let quota = Quota::with_period(Duration::from_secs(1)) .unwrap() .allow_burst(NonZeroU32::new(5u32).unwrap()); @@ -62,12 +57,7 @@ pub(crate) async fn handle( continue; }; - tokio::task::spawn(handle_client( - conn, - data.clone(), - stats.clone(), - logs.clone(), - )); + tokio::task::spawn(handle_client(conn, data.clone())); } } @@ -94,7 +84,7 @@ async fn handshake_and_log(stream: TcpStream, source: SocketAddr) -> Option<(Con None } -async fn handle_client(mut conn: Conn, data: Data, stats: Stats, logs: Logs) { +async fn handle_client(mut conn: Conn, data: Data) { loop { let request = match conn.try_next().await { Ok(Some(request)) => request, @@ -107,7 +97,7 @@ async fn handle_client(mut conn: Conn, data: Data, stats: Stats, logs: Logs) { return; } }; - let response = match perform_request(request, &data, &stats, &logs).await { + let response = match perform_request(request, &data).await { Err(err) => api::Response::Error(err), Ok(r) => r, }; @@ -118,12 +108,7 @@ async fn handle_client(mut conn: Conn, data: Data, stats: Stats, logs: Logs) { } } -async fn perform_request( - request: api::Request, - data: &Data, - stats: &Stats, - logs: &Logs, -) -> Result { +async fn perform_request(request: api::Request, data: &Data) -> Result { Ok(match request { api::Request::Handshake { .. } => return Err(ServerError::AlreadyConnected), api::Request::ListData => api::Response::ListData(data.list().await), @@ -136,7 +121,5 @@ async fn perform_request( let (time, data) = data.get(reading, start, end, n).await?; api::Response::GetData { time, data } } - api::Request::GetLog(device) => api::Response::GetLog(logs.get(&device).await), - api::Request::GetStats(device) => api::Response::GetStats(stats.get(&device).await), }) } diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index e253ae7f..6030f112 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -13,34 +13,19 @@ use data_server::SubMessage; mod series; use series::Series; -mod log; -pub(crate) use log::Logs; - -mod stats; -pub(crate) use stats::Stats; - use crate::api; -pub(crate) async fn run( - data_server_addr: SocketAddr, - data: Data, - stats: Stats, - logs: Logs, - data_dir: &Path, -) -> Result<()> { +pub(crate) async fn run(data_server_addr: SocketAddr, data: Data, data_dir: &Path) -> Result<()> { let mut sub = reconnecting::Subscriber::new(data_server_addr, "ha-data-store".to_string()); let mut recently_logged = (Instant::now(), String::new()); loop { let msg = sub.next_msg().await; let res = match msg { - SubMessage::Reading(reading) => { - series::store(&data, &reading, data_dir) - .await - .with_note(|| format!("reading: {reading:?}"))?; - stats.increment(reading.device()).await - } - SubMessage::ErrorReport(report) => logs.store(*report).await, + SubMessage::Reading(reading) => series::store(&data, &reading, data_dir) + .await + .with_note(|| format!("reading: {reading:?}")), + SubMessage::ErrorReport(_) => Ok(()), }; const FIVE_MIN: Duration = Duration::from_secs(60 * 5); diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index 7d5c4b5c..61c8db5a 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -349,6 +349,7 @@ mod test { name: "test", affects_readings: &[], min_sample_interval: std::time::Duration::from_secs(5), + max_sample_interval: std::time::Duration::from_secs(5), temporal_resolution: std::time::Duration::from_secs(1), }; let factor = millis_to_minimal_representation(info); @@ -358,6 +359,7 @@ mod test { name: "test", affects_readings: &[], min_sample_interval: std::time::Duration::from_secs(5), + max_sample_interval: std::time::Duration::from_secs(5), temporal_resolution: std::time::Duration::from_millis(1), }; let factor = millis_to_minimal_representation(info); diff --git a/crates/log-store/.cargo/config.toml b/crates/log-store/.cargo/config.toml new file mode 100644 index 00000000..1002fed4 --- /dev/null +++ b/crates/log-store/.cargo/config.toml @@ -0,0 +1,2 @@ +[target.aarch64-unknown-linux-musl] +rustflags = ["-Clinker=rust-lld"] diff --git a/crates/log-store/Cargo.toml b/crates/log-store/Cargo.toml new file mode 100644 index 00000000..8dc86cbd --- /dev/null +++ b/crates/log-store/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "log-store" +version = "0.1.0" +rust-version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true + +[features] +api = [] +server = [] +default = ["api", "server"] + +[dependencies] +clap = { workspace = true } +color-eyre = { workspace = true } +tracing = { workspace = true } +tracing-error = { workspace = true } +tracing-subscriber = { workspace = true, features = ["env-filter"] } +jiff = { workspace =true, features = ["serde"] } + +protocol = { workspace = true, features = ["alloc", "thiserror"] } +data-server = { workspace = true } + +tokio = { workspace = true, features = ["fs", "net", "rt-multi-thread", "sync"] } +futures-concurrency = "7.6.1" +tokio-serde = { version = "0.9.0", features = ["bincode"] } +tokio-util = { version = "0.7.11", features = ["codec"] } +serde = { version = "1.0.203", features = ["derive"] } +thiserror = { workspace = true } +futures = "0.3.30" +smallvec = "2.0.0-alpha.6" +num = "0.4.3" +hdrhistogram = "7.5.4" +governor = "0.6.3" + +[dev-dependencies] +futures-concurrency = "7.6.1" +nucleo-matcher = "0.3.1" +reserve-port = "2.0.1" +temp-dir = "0.1.13" diff --git a/crates/log-store/deploy.sh b/crates/log-store/deploy.sh new file mode 100755 index 00000000..b9d23e54 --- /dev/null +++ b/crates/log-store/deploy.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -e + +BUILD_ARG=--release +SERVER="sgc" # ssh config name or full address +NAME=data-store + +cargo build --target=aarch64-unknown-linux-musl $BUILD_ARG +rsync -vh --progress \ + ../../target/aarch64-unknown-linux-musl/release/$NAME \ + $SERVER:/tmp/ + +cmds=" +sudo mv /tmp/$NAME /home/ha/$NAME +sudo chown ha:ha /home/ha/$NAME +sudo systemctl restart $NAME.service +" + +ssh -t sgc "$cmds" diff --git a/crates/log-store/src/api.rs b/crates/log-store/src/api.rs new file mode 100644 index 00000000..8f790030 --- /dev/null +++ b/crates/log-store/src/api.rs @@ -0,0 +1,47 @@ +use std::time::Duration; + +use protocol::Reading; + +use serde::{Deserialize, Serialize}; + +pub mod client; +pub use client::Client; + +// 8 MB +pub(crate) const MAX_PACKAGE_SIZE: usize = 8 * 1024 * 1024; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub(crate) enum Request { + Handshake { + name: String, + }, + GetLog(protocol::Device), + GetStats(protocol::Device), +} + +#[derive(Debug, Clone, Serialize, Deserialize, thiserror::Error)] +pub enum ServerError { + #[error("We do not have any data for this reading: {reading:?}")] + NotInStore { reading: Reading }, + #[error("Internal error while reading data, error: {0}")] + ReadingFromStore(String), + #[error("Connect request should only be send once")] + AlreadyConnected, + #[error("Too many requests, rate limited, next requested allowed in: {0:?}")] + TooManyRequests(Duration), +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Percentile { + pub bucket_ends: u64, + pub percentile: f64, + pub count_in_bucket: u64, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub(crate) enum Response { + GetLog(Vec<(jiff::Timestamp, protocol::Error)>), + GetStats(Vec), + Error(ServerError), + Handshake, +} diff --git a/crates/log-store/src/api/client.rs b/crates/log-store/src/api/client.rs new file mode 100644 index 00000000..6d774409 --- /dev/null +++ b/crates/log-store/src/api/client.rs @@ -0,0 +1,89 @@ +use std::time::Duration; + +use futures::{SinkExt, TryStreamExt}; +use tokio::net::TcpStream; +use tokio::net::ToSocketAddrs; +use tokio_serde::formats::Bincode; +use tokio_util::codec::{Framed, LengthDelimitedCodec}; + +use super::Request; +use super::Response; + +pub struct Client { + stream: tokio_serde::Framed< + Framed, + Response, + super::Request, + Bincode, + >, +} + +#[derive(Debug, thiserror::Error)] +pub enum ConnectError { + #[error("Error while connecting to data server: {0}")] + Io(std::io::Error), + #[error("Could not send handshake: {0}")] + Sending(std::io::Error), + #[error("Timed out waiting for ")] + Timeout, + #[error("Server unexpectedly closed the connection")] + Closed, + #[error("Server send back an error: {0:?}")] + ServerError(super::ServerError), + #[error("Could not receive server response: {0:?}")] + Receiving(std::io::Error), +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Got unexpected response response to request {request:?}")] + IncorrectResponse { request: String, response: String }, + #[error("Error while sending request: {0}")] + Sending(std::io::Error), + #[error("Error while sending request: {0}")] + Receiving(std::io::Error), + #[error("Server ran into an error while processing our request: {0}")] + Server(super::ServerError), + #[error("Server closed connection before it awnserd")] + ConnectionClosed, +} + +impl Client { + pub async fn connect(addr: impl ToSocketAddrs, name: String) -> Result { + let stream = TcpStream::connect(addr).await.map_err(ConnectError::Io)?; + + let length_delimited = Framed::new( + stream, + LengthDelimitedCodec::builder() + .max_frame_length(super::MAX_PACKAGE_SIZE) + .new_codec(), + ); + + let mut stream = tokio_serde::Framed::new(length_delimited, Bincode::default()); + stream + .send(Request::Handshake { name }) + .await + .map_err(ConnectError::Sending)?; + + match tokio::time::timeout(Duration::from_secs(2), stream.try_next()).await { + Ok(Ok(Some(Response::Handshake))) => Ok(Self { stream }), + Ok(Ok(Some(Response::Error(e)))) => Err(ConnectError::ServerError(e)), + Ok(Ok(Some(other))) => unreachable!( + "Server should return handshake response or error after sending \ + first handshake, got impossible response: {other:?}" + ), + Ok(Ok(None)) => Err(ConnectError::Closed), + Ok(Err(e)) => Err(ConnectError::Receiving(e)), + Err(_) => Err(ConnectError::Timeout), + } + } + + async fn send_receive(&mut self, request: super::Request) -> Result { + self.stream.send(request).await.map_err(Error::Sending)?; + match self.stream.try_next().await.map_err(Error::Receiving)? { + Some(Response::Error(e)) => Err(Error::Server(e)), + Some(response) => Ok(response), + None => Err(Error::ConnectionClosed), + } + } +} diff --git a/crates/log-store/src/lib.rs b/crates/log-store/src/lib.rs new file mode 100644 index 00000000..3ca113c0 --- /dev/null +++ b/crates/log-store/src/lib.rs @@ -0,0 +1,6 @@ +#![allow(clippy::missing_errors_doc, clippy::missing_panics_doc)] + +#[cfg(feature = "api")] +pub mod api; +#[cfg(feature = "server")] +pub mod server; diff --git a/crates/log-store/src/main.rs b/crates/log-store/src/main.rs new file mode 100644 index 00000000..7ea76d64 --- /dev/null +++ b/crates/log-store/src/main.rs @@ -0,0 +1,50 @@ +use std::net::SocketAddr; +use std::path::PathBuf; + +use clap::Parser; +use color_eyre::eyre::Result; + +#[derive(Parser, Debug)] +#[command(name = "data server")] +#[command(version = "1.0")] +#[command(about = "Receives sensor events then logs errors and tracks timing")] +struct Cli { + /// data server + #[arg(short, long)] + data_server: SocketAddr, + + #[arg(short, long)] + client_port: u16, + + #[arg(long, default_value = ".")] + log_dir: PathBuf, +} + +#[tokio::main] +async fn main() -> Result<()> { + setup_tracing().unwrap(); + let cli = Cli::parse(); + tracing::info!("started log-store, args: {cli:?}"); + + log_store::server::run(cli.data_server, cli.client_port, &cli.log_dir).await +} + +fn setup_tracing() -> Result<()> { + use tracing_error::ErrorLayer; + use tracing_subscriber::filter; + use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt}; + + color_eyre::install().unwrap(); + + let filter = filter::EnvFilter::builder().from_env().unwrap(); + let fmt = tracing_subscriber::fmt::layer() + .pretty() + .with_line_number(true); + + tracing_subscriber::registry() + .with(filter) + .with(fmt) + .with(ErrorLayer::default()) + .init(); + Ok(()) +} diff --git a/crates/log-store/src/server.rs b/crates/log-store/src/server.rs new file mode 100644 index 00000000..6bf8f151 --- /dev/null +++ b/crates/log-store/src/server.rs @@ -0,0 +1,33 @@ +use color_eyre::Result; +use futures_concurrency::future::Race; +use std::collections::HashMap; +use std::net::SocketAddr; +use std::path::Path; +use std::sync::Arc; +use tokio::sync::Mutex; + +mod clients; +mod db; + +// used from main and tests +pub async fn run(data_server: SocketAddr, client_port: u16, log_dir: &Path) -> Result<()> { + let stats = db::Stats(Arc::new(Mutex::new(HashMap::new()))); + let logs = db::Logs(Arc::new(Mutex::new(HashMap::new()))); + + let error = ( + db::run( + data_server, + stats.clone(), + logs.clone(), + log_dir, + ), + clients::handle(client_port, stats, logs), + ) + .race() + .await; + assert!( + error.is_err(), + "db::run and client::handle never return unless an error happens" + ); + error +} diff --git a/crates/log-store/src/server/clients.rs b/crates/log-store/src/server/clients.rs new file mode 100644 index 00000000..d1ff013f --- /dev/null +++ b/crates/log-store/src/server/clients.rs @@ -0,0 +1,129 @@ +use std::net::SocketAddr; +use std::num::NonZeroU32; +use std::time::Duration; + +use color_eyre::eyre::Context; +use color_eyre::Section; +use futures::{SinkExt, TryStreamExt}; +use governor::clock::{Clock, DefaultClock}; +use governor::{Quota, RateLimiter}; +use tokio::net::{TcpListener, TcpStream}; +use tokio_serde::formats::Bincode; +use tokio_util::codec::{Framed, LengthDelimitedCodec}; +use tracing::{debug, error, info, warn}; + +use super::db::{Logs, Stats}; +use crate::api::{self, ServerError}; + +type Conn = tokio_serde::Framed< + Framed, + api::Request, + api::Response, + Bincode, +>; + +pub(crate) async fn handle( + port: u16, + stats: Stats, + logs: Logs, +) -> color_eyre::Result<()> { + let quota = Quota::with_period(Duration::from_secs(1)) + .unwrap() + .allow_burst(NonZeroU32::new(5u32).unwrap()); + let limiter = RateLimiter::keyed(quota); + let listener = TcpListener::bind(format!("0.0.0.0:{port}")) + .await + .wrap_err("Could not bind to address") + .with_note(|| format!("port: {port}"))?; + + loop { + let (socket, source) = match listener.accept().await { + Err(e) => { + warn!("client could not connect: {e}"); + continue; + } + Ok(res) => res, + }; + + let Some((mut conn, name)) = handshake_and_log(socket, source).await else { + continue; + }; + + if let Err(allowed_again) = limiter.check_key(&(source, name)) { + let allowed_in = allowed_again.wait_time_from(DefaultClock::default().now()); + let _ignore_err = conn.send(api::Response::Error(ServerError::TooManyRequests( + allowed_in, + ))); + continue; + } + + let Ok(()) = conn.send(api::Response::Handshake).await else { + continue; + }; + + tokio::task::spawn(handle_client( + conn, + stats.clone(), + logs.clone(), + )); + } +} + +async fn handshake_and_log(stream: TcpStream, source: SocketAddr) -> Option<(Conn, String)> { + let length_delimited = Framed::new( + stream, + LengthDelimitedCodec::builder() + .max_frame_length(api::MAX_PACKAGE_SIZE) + .new_codec(), + ); + let mut stream: tokio_serde::Framed<_, api::Request, api::Response, _> = + tokio_serde::Framed::new(length_delimited, Bincode::default()); + + match stream.try_next().await { + Ok(Some(api::Request::Handshake { name })) => { + info!("Client {name} connected from {source}"); + return Some((stream, name)); + } + Ok(Some(other)) => warn!("client tried to connected without handshake, it send: {other:?}"), + Ok(None) => warn!("client closed connection immediately"), + Err(e) => warn!("connection or decoding issue while receiving handshake: {e:?}"), + } + + None +} + +async fn handle_client(mut conn: Conn, stats: Stats, logs: Logs) { + loop { + let request = match conn.try_next().await { + Ok(Some(request)) => request, + Ok(None) => { + debug!("Connection ended"); + return; + } + Err(e) => { + error!("Could not receive request: {e:?}"); + return; + } + }; + let response = match perform_request(request, &stats, &logs).await { + Err(err) => api::Response::Error(err), + Ok(r) => r, + }; + if let Err(e) = conn.send(response).await { + error!("Error sending response to client: {e:?}"); + return; + } + } +} + +async fn perform_request( + request: api::Request, + stats: &Stats, + logs: &Logs, +) -> Result { + Ok(match request { + api::Request::Handshake { .. } => return Err(ServerError::AlreadyConnected), + api::Request::GetLog(device) => api::Response::GetLog(logs.get(&device).await), + api::Request::GetStats(device) => api::Response::GetStats(stats.get(&device).await), + }) +} diff --git a/crates/log-store/src/server/db.rs b/crates/log-store/src/server/db.rs new file mode 100644 index 00000000..8a15cbbc --- /dev/null +++ b/crates/log-store/src/server/db.rs @@ -0,0 +1,44 @@ +use std::net::SocketAddr; +use std::path::Path; +use std::time::{Duration, Instant}; + +use data_server::subscriber::reconnecting; + +use color_eyre::Result; +use data_server::SubMessage; + +mod log; +pub(crate) use log::Logs; + +mod stats; +pub(crate) use stats::Stats; + +pub(crate) async fn run( + data_server_addr: SocketAddr, + stats: Stats, + logs: Logs, + log_dir: &Path, +) -> Result<()> { + let mut sub = reconnecting::Subscriber::new(data_server_addr, "ha-data-store".to_string()); + + let mut recently_logged = (Instant::now(), String::new()); + loop { + let msg = sub.next_msg().await; + let res = match msg { + SubMessage::Reading(reading) => stats.increment(reading.device()).await, + SubMessage::ErrorReport(report) => logs.store(*report).await, + }; + + const FIVE_MIN: Duration = Duration::from_secs(60 * 5); + if let Err(report) = res { + let e = format!("got error with report: {report:?}"); + tracing::warn!("test: {e}"); + if recently_logged.1 == e && recently_logged.0.elapsed() <= FIVE_MIN { + continue; + } else { + tracing::error!("Error processing new reading: {e}"); + recently_logged = (Instant::now(), e); + } + } + } +} diff --git a/crates/data-store/src/server/db/log.rs b/crates/log-store/src/server/db/log.rs similarity index 100% rename from crates/data-store/src/server/db/log.rs rename to crates/log-store/src/server/db/log.rs diff --git a/crates/data-store/src/server/db/stats.rs b/crates/log-store/src/server/db/stats.rs similarity index 100% rename from crates/data-store/src/server/db/stats.rs rename to crates/log-store/src/server/db/stats.rs diff --git a/crates/log-store/tests/list_data.rs b/crates/log-store/tests/list_data.rs new file mode 100644 index 00000000..76447d8f --- /dev/null +++ b/crates/log-store/tests/list_data.rs @@ -0,0 +1,207 @@ +use std::net::SocketAddr; +use std::sync::Once; +use std::time::Duration; + +use futures::FutureExt; +use futures_concurrency::future::Race; +use protocol::large_bedroom::bed; +use protocol::{large_bedroom, Reading}; +use temp_dir::TempDir; +use tokio::io::AsyncWriteExt; +use tokio::net::TcpStream; +use tokio::sync::{mpsc, Notify}; +use tokio::time::sleep; +use tracing_error::ErrorLayer; +use tracing_subscriber::layer::SubscriberExt; +use tracing_subscriber::util::SubscriberInitExt; + +const fn test_readings(v: f32) -> [Reading; 2] { + [ + Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::Temperature(v))), + Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::Humidity(v))), + ] +} + +async fn data_server(sub_port: impl Into, data_port: impl Into) { + use data_server::server; + + let (tx, rx) = mpsc::channel(2000); + tokio::select! { + e = server::register_subs(sub_port.into(), &tx) => e.unwrap(), + e = server::handle_data_sources(data_port.into(), &tx) => e.unwrap(), + e = server::spread_updates(rx) => e.unwrap(), + }; +} + +async fn send_sensor_values(data_port: u16, values: &[f32], data_send: &Notify) { + let mut conn = TcpStream::connect(("127.0.0.1", data_port)).await.unwrap(); + for v in values { + let mut sensor_msg = protocol::SensorMessage::<50>::default(); + for val in test_readings(*v) { + sensor_msg.values.push(val).unwrap(); + } + let encoded = protocol::Msg::Readings(sensor_msg).encode(); + conn.write_all(&encoded).await.unwrap(); + sleep(Duration::from_secs_f32(1.1)).await; + } + data_send.notify_waiters(); + sleep(Duration::from_secs(999)).await; +} + +async fn check_client_list_data(data_store_addr: SocketAddr, data_send: &Notify) { + data_send.notified().await; + sleep(Duration::from_secs_f32(0.1)).await; + + let mut client = + data_store::api::Client::connect(data_store_addr, "data_store_example".to_owned()) + .await + .unwrap(); + let list = client.list_data().await.unwrap(); + + assert!( + !list.is_empty(), + "list is empty, should contain one reading" + ); + assert!( + list.iter().any(|r| { + if let protocol::Reading::LargeBedroom(protocol::large_bedroom::Reading::Bed( + protocol::large_bedroom::bed::Reading::Temperature(_), + )) = r + { + true + } else { + false + } + }), + "list is missing expected reading bed::Reading::Temperature. \ + Full list is: {list:?}" + ) +} + +async fn check_client_get_data( + data_store_addr: SocketAddr, + sensor_values: &[f32], + data_send: &Notify, +) { + data_send.notified().await; + sleep(Duration::from_secs_f32(0.1)).await; + let mut client = + data_store::api::Client::connect(data_store_addr, "data_store_example".to_owned()) + .await + .unwrap(); + let (time, data) = client + .get_data( + jiff::Timestamp::now() - jiff::Span::default().seconds(30), + jiff::Timestamp::now() + jiff::Span::default().seconds(30), + test_readings(0.0)[0].clone(), + 5, + ) + .await + .unwrap(); + + assert_eq!(time.len(), data.len()); + assert!(data + .into_iter() + .zip(sensor_values.into_iter().copied()) + .inspect(|r| println!("(got, expected): {r:?}")) + .all(|(a, b)| (a - b).abs() < 0.1)) +} + +static SETUP_REPORTING: Once = Once::new(); + +fn setup_reporting() { + SETUP_REPORTING.call_once(|| { + color_eyre::install().unwrap(); + tracing_subscriber::registry() + .with(ErrorLayer::default()) + .with(tracing_subscriber::fmt::layer().pretty().with_test_writer()) + .init(); + }); +} + +#[tokio::test] +async fn list_data() { + const DATA_SERVER_STARTUP: Duration = Duration::from_millis(20); + const DATA_STORE_STARTUP: Duration = Duration::from_millis(20); + const FIRST_MSG_PROCESSED: Duration = Duration::from_millis(1000); + + setup_reporting(); + + let test_dir = TempDir::new().unwrap(); + + let sub_port = reserve_port::ReservedPort::random().unwrap(); + let data_port = reserve_port::ReservedPort::random().unwrap(); + let store_port = reserve_port::ReservedPort::random().unwrap(); + + let data_server_addr = SocketAddr::from(([127, 0, 0, 1], sub_port.port())); + let data_store_addr = SocketAddr::from(([127, 0, 0, 1], store_port.port())); + + let data_send = Notify::new(); + let run_data_server = data_server( + ([127, 0, 0, 1], sub_port.port()), + ([127, 0, 0, 1], data_port.port()), + ); + let run_data_store = sleep(DATA_SERVER_STARTUP).then(|()| { + data_store::server::run(data_server_addr, data_store_addr.port(), test_dir.path()) + }); + let send_sensor_value = sleep(DATA_SERVER_STARTUP + DATA_STORE_STARTUP) + .then(|()| send_sensor_values(data_port.port(), &[0.0], &data_send)); + let run_test = sleep(DATA_SERVER_STARTUP + DATA_STORE_STARTUP + FIRST_MSG_PROCESSED) + .then(|()| check_client_list_data(data_store_addr, &data_send)); + + let res = ( + run_test.map(Result::Ok), + send_sensor_value.map(Result::Ok), + run_data_store, + run_data_server.map(Result::Ok), + ) + .race() + .await; + + res.unwrap(); +} + +#[tokio::test] +async fn read_data() { + const DATA_SERVER_STARTUP: Duration = Duration::from_millis(20); + const DATA_STORE_STARTUP: Duration = Duration::from_millis(20); + const FIRST_MSG_PROCESSED: Duration = Duration::from_millis(1000); + + let test_dir = TempDir::new().unwrap(); + std::env::set_current_dir(test_dir.path()).unwrap(); + + setup_reporting(); + + let sub_port = reserve_port::ReservedPort::random().unwrap(); + let data_port = reserve_port::ReservedPort::random().unwrap(); + let store_port = reserve_port::ReservedPort::random().unwrap(); + + let data_server_addr = SocketAddr::from(([127, 0, 0, 1], sub_port.port())); + let data_store_addr = SocketAddr::from(([127, 0, 0, 1], store_port.port())); + + let data_send = Notify::new(); + let sensor_values = [0.5]; + // let sensor_values = [0.0, 0.1, 0.2, 0.3]; + let run_data_server = data_server( + ([127, 0, 0, 1], sub_port.port()), + ([127, 0, 0, 1], data_port.port()), + ); + let run_data_store = sleep(DATA_SERVER_STARTUP).then(|()| { + data_store::server::run(data_server_addr, data_store_addr.port(), test_dir.path()) + }); + let send_sensor_value = sleep(DATA_SERVER_STARTUP + DATA_STORE_STARTUP) + .then(|()| send_sensor_values(data_port.port(), &sensor_values, &data_send)); + let run_test = sleep(DATA_SERVER_STARTUP + DATA_STORE_STARTUP + FIRST_MSG_PROCESSED) + .then(|()| check_client_get_data(data_store_addr, &sensor_values, &data_send)); + + let res = ( + run_test.map(Result::Ok), + send_sensor_value.map(Result::Ok), + run_data_store, + run_data_server.map(Result::Ok), + ) + .race() + .await; + + res.unwrap(); +} From fa4ae8454d55a9833319af75060f967fad05b1cc Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 8 Aug 2024 23:50:14 +0200 Subject: [PATCH 181/687] add histogram percentiles fetching from remote server --- crates/sensor-tui/src/tui/reading.rs | 58 +++---- crates/sensor-tui/src/tui/reading/fetch.rs | 152 +----------------- .../src/tui/reading/fetch/histogram.rs | 148 +++++++++++++++++ .../src/tui/reading/fetch/history.rs | 150 +++++++++++++++++ .../src/tui/reading/fetch_timings.rs | 0 5 files changed, 331 insertions(+), 177 deletions(-) create mode 100644 crates/sensor-tui/src/tui/reading/fetch/histogram.rs create mode 100644 crates/sensor-tui/src/tui/reading/fetch/history.rs create mode 100644 crates/sensor-tui/src/tui/reading/fetch_timings.rs diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index b14a5739..d16d06b1 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -1,4 +1,3 @@ -use data_store::api::Percentile; use hdrhistogram::Histogram; use itertools::Itertools; use jiff::Unit; @@ -14,7 +13,7 @@ use std::time::{Duration, Instant}; use tui_tree_widget::TreeItem; mod fetch; -use fetch::StoredHistory; +use fetch::{histogram, history}; use crate::trace_dbg; @@ -22,9 +21,9 @@ use crate::trace_dbg; pub struct SensorInfo { pub reading: Reading, timing: Histogram, - percentiles_from_store: Vec, + pub percentiles_from_store: histogram::Stored, recent_history: Vec<(jiff::Timestamp, f32)>, - pub history_from_store: StoredHistory, + pub history_from_store: history::Stored, condition: Result<(), Box>, log: Vec<(Instant, Error)>, merged_log_from_store: bool, @@ -99,26 +98,30 @@ impl SensorInfo { } pub fn histogram(&self) -> Vec { - let percentiles = if self.percentiles_from_store.is_empty() { - self.timing - .iter_quantiles(1) - .map(|it| data_store::api::Percentile { - percentile: it.percentile(), - bucket_ends: it.value_iterated_to(), - count_in_bucket: it.count_at_value(), - }) - .dedup_by(|a, b| { - a.bucket_ends == b.bucket_ends - && a.percentile.total_cmp(&b.percentile).is_eq() - && a.count_in_bucket == b.count_in_bucket - }) - .collect_vec() + let percentiles = if self.percentiles_from_store.very_outdated() { + self.fallback_local_hist() } else { - self.percentiles_from_store.clone() + self.percentiles_from_store.data.lock().unwrap().clone() }; histogram_bars(&percentiles) } + pub fn fallback_local_hist(&self) -> Vec { + self.timing + .iter_quantiles(1) + .map(|it| log_store::api::Percentile { + percentile: it.percentile(), + bucket_ends: it.value_iterated_to(), + count_in_bucket: it.count_at_value(), + }) + .dedup_by(|a, b| { + a.bucket_ends == b.bucket_ends + && a.percentile.total_cmp(&b.percentile).is_eq() + && a.count_in_bucket == b.count_in_bucket + }) + .collect_vec() + } + pub fn chart<'a>(&mut self, plot_buf: &'a mut Vec<(f64, f64)>) -> Option> { let guard = match self.history_from_store.data.try_lock() { Ok(list) => Some(list), @@ -268,10 +271,10 @@ impl Readings { SensorInfo { reading: broken.clone(), timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), - percentiles_from_store: Vec::new(), + percentiles_from_store: histogram::Stored::new(), recent_history: Vec::new(), - history_from_store: StoredHistory::new(), + history_from_store: history::Stored::new(), condition: Err(error.clone()), log: vec![(Instant::now(), (*error).clone())], @@ -288,10 +291,9 @@ impl Readings { if let Some(info) = self.data.get_mut(&key) { if let Ok(last_reading) = info.last_at() { - info.timing += trace_dbg!((time - last_reading) + info.timing += (time - last_reading) .total(Unit::Millisecond) - .expect("no calander units involved") - as u64) + .expect("no calander units involved") as u64 } info.recent_history.push((time, val)); info.condition = Ok(()); @@ -302,10 +304,10 @@ impl Readings { SensorInfo { reading, timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), - percentiles_from_store: Vec::new(), + percentiles_from_store: histogram::Stored::new(), recent_history: history, - history_from_store: StoredHistory::new(), + history_from_store: history::Stored::new(), condition: Ok(()), log: Vec::new(), @@ -375,11 +377,11 @@ pub struct ChartParts<'a> { pub data: &'a [(f64, f64)], } -fn histogram_bars(percentiles: &[Percentile]) -> Vec> { +fn histogram_bars(percentiles: &[log_store::api::Percentile]) -> Vec> { percentiles .into_iter() .map( - |Percentile { + |log_store::api::Percentile { bucket_ends, percentile, count_in_bucket, diff --git a/crates/sensor-tui/src/tui/reading/fetch.rs b/crates/sensor-tui/src/tui/reading/fetch.rs index 8519e62e..334788be 100644 --- a/crates/sensor-tui/src/tui/reading/fetch.rs +++ b/crates/sensor-tui/src/tui/reading/fetch.rs @@ -1,14 +1,10 @@ -use protocol::Reading; - -use std::net::SocketAddr; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use std::thread; use std::time::Duration; use tokio::sync::Notify; -use tokio::time::sleep; -use tracing::{debug, warn}; -use crate::tui::history_len::{self, HistoryLen}; +pub mod histogram; +pub mod history; #[derive(Debug)] struct Fetching { @@ -16,145 +12,3 @@ struct Fetching { cancel: Arc, history_length: Duration, } - -type Data = Arc>>; - -#[derive(Debug)] -pub struct StoredHistory { - fetching: Option, - curr_hist_dur: Duration, - pub data: Data, -} - -impl StoredHistory { - pub fn new() -> Self { - Self { - fetching: None, - curr_hist_dur: Duration::ZERO, - data: Arc::new(Mutex::new(Vec::new())), - } - } - - fn start_update(&mut self, reading: Reading, new_length: Duration, data_store: SocketAddr) { - if let Some(in_progress) = self.fetching.take() { - in_progress.cancel.notify_one(); - let _ = in_progress.handle.join(); - debug!("Canceled running stored-history update"); - } - - let reading = reading.clone(); - let cancel = Arc::new(Notify::new()); - let cancelled = cancel.clone(); - let data = self.data.clone(); - let handle = - thread::spawn(move || fetch_history(data, reading, data_store, new_length, cancelled)); - self.fetching = Some(Fetching { - handle, - cancel, - history_length: new_length, - }); - } - - pub fn update_if_needed( - &mut self, - data_store: SocketAddr, - reading: Reading, - needed_hist: &mut HistoryLen, - ) { - if let Some(in_progress) = &mut self.fetching { - if in_progress.history_length != needed_hist.dur { - self.start_update(reading, needed_hist.dur, data_store); - needed_hist.state = history_len::State::Fetching; - } - } else { - if self.curr_hist_dur != needed_hist.dur { - self.start_update(reading, needed_hist.dur, data_store); - needed_hist.state = history_len::State::Fetching; - } - } - - if let Some(in_progress) = &self.fetching { - if in_progress.handle.is_finished() { - needed_hist.state = history_len::State::Fetched - } - } - } -} - -fn fetch_history( - history: Arc>>, - reading: Reading, - addr: SocketAddr, - length: Duration, - cancelled: Arc, -) { - let rt = tokio::runtime::Builder::new_current_thread() - .enable_io() - .enable_time() - .build() - .unwrap(); - - let Some(data) = rt.block_on(async { - tokio::select! { - data = connect_and_get_data(addr, length, reading) => Some(data), - _ = cancelled.notified() => None, - } - }) else { - debug!("Canceled data fetch"); - return; - }; - - debug!( - "got data from {:?} till {:?}", - data.0.first(), - data.0.last() - ); - let mut history = history.lock().unwrap(); - history.clear(); - for (t, y) in data.0.into_iter().zip(data.1) { - history.push((t, y)) - } - debug!("done fetching {length:?}!"); -} - -async fn connect_and_get_data( - addr: SocketAddr, - length: Duration, - reading: Reading, -) -> (Vec, Vec) { - let mut retry_period = Duration::ZERO; - loop { - sleep(retry_period).await; - retry_period = Duration::from_secs(5) - .min(retry_period * 2) - .min(Duration::from_millis(100)); - - let host = gethostname::gethostname(); - let host = host.to_string_lossy(); - let name = format!("sensor-tui@{host}"); - let mut api = match data_store::api::Client::connect(addr, name).await { - Ok(api) => api, - Err(e) => { - warn!("Could not connect to data_store (at {addr}): {e}"); - continue; - } - }; - - match api - .get_data( - jiff::Timestamp::now() - - jiff::Span::default().milliseconds(length.as_millis() as i64), - jiff::Timestamp::now(), - reading.clone(), - 300, - ) - .await - { - Ok(res) => return res, - Err(e) => { - warn!("Error getting data from data-store, reconnecting: {e}"); - continue; - } - }; - } -} diff --git a/crates/sensor-tui/src/tui/reading/fetch/histogram.rs b/crates/sensor-tui/src/tui/reading/fetch/histogram.rs new file mode 100644 index 00000000..d56ddd72 --- /dev/null +++ b/crates/sensor-tui/src/tui/reading/fetch/histogram.rs @@ -0,0 +1,148 @@ +use std::net::SocketAddr; +use std::sync::{Arc, Mutex}; +use std::thread; +use std::time::{Duration, Instant}; + +use log_store::api::Percentile; +use protocol::Device; +use tokio::sync::Notify; +use tokio::time::sleep; +use tracing::{debug, warn}; + +use crate::tui::history_len::{self, HistoryLen}; + +use super::Fetching; + +type Percentiles = Arc>>; + +#[derive(Debug)] +pub struct Stored { + last_fetch: Option, + last_update_started: Instant, + pub data: Percentiles, +} + +impl Stored { + pub fn new() -> Self { + Self { + last_fetch: None, + data: Arc::new(Mutex::new(Vec::new())), + // will update immediately anyway since data len is zero + last_update_started: Instant::now(), + } + } + + fn start_update(&mut self, device: Device, new_length: Duration, log_store: SocketAddr) { + if let Some(in_progress) = self.last_fetch.take() { + in_progress.cancel.notify_one(); + let _ = in_progress.handle.join(); + debug!("Canceled running stored-history update"); + } + + debug!("Started histogram fetch"); + let device = device.clone(); + let cancel = Arc::new(Notify::new()); + let cancelled = cancel.clone(); + let data = self.data.clone(); + let handle = thread::spawn(move || fetch(data, device, log_store, new_length, cancelled)); + self.last_fetch = Some(Fetching { + handle, + cancel, + history_length: new_length, + }); + self.last_update_started = Instant::now(); + } + + pub fn update_if_needed( + &mut self, + log_store: SocketAddr, + device: Device, + needed_hist: &mut HistoryLen, + ) { + if let Some(last_fetch) = &mut self.last_fetch { + if last_fetch.history_length != needed_hist.dur || self.outdated() { + self.start_update(device, needed_hist.dur, log_store); + needed_hist.state = history_len::State::Fetching; + } + } else { + self.start_update(device, needed_hist.dur, log_store); + needed_hist.state = history_len::State::Fetching; + } + + if let Some(last_fetch) = &mut self.last_fetch { + if last_fetch.handle.is_finished() { + needed_hist.state = history_len::State::Fetched + } + } + } + + pub(crate) fn outdated(&self) -> bool { + self.data.lock().unwrap().is_empty() + || self.last_update_started.elapsed() > Duration::from_secs(5) + } + + pub(crate) fn very_outdated(&self) -> bool { + self.data.lock().unwrap().is_empty() + || self.last_update_started.elapsed() > Duration::from_secs(15) + } +} + +fn fetch( + histogram: Percentiles, + device: Device, + addr: SocketAddr, + length: Duration, + cancelled: Arc, +) { + let rt = tokio::runtime::Builder::new_current_thread() + .enable_io() + .enable_time() + .build() + .unwrap(); + + let Some(data) = rt.block_on(async { + tokio::select! { + data = connect_and_get_percentiles(addr, length, device) => Some(data), + _ = cancelled.notified() => None, + } + }) else { + debug!("Canceled data fetch"); + return; + }; + + let mut histogram = histogram.lock().unwrap(); + *histogram = data +} + +async fn connect_and_get_percentiles( + addr: SocketAddr, + _: Duration, + device: Device, +) -> Vec { + let mut retry_period = Duration::ZERO; + loop { + sleep(retry_period).await; + retry_period = Duration::from_secs(5) + .min(retry_period * 2) + .min(Duration::from_millis(100)); + + let host = gethostname::gethostname(); + let host = host.to_string_lossy(); + let name = format!("sensor-tui@{host}"); + let mut api = match log_store::api::Client::connect(addr, name).await { + Ok(api) => api, + Err(e) => { + warn!("Could not connect to data_store (at {addr}): {e}"); + continue; + } + }; + + match api.get_percentiles(device.clone()).await { + Ok(res) => return res, + Err(e) => { + warn!("Error getting data from data-store, reconnecting: {e}"); + continue; + } + }; + } +} diff --git a/crates/sensor-tui/src/tui/reading/fetch/history.rs b/crates/sensor-tui/src/tui/reading/fetch/history.rs new file mode 100644 index 00000000..a3d3503f --- /dev/null +++ b/crates/sensor-tui/src/tui/reading/fetch/history.rs @@ -0,0 +1,150 @@ +use protocol::Reading; + +use std::net::SocketAddr; +use std::sync::{Arc, Mutex}; +use std::thread; +use std::time::Duration; +use tokio::sync::Notify; +use tokio::time::sleep; +use tracing::{debug, warn}; + +use crate::tui::history_len::{self, HistoryLen}; + +use super::Fetching; + +type Data = Arc>>; + +#[derive(Debug)] +pub struct Stored { + last_fetch: Option, + pub data: Data, +} + +impl Stored { + pub fn new() -> Self { + Self { + last_fetch: None, + data: Arc::new(Mutex::new(Vec::new())), + } + } + + fn start_update(&mut self, reading: Reading, new_length: Duration, data_store: SocketAddr) { + if let Some(in_progress) = self.last_fetch.take() { + in_progress.cancel.notify_one(); + let _ = in_progress.handle.join(); + debug!("Canceled running stored-history update"); + } + + let reading = reading.clone(); + let cancel = Arc::new(Notify::new()); + let cancelled = cancel.clone(); + let data = self.data.clone(); + let handle = thread::spawn(move || fetch(data, reading, data_store, new_length, cancelled)); + self.last_fetch = Some(Fetching { + handle, + cancel, + history_length: new_length, + }); + } + + pub fn update_if_needed( + &mut self, + data_store: SocketAddr, + reading: Reading, + needed_hist: &mut HistoryLen, + ) { + if let Some(last_fetch) = &mut self.last_fetch { + if last_fetch.history_length != needed_hist.dur { + self.start_update(reading, needed_hist.dur, data_store); + needed_hist.state = history_len::State::Fetching; + } + } else { + self.start_update(reading, needed_hist.dur, data_store); + needed_hist.state = history_len::State::Fetching; + } + + if let Some(last_fetch) = &self.last_fetch { + if last_fetch.handle.is_finished() { + needed_hist.state = history_len::State::Fetched + } + } + } +} + +fn fetch( + history: Arc>>, + reading: Reading, + addr: SocketAddr, + length: Duration, + cancelled: Arc, +) { + let rt = tokio::runtime::Builder::new_current_thread() + .enable_io() + .enable_time() + .build() + .unwrap(); + + let Some(data) = rt.block_on(async { + tokio::select! { + data = connect_and_get_data(addr, length, reading) => Some(data), + _ = cancelled.notified() => None, + } + }) else { + debug!("Canceled data fetch"); + return; + }; + + debug!( + "got data from {:?} till {:?}", + data.0.first(), + data.0.last() + ); + let mut history = history.lock().unwrap(); + history.clear(); + for (t, y) in data.0.into_iter().zip(data.1) { + history.push((t, y)) + } + debug!("done fetching {length:?}!"); +} + +async fn connect_and_get_data( + addr: SocketAddr, + length: Duration, + reading: Reading, +) -> (Vec, Vec) { + let mut retry_period = Duration::ZERO; + loop { + sleep(retry_period).await; + retry_period = Duration::from_secs(5) + .min(retry_period * 2) + .min(Duration::from_millis(100)); + + let host = gethostname::gethostname(); + let host = host.to_string_lossy(); + let name = format!("sensor-tui@{host}"); + let mut api = match data_store::api::Client::connect(addr, name).await { + Ok(api) => api, + Err(e) => { + warn!("Could not connect to data_store (at {addr}): {e}"); + continue; + } + }; + + match api + .get_data( + jiff::Timestamp::now() + - jiff::Span::default().milliseconds(length.as_millis() as i64), + jiff::Timestamp::now(), + reading.clone(), + 300, + ) + .await + { + Ok(res) => return res, + Err(e) => { + warn!("Error getting data from data-store, reconnecting: {e}"); + continue; + } + }; + } +} diff --git a/crates/sensor-tui/src/tui/reading/fetch_timings.rs b/crates/sensor-tui/src/tui/reading/fetch_timings.rs new file mode 100644 index 00000000..e69de29b From 26f2f7bd0e0e4e53298f5ece5b8a6b3b15da9cc8 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 10 Aug 2024 12:59:23 +0200 Subject: [PATCH 182/687] make byteseries workspace dep + better logging on handshake errs --- Cargo.toml | 3 +++ crates/data-store/Cargo.toml | 3 +-- crates/data-store/src/api.rs | 9 --------- crates/data-store/src/server/clients.rs | 12 +++++++----- crates/data-store/src/server/db/series.rs | 2 ++ 5 files changed, 13 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e07a3c52..330830d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,8 +6,11 @@ exclude = ["sensor-nodes/bed-sensors"] [workspace.dependencies] data-server = { path = "crates/data-server" } data-store = { path = "crates/data-store" } +log-store = { path = "crates/log-store" } protocol = { path = "crates/protocol" } +byteseries = { path = "../byteseries" } + tokio = "1.38" color-eyre = "0.6.3" tracing = "0.1.40" diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index c615d6f5..616f8d50 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -22,8 +22,7 @@ jiff = { workspace =true, features = ["serde"] } protocol = { workspace = true, features = ["alloc", "thiserror"] } data-server = { workspace = true } -# byteseries = { git = "https://github.com/dvdsk/byteseries", features = ["smallvec"] } -byteseries = { path = "/home/david/Documents/byteseries" } +byteseries = { workspace = true } tokio = { workspace = true, features = ["fs", "net", "rt-multi-thread", "sync"] } futures-concurrency = "7.6.1" tokio-serde = { version = "0.9.0", features = ["bincode"] } diff --git a/crates/data-store/src/api.rs b/crates/data-store/src/api.rs index aa71c64e..ab49d733 100644 --- a/crates/data-store/src/api.rs +++ b/crates/data-store/src/api.rs @@ -36,22 +36,13 @@ pub enum ServerError { TooManyRequests(Duration), } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Percentile { - pub bucket_ends: u64, - pub percentile: f64, - pub count_in_bucket: u64, -} - #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) enum Response { - GetLog(Vec<(jiff::Timestamp, protocol::Error)>), ListData(Vec), GetData { time: Vec, data: Vec, }, - GetStats(Vec), Error(ServerError), Handshake, } diff --git a/crates/data-store/src/server/clients.rs b/crates/data-store/src/server/clients.rs index f4bd72e9..00345539 100644 --- a/crates/data-store/src/server/clients.rs +++ b/crates/data-store/src/server/clients.rs @@ -45,7 +45,7 @@ pub(crate) async fn handle(port: u16, data: Data) -> color_eyre::Result<()> { continue; }; - if let Err(allowed_again) = limiter.check_key(&(source, name)) { + if let Err(allowed_again) = limiter.check_key(&(source, name.clone())) { let allowed_in = allowed_again.wait_time_from(DefaultClock::default().now()); let _ignore_err = conn.send(api::Response::Error(ServerError::TooManyRequests( allowed_in, @@ -53,6 +53,7 @@ pub(crate) async fn handle(port: u16, data: Data) -> color_eyre::Result<()> { continue; } + info!("Client {name} connected from {source}"); let Ok(()) = conn.send(api::Response::Handshake).await else { continue; }; @@ -73,12 +74,13 @@ async fn handshake_and_log(stream: TcpStream, source: SocketAddr) -> Option<(Con match stream.try_next().await { Ok(Some(api::Request::Handshake { name })) => { - info!("Client {name} connected from {source}"); return Some((stream, name)); } - Ok(Some(other)) => warn!("client tried to connected without handshake, it send: {other:?}"), - Ok(None) => warn!("client closed connection immediately"), - Err(e) => warn!("connection or decoding issue while receiving handshake: {e:?}"), + Ok(Some(other)) => { + warn!("client from {source} tried to connected without handshake, it send: {other:?}") + } + Ok(None) => warn!("client from {source} closed connection immediately"), + Err(e) => warn!("connection or decoding issue while receiving handshake from {source}, error: {e:?}"), } None diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index 61c8db5a..c6f643d1 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -42,6 +42,7 @@ struct Header { } impl Series { + #[instrument] fn open_or_create(reading: &protocol::Reading, dir: &Path) -> Result { let readings = reading.device().info().affects_readings; let specs = to_speclist(readings); @@ -107,6 +108,7 @@ impl Series { }) } + #[instrument] fn append(&mut self, reading: &protocol::Reading) -> Result<()> { let index = reading .device() From a08b5ac04c83938e37c38a25d0c3876c23fb3635 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 10 Aug 2024 13:00:20 +0200 Subject: [PATCH 183/687] log store now saves logs to disk --- crates/log-store/Cargo.toml | 3 + crates/log-store/deploy.sh | 2 +- crates/log-store/src/api.rs | 35 ++- crates/log-store/src/api/client.rs | 70 +++++- crates/log-store/src/server/db.rs | 10 +- crates/log-store/src/server/db/log.rs | 290 ++++++++++++++++++++++-- crates/log-store/src/server/db/stats.rs | 11 +- crates/log-store/tests/list_data.rs | 97 ++++---- crates/protocol/src/lib.rs | 7 + 9 files changed, 429 insertions(+), 96 deletions(-) diff --git a/crates/log-store/Cargo.toml b/crates/log-store/Cargo.toml index 8dc86cbd..f0088ca5 100644 --- a/crates/log-store/Cargo.toml +++ b/crates/log-store/Cargo.toml @@ -21,12 +21,14 @@ jiff = { workspace =true, features = ["serde"] } protocol = { workspace = true, features = ["alloc", "thiserror"] } data-server = { workspace = true } +byteseries = { workspace = true } tokio = { workspace = true, features = ["fs", "net", "rt-multi-thread", "sync"] } futures-concurrency = "7.6.1" tokio-serde = { version = "0.9.0", features = ["bincode"] } tokio-util = { version = "0.7.11", features = ["codec"] } serde = { version = "1.0.203", features = ["derive"] } +bincode = "1.3.3" thiserror = { workspace = true } futures = "0.3.30" smallvec = "2.0.0-alpha.6" @@ -36,6 +38,7 @@ governor = "0.6.3" [dev-dependencies] futures-concurrency = "7.6.1" +heapless = "0.8.0" nucleo-matcher = "0.3.1" reserve-port = "2.0.1" temp-dir = "0.1.13" diff --git a/crates/log-store/deploy.sh b/crates/log-store/deploy.sh index b9d23e54..86304111 100755 --- a/crates/log-store/deploy.sh +++ b/crates/log-store/deploy.sh @@ -3,7 +3,7 @@ set -e BUILD_ARG=--release SERVER="sgc" # ssh config name or full address -NAME=data-store +NAME=log-store cargo build --target=aarch64-unknown-linux-musl $BUILD_ARG rsync -vh --progress \ diff --git a/crates/log-store/src/api.rs b/crates/log-store/src/api.rs index 8f790030..0621b984 100644 --- a/crates/log-store/src/api.rs +++ b/crates/log-store/src/api.rs @@ -12,25 +12,35 @@ pub(crate) const MAX_PACKAGE_SIZE: usize = 8 * 1024 * 1024; #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) enum Request { - Handshake { - name: String, - }, + Handshake { name: String }, GetLog(protocol::Device), GetStats(protocol::Device), } #[derive(Debug, Clone, Serialize, Deserialize, thiserror::Error)] pub enum ServerError { - #[error("We do not have any data for this reading: {reading:?}")] - NotInStore { reading: Reading }, - #[error("Internal error while reading data, error: {0}")] - ReadingFromStore(String), #[error("Connect request should only be send once")] AlreadyConnected, #[error("Too many requests, rate limited, next requested allowed in: {0:?}")] TooManyRequests(Duration), } +#[derive(Debug, Clone, Serialize, Deserialize, thiserror::Error)] +pub enum GetStatsError { + #[error("We do not have any data for this reading: {reading:?}")] + NotInStore { reading: Reading }, + #[error("Internal error while reading data, error: {0}")] + InternalError(String), +} + +#[derive(Debug, Clone, Serialize, Deserialize, thiserror::Error)] +pub enum GetLogError { + #[error("Too many error events ({found}) between requested timepoints, max is: {max}")] + TooMuchData { max: i32, found: u64 }, + #[error("Internal error while reading data, error: {0}")] + InternalError(String), +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Percentile { pub bucket_ends: u64, @@ -38,10 +48,17 @@ pub struct Percentile { pub count_in_bucket: u64, } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ErrorEvent { + pub start: jiff::Timestamp, + pub end: jiff::Timestamp, + pub error: protocol::Error, +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) enum Response { - GetLog(Vec<(jiff::Timestamp, protocol::Error)>), - GetStats(Vec), + GetLog(Result, GetLogError>), + GetStats(Result, GetStatsError>), Error(ServerError), Handshake, } diff --git a/crates/log-store/src/api/client.rs b/crates/log-store/src/api/client.rs index 6d774409..7db15d0c 100644 --- a/crates/log-store/src/api/client.rs +++ b/crates/log-store/src/api/client.rs @@ -3,11 +3,20 @@ use std::time::Duration; use futures::{SinkExt, TryStreamExt}; use tokio::net::TcpStream; use tokio::net::ToSocketAddrs; +use tokio::time::error::Elapsed; +use tokio::time::timeout_at; +use tokio::time::Instant; use tokio_serde::formats::Bincode; use tokio_util::codec::{Framed, LengthDelimitedCodec}; +use crate::api::Percentile; + +use super::ErrorEvent; +use super::GetLogError; +use super::GetStatsError; use super::Request; use super::Response; +use super::ServerError; pub struct Client { stream: tokio_serde::Framed< @@ -35,15 +44,17 @@ pub enum ConnectError { } #[derive(Debug, thiserror::Error)] -pub enum Error { +pub enum Error { #[error("Got unexpected response response to request {request:?}")] IncorrectResponse { request: String, response: String }, #[error("Error while sending request: {0}")] Sending(std::io::Error), #[error("Error while sending request: {0}")] Receiving(std::io::Error), - #[error("Server ran into an error while processing our request: {0}")] - Server(super::ServerError), + #[error("General error while processing request")] + Server(ServerError), + #[error("Server ran into an specific error with our request: {0}")] + Request(#[from] T), #[error("Server closed connection before it awnserd")] ConnectionClosed, } @@ -78,12 +89,59 @@ impl Client { } } - async fn send_receive(&mut self, request: super::Request) -> Result { - self.stream.send(request).await.map_err(Error::Sending)?; - match self.stream.try_next().await.map_err(Error::Receiving)? { + async fn send_receive( + &mut self, + request: super::Request, + ) -> Result> { + fn send_timeout_err(_: Elapsed) -> Error { + Error::Sending(std::io::Error::new(std::io::ErrorKind::TimedOut, "")) + } + fn receive_timeout_err(_: Elapsed) -> Error { + Error::Receiving(std::io::Error::new(std::io::ErrorKind::TimedOut, "")) + } + + let deadline = Instant::now() + Duration::from_secs(5); + timeout_at(deadline, self.stream.send(request)) + .await + .map_err(send_timeout_err)? + .map_err(Error::Sending)?; + match timeout_at(deadline, self.stream.try_next()) + .await + .map_err(receive_timeout_err)? + .map_err(Error::Receiving)? + { Some(Response::Error(e)) => Err(Error::Server(e)), Some(response) => Ok(response), None => Err(Error::ConnectionClosed), } } + + pub async fn get_percentiles( + &mut self, + device: protocol::Device, + ) -> Result, Error> { + let request = super::Request::GetStats(device); + match self.send_receive(request.clone()).await { + Ok(Response::GetStats(percentiles)) => Ok(percentiles?), + Err(err) => Err(err), + response => Err(Error::IncorrectResponse { + request: format!("{request:?}"), + response: format!("{response:?}"), + }), + } + } + + pub async fn get_logs( + &mut self, + device: protocol::Device, + ) -> Result, Error> { + let request = super::Request::GetLog(device); + match self.send_receive(request.clone()).await? { + Response::GetLog(logs) => Ok(logs?), + response => Err(Error::IncorrectResponse { + request: format!("{request:?}"), + response: format!("{response:?}"), + }), + } + } } diff --git a/crates/log-store/src/server/db.rs b/crates/log-store/src/server/db.rs index 8a15cbbc..74e4bb29 100644 --- a/crates/log-store/src/server/db.rs +++ b/crates/log-store/src/server/db.rs @@ -25,8 +25,14 @@ pub(crate) async fn run( loop { let msg = sub.next_msg().await; let res = match msg { - SubMessage::Reading(reading) => stats.increment(reading.device()).await, - SubMessage::ErrorReport(report) => logs.store(*report).await, + SubMessage::Reading(reading) => { + if let Err(e) = stats.increment(reading.device()).await { + Err(e) + } else { + logs.clear_err(reading.device()).await + } + } + SubMessage::ErrorReport(report) => logs.set_err(*report, log_dir).await, }; const FIVE_MIN: Duration = Duration::from_secs(60 * 5); diff --git a/crates/log-store/src/server/db/log.rs b/crates/log-store/src/server/db/log.rs index c897d2c6..3fb43999 100644 --- a/crates/log-store/src/server/db/log.rs +++ b/crates/log-store/src/server/db/log.rs @@ -1,23 +1,233 @@ -use std::collections::{HashMap, VecDeque}; +use std::collections::HashMap; +use std::io::{self, Read, Write}; +use std::path::{Path, PathBuf}; use std::sync::Arc; -use color_eyre::Result; +use byteseries::{series, ByteSeries}; +use color_eyre::eyre::Context; +use color_eyre::{eyre, Result, Section}; +use protocol::Device; +use serde::{Deserialize, Serialize}; use tokio::sync::Mutex; +use tracing::{info, warn}; + +use crate::api::{self, ErrorEvent}; + +#[derive(Debug)] +pub(crate) struct Log { + history: ByteSeries, + current: CurrentError, +} #[derive(Debug)] -pub(crate) struct Log(VecDeque<(jiff::Timestamp, protocol::Error)>); +struct CurrentError { + file: std::fs::File, + value: Option<(jiff::Timestamp, protocol::Error)>, +} + +impl CurrentError { + fn open_or_create(path: &Path) -> Result { + let path = path.with_extension("current_error"); + let mut file = std::fs::OpenOptions::new() + .read(true) + .write(true) + .create(true) + .open(path) + .wrap_err("Could not open or create on disk backup")?; + let mut buf = Vec::new(); + file.read_to_end(&mut buf) + .wrap_err("Failed to read from on disk backup")?; + + let value = if buf.is_empty() { + None + } else { + match bincode::deserialize(&buf) { + Ok(value) => Some(value), + Err(err) => { + warn!( + "On disk backup failed to deserialize setting to None, \ + error was: {err}" + ); + file.set_len(0).wrap_err( + "Could not set on disk backup to value None after \ + failing deserialize", + )?; + None + } + } + }; + + Ok(Self { file, value }) + } + + fn take(&mut self) -> Result> { + self.file + .set_len(0) + .wrap_err("Could not set on disk backup of current error to None")?; + Ok(self.value.take()) + } + + fn set(&mut self, report: protocol::Error) -> Result<()> { + let value = (jiff::Timestamp::now(), report); + let bytes = bincode::serialize(&value).wrap_err("could not serialize current error")?; + self.file + .write_all(&bytes) + .wrap_err("could not backup current error to disk")?; + Ok(()) + } +} + +type Header = String; impl Log { - pub fn new(first_report: protocol::Error) -> Self { - let mut this = Self(VecDeque::new()); - this.push(first_report); - this + pub fn open_or_create(dir: &Path, device: &Device) -> Result { + let path = base_path(device); + let path = dir.join(path); + + let payload_size = protocol::Error::max_size(); + let res = ByteSeries::open_existing::(&path, payload_size); + + let expected_header = format!( + "Bincode encoded error logs for {device:?}. \ + Each line has a size: {payload_size} + 2" + ); + let history = try_create_new_if_open_failed(res, expected_header, &path, payload_size)?; + + Ok(Self { + history, + current: CurrentError::open_or_create(&path) + .wrap_err("Could not setup current error store")?, + }) } - pub fn push(&mut self, report: protocol::Error) { - const MAX_LENGTH: usize = 100; - self.0.truncate(MAX_LENGTH - 1); - self.0.push_front((jiff::Timestamp::now(), report)) + pub fn set_err(&mut self, new_report: protocol::Error) -> Result<()> { + if let Some((started, report)) = self + .current + .take() + .wrap_err("failed to take value out of current error store")? + { + if report == new_report { + return Ok(()); + } + let line = StoredErrorEvent { + end: jiff::Timestamp::now(), + error: report, + }; + let line = bincode::serialize(&line).wrap_err("Could not serialize ErrorEvent")?; + self.history + .push_line(started.as_second() as u64, line) + .wrap_err("Could not push new ErrorEvent into history")?; + } + + self.current + .set(new_report) + .wrap_err("Failed to set new error in current error store") + } + + fn clear(&mut self) -> Result<()> { + self.current + .take() + .wrap_err("failed to set value of current error to None")?; + Ok(()) + } + + fn get_all(&mut self) -> Result>> { + let mut timestamps = Vec::new(); + let mut data = Vec::new(); + let n_lines = self.history.n_lines_between(..).wrap_err( + "Could not check if there is not too much data \ + between the requested points", + )?; + if n_lines > 200 { + return Ok(Err(api::GetLogError::TooMuchData { + max: 200, + found: n_lines, + })); + } + self.history + .read_all(.., &mut Decoder, &mut timestamps, &mut data) + .wrap_err("Could not read log events form disk")?; + + let res = timestamps + .into_iter() + .zip(data) + .map(|(start, StoredErrorEvent { end, error })| api::ErrorEvent { + start: jiff::Timestamp::from_second(start as i64) + .expect("was a jiff::Timestamp before it became a u64"), + end, + error, + }) + .collect(); + Ok(Ok(res)) + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +struct StoredErrorEvent { + end: jiff::Timestamp, + error: protocol::Error, +} + +#[derive(Debug)] +struct Decoder; +impl byteseries::Decoder for Decoder { + type Item = StoredErrorEvent; + + fn decode_payload(&mut self, payload: &[u8]) -> Self::Item { + bincode::deserialize(payload).expect("if its successfully serialized it should deserialize") + } +} + +type ApiResult = std::result::Result; + +fn try_create_new_if_open_failed( + res: Result<(ByteSeries, Header), series::Error>, + expected_header: Header, + path: &Path, + payload_size: usize, +) -> Result { + use byteseries::file::OpenError as FileOpenError; + use series::data::OpenError as DataOpenError; + use series::Error::Open; + + match res { + Ok((byteseries, opened_file_header)) => { + if opened_file_header == expected_header { + info!("Opened existing byteseries from: {}", path.display()); + Ok(byteseries) + } else { + Err(eyre::eyre!("header in file does not match readings")) + .with_note(|| { + format!( + "header in the just existing (opened) byteseries: {opened_file_header:?}", + ) + }) + .with_note(|| { + format!( + "header for the data we want to write: {expected_header:?}", + ) + }) + } + } + Err(Open(DataOpenError::File(FileOpenError::Io(e)))) + if e.kind() == io::ErrorKind::NotFound => + { + if let Some(dirs) = path.parent() { + std::fs::create_dir_all(dirs) + .wrap_err("Could not create dirs structure for reading") + .with_note(|| format!("dirs: {}", dirs.display()))?; + std::fs::read_dir(dirs) + .unwrap() + .map(Result::unwrap) + .for_each(|p| println!("{p:?}")); + } + // compile_error!("create directory structure"); + info!("creating new byteseries"); + ByteSeries::new(&path, payload_size, expected_header) + .wrap_err("Could not create new byteseries") + .with_note(|| format!("path: {}", path.display())) + } + Err(e) => Err(e).wrap_err("Could not open existing byteseries")?, } } @@ -25,25 +235,63 @@ impl Log { pub(crate) struct Logs(pub(crate) Arc>>); impl Logs { - pub async fn store(&self, report: protocol::Error) -> Result<()> { + pub async fn set_err(&self, report: protocol::Error, log_dir: &Path) -> Result<()> { + let device = report.device(); let mut map = self.0.lock().await; - if let Some(log) = map.get_mut(&report.device()) { - log.push(report); + if let Some(log) = map.get_mut(&device) { + log.set_err(report)?; } else { - map.insert(report.device(), Log::new(report)); + let mut log = Log::open_or_create(log_dir, &device) + .wrap_err("Failed to open or create error Log")?; + log.set_err(report)?; + map.insert(device, log); } Ok(()) } - pub async fn get(&self, device: &protocol::Device) -> Vec<(jiff::Timestamp, protocol::Error)> { + pub async fn get(&self, device: &protocol::Device) -> ApiResult> { let mut map = self.0.lock().await; if let Some(log) = map.get_mut(device) { - let (logs, more_logs) = log.0.as_slices(); - let mut logs = logs.to_vec(); - logs.extend_from_slice(more_logs); - logs + match log.get_all() { + Err(report) => Err(api::GetLogError::InternalError(report.to_string())), + Ok(res) => res, + } } else { - Vec::new() + Ok(Vec::new()) + } + } + + pub(crate) async fn clear_err(&self, device: protocol::Device) -> Result<()> { + let mut map = self.0.lock().await; + if let Some(log) = map.get_mut(&device) { + log.clear()?; + } + Ok(()) + } +} + +/// relative path without extension +fn base_path(device: &protocol::Device) -> PathBuf { + use protocol::reading_tree::{Item, ReadingInfo, Tree}; + + let mut parts = Vec::new(); + let mut current = device + .info() + .affects_readings + .first() + .expect("a device has at least one reading it affects") as &dyn Tree; + loop { + match current.inner() { + Item::Leaf(ReadingInfo { device, .. }) => { + parts.push(device.info().name.to_lowercase()); + break; + } + Item::Node(inner) => { + parts.push(current.name().to_lowercase()); + current = inner; + continue; + } } } + parts.into_iter().collect() } diff --git a/crates/log-store/src/server/db/stats.rs b/crates/log-store/src/server/db/stats.rs index 75baf1c3..6f20db3d 100644 --- a/crates/log-store/src/server/db/stats.rs +++ b/crates/log-store/src/server/db/stats.rs @@ -6,7 +6,7 @@ use std::time::Instant; use tokio::sync::Mutex; -use crate::api::Percentile; +use crate::api::{self, Percentile}; #[derive(Debug)] pub(crate) struct Histogram { @@ -46,9 +46,12 @@ impl Stats { Ok(()) } - pub(crate) async fn get(&self, device: &protocol::Device) -> Vec { + pub(crate) async fn get( + &self, + device: &protocol::Device, + ) -> Result, api::GetStatsError> { let mut map = self.0.lock().await; - if let Some(timings) = map.get_mut(device) { + Ok(if let Some(timings) = map.get_mut(device) { timings .histogram .iter_quantiles(1) @@ -60,6 +63,6 @@ impl Stats { .collect() } else { Vec::new() - } + }) } } diff --git a/crates/log-store/tests/list_data.rs b/crates/log-store/tests/list_data.rs index 76447d8f..059074ac 100644 --- a/crates/log-store/tests/list_data.rs +++ b/crates/log-store/tests/list_data.rs @@ -1,4 +1,5 @@ use std::net::SocketAddr; +use std::str::FromStr; use std::sync::Once; use std::time::Duration; @@ -22,6 +23,14 @@ const fn test_readings(v: f32) -> [Reading; 2] { ] } +fn test_error() -> protocol::Error { + protocol::Error::LargeBedroom(large_bedroom::Error::Bed(bed::Error::Setup( + bed::SensorError::Sht31( + heapless::String::from_str("log server integration test error").unwrap(), + ), + ))) +} + async fn data_server(sub_port: impl Into, data_port: impl Into) { use data_server::server; @@ -33,11 +42,11 @@ async fn data_server(sub_port: impl Into, data_port: impl Into::default(); - for val in test_readings(*v) { + for val in test_readings(v) { sensor_msg.values.push(val).unwrap(); } let encoded = protocol::Msg::Readings(sensor_msg).encode(); @@ -48,63 +57,47 @@ async fn send_sensor_values(data_port: u16, values: &[f32], data_send: &Notify) sleep(Duration::from_secs(999)).await; } -async fn check_client_list_data(data_store_addr: SocketAddr, data_send: &Notify) { +async fn send_sensor_errors(data_port: u16, data_send: &Notify) { + let mut conn = TcpStream::connect(("127.0.0.1", data_port)).await.unwrap(); + for _ in [1, 2, 3, 4] { + let report = protocol::ErrorReport::new(test_error()); + let encoded = protocol::Msg::<50>::ErrorReport(report).encode(); + conn.write_all(&encoded).await.unwrap(); + sleep(Duration::from_secs_f32(1.1)).await; + } + data_send.notify_waiters(); + sleep(Duration::from_secs(999)).await; +} + +async fn check_client_get_percentiles(data_store_addr: SocketAddr, data_send: &Notify) { data_send.notified().await; sleep(Duration::from_secs_f32(0.1)).await; let mut client = - data_store::api::Client::connect(data_store_addr, "data_store_example".to_owned()) + log_store::api::Client::connect(data_store_addr, "data_store_example".to_owned()) .await .unwrap(); - let list = client.list_data().await.unwrap(); + let test_device = test_readings(0.0).first().unwrap().device(); + let list = client.get_percentiles(test_device).await.unwrap(); assert!( !list.is_empty(), "list is empty, should contain one reading" ); - assert!( - list.iter().any(|r| { - if let protocol::Reading::LargeBedroom(protocol::large_bedroom::Reading::Bed( - protocol::large_bedroom::bed::Reading::Temperature(_), - )) = r - { - true - } else { - false - } - }), - "list is missing expected reading bed::Reading::Temperature. \ - Full list is: {list:?}" - ) } -async fn check_client_get_data( - data_store_addr: SocketAddr, - sensor_values: &[f32], - data_send: &Notify, -) { +async fn check_client_get_logs(data_store_addr: SocketAddr, data_send: &Notify) { data_send.notified().await; sleep(Duration::from_secs_f32(0.1)).await; let mut client = - data_store::api::Client::connect(data_store_addr, "data_store_example".to_owned()) + log_store::api::Client::connect(data_store_addr, "data_store_example".to_owned()) .await .unwrap(); - let (time, data) = client - .get_data( - jiff::Timestamp::now() - jiff::Span::default().seconds(30), - jiff::Timestamp::now() + jiff::Span::default().seconds(30), - test_readings(0.0)[0].clone(), - 5, - ) - .await - .unwrap(); - - assert_eq!(time.len(), data.len()); - assert!(data - .into_iter() - .zip(sensor_values.into_iter().copied()) - .inspect(|r| println!("(got, expected): {r:?}")) - .all(|(a, b)| (a - b).abs() < 0.1)) + + let test_device = test_readings(0.0).first().unwrap().device(); + let logs = client.get_logs(test_device).await.unwrap(); + + assert_eq!(logs.len(), 4); } static SETUP_REPORTING: Once = Once::new(); @@ -120,7 +113,7 @@ fn setup_reporting() { } #[tokio::test] -async fn list_data() { +async fn get_logs() { const DATA_SERVER_STARTUP: Duration = Duration::from_millis(20); const DATA_STORE_STARTUP: Duration = Duration::from_millis(20); const FIRST_MSG_PROCESSED: Duration = Duration::from_millis(1000); @@ -136,18 +129,18 @@ async fn list_data() { let data_server_addr = SocketAddr::from(([127, 0, 0, 1], sub_port.port())); let data_store_addr = SocketAddr::from(([127, 0, 0, 1], store_port.port())); - let data_send = Notify::new(); + let errors_send = Notify::new(); let run_data_server = data_server( ([127, 0, 0, 1], sub_port.port()), ([127, 0, 0, 1], data_port.port()), ); let run_data_store = sleep(DATA_SERVER_STARTUP).then(|()| { - data_store::server::run(data_server_addr, data_store_addr.port(), test_dir.path()) + log_store::server::run(data_server_addr, data_store_addr.port(), test_dir.path()) }); let send_sensor_value = sleep(DATA_SERVER_STARTUP + DATA_STORE_STARTUP) - .then(|()| send_sensor_values(data_port.port(), &[0.0], &data_send)); + .then(|()| send_sensor_errors(data_port.port(), &errors_send)); let run_test = sleep(DATA_SERVER_STARTUP + DATA_STORE_STARTUP + FIRST_MSG_PROCESSED) - .then(|()| check_client_list_data(data_store_addr, &data_send)); + .then(|()| check_client_get_logs(data_store_addr, &errors_send)); let res = ( run_test.map(Result::Ok), @@ -162,7 +155,7 @@ async fn list_data() { } #[tokio::test] -async fn read_data() { +async fn get_percentiles() { const DATA_SERVER_STARTUP: Duration = Duration::from_millis(20); const DATA_STORE_STARTUP: Duration = Duration::from_millis(20); const FIRST_MSG_PROCESSED: Duration = Duration::from_millis(1000); @@ -180,19 +173,17 @@ async fn read_data() { let data_store_addr = SocketAddr::from(([127, 0, 0, 1], store_port.port())); let data_send = Notify::new(); - let sensor_values = [0.5]; - // let sensor_values = [0.0, 0.1, 0.2, 0.3]; let run_data_server = data_server( ([127, 0, 0, 1], sub_port.port()), ([127, 0, 0, 1], data_port.port()), ); let run_data_store = sleep(DATA_SERVER_STARTUP).then(|()| { - data_store::server::run(data_server_addr, data_store_addr.port(), test_dir.path()) + log_store::server::run(data_server_addr, data_store_addr.port(), test_dir.path()) }); let send_sensor_value = sleep(DATA_SERVER_STARTUP + DATA_STORE_STARTUP) - .then(|()| send_sensor_values(data_port.port(), &sensor_values, &data_send)); + .then(|()| send_sensor_values(data_port.port(), &data_send)); let run_test = sleep(DATA_SERVER_STARTUP + DATA_STORE_STARTUP + FIRST_MSG_PROCESSED) - .then(|()| check_client_get_data(data_store_addr, &sensor_values, &data_send)); + .then(|()| check_client_get_percentiles(data_store_addr, &data_send)); let res = ( run_test.map(Result::Ok), diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 95f34a38..d05122c5 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -108,6 +108,8 @@ reading_tree::all_nodes! {Reading; ReadingDiscriminants; LargeBedroom, SmallBedr Serialize, Deserialize, MaxSize, + PartialEq, + Eq, )] pub enum Error { LargeBedroom(large_bedroom::Error), @@ -120,6 +122,11 @@ impl Error { Error::LargeBedroom(error) => Device::LargeBedroom(error.device()), } } + + #[must_use] + pub const fn max_size() -> usize { + Self::POSTCARD_MAX_SIZE + } } impl Display for Error { From bdf9dd8d2faeb7229770acefa3a9bb8f0374dbf0 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 10 Aug 2024 13:01:23 +0200 Subject: [PATCH 184/687] sensor tui uses new log store api --- crates/sensor-tui/Cargo.toml | 5 +- crates/sensor-tui/src/main.rs | 7 +- crates/sensor-tui/src/tui.rs | 16 ++- crates/sensor-tui/src/tui/reading.rs | 63 ++++----- crates/sensor-tui/src/tui/reading/fetch.rs | 1 + .../sensor-tui/src/tui/reading/fetch/logs.rs | 133 ++++++++++++++++++ crates/sensor-tui/src/tui/reading/logs2.rs | 53 +++++++ crates/sensor-tui/src/tui/render.rs | 4 +- 8 files changed, 239 insertions(+), 43 deletions(-) create mode 100644 crates/sensor-tui/src/tui/reading/fetch/logs.rs create mode 100644 crates/sensor-tui/src/tui/reading/logs2.rs diff --git a/crates/sensor-tui/Cargo.toml b/crates/sensor-tui/Cargo.toml index 8212e296..73b00707 100644 --- a/crates/sensor-tui/Cargo.toml +++ b/crates/sensor-tui/Cargo.toml @@ -15,13 +15,14 @@ tui-tree-widget = { version = "0.21.0", git = "https://github.com/dvdsk/tui-rs-t clap = { workspace = true } tokio = { workspace = true} -tracing = {workspace = true} +tracing.workspace = true tracing-error = { workspace = true } -tracing-subscriber = { workspace =true, features = ["env-filter"] } +tracing-subscriber.workspace = true protocol = { workspace = true, features = ["alloc"] } data-server = { workspace = true } data-store = { workspace = true } +log-store = { workspace = true, features = ["api"] } jiff = { workspace = true } thiserror.workspace = true itertools = "0.13.0" diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index d968d42f..d7a8ed76 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -49,6 +49,10 @@ struct Cli { /// server where we can fetch historical sensor data #[arg(short='s', long, default_value_t = SocketAddr::from(([192,168,1,43], 1236)))] data_store: SocketAddr, + + /// server where we can fetch logs and timing information + #[arg(short, long, default_value_t = SocketAddr::from(([192,168,1,43], 1237)))] + log_store: SocketAddr, } fn main() -> Result<()> { @@ -57,6 +61,7 @@ fn main() -> Result<()> { let Cli { data_server, data_store, + log_store, } = Cli::parse(); let sub = data_server::Subscriber::connect(data_server, "ha-tui") @@ -68,7 +73,7 @@ fn main() -> Result<()> { let tx1_clone = tx1.clone(); thread::spawn(move || receive_data(sub, tx1_clone)); - thread::spawn(move || tui::run(rx2, tx1, data_store)); + thread::spawn(move || tui::run(rx2, tx1, data_store, log_store)); loop { let update = rx1.recv()??; diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index 7febb63d..80ce6323 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -55,8 +55,9 @@ pub fn run( rx: mpsc::Receiver, shutdown_tx: mpsc::Sender>, data_store: SocketAddr, + log_store: SocketAddr, ) -> Result<(), std::io::Error> { - App::default().run(rx, shutdown_tx, data_store) + App::default().run(rx, shutdown_tx, data_store, log_store) } #[derive(Default)] @@ -75,6 +76,7 @@ impl App { rx: mpsc::Receiver, shutdown_tx: mpsc::Sender>, data_store: SocketAddr, + log_store: SocketAddr, ) -> Result<(), std::io::Error> { let mut readings = Readings { ground: Vec::new(), @@ -98,11 +100,21 @@ impl App { let plot_open = data.is_some(); let (chart, histogram, details) = if let Some(data) = data { + data.logs_from_store.update_if_needed( + data_store, + data.reading.clone(), + &mut self.history_length, + ); data.history_from_store.update_if_needed( data_store, data.reading.clone(), &mut self.history_length, ); + data.percentiles_from_store.update_if_needed( + log_store, + data.reading.device(), + &mut self.history_length, + ); ( data.chart(&mut plot_buf), data.histogram(), @@ -187,7 +199,7 @@ impl App { fn handle_key_bounds_mode(&mut self, key: KeyEvent) -> ShouldExit { match key.code { - KeyCode::Esc => { + KeyCode::Char('q') | KeyCode::Esc => { self.history_length.exit_editing(); self.input_mode = InputMode::Normal; } diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index d16d06b1..2176cf22 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -9,13 +9,12 @@ use protocol::Reading; use ratatui::{text::Line, widgets::Bar}; use std::collections::HashMap; use std::sync::TryLockError; -use std::time::{Duration, Instant}; use tui_tree_widget::TreeItem; mod fetch; -use fetch::{histogram, history}; +use fetch::{histogram, history, logs}; -use crate::trace_dbg; +mod logs2; #[derive(Debug)] pub struct SensorInfo { @@ -25,38 +24,29 @@ pub struct SensorInfo { recent_history: Vec<(jiff::Timestamp, f32)>, pub history_from_store: history::Stored, condition: Result<(), Box>, - log: Vec<(Instant, Error)>, - merged_log_from_store: bool, + errors: logs2::Logs, + pub logs_from_store: logs::Stored, } -pub struct NumErrorSince { - pub t5_min: usize, - pub t15_min: usize, - pub t30_min: usize, - pub t45_min: usize, - pub t60_min: usize, +pub struct ErrorDensity { + pub t5_min: f32, + pub t15_min: f32, + pub t30_min: f32, + pub t45_min: f32, + pub t60_min: f32, } -impl NumErrorSince { - fn from_log(log: &[(Instant, Error)]) -> Self { - let mut buckets = [5, 15, 30, 45, 60] - .map(|min| Duration::from_secs(60 * min)) - .map(|bound| (bound, 0)); - - for (occurred, _) in log.iter().rev() { - for (bound, count) in &mut buckets { - if occurred.elapsed() < *bound { - *count += 1; - } - } - } +impl ErrorDensity { + fn from_log(log: &logs2::Logs) -> Self { + let buckets = [5, 15, 30, 45, 60].map(|min| jiff::Span::new().minutes(min)); + let counts = log.density(buckets); Self { - t5_min: buckets[0].1, - t15_min: buckets[1].1, - t30_min: buckets[2].1, - t45_min: buckets[3].1, - t60_min: buckets[4].1, + t5_min: counts[0], + t15_min: counts[1], + t30_min: counts[2], + t45_min: counts[3], + t60_min: counts[4], } } } @@ -65,7 +55,7 @@ pub struct Details { pub last_reading: Option<(jiff::Timestamp, String)>, pub condition: Result<(), Box>, pub description: String, - pub errors_since: NumErrorSince, + pub errors_since: ErrorDensity, } impl SensorInfo { @@ -93,7 +83,7 @@ impl SensorInfo { last_reading, condition: self.condition.clone(), description: self.reading.leaf().description.to_owned(), - errors_since: NumErrorSince::from_log(&self.log), + errors_since: ErrorDensity::from_log(&self.errors), } } @@ -264,8 +254,9 @@ impl Readings { if let Some(info) = self.data.get_mut(&key) { info.condition = Err(error.clone()); - info.log.push((Instant::now(), (*error).clone())); + info.errors.add(&error); } else { + let errors = logs2::Logs::new_from(&error); self.data.insert( key, SensorInfo { @@ -275,10 +266,10 @@ impl Readings { recent_history: Vec::new(), history_from_store: history::Stored::new(), + logs_from_store: fetch::logs::Stored::new(), condition: Err(error.clone()), - log: vec![(Instant::now(), (*error).clone())], - merged_log_from_store: false, + errors, }, ); } @@ -308,10 +299,10 @@ impl Readings { recent_history: history, history_from_store: history::Stored::new(), + logs_from_store: fetch::logs::Stored::new(), condition: Ok(()), - log: Vec::new(), - merged_log_from_store: false, + errors: logs2::Logs::new_empty(), }, ); } diff --git a/crates/sensor-tui/src/tui/reading/fetch.rs b/crates/sensor-tui/src/tui/reading/fetch.rs index 334788be..f4225037 100644 --- a/crates/sensor-tui/src/tui/reading/fetch.rs +++ b/crates/sensor-tui/src/tui/reading/fetch.rs @@ -5,6 +5,7 @@ use tokio::sync::Notify; pub mod histogram; pub mod history; +pub mod logs; #[derive(Debug)] struct Fetching { diff --git a/crates/sensor-tui/src/tui/reading/fetch/logs.rs b/crates/sensor-tui/src/tui/reading/fetch/logs.rs new file mode 100644 index 00000000..57bbe5d8 --- /dev/null +++ b/crates/sensor-tui/src/tui/reading/fetch/logs.rs @@ -0,0 +1,133 @@ +use log_store::api::ErrorEvent; +use protocol::Reading; + +use std::net::SocketAddr; +use std::sync::{Arc, Mutex}; +use std::thread; +use std::time::Duration; +use tokio::sync::Notify; +use tokio::time::sleep; +use tracing::{debug, warn}; + +use crate::tui::history_len::{self, HistoryLen}; + +use super::Fetching; + +type Data = Arc>>; + +#[derive(Debug)] +pub struct Stored { + last_fetch: Option, + pub logs: Data, +} + +impl Stored { + pub fn new() -> Self { + Self { + last_fetch: None, + logs: Arc::new(Mutex::new(Vec::new())), + } + } + + fn start_update(&mut self, reading: Reading, new_length: Duration, data_store: SocketAddr) { + if let Some(in_progress) = self.last_fetch.take() { + in_progress.cancel.notify_one(); + let _ = in_progress.handle.join(); + debug!("Canceled running stored-history update"); + } + + let reading = reading.clone(); + let cancel = Arc::new(Notify::new()); + let cancelled = cancel.clone(); + let data = self.logs.clone(); + let handle = thread::spawn(move || fetch(data, reading, data_store, new_length, cancelled)); + self.last_fetch = Some(Fetching { + handle, + cancel, + history_length: new_length, + }); + } + + pub fn update_if_needed( + &mut self, + data_store: SocketAddr, + reading: Reading, + needed_hist: &mut HistoryLen, + ) { + if let Some(last_fetch) = &mut self.last_fetch { + if last_fetch.history_length != needed_hist.dur { + self.start_update(reading, needed_hist.dur, data_store); + needed_hist.state = history_len::State::Fetching; + } + } else { + self.start_update(reading, needed_hist.dur, data_store); + needed_hist.state = history_len::State::Fetching; + } + + if let Some(last_fetch) = &self.last_fetch { + if last_fetch.handle.is_finished() { + needed_hist.state = history_len::State::Fetched + } + } + } +} + +fn fetch( + logs: Arc>>, + reading: Reading, + addr: SocketAddr, + length: Duration, + cancelled: Arc, +) { + let rt = tokio::runtime::Builder::new_current_thread() + .enable_io() + .enable_time() + .build() + .unwrap(); + + let Some(data) = rt.block_on(async { + tokio::select! { + data = connect_and_get_data(addr, length, reading) => Some(data), + _ = cancelled.notified() => None, + } + }) else { + debug!("Canceled data fetch"); + return; + }; + + let mut logs = logs.lock().unwrap(); + *logs = data; +} + +async fn connect_and_get_data( + addr: SocketAddr, + _length: Duration, + reading: Reading, +) -> Vec { + let mut retry_period = Duration::ZERO; + loop { + sleep(retry_period).await; + retry_period = Duration::from_secs(5) + .min(retry_period * 2) + .min(Duration::from_millis(100)); + + let host = gethostname::gethostname(); + let host = host.to_string_lossy(); + let name = format!("sensor-tui@{host}"); + let mut api = match log_store::api::Client::connect(addr, name).await { + Ok(api) => api, + Err(e) => { + warn!("Could not connect to data_store (at {addr}): {e}"); + continue; + } + }; + + match api.get_logs(reading.device()).await { + Ok(res) => return res, + Err(e) => { + warn!("Error getting data from data-store, reconnecting: {e}"); + continue; + } + }; + } +} diff --git a/crates/sensor-tui/src/tui/reading/logs2.rs b/crates/sensor-tui/src/tui/reading/logs2.rs new file mode 100644 index 00000000..78513dcf --- /dev/null +++ b/crates/sensor-tui/src/tui/reading/logs2.rs @@ -0,0 +1,53 @@ +use jiff::Unit; +use log_store::api::{self, ErrorEvent}; + +#[derive(Debug)] +pub(crate) struct Logs { + current: Option<(jiff::Timestamp, protocol::Error)>, + history: Vec, +} + +impl Logs { + pub(crate) fn new_from(error: &protocol::Error) -> Self { + Self { + current: Some((jiff::Timestamp::now(), error.clone())), + history: Vec::new(), + } + } + + pub(crate) fn new_empty() -> Self { + Self { + current: None, + history: Vec::new(), + } + } + + pub(crate) fn add(&mut self, error: &protocol::Error) { + if let Some((started, event)) = self.current.take() { + self.history.push(api::ErrorEvent { + start: started, + end: jiff::Timestamp::now(), + error: event, + }) + } + + self.current = Some((jiff::Timestamp::now(), error.clone())) + } + + pub(crate) fn density(&self, buckets: [jiff::Span; N]) -> [f32; N] { + let now = jiff::Timestamp::now(); + let mut buckets = buckets.map(|bound| (bound, 0.0)); + for ErrorEvent { start, end, .. } in self.history.iter().rev() { + for (bound, count) in &mut buckets { + let bound_start = now - *bound; + let start = start.max(&bound_start); + let error_time = end.since(*start).expect("duration should fit type"); + if !error_time.is_negative() { + *count += error_time.total(Unit::Second).expect("smaller then day") + / bound.total(Unit::Second).expect("smaller then day"); + } + } + } + buckets.map(|(_, count)| count as f32) + } +} diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs index 805bc000..dcea35a6 100644 --- a/crates/sensor-tui/src/tui/render.rs +++ b/crates/sensor-tui/src/tui/render.rs @@ -10,7 +10,7 @@ use ratatui::{ use tui_tree_widget::{Tree, TreeItem}; use super::{ - reading::{ChartParts, Details, NumErrorSince, TreeKey}, + reading::{ChartParts, Details, ErrorDensity, TreeKey}, ActiveList, App, }; @@ -164,7 +164,7 @@ fn render_details(frame: &mut Frame, layout: Rect, details: Details) { Err(err) => format!("error: {err}\n"), }; - let NumErrorSince { + let ErrorDensity { t5_min, t15_min, t30_min, From 2503cbad1157f3c2688957af34d8a939a43e0b07 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 12 Aug 2024 14:51:39 +0200 Subject: [PATCH 185/687] add logs, fix some problemens in histogram/history fetching --- crates/sensor-tui/src/tui.rs | 47 +++--- crates/sensor-tui/src/tui/history_len.rs | 10 +- crates/sensor-tui/src/tui/reading.rs | 27 ++- .../src/tui/reading/fetch/histogram.rs | 4 +- .../src/tui/reading/fetch/history.rs | 6 +- .../sensor-tui/src/tui/reading/fetch/logs.rs | 20 ++- .../src/tui/reading/fetch_timings.rs | 0 crates/sensor-tui/src/tui/reading/logs2.rs | 4 + crates/sensor-tui/src/tui/render.rs | 157 +++++++++++------- crates/sensor-tui/src/tui/render/logs.rs | 64 +++++++ 10 files changed, 236 insertions(+), 103 deletions(-) delete mode 100644 crates/sensor-tui/src/tui/reading/fetch_timings.rs create mode 100644 crates/sensor-tui/src/tui/render/logs.rs diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index 80ce6323..92b9f8f6 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -5,7 +5,7 @@ use crossterm::{ }; use ratatui::{ prelude::{CrosstermBackend, Terminal}, - style::{Color, Style}, + widgets::TableState, }; use std::{collections::HashMap, io::stdout, net::SocketAddr, sync::mpsc, time::Duration}; use tui_tree_widget::TreeState; @@ -21,27 +21,26 @@ use history_len::HistoryLen; use self::reading::TreeKey; #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] -enum ActiveList { +enum ActiveTab { #[default] Readings, Affectors, } -impl ActiveList { - fn style(&self, list: Self) -> Style { - if *self == list { - Style::default().fg(Color::Black) - } else { - Style::default().fg(Color::Indexed(242)) - } - } - +impl ActiveTab { fn swap(self) -> Self { match self { Self::Readings => Self::Affectors, Self::Affectors => Self::Readings, } } + + fn number(&self) -> usize { + match self { + ActiveTab::Readings => 0, + ActiveTab::Affectors => 1, + } + } } #[derive(Debug, Default, Clone, Copy)] @@ -63,10 +62,12 @@ pub fn run( #[derive(Default)] struct App { input_mode: InputMode, - active_list: ActiveList, + active_tab: ActiveTab, show_histogram: bool, + show_logs: bool, reading_tree_state: TreeState, affector_tree_state: TreeState, + logs_table_state: TableState, history_length: HistoryLen, } @@ -99,9 +100,9 @@ impl App { .and_then(|key| readings.data.get_mut(key)); let plot_open = data.is_some(); - let (chart, histogram, details) = if let Some(data) = data { + let (chart, histogram, details, logs) = if let Some(data) = data { data.logs_from_store.update_if_needed( - data_store, + log_store, data.reading.clone(), &mut self.history_length, ); @@ -119,9 +120,10 @@ impl App { data.chart(&mut plot_buf), data.histogram(), Some(data.details()), + Some(data.logs()), ) } else { - (None, Vec::new(), None) + (None, Vec::new(), None, None) }; terminal.draw(|frame| { @@ -132,6 +134,7 @@ impl App { &affectors, details, chart, + logs, &histogram, ); })?; @@ -144,7 +147,10 @@ impl App { if let event::Event::Key(key) = event::read()? { tracing::trace!("key pressed: {key:?}"); if key.kind == KeyEventKind::Press { - self.handle_key_all_modes(key); + let res = self.handle_key_all_modes(key); + if let ShouldExit::Yes = res { + break; + } let res = match self.input_mode { InputMode::Normal => self.handle_key_normal_mode(key, plot_open), InputMode::EditingBounds => self.handle_key_bounds_mode(key), @@ -174,14 +180,14 @@ impl App { fn handle_key_normal_mode(&mut self, key: KeyEvent, plot_open: bool) -> ShouldExit { match key.code { - KeyCode::Char('q') => { + KeyCode::Char('q') | KeyCode::Esc => { return ShouldExit::Yes; } KeyCode::Left => { - self.active_list = self.active_list.swap(); + self.active_tab = self.active_tab.swap(); } KeyCode::Right => { - self.active_list = self.active_list.swap(); + self.active_tab = self.active_tab.swap(); } KeyCode::Char('b') => { if plot_open { @@ -192,6 +198,9 @@ impl App { KeyCode::Char('h') => { self.show_histogram = !self.show_histogram; } + KeyCode::Char('l') => { + self.show_logs = !self.show_logs; + } _other => (), } ShouldExit::No diff --git a/crates/sensor-tui/src/tui/history_len.rs b/crates/sensor-tui/src/tui/history_len.rs index c1325faa..028470e0 100644 --- a/crates/sensor-tui/src/tui/history_len.rs +++ b/crates/sensor-tui/src/tui/history_len.rs @@ -3,7 +3,7 @@ use ratatui::{ style::{Color, Modifier, Style}, text::Span, }; -use std::time::Duration; +use std::time::{Duration, Instant}; use crate::time::format::fmt_seconds; use crate::time::parse::parse_duration; @@ -13,7 +13,7 @@ pub enum State { Empty, Invalid, Valid, - Fetching, + Fetching(Instant), Fetched, } @@ -81,12 +81,12 @@ impl HistoryLen { let style = Style::default().add_modifier(Modifier::ITALIC); Span::raw(text).style(style) } - State::Fetching => { + State::Fetching(started) if started.elapsed() > Duration::from_secs(2) => { let style = Style::default().add_modifier(Modifier::ITALIC); text.push_str(" (fetching)"); Span::raw(text).style(style) } - State::Fetched => { + State::Fetched | State::Fetching(_) => { if self.editing { Span::raw(text) } else { @@ -100,7 +100,7 @@ impl HistoryLen { self.editing = false; self.state = match self.state { State::Empty | State::Invalid => State::Fetched, - State::Valid | State::Fetching | State::Fetched => self.state, + State::Valid | State::Fetching(_) | State::Fetched => self.state, } } diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index 2176cf22..5e42ed12 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -1,6 +1,7 @@ use hdrhistogram::Histogram; use itertools::Itertools; use jiff::Unit; +use log_store::api::ErrorEvent; use protocol::reading_tree::ReadingInfo; use protocol::reading_tree::{Item, Tree}; use protocol::Error; @@ -24,7 +25,7 @@ pub struct SensorInfo { recent_history: Vec<(jiff::Timestamp, f32)>, pub history_from_store: history::Stored, condition: Result<(), Box>, - errors: logs2::Logs, + logs: logs2::Logs, pub logs_from_store: logs::Stored, } @@ -83,7 +84,7 @@ impl SensorInfo { last_reading, condition: self.condition.clone(), description: self.reading.leaf().description.to_owned(), - errors_since: ErrorDensity::from_log(&self.errors), + errors_since: ErrorDensity::from_log(&self.logs), } } @@ -158,6 +159,22 @@ impl SensorInfo { data: plot_buf, }) } + + pub fn logs(&self) -> Vec { + let mut logs = self.logs_from_store.list(); + let last = logs + .last() + .map(|ErrorEvent { start, .. }| *start) + .unwrap_or(jiff::Timestamp::from_second(0).unwrap()); + let without_duplicates = self + .logs + .list() + .iter() + .skip_while(|ErrorEvent { start, .. }| start < &last) + .cloned(); + logs.extend(without_duplicates); + logs + } } /// Guaranteed to be unique for a leaf, @@ -254,7 +271,7 @@ impl Readings { if let Some(info) = self.data.get_mut(&key) { info.condition = Err(error.clone()); - info.errors.add(&error); + info.logs.add(&error); } else { let errors = logs2::Logs::new_from(&error); self.data.insert( @@ -269,7 +286,7 @@ impl Readings { logs_from_store: fetch::logs::Stored::new(), condition: Err(error.clone()), - errors, + logs: errors, }, ); } @@ -302,7 +319,7 @@ impl Readings { logs_from_store: fetch::logs::Stored::new(), condition: Ok(()), - errors: logs2::Logs::new_empty(), + logs: logs2::Logs::new_empty(), }, ); } diff --git a/crates/sensor-tui/src/tui/reading/fetch/histogram.rs b/crates/sensor-tui/src/tui/reading/fetch/histogram.rs index d56ddd72..c253a285 100644 --- a/crates/sensor-tui/src/tui/reading/fetch/histogram.rs +++ b/crates/sensor-tui/src/tui/reading/fetch/histogram.rs @@ -62,11 +62,11 @@ impl Stored { if let Some(last_fetch) = &mut self.last_fetch { if last_fetch.history_length != needed_hist.dur || self.outdated() { self.start_update(device, needed_hist.dur, log_store); - needed_hist.state = history_len::State::Fetching; + needed_hist.state = history_len::State::Fetching(Instant::now()); } } else { self.start_update(device, needed_hist.dur, log_store); - needed_hist.state = history_len::State::Fetching; + needed_hist.state = history_len::State::Fetching(Instant::now()); } if let Some(last_fetch) = &mut self.last_fetch { diff --git a/crates/sensor-tui/src/tui/reading/fetch/history.rs b/crates/sensor-tui/src/tui/reading/fetch/history.rs index a3d3503f..5dec44dd 100644 --- a/crates/sensor-tui/src/tui/reading/fetch/history.rs +++ b/crates/sensor-tui/src/tui/reading/fetch/history.rs @@ -3,7 +3,7 @@ use protocol::Reading; use std::net::SocketAddr; use std::sync::{Arc, Mutex}; use std::thread; -use std::time::Duration; +use std::time::{Duration, Instant}; use tokio::sync::Notify; use tokio::time::sleep; use tracing::{debug, warn}; @@ -56,11 +56,11 @@ impl Stored { if let Some(last_fetch) = &mut self.last_fetch { if last_fetch.history_length != needed_hist.dur { self.start_update(reading, needed_hist.dur, data_store); - needed_hist.state = history_len::State::Fetching; + needed_hist.state = history_len::State::Fetching(Instant::now()); } } else { self.start_update(reading, needed_hist.dur, data_store); - needed_hist.state = history_len::State::Fetching; + needed_hist.state = history_len::State::Fetching(Instant::now()); } if let Some(last_fetch) = &self.last_fetch { diff --git a/crates/sensor-tui/src/tui/reading/fetch/logs.rs b/crates/sensor-tui/src/tui/reading/fetch/logs.rs index 57bbe5d8..e0e80df4 100644 --- a/crates/sensor-tui/src/tui/reading/fetch/logs.rs +++ b/crates/sensor-tui/src/tui/reading/fetch/logs.rs @@ -4,7 +4,7 @@ use protocol::Reading; use std::net::SocketAddr; use std::sync::{Arc, Mutex}; use std::thread; -use std::time::Duration; +use std::time::{Duration, Instant}; use tokio::sync::Notify; use tokio::time::sleep; use tracing::{debug, warn}; @@ -29,7 +29,11 @@ impl Stored { } } - fn start_update(&mut self, reading: Reading, new_length: Duration, data_store: SocketAddr) { + pub(crate) fn list(&self) -> Vec { + self.logs.lock().unwrap().clone() + } + + fn start_update(&mut self, reading: Reading, new_length: Duration, log_store: SocketAddr) { if let Some(in_progress) = self.last_fetch.take() { in_progress.cancel.notify_one(); let _ = in_progress.handle.join(); @@ -40,7 +44,7 @@ impl Stored { let cancel = Arc::new(Notify::new()); let cancelled = cancel.clone(); let data = self.logs.clone(); - let handle = thread::spawn(move || fetch(data, reading, data_store, new_length, cancelled)); + let handle = thread::spawn(move || fetch(data, reading, log_store, new_length, cancelled)); self.last_fetch = Some(Fetching { handle, cancel, @@ -50,18 +54,18 @@ impl Stored { pub fn update_if_needed( &mut self, - data_store: SocketAddr, + log_store: SocketAddr, reading: Reading, needed_hist: &mut HistoryLen, ) { if let Some(last_fetch) = &mut self.last_fetch { if last_fetch.history_length != needed_hist.dur { - self.start_update(reading, needed_hist.dur, data_store); - needed_hist.state = history_len::State::Fetching; + self.start_update(reading, needed_hist.dur, log_store); + needed_hist.state = history_len::State::Fetching(Instant::now()); } } else { - self.start_update(reading, needed_hist.dur, data_store); - needed_hist.state = history_len::State::Fetching; + self.start_update(reading, needed_hist.dur, log_store); + needed_hist.state = history_len::State::Fetching(Instant::now()); } if let Some(last_fetch) = &self.last_fetch { diff --git a/crates/sensor-tui/src/tui/reading/fetch_timings.rs b/crates/sensor-tui/src/tui/reading/fetch_timings.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/crates/sensor-tui/src/tui/reading/logs2.rs b/crates/sensor-tui/src/tui/reading/logs2.rs index 78513dcf..fb9bbe83 100644 --- a/crates/sensor-tui/src/tui/reading/logs2.rs +++ b/crates/sensor-tui/src/tui/reading/logs2.rs @@ -50,4 +50,8 @@ impl Logs { } buckets.map(|(_, count)| count as f32) } + + pub(crate) fn list(&self) -> &[api::ErrorEvent] { + &self.history + } } diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs index dcea35a6..dec0b87d 100644 --- a/crates/sensor-tui/src/tui/render.rs +++ b/crates/sensor-tui/src/tui/render.rs @@ -1,20 +1,21 @@ use jiff::Timestamp; use ratatui::{ self, - layout::{Constraint, Flex, Layout, Rect}, - style::{Modifier, Style}, + layout::{Alignment, Constraint, Direction, Flex, Layout, Rect}, + style::{Color, Modifier, Style}, text::Text, - widgets::{self, Bar, BarChart, BarGroup, Block, Borders}, + widgets::{self, Bar, BarChart, BarGroup, Block, Borders, Tabs}, Frame, }; use tui_tree_widget::{Tree, TreeItem}; use super::{ reading::{ChartParts, Details, ErrorDensity, TreeKey}, - ActiveList, App, + ActiveTab, App, }; mod chart; +mod logs; pub(crate) fn app( frame: &mut Frame, @@ -23,13 +24,15 @@ pub(crate) fn app( affectors: &[TreeItem<'static, TreeKey>], details: Option
, chart: Option, + logs: Option>, histogram: &[Bar], ) { let [list_constraint, graph_constraint] = if chart.is_some() { - let list_height = 2 + app.reading_tree_state.flatten(readings).len(); - if (frame.size().height as f32) / 3. > list_height as f32 { + let tree_height = 2 + app.reading_tree_state.flatten(readings).len(); + let details_height = 9; + if (frame.size().height as f32) / 3. > tree_height as f32 { [ - Constraint::Min(list_height as u16), + Constraint::Min(tree_height.max(details_height) as u16), Constraint::Percentage(100), ] } else { @@ -40,52 +43,100 @@ pub(crate) fn app( }; let area = frame.size(); - let [top, bottom, footer] = - Layout::vertical([list_constraint, graph_constraint, Constraint::Min(1)]) - .flex(Flex::Legacy) - .areas(area); - - render_readings_and_actuators(frame, top, app, readings, affectors, details); - render_graph_and_hist(frame, bottom, app, histogram, chart); + let [top_line, top, bottom, footer] = Layout::vertical([ + Constraint::Min(1), + list_constraint, + graph_constraint, + Constraint::Min(1), + ]) + .flex(Flex::Legacy) + .areas(area); + + render_tab(frame, top_line, app.active_tab); + + match app.active_tab { + ActiveTab::Readings => { + render_readings_and_details(frame, top, app, readings, details); + render_graph_hist_logs(frame, bottom, app, histogram, logs, chart); + } + ActiveTab::Affectors => render_affectors(frame, top, app, affectors), + } render_footer(frame, footer, app); } +fn render_tab(frame: &mut Frame, layout: Rect, active_tab: ActiveTab) { + let tabs = Tabs::new(vec!["Readings", "Affectors"]) + .style(Style::new().bg(Color::Gray)) + .select(active_tab.number()) + .divider("|") + .padding(" ", " "); + + frame.render_widget(tabs, layout); +} + fn render_footer(frame: &mut Frame, layout: Rect, app: &mut App) { - let text = if app.history_length.editing { - "ESC: stop bound editing" + let mut footer = Vec::new(); + + if app.history_length.editing { + footer.push("ESC or q: stop bound editing"); } else { - if app.show_histogram { - "b: edit graph start, h: hide histogram" - } else { - "b: edit graph start, h: show histogram" - } - }; + footer.push("ESC or q: quit"); + footer.push("b: edit graph start"); + } - let text = Text::raw(text); - frame.render_widget(text, layout) + if app.show_histogram { + footer.push("h: hide histogram"); + } else { + footer.push("h: show histogram"); + } + + if app.show_logs { + footer.push("l: hide logs"); + } else { + footer.push("l: show logs"); + } + + let footer = footer.join(" "); + let footer = Text::raw(footer) + .alignment(Alignment::Center) + .style(Style::new().bg(Color::Gray)); + frame.render_widget(footer, layout) } -fn render_graph_and_hist( +fn render_graph_hist_logs( frame: &mut Frame, layout: Rect, app: &mut App, histogram: &[Bar], + logs: Option>, chart: Option, ) { - match (chart, app.show_histogram) { - (None, true) => render_histogram(frame, layout, histogram), - (None, false) => (), - (Some(chart), true) => { - let [top, lower] = - Layout::vertical([Constraint::Percentage(65), Constraint::Percentage(35)]) - .flex(Flex::Legacy) - .areas(layout); - chart::render(frame, top, app, chart); - render_histogram(frame, lower, histogram); - } - (Some(chart), false) => { - chart::render(frame, layout, app, chart); - } + let logs = app.show_logs.then(|| logs).flatten(); + let num_elems = chart.is_some() as u8 + app.show_histogram as u8 + logs.is_some() as u8; + + let layout = Layout::default() + .direction(Direction::Vertical) + .constraints((0..num_elems).into_iter().map(|_| Constraint::Fill(10))) + .flex(Flex::Legacy) + .split(layout); + + let mut layout = layout.into_iter(); + + if let Some(chart) = chart { + chart::render(frame, layout.next().unwrap().clone(), app, chart); + } + + if let Some(logs) = logs { + logs::render( + frame, + layout.next().unwrap().clone(), + &mut app.logs_table_state, + logs, + ) + } + + if app.show_histogram { + render_histogram(frame, layout.next().unwrap().clone(), histogram); } } @@ -94,17 +145,13 @@ fn render_histogram(frame: &mut Frame, lower: Rect, histogram: &[Bar]) { .block(Block::bordered().title("Histogram")) .data(BarGroup::default().bars(histogram)) .bar_width(12); - // .bar_style(Style::default()) - // .value_style(Style::default()); frame.render_widget(barchart, lower) } - -pub(crate) fn render_readings_and_actuators( +pub(crate) fn render_readings_and_details( frame: &mut Frame, layout: Rect, app: &mut App, readings: &[TreeItem<'static, TreeKey>], - affectors: &[TreeItem<'static, TreeKey>], details: Option
, ) { let [left, right] = @@ -118,25 +165,15 @@ pub(crate) fn render_readings_and_actuators( .block( Block::default() .title("Sensor readings") - .borders(Borders::ALL) - .border_style(app.active_list.style(ActiveList::Readings)), + .borders(Borders::ALL), ) - .style(app.active_list.style(ActiveList::Readings)) .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) .highlight_symbol(">>"), left, &mut app.reading_tree_state, ); - - if let (Some(details), ActiveList::Readings) = (details, app.active_list) { - let [top, bottom] = - Layout::vertical([Constraint::Percentage(30), Constraint::Percentage(70)]) - .flex(Flex::Legacy) - .areas(right); - render_affectors(frame, top, app, affectors); - render_details(frame, bottom, details); - } else { - render_affectors(frame, right, app, affectors) + if let Some(details) = details { + render_details(frame, right, details); } } @@ -193,11 +230,9 @@ fn render_affectors( .expect("all item identifiers should be unique") .block( Block::default() - .title("Controllable actuators") - .borders(Borders::ALL) - .border_style(app.active_list.style(ActiveList::Affectors)), + .title("Controllable affectors") + .borders(Borders::ALL), ) - .style(app.active_list.style(ActiveList::Affectors)) .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) .highlight_symbol(">>"), layout, diff --git a/crates/sensor-tui/src/tui/render/logs.rs b/crates/sensor-tui/src/tui/render/logs.rs new file mode 100644 index 00000000..b419f00b --- /dev/null +++ b/crates/sensor-tui/src/tui/render/logs.rs @@ -0,0 +1,64 @@ +use log_store::api::ErrorEvent; +use ratatui::layout::{Constraint, Rect}; +use ratatui::style::{Color, Modifier, Style, Stylize}; +use ratatui::text::Text; +use ratatui::widgets::{Cell, HighlightSpacing, Row, Table, TableState}; +use ratatui::Frame; + +pub fn render( + frame: &mut Frame, + layout: Rect, + table_state: &mut TableState, + logs: Vec, +) { + let header_style = Style::default().fg(Color::Black).bg(Color::Gray); + let selected_style = Style::default() + .add_modifier(Modifier::REVERSED) + .fg(Color::White); + + let header = ["Error", "Started at", "Cleared at"] + .into_iter() + .map(Cell::from) + .collect::() + .style(header_style) + .height(1); + + let rows = logs + .into_iter() + .enumerate() + .map(|(i, ErrorEvent { start, end, error })| { + let color = match i % 2 { + 0 => Color::DarkGray, + _ => Color::Gray, + }; + let item = [format!("{error}"), format!("{start}"), format!("{end}")]; + item.into_iter() + .map(|content| Text::from(content)) + .map(|content| Cell::from(content)) + .collect::() + .style(Style::new().fg(Color::Black).bg(color)) + .height(1) + }); + + let bar = " â–ˆ "; + let table = Table::new( + rows, + [ + Constraint::Length(10), + Constraint::Min(10), + Constraint::Min(10), + ], + ) + .header(header) + .highlight_style(selected_style) + .highlight_symbol(Text::from(vec![ + "".into(), + bar.into(), + bar.into(), + "".into(), + ])) + .bg(Color::White) + .highlight_spacing(HighlightSpacing::Always); + + frame.render_stateful_widget(table, layout, table_state); +} From 695ebcb7c9ee3387a798ea7ecf163b4bce13baaa Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 12 Aug 2024 14:52:45 +0200 Subject: [PATCH 186/687] fixes ratelimiting keys being too unique --- crates/data-store/src/server/clients.rs | 6 ++++-- crates/log-store/src/server/clients.rs | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/data-store/src/server/clients.rs b/crates/data-store/src/server/clients.rs index 00345539..45988d3a 100644 --- a/crates/data-store/src/server/clients.rs +++ b/crates/data-store/src/server/clients.rs @@ -45,7 +45,7 @@ pub(crate) async fn handle(port: u16, data: Data) -> color_eyre::Result<()> { continue; }; - if let Err(allowed_again) = limiter.check_key(&(source, name.clone())) { + if let Err(allowed_again) = limiter.check_key(&(source.ip(), name.clone())) { let allowed_in = allowed_again.wait_time_from(DefaultClock::default().now()); let _ignore_err = conn.send(api::Response::Error(ServerError::TooManyRequests( allowed_in, @@ -80,7 +80,9 @@ async fn handshake_and_log(stream: TcpStream, source: SocketAddr) -> Option<(Con warn!("client from {source} tried to connected without handshake, it send: {other:?}") } Ok(None) => warn!("client from {source} closed connection immediately"), - Err(e) => warn!("connection or decoding issue while receiving handshake from {source}, error: {e:?}"), + Err(e) => warn!( + "connection or decoding issue while receiving handshake from {source}, error: {e:?}" + ), } None diff --git a/crates/log-store/src/server/clients.rs b/crates/log-store/src/server/clients.rs index d1ff013f..1595dea3 100644 --- a/crates/log-store/src/server/clients.rs +++ b/crates/log-store/src/server/clients.rs @@ -49,7 +49,7 @@ pub(crate) async fn handle( continue; }; - if let Err(allowed_again) = limiter.check_key(&(source, name)) { + if let Err(allowed_again) = limiter.check_key(&(source.ip(), name)) { let allowed_in = allowed_again.wait_time_from(DefaultClock::default().now()); let _ignore_err = conn.send(api::Response::Error(ServerError::TooManyRequests( allowed_in, From 930e4dbde2ad962ce72240e824e7d3a0c2b50db0 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 12 Aug 2024 14:53:18 +0200 Subject: [PATCH 187/687] adds weight sensor to fast sensors --- Cargo.lock | 4 ++ sensor-nodes/bed-sensors/Cargo.lock | 12 +++++ sensor-nodes/bed-sensors/Cargo.toml | 2 +- sensor-nodes/bed-sensors/src/error_cache.rs | 2 + sensor-nodes/bed-sensors/src/main.rs | 22 ++++++-- sensor-nodes/bed-sensors/src/sensors.rs | 16 +++--- sensor-nodes/bed-sensors/src/sensors/fast.rs | 52 +++++++++++++++++-- sensor-nodes/bed-sensors/src/sensors/retry.rs | 22 +++++++- .../src/sensors/retry/reinit_on_error.rs | 2 + 9 files changed, 115 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0bdf4898..ebb599a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1979,6 +1979,8 @@ dependencies = [ name = "log-store" version = "0.1.0" dependencies = [ + "bincode", + "byteseries", "clap", "color-eyre", "data-server", @@ -1986,6 +1988,7 @@ dependencies = [ "futures-concurrency", "governor", "hdrhistogram", + "heapless 0.8.0", "jiff", "nucleo-matcher", "num", @@ -2947,6 +2950,7 @@ dependencies = [ "hdrhistogram", "itertools", "jiff", + "log-store", "protocol", "ratatui", "thiserror", diff --git a/sensor-nodes/bed-sensors/Cargo.lock b/sensor-nodes/bed-sensors/Cargo.lock index 3f6a0e17..24b9b5ca 100644 --- a/sensor-nodes/bed-sensors/Cargo.lock +++ b/sensor-nodes/bed-sensors/Cargo.lock @@ -57,6 +57,7 @@ dependencies = [ "heapless 0.8.0", "max44009", "mhzx", + "nau7802-async", "nb 1.1.0", "panic-probe", "protocol", @@ -790,6 +791,17 @@ dependencies = [ "serde", ] +[[package]] +name = "nau7802-async" +version = "0.2.0" +dependencies = [ + "byteorder", + "defmt", + "embedded-hal-async", + "postcard", + "serde", +] + [[package]] name = "nb" version = "0.1.3" diff --git a/sensor-nodes/bed-sensors/Cargo.toml b/sensor-nodes/bed-sensors/Cargo.toml index 4baf653a..4badc186 100644 --- a/sensor-nodes/bed-sensors/Cargo.toml +++ b/sensor-nodes/bed-sensors/Cargo.toml @@ -37,9 +37,9 @@ static_cell = "2.0.0" bosch-bme680 = { version = "1.0.2", path = "/home/david/Documents/async-bosch-bme680" } max44009 = { version = "0.2", git = "https://github.com/dvdsk/max44009-rs" } sht31 = { version = "0.3.0", git = "https://github.com/dvdsk/SHT31-rs", features = ["postcard"] } -# mhzx = { version = "0.3.0", git = "https://github.com/dvdsk/mhzx", features = ["postcard"] } mhzx = { version = "0.3.0", path = "/home/david/tmp/mh-zx-driver", features = ["serde", "postcard"] } sps30-async = { version = "0.2.0", path = "/home/david/tmp/sps30", features = ["serde", "postcard"] } +nau7802-async = { path = "/home/david/tmp/nau7802-rs", features = ["serde", "postcard", "defmt"] } # encoding protocol = { path = "../../crates/protocol" } diff --git a/sensor-nodes/bed-sensors/src/error_cache.rs b/sensor-nodes/bed-sensors/src/error_cache.rs index 83edb813..56e2ee8c 100644 --- a/sensor-nodes/bed-sensors/src/error_cache.rs +++ b/sensor-nodes/bed-sensors/src/error_cache.rs @@ -10,6 +10,7 @@ pub enum SensorError { Sht31(sht31::SHTError), Bme680(bosch_bme680::BmeError), Max44(max44009::Error), + Nau7802Left(nau7802_async::Error), } impl From for bed::SensorError { @@ -20,6 +21,7 @@ impl From for bed::SensorError { SensorError::Sht31(e) => bed::SensorError::Sht31(make_error_string(e)), SensorError::Bme680(e) => bed::SensorError::Bme680(make_error_string(e)), SensorError::Max44(e) => bed::SensorError::Max44(make_error_string(e)), + SensorError::Nau7802Left(e) => bed::SensorError::Nau7802Left(make_error_string(e)), } } } diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index ff1da392..97613634 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -37,6 +37,8 @@ use crate::channel::Queues; embassy_stm32::bind_interrupts!(struct Irqs { I2C1_EV => embassy_stm32::i2c::EventInterruptHandler; I2C1_ER => embassy_stm32::i2c::ErrorInterruptHandler; + I2C3_EV => embassy_stm32::i2c::EventInterruptHandler; + I2C3_ER => embassy_stm32::i2c::ErrorInterruptHandler; USART1 => embassy_stm32::usart::InterruptHandler; USART2 => embassy_stm32::usart::InterruptHandler; }); @@ -118,7 +120,7 @@ async fn main(spawner: Spawner) { usart_config, )); - let i2c = I2c::new( + let i2c_1 = I2c::new( p.I2C1, p.PB8, p.PB9, @@ -129,8 +131,20 @@ async fn main(spawner: Spawner) { Hertz(150_000), i2c::Config::default(), ); - let i2c: Mutex = Mutex::new(i2c); + let i2c_1: Mutex = Mutex::new(i2c_1); + let i2c_3 = I2c::new( + p.I2C3, + p.PA8, + p.PB4, + Irqs, + p.DMA1_CH4, + p.DMA1_CH1, + // extra slow, helps with longer cable runs + Hertz(150_000), + i2c::Config::default(), + ); + let i2c_3: Mutex = Mutex::new(i2c_3); /* // let buttons = ButtonInputs { // top_left: ExtiInput::new(p.PA13, p.EXTI13, Pull::Down), @@ -145,7 +159,7 @@ async fn main(spawner: Spawner) { */ let mut spi_cfg = SpiConfig::default(); - spi_cfg.frequency = Hertz(50_000_000); // up to 50m works + spi_cfg.frequency = Hertz(5_000_000); // up to 50m works let (miso, mosi, clk) = (p.PA6, p.PA7, p.PA5); let spi = Spi::new(p.SPI1, clk, mosi, miso, p.DMA2_CH3, p.DMA2_CH0, spi_cfg); let cs = Output::new(p.PA4, Level::High, Speed::VeryHigh); @@ -189,7 +203,7 @@ async fn main(spawner: Spawner) { // let send_and_pet_dog = join::join(&mut send_published, keep_dog_happy); let send_and_pet_dog = &mut send_published; - let init_then_measure = sensors::init_then_measure(&publish, i2c, usart_mhz, usart_sps30); + let init_then_measure = sensors::init_then_measure(&publish, i2c_1, i2c_3, usart_mhz, usart_sps30); let res = select::select(send_and_pet_dog, init_then_measure).await; let unrecoverable_err = match res { Either::First(network::ConnDownTooLong) => cortex_m::peripheral::SCB::sys_reset(), diff --git a/sensor-nodes/bed-sensors/src/sensors.rs b/sensor-nodes/bed-sensors/src/sensors.rs index 8c12c6be..712c1523 100644 --- a/sensor-nodes/bed-sensors/src/sensors.rs +++ b/sensor-nodes/bed-sensors/src/sensors.rs @@ -9,6 +9,7 @@ use embassy_sync::mutex::Mutex; use embassy_time::Delay; use mhzx::MHZ; use protocol::large_bedroom::bed::Device; +use retry::Nau7802Driver; use sps30_async::Sps30; use crate::channel::Queues; @@ -21,9 +22,6 @@ pub mod fast; pub mod retry; pub mod slow; -// Todo make failed init not critical. Keep trying init in background -// while we are measuring -// pub type I2cError = I2cDeviceError; pub type UartError = embassy_stm32::usart::Error; @@ -45,14 +43,16 @@ const SPS30_DRIVER_BUF_SIZE: usize = 2 * SPS30_UART_BUF_SIZE; pub async fn init_then_measure( publish: &Queues, - i2c: Mutex>, + i2c_1: Mutex>, + i2c_3: Mutex>, usart_mhz: Uart<'static, Async>, usart_sps: Uart<'static, Async>, ) -> Result<(), Error> { info!("initializing sensors"); - let bme = Bme680Driver::new(&i2c, Device::Bme680); - let max44009 = Max44Driver::new(&i2c, Device::Max44); - let sht = Sht31Driver::new(&i2c, Device::Sht31); + let bme = Bme680Driver::new(&i2c_3, Device::Bme680); + let max44009 = Max44Driver::new(&i2c_1, Device::Max44); + let sht = Sht31Driver::new(&i2c_1, Device::Sht31); + let nau_left = Nau7802Driver::new(&i2c_3, Device::Nau7802Left); let (tx, rx) = usart_mhz.split(); let mut usart_buf = [0u8; 9 * 10]; // 9 byte messages @@ -64,7 +64,7 @@ pub async fn init_then_measure( let rx = rx.into_ring_buffered(&mut usart_buf); let sps30 = Sps30Driver::init(tx, rx); - let sensors_fast = fast::read(max44009, /*buttons,*/ publish); + let sensors_fast = fast::read(max44009, nau_left, /*buttons,*/ publish); let sensors_slow = slow::read(sht, bme, mhz, sps30, publish); join::join(sensors_fast, sensors_slow).await; diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed-sensors/src/sensors/fast.rs index 64e53945..b5c01f93 100644 --- a/sensor-nodes/bed-sensors/src/sensors/fast.rs +++ b/sensor-nodes/bed-sensors/src/sensors/fast.rs @@ -1,12 +1,12 @@ use defmt::warn; -use embassy_futures::yield_now; +use embassy_futures::{join, yield_now}; use embassy_stm32::exti::ExtiInput; use embassy_time::{Duration, Instant, Timer}; use protocol::large_bedroom::{bed::Button, bed::Reading}; +use super::retry::{Max44Driver, Nau7802Driver}; use crate::channel::Queues; -use super::retry::Max44Driver; fn sig_lux_diff(old: f32, new: f32) -> bool { let diff = old - new; @@ -14,8 +14,13 @@ fn sig_lux_diff(old: f32, new: f32) -> bool { diff > old / 20.0 || -diff > old / 20.0 } +fn sig_weight_diff(old: u32, new: u32) -> bool { + let diff = new.abs_diff(old); + diff > 20 +} + async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues) { - const MAX_INTERVAL: Duration = Duration::from_secs(1); + const MAX_INTERVAL: Duration = Duration::from_secs(5); let mut prev_lux = f32::MAX; let mut last_lux = Instant::now(); @@ -46,6 +51,38 @@ async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues) { } } +async fn report_weight(mut nau: Nau7802Driver<'_>, publish: &Queues) { + const MAX_INTERVAL: Duration = Duration::from_secs(5); + + let mut prev_weight = u32::MAX; + let mut last_lux = Instant::now(); + + // todo!("reinit devices after error"); + loop { + Timer::after_millis(100).await; + let weight = match nau.try_measure().await { + Ok(lux) => lux, + Err(err) if last_lux.elapsed() > MAX_INTERVAL => { + publish.queue_error(err); + continue; + } + Err(_) => continue, + }; + + if sig_weight_diff(prev_weight, weight) { + publish.send_p2(Reading::WeightLeft(weight)); + } else if last_lux.elapsed() > MAX_INTERVAL { + publish.send_p1(Reading::WeightLeft(weight)); + } else { + yield_now().await; + continue; + }; + + prev_weight = weight; + last_lux = Instant::now(); + } +} + #[allow(dead_code)] async fn watch_button( mut input: ExtiInput<'static>, @@ -84,7 +121,11 @@ pub struct ButtonInputs { pub lower_outer: ExtiInput<'static>, } -pub async fn read(max44: Max44Driver<'_>, /*inputs: ButtonInputs,*/ publish: &Queues) { +pub async fn read( + max44: Max44Driver<'_>, + nau_left: Nau7802Driver<'_>, + /*inputs: ButtonInputs,*/ publish: &Queues, +) { // let watch_buttons_1 = join5( // watch_button(inputs.top_left, BedButton::TopLeft, publish), // watch_button(inputs.top_right, BedButton::TopRight, publish), @@ -100,6 +141,7 @@ pub async fn read(max44: Max44Driver<'_>, /*inputs: ButtonInputs,*/ publish: &Qu // ); let watch_lux = report_lux(max44, publish); - watch_lux.await; + let report_weight = report_weight(nau_left, publish); + join::join(watch_lux, report_weight).await; // join::join3(watch_buttons_1, watch_buttons_2, watch_lux).await; } diff --git a/sensor-nodes/bed-sensors/src/sensors/retry.rs b/sensor-nodes/bed-sensors/src/sensors/retry.rs index 413959da..e509fbb5 100644 --- a/sensor-nodes/bed-sensors/src/sensors/retry.rs +++ b/sensor-nodes/bed-sensors/src/sensors/retry.rs @@ -6,6 +6,7 @@ use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; use embassy_time::{Delay, Timer}; use max44009::{Max44009, SlaveAddr}; +use nau7802_async::Nau7802; use sht31::mode::SingleShot; use sht31::SHT31; @@ -13,7 +14,7 @@ use super::concrete_types::ConcreteSharedI2c; use crate::error_cache::SensorError; mod reinit_on_error; -pub use reinit_on_error::{Bme680Driver, Max44Driver, Sht31Driver}; +pub use reinit_on_error::{Bme680Driver, Max44Driver, Nau7802Driver, Sht31Driver}; mod retry_init; pub use retry_init::Sps30Driver; @@ -84,6 +85,25 @@ impl<'a> ReInitableDriver for Max44009> { } } +impl<'a> ReInitableDriver for Nau7802, Delay> { + type Parts = &'a Mutex>; + type Measurement = u32; + + async fn init(parts: Self::Parts) -> Result { + let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); + // wrap these two into something returning Ok or Err + // then make it a generic arg, maybe Driverfactory::init + let driver = Nau7802::new(shared_i2c, Delay) + .await + .map_err(SensorError::Nau7802Left)?; + Ok(driver) + } + + async fn measure(&mut self) -> Result { + self.read().await.map_err(SensorError::Nau7802Left) + } +} + /// a driver that can be re-initialized from copyable parts pub trait ReInitableDriver: Sized { type Parts: Clone; diff --git a/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs b/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs index c4a2a38a..a53e787a 100644 --- a/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs +++ b/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs @@ -1,6 +1,7 @@ use bosch_bme680::Bme680; use embassy_time::Delay; use max44009::Max44009; +use nau7802_async::Nau7802; use protocol::large_bedroom::bed::Device; use sht31::mode::SingleShot; use sht31::SHT31; @@ -9,6 +10,7 @@ use super::super::concrete_types::ConcreteSharedI2c; use super::ReInitableDriver; use crate::error_cache::Error; +pub type Nau7802Driver<'a> = ReInitOnErrorDriver, Delay>>; pub type Max44Driver<'a> = ReInitOnErrorDriver>>; pub type Bme680Driver<'a> = ReInitOnErrorDriver, Delay>>; pub type Sht31Driver<'a> = ReInitOnErrorDriver>>; From ccc3b138cc642f064871a789ad244c8cbaa81fca Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 12 Aug 2024 16:32:04 +0200 Subject: [PATCH 188/687] add ratelimited logger --- crates/log-store/src/server/clients.rs | 40 ++++++++------ crates/log-store/src/server/clients/logger.rs | 55 +++++++++++++++++++ crates/log-store/src/server/db/log.rs | 15 ++--- 3 files changed, 85 insertions(+), 25 deletions(-) create mode 100644 crates/log-store/src/server/clients/logger.rs diff --git a/crates/log-store/src/server/clients.rs b/crates/log-store/src/server/clients.rs index 1595dea3..63839987 100644 --- a/crates/log-store/src/server/clients.rs +++ b/crates/log-store/src/server/clients.rs @@ -7,14 +7,17 @@ use color_eyre::Section; use futures::{SinkExt, TryStreamExt}; use governor::clock::{Clock, DefaultClock}; use governor::{Quota, RateLimiter}; +use logger::RateLimitedLogger; use tokio::net::{TcpListener, TcpStream}; use tokio_serde::formats::Bincode; use tokio_util::codec::{Framed, LengthDelimitedCodec}; -use tracing::{debug, error, info, warn}; +use tracing::{debug, error, warn}; use super::db::{Logs, Stats}; use crate::api::{self, ServerError}; +mod logger; + type Conn = tokio_serde::Framed< Framed, api::Request, @@ -22,19 +25,16 @@ type Conn = tokio_serde::Framed< Bincode, >; -pub(crate) async fn handle( - port: u16, - stats: Stats, - logs: Logs, -) -> color_eyre::Result<()> { +pub(crate) async fn handle(port: u16, stats: Stats, logs: Logs) -> color_eyre::Result<()> { let quota = Quota::with_period(Duration::from_secs(1)) .unwrap() - .allow_burst(NonZeroU32::new(5u32).unwrap()); + .allow_burst(NonZeroU32::new(5).unwrap()); let limiter = RateLimiter::keyed(quota); let listener = TcpListener::bind(format!("0.0.0.0:{port}")) .await .wrap_err("Could not bind to address") .with_note(|| format!("port: {port}"))?; + let mut logger = RateLimitedLogger::new(); loop { let (socket, source) = match listener.accept().await { @@ -45,7 +45,7 @@ pub(crate) async fn handle( Ok(res) => res, }; - let Some((mut conn, name)) = handshake_and_log(socket, source).await else { + let Some((mut conn, name)) = handshake(socket, source, &mut logger).await else { continue; }; @@ -61,15 +61,15 @@ pub(crate) async fn handle( continue; }; - tokio::task::spawn(handle_client( - conn, - stats.clone(), - logs.clone(), - )); + tokio::task::spawn(handle_client(conn, stats.clone(), logs.clone())); } } -async fn handshake_and_log(stream: TcpStream, source: SocketAddr) -> Option<(Conn, String)> { +async fn handshake( + stream: TcpStream, + source: SocketAddr, + logger: &mut RateLimitedLogger, +) -> Option<(Conn, String)> { let length_delimited = Framed::new( stream, LengthDelimitedCodec::builder() @@ -81,12 +81,16 @@ async fn handshake_and_log(stream: TcpStream, source: SocketAddr) -> Option<(Con match stream.try_next().await { Ok(Some(api::Request::Handshake { name })) => { - info!("Client {name} connected from {source}"); + logger.info(&format!("Client {name} connected from {source}")); return Some((stream, name)); } - Ok(Some(other)) => warn!("client tried to connected without handshake, it send: {other:?}"), - Ok(None) => warn!("client closed connection immediately"), - Err(e) => warn!("connection or decoding issue while receiving handshake: {e:?}"), + Ok(Some(other)) => logger.warn(&format!( + "client tried to connected without handshake, it send: {other:?}" + )), + Ok(None) => logger.warn("client closed connection immediately"), + Err(e) => logger.warn(&format!( + "connection or decoding issue while receiving handshake: {e:?}" + )), } None diff --git a/crates/log-store/src/server/clients/logger.rs b/crates/log-store/src/server/clients/logger.rs new file mode 100644 index 00000000..ca3ba466 --- /dev/null +++ b/crates/log-store/src/server/clients/logger.rs @@ -0,0 +1,55 @@ +use governor::clock::DefaultClock; +use governor::middleware::NoOpMiddleware; +use governor::state::InMemoryState; +use governor::state::NotKeyed; +use governor::Quota; +use governor::RateLimiter; +use std::num::NonZeroU32; +use std::time::Duration; +use tracing::info; +use tracing::warn; + +pub(crate) struct RateLimitedLogger { + pub(crate) rate_limiter: RateLimiter, + pub(crate) withheld: usize, +} + +impl RateLimitedLogger { + pub(crate) fn new() -> Self { + let quota = Quota::with_period(Duration::from_secs(1)) + .unwrap() + .allow_burst(NonZeroU32::new(5).unwrap()); + Self { + rate_limiter: RateLimiter::direct(quota), + withheld: 0, + } + } + + pub(crate) fn warn(&mut self, txt: &str) { + if self.rate_limiter.check().is_err() { + self.withheld += 1; + return; + } + + if self.withheld > 0 { + warn!("Logs are being spammed, withheld {} logs", self.withheld); + self.withheld = 0; + } + + warn!(txt); + } + + pub(crate) fn info(&mut self, txt: &str) { + if self.rate_limiter.check().is_err() { + self.withheld += 1; + return; + } + + if self.withheld > 0 { + info!("Logs are being spammed, withheld {} logs", self.withheld); + self.withheld = 0; + } + + info!(txt); + } +} diff --git a/crates/log-store/src/server/db/log.rs b/crates/log-store/src/server/db/log.rs index 3fb43999..ae61f84f 100644 --- a/crates/log-store/src/server/db/log.rs +++ b/crates/log-store/src/server/db/log.rs @@ -44,8 +44,9 @@ impl CurrentError { match bincode::deserialize(&buf) { Ok(value) => Some(value), Err(err) => { + tracing::debug!("Data was: {buf:?}"); warn!( - "On disk backup failed to deserialize setting to None, \ + "On disk backup failed to deserialize, setting to None, \ error was: {err}" ); file.set_len(0).wrap_err( @@ -73,6 +74,9 @@ impl CurrentError { self.file .write_all(&bytes) .wrap_err("could not backup current error to disk")?; + self.file + .flush() + .wrap_err("failed to flush current err backup to disk")?; Ok(()) } } @@ -96,7 +100,9 @@ impl Log { Ok(Self { history, current: CurrentError::open_or_create(&path) - .wrap_err("Could not setup current error store")?, + .wrap_err("Could not setup current error store") + .with_note(|| format!("device: {device:?}")) + .with_note(|| format!("path: {}", path.display()))?, }) } @@ -216,12 +222,7 @@ fn try_create_new_if_open_failed( std::fs::create_dir_all(dirs) .wrap_err("Could not create dirs structure for reading") .with_note(|| format!("dirs: {}", dirs.display()))?; - std::fs::read_dir(dirs) - .unwrap() - .map(Result::unwrap) - .for_each(|p| println!("{p:?}")); } - // compile_error!("create directory structure"); info!("creating new byteseries"); ByteSeries::new(&path, payload_size, expected_header) .wrap_err("Could not create new byteseries") From 10f3533398b1a8843b5345c4187748cd43699041 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 13 Aug 2024 23:05:40 +0200 Subject: [PATCH 189/687] prepopulate list of sensor readings on startup --- crates/log-store/src/api.rs | 7 +- crates/log-store/src/api/client.rs | 12 ++ crates/log-store/src/server/clients.rs | 1 + crates/log-store/src/server/db/log.rs | 7 +- crates/protocol/src/lib.rs | 2 +- crates/protocol/src/reading_tree.rs | 2 +- crates/sensor-tui/Cargo.toml | 4 +- crates/sensor-tui/src/main.rs | 21 +++- crates/sensor-tui/src/populate.rs | 56 +++++++++ crates/sensor-tui/src/tui.rs | 6 + crates/sensor-tui/src/tui/reading.rs | 112 ++++++++++++------ .../src/tui/reading/fetch/histogram.rs | 29 ++--- .../src/tui/reading/fetch/history.rs | 8 +- .../sensor-tui/src/tui/reading/fetch/logs.rs | 14 +-- .../src/tui/reading/{logs2.rs => logs.rs} | 3 +- crates/sensor-tui/src/tui/render.rs | 43 +++++-- crates/sensor-tui/src/tui/render/chart.rs | 7 +- .../sensor-tui/src/tui/render/chart/labels.rs | 8 +- crates/sensor-tui/src/tui/render/logs.rs | 30 ++++- 19 files changed, 269 insertions(+), 103 deletions(-) create mode 100644 crates/sensor-tui/src/populate.rs rename crates/sensor-tui/src/tui/reading/{logs2.rs => logs.rs} (93%) diff --git a/crates/log-store/src/api.rs b/crates/log-store/src/api.rs index 0621b984..e82e033e 100644 --- a/crates/log-store/src/api.rs +++ b/crates/log-store/src/api.rs @@ -1,6 +1,6 @@ use std::time::Duration; -use protocol::Reading; +use protocol::{Device, Reading}; use serde::{Deserialize, Serialize}; @@ -15,6 +15,7 @@ pub(crate) enum Request { Handshake { name: String }, GetLog(protocol::Device), GetStats(protocol::Device), + ListDevices, } #[derive(Debug, Clone, Serialize, Deserialize, thiserror::Error)] @@ -51,13 +52,15 @@ pub struct Percentile { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ErrorEvent { pub start: jiff::Timestamp, - pub end: jiff::Timestamp, + /// if None then the error is ongoing + pub end: Option, pub error: protocol::Error, } #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) enum Response { GetLog(Result, GetLogError>), + ListDevices(Vec), GetStats(Result, GetStatsError>), Error(ServerError), Handshake, diff --git a/crates/log-store/src/api/client.rs b/crates/log-store/src/api/client.rs index 7db15d0c..79450b2c 100644 --- a/crates/log-store/src/api/client.rs +++ b/crates/log-store/src/api/client.rs @@ -1,6 +1,7 @@ use std::time::Duration; use futures::{SinkExt, TryStreamExt}; +use protocol::Device; use tokio::net::TcpStream; use tokio::net::ToSocketAddrs; use tokio::time::error::Elapsed; @@ -144,4 +145,15 @@ impl Client { }), } } + + pub async fn list_devices(&mut self) -> Result, Error> { + let request = super::Request::ListDevices; + match self.send_receive(request.clone()).await? { + Response::ListDevices(logs) => Ok(logs), + response => Err(Error::IncorrectResponse { + request: format!("{request:?}"), + response: format!("{response:?}"), + }), + } + } } diff --git a/crates/log-store/src/server/clients.rs b/crates/log-store/src/server/clients.rs index 63839987..13524be4 100644 --- a/crates/log-store/src/server/clients.rs +++ b/crates/log-store/src/server/clients.rs @@ -129,5 +129,6 @@ async fn perform_request( api::Request::Handshake { .. } => return Err(ServerError::AlreadyConnected), api::Request::GetLog(device) => api::Response::GetLog(logs.get(&device).await), api::Request::GetStats(device) => api::Response::GetStats(stats.get(&device).await), + api::Request::ListDevices => api::Response::ListDevices(logs.list_devices().await), }) } diff --git a/crates/log-store/src/server/db/log.rs b/crates/log-store/src/server/db/log.rs index ae61f84f..3f059670 100644 --- a/crates/log-store/src/server/db/log.rs +++ b/crates/log-store/src/server/db/log.rs @@ -160,7 +160,7 @@ impl Log { .map(|(start, StoredErrorEvent { end, error })| api::ErrorEvent { start: jiff::Timestamp::from_second(start as i64) .expect("was a jiff::Timestamp before it became a u64"), - end, + end: Some(end), error, }) .collect(); @@ -269,6 +269,11 @@ impl Logs { } Ok(()) } + + pub(crate) async fn list_devices(&self) -> Vec { + let map = self.0.lock().await; + map.iter().map(|(key, _)| key.clone()).collect() + } } /// relative path without extension diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index d05122c5..93499f17 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -16,7 +16,7 @@ pub(crate) use button::button_enum; #[cfg(feature = "alloc")] pub mod reading_tree; -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Unit { Pa, C, diff --git a/crates/protocol/src/reading_tree.rs b/crates/protocol/src/reading_tree.rs index 34c17bba..a3751da8 100644 --- a/crates/protocol/src/reading_tree.rs +++ b/crates/protocol/src/reading_tree.rs @@ -1,6 +1,6 @@ use crate::{Device, Reading, Unit}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ReadingInfo { pub val: f32, pub device: Device, diff --git a/crates/sensor-tui/Cargo.toml b/crates/sensor-tui/Cargo.toml index 73b00707..075d83a7 100644 --- a/crates/sensor-tui/Cargo.toml +++ b/crates/sensor-tui/Cargo.toml @@ -10,8 +10,8 @@ authors.workspace = true color-eyre = { workspace = true } crossterm = "0.27.0" hdrhistogram = "7.5" -ratatui = "0.27" -tui-tree-widget = { version = "0.21.0", git = "https://github.com/dvdsk/tui-rs-tree-widget" } +ratatui = "0.28" +tui-tree-widget = { version = "0.22.0", git = "https://github.com/dvdsk/tui-rs-tree-widget" } clap = { workspace = true } tokio = { workspace = true} diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index d7a8ed76..19f534b9 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -7,19 +7,19 @@ use color_eyre::eyre::WrapErr; use color_eyre::{Help, Result}; use data_server::SubMessage; -mod tui; mod time; +mod tui; +mod populate; enum Update { + ReadingList(Vec), Reading(protocol::Reading), Error(Box), Shutdown, + DeviceList(Vec), } -fn receive_data( - mut sub: data_server::Subscriber, - tx: mpsc::Sender>, -) { +fn receive_data(mut sub: data_server::Subscriber, tx: mpsc::Sender>) { loop { let update = sub .next_msg() @@ -37,6 +37,7 @@ fn receive_data( } } + #[derive(Parser)] #[command(name = "sensor tui")] #[command(version = "1.0")] @@ -64,7 +65,7 @@ fn main() -> Result<()> { log_store, } = Cli::parse(); - let sub = data_server::Subscriber::connect(data_server, "ha-tui") + let sub = data_server::Subscriber::connect(data_server, &client_name()) .wrap_err("failed to connect") .with_suggestion(|| format!("verify the server is listening on: {data_server}"))?; @@ -72,7 +73,9 @@ fn main() -> Result<()> { let (tx2, rx2) = mpsc::channel(); let tx1_clone = tx1.clone(); + let tx1_clone_clone = tx1.clone(); thread::spawn(move || receive_data(sub, tx1_clone)); + thread::spawn(move || populate::tree(data_store, log_store, tx1_clone_clone)); thread::spawn(move || tui::run(rx2, tx1, data_store, log_store)); loop { @@ -105,6 +108,12 @@ fn setup_tracing() -> Result<()> { Ok(()) } +fn client_name() -> String { + let host = gethostname::gethostname(); + let host = host.to_string_lossy(); + format!("sensor-tui@{host}") +} + /// Similar to the `std::dbg!` macro, but generates `tracing` events rather /// than printing to stdout. /// diff --git a/crates/sensor-tui/src/populate.rs b/crates/sensor-tui/src/populate.rs new file mode 100644 index 00000000..a4170c62 --- /dev/null +++ b/crates/sensor-tui/src/populate.rs @@ -0,0 +1,56 @@ +use std::net::SocketAddr; +use std::sync::mpsc; + +use color_eyre::Result; +use tracing::warn; + +use crate::{client_name, Update}; + +pub fn tree( + data_store_addr: SocketAddr, + log_store_addr: SocketAddr, + tx: mpsc::Sender>, +) { + let rt = tokio::runtime::Builder::new_current_thread() + .enable_io() + .enable_time() + .build() + .unwrap(); + + let (res1, res2) = rt.block_on(async { + tokio::join!( + list_from_store(data_store_addr, tx.clone()), + list_from_logs(log_store_addr, tx) + ) + }); + + if let Err(e) = res1 { + warn!("Could not populate readings list from store: {e}") + } + + if let Err(e) = res2 { + warn!("Could not populate readings list from logs: {e}") + } +} + +async fn list_from_store( + data_store_addr: SocketAddr, + tx: mpsc::Sender>, +) -> Result<()> { + let mut client = data_store::api::Client::connect(data_store_addr, client_name()).await?; + let list = client.list_data().await?; + tracing::debug!("list: {list:?}"); + tx.send(Ok(Update::ReadingList(list))).unwrap(); + Ok(()) +} + +async fn list_from_logs( + log_store_addr: SocketAddr, + tx: mpsc::Sender>, +) -> Result<()> { + let mut client = log_store::api::Client::connect(log_store_addr, client_name()).await?; + let list = client.list_devices().await?; + tracing::debug!("list: {list:?}"); + tx.send(Ok(Update::DeviceList(list))).unwrap(); + Ok(()) +} diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index 92b9f8f6..87a3c561 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -167,6 +167,12 @@ impl App { Ok(Update::Reading(reading)) => { readings.add(reading); } + Ok(Update::ReadingList(list)) => { + readings.populate_from_reading_list(list); + } + Ok(Update::DeviceList(list)) => { + readings.populate_from_device_list(list); + } Ok(Update::Error(err)) => readings.add_error(err), _ => (), } diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index 5e42ed12..0d8a86ca 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -4,8 +4,8 @@ use jiff::Unit; use log_store::api::ErrorEvent; use protocol::reading_tree::ReadingInfo; use protocol::reading_tree::{Item, Tree}; -use protocol::Error; use protocol::Reading; +use protocol::{Device, Error}; use ratatui::{text::Line, widgets::Bar}; use std::collections::HashMap; @@ -13,20 +13,23 @@ use std::sync::TryLockError; use tui_tree_widget::TreeItem; mod fetch; -use fetch::{histogram, history, logs}; +use fetch::{histogram, history}; -mod logs2; +mod logs; #[derive(Debug)] pub struct SensorInfo { + pub info: ReadingInfo, + /// This value is not up to date, only use for requesting + /// data use the last element of recent_history for printing pub reading: Reading, timing: Histogram, pub percentiles_from_store: histogram::Stored, recent_history: Vec<(jiff::Timestamp, f32)>, pub history_from_store: history::Stored, condition: Result<(), Box>, - logs: logs2::Logs, - pub logs_from_store: logs::Stored, + logs: logs::Logs, + pub logs_from_store: fetch::logs::Stored, } pub struct ErrorDensity { @@ -38,7 +41,7 @@ pub struct ErrorDensity { } impl ErrorDensity { - fn from_log(log: &logs2::Logs) -> Self { + fn from_log(log: &logs::Logs) -> Self { let buckets = [5, 15, 30, 45, 60].map(|min| jiff::Span::new().minutes(min)); let counts = log.density(buckets); @@ -60,30 +63,20 @@ pub struct Details { } impl SensorInfo { - fn last_at(&self) -> Result> { - self.condition.clone()?; - - let last = self - .recent_history - .last() - .expect("Items are put in the map when they arrive with a value"); - Ok(last.0) + fn last_at(&self) -> Option { + self.condition.clone().ok(); + self.recent_history.last().map(|(ts, _)| ts).copied() } pub fn details(&self) -> Details { let last_reading = self.recent_history.last().copied().map(|(ts, val)| { - let val = format!( - "{0:.1$} {2}", - val, - self.reading.leaf().precision(), - self.reading.leaf().unit - ); + let val = format!("{0:.1$} {2}", val, self.info.precision(), self.info.unit); (ts, val) }); Details { last_reading, condition: self.condition.clone(), - description: self.reading.leaf().description.to_owned(), + description: self.info.description.to_owned(), errors_since: ErrorDensity::from_log(&self.logs), } } @@ -155,7 +148,7 @@ impl SensorInfo { } Some(ChartParts { - reading: self.reading.clone(), + reading: self.info.clone(), data: plot_buf, }) } @@ -254,12 +247,31 @@ fn extract_leaf_info(reading: &Reading) -> (TreeKey, String, f32) { unreachable!("reading should not be deeper then key size") } +enum IsPlaceholder { + Yes, + No, +} + impl Readings { pub fn add(&mut self, reading: Reading) { - self.update_tree(&reading); + self.update_tree(&reading, IsPlaceholder::No); self.record_data(reading); } + pub(crate) fn populate_from_reading_list(&mut self, list: Vec) { + for reading in list { + self.update_tree(&reading, IsPlaceholder::Yes); + self.record_missing_data(reading); + } + } + + pub(crate) fn populate_from_device_list(&mut self, list: Vec) { + for reading in list.iter().flat_map(|d| d.info().affects_readings) { + self.update_tree(&reading, IsPlaceholder::Yes); + self.record_missing_data(reading.clone()); + } + } + pub fn add_error(&mut self, error: Box) { self.update_tree_err(&error); self.record_error(error); @@ -273,10 +285,11 @@ impl Readings { info.condition = Err(error.clone()); info.logs.add(&error); } else { - let errors = logs2::Logs::new_from(&error); + let errors = logs::Logs::new_from(&error); self.data.insert( key, SensorInfo { + info: broken.leaf(), reading: broken.clone(), timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), percentiles_from_store: histogram::Stored::new(), @@ -298,7 +311,7 @@ impl Readings { let time = jiff::Timestamp::now(); if let Some(info) = self.data.get_mut(&key) { - if let Ok(last_reading) = info.last_at() { + if let Some(last_reading) = info.last_at() { info.timing += (time - last_reading) .total(Unit::Millisecond) .expect("no calander units involved") as u64 @@ -310,6 +323,7 @@ impl Readings { self.data.insert( key, SensorInfo { + info: reading.leaf(), reading, timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), percentiles_from_store: histogram::Stored::new(), @@ -319,13 +333,37 @@ impl Readings { logs_from_store: fetch::logs::Stored::new(), condition: Ok(()), - logs: logs2::Logs::new_empty(), + logs: logs::Logs::new_empty(), }, ); } } - fn update_tree(&mut self, reading: &Reading) { + fn record_missing_data(&mut self, reading: Reading) { + let (key, _, _) = extract_leaf_info(&reading); + if self.data.contains_key(&key) { + return; + } + + self.data.insert( + key, + SensorInfo { + info: reading.leaf(), + reading, + timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), + percentiles_from_store: histogram::Stored::new(), + + recent_history: Vec::new(), + history_from_store: history::Stored::new(), + logs_from_store: fetch::logs::Stored::new(), + + condition: Ok(()), + logs: logs::Logs::new_empty(), + }, + ); + } + + fn update_tree(&mut self, reading: &Reading, placeholder: IsPlaceholder) { let (key, _, _) = extract_leaf_info(reading); let mut tree = add_root(reading as &dyn Tree, &mut self.ground); @@ -336,13 +374,17 @@ impl Readings { loop { match tomato.inner() { Item::Leaf(info) => { - let text = format!( - "{0}: {1:.2$} {3}", - tomato.name(), - info.val, - info.precision(), - info.unit - ); + let text = if let IsPlaceholder::Yes = placeholder { + tomato.name() + } else { + format!( + "{0}: {1:.2$} {3}", + tomato.name(), + info.val, + info.precision(), + info.unit + ) + }; add_leaf(text, tree, key); return; } @@ -381,7 +423,7 @@ impl Readings { } pub struct ChartParts<'a> { - pub reading: Reading, + pub reading: ReadingInfo, pub data: &'a [(f64, f64)], } diff --git a/crates/sensor-tui/src/tui/reading/fetch/histogram.rs b/crates/sensor-tui/src/tui/reading/fetch/histogram.rs index c253a285..c15361a3 100644 --- a/crates/sensor-tui/src/tui/reading/fetch/histogram.rs +++ b/crates/sensor-tui/src/tui/reading/fetch/histogram.rs @@ -7,8 +7,9 @@ use log_store::api::Percentile; use protocol::Device; use tokio::sync::Notify; use tokio::time::sleep; -use tracing::{debug, warn}; +use tracing::warn; +use crate::client_name; use crate::tui::history_len::{self, HistoryLen}; use super::Fetching; @@ -36,10 +37,8 @@ impl Stored { if let Some(in_progress) = self.last_fetch.take() { in_progress.cancel.notify_one(); let _ = in_progress.handle.join(); - debug!("Canceled running stored-history update"); } - debug!("Started histogram fetch"); let device = device.clone(); let cancel = Arc::new(Notify::new()); let cancelled = cancel.clone(); @@ -60,7 +59,12 @@ impl Stored { needed_hist: &mut HistoryLen, ) { if let Some(last_fetch) = &mut self.last_fetch { - if last_fetch.history_length != needed_hist.dur || self.outdated() { + let outdated = self.last_update_started.elapsed() > Duration::from_secs(5) + || self.data.lock().unwrap().is_empty(); + let finished = last_fetch.handle.is_finished(); + let params_changed = last_fetch.history_length != needed_hist.dur; + + if params_changed || (outdated && finished) { self.start_update(device, needed_hist.dur, log_store); needed_hist.state = history_len::State::Fetching(Instant::now()); } @@ -76,11 +80,6 @@ impl Stored { } } - pub(crate) fn outdated(&self) -> bool { - self.data.lock().unwrap().is_empty() - || self.last_update_started.elapsed() > Duration::from_secs(5) - } - pub(crate) fn very_outdated(&self) -> bool { self.data.lock().unwrap().is_empty() || self.last_update_started.elapsed() > Duration::from_secs(15) @@ -106,7 +105,6 @@ fn fetch( _ = cancelled.notified() => None, } }) else { - debug!("Canceled data fetch"); return; }; @@ -124,15 +122,12 @@ async fn connect_and_get_percentiles( sleep(retry_period).await; retry_period = Duration::from_secs(5) .min(retry_period * 2) - .min(Duration::from_millis(100)); + .max(Duration::from_millis(100)); - let host = gethostname::gethostname(); - let host = host.to_string_lossy(); - let name = format!("sensor-tui@{host}"); - let mut api = match log_store::api::Client::connect(addr, name).await { + let mut api = match log_store::api::Client::connect(addr, client_name()).await { Ok(api) => api, Err(e) => { - warn!("Could not connect to data_store (at {addr}): {e}"); + warn!("Could not connect to log_store (at {addr}): {e}"); continue; } }; @@ -140,7 +135,7 @@ async fn connect_and_get_percentiles( match api.get_percentiles(device.clone()).await { Ok(res) => return res, Err(e) => { - warn!("Error getting data from data-store, reconnecting: {e}"); + warn!("Error getting data from log-store, reconnecting: {e}"); continue; } }; diff --git a/crates/sensor-tui/src/tui/reading/fetch/history.rs b/crates/sensor-tui/src/tui/reading/fetch/history.rs index 5dec44dd..0aa4fa1a 100644 --- a/crates/sensor-tui/src/tui/reading/fetch/history.rs +++ b/crates/sensor-tui/src/tui/reading/fetch/history.rs @@ -8,6 +8,7 @@ use tokio::sync::Notify; use tokio::time::sleep; use tracing::{debug, warn}; +use crate::client_name; use crate::tui::history_len::{self, HistoryLen}; use super::Fetching; @@ -117,12 +118,9 @@ async fn connect_and_get_data( sleep(retry_period).await; retry_period = Duration::from_secs(5) .min(retry_period * 2) - .min(Duration::from_millis(100)); + .max(Duration::from_millis(100)); - let host = gethostname::gethostname(); - let host = host.to_string_lossy(); - let name = format!("sensor-tui@{host}"); - let mut api = match data_store::api::Client::connect(addr, name).await { + let mut api = match data_store::api::Client::connect(addr, client_name()).await { Ok(api) => api, Err(e) => { warn!("Could not connect to data_store (at {addr}): {e}"); diff --git a/crates/sensor-tui/src/tui/reading/fetch/logs.rs b/crates/sensor-tui/src/tui/reading/fetch/logs.rs index e0e80df4..e7db5511 100644 --- a/crates/sensor-tui/src/tui/reading/fetch/logs.rs +++ b/crates/sensor-tui/src/tui/reading/fetch/logs.rs @@ -9,6 +9,7 @@ use tokio::sync::Notify; use tokio::time::sleep; use tracing::{debug, warn}; +use crate::client_name; use crate::tui::history_len::{self, HistoryLen}; use super::Fetching; @@ -37,7 +38,7 @@ impl Stored { if let Some(in_progress) = self.last_fetch.take() { in_progress.cancel.notify_one(); let _ = in_progress.handle.join(); - debug!("Canceled running stored-history update"); + debug!("Canceled running stored-logs update"); } let reading = reading.clone(); @@ -113,15 +114,12 @@ async fn connect_and_get_data( sleep(retry_period).await; retry_period = Duration::from_secs(5) .min(retry_period * 2) - .min(Duration::from_millis(100)); + .max(Duration::from_millis(100)); - let host = gethostname::gethostname(); - let host = host.to_string_lossy(); - let name = format!("sensor-tui@{host}"); - let mut api = match log_store::api::Client::connect(addr, name).await { + let mut api = match log_store::api::Client::connect(addr, client_name()).await { Ok(api) => api, Err(e) => { - warn!("Could not connect to data_store (at {addr}): {e}"); + warn!("Could not connect to log_store (at {addr}): {e}"); continue; } }; @@ -129,7 +127,7 @@ async fn connect_and_get_data( match api.get_logs(reading.device()).await { Ok(res) => return res, Err(e) => { - warn!("Error getting data from data-store, reconnecting: {e}"); + warn!("Error getting data from log-store, reconnecting: {e}"); continue; } }; diff --git a/crates/sensor-tui/src/tui/reading/logs2.rs b/crates/sensor-tui/src/tui/reading/logs.rs similarity index 93% rename from crates/sensor-tui/src/tui/reading/logs2.rs rename to crates/sensor-tui/src/tui/reading/logs.rs index fb9bbe83..43c1bf15 100644 --- a/crates/sensor-tui/src/tui/reading/logs2.rs +++ b/crates/sensor-tui/src/tui/reading/logs.rs @@ -26,7 +26,7 @@ impl Logs { if let Some((started, event)) = self.current.take() { self.history.push(api::ErrorEvent { start: started, - end: jiff::Timestamp::now(), + end: Some(jiff::Timestamp::now()), error: event, }) } @@ -41,6 +41,7 @@ impl Logs { for (bound, count) in &mut buckets { let bound_start = now - *bound; let start = start.max(&bound_start); + let end = if let Some(end) = end { end } else { &now }; let error_time = end.since(*start).expect("duration should fit type"); if !error_time.is_negative() { *count += error_time.total(Unit::Second).expect("smaller then day") diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs index dec0b87d..4ff5e297 100644 --- a/crates/sensor-tui/src/tui/render.rs +++ b/crates/sensor-tui/src/tui/render.rs @@ -1,4 +1,5 @@ use jiff::Timestamp; +use log_store::api::ErrorEvent; use ratatui::{ self, layout::{Alignment, Constraint, Direction, Flex, Layout, Rect}, @@ -7,6 +8,7 @@ use ratatui::{ widgets::{self, Bar, BarChart, BarGroup, Block, Borders, Tabs}, Frame, }; +use tracing::debug; use tui_tree_widget::{Tree, TreeItem}; use super::{ @@ -24,13 +26,13 @@ pub(crate) fn app( affectors: &[TreeItem<'static, TreeKey>], details: Option
, chart: Option, - logs: Option>, + logs: Option>, histogram: &[Bar], ) { let [list_constraint, graph_constraint] = if chart.is_some() { let tree_height = 2 + app.reading_tree_state.flatten(readings).len(); let details_height = 9; - if (frame.size().height as f32) / 3. > tree_height as f32 { + if (frame.area().height as f32) / 3. > tree_height as f32 { [ Constraint::Min(tree_height.max(details_height) as u16), Constraint::Percentage(100), @@ -42,7 +44,7 @@ pub(crate) fn app( [Constraint::Percentage(100), Constraint::Percentage(100)] }; - let area = frame.size(); + let area = frame.area(); let [top_line, top, bottom, footer] = Layout::vertical([ Constraint::Min(1), list_constraint, @@ -56,8 +58,11 @@ pub(crate) fn app( match app.active_tab { ActiveTab::Readings => { + let have_details = details.is_some(); render_readings_and_details(frame, top, app, readings, details); - render_graph_hist_logs(frame, bottom, app, histogram, logs, chart); + if have_details { + render_graph_hist_logs(frame, bottom, app, histogram, logs, chart); + } } ActiveTab::Affectors => render_affectors(frame, top, app, affectors), } @@ -108,11 +113,10 @@ fn render_graph_hist_logs( layout: Rect, app: &mut App, histogram: &[Bar], - logs: Option>, + logs: Option>, chart: Option, ) { - let logs = app.show_logs.then(|| logs).flatten(); - let num_elems = chart.is_some() as u8 + app.show_histogram as u8 + logs.is_some() as u8; + let num_elems = 1u8 + app.show_histogram as u8 + app.show_logs as u8; let layout = Layout::default() .direction(Direction::Vertical) @@ -120,23 +124,29 @@ fn render_graph_hist_logs( .flex(Flex::Legacy) .split(layout); - let mut layout = layout.into_iter(); + let mut layout = layout.into_iter().cloned(); if let Some(chart) = chart { - chart::render(frame, layout.next().unwrap().clone(), app, chart); + chart::render(frame, layout.next().unwrap(), app, chart); + } else { + centered_text("No data", frame, layout.next().unwrap()) } - if let Some(logs) = logs { + if app.show_logs { logs::render( frame, - layout.next().unwrap().clone(), + layout.next().unwrap(), &mut app.logs_table_state, logs, ) } if app.show_histogram { - render_histogram(frame, layout.next().unwrap().clone(), histogram); + if histogram.is_empty() { + centered_text("No timing information", frame, layout.next().unwrap()) + } else { + render_histogram(frame, layout.next().unwrap(), histogram); + } } } @@ -208,7 +218,7 @@ fn render_details(frame: &mut Frame, layout: Rect, details: Details) { t45_min, t60_min, } = errors_since; - let errors_since = format!("errors in the past:\n5min: {t5_min}, 15min: {t15_min}, 30min: {t30_min}, 45min {t45_min}, 60m: {t60_min}"); + let errors_since = format!("errors in the past:\n5min: {t5_min:.2}, 15min: {t15_min:.2}, 30min: {t30_min:.2}, 45min {t45_min:.2}, 60m: {t60_min:.2}"); let text = format!("{description}\n{last_reading}\n{condition}{errors_since}"); frame.render_widget( @@ -239,3 +249,10 @@ fn render_affectors( &mut app.affector_tree_state, ); } + +fn centered_text(text: &str, frame: &mut Frame, area: Rect) { + let footer = Text::raw(text) + .alignment(Alignment::Center) + .style(Style::new().bg(Color::Gray)); + frame.render_widget(footer, area) +} diff --git a/crates/sensor-tui/src/tui/render/chart.rs b/crates/sensor-tui/src/tui/render/chart.rs index a3de6f99..5da3b63a 100644 --- a/crates/sensor-tui/src/tui/render/chart.rs +++ b/crates/sensor-tui/src/tui/render/chart.rs @@ -1,4 +1,3 @@ -use protocol::reading_tree::Tree; use ratatui::{ layout::{Alignment, Rect}, style::Style, @@ -35,7 +34,7 @@ pub fn render(frame: &mut Frame, layout: Rect, app: &mut App, chart: ChartParts) .labels(x_labels) .labels_alignment(Alignment::Center); let y_axis = Axis::default() - .title(chart.reading.leaf().unit.to_string()) + .title(chart.reading.unit.to_string()) .style(Style::default()) .bounds(y_bounds) .labels(y_labels); @@ -63,8 +62,8 @@ fn bounds(chart: &ChartParts, layout: Rect) -> (Bounds, Bounds) { let y_range = y_bounds[1] - y_bounds[0]; let margin = 5.0 / layout.height as f64; - let range = chart.reading.leaf().range; - let resolution = chart.reading.resolution() as f64; + let range = &chart.reading.range; + let resolution = chart.reading.resolution as f64; let y_margin = f64::max(y_range * margin, resolution / 2.0); let y_bounds = [y_bounds[0] - y_margin, y_bounds[1] + y_margin]; let y_bounds = [ diff --git a/crates/sensor-tui/src/tui/render/chart/labels.rs b/crates/sensor-tui/src/tui/render/chart/labels.rs index 51c85f85..d068980d 100644 --- a/crates/sensor-tui/src/tui/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/render/chart/labels.rs @@ -1,4 +1,4 @@ -use protocol::reading_tree::{ReadingInfo, Tree}; +use protocol::reading_tree::ReadingInfo; use ratatui::layout::Rect; use ratatui::text::Span; @@ -15,15 +15,15 @@ pub fn labels<'a>( y_bounds: Bounds, ) -> (Labels, Labels) { let y_label_spacing = 10; - let info = chart.reading.leaf(); + let info = &chart.reading; // characters are about twice as high as wide - let x = evenly_spaced_labels(layout.width / y_label_spacing / 2, &info, x_bounds) + let x = evenly_spaced_labels(layout.width / y_label_spacing / 2, info, x_bounds) .rev() .map(crate::time::format::fmt_seconds) .map(Into::into) .collect(); - let y = evenly_spaced_labels(layout.height / y_label_spacing, &info, y_bounds) + let y = evenly_spaced_labels(layout.height / y_label_spacing, info, y_bounds) .map(|y| format!("{0:.1$}", y, info.precision()).into()) .collect(); diff --git a/crates/sensor-tui/src/tui/render/logs.rs b/crates/sensor-tui/src/tui/render/logs.rs index b419f00b..cc517d03 100644 --- a/crates/sensor-tui/src/tui/render/logs.rs +++ b/crates/sensor-tui/src/tui/render/logs.rs @@ -5,7 +5,26 @@ use ratatui::text::Text; use ratatui::widgets::{Cell, HighlightSpacing, Row, Table, TableState}; use ratatui::Frame; +use super::centered_text; + pub fn render( + frame: &mut Frame, + layout: Rect, + table_state: &mut TableState, + logs: Option>, +) { + if let Some(logs) = logs { + if logs.is_empty() { + centered_text("Logs are empty", frame, layout) + } else { + render_table(frame, layout, table_state, logs) + } + } else { + centered_text("No logs", frame, layout) + } +} + +pub fn render_table( frame: &mut Frame, layout: Rect, table_state: &mut TableState, @@ -28,10 +47,15 @@ pub fn render( .enumerate() .map(|(i, ErrorEvent { start, end, error })| { let color = match i % 2 { - 0 => Color::DarkGray, - _ => Color::Gray, + 0 => Color::Gray, + _ => Color::White, + }; + let end = if let Some(timestamp) = end { + format!("{timestamp}") + } else { + "ongoing".to_owned() }; - let item = [format!("{error}"), format!("{start}"), format!("{end}")]; + let item = [format!("{error}"), format!("{start}"), end]; item.into_iter() .map(|content| Text::from(content)) .map(|content| Cell::from(content)) From aae2656050c935188be6cf593737e4524ac7df02 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 13 Aug 2024 23:06:41 +0200 Subject: [PATCH 190/687] fix typo + cargo update --- Cargo.lock | 364 +++++++++++++--------- crates/protocol/src/large_bedroom/desk.rs | 2 +- 2 files changed, 225 insertions(+), 141 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ebb599a9..41319279 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", @@ -76,33 +76,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -168,7 +168,7 @@ checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ "async-channel 2.3.1", "async-executor", - "async-io 2.3.3", + "async-io 2.3.4", "async-lock 3.4.0", "blocking", "futures-lite 2.3.0", @@ -197,9 +197,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.3" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" dependencies = [ "async-lock 3.4.0", "cfg-if 1.0.0", @@ -207,11 +207,11 @@ dependencies = [ "futures-io", "futures-lite 2.3.0", "parking", - "polling 3.7.2", + "polling 3.7.3", "rustix 0.38.34", "slab", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -253,11 +253,11 @@ dependencies = [ [[package]] name = "async-signal" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb3634b73397aa844481f814fad23bbf07fdb0eabec10f2eb95e58944b1ec32" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" dependencies = [ - "async-io 2.3.3", + "async-io 2.3.4", "async-lock 3.4.0", "atomic-waker", "cfg-if 1.0.0", @@ -266,7 +266,7 @@ dependencies = [ "rustix 0.38.34", "signal-hook-registry", "slab", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -332,7 +332,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -415,7 +415,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -558,9 +558,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "byteseries" @@ -571,7 +571,7 @@ dependencies = [ "num-traits", "ron", "serde", - "smallvec 2.0.0-alpha.6", + "smallvec 2.0.0-alpha.7", "thiserror", "tracing", ] @@ -599,9 +599,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.6" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" +checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292" [[package]] name = "cfg-if" @@ -632,9 +632,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.9" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" +checksum = "11d8838454fda655dafd3accb2b6e2bea645b9e4078abe84a22ceb947235c5cc" dependencies = [ "clap_builder", "clap_derive", @@ -642,9 +642,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.9" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstream", "anstyle", @@ -654,21 +654,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.8" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] name = "clap_lex" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "clipboard-win" @@ -716,19 +716,20 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "compact_str" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" +checksum = "6050c3a16ddab2e412160b31f2c871015704239bca62f72f6e5f0be631d3f644" dependencies = [ "castaway", "cfg-if 1.0.0", "itoa", + "rustversion", "ryu", "static_assertions", ] @@ -776,9 +777,9 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "crc32fast" @@ -835,6 +836,22 @@ dependencies = [ "winapi", ] +[[package]] +name = "crossterm" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" +dependencies = [ + "bitflags 2.6.0", + "crossterm_winapi", + "mio 1.0.2", + "parking_lot 0.12.3", + "rustix 0.38.34", + "signal-hook", + "signal-hook-mio", + "winapi", +] + [[package]] name = "crossterm_winapi" version = "0.9.1" @@ -891,7 +908,7 @@ dependencies = [ "protocol", "reserve-port", "serde", - "smallvec 2.0.0-alpha.6", + "smallvec 2.0.0-alpha.7", "temp-dir", "thiserror", "tokio", @@ -922,7 +939,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -953,7 +970,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -974,6 +991,16 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "diatomic-waker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92a510eb4dc7fa435297888c00e0f999aa2ee3e920a357221c35ab615a80bbcf" +dependencies = [ + "loom", + "waker-fn", +] + [[package]] name = "dirs" version = "5.0.1" @@ -1035,7 +1062,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -1098,7 +1125,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -1217,9 +1244,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" dependencies = [ "crc32fast", "miniz_oxide", @@ -1273,12 +1300,12 @@ dependencies = [ [[package]] name = "futures-buffered" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02dcae03ee5afa5ea17b1aebc793806b8ddfc6dc500e0b8e8e1eb30b9dad22c0" +checksum = "91fa130f3777d0d4b0993653c20bc433026d3290627693c4ed1b18dd237357ab" dependencies = [ + "diatomic-waker", "futures-core", - "futures-util", "pin-project-lite", ] @@ -1366,7 +1393,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -1414,6 +1441,19 @@ dependencies = [ "byteorder", ] +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows", +] + [[package]] name = "gethostname" version = "0.5.0" @@ -1718,9 +1758,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" dependencies = [ "bytes", "futures-channel", @@ -1789,14 +1829,24 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "2.2.6" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" dependencies = [ "equivalent", "hashbrown", ] +[[package]] +name = "instability" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" +dependencies = [ + "quote", + "syn 2.0.74", +] + [[package]] name = "instant" version = "0.1.13" @@ -1841,9 +1891,9 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" @@ -1862,9 +1912,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jiff" -version = "0.1.0" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fbd74d242eb38b2f0d73c9ad5e7e4371525d856e64018939874380494ce4ed6" +checksum = "a2e918a22c40c7671d8e7d3495983f54a3b13e63cb09e1f51f2729fa35cf108f" dependencies = [ "jiff-tzdb-platform", "serde", @@ -1888,9 +1938,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -1995,7 +2045,7 @@ dependencies = [ "protocol", "reserve-port", "serde", - "smallvec 2.0.0-alpha.6", + "smallvec 2.0.0-alpha.7", "temp-dir", "thiserror", "tokio", @@ -2006,11 +2056,24 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if 1.0.0", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + [[package]] name = "lru" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" dependencies = [ "hashbrown", ] @@ -2127,12 +2190,13 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi 0.3.9", "libc", + "log", "wasi", "windows-sys 0.52.0", ] @@ -2446,7 +2510,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -2463,9 +2527,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", "fastrand 2.1.0", @@ -2490,9 +2554,9 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.2" +version = "3.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" dependencies = [ "cfg-if 1.0.0", "concurrent-queue", @@ -2500,7 +2564,7 @@ dependencies = [ "pin-project-lite", "rustix 0.38.34", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2542,9 +2606,12 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro-error" @@ -2689,18 +2756,18 @@ dependencies = [ [[package]] name = "ratatui" -version = "0.27.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16546c5b5962abf8ce6e2881e722b4e0ae3b6f1a08a26ae3573c55853ca68d3" +checksum = "5ba6a365afbe5615999275bea2446b970b10a41102500e27ce7678d50d978303" dependencies = [ "bitflags 2.6.0", "cassowary", "compact_str", - "crossterm", + "crossterm 0.28.1", + "instability", "itertools", "lru", "paste", - "stability", "strum", "strum_macros", "unicode-segmentation", @@ -2748,9 +2815,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.5" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -2925,6 +2992,12 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -2943,7 +3016,7 @@ version = "0.0.0" dependencies = [ "clap", "color-eyre", - "crossterm", + "crossterm 0.27.0", "data-server", "data-store", "gethostname", @@ -2963,31 +3036,32 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.204" +version = "1.0.207" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "5665e14a49a4ea1b91029ba7d3bca9f299e1f7cfa194388ccc20f14743e784f2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.207" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "6aea2634c86b0e8ef2cfdc0c340baede54ec27b1e46febd7f80dffb2aa44a00e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] name = "serde_json" -version = "1.0.120" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -3019,9 +3093,9 @@ dependencies = [ [[package]] name = "serialport" -version = "4.4.0" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de7c4f0cce25b9b3518eea99618112f9ee4549f974480c8f43d3c06f03c131a0" +checksum = "241ebb629ed9bf598b2b392ba42aa429f9ef2a0099001246a36ac4c084ee183f" dependencies = [ "bitflags 2.6.0", "cfg-if 1.0.0", @@ -3029,7 +3103,6 @@ dependencies = [ "io-kit-sys", "mach2", "nix 0.26.4", - "regex", "scopeguard", "unescaper", "winapi", @@ -3056,12 +3129,13 @@ dependencies = [ [[package]] name = "signal-hook-mio" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" dependencies = [ "libc", "mio 0.8.11", + "mio 1.0.2", "signal-hook", ] @@ -3107,9 +3181,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smallvec" -version = "2.0.0-alpha.6" +version = "2.0.0-alpha.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66778689f64ae4f4e9365890e55048783afc0bb07a8e214b0bcfe7b88e6bb2bf" +checksum = "e6a96cb564e12be8458b004bd829787ebe887de197d94516d2ba5a2a32235a0c" [[package]] name = "socket2" @@ -3160,16 +3234,6 @@ dependencies = [ "lock_api", ] -[[package]] -name = "stability" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" -dependencies = [ - "quote", - "syn 2.0.72", -] - [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -3213,7 +3277,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -3229,9 +3293,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.72" +version = "2.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" dependencies = [ "proc-macro2", "quote", @@ -3300,7 +3364,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -3360,14 +3424,14 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.0" +version = "1.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3318c4fc7126c339a40fbc025927d0328ca32259f68bfe4321660644c1f626" +checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" dependencies = [ "backtrace", "bytes", "libc", - "mio 1.0.1", + "mio 1.0.2", "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", @@ -3384,7 +3448,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -3443,15 +3507,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -3472,7 +3536,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -3543,8 +3607,8 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tui-tree-widget" -version = "0.21.0" -source = "git+https://github.com/dvdsk/tui-rs-tree-widget#5db19b1895383f79d63810ea8a798dc9ccd89805" +version = "0.22.0" +source = "git+https://github.com/dvdsk/tui-rs-tree-widget#2c8d29d9a5439c82d46a276b4ae6e8f6b2049f9d" dependencies = [ "ratatui", "unicode-width", @@ -3664,9 +3728,9 @@ checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "waker-fn" @@ -3691,34 +3755,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if 1.0.0", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -3728,9 +3793,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3738,28 +3803,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", @@ -3787,6 +3852,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -3814,6 +3888,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -3960,6 +4043,7 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] @@ -3971,5 +4055,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index 362a51a3..fa35e02e 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -63,7 +63,7 @@ impl Tree for Reading { resolution: 0.008, range: 0.0..100.0, unit: Unit::RH, - description: "Temperature", + description: "Humidity", branch_id: self.branch_id(), }, Reading::Pressure(val) => ReadingInfo { From db8ab515e0e6aec033158972088938593f5b14d5 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 13 Aug 2024 23:10:23 +0200 Subject: [PATCH 191/687] update more deps --- Cargo.lock | 40 ++++++------------------------------ Cargo.toml | 2 +- crates/sensor-tui/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 41319279..0cf7cecf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -565,6 +565,7 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "byteseries" version = "0.5.0" +source = "git+https://github.com/dvdsk/byteseries#9c724e34ccd908c31bf1047ffe7c6a7bb55a51f7" dependencies = [ "arraydeque", "itertools", @@ -820,22 +821,6 @@ version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" -[[package]] -name = "crossterm" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" -dependencies = [ - "bitflags 2.6.0", - "crossterm_winapi", - "libc", - "mio 0.8.11", - "parking_lot 0.12.3", - "signal-hook", - "signal-hook-mio", - "winapi", -] - [[package]] name = "crossterm" version = "0.28.1" @@ -844,7 +829,7 @@ checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ "bitflags 2.6.0", "crossterm_winapi", - "mio 1.0.2", + "mio", "parking_lot 0.12.3", "rustix 0.38.34", "signal-hook", @@ -2176,18 +2161,6 @@ dependencies = [ "adler", ] -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.48.0", -] - [[package]] name = "mio" version = "1.0.2" @@ -2763,7 +2736,7 @@ dependencies = [ "bitflags 2.6.0", "cassowary", "compact_str", - "crossterm 0.28.1", + "crossterm", "instability", "itertools", "lru", @@ -3016,7 +2989,7 @@ version = "0.0.0" dependencies = [ "clap", "color-eyre", - "crossterm 0.27.0", + "crossterm", "data-server", "data-store", "gethostname", @@ -3134,8 +3107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" dependencies = [ "libc", - "mio 0.8.11", - "mio 1.0.2", + "mio", "signal-hook", ] @@ -3431,7 +3403,7 @@ dependencies = [ "backtrace", "bytes", "libc", - "mio 1.0.2", + "mio", "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", diff --git a/Cargo.toml b/Cargo.toml index 330830d1..7fafe2ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ data-store = { path = "crates/data-store" } log-store = { path = "crates/log-store" } protocol = { path = "crates/protocol" } -byteseries = { path = "../byteseries" } +byteseries = { git = "https://github.com/dvdsk/byteseries" } tokio = "1.38" color-eyre = "0.6.3" diff --git a/crates/sensor-tui/Cargo.toml b/crates/sensor-tui/Cargo.toml index 075d83a7..58377c3e 100644 --- a/crates/sensor-tui/Cargo.toml +++ b/crates/sensor-tui/Cargo.toml @@ -8,7 +8,7 @@ authors.workspace = true [dependencies] color-eyre = { workspace = true } -crossterm = "0.27.0" +crossterm = "0.28" hdrhistogram = "7.5" ratatui = "0.28" tui-tree-widget = { version = "0.22.0", git = "https://github.com/dvdsk/tui-rs-tree-widget" } From bd23073818523bf3743bc740399acb8bcc3a9f4f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 14 Aug 2024 02:03:33 +0200 Subject: [PATCH 192/687] show ongoing error in log table --- crates/sensor-tui/src/tui.rs | 1 + crates/sensor-tui/src/tui/reading.rs | 1 - crates/sensor-tui/src/tui/reading/logs.rs | 27 ++++++--- crates/sensor-tui/src/tui/render.rs | 68 ++++++++++++++++++----- crates/sensor-tui/src/tui/render/logs.rs | 29 +++++++--- 5 files changed, 96 insertions(+), 30 deletions(-) diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index 87a3c561..30bb0fd4 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -61,6 +61,7 @@ pub fn run( #[derive(Default)] struct App { + theme: render::Theme, input_mode: InputMode, active_tab: ActiveTab, show_histogram: bool, diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index 0d8a86ca..fc71ddac 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -162,7 +162,6 @@ impl SensorInfo { let without_duplicates = self .logs .list() - .iter() .skip_while(|ErrorEvent { start, .. }| start < &last) .cloned(); logs.extend(without_duplicates); diff --git a/crates/sensor-tui/src/tui/reading/logs.rs b/crates/sensor-tui/src/tui/reading/logs.rs index 43c1bf15..32ba9e6e 100644 --- a/crates/sensor-tui/src/tui/reading/logs.rs +++ b/crates/sensor-tui/src/tui/reading/logs.rs @@ -1,16 +1,23 @@ +use std::iter; + use jiff::Unit; use log_store::api::{self, ErrorEvent}; #[derive(Debug)] pub(crate) struct Logs { - current: Option<(jiff::Timestamp, protocol::Error)>, + current: Option, + /// newest items at the end history: Vec, } impl Logs { pub(crate) fn new_from(error: &protocol::Error) -> Self { Self { - current: Some((jiff::Timestamp::now(), error.clone())), + current: Some(ErrorEvent { + start: jiff::Timestamp::now(), + end: None, + error: error.clone(), + }), history: Vec::new(), } } @@ -23,15 +30,19 @@ impl Logs { } pub(crate) fn add(&mut self, error: &protocol::Error) { - if let Some((started, event)) = self.current.take() { + if let Some(ErrorEvent { start, error, .. }) = self.current.take() { self.history.push(api::ErrorEvent { - start: started, + start, end: Some(jiff::Timestamp::now()), - error: event, + error, }) } - self.current = Some((jiff::Timestamp::now(), error.clone())) + self.current = Some(ErrorEvent { + start: jiff::Timestamp::now(), + end: None, + error: error.clone(), + }) } pub(crate) fn density(&self, buckets: [jiff::Span; N]) -> [f32; N] { @@ -52,7 +63,7 @@ impl Logs { buckets.map(|(_, count)| count as f32) } - pub(crate) fn list(&self) -> &[api::ErrorEvent] { - &self.history + pub(crate) fn list(&self) -> impl Iterator { + self.history.iter().chain(self.current.iter()) } } diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs index 4ff5e297..ce120887 100644 --- a/crates/sensor-tui/src/tui/render.rs +++ b/crates/sensor-tui/src/tui/render.rs @@ -8,7 +8,6 @@ use ratatui::{ widgets::{self, Bar, BarChart, BarGroup, Block, Borders, Tabs}, Frame, }; -use tracing::debug; use tui_tree_widget::{Tree, TreeItem}; use super::{ @@ -19,6 +18,24 @@ use super::{ mod chart; mod logs; +pub(crate) struct Theme { + bars: Style, + centered_text: Style, + alt_background: Color, + background: Color, +} + +impl Default for Theme { + fn default() -> Self { + Self { + bars: Style::new().bg(Color::Gray).fg(Color::Black), + centered_text: Style::new(), + alt_background: Color::Gray, + background: Color::Black, + } + } +} + pub(crate) fn app( frame: &mut Frame, app: &mut App, @@ -40,8 +57,10 @@ pub(crate) fn app( } else { [Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)] } + } else if logs.is_some() { + [Constraint::Percentage(60), Constraint::Percentage(40)] } else { - [Constraint::Percentage(100), Constraint::Percentage(100)] + [Constraint::Percentage(100), Constraint::Percentage(0)] }; let area = frame.area(); @@ -54,7 +73,7 @@ pub(crate) fn app( .flex(Flex::Legacy) .areas(area); - render_tab(frame, top_line, app.active_tab); + render_tab(frame, top_line, app); match app.active_tab { ActiveTab::Readings => { @@ -69,10 +88,10 @@ pub(crate) fn app( render_footer(frame, footer, app); } -fn render_tab(frame: &mut Frame, layout: Rect, active_tab: ActiveTab) { +fn render_tab(frame: &mut Frame, layout: Rect, app: &App) { let tabs = Tabs::new(vec!["Readings", "Affectors"]) - .style(Style::new().bg(Color::Gray)) - .select(active_tab.number()) + .style(app.theme.bars) + .select(app.active_tab.number()) .divider("|") .padding(" ", " "); @@ -104,7 +123,7 @@ fn render_footer(frame: &mut Frame, layout: Rect, app: &mut App) { let footer = footer.join(" "); let footer = Text::raw(footer) .alignment(Alignment::Center) - .style(Style::new().bg(Color::Gray)); + .style(app.theme.bars); frame.render_widget(footer, layout) } @@ -116,11 +135,23 @@ fn render_graph_hist_logs( logs: Option>, chart: Option, ) { - let num_elems = 1u8 + app.show_histogram as u8 + app.show_logs as u8; + let num_elems = 1usize + app.show_histogram as usize + app.show_logs as usize; + + let mut constraints = [Constraint::Max(2); 3]; + if chart.is_some() { + constraints[0] = Constraint::Fill(10); + } + if logs.is_some() && app.show_logs { + constraints[1] = Constraint::Fill(10); + } + if !histogram.is_empty() && app.show_histogram { + let idx = 1 + app.show_histogram as usize; + constraints[idx] = Constraint::Fill(10); + } let layout = Layout::default() .direction(Direction::Vertical) - .constraints((0..num_elems).into_iter().map(|_| Constraint::Fill(10))) + .constraints(&constraints[..num_elems]) .flex(Flex::Legacy) .split(layout); @@ -129,7 +160,12 @@ fn render_graph_hist_logs( if let Some(chart) = chart { chart::render(frame, layout.next().unwrap(), app, chart); } else { - centered_text("No data", frame, layout.next().unwrap()) + centered_text( + "No chart as there is no data", + frame, + layout.next().unwrap(), + &app.theme, + ) } if app.show_logs { @@ -138,12 +174,18 @@ fn render_graph_hist_logs( layout.next().unwrap(), &mut app.logs_table_state, logs, + &app.theme, ) } if app.show_histogram { if histogram.is_empty() { - centered_text("No timing information", frame, layout.next().unwrap()) + centered_text( + "No histogram as there is no timing information", + frame, + layout.next().unwrap(), + &app.theme, + ) } else { render_histogram(frame, layout.next().unwrap(), histogram); } @@ -250,9 +292,9 @@ fn render_affectors( ); } -fn centered_text(text: &str, frame: &mut Frame, area: Rect) { +fn centered_text(text: &str, frame: &mut Frame, area: Rect, theme: &Theme) { let footer = Text::raw(text) .alignment(Alignment::Center) - .style(Style::new().bg(Color::Gray)); + .style(theme.centered_text); frame.render_widget(footer, area) } diff --git a/crates/sensor-tui/src/tui/render/logs.rs b/crates/sensor-tui/src/tui/render/logs.rs index cc517d03..2c17f02c 100644 --- a/crates/sensor-tui/src/tui/render/logs.rs +++ b/crates/sensor-tui/src/tui/render/logs.rs @@ -1,5 +1,5 @@ use log_store::api::ErrorEvent; -use ratatui::layout::{Constraint, Rect}; +use ratatui::layout::{Constraint, Flex, Rect}; use ratatui::style::{Color, Modifier, Style, Stylize}; use ratatui::text::Text; use ratatui::widgets::{Cell, HighlightSpacing, Row, Table, TableState}; @@ -12,15 +12,16 @@ pub fn render( layout: Rect, table_state: &mut TableState, logs: Option>, + theme: &super::Theme, ) { if let Some(logs) = logs { if logs.is_empty() { - centered_text("Logs are empty", frame, layout) + centered_text("Logs are empty", frame, layout, theme) } else { render_table(frame, layout, table_state, logs) } } else { - centered_text("No logs", frame, layout) + centered_text("No logs", frame, layout, theme) } } @@ -42,8 +43,14 @@ pub fn render_table( .style(header_style) .height(1); + let longest_error_msg = logs + .iter() + .map(|ErrorEvent { error, .. }| error.to_string().chars().count() as u16) + .max() + .unwrap_or_default(); let rows = logs .into_iter() + .rev() .enumerate() .map(|(i, ErrorEvent { start, end, error })| { let color = match i % 2 { @@ -51,11 +58,15 @@ pub fn render_table( _ => Color::White, }; let end = if let Some(timestamp) = end { - format!("{timestamp}") + format!("{}", timestamp.strftime("%I:%M:%S")) } else { "ongoing".to_owned() }; - let item = [format!("{error}"), format!("{start}"), end]; + let item = [ + format!("{error}"), + format!("{}", start.strftime("%I:%M:%S")), + end, + ]; item.into_iter() .map(|content| Text::from(content)) .map(|content| Cell::from(content)) @@ -68,12 +79,14 @@ pub fn render_table( let table = Table::new( rows, [ - Constraint::Length(10), - Constraint::Min(10), - Constraint::Min(10), + Constraint::Max(longest_error_msg), + Constraint::Max(10), + Constraint::Max(10), ], ) .header(header) + .flex(Flex::SpaceAround) + .column_spacing(1) .highlight_style(selected_style) .highlight_symbol(Text::from(vec![ "".into(), From 37d37c0d346d0725b4c40242ed93969c86a3e7be Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 14 Aug 2024 11:32:19 +0200 Subject: [PATCH 193/687] fix error deduplication --- crates/log-store/src/server/db/log.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/crates/log-store/src/server/db/log.rs b/crates/log-store/src/server/db/log.rs index 3f059670..a336489e 100644 --- a/crates/log-store/src/server/db/log.rs +++ b/crates/log-store/src/server/db/log.rs @@ -71,6 +71,9 @@ impl CurrentError { fn set(&mut self, report: protocol::Error) -> Result<()> { let value = (jiff::Timestamp::now(), report); let bytes = bincode::serialize(&value).wrap_err("could not serialize current error")?; + self.file + .set_len(0) + .wrap_err("Could not clear file prior to backing up value")?; self.file .write_all(&bytes) .wrap_err("could not backup current error to disk")?; @@ -79,6 +82,10 @@ impl CurrentError { .wrap_err("failed to flush current err backup to disk")?; Ok(()) } + + fn get(&self) -> &Option<(jiff::Timestamp, protocol::Error)> { + &self.value + } } type Header = String; @@ -107,17 +114,13 @@ impl Log { } pub fn set_err(&mut self, new_report: protocol::Error) -> Result<()> { - if let Some((started, report)) = self - .current - .take() - .wrap_err("failed to take value out of current error store")? - { - if report == new_report { + if let Some((started, report)) = self.current.get() { + if report == &new_report { return Ok(()); } let line = StoredErrorEvent { end: jiff::Timestamp::now(), - error: report, + error: report.clone(), }; let line = bincode::serialize(&line).wrap_err("Could not serialize ErrorEvent")?; self.history From 9624bbfba2e364328548050b5ebd1aef9fbf7081 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 14 Aug 2024 17:42:09 +0200 Subject: [PATCH 194/687] refactor fetching to seperate thread --- crates/sensor-tui/src/fetch.rs | 173 +++++++++++++++++++++ crates/sensor-tui/src/main.rs | 68 +++++--- crates/sensor-tui/src/populate.rs | 10 +- crates/sensor-tui/src/tui.rs | 65 ++++---- crates/sensor-tui/src/tui/reading.rs | 79 ++++++---- crates/sensor-tui/src/tui/reading/fetch.rs | 1 - crates/sensor-tui/src/tui/reading/logs.rs | 1 - 7 files changed, 311 insertions(+), 86 deletions(-) create mode 100644 crates/sensor-tui/src/fetch.rs diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs new file mode 100644 index 00000000..220f5fe2 --- /dev/null +++ b/crates/sensor-tui/src/fetch.rs @@ -0,0 +1,173 @@ +use std::collections::VecDeque; +use std::future::Future; +use std::net::SocketAddr; +use std::ops::RangeInclusive; +use std::sync::mpsc; +use std::thread; +use std::time::Duration; + +use color_eyre::Result; +use jiff::Timestamp; +use protocol::Reading; +use tracing::{debug, warn}; + +use crate::{client_name, Fetched, Update}; + +const MAX_IN_FLIGHT_REQUESTS: usize = 6; + +#[derive(Debug, Clone)] +pub struct Data { + reading: Reading, + range: RangeInclusive, +} + +#[derive(Debug, Clone)] +pub enum Request { + Data(Data), +} + +impl Request { + fn unwrap_data(&self) -> Option<&Data> { + match self { + Request::Data(d) => Some(d), + } + } +} + +pub struct Fetch { + pub recently_issued: VecDeque, + pub tx: tokio::sync::mpsc::Sender, +} + +impl Fetch { + pub fn new( + data_store: SocketAddr, + log_store: SocketAddr, + update_tx: mpsc::Sender, + ) -> (Self, thread::JoinHandle<()>) { + let (tx, rx) = tokio::sync::mpsc::channel(32); + + let this = Self { + recently_issued: VecDeque::new(), + tx, + }; + + let maintainer = thread::spawn(move || { + let rt = tokio::runtime::Builder::new_current_thread() + .enable_io() + .enable_time() + .build() + .unwrap(); + warn!("yo"); + rt.block_on(handle_requests(data_store, log_store, rx, update_tx)); + }); + (this, maintainer) + } + + pub fn assure_up_to_date( + &mut self, + reading: Reading, + history_length: Duration, + oldest_in_data: Timestamp, + ) { + let history_len = jiff::Span::try_from(history_length).unwrap(); + let start_needed = Timestamp::now() - history_len; + if self.history_outdated_not_updating(&reading, start_needed, oldest_in_data) { + self.request(Request::Data(Data { + reading, + range: start_needed..=Timestamp::now(), + })) + } + } + + fn history_outdated_not_updating( + &mut self, + reading: &Reading, + oldest_needed: Timestamp, + oldest_in_history: Timestamp, + ) -> bool { + if oldest_in_history <= oldest_needed { + return false; + } + + let with_margin = oldest_needed.as_millisecond() as f64 * 1.2; + let not_too_old = |start: &i64| *start < with_margin as i64; + + !self + .recently_issued + .iter() + .filter_map(Request::unwrap_data) + .filter(|req| &req.reading == reading) + .map(|req| req.range.start().as_millisecond()) + .filter(not_too_old) + .any(|start| start < oldest_needed.as_millisecond()) + } + + fn request(&mut self, req: Request) { + debug!("sending request: {req:?}"); + self.tx.blocking_send(req.clone()).unwrap(); + self.recently_issued.push_front(req); + // might get out of sync with request handler, that is okay + // false positives in self.recently_issued are allowed. They only + // delay an update by a single frame. + if self.recently_issued.len() > MAX_IN_FLIGHT_REQUESTS { + self.recently_issued.pop_back(); + } + } +} + +pub(crate) async fn handle_requests( + data_store: SocketAddr, + _log_store: SocketAddr, + mut rx: tokio::sync::mpsc::Receiver, + tx: mpsc::Sender, +) { + let mut inflight_request = VecDeque::new(); + while let Some(request) = rx.recv().await { + let data_store = data_store.clone(); + let tx = tx.clone(); + let handle = match request { + Request::Data(Data { reading, range }) => tokio::spawn(get_wrap_send( + get_data(data_store, reading.clone(), range), + |res| match res { + Ok(data) => Update::Fetched(Fetched::Data { + reading, + timestamps: data.0, + data: data.1, + }), + Err(err) => Update::FetchError(err), + }, + tx, + )), + }; + inflight_request.push_front(handle); + if inflight_request.len() > 6 { + let to_cancel = inflight_request.pop_back().expect("more then 0 items"); + to_cancel.abort(); + } + } + unreachable!() +} + +pub async fn get_wrap_send( + getter: impl Future, + wrapper: impl FnOnce(T) -> Update, + tx: mpsc::Sender, +) { + let val = getter.await; + let update = (wrapper)(val); + tx.send(update).unwrap(); +} + +pub async fn get_data( + data_store: SocketAddr, + reading: Reading, + range: RangeInclusive, +) -> Result<(Vec, Vec)> { + let mut api = data_store::api::Client::connect(data_store, client_name()).await?; + + let history = api + .get_data(*range.start(), *range.end(), reading, 300) + .await?; + Ok(history) +} diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index 19f534b9..cd557f18 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -7,37 +7,59 @@ use color_eyre::eyre::WrapErr; use color_eyre::{Help, Result}; use data_server::SubMessage; +mod fetch; +mod populate; mod time; mod tui; -mod populate; + +pub(crate) use fetch::Fetch; +use protocol::Reading; + +#[derive(Debug, PartialEq, Eq)] +enum UserIntent { + Shutdown, +} + +enum Fetched { + Data { + reading: Reading, + timestamps: Vec, + data: Vec, + }, +} enum Update { ReadingList(Vec), - Reading(protocol::Reading), - Error(Box), - Shutdown, + Fetched(Fetched), + FetchError(color_eyre::Report), + SensorReading(protocol::Reading), + SensorError(Box), + SubscribeError(color_eyre::Report), DeviceList(Vec), } -fn receive_data(mut sub: data_server::Subscriber, tx: mpsc::Sender>) { +fn receive_data(mut sub: data_server::Subscriber, tx: mpsc::Sender) { loop { - let update = sub + let res = sub .next_msg() .wrap_err("Error getting next reading from server") .map(|msg| match msg { - SubMessage::Reading(reading) => Update::Reading(reading), - SubMessage::ErrorReport(error) => Update::Error(error), + SubMessage::Reading(reading) => Update::SensorReading(reading), + SubMessage::ErrorReport(error) => Update::SensorError(error), }); - let err = update.is_err(); - tx.send(update).unwrap(); - if err { - break; + match res { + Ok(msg) => { + tx.send(msg).unwrap(); + } + Err(err) => { + tx.send(Update::SubscribeError(err)).unwrap(); + break; + } } } } - #[derive(Parser)] #[command(name = "sensor tui")] #[command(version = "1.0")] @@ -72,18 +94,18 @@ fn main() -> Result<()> { let (tx1, rx1) = mpsc::channel(); let (tx2, rx2) = mpsc::channel(); - let tx1_clone = tx1.clone(); - let tx1_clone_clone = tx1.clone(); - thread::spawn(move || receive_data(sub, tx1_clone)); - thread::spawn(move || populate::tree(data_store, log_store, tx1_clone_clone)); - thread::spawn(move || tui::run(rx2, tx1, data_store, log_store)); + let (fetcher, maintain_fetch) = Fetch::new(data_store, log_store, tx1.clone()); + + let tx1_clone1 = tx1.clone(); + let tx1_clone2 = tx1.clone(); + thread::spawn(move || receive_data(sub, tx1_clone1)); + thread::spawn(move || tui::run(rx1, tx2, fetcher, log_store)); + thread::spawn(move || maintain_fetch); + thread::spawn(move || populate::tree(data_store, log_store, tx1_clone2)); loop { - let update = rx1.recv()??; - if let Update::Shutdown = update { - break Ok(()); - }; - tx2.send(update).unwrap() + let UserIntent::Shutdown = rx2.recv()?; + break Ok(()); } } diff --git a/crates/sensor-tui/src/populate.rs b/crates/sensor-tui/src/populate.rs index a4170c62..db523876 100644 --- a/crates/sensor-tui/src/populate.rs +++ b/crates/sensor-tui/src/populate.rs @@ -9,7 +9,7 @@ use crate::{client_name, Update}; pub fn tree( data_store_addr: SocketAddr, log_store_addr: SocketAddr, - tx: mpsc::Sender>, + tx: mpsc::Sender, ) { let rt = tokio::runtime::Builder::new_current_thread() .enable_io() @@ -35,22 +35,22 @@ pub fn tree( async fn list_from_store( data_store_addr: SocketAddr, - tx: mpsc::Sender>, + tx: mpsc::Sender, ) -> Result<()> { let mut client = data_store::api::Client::connect(data_store_addr, client_name()).await?; let list = client.list_data().await?; tracing::debug!("list: {list:?}"); - tx.send(Ok(Update::ReadingList(list))).unwrap(); + tx.send(Update::ReadingList(list)).unwrap(); Ok(()) } async fn list_from_logs( log_store_addr: SocketAddr, - tx: mpsc::Sender>, + tx: mpsc::Sender, ) -> Result<()> { let mut client = log_store::api::Client::connect(log_store_addr, client_name()).await?; let list = client.list_devices().await?; tracing::debug!("list: {list:?}"); - tx.send(Ok(Update::DeviceList(list))).unwrap(); + tx.send(Update::DeviceList(list)).unwrap(); Ok(()) } diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index 30bb0fd4..a20991fc 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -7,19 +7,24 @@ use ratatui::{ prelude::{CrosstermBackend, Terminal}, widgets::TableState, }; -use std::{collections::HashMap, io::stdout, net::SocketAddr, sync::mpsc, time::Duration}; +use std::{ + collections::HashMap, + io::{stdout, Stdout}, + net::SocketAddr, + sync::mpsc, + time::Duration, +}; use tui_tree_widget::TreeState; mod reading; -use reading::Readings; +use reading::{Readings, TreeKey}; + mod render; -use crate::Update; +use crate::{fetch::Fetch, Update, UserIntent}; mod history_len; use history_len::HistoryLen; -use self::reading::TreeKey; - #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] enum ActiveTab { #[default] @@ -52,11 +57,22 @@ enum InputMode { pub fn run( rx: mpsc::Receiver, - shutdown_tx: mpsc::Sender>, - data_store: SocketAddr, + shutdown_tx: mpsc::Sender, + fetcher: Fetch, log_store: SocketAddr, ) -> Result<(), std::io::Error> { - App::default().run(rx, shutdown_tx, data_store, log_store) + stdout().execute(EnterAlternateScreen)?; + enable_raw_mode()?; + let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; + terminal.clear()?; + + let res = App::default().run(terminal, rx, fetcher, log_store); + shutdown_tx.send(UserIntent::Shutdown).unwrap(); + + stdout().execute(LeaveAlternateScreen)?; + disable_raw_mode()?; + + res } #[derive(Default)] @@ -75,9 +91,9 @@ struct App { impl App { pub fn run( &mut self, + mut terminal: Terminal>, rx: mpsc::Receiver, - shutdown_tx: mpsc::Sender>, - data_store: SocketAddr, + mut fetcher: Fetch, log_store: SocketAddr, ) -> Result<(), std::io::Error> { let mut readings = Readings { @@ -85,11 +101,6 @@ impl App { data: HashMap::new(), }; - stdout().execute(EnterAlternateScreen)?; - enable_raw_mode()?; - let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; - terminal.clear()?; - let affectors = Vec::new(); let mut plot_buf = Vec::new(); @@ -107,10 +118,10 @@ impl App { data.reading.clone(), &mut self.history_length, ); - data.history_from_store.update_if_needed( - data_store, + fetcher.assure_up_to_date( data.reading.clone(), - &mut self.history_length, + self.history_length.dur, + data.oldest_in_history(), ); data.percentiles_from_store.update_if_needed( log_store, @@ -164,24 +175,26 @@ impl App { } }; - match rx.try_recv() { - Ok(Update::Reading(reading)) => { + let Ok(update) = rx.try_recv() else { + continue; + }; + + match update { + Update::SensorReading(reading) => { readings.add(reading); } - Ok(Update::ReadingList(list)) => { + Update::ReadingList(list) => { readings.populate_from_reading_list(list); } - Ok(Update::DeviceList(list)) => { + Update::DeviceList(list) => { readings.populate_from_device_list(list); } - Ok(Update::Error(err)) => readings.add_error(err), + Update::SensorError(err) => readings.add_error(err), + Update::Fetched(fetched) => readings.add_fetched(fetched), _ => (), } } - stdout().execute(LeaveAlternateScreen)?; - disable_raw_mode()?; - shutdown_tx.send(Ok(Update::Shutdown)).unwrap(); Ok(()) } diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index fc71ddac..be2867c2 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -9,11 +9,10 @@ use protocol::{Device, Error}; use ratatui::{text::Line, widgets::Bar}; use std::collections::HashMap; -use std::sync::TryLockError; use tui_tree_widget::TreeItem; mod fetch; -use fetch::{histogram, history}; +use fetch::histogram; mod logs; @@ -26,7 +25,7 @@ pub struct SensorInfo { timing: Histogram, pub percentiles_from_store: histogram::Stored, recent_history: Vec<(jiff::Timestamp, f32)>, - pub history_from_store: history::Stored, + pub history_from_store: Vec<(jiff::Timestamp, f32)>, condition: Result<(), Box>, logs: logs::Logs, pub logs_from_store: fetch::logs::Stored, @@ -107,18 +106,8 @@ impl SensorInfo { } pub fn chart<'a>(&mut self, plot_buf: &'a mut Vec<(f64, f64)>) -> Option> { - let guard = match self.history_from_store.data.try_lock() { - Ok(list) => Some(list), - Err(TryLockError::WouldBlock) => None, - Err(other) => panic!( - "fetching sensor history from data-store \ - panicked: {other}" - ), - }; - let empty = Vec::new(); - let old_history = guard.as_deref().unwrap_or(&empty); - - let reference = old_history + let reference = self + .history_from_store .first() .map(|(t, _)| t) .or_else(|| self.recent_history.first().map(|(t, _)| t))?; @@ -131,7 +120,8 @@ impl SensorInfo { .unwrap_or(jiff::Timestamp::default()); plot_buf.clear(); - for xy in old_history + for xy in self + .history_from_store .iter() .take_while(|(t, _)| *t < first_recent) .chain(self.recent_history.iter()) @@ -167,6 +157,21 @@ impl SensorInfo { logs.extend(without_duplicates); logs } + + pub(crate) fn oldest_in_history(&self) -> jiff::Timestamp { + jiff::Timestamp::min( + self.history_from_store + .first() + .map(|(ts, _)| ts) + .copied() + .unwrap_or(jiff::Timestamp::MAX), + self.recent_history + .first() + .map(|(ts, _)| ts) + .copied() + .unwrap_or(jiff::Timestamp::MAX), + ) + } } /// Guaranteed to be unique for a leaf, @@ -226,7 +231,7 @@ fn add_node<'a>( tree.child_mut(new_child).expect("just added it") } -fn extract_leaf_info(reading: &Reading) -> (TreeKey, String, f32) { +pub(crate) fn tree_key(reading: &Reading) -> TreeKey { let mut key = [0u8; 6]; key[0] = reading.branch_id(); @@ -237,9 +242,8 @@ fn extract_leaf_info(reading: &Reading) -> (TreeKey, String, f32) { *byte = inner.branch_id(); inner } - Item::Leaf(ReadingInfo { val, .. }) => { - let name = reading.name(); - return (key, name, val); + Item::Leaf(ReadingInfo { .. }) => { + return key; } }; } @@ -278,7 +282,7 @@ impl Readings { fn record_error(&mut self, error: Box) { for broken in error.device().info().affects_readings { - let (key, _, _) = extract_leaf_info(broken); + let key = tree_key(broken); if let Some(info) = self.data.get_mut(&key) { info.condition = Err(error.clone()); @@ -294,7 +298,7 @@ impl Readings { percentiles_from_store: histogram::Stored::new(), recent_history: Vec::new(), - history_from_store: history::Stored::new(), + history_from_store: Vec::new(), logs_from_store: fetch::logs::Stored::new(), condition: Err(error.clone()), @@ -306,7 +310,7 @@ impl Readings { } fn record_data(&mut self, reading: Reading) { - let (key, _, val) = extract_leaf_info(&reading); + let key = tree_key(&reading); let time = jiff::Timestamp::now(); if let Some(info) = self.data.get_mut(&key) { @@ -315,10 +319,10 @@ impl Readings { .total(Unit::Millisecond) .expect("no calander units involved") as u64 } - info.recent_history.push((time, val)); + info.recent_history.push((time, reading.leaf().val)); info.condition = Ok(()); } else { - let history = vec![(time, val)]; + let history = vec![(time, reading.leaf().val)]; self.data.insert( key, SensorInfo { @@ -328,7 +332,7 @@ impl Readings { percentiles_from_store: histogram::Stored::new(), recent_history: history, - history_from_store: history::Stored::new(), + history_from_store: Vec::new(), logs_from_store: fetch::logs::Stored::new(), condition: Ok(()), @@ -339,7 +343,7 @@ impl Readings { } fn record_missing_data(&mut self, reading: Reading) { - let (key, _, _) = extract_leaf_info(&reading); + let key = tree_key(&reading); if self.data.contains_key(&key) { return; } @@ -353,7 +357,7 @@ impl Readings { percentiles_from_store: histogram::Stored::new(), recent_history: Vec::new(), - history_from_store: history::Stored::new(), + history_from_store: Vec::new(), logs_from_store: fetch::logs::Stored::new(), condition: Ok(()), @@ -363,7 +367,7 @@ impl Readings { } fn update_tree(&mut self, reading: &Reading, placeholder: IsPlaceholder) { - let (key, _, _) = extract_leaf_info(reading); + let key = tree_key(reading); let mut tree = add_root(reading as &dyn Tree, &mut self.ground); let mut tomato = match reading.inner() { @@ -397,7 +401,7 @@ impl Readings { fn update_tree_err(&mut self, error: &Error) { for broken in error.device().info().affects_readings { - let (key, _, _) = extract_leaf_info(broken); + let key = tree_key(broken); let mut tree = add_root(broken as &dyn Tree, &mut self.ground); let mut tomato = match broken.inner() { @@ -419,6 +423,21 @@ impl Readings { } } } + + pub(crate) fn add_fetched(&mut self, fetched: crate::Fetched) { + match fetched { + crate::Fetched::Data { + reading, + timestamps, + data, + } => { + self.data + .get_mut(&tree_key(&reading)) + .expect("data is never removed") + .history_from_store = timestamps.into_iter().zip(data.into_iter()).collect() + } + } + } } pub struct ChartParts<'a> { diff --git a/crates/sensor-tui/src/tui/reading/fetch.rs b/crates/sensor-tui/src/tui/reading/fetch.rs index f4225037..d0f09bf6 100644 --- a/crates/sensor-tui/src/tui/reading/fetch.rs +++ b/crates/sensor-tui/src/tui/reading/fetch.rs @@ -4,7 +4,6 @@ use std::time::Duration; use tokio::sync::Notify; pub mod histogram; -pub mod history; pub mod logs; #[derive(Debug)] diff --git a/crates/sensor-tui/src/tui/reading/logs.rs b/crates/sensor-tui/src/tui/reading/logs.rs index 32ba9e6e..793b90a9 100644 --- a/crates/sensor-tui/src/tui/reading/logs.rs +++ b/crates/sensor-tui/src/tui/reading/logs.rs @@ -1,4 +1,3 @@ -use std::iter; use jiff::Unit; use log_store::api::{self, ErrorEvent}; From 4f34b2e9b50e866341dc6512be716f7e25266246 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 15 Aug 2024 22:56:24 +0200 Subject: [PATCH 195/687] mov histogram and log fetching to new fetch framework --- crates/protocol/src/large_bedroom/bed.rs | 4 +- crates/sensor-tui/src/fetch.rs | 161 ++++++++++++++++-- crates/sensor-tui/src/main.rs | 22 ++- crates/sensor-tui/src/tui.rs | 39 ++--- crates/sensor-tui/src/tui/reading.rs | 79 ++++++--- crates/sensor-tui/src/tui/reading/fetch.rs | 14 -- .../src/tui/reading/fetch/histogram.rs | 143 ---------------- .../src/tui/reading/fetch/history.rs | 148 ---------------- .../sensor-tui/src/tui/reading/fetch/logs.rs | 135 --------------- crates/sensor-tui/src/tui/reading/logs.rs | 9 +- crates/sensor-tui/src/tui/render.rs | 4 +- 11 files changed, 245 insertions(+), 513 deletions(-) delete mode 100644 crates/sensor-tui/src/tui/reading/fetch.rs delete mode 100644 crates/sensor-tui/src/tui/reading/fetch/histogram.rs delete mode 100644 crates/sensor-tui/src/tui/reading/fetch/history.rs delete mode 100644 crates/sensor-tui/src/tui/reading/fetch/logs.rs diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index e051ab1f..338b981a 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -145,7 +145,7 @@ impl Tree for Reading { Reading::WeightLeft(val) => ( *val as f32, Device::Nau7802Left.rooted(), - 0.0..2.0_f32.exp2(), + 0.0..24.0_f32.exp2(), 1.0, Unit::Ohm, "Left weight sensor resistance", @@ -153,7 +153,7 @@ impl Tree for Reading { Reading::WeightRight(val) => ( *val as f32, Device::Nau7802Right.rooted(), - 0.0..2.0_f32.exp2(), + 0.0..24.0_f32.exp2(), 1.0, Unit::Ohm, "Right weight sensor resistance", diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index 220f5fe2..85edff61 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -4,14 +4,16 @@ use std::net::SocketAddr; use std::ops::RangeInclusive; use std::sync::mpsc; use std::thread; -use std::time::Duration; +use std::time::Instant; use color_eyre::Result; -use jiff::Timestamp; +use jiff::{Span, Timestamp}; +use log_store::api::{ErrorEvent, Percentile}; use protocol::Reading; -use tracing::{debug, warn}; +use tracing::debug; -use crate::{client_name, Fetched, Update}; +use crate::tui::history_len; +use crate::{client_name, Fetchable, Update}; const MAX_IN_FLIGHT_REQUESTS: usize = 6; @@ -21,15 +23,42 @@ pub struct Data { range: RangeInclusive, } +#[derive(Debug, Clone)] +pub struct Logs { + reading: Reading, + range: RangeInclusive, +} + +#[derive(Debug, Clone)] +pub struct Hist { + reading: Reading, + range: RangeInclusive, +} + #[derive(Debug, Clone)] pub enum Request { Data(Data), + Logs(Logs), + Hist(Hist), } impl Request { + fn unwrap_logs(&self) -> Option<&Logs> { + match self { + Request::Logs(d) => Some(d), + _ => None, + } + } fn unwrap_data(&self) -> Option<&Data> { match self { Request::Data(d) => Some(d), + _ => None, + } + } + fn unwrap_hist(&self) -> Option<&Hist> { + match self { + Request::Hist(d) => Some(d), + _ => None, } } } @@ -58,7 +87,6 @@ impl Fetch { .enable_time() .build() .unwrap(); - warn!("yo"); rt.block_on(handle_requests(data_store, log_store, rx, update_tx)); }); (this, maintainer) @@ -66,15 +94,33 @@ impl Fetch { pub fn assure_up_to_date( &mut self, + history_len: &mut history_len::HistoryLen, reading: Reading, - history_length: Duration, oldest_in_data: Timestamp, + logs_cover_from: Option, + hist_cover: Option>, ) { - let history_len = jiff::Span::try_from(history_length).unwrap(); - let start_needed = Timestamp::now() - history_len; + let history_spans = Span::try_from(history_len.dur).unwrap(); + let start_needed = Timestamp::now() - history_spans; if self.history_outdated_not_updating(&reading, start_needed, oldest_in_data) { + debug!("Requesting history for {reading:?}"); self.request(Request::Data(Data { - reading, + reading: reading.clone(), + range: start_needed..=Timestamp::now(), + })); + history_len.state = history_len::State::Fetching(Instant::now()); + } + if self.logs_outdated_not_updating(&reading, start_needed, logs_cover_from) { + debug!("Requesting logs for {reading:?}"); + self.request(Request::Logs(Logs { + reading: reading.clone(), + range: start_needed..=Timestamp::now(), + })) + } + if self.hist_outdated_not_updating(&reading, start_needed, hist_cover) { + debug!("Requesting percentiles for {reading:?}"); + self.request(Request::Hist(Hist { + reading: reading.clone(), range: start_needed..=Timestamp::now(), })) } @@ -103,8 +149,51 @@ impl Fetch { .any(|start| start < oldest_needed.as_millisecond()) } + fn logs_outdated_not_updating( + &mut self, + reading: &Reading, + oldest_needed: Timestamp, + logs_cover_from: Option, + ) -> bool { + if logs_cover_from.is_some_and(|oldest| oldest <= oldest_needed) { + return false; + } + + !self + .recently_issued + .iter() + .filter_map(Request::unwrap_logs) + .filter(|req| &req.reading == reading) + .map(|req| req.range.start().as_millisecond()) + .any(|start| start < oldest_needed.as_millisecond()) + } + + fn hist_outdated_not_updating( + &mut self, + reading: &Reading, + oldest_needed: Timestamp, + hist_range: Option>, + ) -> bool { + fn covers_recently(end: Timestamp) -> bool { + Timestamp::now().since(end).unwrap().get_seconds() < 5 + } + + if hist_range.is_some_and(|r| r.contains(&oldest_needed) && covers_recently(*r.end())) { + return false; + } + + !self + .recently_issued + .iter() + .filter_map(Request::unwrap_hist) + .filter(|req| &req.reading == reading) + .map(|req| req.range.clone()) + .filter(|range| covers_recently(*range.end())) + .map(|range| range.start().as_millisecond()) + .any(|start| start < oldest_needed.as_millisecond()) + } + fn request(&mut self, req: Request) { - debug!("sending request: {req:?}"); self.tx.blocking_send(req.clone()).unwrap(); self.recently_issued.push_front(req); // might get out of sync with request handler, that is okay @@ -118,7 +207,7 @@ impl Fetch { pub(crate) async fn handle_requests( data_store: SocketAddr, - _log_store: SocketAddr, + log_store: SocketAddr, mut rx: tokio::sync::mpsc::Receiver, tx: mpsc::Sender, ) { @@ -130,11 +219,38 @@ pub(crate) async fn handle_requests( Request::Data(Data { reading, range }) => tokio::spawn(get_wrap_send( get_data(data_store, reading.clone(), range), |res| match res { - Ok(data) => Update::Fetched(Fetched::Data { + Ok(data) => Update::Fetched { reading, - timestamps: data.0, - data: data.1, - }), + thing: Fetchable::Data { + timestamps: data.0, + data: data.1, + }, + }, + Err(err) => Update::FetchError(err), + }, + tx, + )), + Request::Logs(Logs { reading, range }) => tokio::spawn(get_wrap_send( + get_logs(log_store, reading.clone()), + move |res| match res { + Ok(logs) => Update::Fetched { + reading, + thing: Fetchable::Logs { + logs, + start_at: *range.start(), + }, + }, + Err(err) => Update::FetchError(err), + }, + tx, + )), + Request::Hist(Hist { reading, range }) => tokio::spawn(get_wrap_send( + get_percentiles(log_store, reading.clone()), + move |res| match res { + Ok(percentiles) => Update::Fetched { + reading, + thing: Fetchable::Hist { percentiles, range }, + }, Err(err) => Update::FetchError(err), }, tx, @@ -146,7 +262,6 @@ pub(crate) async fn handle_requests( to_cancel.abort(); } } - unreachable!() } pub async fn get_wrap_send( @@ -171,3 +286,17 @@ pub async fn get_data( .await?; Ok(history) } + +pub async fn get_logs(log_store: SocketAddr, reading: Reading) -> Result> { + let mut api = log_store::api::Client::connect(log_store, client_name()).await?; + + let history = api.get_logs(reading.device()).await?; + Ok(history) +} + +pub async fn get_percentiles(log_store: SocketAddr, reading: Reading) -> Result> { + let mut api = log_store::api::Client::connect(log_store, client_name()).await?; + + let percentile = api.get_percentiles(reading.device()).await?; + Ok(percentile) +} diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index cd557f18..529bd1da 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -1,4 +1,5 @@ use std::net::SocketAddr; +use std::ops::RangeInclusive; use std::sync::mpsc; use std::thread; @@ -13,6 +14,7 @@ mod time; mod tui; pub(crate) use fetch::Fetch; +use log_store::api::{ErrorEvent, Percentile}; use protocol::Reading; #[derive(Debug, PartialEq, Eq)] @@ -20,17 +22,29 @@ enum UserIntent { Shutdown, } -enum Fetched { +struct Fetched { + reading: Reading, + thing: Fetchable +} + +enum Fetchable { Data { - reading: Reading, timestamps: Vec, data: Vec, }, + Logs { + logs: Vec, + start_at: jiff::Timestamp, + }, + Hist { + percentiles: Vec, + range: RangeInclusive, + }, } enum Update { ReadingList(Vec), - Fetched(Fetched), + Fetched{reading: Reading, thing: Fetchable}, FetchError(color_eyre::Report), SensorReading(protocol::Reading), SensorError(Box), @@ -99,7 +113,7 @@ fn main() -> Result<()> { let tx1_clone1 = tx1.clone(); let tx1_clone2 = tx1.clone(); thread::spawn(move || receive_data(sub, tx1_clone1)); - thread::spawn(move || tui::run(rx1, tx2, fetcher, log_store)); + thread::spawn(move || tui::run(rx1, tx2, fetcher)); thread::spawn(move || maintain_fetch); thread::spawn(move || populate::tree(data_store, log_store, tx1_clone2)); diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index a20991fc..804bd67a 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -10,7 +10,6 @@ use ratatui::{ use std::{ collections::HashMap, io::{stdout, Stdout}, - net::SocketAddr, sync::mpsc, time::Duration, }; @@ -22,7 +21,7 @@ use reading::{Readings, TreeKey}; mod render; use crate::{fetch::Fetch, Update, UserIntent}; -mod history_len; +pub(crate) mod history_len; use history_len::HistoryLen; #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] @@ -59,14 +58,13 @@ pub fn run( rx: mpsc::Receiver, shutdown_tx: mpsc::Sender, fetcher: Fetch, - log_store: SocketAddr, ) -> Result<(), std::io::Error> { stdout().execute(EnterAlternateScreen)?; enable_raw_mode()?; let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; terminal.clear()?; - let res = App::default().run(terminal, rx, fetcher, log_store); + let res = App::default().run(terminal, rx, fetcher); shutdown_tx.send(UserIntent::Shutdown).unwrap(); stdout().execute(LeaveAlternateScreen)?; @@ -94,7 +92,6 @@ impl App { mut terminal: Terminal>, rx: mpsc::Receiver, mut fetcher: Fetch, - log_store: SocketAddr, ) -> Result<(), std::io::Error> { let mut readings = Readings { ground: Vec::new(), @@ -105,28 +102,20 @@ impl App { let mut plot_buf = Vec::new(); loop { - let data = self + let mut data = self .reading_tree_state .selected() .last() // unique leaf id .and_then(|key| readings.data.get_mut(key)); let plot_open = data.is_some(); - let (chart, histogram, details, logs) = if let Some(data) = data { - data.logs_from_store.update_if_needed( - log_store, - data.reading.clone(), - &mut self.history_length, - ); + let (chart, histogram, details, logs) = if let Some(data) = data.as_mut() { fetcher.assure_up_to_date( + &mut self.history_length, data.reading.clone(), - self.history_length.dur, data.oldest_in_history(), - ); - data.percentiles_from_store.update_if_needed( - log_store, - data.reading.device(), - &mut self.history_length, + data.logs_from_store_hist, + data.histogram_range.clone(), ); ( data.chart(&mut plot_buf), @@ -190,7 +179,19 @@ impl App { readings.populate_from_device_list(list); } Update::SensorError(err) => readings.add_error(err), - Update::Fetched(fetched) => readings.add_fetched(fetched), + Update::Fetched { + reading, + thing: fetched, + } => { + if data + .as_ref() + .is_some_and(|i| i.reading.is_same_as(&reading)) + { + self.history_length.state = history_len::State::Fetched; + } + readings.add_fetched(reading, fetched); + } + _ => (), } } diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/reading.rs index be2867c2..825cb2b3 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/reading.rs @@ -1,7 +1,7 @@ use hdrhistogram::Histogram; use itertools::Itertools; use jiff::Unit; -use log_store::api::ErrorEvent; +use log_store::api::{ErrorEvent, Percentile}; use protocol::reading_tree::ReadingInfo; use protocol::reading_tree::{Item, Tree}; use protocol::Reading; @@ -9,10 +9,10 @@ use protocol::{Device, Error}; use ratatui::{text::Line, widgets::Bar}; use std::collections::HashMap; +use std::ops::RangeInclusive; use tui_tree_widget::TreeItem; -mod fetch; -use fetch::histogram; +use crate::Fetchable; mod logs; @@ -23,12 +23,14 @@ pub struct SensorInfo { /// data use the last element of recent_history for printing pub reading: Reading, timing: Histogram, - pub percentiles_from_store: histogram::Stored, + pub percentiles_from_store: Vec, recent_history: Vec<(jiff::Timestamp, f32)>, + pub histogram_range: Option>, pub history_from_store: Vec<(jiff::Timestamp, f32)>, condition: Result<(), Box>, logs: logs::Logs, - pub logs_from_store: fetch::logs::Stored, + pub logs_from_store: Vec, + pub logs_from_store_hist: Option, } pub struct ErrorDensity { @@ -81,10 +83,20 @@ impl SensorInfo { } pub fn histogram(&self) -> Vec { - let percentiles = if self.percentiles_from_store.very_outdated() { + let older_then_15s = |range: &RangeInclusive| { + jiff::Timestamp::now() + .since(*range.end()) + .unwrap() + .get_seconds() + > 15 + }; + + let percentiles = if self.histogram_range.is_none() + || self.histogram_range.as_ref().is_some_and(older_then_15s) + { self.fallback_local_hist() } else { - self.percentiles_from_store.data.lock().unwrap().clone() + self.percentiles_from_store.clone() }; histogram_bars(&percentiles) } @@ -144,8 +156,8 @@ impl SensorInfo { } pub fn logs(&self) -> Vec { - let mut logs = self.logs_from_store.list(); - let last = logs + let last = self + .logs_from_store .last() .map(|ErrorEvent { start, .. }| *start) .unwrap_or(jiff::Timestamp::from_second(0).unwrap()); @@ -154,6 +166,7 @@ impl SensorInfo { .list() .skip_while(|ErrorEvent { start, .. }| start < &last) .cloned(); + let mut logs = self.logs_from_store.clone(); logs.extend(without_duplicates); logs } @@ -288,21 +301,23 @@ impl Readings { info.condition = Err(error.clone()); info.logs.add(&error); } else { - let errors = logs::Logs::new_from(&error); + let logs = logs::Logs::new_from(&error); self.data.insert( key, SensorInfo { info: broken.leaf(), reading: broken.clone(), timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), - percentiles_from_store: histogram::Stored::new(), + percentiles_from_store: Vec::new(), + histogram_range: None, recent_history: Vec::new(), history_from_store: Vec::new(), - logs_from_store: fetch::logs::Stored::new(), + logs_from_store: Vec::new(), + logs_from_store_hist: Option::None, condition: Err(error.clone()), - logs: errors, + logs, }, ); } @@ -329,11 +344,13 @@ impl Readings { info: reading.leaf(), reading, timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), - percentiles_from_store: histogram::Stored::new(), + percentiles_from_store: Vec::new(), + histogram_range: None, recent_history: history, history_from_store: Vec::new(), - logs_from_store: fetch::logs::Stored::new(), + logs_from_store: Vec::new(), + logs_from_store_hist: Option::None, condition: Ok(()), logs: logs::Logs::new_empty(), @@ -354,11 +371,13 @@ impl Readings { info: reading.leaf(), reading, timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), - percentiles_from_store: histogram::Stored::new(), + percentiles_from_store: Vec::new(), + histogram_range: None, recent_history: Vec::new(), history_from_store: Vec::new(), - logs_from_store: fetch::logs::Stored::new(), + logs_from_store: Vec::new(), + logs_from_store_hist: Option::None, condition: Ok(()), logs: logs::Logs::new_empty(), @@ -424,17 +443,23 @@ impl Readings { } } - pub(crate) fn add_fetched(&mut self, fetched: crate::Fetched) { + pub(crate) fn add_fetched(&mut self, reading: Reading, fetched: Fetchable) { + let sensorinfo = self + .data + .get_mut(&tree_key(&reading)) + .expect("data is never removed"); match fetched { - crate::Fetched::Data { - reading, - timestamps, - data, - } => { - self.data - .get_mut(&tree_key(&reading)) - .expect("data is never removed") - .history_from_store = timestamps.into_iter().zip(data.into_iter()).collect() + Fetchable::Data { timestamps, data } => { + sensorinfo.history_from_store = + timestamps.into_iter().zip(data.into_iter()).collect() + } + Fetchable::Logs { logs, start_at } => { + sensorinfo.logs_from_store = logs; + sensorinfo.logs_from_store_hist = Some(start_at); + } + Fetchable::Hist { percentiles, range } => { + sensorinfo.percentiles_from_store = percentiles; + sensorinfo.histogram_range = Some(range); } } } diff --git a/crates/sensor-tui/src/tui/reading/fetch.rs b/crates/sensor-tui/src/tui/reading/fetch.rs deleted file mode 100644 index d0f09bf6..00000000 --- a/crates/sensor-tui/src/tui/reading/fetch.rs +++ /dev/null @@ -1,14 +0,0 @@ -use std::sync::Arc; -use std::thread; -use std::time::Duration; -use tokio::sync::Notify; - -pub mod histogram; -pub mod logs; - -#[derive(Debug)] -struct Fetching { - handle: thread::JoinHandle<()>, - cancel: Arc, - history_length: Duration, -} diff --git a/crates/sensor-tui/src/tui/reading/fetch/histogram.rs b/crates/sensor-tui/src/tui/reading/fetch/histogram.rs deleted file mode 100644 index c15361a3..00000000 --- a/crates/sensor-tui/src/tui/reading/fetch/histogram.rs +++ /dev/null @@ -1,143 +0,0 @@ -use std::net::SocketAddr; -use std::sync::{Arc, Mutex}; -use std::thread; -use std::time::{Duration, Instant}; - -use log_store::api::Percentile; -use protocol::Device; -use tokio::sync::Notify; -use tokio::time::sleep; -use tracing::warn; - -use crate::client_name; -use crate::tui::history_len::{self, HistoryLen}; - -use super::Fetching; - -type Percentiles = Arc>>; - -#[derive(Debug)] -pub struct Stored { - last_fetch: Option, - last_update_started: Instant, - pub data: Percentiles, -} - -impl Stored { - pub fn new() -> Self { - Self { - last_fetch: None, - data: Arc::new(Mutex::new(Vec::new())), - // will update immediately anyway since data len is zero - last_update_started: Instant::now(), - } - } - - fn start_update(&mut self, device: Device, new_length: Duration, log_store: SocketAddr) { - if let Some(in_progress) = self.last_fetch.take() { - in_progress.cancel.notify_one(); - let _ = in_progress.handle.join(); - } - - let device = device.clone(); - let cancel = Arc::new(Notify::new()); - let cancelled = cancel.clone(); - let data = self.data.clone(); - let handle = thread::spawn(move || fetch(data, device, log_store, new_length, cancelled)); - self.last_fetch = Some(Fetching { - handle, - cancel, - history_length: new_length, - }); - self.last_update_started = Instant::now(); - } - - pub fn update_if_needed( - &mut self, - log_store: SocketAddr, - device: Device, - needed_hist: &mut HistoryLen, - ) { - if let Some(last_fetch) = &mut self.last_fetch { - let outdated = self.last_update_started.elapsed() > Duration::from_secs(5) - || self.data.lock().unwrap().is_empty(); - let finished = last_fetch.handle.is_finished(); - let params_changed = last_fetch.history_length != needed_hist.dur; - - if params_changed || (outdated && finished) { - self.start_update(device, needed_hist.dur, log_store); - needed_hist.state = history_len::State::Fetching(Instant::now()); - } - } else { - self.start_update(device, needed_hist.dur, log_store); - needed_hist.state = history_len::State::Fetching(Instant::now()); - } - - if let Some(last_fetch) = &mut self.last_fetch { - if last_fetch.handle.is_finished() { - needed_hist.state = history_len::State::Fetched - } - } - } - - pub(crate) fn very_outdated(&self) -> bool { - self.data.lock().unwrap().is_empty() - || self.last_update_started.elapsed() > Duration::from_secs(15) - } -} - -fn fetch( - histogram: Percentiles, - device: Device, - addr: SocketAddr, - length: Duration, - cancelled: Arc, -) { - let rt = tokio::runtime::Builder::new_current_thread() - .enable_io() - .enable_time() - .build() - .unwrap(); - - let Some(data) = rt.block_on(async { - tokio::select! { - data = connect_and_get_percentiles(addr, length, device) => Some(data), - _ = cancelled.notified() => None, - } - }) else { - return; - }; - - let mut histogram = histogram.lock().unwrap(); - *histogram = data -} - -async fn connect_and_get_percentiles( - addr: SocketAddr, - _: Duration, - device: Device, -) -> Vec { - let mut retry_period = Duration::ZERO; - loop { - sleep(retry_period).await; - retry_period = Duration::from_secs(5) - .min(retry_period * 2) - .max(Duration::from_millis(100)); - - let mut api = match log_store::api::Client::connect(addr, client_name()).await { - Ok(api) => api, - Err(e) => { - warn!("Could not connect to log_store (at {addr}): {e}"); - continue; - } - }; - - match api.get_percentiles(device.clone()).await { - Ok(res) => return res, - Err(e) => { - warn!("Error getting data from log-store, reconnecting: {e}"); - continue; - } - }; - } -} diff --git a/crates/sensor-tui/src/tui/reading/fetch/history.rs b/crates/sensor-tui/src/tui/reading/fetch/history.rs deleted file mode 100644 index 0aa4fa1a..00000000 --- a/crates/sensor-tui/src/tui/reading/fetch/history.rs +++ /dev/null @@ -1,148 +0,0 @@ -use protocol::Reading; - -use std::net::SocketAddr; -use std::sync::{Arc, Mutex}; -use std::thread; -use std::time::{Duration, Instant}; -use tokio::sync::Notify; -use tokio::time::sleep; -use tracing::{debug, warn}; - -use crate::client_name; -use crate::tui::history_len::{self, HistoryLen}; - -use super::Fetching; - -type Data = Arc>>; - -#[derive(Debug)] -pub struct Stored { - last_fetch: Option, - pub data: Data, -} - -impl Stored { - pub fn new() -> Self { - Self { - last_fetch: None, - data: Arc::new(Mutex::new(Vec::new())), - } - } - - fn start_update(&mut self, reading: Reading, new_length: Duration, data_store: SocketAddr) { - if let Some(in_progress) = self.last_fetch.take() { - in_progress.cancel.notify_one(); - let _ = in_progress.handle.join(); - debug!("Canceled running stored-history update"); - } - - let reading = reading.clone(); - let cancel = Arc::new(Notify::new()); - let cancelled = cancel.clone(); - let data = self.data.clone(); - let handle = thread::spawn(move || fetch(data, reading, data_store, new_length, cancelled)); - self.last_fetch = Some(Fetching { - handle, - cancel, - history_length: new_length, - }); - } - - pub fn update_if_needed( - &mut self, - data_store: SocketAddr, - reading: Reading, - needed_hist: &mut HistoryLen, - ) { - if let Some(last_fetch) = &mut self.last_fetch { - if last_fetch.history_length != needed_hist.dur { - self.start_update(reading, needed_hist.dur, data_store); - needed_hist.state = history_len::State::Fetching(Instant::now()); - } - } else { - self.start_update(reading, needed_hist.dur, data_store); - needed_hist.state = history_len::State::Fetching(Instant::now()); - } - - if let Some(last_fetch) = &self.last_fetch { - if last_fetch.handle.is_finished() { - needed_hist.state = history_len::State::Fetched - } - } - } -} - -fn fetch( - history: Arc>>, - reading: Reading, - addr: SocketAddr, - length: Duration, - cancelled: Arc, -) { - let rt = tokio::runtime::Builder::new_current_thread() - .enable_io() - .enable_time() - .build() - .unwrap(); - - let Some(data) = rt.block_on(async { - tokio::select! { - data = connect_and_get_data(addr, length, reading) => Some(data), - _ = cancelled.notified() => None, - } - }) else { - debug!("Canceled data fetch"); - return; - }; - - debug!( - "got data from {:?} till {:?}", - data.0.first(), - data.0.last() - ); - let mut history = history.lock().unwrap(); - history.clear(); - for (t, y) in data.0.into_iter().zip(data.1) { - history.push((t, y)) - } - debug!("done fetching {length:?}!"); -} - -async fn connect_and_get_data( - addr: SocketAddr, - length: Duration, - reading: Reading, -) -> (Vec, Vec) { - let mut retry_period = Duration::ZERO; - loop { - sleep(retry_period).await; - retry_period = Duration::from_secs(5) - .min(retry_period * 2) - .max(Duration::from_millis(100)); - - let mut api = match data_store::api::Client::connect(addr, client_name()).await { - Ok(api) => api, - Err(e) => { - warn!("Could not connect to data_store (at {addr}): {e}"); - continue; - } - }; - - match api - .get_data( - jiff::Timestamp::now() - - jiff::Span::default().milliseconds(length.as_millis() as i64), - jiff::Timestamp::now(), - reading.clone(), - 300, - ) - .await - { - Ok(res) => return res, - Err(e) => { - warn!("Error getting data from data-store, reconnecting: {e}"); - continue; - } - }; - } -} diff --git a/crates/sensor-tui/src/tui/reading/fetch/logs.rs b/crates/sensor-tui/src/tui/reading/fetch/logs.rs deleted file mode 100644 index e7db5511..00000000 --- a/crates/sensor-tui/src/tui/reading/fetch/logs.rs +++ /dev/null @@ -1,135 +0,0 @@ -use log_store::api::ErrorEvent; -use protocol::Reading; - -use std::net::SocketAddr; -use std::sync::{Arc, Mutex}; -use std::thread; -use std::time::{Duration, Instant}; -use tokio::sync::Notify; -use tokio::time::sleep; -use tracing::{debug, warn}; - -use crate::client_name; -use crate::tui::history_len::{self, HistoryLen}; - -use super::Fetching; - -type Data = Arc>>; - -#[derive(Debug)] -pub struct Stored { - last_fetch: Option, - pub logs: Data, -} - -impl Stored { - pub fn new() -> Self { - Self { - last_fetch: None, - logs: Arc::new(Mutex::new(Vec::new())), - } - } - - pub(crate) fn list(&self) -> Vec { - self.logs.lock().unwrap().clone() - } - - fn start_update(&mut self, reading: Reading, new_length: Duration, log_store: SocketAddr) { - if let Some(in_progress) = self.last_fetch.take() { - in_progress.cancel.notify_one(); - let _ = in_progress.handle.join(); - debug!("Canceled running stored-logs update"); - } - - let reading = reading.clone(); - let cancel = Arc::new(Notify::new()); - let cancelled = cancel.clone(); - let data = self.logs.clone(); - let handle = thread::spawn(move || fetch(data, reading, log_store, new_length, cancelled)); - self.last_fetch = Some(Fetching { - handle, - cancel, - history_length: new_length, - }); - } - - pub fn update_if_needed( - &mut self, - log_store: SocketAddr, - reading: Reading, - needed_hist: &mut HistoryLen, - ) { - if let Some(last_fetch) = &mut self.last_fetch { - if last_fetch.history_length != needed_hist.dur { - self.start_update(reading, needed_hist.dur, log_store); - needed_hist.state = history_len::State::Fetching(Instant::now()); - } - } else { - self.start_update(reading, needed_hist.dur, log_store); - needed_hist.state = history_len::State::Fetching(Instant::now()); - } - - if let Some(last_fetch) = &self.last_fetch { - if last_fetch.handle.is_finished() { - needed_hist.state = history_len::State::Fetched - } - } - } -} - -fn fetch( - logs: Arc>>, - reading: Reading, - addr: SocketAddr, - length: Duration, - cancelled: Arc, -) { - let rt = tokio::runtime::Builder::new_current_thread() - .enable_io() - .enable_time() - .build() - .unwrap(); - - let Some(data) = rt.block_on(async { - tokio::select! { - data = connect_and_get_data(addr, length, reading) => Some(data), - _ = cancelled.notified() => None, - } - }) else { - debug!("Canceled data fetch"); - return; - }; - - let mut logs = logs.lock().unwrap(); - *logs = data; -} - -async fn connect_and_get_data( - addr: SocketAddr, - _length: Duration, - reading: Reading, -) -> Vec { - let mut retry_period = Duration::ZERO; - loop { - sleep(retry_period).await; - retry_period = Duration::from_secs(5) - .min(retry_period * 2) - .max(Duration::from_millis(100)); - - let mut api = match log_store::api::Client::connect(addr, client_name()).await { - Ok(api) => api, - Err(e) => { - warn!("Could not connect to log_store (at {addr}): {e}"); - continue; - } - }; - - match api.get_logs(reading.device()).await { - Ok(res) => return res, - Err(e) => { - warn!("Error getting data from log-store, reconnecting: {e}"); - continue; - } - }; - } -} diff --git a/crates/sensor-tui/src/tui/reading/logs.rs b/crates/sensor-tui/src/tui/reading/logs.rs index 793b90a9..110838d0 100644 --- a/crates/sensor-tui/src/tui/reading/logs.rs +++ b/crates/sensor-tui/src/tui/reading/logs.rs @@ -1,4 +1,3 @@ - use jiff::Unit; use log_store::api::{self, ErrorEvent}; @@ -28,8 +27,12 @@ impl Logs { } } - pub(crate) fn add(&mut self, error: &protocol::Error) { + pub(crate) fn add(&mut self, new_error: &protocol::Error) { if let Some(ErrorEvent { start, error, .. }) = self.current.take() { + if &error == new_error { + return; + } + self.history.push(api::ErrorEvent { start, end: Some(jiff::Timestamp::now()), @@ -40,7 +43,7 @@ impl Logs { self.current = Some(ErrorEvent { start: jiff::Timestamp::now(), end: None, - error: error.clone(), + error: new_error.clone(), }) } diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs index ce120887..a1e12955 100644 --- a/crates/sensor-tui/src/tui/render.rs +++ b/crates/sensor-tui/src/tui/render.rs @@ -141,11 +141,11 @@ fn render_graph_hist_logs( if chart.is_some() { constraints[0] = Constraint::Fill(10); } - if logs.is_some() && app.show_logs { + if logs.as_ref().is_some_and(|logs| !logs.is_empty()) && app.show_logs { constraints[1] = Constraint::Fill(10); } if !histogram.is_empty() && app.show_histogram { - let idx = 1 + app.show_histogram as usize; + let idx = 1 + app.show_logs as usize; constraints[idx] = Constraint::Fill(10); } From ce1e5af3cdc2c08f694ec6dfc6f8cbe2a613ed30 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 15 Aug 2024 22:57:03 +0200 Subject: [PATCH 196/687] update deps and prevent weight sensor spamming + make error path wait before retry --- Cargo.lock | 13 +++++- sensor-nodes/bed-sensors/Cargo.lock | 44 +++++++++---------- sensor-nodes/bed-sensors/Cargo.toml | 23 +++++----- sensor-nodes/bed-sensors/src/sensors/fast.rs | 2 +- .../src/sensors/retry/reinit_on_error.rs | 4 ++ 5 files changed, 50 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0cf7cecf..58350e98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -600,9 +600,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292" +checksum = "5fb8dd288a69fc53a1996d7ecfbf4a20d59065bff137ce7e56bbd620de191189" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -3090,6 +3093,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook" version = "0.3.17" diff --git a/sensor-nodes/bed-sensors/Cargo.lock b/sensor-nodes/bed-sensors/Cargo.lock index 24b9b5ca..8cf9228b 100644 --- a/sensor-nodes/bed-sensors/Cargo.lock +++ b/sensor-nodes/bed-sensors/Cargo.lock @@ -288,8 +288,8 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" -version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "defmt", "embassy-futures", @@ -305,8 +305,8 @@ dependencies = [ [[package]] name = "embassy-executor" -version = "0.5.0" -source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" +version = "0.6.0" +source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "cortex-m", "critical-section", @@ -319,8 +319,8 @@ dependencies = [ [[package]] name = "embassy-executor-macros" -version = "0.4.1" -source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" +version = "0.5.0" +source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "darling", "proc-macro2", @@ -331,12 +331,12 @@ dependencies = [ [[package]] name = "embassy-futures" version = "0.1.1" -source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" +source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" [[package]] name = "embassy-hal-internal" -version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "cortex-m", "critical-section", @@ -347,7 +347,7 @@ dependencies = [ [[package]] name = "embassy-net" version = "0.4.0" -source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" +source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "defmt", "document-features", @@ -364,15 +364,15 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" +source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "defmt", ] [[package]] name = "embassy-net-driver-channel" -version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" +version = "0.3.0" +source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "embassy-futures", "embassy-net-driver", @@ -382,7 +382,7 @@ dependencies = [ [[package]] name = "embassy-net-wiznet" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" +source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "defmt", "embassy-futures", @@ -395,7 +395,7 @@ dependencies = [ [[package]] name = "embassy-stm32" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" +source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "bit_field", "bitflags 2.5.0", @@ -439,7 +439,7 @@ dependencies = [ [[package]] name = "embassy-sync" version = "0.6.0" -source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" +source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "cfg-if", "critical-section", @@ -451,8 +451,8 @@ dependencies = [ [[package]] name = "embassy-time" -version = "0.3.1" -source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" +version = "0.3.2" +source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "cfg-if", "critical-section", @@ -470,7 +470,7 @@ dependencies = [ [[package]] name = "embassy-time-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" +source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "document-features", ] @@ -478,12 +478,12 @@ dependencies = [ [[package]] name = "embassy-time-queue-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" +source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" [[package]] name = "embassy-usb-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" +source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "defmt", ] @@ -491,7 +491,7 @@ dependencies = [ [[package]] name = "embassy-usb-synopsys-otg" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=2537fc6#2537fc6f4fcbdaa0fcea45a37382d61f59cc5767" +source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "critical-section", "embassy-sync", diff --git a/sensor-nodes/bed-sensors/Cargo.toml b/sensor-nodes/bed-sensors/Cargo.toml index 4badc186..d6eb797d 100644 --- a/sensor-nodes/bed-sensors/Cargo.toml +++ b/sensor-nodes/bed-sensors/Cargo.toml @@ -12,10 +12,10 @@ embassy-stm32 = { version = "0.1.0", features = [ "defmt", "stm32f401cc", embassy-net = { version = "0.4.0", features = ["defmt", "proto-ipv4", "tcp", "dhcpv4","medium-ethernet"] } embassy-net-wiznet = { version = "0.1.0", features = ["defmt"] } embassy-sync = { version = "0.6.0", features = ["defmt"] } -embassy-executor = { version = "0.5.0", features = ["arch-cortex-m", +embassy-executor = { version = "0.6.0", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers", "executor-interrupt"] } -embassy-embedded-hal = { version = "0.1.0" } -embassy-time = { version = "0.3.0", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-embedded-hal = { version = "0.2.0" } +embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-futures = { version = "0.1.0"} defmt = "0.3" @@ -52,15 +52,16 @@ rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } # fasthash = { version = "0.4.0", default-features = false } [patch.crates-io] -embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "2537fc6" } -embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "2537fc6" } -embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "2537fc6" } -embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "2537fc6" } -embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "2537fc6" } -embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "2537fc6" } -embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "2537fc6" } -embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "2537fc6" } +embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +# [patch.crates-io] # embassy-stm32 = {path = "../../../embassy/embassy-stm32" } # embassy-net = {path = "../../../embassy/embassy-net" } # embassy-net-wiznet = {path = "../../../embassy/embassy-net-wiznet" } diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed-sensors/src/sensors/fast.rs index b5c01f93..745a7ee0 100644 --- a/sensor-nodes/bed-sensors/src/sensors/fast.rs +++ b/sensor-nodes/bed-sensors/src/sensors/fast.rs @@ -16,7 +16,7 @@ fn sig_lux_diff(old: f32, new: f32) -> bool { fn sig_weight_diff(old: u32, new: u32) -> bool { let diff = new.abs_diff(old); - diff > 20 + diff > 2000 } async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues) { diff --git a/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs b/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs index a53e787a..d0c3bf79 100644 --- a/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs +++ b/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs @@ -102,6 +102,10 @@ async fn advance_state( } } Err(err) => { + // drivers might contain blocking code in their + // error path, this makes sure the executor + // will not block on retrying. + embassy_time::Timer::after_millis(250).await; let new_state = State::Uninit; let err = Error::Setup(err); (new_state, Err(err)) From dc0f73924ac938551e1a8f30d7f10f2bae83d833 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 16 Aug 2024 20:55:46 +0200 Subject: [PATCH 197/687] refactor protocol, turn large lib into multiple modules --- crates/protocol/src/affector.rs | 42 ++++ crates/protocol/src/device.rs | 31 +++ crates/protocol/src/error.rs | 42 ++++ crates/protocol/src/error_tomato.rs | 39 ---- crates/protocol/src/large_bedroom.rs | 5 +- crates/protocol/src/lib.rs | 297 ++------------------------- crates/protocol/src/msg.rs | 78 +++++++ crates/protocol/src/msg/error.rs | 57 +++++ crates/protocol/src/msg/sensor.rs | 57 +++++ crates/protocol/src/reading.rs | 58 ++++++ 10 files changed, 386 insertions(+), 320 deletions(-) create mode 100644 crates/protocol/src/affector.rs create mode 100644 crates/protocol/src/device.rs create mode 100644 crates/protocol/src/error.rs delete mode 100644 crates/protocol/src/error_tomato.rs create mode 100644 crates/protocol/src/msg.rs create mode 100644 crates/protocol/src/msg/error.rs create mode 100644 crates/protocol/src/msg/sensor.rs create mode 100644 crates/protocol/src/reading.rs diff --git a/crates/protocol/src/affector.rs b/crates/protocol/src/affector.rs new file mode 100644 index 00000000..c3374e3b --- /dev/null +++ b/crates/protocol/src/affector.rs @@ -0,0 +1,42 @@ +use postcard::accumulator::{CobsAccumulator, FeedResult}; +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +use crate::large_bedroom; +use crate::msg::cobs_overhead; + +#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] +pub enum Affector { + LargeBedroom(large_bedroom::Affector), +} + +impl Affector { + const ENCODED_SIZE: usize = + Affector::POSTCARD_MAX_SIZE + cobs_overhead(Affector::POSTCARD_MAX_SIZE); +} + +pub struct Decoder { + cobs_buf: CobsAccumulator<{ Affector::ENCODED_SIZE }>, +} + +impl Decoder { + pub fn new() -> Self { + Self { + cobs_buf: CobsAccumulator::new(), + } + } + + /// if this returns Some(_, remaining) move the remaining into it again + pub fn feed<'a>(&mut self, read_bytes: &'a [u8]) -> Option<(Affector, &'a [u8])> { + let mut window = read_bytes; + while !window.is_empty() { + window = match self.cobs_buf.feed::(read_bytes) { + FeedResult::Consumed => break, + FeedResult::OverFull(new_window) => new_window, + FeedResult::DeserError(new_window) => new_window, + FeedResult::Success { data, remaining } => return Some((data, remaining)), + } + } + None + } +} diff --git a/crates/protocol/src/device.rs b/crates/protocol/src/device.rs new file mode 100644 index 00000000..8aab842f --- /dev/null +++ b/crates/protocol/src/device.rs @@ -0,0 +1,31 @@ +use core::time::Duration; + +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +use crate::{large_bedroom, small_bedroom, Reading}; + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, PartialEq, Eq, Hash)] +pub enum Device { + LargeBedroom(large_bedroom::Device), + SmallBedroom(small_bedroom::Device), +} +impl Device { + #[must_use] + pub const fn info(&self) -> DeviceInfo { + match self { + Device::LargeBedroom(dev) => dev.info(), + Device::SmallBedroom(dev) => dev.info(), + } + } +} + +#[derive(Debug)] +pub struct DeviceInfo { + pub name: &'static str, + pub affects_readings: &'static [Reading], + pub min_sample_interval: Duration, + pub max_sample_interval: Duration, + pub temporal_resolution: Duration, +} + diff --git a/crates/protocol/src/error.rs b/crates/protocol/src/error.rs new file mode 100644 index 00000000..a84dd378 --- /dev/null +++ b/crates/protocol/src/error.rs @@ -0,0 +1,42 @@ +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +use crate::{large_bedroom, Device}; + +#[derive( + strum::EnumDiscriminants, + strum::VariantNames, + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, + Eq, +)] +pub enum Error { + LargeBedroom(large_bedroom::Error), +} + +impl Error { + #[must_use] + pub fn device(&self) -> Device { + match self { + Error::LargeBedroom(error) => Device::LargeBedroom(error.device()), + } + } + + #[must_use] + pub const fn max_size() -> usize { + Self::POSTCARD_MAX_SIZE + } +} + +impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Error::LargeBedroom(error) => write!(f, "{error}"), + } + } +} diff --git a/crates/protocol/src/error_tomato.rs b/crates/protocol/src/error_tomato.rs deleted file mode 100644 index 034d12ed..00000000 --- a/crates/protocol/src/error_tomato.rs +++ /dev/null @@ -1,39 +0,0 @@ -pub type ErrorTomatoId = u8; -#[derive(Debug)] -pub enum ErrorTomatoItem<'a> { - Leaf(String), - Node(&'a dyn ErrorTomato), -} - -pub trait ErrorTomato: core::fmt::Debug { - fn inner<'a>(&'a self) -> ErrorTomatoItem<'a>; - fn name(&self) -> String { - let dbg_repr = format!("{:?}", self); - dbg_repr - .split_once('(') - .map(|(name, _)| name) - .unwrap_or("-") - .to_string() - } - fn id(&self) -> ErrorTomatoId; -} - -macro_rules! error_all_nodes { - ($name:ident; $variant:ident; $($var:ident),*) => { - impl crate::error_tomato::ErrorTomato for $name { - fn inner<'a>(&'a self) -> crate::error_tomato::ErrorTomatoItem<'a> { - match self { - $( - $name::$var(inner) => crate::error_tomato::ErrorTomatoItem::Node(inner as &dyn crate::error_tomato::ErrorTomato) - ),* - } - } - - fn id(&self) -> crate::error_tomato::ErrorTomatoId { - $variant::from(self) as crate::error_tomato::ErrorTomatoId - } - } - }; -} - -pub(crate) use error_all_nodes; diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index 5082ea60..45b1d9ee 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -1,6 +1,7 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; +use crate::msg::DecodeMsgError; #[cfg(feature = "alloc")] use crate::reading_tree; @@ -98,8 +99,8 @@ impl Affector { postcard::to_slice_cobs(self, buf).expect("Encoding should not fail") } - pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { - postcard::from_bytes_cobs(bytes.as_mut()).map_err(crate::DecodeError::CorruptEncoding) + pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { + postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeMsgError::CorruptEncoding) } #[must_use] diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 93499f17..638aa985 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -2,19 +2,30 @@ #![allow(clippy::missing_panics_doc, clippy::missing_errors_doc)] use core::fmt::Display; -use core::time::Duration; -use postcard::experimental::max_size::MaxSize; -use serde::{Deserialize, Serialize}; +#[cfg(feature = "alloc")] +pub mod reading_tree; +pub mod button; +pub(crate) use button::button_enum; pub mod large_bedroom; pub mod small_bedroom; -pub mod button; -pub(crate) use button::button_enum; +mod reading; +mod device; +mod error; +pub mod affector; + +mod msg; +pub use msg::{Msg, DecodeMsgError}; +pub use msg::sensor::SensorMessage; +pub use msg::error::ErrorReport; +pub use msg::error::make_error_string; +pub use reading::Reading; +pub use device::{Device, DeviceInfo}; +pub use error::Error; +pub use affector::Affector; -#[cfg(feature = "alloc")] -pub mod reading_tree; #[derive(Debug, Clone)] pub enum Unit { @@ -46,275 +57,3 @@ impl Display for Unit { } } } - -#[derive( - strum::EnumDiscriminants, - strum::VariantNames, - Clone, - Debug, - defmt::Format, - Serialize, - Deserialize, - MaxSize, - PartialEq, -)] -#[strum_discriminants(derive(Hash))] -pub enum Reading { - LargeBedroom(large_bedroom::Reading), - SmallBedroom(small_bedroom::Reading), - // Test, -} - -#[cfg(feature = "alloc")] -impl Reading { - #[must_use] - pub fn from_same_device(&self) -> &'static [Reading] { - use reading_tree::Tree; - self.leaf().from_same_device() - } - #[must_use] - pub fn range(&self) -> core::ops::Range { - use reading_tree::Tree; - self.leaf().range - } - #[must_use] - /// the step between the two closest datapoints that are not the same - pub fn resolution(&self) -> f32 { - use reading_tree::Tree; - self.leaf().resolution - } - #[must_use] - pub fn device(&self) -> Device { - use reading_tree::Tree; - self.leaf().device - } -} -impl Reading { - #[must_use] - pub fn version() -> u8 { - 0u8 - } -} - -#[cfg(feature = "alloc")] -reading_tree::all_nodes! {Reading; ReadingDiscriminants; LargeBedroom, SmallBedroom} - -#[derive( - strum::EnumDiscriminants, - strum::VariantNames, - Clone, - Debug, - defmt::Format, - Serialize, - Deserialize, - MaxSize, - PartialEq, - Eq, -)] -pub enum Error { - LargeBedroom(large_bedroom::Error), -} - -impl Error { - #[must_use] - pub fn device(&self) -> Device { - match self { - Error::LargeBedroom(error) => Device::LargeBedroom(error.device()), - } - } - - #[must_use] - pub const fn max_size() -> usize { - Self::POSTCARD_MAX_SIZE - } -} - -impl Display for Error { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - Error::LargeBedroom(error) => write!(f, "{error}"), - } - } -} - -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, PartialEq, Eq, Hash)] -pub enum Device { - LargeBedroom(large_bedroom::Device), - SmallBedroom(small_bedroom::Device), -} -impl Device { - #[must_use] - pub const fn info(&self) -> DeviceInfo { - match self { - Device::LargeBedroom(dev) => dev.info(), - Device::SmallBedroom(dev) => dev.info(), - } - } -} - -#[derive(Debug)] -pub struct DeviceInfo { - pub name: &'static str, - pub affects_readings: &'static [Reading], - pub min_sample_interval: Duration, - pub max_sample_interval: Duration, - pub temporal_resolution: Duration, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct SensorMessage { - pub values: heapless::Vec, - pub version: u8, -} - -#[allow(clippy::large_enum_variant)] // can not use Box on embedded -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ErrorReport { - pub error: Error, - pub version: u8, -} - -#[derive(Debug)] -#[allow(clippy::large_enum_variant)] // can not use Box on embedded -pub enum Msg { - Readings(SensorMessage), - ErrorReport(ErrorReport), -} - -impl Msg { - pub const READINGS: u8 = 1; - pub const ERROR_REPORT: u8 = 2; - - #[must_use] - pub fn header(&self) -> u8 { - let header = match self { - Msg::Readings(_) => Self::READINGS, - Msg::ErrorReport(_) => Self::ERROR_REPORT, - }; - assert_ne!(header, 0, "0 is reserved for cobs encoding"); - header - } - - pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { - let bytes = bytes.as_mut(); - assert!(!bytes.is_empty(), "can not decode nothing (zero bytes)"); - - let msg_type = bytes[0]; - let bytes = &mut bytes[1..]; - - if msg_type == Self::READINGS { - Ok(Self::Readings(SensorMessage::::decode(bytes)?)) - } else if msg_type == Self::ERROR_REPORT { - Ok(Self::ErrorReport(ErrorReport::decode(bytes)?)) - } else { - Err(DecodeError::IncorrectMsgType(msg_type)) - } - } - - #[cfg(feature = "alloc")] - #[must_use] - pub fn encode(&self) -> Vec { - let mut bytes = match self { - Msg::Readings(readings) => readings.encode(), - Msg::ErrorReport(report) => report.encode(), - }; - - bytes.insert(0, self.header()); - bytes - } -} - -#[derive(Debug, Clone)] -#[cfg_attr(feature = "thiserror", derive(thiserror::Error))] -pub enum DecodeError { - #[cfg_attr(feature = "thiserror", error("Could not decode SensorMessage: {0}"))] - CorruptEncoding(postcard::Error), - #[cfg_attr( - feature = "thiserror", - error("Got an unknown message type, expected zero or one got: {0}") - )] - IncorrectMsgType(u8), -} - -impl Default for SensorMessage { - fn default() -> Self { - Self { - values: heapless::Vec::new(), - version: 0, - } - } -} -impl SensorMessage { - /// the 2x is the max overhead from COBS encoding the encoded data - /// +2 is for the version - /// +4 covers the length of the heapless list - pub const ENCODED_SIZE: usize = 2 * (MAX_ITEMS * Reading::POSTCARD_MAX_SIZE + 2 + 4); - - #[must_use] - pub fn space_left(&self) -> bool { - self.values.len() < self.values.capacity() - } - - #[cfg(feature = "alloc")] - #[must_use] - pub fn encode(&self) -> Vec { - postcard::to_allocvec_cobs(self).expect("Encoding should not fail") - } - - /// Buffer should be at least `Self::ENCODED_SIZE` long. The returned slice contains - /// the serialized data. It can be shorter then the input buffer. - #[must_use] - pub fn encode_slice<'a>(&self, buf: &'a mut [u8]) -> &'a mut [u8] { - postcard::to_slice_cobs(self, buf).expect("Encoding should not fail") - } - - pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { - postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeError::CorruptEncoding) - } - - #[must_use] - pub fn version(&self) -> u8 { - self.version - } -} - -impl ErrorReport { - /// the 2x is the max overhead from COBS encoding the encoded data - /// +2 is for the version - /// +4 covers the length of the heapless list - pub const ENCODED_SIZE: usize = 2 * (Error::POSTCARD_MAX_SIZE + 2); - - #[must_use] - pub fn new(error: Error) -> Self { - Self { error, version: 0 } - } - - #[cfg(feature = "alloc")] - #[must_use] - pub fn encode(&self) -> Vec { - postcard::to_allocvec_cobs(self).expect("Encoding should not fail") - } - - /// Buffer should be at least `Self::ENCODED_SIZE` long. The returned slice contains - /// the serialized data. It can be shorter then the input buffer. - #[must_use] - pub fn encode_slice<'a>(&self, buf: &'a mut [u8]) -> &'a mut [u8] { - postcard::to_slice_cobs(self, buf).expect("Encoding should not fail") - } - - pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { - postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeError::CorruptEncoding) - } -} - -pub type ErrorString = heapless::String<200>; -// thiserror does not work on nostd. That will change when this lands: -// https://github.com/rust-lang/rust/issues/103765 -// at that point try switching this to fmt::Display -pub fn make_error_string(e: impl core::fmt::Debug) -> ErrorString { - use core::fmt::Write; - - let mut s = ErrorString::new(); - core::write!(s, "{e:?}").ok(); - s -} diff --git a/crates/protocol/src/msg.rs b/crates/protocol/src/msg.rs new file mode 100644 index 00000000..73656218 --- /dev/null +++ b/crates/protocol/src/msg.rs @@ -0,0 +1,78 @@ +pub(crate) mod error; +pub(crate) mod sensor; + +#[derive(Debug)] +#[allow(clippy::large_enum_variant)] // can not use Box on embedded +pub enum Msg { + Readings(sensor::SensorMessage), + ErrorReport(error::ErrorReport), +} + +impl Msg { + pub const READINGS: u8 = 1; + pub const ERROR_REPORT: u8 = 2; + + #[must_use] + pub fn header(&self) -> u8 { + let header = match self { + Msg::Readings(_) => Self::READINGS, + Msg::ErrorReport(_) => Self::ERROR_REPORT, + }; + assert_ne!(header, 0, "0 is reserved for cobs encoding"); + header + } + + pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { + let bytes = bytes.as_mut(); + assert!(!bytes.is_empty(), "can not decode nothing (zero bytes)"); + + let msg_type = bytes[0]; + let bytes = &mut bytes[1..]; + + if msg_type == Self::READINGS { + Ok(Self::Readings(sensor::SensorMessage::::decode(bytes)?)) + } else if msg_type == Self::ERROR_REPORT { + Ok(Self::ErrorReport(error::ErrorReport::decode(bytes)?)) + } else { + Err(DecodeMsgError::IncorrectMsgType(msg_type)) + } + } + + #[cfg(feature = "alloc")] + #[must_use] + pub fn encode(&self) -> Vec { + let mut bytes = match self { + Msg::Readings(readings) => readings.encode(), + Msg::ErrorReport(report) => report.encode(), + }; + + bytes.insert(0, self.header()); + bytes + } +} + +#[derive(Debug, Clone)] +#[cfg_attr(feature = "thiserror", derive(thiserror::Error))] +pub enum DecodeMsgError { + #[cfg_attr(feature = "thiserror", error("Could not decode SensorMessage: {0}"))] + CorruptEncoding(postcard::Error), + #[cfg_attr( + feature = "thiserror", + error("Got an unknown message type, expected zero or one got: {0}") + )] + IncorrectMsgType(u8), +} + +pub(crate) const fn max(a: usize, b: usize) -> usize { + [a, b][(a < b) as usize] +} + +pub(crate) const fn cobs_overhead(uncobsed_size: usize) -> usize { + // COBS requires a minimum of 1 byte overhead, and a maximum of ⌈n/254⌉ + // bytes for n data bytes (one byte in 254, rounded up). (wiki) + + // div_ceil does not round up to one for zero, but messages of 0 bytes + // make no sense + assert!(uncobsed_size > 0, "does not support zero length messages"); + uncobsed_size.div_ceil(254) +} diff --git a/crates/protocol/src/msg/error.rs b/crates/protocol/src/msg/error.rs new file mode 100644 index 00000000..66f36245 --- /dev/null +++ b/crates/protocol/src/msg/error.rs @@ -0,0 +1,57 @@ +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +use crate::Error; + +use super::{cobs_overhead, DecodeMsgError}; + +#[allow(clippy::large_enum_variant)] // can not use Box on embedded +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ErrorReport { + pub error: Error, + pub version: u8, +} + +impl ErrorReport { + /// +2 is for the version + /// cobs encoding still needed + const HALF_ENCODED_SIZE: usize = Error::POSTCARD_MAX_SIZE + 2; + + /// cobs and postcard encoded + pub const ENCODED_SIZE: usize = + Self::HALF_ENCODED_SIZE + cobs_overhead(Self::HALF_ENCODED_SIZE); + + #[must_use] + pub fn new(error: Error) -> Self { + Self { error, version: 0 } + } + + #[cfg(feature = "alloc")] + #[must_use] + pub fn encode(&self) -> Vec { + postcard::to_allocvec_cobs(self).expect("Encoding should not fail") + } + + /// Buffer should be at least `Self::ENCODED_SIZE` long. The returned slice contains + /// the serialized data. It can be shorter then the input buffer. + #[must_use] + pub fn encode_slice<'a>(&self, buf: &'a mut [u8]) -> &'a mut [u8] { + postcard::to_slice_cobs(self, buf).expect("Encoding should not fail") + } + + pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { + postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeMsgError::CorruptEncoding) + } +} + +pub type ErrorString = heapless::String<200>; +// thiserror does not work on nostd. That will change when this lands: +// https://github.com/rust-lang/rust/issues/103765 +// at that point try switching this to fmt::Display +pub fn make_error_string(e: impl core::fmt::Debug) -> ErrorString { + use core::fmt::Write; + + let mut s = ErrorString::new(); + core::write!(s, "{e:?}").ok(); + s +} diff --git a/crates/protocol/src/msg/sensor.rs b/crates/protocol/src/msg/sensor.rs new file mode 100644 index 00000000..7d8bdfb3 --- /dev/null +++ b/crates/protocol/src/msg/sensor.rs @@ -0,0 +1,57 @@ +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +use crate::Reading; + +use super::{cobs_overhead, DecodeMsgError}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SensorMessage { + pub values: heapless::Vec, + pub version: u8, +} + +impl Default for SensorMessage { + fn default() -> Self { + Self { + values: heapless::Vec::new(), + version: 0, + } + } +} +impl SensorMessage { + /// +2 is for the version + /// +4 covers the length of the heapless list + pub const HALF_ENCODED_SIZE: usize = (MAX_ITEMS * Reading::POSTCARD_MAX_SIZE + 2 + 4); + + /// cobs and postcard encoded + pub const ENCODED_SIZE: usize = + Self::HALF_ENCODED_SIZE + cobs_overhead(Self::HALF_ENCODED_SIZE); + + #[must_use] + pub fn space_left(&self) -> bool { + self.values.len() < self.values.capacity() + } + + #[cfg(feature = "alloc")] + #[must_use] + pub fn encode(&self) -> Vec { + postcard::to_allocvec_cobs(self).expect("Encoding should not fail") + } + + /// Buffer should be at least `Self::ENCODED_SIZE` long. The returned slice contains + /// the serialized data. It can be shorter then the input buffer. + #[must_use] + pub fn encode_slice<'a>(&self, buf: &'a mut [u8]) -> &'a mut [u8] { + postcard::to_slice_cobs(self, buf).expect("Encoding should not fail") + } + + pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { + postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeMsgError::CorruptEncoding) + } + + #[must_use] + pub fn version(&self) -> u8 { + self.version + } +} diff --git a/crates/protocol/src/reading.rs b/crates/protocol/src/reading.rs new file mode 100644 index 00000000..f1b2f3b9 --- /dev/null +++ b/crates/protocol/src/reading.rs @@ -0,0 +1,58 @@ +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +use crate::{large_bedroom, small_bedroom}; +#[cfg(feature = "alloc")] +use crate::Device; + +#[derive( + strum::EnumDiscriminants, + strum::VariantNames, + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, +)] +#[strum_discriminants(derive(Hash))] +pub enum Reading { + LargeBedroom(large_bedroom::Reading), + SmallBedroom(small_bedroom::Reading), + // Test, +} + +#[cfg(feature = "alloc")] +impl Reading { + #[must_use] + pub fn from_same_device(&self) -> &'static [Reading] { + use crate::reading_tree::Tree; + self.leaf().from_same_device() + } + #[must_use] + pub fn range(&self) -> core::ops::Range { + use crate::reading_tree::Tree; + self.leaf().range + } + #[must_use] + /// the step between the two closest datapoints that are not the same + pub fn resolution(&self) -> f32 { + use crate::reading_tree::Tree; + self.leaf().resolution + } + #[must_use] + pub fn device(&self) -> Device { + use crate::reading_tree::Tree; + self.leaf().device + } +} +impl Reading { + #[must_use] + pub fn version() -> u8 { + 0u8 + } +} + +#[cfg(feature = "alloc")] +crate::reading_tree::all_nodes! {Reading; ReadingDiscriminants; LargeBedroom, SmallBedroom} From 3e97aab01e81db80cf7bcd7a69ab9970ea9ef345 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 16 Aug 2024 21:05:04 +0200 Subject: [PATCH 198/687] fixes random disconnects by removing socket_timeout also introduce sensor reading The socket timeout was set to Some(5s) and we send updates about every 5 seconds. This meant it timed out after a seemingly random time. In practise it timed out when sensor updates aligned such that > 5s was between the socket being used. --- sensor-nodes/bed-sensors/Cargo.lock | 16 ----- sensor-nodes/bed-sensors/Cargo.toml | 46 ++++++++------- sensor-nodes/bed-sensors/src/main.rs | 23 +++----- sensor-nodes/bed-sensors/src/network.rs | 78 +++++++++++++------------ 4 files changed, 76 insertions(+), 87 deletions(-) diff --git a/sensor-nodes/bed-sensors/Cargo.lock b/sensor-nodes/bed-sensors/Cargo.lock index 8cf9228b..068e730f 100644 --- a/sensor-nodes/bed-sensors/Cargo.lock +++ b/sensor-nodes/bed-sensors/Cargo.lock @@ -289,7 +289,6 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "defmt", "embassy-futures", @@ -306,7 +305,6 @@ dependencies = [ [[package]] name = "embassy-executor" version = "0.6.0" -source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "cortex-m", "critical-section", @@ -320,7 +318,6 @@ dependencies = [ [[package]] name = "embassy-executor-macros" version = "0.5.0" -source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "darling", "proc-macro2", @@ -331,12 +328,10 @@ dependencies = [ [[package]] name = "embassy-futures" version = "0.1.1" -source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" [[package]] name = "embassy-hal-internal" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "cortex-m", "critical-section", @@ -347,7 +342,6 @@ dependencies = [ [[package]] name = "embassy-net" version = "0.4.0" -source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "defmt", "document-features", @@ -364,7 +358,6 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "defmt", ] @@ -372,7 +365,6 @@ dependencies = [ [[package]] name = "embassy-net-driver-channel" version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "embassy-futures", "embassy-net-driver", @@ -382,7 +374,6 @@ dependencies = [ [[package]] name = "embassy-net-wiznet" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "defmt", "embassy-futures", @@ -395,7 +386,6 @@ dependencies = [ [[package]] name = "embassy-stm32" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "bit_field", "bitflags 2.5.0", @@ -439,7 +429,6 @@ dependencies = [ [[package]] name = "embassy-sync" version = "0.6.0" -source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "cfg-if", "critical-section", @@ -452,7 +441,6 @@ dependencies = [ [[package]] name = "embassy-time" version = "0.3.2" -source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "cfg-if", "critical-section", @@ -470,7 +458,6 @@ dependencies = [ [[package]] name = "embassy-time-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "document-features", ] @@ -478,12 +465,10 @@ dependencies = [ [[package]] name = "embassy-time-queue-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" [[package]] name = "embassy-usb-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "defmt", ] @@ -491,7 +476,6 @@ dependencies = [ [[package]] name = "embassy-usb-synopsys-otg" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=7a26e11#7a26e117ccd5f8669548cc8c2424be4691c1c402" dependencies = [ "critical-section", "embassy-sync", diff --git a/sensor-nodes/bed-sensors/Cargo.toml b/sensor-nodes/bed-sensors/Cargo.toml index d6eb797d..532465b9 100644 --- a/sensor-nodes/bed-sensors/Cargo.toml +++ b/sensor-nodes/bed-sensors/Cargo.toml @@ -8,14 +8,15 @@ authors = ["David Kleingeld & Eva van Houten"] [dependencies] embassy-stm32 = { version = "0.1.0", features = [ "defmt", "stm32f401cc", -"unstable-pac", "memory-x", "time-driver-tim1", "time", "exti" ] } +"unstable-pac", "memory-x", "time-driver-any", "time", "exti" ] } embassy-net = { version = "0.4.0", features = ["defmt", "proto-ipv4", "tcp", "dhcpv4","medium-ethernet"] } embassy-net-wiznet = { version = "0.1.0", features = ["defmt"] } embassy-sync = { version = "0.6.0", features = ["defmt"] } embassy-executor = { version = "0.6.0", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers", "executor-interrupt"] } embassy-embedded-hal = { version = "0.2.0" } -embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-time = { version = "0.3.2", features = ["defmt", +"defmt-timestamp-uptime-ms", "tick-hz-32_768"] } embassy-futures = { version = "0.1.0"} defmt = "0.3" @@ -51,25 +52,30 @@ stm32f4 = { version = "0.15.1", default-features = false, features = ["stm32f401 rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } # fasthash = { version = "0.4.0", default-features = false } -[patch.crates-io] -embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } -embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } -embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } -embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } -embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } -embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } -embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } -embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } - # [patch.crates-io] -# embassy-stm32 = {path = "../../../embassy/embassy-stm32" } -# embassy-net = {path = "../../../embassy/embassy-net" } -# embassy-net-wiznet = {path = "../../../embassy/embassy-net-wiznet" } -# embassy-sync = {path = "../../../embassy/embassy-sync" } -# embassy-executor = {path = "../../../embassy/embassy-executor" } -# embassy-embedded-hal = {path = "../../../embassy/embassy-embedded-hal" } -# embassy-time = {path = "../../../embassy/embassy-time" } -# embassy-futures = {path = "../../../embassy/embassy-futures" } +# embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +# embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +# embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +# embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +# embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +# embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +# embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +# embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +# embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +# embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } + +# [patch.'https://github.com/embassy-rs/embassy.git'] +[patch.crates-io] +embassy-stm32 = {path = "../../../embassy/embassy-stm32" } +embassy-net = {path = "../../../embassy/embassy-net" } +embassy-net-wiznet = {path = "../../../embassy/embassy-net-wiznet" } +embassy-sync = {path = "../../../embassy/embassy-sync" } +embassy-executor = {path = "../../../embassy/embassy-executor" } +embassy-embedded-hal = {path = "../../../embassy/embassy-embedded-hal" } +embassy-time = {path = "../../../embassy/embassy-time" } +embassy-futures = {path = "../../../embassy/embassy-futures" } +embassy-time-driver = {path = "../../../embassy/embassy-time-driver"} +embassy-time-queue-driver = {path = "../../../embassy/embassy-time-queue-driver"} [profile.dev] opt-level = "s" diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index 97613634..8899880d 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -1,7 +1,6 @@ #![no_std] #![no_main] -use defmt::{error, trace, unwrap}; use embassy_executor::Spawner; use embassy_futures::select; use embassy_futures::select::Either; @@ -25,6 +24,7 @@ use futures::pin_mut; use heapless::Vec; use static_cell::StaticCell; +use defmt::{error, trace, unwrap}; use {defmt_rtt as _, panic_probe as _}; mod channel; @@ -88,7 +88,6 @@ async fn main(spawner: Spawner) { let p = embassy_stm32::init(config()); let seed = rng::generate_seed_blocking(); defmt::info!("random seed: {}", seed); - // let dog = IndependentWatchdog::new(p.IWDG, 20 * 1000 * 1000); let mut usart_config = usart::Config::default(); usart_config.baudrate = 9600; @@ -109,7 +108,6 @@ async fn main(spawner: Spawner) { usart_config.baudrate = 115_200; usart_config.data_bits = DataBits::DataBits8; usart_config.stop_bits = StopBits::STOP1; - // usart_config.parity = Parity::ParityEven; let usart_sps30 = unwrap!(Uart::new( p.USART2, p.PA3, @@ -197,24 +195,21 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(net_task(stack))); let publish = Queues::new(); - let send_published = network::send_published(stack, &publish); - pin_mut!(send_published); - // let keep_dog_happy = keep_dog_happy(dog); - // let send_and_pet_dog = join::join(&mut send_published, keep_dog_happy); - let send_and_pet_dog = &mut send_published; - - let init_then_measure = sensors::init_then_measure(&publish, i2c_1, i2c_3, usart_mhz, usart_sps30); - let res = select::select(send_and_pet_dog, init_then_measure).await; + let handle_network = network::handle(stack, &publish); + pin_mut!(handle_network); + + let init_then_measure = + sensors::init_then_measure(&publish, i2c_1, i2c_3, usart_mhz, usart_sps30); + let res = select::select(&mut handle_network, init_then_measure).await; let unrecoverable_err = match res { - Either::First(network::ConnDownTooLong) => cortex_m::peripheral::SCB::sys_reset(), - Either::Second(Ok(())) => defmt::unreachable!(), + Either::First(()) | Either::Second(Ok(())) => defmt::unreachable!(), Either::Second(Err(err)) => err, }; // at this point no other errors have occurred error!("unrecoverable error, resetting: {}", unrecoverable_err); publish.queue_error(unrecoverable_err); - send_published.await; // if this takes too long the dog will get us + handle_network.await; // if this takes too long the dog will get us } async fn keep_dog_happy(mut dog: IndependentWatchdog<'_, IWDG>) { diff --git a/sensor-nodes/bed-sensors/src/network.rs b/sensor-nodes/bed-sensors/src/network.rs index 9f4330a5..41ccf050 100644 --- a/sensor-nodes/bed-sensors/src/network.rs +++ b/sensor-nodes/bed-sensors/src/network.rs @@ -1,6 +1,7 @@ -use defmt::{debug, error, info, unwrap, warn}; +use defmt::{debug, info, unwrap, warn}; +use embassy_futures::select::{self, select}; use embassy_net::driver::Driver; -use embassy_net::tcp::TcpSocket; +use embassy_net::tcp::{TcpReader, TcpSocket, TcpWriter}; use embassy_net::{Ipv4Address, Stack}; use embassy_time::{with_timeout, Duration, Instant, Timer}; use embedded_io_async::Write; @@ -64,55 +65,58 @@ const fn max(a: usize, b: usize) -> usize { [a, b][(a < b) as usize] } -pub struct ConnDownTooLong; -pub async fn send_published(stack: &Stack, publish: &Queues) -> ConnDownTooLong { +pub async fn handle(stack: &Stack, publish: &Queues) { let mut rx_buffer = [0; 1024]; let mut tx_buffer = [0; max(Msg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE) * 2]; - let mut encoded_msg_buffer = [0; max(Msg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE)]; let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); - socket.set_timeout(Some(Duration::from_secs(5))); + socket.set_timeout(None); + socket.set_keep_alive(Some(Duration::from_secs(5))); let host_addr = Ipv4Address::new(192, 168, 1, 43); let host_port = 1234; - // connection sometimes does not recover from going down - // track how long it has been down and reset the chip if - // it has been down too long. - let mut since_last_connection: Option = None; - let mut connected = false; - debug!("Configured socket and connecting"); loop { - if !connected { - match since_last_connection { - Some(went_down) if went_down.elapsed() > Duration::from_secs(20) => { - error!("connection down to long, might have gotten stuck: resetting"); - return ConnDownTooLong; - } - Some(_) => (), - None => { - since_last_connection = Some(Instant::now()); - warn!("warning connection down, resetting if not up soon"); - } - } + if let Err(e) = socket.connect((host_addr, host_port)).await { + warn!("connect error: {:?}", e); + Timer::after_secs(1).await; + continue; } + info!("(re-)connected"); + // prevent out-dated data from being send + publish.clear().await; - if !connected { - if let Err(e) = socket.connect((host_addr, host_port)).await { - warn!("connect error: {:?}", e); - Timer::after_secs(1).await; - continue; - } - info!("(re-)connected"); - connected = true; - // prevent out-dated data from being send - publish.clear().await; + let (reader, writer) = socket.split(); + + match select(send_messages(writer, publish), receive_orders(reader)).await { + select::Either::First(e) => warn!("Error while sending messages: {:?}", e), + select::Either::Second(e) => warn!("Error receiving orders: {:?}", e), } + } +} +async fn send_messages(mut tcp: TcpWriter<'_>, publish: &Queues) -> embassy_net::tcp::Error { + let mut encoded_msg_buffer = [0; max(Msg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE)]; + loop { let to_send = get_messages(publish, &mut encoded_msg_buffer).await; - if let Err(e) = socket.write_all(to_send).await { - warn!("write error: {:?}", e); - connected = false; + if let Err(e) = tcp.write_all(to_send).await { + return e; + } + } +} + +async fn receive_orders(mut tcp: TcpReader<'_>) -> embassy_net::tcp::Error { + let mut buf = [0u8; 100]; + loop { + let n_read = match tcp.read(&mut buf).await { + Ok(n_read) => n_read, + Err(e) => return e, + }; + let mut read = &buf[..n_read]; + let mut decoder = protocol::affector::Decoder::new(); + while let Some((item, remaining)) = decoder.feed(read) { + read = remaining; + defmt::info!("received item: {:?}", item) } } } From 71421120c8a2d400a487e2608fbba26bdd9a4f82 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 16 Aug 2024 21:07:04 +0200 Subject: [PATCH 199/687] fix deps broken by refactor of protocol lib.rs --- crates/data-server/src/subscriber.rs | 4 ++-- crates/desk-sensors/src/sensors.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/data-server/src/subscriber.rs b/crates/data-server/src/subscriber.rs index 7f6d95ad..1463c23b 100644 --- a/crates/data-server/src/subscriber.rs +++ b/crates/data-server/src/subscriber.rs @@ -3,7 +3,7 @@ use std::net::{SocketAddr, TcpStream}; use std::time::Duration; use std::vec; -use protocol::{DecodeError, Msg}; +use protocol::Msg; use tokio::io::{AsyncBufReadExt, AsyncWriteExt}; use tracing::instrument; @@ -149,7 +149,7 @@ pub enum SubscribeError { "Could not decode message, is protocol lib up to date on server \ and client? Or has the server crashed? Decoderror: {0:?}" )] - DecodeFailed(DecodeError), + DecodeFailed(protocol::DecodeMsgError), #[error("Connection ended")] ConnEnded, #[error("A subscribers name must be smaller then 256 bytes long")] diff --git a/crates/desk-sensors/src/sensors.rs b/crates/desk-sensors/src/sensors.rs index ba1b75cd..83c9f87a 100644 --- a/crates/desk-sensors/src/sensors.rs +++ b/crates/desk-sensors/src/sensors.rs @@ -10,7 +10,7 @@ use std::time::{Duration, Instant}; use protocol::large_bedroom::desk::Reading as DeskReading; use protocol::large_bedroom::desk::{Error, SensorError}; -use protocol::{make_error_string, Reading}; +use protocol::Reading; use crate::{send_error, send_reading}; @@ -53,7 +53,7 @@ pub fn start_monitoring(tx: Sender>) -> Result< last_warning = Instant::now(); tracing::error!("Could not read bme280 sensor: {e}"); } - let err = make_error_string(e); + let err = protocol::make_error_string(e); send_error(&tx, Error::Running(SensorError::BmeError(err))) } } From aef9e788c8eb097511453a21d228a59f7664d9ab Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 18 Aug 2024 17:11:27 +0200 Subject: [PATCH 200/687] overhauls data-server client to support affectors in future --- crates/data-server/Cargo.toml | 4 + crates/data-server/src/api.rs | 40 ++++ crates/data-server/src/api/client.rs | 173 ++++++++++++++ .../src/api/client/reconnecting.rs | 146 ++++++++++++ crates/data-server/src/lib.rs | 4 +- crates/data-server/src/main.rs | 2 +- crates/data-server/src/server.rs | 219 +++--------------- crates/data-server/src/server/client.rs | 112 +++++++++ crates/data-server/src/server/data_source.rs | 75 ++++++ crates/data-server/src/server/subscribe.rs | 54 +++++ crates/data-server/src/subscriber.rs | 6 +- .../src/subscriber/reconnecting.rs | 80 ------- crates/data-server/tests/api.rs | 47 +++- 13 files changed, 669 insertions(+), 293 deletions(-) create mode 100644 crates/data-server/src/api.rs create mode 100644 crates/data-server/src/api/client.rs create mode 100644 crates/data-server/src/api/client/reconnecting.rs create mode 100644 crates/data-server/src/server/client.rs create mode 100644 crates/data-server/src/server/data_source.rs create mode 100644 crates/data-server/src/server/subscribe.rs diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index fe3535bb..663fd26c 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -20,6 +20,10 @@ protocol = { workspace = true, features = ["alloc", "thiserror"] } tokio = { workspace = true, features = ["rt", "macros", "net", "sync", "io-util"] } tokio-stream = { version = "0.1.15", features = ["net"] } thiserror = "1.0.61" +futures = "0.3.30" +tokio-serde = { version = "0.9.0", features = ["bincode"] } +tokio-util = { version = "0.7.11", features = ["codec"] } +serde = { version = "1.0.208", features = ["derive"] } [dev-dependencies] reserve-port = "2" diff --git a/crates/data-server/src/api.rs b/crates/data-server/src/api.rs new file mode 100644 index 00000000..f2dd5055 --- /dev/null +++ b/crates/data-server/src/api.rs @@ -0,0 +1,40 @@ +use serde::{Deserialize, Serialize}; + +pub mod client; +pub use client::reconnecting::Client as ReconnectingClient; +pub use client::reconnecting::SubscribedClient as ReconnectingSubscribedClient; +pub use client::{Client, SubscribedClient}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum Request { + Handshake { name: String }, + Actuate(protocol::Affector), + Subscribe, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum Response { + Handshake, + Error(ServerError), + Actuate, + SubUpdate(SubMessage), + Subscribe, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum SubMessage { + Reading(protocol::Reading), + ErrorReport(Box), +} + +#[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)] +#[error("placeholder")] +pub struct ActuateAffectorError; + +#[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)] +#[error("placeholder")] +pub struct SubscribeError; + +#[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)] +#[error("placeholder")] +pub struct ServerError; diff --git a/crates/data-server/src/api/client.rs b/crates/data-server/src/api/client.rs new file mode 100644 index 00000000..ad59100c --- /dev/null +++ b/crates/data-server/src/api/client.rs @@ -0,0 +1,173 @@ +use std::net::SocketAddr; +use std::time::Duration; + +use futures::SinkExt; +use tokio::net::TcpStream; +use tokio::time::error::Elapsed; +use tokio::time::timeout_at; +use tokio::time::Instant; +use tokio_serde::formats::Bincode; +use tokio_stream::StreamExt; +use tokio_util::codec::{Framed, LengthDelimitedCodec}; + +use super::ActuateAffectorError; +use super::Request; +use super::Response; +use super::ServerError; +use super::SubMessage; +use super::SubscribeError; + +pub(crate) mod reconnecting; + +#[derive(Debug)] +pub struct Client { + stream: tokio_serde::Framed< + Framed, + Response, + Request, + Bincode, + >, +} + +impl Client { + pub async fn connect(addr: impl Into, name: String) -> Result { + let stream = TcpStream::connect(addr.into()) + .await + .map_err(ConnectError::Io)?; + + let length_delimited = Framed::new( + stream, + LengthDelimitedCodec::builder() + .max_frame_length(1024) + .new_codec(), + ); + + let mut stream = tokio_serde::Framed::new(length_delimited, Bincode::default()); + stream + .send(Request::Handshake { name }) + .await + .map_err(ConnectError::Sending)?; + + match tokio::time::timeout(Duration::from_secs(2), stream.try_next()).await { + Ok(Ok(Some(Response::Handshake))) => Ok(Self { stream }), + Ok(Ok(Some(Response::Error(e)))) => Err(ConnectError::ServerError(e)), + Ok(Ok(Some(other))) => unreachable!( + "Server should return handshake response or error after sending \ + first handshake, got impossible response: {other:?}" + ), + Ok(Ok(None)) => Err(ConnectError::Closed), + Ok(Err(e)) => Err(ConnectError::Receiving(e)), + Err(_) => Err(ConnectError::Timeout), + } + } + + async fn send_receive( + &mut self, + request: Request, + ) -> Result> { + fn send_timeout_err(_: Elapsed) -> Error { + Error::Sending(std::io::Error::new(std::io::ErrorKind::TimedOut, "")) + } + fn receive_timeout_err(_: Elapsed) -> Error { + Error::Receiving(std::io::Error::new(std::io::ErrorKind::TimedOut, "")) + } + + let deadline = Instant::now() + Duration::from_secs(5); + timeout_at(deadline, self.stream.send(request)) + .await + .map_err(send_timeout_err)? + .map_err(Error::Sending)?; + match timeout_at(deadline, self.stream.try_next()) + .await + .map_err(receive_timeout_err)? + .map_err(Error::Receiving)? + { + Some(Response::Error(e)) => Err(Error::Server(e)), + Some(response) => Ok(response), + None => Err(Error::ConnectionClosed), + } + } + + pub async fn actuate_affector( + &mut self, + affector: protocol::Affector, + ) -> Result<(), Error> { + let request = Request::Actuate(affector); + match self.send_receive(request.clone()).await { + Ok(Response::Actuate) => Ok(()), + Err(err) => Err(err), + response => Err(Error::IncorrectResponse { + request: format!("{request:?}"), + response: format!("{response:?}"), + }), + } + } + + pub async fn subscribe(mut self) -> Result> { + let request = Request::Subscribe; + match self.send_receive(request.clone()).await { + Ok(Response::Subscribe) => Ok(SubscribedClient(self)), + Err(err) => Err(err), + response => Err(Error::IncorrectResponse { + request: format!("{request:?}"), + response: format!("{response:?}"), + }), + } + } +} + +#[derive(Debug)] +pub struct SubscribedClient(Client); + +impl SubscribedClient { + pub async fn next(&mut self) -> Result> { + let received = self + .0 + .stream + .try_next() + .await + .map_err(Error::Receiving)? + .ok_or(Error::ConnectionClosed)?; + + if let Response::SubUpdate(update) = received { + Ok(update) + } else { + Err(Error::IncorrectResponse { + request: "none, we are subscribed".to_string(), + response: format!("{received:?}"), + }) + } + } +} + +#[derive(Debug, thiserror::Error)] +pub enum ConnectError { + #[error("Error while connecting to data server: {0}")] + Io(std::io::Error), + #[error("Could not send handshake: {0}")] + Sending(std::io::Error), + #[error("Timed out waiting for ")] + Timeout, + #[error("Server unexpectedly closed the connection")] + Closed, + #[error("Server send back an error: {0:?}")] + ServerError(ServerError), + #[error("Could not receive server response: {0:?}")] + Receiving(std::io::Error), +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Got unexpected response response to request {request:?}")] + IncorrectResponse { request: String, response: String }, + #[error("Error while sending request: {0}")] + Sending(std::io::Error), + #[error("Error while sending request: {0}")] + Receiving(std::io::Error), + #[error("General error while processing request")] + Server(ServerError), + #[error("Server ran into an specific error with our request: {0}")] + Request(#[from] T), + #[error("Server closed connection before it awnserd")] + ConnectionClosed, +} diff --git a/crates/data-server/src/api/client/reconnecting.rs b/crates/data-server/src/api/client/reconnecting.rs new file mode 100644 index 00000000..e81cb1fe --- /dev/null +++ b/crates/data-server/src/api/client/reconnecting.rs @@ -0,0 +1,146 @@ +use crate::api::SubMessage; + +use std::net::SocketAddr; +use std::time::Duration; +use tokio::time::{sleep, timeout}; +use tracing::{info, warn}; + +#[derive(Debug)] +pub struct Client { + retry_period: Duration, + connection: Option, + addr: SocketAddr, + name: String, +} + +impl Client { + pub fn new(addr: SocketAddr, name: String) -> Self { + Self { + retry_period: Duration::from_millis(200), + connection: None, + addr, + name, + } + } + + pub fn subscribe(self) -> SubscribedClient { + SubscribedClient { + retry_period: self.retry_period, + connection: self.connection.map(ConnState::Connected), + addr: self.addr, + name: self.name, + } + } + + /// # Cancel safety + /// This is cancel safe however the connection will need to be re-established + /// the next time its called. This will retry forever, you should call this + /// in a timeout future. + pub async fn actuate_affector(&mut self, affector: protocol::Affector) { + loop { + let mut conn = if let Some(conn) = self.connection.take() { + conn + } else { + get_connection_or_reconnect(self.addr.clone(), &self.name, &mut self.retry_period) + .await + }; + + match conn.actuate_affector(affector).await { + Ok(msg) => { + self.retry_period /= 2; + self.retry_period = self.retry_period.max(Duration::from_millis(200)); + self.connection = Some(conn); + return msg; + } + Err(issue) => { + warn!("Conn issue while getting next_msg: {issue}, reconnecting") + } + }; + } + } +} + +#[derive(Debug)] +enum ConnState { + Connected(super::Client), + Subbed(super::SubscribedClient), +} + +#[derive(Debug)] +pub struct SubscribedClient { + retry_period: Duration, + connection: Option, + addr: SocketAddr, + name: String, +} + +impl SubscribedClient { + pub async fn next(&mut self) -> SubMessage { + loop { + let conn = if let Some(conn) = self.connection.take() { + conn + } else { + ConnState::Connected( + get_connection_or_reconnect( + self.addr.clone(), + &self.name, + &mut self.retry_period, + ) + .await, + ) + }; + + let mut subbed = match conn { + ConnState::Connected(conn) => match conn.subscribe().await { + Ok(subbed) => subbed, + Err(_) => continue, + }, + ConnState::Subbed(subbed) => subbed, + }; + + match subbed.next().await { + Ok(msg) => { + self.retry_period /= 2; + self.retry_period = self.retry_period.max(Duration::from_millis(200)); + self.connection = Some(ConnState::Subbed(subbed)); + return msg; + } + Err(issue) => { + warn!("Conn issue while getting next_msg: {issue}, reconnecting") + } + }; + } + } +} + +async fn get_connection_or_reconnect( + addr: SocketAddr, + name: &String, + retry_period: &mut Duration, +) -> super::Client { + loop { + match timeout( + Duration::from_millis(500), + super::Client::connect(addr, name.clone()), + ) + .await + { + Ok(Ok(conn)) => { + info!("Successfully (re)connected to data-server"); + return conn; + } + Ok(Err(e)) => warn!( + "Failed to (re)connect: {e}\n\ + retrying in {:?}", + retry_period + ), + Err(_) => warn!( + "Failed to (re)connect, timed out.\n\ + retrying in {:?}", + retry_period + ), + } + sleep(*retry_period).await; + *retry_period = (*retry_period * 2).min(Duration::from_secs(5)); + } +} diff --git a/crates/data-server/src/lib.rs b/crates/data-server/src/lib.rs index 57c5dba5..4a619a91 100644 --- a/crates/data-server/src/lib.rs +++ b/crates/data-server/src/lib.rs @@ -1,9 +1,7 @@ #![allow(clippy::missing_panics_doc, clippy::missing_errors_doc)] #[cfg(feature = "api")] -pub mod subscriber; -#[cfg(feature = "api")] -pub use subscriber::{Subscriber, AsyncSubscriber, SubMessage}; +pub mod api; #[cfg(feature = "server")] pub mod server; diff --git a/crates/data-server/src/main.rs b/crates/data-server/src/main.rs index bfe9dcea..adb15358 100644 --- a/crates/data-server/src/main.rs +++ b/crates/data-server/src/main.rs @@ -38,7 +38,7 @@ async fn main() -> Result<()> { let (tx, rx) = mpsc::channel(2000); select! { - e = server::register_subs(subscribe_addr, &tx) => e, + e = server::client::handle(subscribe_addr, tx.clone()) => e, e = server::handle_data_sources(update_addr, &tx) => e, e = server::spread_updates(rx) => e, } diff --git a/crates/data-server/src/server.rs b/crates/data-server/src/server.rs index 86e17e2f..7b7906aa 100644 --- a/crates/data-server/src/server.rs +++ b/crates/data-server/src/server.rs @@ -1,196 +1,29 @@ -use color_eyre::eyre::Context; -use std::mem; -use std::net::SocketAddr; -use std::sync::Arc; -use std::time::Duration; -use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufStream}; -use tokio::net::{TcpListener, TcpStream}; -use tokio::sync::mpsc::{self, Sender}; -use tokio::time::timeout; - -use color_eyre::{Result, Section}; -use protocol::{Reading, SensorMessage}; - -use tracing::{info, warn}; - -pub async fn handle_data_source(stream: TcpStream, queue: Sender) { - let mut reader = BufStream::new(stream); - let mut buf = Vec::new(); - loop { - buf.clear(); - let n_read = match reader.read_until(0, &mut buf).await { - Err(e) => { - warn!("Connection failed/closed: {e}"); - return; - } - Ok(bytes) => bytes, - }; - - let bytes = &mut buf[0..n_read]; - if bytes.is_empty() { - //eof - warn!("end of stream"); - return; - } - - let decoded = match protocol::Msg::<50>::decode(bytes) { - Ok(msg) => msg, - Err(e) => { - warn!("decode failed: {e:?}"); - return; - } - }; - match decoded { - protocol::Msg::Readings(readings) => { - for value in readings.values { - queue - .send(Event::NewReading(Ok(value))) - .await - .expect("fn spread_updates should stay running"); - } - } - protocol::Msg::ErrorReport(report) => queue - .send(Event::NewReading(Err(Box::new(report.error)))) - .await - .expect("fn spread_updates should stay running"), - } - } -} - +use color_eyre::Result; +use protocol::Reading; +use tokio::net::TcpStream; +use tokio::sync::mpsc; +use tokio_serde::formats::Bincode; +use tokio_util::codec::{Framed, LengthDelimitedCodec}; + +pub mod client; +mod data_source; +mod subscribe; + +pub use data_source::handle_data_sources; +pub use subscribe::spread_updates; + +use crate::api; +use crate::api::SubMessage; + +pub type Conn = tokio_serde::Framed< + Framed, + api::Request, + api::Response, + Bincode, +>; + +#[derive(Debug)] pub enum Event { - NewSub(TcpStream), + NewSub { tx: mpsc::Sender }, NewReading(Result>), } - -pub async fn handle_sub_conn(mut sub: TcpStream, mut tx: mpsc::Receiver>) { - loop { - let msg = tx.recv().await.expect("updates always keep coming"); - if let Err(e) = timeout(Duration::from_secs(2), sub.write_all(&msg)).await { - warn!("Subscriber connection failed: {e}"); - break; - } - } -} - -pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { - let mut subscribers = Vec::new(); - - loop { - let event = events - .recv() - .await - .expect("queue is kept open by register_subs"); - - let msg = match event { - Event::NewSub(sub) => { - let (tx, rx) = tokio::sync::mpsc::channel(100); - tokio::spawn(handle_sub_conn(sub, rx)); - subscribers.push(tx); - continue; - } - Event::NewReading(Ok(reading)) => { - // PERF: - // use futures-util's peekable with next_if - // to get up to 49 extra messages for efficiency - let mut readings: SensorMessage<50> = SensorMessage::default(); - readings - .values - .push(reading) - .expect("capacity should be > 0"); - protocol::Msg::Readings(readings) - } - Event::NewReading(Err(err)) => { - let report = protocol::ErrorReport::new(*err); - protocol::Msg::ErrorReport(report) - } - }; - - let bytes = msg.encode(); - let bytes: Arc<[u8]> = Arc::from(bytes.into_boxed_slice()); - - let subs = mem::take(&mut subscribers); - for sub in subs { - if sub.try_send(bytes.clone()).is_ok() { - subscribers.push(sub); - } - } - } -} - -pub async fn handle_data_sources(addr: SocketAddr, share: &mpsc::Sender) -> Result<()> { - let listener = TcpListener::bind(addr) - .await - .wrap_err("Could not start listening for new subscribers") - .with_note(|| format!("trying to listen on: {addr}"))?; - - loop { - let res = listener.accept().await; - match res { - Ok((stream, source)) => { - info!("new data source connected from: {source}"); - tokio::spawn(handle_data_source(stream, share.clone())); - } - Err(e) => { - println!("new connection failed: {e}"); - continue; - } - }; - } -} - -pub async fn register_subs(addr: SocketAddr, tx: &mpsc::Sender) -> Result<()> { - let listener = TcpListener::bind(addr) - .await - .wrap_err("Could not start receiving updates") - .with_note(|| format!("trying to listen on: {addr}"))?; - - loop { - let res = listener.accept().await; - match res { - Ok((mut stream, source)) => { - match check_sub(&mut stream).await { - Ok(name) => info!("new subscriber '{name}' connected from: {source}"), - Err(e) => { - warn!( - "newly connected subscriber from: {source} failed to\ - pass check: {e}, disconnecting" - ); - continue; - } - } - tx.send(Event::NewSub(stream)) - .await - .expect("spread_updates (rx) never ends"); - } - Err(e) => { - warn!("new connection failed: {e}"); - continue; - } - }; - } -} - -#[derive(Debug, thiserror::Error)] -pub enum CheckErr { - #[error("Could not read name length: {0}")] - ReadLen(std::io::Error), - #[error("Timed out reading subscriber name")] - Timeout, - #[error("Name could not be parsed: {0}")] - ParseName(std::string::FromUtf8Error), -} - -async fn check_sub(stream: &mut TcpStream) -> Result { - let name_len = timeout(Duration::from_millis(200), stream.read_u8()) - .await - .map_err(|_| CheckErr::Timeout)? - .map_err(CheckErr::ReadLen)?; - let mut buf = vec![0; name_len as usize]; - timeout(Duration::from_millis(200), stream.read_exact(&mut buf)) - .await - .map_err(|_| CheckErr::Timeout)? - .map_err(CheckErr::ReadLen)?; - - let name = String::from_utf8(buf).map_err(CheckErr::ParseName)?; - Ok(name) -} diff --git a/crates/data-server/src/server/client.rs b/crates/data-server/src/server/client.rs new file mode 100644 index 00000000..f38d588d --- /dev/null +++ b/crates/data-server/src/server/client.rs @@ -0,0 +1,112 @@ +use std::net::SocketAddr; + +use color_eyre::eyre::Context; +use futures::SinkExt; +use tokio::net::{TcpListener, TcpStream}; +use tokio::sync::mpsc; +use tokio_serde::formats::Bincode; +use tokio_stream::StreamExt; +use tokio_util::codec::{Framed, LengthDelimitedCodec}; + +use color_eyre::{Result, Section}; + +use tracing::{info, warn}; + +use crate::api; +use crate::api::Response; + +use super::{Conn, Event}; + +async fn handle_client_inner( + conn: &mut Conn, + new_subscribers: &mut mpsc::Sender, +) -> color_eyre::Result<()> { + let request = conn + .try_next() + .await + .wrap_err("Could not get next client request")?; + let Some(request) = request else { + return Ok(()); + }; + + let response = match &request { + api::Request::Handshake { name } => Response::Handshake, + api::Request::Actuate(affector) => todo!(), + api::Request::Subscribe => api::Response::Subscribe, + }; + + conn.send(response) + .await + .wrap_err("failed to send response to client")?; + + if let api::Request::Subscribe = request { + let (tx, rx) = tokio::sync::mpsc::channel(100); + new_subscribers + .send(Event::NewSub { tx }) + .await + .wrap_err("Could not register the client as subscriber")?; + return Err(crate::server::subscribe::handle_subscriber(conn, rx) + .await + .wrap_err("Somewhing went wrong sending updates to the client")); + } + + Ok(()) +} + +async fn handle_client(mut conn: Conn, id: String, mut new_subscribers: mpsc::Sender) { + loop { + if let Err(e) = handle_client_inner(&mut conn, &mut new_subscribers).await { + warn!("Error while handling client {id}: {e:?}") + } + } +} + +pub async fn handle(addr: SocketAddr, tx: mpsc::Sender) -> Result<()> { + let listener = TcpListener::bind(addr) + .await + .wrap_err("Could not start receiving updates") + .with_note(|| format!("trying to listen on: {addr}"))?; + + loop { + let res = listener.accept().await; + match res { + Ok((stream, source)) => { + if let Some((conn, name)) = handshake(stream, source).await { + let id = format!("{name}@{source}"); + tokio::task::spawn(handle_client(conn, id, tx.clone())); + } + } + Err(e) => { + warn!("new connection failed: {e}"); + continue; + } + }; + } +} + +#[tracing::instrument(skip(stream))] +async fn handshake(stream: TcpStream, source: SocketAddr) -> Option<(Conn, String)> { + let length_delimited = Framed::new( + stream, + LengthDelimitedCodec::builder() + .max_frame_length(1024) + .new_codec(), + ); + let mut stream: tokio_serde::Framed<_, api::Request, api::Response, _> = + tokio_serde::Framed::new(length_delimited, Bincode::default()); + + match stream.try_next().await { + Ok(Some(api::Request::Handshake { name })) => { + info!("Client {name} connected from {source}"); + if let Err(e) = stream.send(Response::Handshake).await { + warn!("Failed to acknowledge handshake, error: {e}"); + }; + return Some((stream, name)); + } + Ok(Some(other)) => warn!("client tried to connected without handshake, it send: {other:?}"), + Ok(None) => warn!("client closed connection immediately"), + Err(e) => warn!("connection or decoding issue while receiving handshake: {e:?}"), + } + + None +} diff --git a/crates/data-server/src/server/data_source.rs b/crates/data-server/src/server/data_source.rs new file mode 100644 index 00000000..74f9c095 --- /dev/null +++ b/crates/data-server/src/server/data_source.rs @@ -0,0 +1,75 @@ +use std::net::SocketAddr; + +use color_eyre::eyre::Context; +use color_eyre::{Result, Section}; +use tokio::io::{AsyncBufReadExt, BufStream}; +use tokio::net::{TcpListener, TcpStream}; +use tokio::sync::mpsc::Sender; + +use super::Event; +use tracing::{info, warn}; + +pub async fn handle_data_sources(addr: SocketAddr, share: &Sender) -> Result<()> { + let listener = TcpListener::bind(addr) + .await + .wrap_err("Could not start listening for new subscribers") + .with_note(|| format!("trying to listen on: {addr}"))?; + + loop { + let res = listener.accept().await; + match res { + Ok((stream, source)) => { + info!("new data source connected from: {source}"); + tokio::spawn(handle_data_source(stream, share.clone())); + } + Err(e) => { + println!("new connection failed: {e}"); + continue; + } + }; + } +} + +pub async fn handle_data_source(stream: TcpStream, queue: Sender) { + let mut reader = BufStream::new(stream); + let mut buf = Vec::new(); + loop { + buf.clear(); + let n_read = match reader.read_until(0, &mut buf).await { + Err(e) => { + warn!("Connection failed/closed: {e}"); + return; + } + Ok(bytes) => bytes, + }; + + let bytes = &mut buf[0..n_read]; + if bytes.is_empty() { + //eof + warn!("end of stream"); + return; + } + + let decoded = match protocol::Msg::<50>::decode(bytes) { + Ok(msg) => msg, + Err(e) => { + warn!("decode failed: {e:?}"); + return; + } + }; + match decoded { + protocol::Msg::Readings(readings) => { + for value in readings.values { + queue + .send(Event::NewReading(Ok(value))) + .await + .expect("fn spread_updates should stay running"); + } + } + protocol::Msg::ErrorReport(report) => queue + .send(Event::NewReading(Err(Box::new(report.error)))) + .await + .expect("fn spread_updates should stay running"), + } + } +} diff --git a/crates/data-server/src/server/subscribe.rs b/crates/data-server/src/server/subscribe.rs new file mode 100644 index 00000000..8cf8c935 --- /dev/null +++ b/crates/data-server/src/server/subscribe.rs @@ -0,0 +1,54 @@ +use std::time::Duration; + +use color_eyre::eyre::eyre; +use futures::SinkExt; +use tracing::debug; +use std::mem; +use tokio::sync::mpsc; +use tokio::time::timeout; + +use color_eyre::Result; + +use super::{Conn, Event}; +use crate::api::{Response, SubMessage}; + +pub async fn handle_subscriber( + sub: &mut Conn, + mut rx: mpsc::Receiver, +) -> color_eyre::Report { + loop { + let update = rx.recv().await.expect("updates always keep coming"); + let message = Response::SubUpdate(update); + if let Err(_) = timeout(Duration::from_secs(2), sub.send(message)).await { + return eyre!("Timed out while sending update"); + } + } +} + +pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { + let mut subscribers = Vec::new(); + + loop { + let event = events + .recv() + .await + .expect("queue is kept open by register_subs"); + debug!("event: {event:?}"); + + let msg = match event { + Event::NewSub { tx } => { + subscribers.push(tx); + continue; + } + Event::NewReading(Ok(reading)) => SubMessage::Reading(reading), + Event::NewReading(Err(err)) => SubMessage::ErrorReport(err), + }; + + let subs = mem::take(&mut subscribers); + for sub in subs { + if sub.try_send(msg.clone()).is_ok() { + subscribers.push(sub); + } + } + } +} diff --git a/crates/data-server/src/subscriber.rs b/crates/data-server/src/subscriber.rs index 1463c23b..7eca984c 100644 --- a/crates/data-server/src/subscriber.rs +++ b/crates/data-server/src/subscriber.rs @@ -4,16 +4,12 @@ use std::time::Duration; use std::vec; use protocol::Msg; +use serde::{Deserialize, Serialize}; use tokio::io::{AsyncBufReadExt, AsyncWriteExt}; use tracing::instrument; pub mod reconnecting; -#[derive(Debug)] -pub enum SubMessage { - Reading(protocol::Reading), - ErrorReport(Box), -} pub struct Subscriber { reader: BufReader, diff --git a/crates/data-server/src/subscriber/reconnecting.rs b/crates/data-server/src/subscriber/reconnecting.rs index 9f3e7697..e69de29b 100644 --- a/crates/data-server/src/subscriber/reconnecting.rs +++ b/crates/data-server/src/subscriber/reconnecting.rs @@ -1,80 +0,0 @@ -use super::{AsyncSubscriber, SubMessage, SubscribeError}; -use std::net::SocketAddr; -use std::time::Duration; -use tokio::time::{sleep, timeout}; -use tracing::{info, warn}; - -#[derive(Debug)] -pub struct Subscriber { - retry_period: Duration, - connection: Option, - addr: SocketAddr, - name: String, -} - -impl Subscriber { - pub fn new(addr: SocketAddr, name: String) -> Self { - Self { - retry_period: Duration::from_millis(200), - connection: None, - addr, - name, - } - } - - /// # Cancel safety - /// This is cancel safe however the connection will need to be re-established - /// the next time its called - pub async fn next_msg(&mut self) -> SubMessage { - loop { - let mut conn = if let Some(conn) = self.connection.take() { - conn - } else { - self.get_connection_or_reconnect().await - }; - - match conn.next_msg().await { - Ok(msg) => { - self.retry_period /= 2; - self.retry_period = self.retry_period.max(Duration::from_millis(200)); - self.connection = Some(conn); - return msg; - } - Err(SubscribeError::DecodeFailed(e)) => { - panic!("Critical error while receiving msg from data-server: {e}") - } - Err(issue) => { - warn!("Conn issue while getting next_msg: {issue}, reconnecting") - } - }; - } - } - - async fn get_connection_or_reconnect(&mut self) -> AsyncSubscriber { - loop { - match timeout( - Duration::from_millis(500), - AsyncSubscriber::connect(self.addr, &self.name), - ) - .await - { - Ok(Ok(conn)) => { - info!("Successfully (re)connected to data-server"); - return conn; - } - Ok(Err(e)) => warn!( - "Failed to (re)connect: {e}\n\ - retrying in {:?}", - self.retry_period - ), - Err(_) => warn!( - "Failed to (re)connect, timed out.\n\ - retrying in {:?}", - self.retry_period - ), - } - sleep(self.retry_period).await; - self.retry_period = (self.retry_period * 2).min(Duration::from_secs(5)); - } - } -} diff --git a/crates/data-server/tests/api.rs b/crates/data-server/tests/api.rs index 973a0b48..0c7f0222 100644 --- a/crates/data-server/tests/api.rs +++ b/crates/data-server/tests/api.rs @@ -1,9 +1,9 @@ -use std::net::SocketAddr; +use std::net::{Ipv4Addr, SocketAddr}; use std::time::Duration; use color_eyre::Result; +use data_server::api::{Client, SubMessage}; use data_server::server; -use data_server::subscriber::SubMessage; use protocol::large_bedroom; use protocol::large_bedroom::bed; use protocol::Reading; @@ -21,12 +21,12 @@ enum Done { } async fn run_server( - sub_port: impl Into, + client_addr: impl Into, data_port: impl Into, ) -> Result { let (tx, rx) = mpsc::channel(2000); select! { - e = server::register_subs(sub_port.into(), &tx) => e?, + e = server::client::handle(client_addr.into(), tx.clone()) => e?, e = server::handle_data_sources(data_port.into(), &tx) => e?, e = server::spread_updates(rx) => e?, }; @@ -38,7 +38,7 @@ const TEST_READING: Reading = Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::Temperature(0.0))); async fn send_sensor_value(data_port: u16) -> Result { - tokio::time::sleep(Duration::from_millis(100)).await; + tokio::time::sleep(Duration::from_millis(500)).await; let mut sensor_msg = protocol::SensorMessage::<50>::default(); sensor_msg.values.push(TEST_READING).unwrap(); let encoded = protocol::Msg::Readings(sensor_msg).encode(); @@ -51,12 +51,17 @@ async fn send_sensor_value(data_port: u16) -> Result { async fn subscribe_and_receive(sub_port: u16) -> Result { tokio::time::sleep(Duration::from_millis(100)).await; - let mut sub = - data_server::AsyncSubscriber::connect(("127.0.0.1", sub_port), "api_integration_tests") - .await - .unwrap(); - let received = sub.next_msg().await.unwrap(); - dbg!(&received); + let mut sub = Client::connect( + (Ipv4Addr::LOCALHOST, sub_port), + "api_integration_tests".to_owned(), + ) + .await + .unwrap() + .subscribe() + .await + .unwrap(); + + let received = sub.next().await.unwrap(); assert!(matches!(received, SubMessage::Reading(TEST_READING))); Ok(Done::Test) @@ -64,6 +69,8 @@ async fn subscribe_and_receive(sub_port: u16) -> Result { #[tokio::test] async fn main() { + setup_tracing(); + let sub_port = reserve_port::ReservedPort::random().unwrap(); let data_port = reserve_port::ReservedPort::random().unwrap(); let res = select! { @@ -73,3 +80,21 @@ async fn main() { }; assert_eq!(res.unwrap(), Done::Test); } + +fn setup_tracing() { + use tracing_error::ErrorLayer; + use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt, Layer}; + + color_eyre::install().unwrap(); + + let file_subscriber = tracing_subscriber::fmt::layer() + .with_file(true) + .with_line_number(true) + .with_target(false) + .with_ansi(false) + .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()); + tracing_subscriber::registry() + .with(file_subscriber) + .with(ErrorLayer::default()) + .init(); +} From d685faa25c4d6250348b332c9cde2569e27f9f5c Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 18 Aug 2024 17:11:57 +0200 Subject: [PATCH 201/687] apply api changes from data-server client refactor --- Cargo.lock | 12 ++++-- crates/brain/src/input/sensors.rs | 36 +++-------------- crates/data-store/src/server/db.rs | 9 +++-- crates/data-store/tests/list_data.rs | 4 +- crates/log-store/src/server/db.rs | 9 +++-- crates/log-store/tests/list_data.rs | 4 +- crates/protocol/src/msg.rs | 4 -- crates/sensor-tui/Cargo.toml | 2 +- crates/sensor-tui/src/fetch.rs | 19 +++------ crates/sensor-tui/src/main.rs | 53 +++++++++++++++---------- crates/text-widget/src/main.rs | 12 +++--- crates/text-widget/src/resolve.rs | 4 +- crates/text-widget/src/resolve/fetch.rs | 8 ++-- 13 files changed, 79 insertions(+), 97 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 58350e98..aa2beace 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -868,11 +868,15 @@ version = "0.0.0" dependencies = [ "clap", "color-eyre", + "futures", "protocol", "reserve-port", + "serde", "thiserror", "tokio", + "tokio-serde", "tokio-stream", + "tokio-util", "tracing", "tracing-error", "tracing-subscriber", @@ -3012,18 +3016,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.207" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5665e14a49a4ea1b91029ba7d3bca9f299e1f7cfa194388ccc20f14743e784f2" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.207" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aea2634c86b0e8ef2cfdc0c340baede54ec27b1e46febd7f80dffb2aa44a00e" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" dependencies = [ "proc-macro2", "quote", diff --git a/crates/brain/src/input/sensors.rs b/crates/brain/src/input/sensors.rs index fc0974d7..bfdc23c3 100644 --- a/crates/brain/src/input/sensors.rs +++ b/crates/brain/src/input/sensors.rs @@ -1,42 +1,18 @@ use std::net::SocketAddr; -use data_server::subscriber::SubscribeError; -use data_server::{AsyncSubscriber, SubMessage}; -use std::time::Duration; +use data_server::api::{ReconnectingClient, SubMessage}; use tokio::sync::broadcast; -use tracing::{error, warn}; use crate::controller::Event; pub async fn subscribe(event_tx: broadcast::Sender, data_server: SocketAddr) { + let mut sub = ReconnectingClient::new(data_server, "ha-brain".to_owned()).subscribe(); loop { - let mut sub = loop { - match AsyncSubscriber::connect(data_server, "ha-brain").await { - Ok(sub) => break sub, - Err(SubscribeError::DecodeFailed(e)) => { - error!("Decode failed: {e:?}. is protocol lib up to date? Exiting"); - return; - } - Err(other) => { - warn!("Error subscribing to sensor readings: {other}, retrying..."); - } + match sub.next().await { + SubMessage::Reading(reading) => { + event_tx.send(Event::Sensor(reading)).unwrap(); } - tokio::time::sleep(Duration::from_secs(5)).await; - }; - - loop { - match sub.next_msg().await { - Ok(SubMessage::Reading(reading)) => { - event_tx.send(Event::Sensor(reading)).unwrap(); - } - Ok(SubMessage::ErrorReport(_)) => continue, - Err(e) => { - warn!("Error while subscribed to sensor readings: {e}, retrying..."); - break; - } - }; + SubMessage::ErrorReport(_) => continue, } - - tokio::time::sleep(Duration::from_secs(5)).await; } } diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index 6030f112..ab09dbae 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -4,11 +4,11 @@ use std::path::Path; use std::sync::Arc; use std::time::{Duration, Instant}; -use data_server::subscriber::reconnecting; +use data_server::api::ReconnectingClient; use tokio::sync::Mutex; use color_eyre::{Result, Section}; -use data_server::SubMessage; +use data_server::api::SubMessage; mod series; use series::Series; @@ -16,11 +16,12 @@ use series::Series; use crate::api; pub(crate) async fn run(data_server_addr: SocketAddr, data: Data, data_dir: &Path) -> Result<()> { - let mut sub = reconnecting::Subscriber::new(data_server_addr, "ha-data-store".to_string()); + let mut sub = + ReconnectingClient::new(data_server_addr, "ha-data-store".to_string()).subscribe(); let mut recently_logged = (Instant::now(), String::new()); loop { - let msg = sub.next_msg().await; + let msg = sub.next().await; let res = match msg { SubMessage::Reading(reading) => series::store(&data, &reading, data_dir) .await diff --git a/crates/data-store/tests/list_data.rs b/crates/data-store/tests/list_data.rs index 76447d8f..4c6588b4 100644 --- a/crates/data-store/tests/list_data.rs +++ b/crates/data-store/tests/list_data.rs @@ -22,12 +22,12 @@ const fn test_readings(v: f32) -> [Reading; 2] { ] } -async fn data_server(sub_port: impl Into, data_port: impl Into) { +async fn data_server(client_addr: impl Into, data_port: impl Into) { use data_server::server; let (tx, rx) = mpsc::channel(2000); tokio::select! { - e = server::register_subs(sub_port.into(), &tx) => e.unwrap(), + e = server::client::handle(client_addr.into(), tx.clone()) => e.unwrap(), e = server::handle_data_sources(data_port.into(), &tx) => e.unwrap(), e = server::spread_updates(rx) => e.unwrap(), }; diff --git a/crates/log-store/src/server/db.rs b/crates/log-store/src/server/db.rs index 74e4bb29..145eb686 100644 --- a/crates/log-store/src/server/db.rs +++ b/crates/log-store/src/server/db.rs @@ -2,10 +2,10 @@ use std::net::SocketAddr; use std::path::Path; use std::time::{Duration, Instant}; -use data_server::subscriber::reconnecting; +use data_server::api::ReconnectingClient; use color_eyre::Result; -use data_server::SubMessage; +use data_server::api::SubMessage; mod log; pub(crate) use log::Logs; @@ -19,11 +19,12 @@ pub(crate) async fn run( logs: Logs, log_dir: &Path, ) -> Result<()> { - let mut sub = reconnecting::Subscriber::new(data_server_addr, "ha-data-store".to_string()); + let mut sub = + ReconnectingClient::new(data_server_addr, "ha-data-store".to_string()).subscribe(); let mut recently_logged = (Instant::now(), String::new()); loop { - let msg = sub.next_msg().await; + let msg = sub.next().await; let res = match msg { SubMessage::Reading(reading) => { if let Err(e) = stats.increment(reading.device()).await { diff --git a/crates/log-store/tests/list_data.rs b/crates/log-store/tests/list_data.rs index 059074ac..6400761e 100644 --- a/crates/log-store/tests/list_data.rs +++ b/crates/log-store/tests/list_data.rs @@ -31,12 +31,12 @@ fn test_error() -> protocol::Error { ))) } -async fn data_server(sub_port: impl Into, data_port: impl Into) { +async fn data_server(client_addr: impl Into, data_port: impl Into) { use data_server::server; let (tx, rx) = mpsc::channel(2000); tokio::select! { - e = server::register_subs(sub_port.into(), &tx) => e.unwrap(), + e = server::client::handle(client_addr.into(), tx.clone()) => e.unwrap(), e = server::handle_data_sources(data_port.into(), &tx) => e.unwrap(), e = server::spread_updates(rx) => e.unwrap(), }; diff --git a/crates/protocol/src/msg.rs b/crates/protocol/src/msg.rs index 73656218..c654f954 100644 --- a/crates/protocol/src/msg.rs +++ b/crates/protocol/src/msg.rs @@ -63,10 +63,6 @@ pub enum DecodeMsgError { IncorrectMsgType(u8), } -pub(crate) const fn max(a: usize, b: usize) -> usize { - [a, b][(a < b) as usize] -} - pub(crate) const fn cobs_overhead(uncobsed_size: usize) -> usize { // COBS requires a minimum of 1 byte overhead, and a maximum of ⌈n/254⌉ // bytes for n data bytes (one byte in 254, rounded up). (wiki) diff --git a/crates/sensor-tui/Cargo.toml b/crates/sensor-tui/Cargo.toml index 58377c3e..1c480129 100644 --- a/crates/sensor-tui/Cargo.toml +++ b/crates/sensor-tui/Cargo.toml @@ -14,7 +14,7 @@ ratatui = "0.28" tui-tree-widget = { version = "0.22.0", git = "https://github.com/dvdsk/tui-rs-tree-widget" } clap = { workspace = true } -tokio = { workspace = true} +tokio = { workspace = true, features = ["macros"] } tracing.workspace = true tracing-error = { workspace = true } tracing-subscriber.workspace = true diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index 85edff61..50a6fcd1 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -3,13 +3,13 @@ use std::future::Future; use std::net::SocketAddr; use std::ops::RangeInclusive; use std::sync::mpsc; -use std::thread; use std::time::Instant; use color_eyre::Result; use jiff::{Span, Timestamp}; use log_store::api::{ErrorEvent, Percentile}; use protocol::Reading; +use tokio::task; use tracing::debug; use crate::tui::history_len; @@ -73,23 +73,14 @@ impl Fetch { data_store: SocketAddr, log_store: SocketAddr, update_tx: mpsc::Sender, - ) -> (Self, thread::JoinHandle<()>) { + ) -> Self { let (tx, rx) = tokio::sync::mpsc::channel(32); - let this = Self { + task::spawn(handle_requests(data_store, log_store, rx, update_tx)); + Self { recently_issued: VecDeque::new(), tx, - }; - - let maintainer = thread::spawn(move || { - let rt = tokio::runtime::Builder::new_current_thread() - .enable_io() - .enable_time() - .build() - .unwrap(); - rt.block_on(handle_requests(data_store, log_store, rx, update_tx)); - }); - (this, maintainer) + } } pub fn assure_up_to_date( diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index 529bd1da..6f4a32b8 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -4,9 +4,9 @@ use std::sync::mpsc; use std::thread; use clap::Parser; -use color_eyre::eyre::WrapErr; -use color_eyre::{Help, Result}; -use data_server::SubMessage; +use color_eyre::eyre::{Report, WrapErr}; +use color_eyre::Result; +use data_server::api::{Client, SubMessage}; mod fetch; mod populate; @@ -16,17 +16,13 @@ mod tui; pub(crate) use fetch::Fetch; use log_store::api::{ErrorEvent, Percentile}; use protocol::Reading; +use tokio::task; #[derive(Debug, PartialEq, Eq)] enum UserIntent { Shutdown, } -struct Fetched { - reading: Reading, - thing: Fetchable -} - enum Fetchable { Data { timestamps: Vec, @@ -44,7 +40,7 @@ enum Fetchable { enum Update { ReadingList(Vec), - Fetched{reading: Reading, thing: Fetchable}, + Fetched { reading: Reading, thing: Fetchable }, FetchError(color_eyre::Report), SensorReading(protocol::Reading), SensorError(Box), @@ -52,10 +48,31 @@ enum Update { DeviceList(Vec), } -fn receive_data(mut sub: data_server::Subscriber, tx: mpsc::Sender) { +async fn receive_data(data_server: SocketAddr, tx: mpsc::Sender) { + let client = match Client::connect(data_server, client_name()).await { + Ok(client) => client, + Err(err) => { + let _ignore_panicked_ui = tx.send(Update::SubscribeError( + Report::new(err).wrap_err("Could not connect to data server"), + )); + return; + } + }; + + let mut subbed = match client.subscribe().await { + Ok(client) => client, + Err(err) => { + let _ignore_panicked_ui = tx.send(Update::SubscribeError( + Report::new(err).wrap_err("Could not subscribe to data server"), + )); + return; + } + }; + loop { - let res = sub - .next_msg() + let res = subbed + .next() + .await .wrap_err("Error getting next reading from server") .map(|msg| match msg { SubMessage::Reading(reading) => Update::SensorReading(reading), @@ -92,7 +109,8 @@ struct Cli { log_store: SocketAddr, } -fn main() -> Result<()> { +#[tokio::main] +async fn main() -> Result<()> { setup_tracing().unwrap(); let Cli { @@ -101,20 +119,15 @@ fn main() -> Result<()> { log_store, } = Cli::parse(); - let sub = data_server::Subscriber::connect(data_server, &client_name()) - .wrap_err("failed to connect") - .with_suggestion(|| format!("verify the server is listening on: {data_server}"))?; - let (tx1, rx1) = mpsc::channel(); let (tx2, rx2) = mpsc::channel(); - let (fetcher, maintain_fetch) = Fetch::new(data_store, log_store, tx1.clone()); + let fetcher = Fetch::new(data_store, log_store, tx1.clone()); let tx1_clone1 = tx1.clone(); let tx1_clone2 = tx1.clone(); - thread::spawn(move || receive_data(sub, tx1_clone1)); + task::spawn(receive_data(data_server, tx1_clone1)); thread::spawn(move || tui::run(rx1, tx2, fetcher)); - thread::spawn(move || maintain_fetch); thread::spawn(move || populate::tree(data_store, log_store, tx1_clone2)); loop { diff --git a/crates/text-widget/src/main.rs b/crates/text-widget/src/main.rs index ba7f817a..c6ea095a 100644 --- a/crates/text-widget/src/main.rs +++ b/crates/text-widget/src/main.rs @@ -1,7 +1,7 @@ use color_eyre::eyre::{eyre, Context}; use color_eyre::Result; -use data_server::subscriber::reconnecting; -use data_server::SubMessage; +use data_server::api::SubMessage; +use data_server::api::{ReconnectingClient, ReconnectingSubscribedClient}; use gethostname::gethostname; use protocol::reading_tree::Tree; use protocol::Reading; @@ -38,9 +38,9 @@ struct Cli { debug: bool, } -async fn wait_for_update(client: &mut reconnecting::Subscriber, needed: &Reading) -> Reading { +async fn wait_for_update(client: &mut ReconnectingSubscribedClient, needed: &Reading) -> Reading { loop { - let SubMessage::Reading(r) = client.next_msg().await else { + let SubMessage::Reading(r) = client.next().await else { continue; }; if r.is_same_as(needed) { @@ -49,7 +49,7 @@ async fn wait_for_update(client: &mut reconnecting::Subscriber, needed: &Reading } } -async fn setup(cli: &Cli, client: &mut reconnecting::Subscriber) -> Result { +async fn setup(cli: &Cli, client: &mut ReconnectingSubscribedClient) -> Result { let reading = match resolve::query(cli, client).await { Ok(reading) => reading, Err(e) => { @@ -72,7 +72,7 @@ async fn main() -> Result<()> { let cli = Cli::parse(); setup_tracing(cli.debug)?; - let mut client = reconnecting::Subscriber::new(cli.server, name()); + let mut client = ReconnectingClient::new(cli.server, name()).subscribe(); let reading = match cache::load_from_file(&cli.reading).await { Ok(Some(reading)) => reading, diff --git a/crates/text-widget/src/resolve.rs b/crates/text-widget/src/resolve.rs index bf9095ca..1723a4e2 100644 --- a/crates/text-widget/src/resolve.rs +++ b/crates/text-widget/src/resolve.rs @@ -1,5 +1,5 @@ use color_eyre::eyre::eyre; -use data_server::subscriber::reconnecting::Subscriber; +use data_server::api::ReconnectingSubscribedClient; use nucleo_matcher::pattern::Pattern; use protocol::Reading; use std::time::Duration; @@ -11,7 +11,7 @@ mod fetch; pub async fn query( cli: &crate::Cli, - client: &mut Subscriber, + client: &mut ReconnectingSubscribedClient, ) -> color_eyre::Result { let mut list = if let Some(store_addr) = cli.store { fetch::datalist_on_store(store_addr, crate::name()) diff --git a/crates/text-widget/src/resolve/fetch.rs b/crates/text-widget/src/resolve/fetch.rs index e3dc0a1c..c9ba6761 100644 --- a/crates/text-widget/src/resolve/fetch.rs +++ b/crates/text-widget/src/resolve/fetch.rs @@ -1,6 +1,6 @@ use color_eyre::eyre::Context; -use data_server::subscriber::reconnecting; -use data_server::SubMessage; +use data_server::api::ReconnectingSubscribedClient; +use data_server::api::SubMessage; use std::net::SocketAddr; use data_store::api::Client; @@ -18,11 +18,11 @@ pub(super) async fn datalist_on_store( } pub(super) async fn datalist_from_updates( - client: &mut reconnecting::Subscriber, + client: &mut ReconnectingSubscribedClient, list: &mut Vec, ) { loop { - if let SubMessage::Reading(new) = client.next_msg().await { + if let SubMessage::Reading(new) = client.next().await { if !list.iter().any(|in_list| new.is_same_as(in_list)) { list.push(new); } From 7052b2a390c2c6ecb20b1b6cee197608d83ddbd9 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 19 Aug 2024 12:00:09 +0200 Subject: [PATCH 202/687] adds affector control through data-server --- Cargo.lock | 11 ++ crates/data-server/Cargo.toml | 2 + crates/data-server/src/api.rs | 11 +- crates/data-server/src/api/client.rs | 14 +-- .../src/api/client/reconnecting.rs | 23 ++-- crates/data-server/src/main.rs | 5 +- crates/data-server/src/server.rs | 4 +- crates/data-server/src/server/affector.rs | 111 ++++++++++++++++++ crates/data-server/src/server/client.rs | 29 +++-- crates/data-server/src/server/data_source.rs | 101 +++++++++++----- crates/data-server/src/server/subscribe.rs | 7 +- crates/data-server/tests/api.rs | 7 +- crates/data-store/src/server/db/series.rs | 2 + crates/data-store/tests/list_data.rs | 6 +- crates/log-store/tests/list_data.rs | 6 +- crates/protocol/src/affector.rs | 19 ++- crates/protocol/src/device.rs | 7 +- crates/protocol/src/large_bedroom.rs | 4 +- crates/protocol/src/large_bedroom/bed.rs | 10 +- crates/protocol/src/large_bedroom/desk.rs | 1 + crates/protocol/src/lib.rs | 3 +- crates/protocol/src/msg/error.rs | 2 + crates/protocol/src/msg/sensor.rs | 2 + crates/protocol/src/reading_tree.rs | 2 + crates/protocol/src/small_bedroom.rs | 3 +- 25 files changed, 303 insertions(+), 89 deletions(-) create mode 100644 crates/data-server/src/server/affector.rs diff --git a/Cargo.lock b/Cargo.lock index aa2beace..11d9055a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -869,9 +869,11 @@ dependencies = [ "clap", "color-eyre", "futures", + "futures-concurrency", "protocol", "reserve-port", "serde", + "slotmap", "thiserror", "tokio", "tokio-serde", @@ -3158,6 +3160,15 @@ dependencies = [ "parking_lot 0.11.2", ] +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "version_check", +] + [[package]] name = "smallvec" version = "1.13.2" diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index 663fd26c..b883b93d 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -24,6 +24,8 @@ futures = "0.3.30" tokio-serde = { version = "0.9.0", features = ["bincode"] } tokio-util = { version = "0.7.11", features = ["codec"] } serde = { version = "1.0.208", features = ["derive"] } +futures-concurrency = "7.6.1" +slotmap = "1.0.7" [dev-dependencies] reserve-port = "2" diff --git a/crates/data-server/src/api.rs b/crates/data-server/src/api.rs index f2dd5055..eec2fe26 100644 --- a/crates/data-server/src/api.rs +++ b/crates/data-server/src/api.rs @@ -3,7 +3,8 @@ use serde::{Deserialize, Serialize}; pub mod client; pub use client::reconnecting::Client as ReconnectingClient; pub use client::reconnecting::SubscribedClient as ReconnectingSubscribedClient; -pub use client::{Client, SubscribedClient}; +pub use client::Client; +pub use client::Subscribed as SubscribedClient; #[derive(Debug, Clone, Serialize, Deserialize)] pub enum Request { @@ -16,7 +17,7 @@ pub enum Request { pub enum Response { Handshake, Error(ServerError), - Actuate, + Actuate(Result<(), AffectorError>), SubUpdate(SubMessage), Subscribe, } @@ -28,8 +29,10 @@ pub enum SubMessage { } #[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)] -#[error("placeholder")] -pub struct ActuateAffectorError; +pub enum AffectorError { + #[error("We do not have a connection to the actuator's node")] + Offline, +} #[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)] #[error("placeholder")] diff --git a/crates/data-server/src/api/client.rs b/crates/data-server/src/api/client.rs index ad59100c..ba771258 100644 --- a/crates/data-server/src/api/client.rs +++ b/crates/data-server/src/api/client.rs @@ -10,7 +10,7 @@ use tokio_serde::formats::Bincode; use tokio_stream::StreamExt; use tokio_util::codec::{Framed, LengthDelimitedCodec}; -use super::ActuateAffectorError; +use super::AffectorError; use super::Request; use super::Response; use super::ServerError; @@ -91,10 +91,10 @@ impl Client { pub async fn actuate_affector( &mut self, affector: protocol::Affector, - ) -> Result<(), Error> { + ) -> Result<(), Error> { let request = Request::Actuate(affector); match self.send_receive(request.clone()).await { - Ok(Response::Actuate) => Ok(()), + Ok(Response::Actuate(res)) => res.map_err(Error::Request), Err(err) => Err(err), response => Err(Error::IncorrectResponse { request: format!("{request:?}"), @@ -103,10 +103,10 @@ impl Client { } } - pub async fn subscribe(mut self) -> Result> { + pub async fn subscribe(mut self) -> Result> { let request = Request::Subscribe; match self.send_receive(request.clone()).await { - Ok(Response::Subscribe) => Ok(SubscribedClient(self)), + Ok(Response::Subscribe) => Ok(Subscribed(self)), Err(err) => Err(err), response => Err(Error::IncorrectResponse { request: format!("{request:?}"), @@ -117,9 +117,9 @@ impl Client { } #[derive(Debug)] -pub struct SubscribedClient(Client); +pub struct Subscribed(Client); -impl SubscribedClient { +impl Subscribed { pub async fn next(&mut self) -> Result> { let received = self .0 diff --git a/crates/data-server/src/api/client/reconnecting.rs b/crates/data-server/src/api/client/reconnecting.rs index e81cb1fe..42952951 100644 --- a/crates/data-server/src/api/client/reconnecting.rs +++ b/crates/data-server/src/api/client/reconnecting.rs @@ -14,6 +14,7 @@ pub struct Client { } impl Client { + #[must_use] pub fn new(addr: SocketAddr, name: String) -> Self { Self { retry_period: Duration::from_millis(200), @@ -23,6 +24,7 @@ impl Client { } } + #[must_use] pub fn subscribe(self) -> SubscribedClient { SubscribedClient { retry_period: self.retry_period, @@ -41,8 +43,7 @@ impl Client { let mut conn = if let Some(conn) = self.connection.take() { conn } else { - get_connection_or_reconnect(self.addr.clone(), &self.name, &mut self.retry_period) - .await + get_connection_or_reconnect(self.addr, &self.name, &mut self.retry_period).await }; match conn.actuate_affector(affector).await { @@ -53,7 +54,7 @@ impl Client { return msg; } Err(issue) => { - warn!("Conn issue while getting next_msg: {issue}, reconnecting") + warn!("Conn issue while getting next_msg: {issue}, reconnecting"); } }; } @@ -63,7 +64,7 @@ impl Client { #[derive(Debug)] enum ConnState { Connected(super::Client), - Subbed(super::SubscribedClient), + Subbed(super::Subscribed), } #[derive(Debug)] @@ -81,12 +82,8 @@ impl SubscribedClient { conn } else { ConnState::Connected( - get_connection_or_reconnect( - self.addr.clone(), - &self.name, - &mut self.retry_period, - ) - .await, + get_connection_or_reconnect(self.addr, &self.name, &mut self.retry_period) + .await, ) }; @@ -106,7 +103,7 @@ impl SubscribedClient { return msg; } Err(issue) => { - warn!("Conn issue while getting next_msg: {issue}, reconnecting") + warn!("Conn issue while getting next_msg: {issue}, reconnecting"); } }; } @@ -115,13 +112,13 @@ impl SubscribedClient { async fn get_connection_or_reconnect( addr: SocketAddr, - name: &String, + name: &str, retry_period: &mut Duration, ) -> super::Client { loop { match timeout( Duration::from_millis(500), - super::Client::connect(addr, name.clone()), + super::Client::connect(addr, name.to_owned()), ) .await { diff --git a/crates/data-server/src/main.rs b/crates/data-server/src/main.rs index adb15358..201d0f6c 100644 --- a/crates/data-server/src/main.rs +++ b/crates/data-server/src/main.rs @@ -36,10 +36,11 @@ async fn main() -> Result<()> { info!("listening for updates on: {update_addr}"); info!("serving subscribers on: {subscribe_addr}"); + let affectors = server::AffectorRegistar::default(); let (tx, rx) = mpsc::channel(2000); select! { - e = server::client::handle(subscribe_addr, tx.clone()) => e, - e = server::handle_data_sources(update_addr, &tx) => e, + e = server::client::handle(subscribe_addr, tx.clone(), affectors.clone()) => e, + e = server::handle_nodes(update_addr, &tx, affectors) => e, e = server::spread_updates(rx) => e, } } diff --git a/crates/data-server/src/server.rs b/crates/data-server/src/server.rs index 7b7906aa..a5986d76 100644 --- a/crates/data-server/src/server.rs +++ b/crates/data-server/src/server.rs @@ -7,9 +7,11 @@ use tokio_util::codec::{Framed, LengthDelimitedCodec}; pub mod client; mod data_source; +mod affector; mod subscribe; -pub use data_source::handle_data_sources; +pub use affector::Registar as AffectorRegistar; +pub use data_source::handle_nodes; pub use subscribe::spread_updates; use crate::api; diff --git a/crates/data-server/src/server/affector.rs b/crates/data-server/src/server/affector.rs new file mode 100644 index 00000000..8cbc63c9 --- /dev/null +++ b/crates/data-server/src/server/affector.rs @@ -0,0 +1,111 @@ +use std::collections::HashSet; +use std::sync::{Arc, Mutex}; + +use color_eyre::Result; +use futures::FutureExt; +use futures_concurrency::future::Race; +use protocol::Affector; +use slotmap::{DefaultKey, SlotMap}; +use tokio::io::AsyncWriteExt; +use tokio::net::tcp::OwnedWriteHalf; +use tokio::sync::mpsc::{Receiver, Sender}; + +use tracing::warn; + +#[derive(Debug)] +pub(crate) struct Registration { + tx: tokio::sync::mpsc::Sender, + controls: HashSet, +} + +#[derive(Debug, Clone, Default)] +pub struct Registar(Arc>>); + +impl Registar { + fn register(&self, tx: Sender) -> DefaultKey { + let mut this = self.0.lock().expect("nothing should panic"); + this.insert(Registration { + tx, + controls: HashSet::new(), + }) + } + + fn update_affectors(&self, key: DefaultKey, list: &[Affector]) { + let mut this = self.0.lock().expect("nothing should panic"); + let registration = this + .get_mut(key) + .expect("items are removed when track_and_control_affectors only"); + registration.controls.extend(list.iter()); + } + + fn remove(&self, key: DefaultKey) { + let mut this = self.0.lock().expect("nothing should panic"); + this.remove(key).expect("things are only removed once"); + } + + pub(crate) fn activate(&self, affector: Affector) -> Result<(), Offline> { + let this = self.0.lock().expect("nothing should panic"); + for possible_controller in this + .iter() + .map(|(_, reg)| reg) + .filter(|reg| reg.controls.contains(&affector)) + { + if possible_controller.tx.try_send(affector).is_ok() { + return Ok(()); + } + } + + Err(Offline) + } +} + +pub struct Offline; + +pub(super) async fn track_and_control_affectors( + mut writer: OwnedWriteHalf, + mut update_from_same_node: Receiver, + registar: Registar, +) { + let (tx, mut rx) = tokio::sync::mpsc::channel(10); + let key = registar.register(tx); + + loop { + let new_update = update_from_same_node.recv().map(Res::from); + let new_order = rx + .recv() + .map(|opt| opt.expect("Register never drops")) + .map(Res::Order); + + let res = (new_update, new_order).race().await; + match res { + Res::Disconnected => break, + Res::Update(device) => { + registar.update_affectors(key, device.info().affectors); + } + Res::Order(affector) => { + let buf = affector.encode(); + if let Err(e) = writer.write_all(&buf).await { + warn!("Could not send affector order: {e}"); + break; + } + } + } + } + + registar.remove(key); +} + +enum Res { + Disconnected, + Update(protocol::Device), + Order(protocol::Affector), +} + +impl Res { + fn from(val: Option) -> Self { + match val { + Some(device) => Self::Update(device), + None => Self::Disconnected, + } + } +} diff --git a/crates/data-server/src/server/client.rs b/crates/data-server/src/server/client.rs index f38d588d..b9a3009f 100644 --- a/crates/data-server/src/server/client.rs +++ b/crates/data-server/src/server/client.rs @@ -13,13 +13,14 @@ use color_eyre::{Result, Section}; use tracing::{info, warn}; use crate::api; -use crate::api::Response; +use crate::api::{AffectorError, Response}; -use super::{Conn, Event}; +use super::{affector::Offline, affector::Registar, Conn, Event}; async fn handle_client_inner( conn: &mut Conn, new_subscribers: &mut mpsc::Sender, + affectors: &Registar, ) -> color_eyre::Result<()> { let request = conn .try_next() @@ -30,8 +31,13 @@ async fn handle_client_inner( }; let response = match &request { - api::Request::Handshake { name } => Response::Handshake, - api::Request::Actuate(affector) => todo!(), + api::Request::Handshake { .. } => { + unreachable!("handshake only takes place during connection") + } + api::Request::Actuate(affector) => match affectors.activate(*affector) { + Ok(()) => api::Response::Actuate(Ok(())), + Err(Offline) => api::Response::Actuate(Err(AffectorError::Offline)), + }, api::Request::Subscribe => api::Response::Subscribe, }; @@ -53,15 +59,20 @@ async fn handle_client_inner( Ok(()) } -async fn handle_client(mut conn: Conn, id: String, mut new_subscribers: mpsc::Sender) { +async fn handle_client( + mut conn: Conn, + id: String, + mut new_subscribers: mpsc::Sender, + affectors: Registar, +) { loop { - if let Err(e) = handle_client_inner(&mut conn, &mut new_subscribers).await { - warn!("Error while handling client {id}: {e:?}") + if let Err(e) = handle_client_inner(&mut conn, &mut new_subscribers, &affectors).await { + warn!("Error while handling client {id}: {e:?}"); } } } -pub async fn handle(addr: SocketAddr, tx: mpsc::Sender) -> Result<()> { +pub async fn handle(addr: SocketAddr, tx: mpsc::Sender, affectors: Registar) -> Result<()> { let listener = TcpListener::bind(addr) .await .wrap_err("Could not start receiving updates") @@ -73,7 +84,7 @@ pub async fn handle(addr: SocketAddr, tx: mpsc::Sender) -> Result<()> { Ok((stream, source)) => { if let Some((conn, name)) = handshake(stream, source).await { let id = format!("{name}@{source}"); - tokio::task::spawn(handle_client(conn, id, tx.clone())); + tokio::task::spawn(handle_client(conn, id, tx.clone(), affectors.clone())); } } Err(e) => { diff --git a/crates/data-server/src/server/data_source.rs b/crates/data-server/src/server/data_source.rs index 74f9c095..1a77acea 100644 --- a/crates/data-server/src/server/data_source.rs +++ b/crates/data-server/src/server/data_source.rs @@ -1,15 +1,23 @@ use std::net::SocketAddr; -use color_eyre::eyre::Context; +use color_eyre::eyre::{eyre, Context}; use color_eyre::{Result, Section}; -use tokio::io::{AsyncBufReadExt, BufStream}; -use tokio::net::{TcpListener, TcpStream}; -use tokio::sync::mpsc::Sender; +use tokio::io::{AsyncBufReadExt, BufReader}; +use tokio::net::tcp::OwnedReadHalf; +use tokio::net::TcpListener; +use tokio::net::TcpStream; +use tokio::sync::mpsc::{self, Sender}; use super::Event; use tracing::{info, warn}; -pub async fn handle_data_sources(addr: SocketAddr, share: &Sender) -> Result<()> { +use super::affector::{track_and_control_affectors, Registar}; + +pub async fn handle_nodes( + addr: SocketAddr, + share: &Sender, + registar: Registar, +) -> Result<()> { let listener = TcpListener::bind(addr) .await .wrap_err("Could not start listening for new subscribers") @@ -20,7 +28,7 @@ pub async fn handle_data_sources(addr: SocketAddr, share: &Sender) -> Res match res { Ok((stream, source)) => { info!("new data source connected from: {source}"); - tokio::spawn(handle_data_source(stream, share.clone())); + tokio::spawn(handle_node(stream, share.clone(), registar.clone())); } Err(e) => { println!("new connection failed: {e}"); @@ -30,46 +38,75 @@ pub async fn handle_data_sources(addr: SocketAddr, share: &Sender) -> Res } } -pub async fn handle_data_source(stream: TcpStream, queue: Sender) { - let mut reader = BufStream::new(stream); +pub async fn read_and_decode_packet( + reader: &mut BufReader, + buf: &mut Vec, +) -> color_eyre::Result> { + buf.clear(); + let n_read = reader + .read_until(0, buf) + .await + .wrap_err("Connection failed/closed")?; + + let bytes = &mut buf[0..n_read]; + if bytes.is_empty() { + return Err(eyre!("End of stream, connection is closed")); + } + + protocol::Msg::<50>::decode(bytes).wrap_err("decode failed") +} + +async fn handle_node(stream: TcpStream, queue: Sender, registar: Registar) { + let (reader, writer) = stream.into_split(); + let reader = BufReader::new(reader); + + let (tx, rx) = mpsc::channel(100); + tokio::join!( + receive_and_spread_updates(reader, queue, tx), + track_and_control_affectors(writer, rx, registar), + ); +} + +async fn receive_and_spread_updates( + mut reader: BufReader, + queue: Sender, + affectors: Sender, +) { let mut buf = Vec::new(); + loop { - buf.clear(); - let n_read = match reader.read_until(0, &mut buf).await { + let msg = match read_and_decode_packet(&mut reader, &mut buf).await { + Ok(decoded) => decoded, Err(e) => { - warn!("Connection failed/closed: {e}"); + warn!("Error while reading and decoding packet: {e}"); return; } - Ok(bytes) => bytes, }; - let bytes = &mut buf[0..n_read]; - if bytes.is_empty() { - //eof - warn!("end of stream"); - return; - } - - let decoded = match protocol::Msg::<50>::decode(bytes) { - Ok(msg) => msg, - Err(e) => { - warn!("decode failed: {e:?}"); - return; - } - }; - match decoded { + match msg { protocol::Msg::Readings(readings) => { for value in readings.values { + affectors + .send(value.device()) + .await + .expect("fn track_and_control_affectors should not end"); queue .send(Event::NewReading(Ok(value))) .await .expect("fn spread_updates should stay running"); } } - protocol::Msg::ErrorReport(report) => queue - .send(Event::NewReading(Err(Box::new(report.error)))) - .await - .expect("fn spread_updates should stay running"), + protocol::Msg::ErrorReport(report) => { + affectors + .send(report.error.device()) + .await + .expect("fn track_and_control_affectors should not end"); + let boxed = Box::new(report.error); + queue + .send(Event::NewReading(Err(boxed))) + .await + .expect("fn spread_updates should stay running"); + } } - } + } // loop } diff --git a/crates/data-server/src/server/subscribe.rs b/crates/data-server/src/server/subscribe.rs index 8cf8c935..ab3d65a4 100644 --- a/crates/data-server/src/server/subscribe.rs +++ b/crates/data-server/src/server/subscribe.rs @@ -2,10 +2,10 @@ use std::time::Duration; use color_eyre::eyre::eyre; use futures::SinkExt; -use tracing::debug; use std::mem; use tokio::sync::mpsc; use tokio::time::timeout; +use tracing::debug; use color_eyre::Result; @@ -19,7 +19,10 @@ pub async fn handle_subscriber( loop { let update = rx.recv().await.expect("updates always keep coming"); let message = Response::SubUpdate(update); - if let Err(_) = timeout(Duration::from_secs(2), sub.send(message)).await { + if timeout(Duration::from_secs(2), sub.send(message)) + .await + .is_err() + { return eyre!("Timed out while sending update"); } } diff --git a/crates/data-server/tests/api.rs b/crates/data-server/tests/api.rs index 0c7f0222..aa7a2444 100644 --- a/crates/data-server/tests/api.rs +++ b/crates/data-server/tests/api.rs @@ -3,7 +3,7 @@ use std::time::Duration; use color_eyre::Result; use data_server::api::{Client, SubMessage}; -use data_server::server; +use data_server::server::{self, AffectorRegistar}; use protocol::large_bedroom; use protocol::large_bedroom::bed; use protocol::Reading; @@ -25,9 +25,10 @@ async fn run_server( data_port: impl Into, ) -> Result { let (tx, rx) = mpsc::channel(2000); + let affectors = AffectorRegistar::default(); select! { - e = server::client::handle(client_addr.into(), tx.clone()) => e?, - e = server::handle_data_sources(data_port.into(), &tx) => e?, + e = server::client::handle(client_addr.into(), tx.clone(), affectors.clone()) => e.unwrap(), + e = server::handle_nodes(data_port.into(), &tx, affectors) => e.unwrap(), e = server::spread_updates(rx) => e?, }; diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index c6f643d1..3cd282c0 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -353,6 +353,7 @@ mod test { min_sample_interval: std::time::Duration::from_secs(5), max_sample_interval: std::time::Duration::from_secs(5), temporal_resolution: std::time::Duration::from_secs(1), + affectors: &[], }; let factor = millis_to_minimal_representation(info); assert_eq!(5000 / factor, 5); @@ -363,6 +364,7 @@ mod test { min_sample_interval: std::time::Duration::from_secs(5), max_sample_interval: std::time::Duration::from_secs(5), temporal_resolution: std::time::Duration::from_millis(1), + affectors: &[], }; let factor = millis_to_minimal_representation(info); assert_eq!(5005 / factor, 5005) diff --git a/crates/data-store/tests/list_data.rs b/crates/data-store/tests/list_data.rs index 4c6588b4..3cbfe853 100644 --- a/crates/data-store/tests/list_data.rs +++ b/crates/data-store/tests/list_data.rs @@ -2,6 +2,7 @@ use std::net::SocketAddr; use std::sync::Once; use std::time::Duration; +use data_server::server::AffectorRegistar; use futures::FutureExt; use futures_concurrency::future::Race; use protocol::large_bedroom::bed; @@ -26,9 +27,10 @@ async fn data_server(client_addr: impl Into, data_port: impl Into e.unwrap(), - e = server::handle_data_sources(data_port.into(), &tx) => e.unwrap(), + e = server::client::handle(client_addr.into(), tx.clone(), affectors.clone()) => e.unwrap(), + e = server::handle_nodes(data_port.into(), &tx, affectors) => e.unwrap(), e = server::spread_updates(rx) => e.unwrap(), }; } diff --git a/crates/log-store/tests/list_data.rs b/crates/log-store/tests/list_data.rs index 6400761e..f4435fb5 100644 --- a/crates/log-store/tests/list_data.rs +++ b/crates/log-store/tests/list_data.rs @@ -3,6 +3,7 @@ use std::str::FromStr; use std::sync::Once; use std::time::Duration; +use data_server::server::AffectorRegistar; use futures::FutureExt; use futures_concurrency::future::Race; use protocol::large_bedroom::bed; @@ -34,10 +35,11 @@ fn test_error() -> protocol::Error { async fn data_server(client_addr: impl Into, data_port: impl Into) { use data_server::server; + let affectors = AffectorRegistar::default(); let (tx, rx) = mpsc::channel(2000); tokio::select! { - e = server::client::handle(client_addr.into(), tx.clone()) => e.unwrap(), - e = server::handle_data_sources(data_port.into(), &tx) => e.unwrap(), + e = server::client::handle(client_addr.into(), tx.clone(), affectors.clone()) => e.unwrap(), + e = server::handle_nodes(data_port.into(), &tx, affectors) => e.unwrap(), e = server::spread_updates(rx) => e.unwrap(), }; } diff --git a/crates/protocol/src/affector.rs b/crates/protocol/src/affector.rs index c3374e3b..129ccc19 100644 --- a/crates/protocol/src/affector.rs +++ b/crates/protocol/src/affector.rs @@ -5,7 +5,9 @@ use serde::{Deserialize, Serialize}; use crate::large_bedroom; use crate::msg::cobs_overhead; -#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] +#[derive( + Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Hash, PartialEq, Eq, +)] pub enum Affector { LargeBedroom(large_bedroom::Affector), } @@ -13,27 +15,34 @@ pub enum Affector { impl Affector { const ENCODED_SIZE: usize = Affector::POSTCARD_MAX_SIZE + cobs_overhead(Affector::POSTCARD_MAX_SIZE); + + #[cfg(feature = "alloc")] + #[must_use] + pub fn encode(&self) -> Vec { + postcard::to_allocvec_cobs(self).expect("Encoding should not fail") + } } pub struct Decoder { cobs_buf: CobsAccumulator<{ Affector::ENCODED_SIZE }>, } -impl Decoder { - pub fn new() -> Self { +impl Default for Decoder { + fn default() -> Self { Self { cobs_buf: CobsAccumulator::new(), } } +} +impl Decoder { /// if this returns Some(_, remaining) move the remaining into it again pub fn feed<'a>(&mut self, read_bytes: &'a [u8]) -> Option<(Affector, &'a [u8])> { let mut window = read_bytes; while !window.is_empty() { window = match self.cobs_buf.feed::(read_bytes) { FeedResult::Consumed => break, - FeedResult::OverFull(new_window) => new_window, - FeedResult::DeserError(new_window) => new_window, + FeedResult::OverFull(new_window) | FeedResult::DeserError(new_window) => new_window, FeedResult::Success { data, remaining } => return Some((data, remaining)), } } diff --git a/crates/protocol/src/device.rs b/crates/protocol/src/device.rs index 8aab842f..4c256584 100644 --- a/crates/protocol/src/device.rs +++ b/crates/protocol/src/device.rs @@ -3,7 +3,7 @@ use core::time::Duration; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; -use crate::{large_bedroom, small_bedroom, Reading}; +use crate::{large_bedroom, small_bedroom, Affector, Reading}; #[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, PartialEq, Eq, Hash)] pub enum Device { @@ -12,7 +12,7 @@ pub enum Device { } impl Device { #[must_use] - pub const fn info(&self) -> DeviceInfo { + pub const fn info(&self) -> Info { match self { Device::LargeBedroom(dev) => dev.info(), Device::SmallBedroom(dev) => dev.info(), @@ -21,9 +21,10 @@ impl Device { } #[derive(Debug)] -pub struct DeviceInfo { +pub struct Info { pub name: &'static str, pub affects_readings: &'static [Reading], + pub affectors: &'static [Affector], pub min_sample_interval: Duration, pub max_sample_interval: Duration, pub temporal_resolution: Duration, diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index 45b1d9ee..decad613 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -79,7 +79,9 @@ impl Device { } } -#[derive(Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize)] +#[derive( + Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Hash, PartialEq, Eq, +)] pub enum Affector { CleanSensor, CalibrateCo2, diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 338b981a..21b1b49b 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -386,7 +386,7 @@ macro_rules! tree { } impl Device { - /// Note the order in which the affects_readings occur is the order in which + /// Note the order in which the `affects_readings` occur is the order in which /// they will be stored, do not change it! #[must_use] pub const fn info(&self) -> crate::DeviceInfo { @@ -400,6 +400,7 @@ impl Device { temporal_resolution, min_sample_interval, max_sample_interval, + affectors: &[], }, Device::Bme680 => crate::DeviceInfo { name: "Bme680", @@ -407,6 +408,7 @@ impl Device { temporal_resolution, min_sample_interval, max_sample_interval, + affectors: &[], }, Device::Max44 => crate::DeviceInfo { name: "Max44", @@ -414,6 +416,7 @@ impl Device { temporal_resolution: Duration::from_millis(50), min_sample_interval: Duration::from_millis(50), max_sample_interval, + affectors: &[], }, Device::Mhz14 => crate::DeviceInfo { name: "Mhz14", @@ -421,6 +424,7 @@ impl Device { temporal_resolution, min_sample_interval, max_sample_interval, + affectors: &[], }, Device::Sps30 => crate::DeviceInfo { name: "Sps30", @@ -439,6 +443,7 @@ impl Device { temporal_resolution, min_sample_interval, max_sample_interval, + affectors: &[], }, Device::Nau7802Left => crate::DeviceInfo { name: "Nau7802Left", @@ -446,6 +451,7 @@ impl Device { temporal_resolution: Duration::from_millis(100), min_sample_interval: Duration::from_millis(100), max_sample_interval, + affectors: &[], }, Device::Nau7802Right => crate::DeviceInfo { name: "Nau7802Right", @@ -453,6 +459,7 @@ impl Device { temporal_resolution: Duration::from_millis(100), min_sample_interval: Duration::from_millis(100), max_sample_interval, + affectors: &[], }, Device::Gpio => crate::DeviceInfo { name: "Gpio", @@ -469,6 +476,7 @@ impl Device { temporal_resolution: Duration::from_millis(1), min_sample_interval: Duration::from_millis(2), max_sample_interval: Duration::MAX, + affectors: &[], }, } } diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index fa35e02e..c53d975d 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -192,6 +192,7 @@ impl Device { Reading::Humidity(0.0), Reading::Pressure(0.0) ], + affectors: &[], min_sample_interval: Duration::from_secs(5), max_sample_interval: Duration::from_secs(5), temporal_resolution: Duration::from_secs(1), diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 638aa985..9118b0fd 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -22,7 +22,8 @@ pub use msg::sensor::SensorMessage; pub use msg::error::ErrorReport; pub use msg::error::make_error_string; pub use reading::Reading; -pub use device::{Device, DeviceInfo}; +pub use device::Device; +pub use device::Info as DeviceInfo; pub use error::Error; pub use affector::Affector; diff --git a/crates/protocol/src/msg/error.rs b/crates/protocol/src/msg/error.rs index 66f36245..273e782e 100644 --- a/crates/protocol/src/msg/error.rs +++ b/crates/protocol/src/msg/error.rs @@ -1,3 +1,5 @@ +#![allow(clippy::module_name_repetitions)] + use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; diff --git a/crates/protocol/src/msg/sensor.rs b/crates/protocol/src/msg/sensor.rs index 7d8bdfb3..e2716511 100644 --- a/crates/protocol/src/msg/sensor.rs +++ b/crates/protocol/src/msg/sensor.rs @@ -1,3 +1,5 @@ +#![allow(clippy::module_name_repetitions)] + use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; diff --git a/crates/protocol/src/reading_tree.rs b/crates/protocol/src/reading_tree.rs index a3751da8..a2014d3b 100644 --- a/crates/protocol/src/reading_tree.rs +++ b/crates/protocol/src/reading_tree.rs @@ -32,6 +32,8 @@ impl ReadingInfo { /// let printed = format!("{0:.1$}", info.val, info.precision()); /// assert_eq!(printed, "22.42"); /// ``` + #[must_use] + #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] pub fn precision(&self) -> usize { if self.resolution > 1.0 { 0 diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index 38a913b1..e6819da7 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -75,7 +75,7 @@ macro_rules! tree { } impl Device { - /// Note the order in which the affects_readings occur is the order in which + /// Note the order in which the `affects_readings` occur is the order in which /// they will be stored, do not change it! #[must_use] pub const fn info(&self) -> crate::DeviceInfo { @@ -90,6 +90,7 @@ impl Device { ButtonPanel::BottomMiddle(Press(0)), ButtonPanel::BOttomRight(Press(0)) ], + affectors: &[], temporal_resolution: Duration::from_millis(1), min_sample_interval: Duration::from_millis(2), max_sample_interval: Duration::MAX, From 07c9f2cc99efc180975a8cf0a4d2bbdd9aa063b1 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 19 Aug 2024 12:35:19 +0200 Subject: [PATCH 203/687] adds list affectors to data-server api --- crates/data-server/src/api.rs | 2 + crates/data-server/src/api/client.rs | 14 +++++ crates/data-server/src/server/affector.rs | 8 +++ crates/data-server/src/server/client.rs | 1 + crates/data-server/tests/api.rs | 73 ++++++++++++++++++----- crates/protocol/src/large_bedroom.rs | 3 +- crates/protocol/src/large_bedroom/bed.rs | 39 +++++++----- 7 files changed, 108 insertions(+), 32 deletions(-) diff --git a/crates/data-server/src/api.rs b/crates/data-server/src/api.rs index eec2fe26..4e282352 100644 --- a/crates/data-server/src/api.rs +++ b/crates/data-server/src/api.rs @@ -11,6 +11,7 @@ pub enum Request { Handshake { name: String }, Actuate(protocol::Affector), Subscribe, + ListAffectors, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -18,6 +19,7 @@ pub enum Response { Handshake, Error(ServerError), Actuate(Result<(), AffectorError>), + ListAffectors(Vec), SubUpdate(SubMessage), Subscribe, } diff --git a/crates/data-server/src/api/client.rs b/crates/data-server/src/api/client.rs index ba771258..b0b68420 100644 --- a/crates/data-server/src/api/client.rs +++ b/crates/data-server/src/api/client.rs @@ -103,6 +103,20 @@ impl Client { } } + pub async fn list_affectors( + &mut self, + ) -> Result, Error> { + let request = Request::ListAffectors; + match self.send_receive(request.clone()).await { + Ok(Response::ListAffectors(list)) => Ok(list), + Err(err) => Err(err), + response => Err(Error::IncorrectResponse { + request: format!("{request:?}"), + response: format!("{response:?}"), + }), + } + } + pub async fn subscribe(mut self) -> Result> { let request = Request::Subscribe; match self.send_receive(request.clone()).await { diff --git a/crates/data-server/src/server/affector.rs b/crates/data-server/src/server/affector.rs index 8cbc63c9..ffbd836f 100644 --- a/crates/data-server/src/server/affector.rs +++ b/crates/data-server/src/server/affector.rs @@ -57,6 +57,14 @@ impl Registar { Err(Offline) } + + pub(crate) fn list(&self) -> Vec { + let this = self.0.lock().expect("nothing should panic"); + this.iter() + .flat_map(|(_, reg)| reg.controls.iter()) + .cloned() + .collect() + } } pub struct Offline; diff --git a/crates/data-server/src/server/client.rs b/crates/data-server/src/server/client.rs index b9a3009f..8b82f23c 100644 --- a/crates/data-server/src/server/client.rs +++ b/crates/data-server/src/server/client.rs @@ -39,6 +39,7 @@ async fn handle_client_inner( Err(Offline) => api::Response::Actuate(Err(AffectorError::Offline)), }, api::Request::Subscribe => api::Response::Subscribe, + api::Request::ListAffectors => api::Response::ListAffectors(affectors.list()), }; conn.send(response) diff --git a/crates/data-server/tests/api.rs b/crates/data-server/tests/api.rs index aa7a2444..dfa766cc 100644 --- a/crates/data-server/tests/api.rs +++ b/crates/data-server/tests/api.rs @@ -36,7 +36,7 @@ async fn run_server( } const TEST_READING: Reading = - Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::Temperature(0.0))); + Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::NumberPm2_5(0.0))); async fn send_sensor_value(data_port: u16) -> Result { tokio::time::sleep(Duration::from_millis(500)).await; @@ -50,7 +50,7 @@ async fn send_sensor_value(data_port: u16) -> Result { Ok(Done::SendValue) } -async fn subscribe_and_receive(sub_port: u16) -> Result { +async fn subscribe_and_receive_inner(sub_port: u16) -> Result { tokio::time::sleep(Duration::from_millis(100)).await; let mut sub = Client::connect( (Ipv4Addr::LOCALHOST, sub_port), @@ -68,8 +68,30 @@ async fn subscribe_and_receive(sub_port: u16) -> Result { Ok(Done::Test) } +async fn list_affectors_inner(sub_port: u16) -> Result { + tokio::time::sleep(Duration::from_millis(500)).await; + let list = Client::connect( + (Ipv4Addr::LOCALHOST, sub_port), + "api_integration_tests".to_owned(), + ) + .await + .unwrap() + .list_affectors() + .await + .unwrap(); + + assert_eq!( + list, + [protocol::Affector::LargeBedroom( + large_bedroom::Affector::Bed(bed::Affector::Sps30FanClean) + )] + ); + + Ok(Done::Test) +} + #[tokio::test] -async fn main() { +async fn subscribe_and_receive() { setup_tracing(); let sub_port = reserve_port::ReservedPort::random().unwrap(); @@ -77,25 +99,44 @@ async fn main() { let res = select! { e = run_server(([127,0,0,1], sub_port.port()), ([127,0,0,1], data_port.port())) => e, e = send_sensor_value(data_port.port()) => e, - e = subscribe_and_receive(sub_port.port()) => e, + e = subscribe_and_receive_inner(sub_port.port()) => e, + }; + assert_eq!(res.unwrap(), Done::Test); +} + +#[tokio::test] +async fn list_affectors() { + setup_tracing(); + + let sub_port = reserve_port::ReservedPort::random().unwrap(); + let data_port = reserve_port::ReservedPort::random().unwrap(); + let res = select! { + e = run_server(([127,0,0,1], sub_port.port()), ([127,0,0,1], data_port.port())) => e, + e = send_sensor_value(data_port.port()) => e, + e = list_affectors_inner(sub_port.port()) => e, }; assert_eq!(res.unwrap(), Done::Test); } fn setup_tracing() { + use std::sync::Once; use tracing_error::ErrorLayer; use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt, Layer}; - color_eyre::install().unwrap(); - - let file_subscriber = tracing_subscriber::fmt::layer() - .with_file(true) - .with_line_number(true) - .with_target(false) - .with_ansi(false) - .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()); - tracing_subscriber::registry() - .with(file_subscriber) - .with(ErrorLayer::default()) - .init(); + static INIT: Once = Once::new(); + + INIT.call_once(|| { + color_eyre::install().unwrap(); + + let file_subscriber = tracing_subscriber::fmt::layer() + .with_file(true) + .with_line_number(true) + .with_target(false) + .with_ansi(false) + .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()); + tracing_subscriber::registry() + .with(file_subscriber) + .with(ErrorLayer::default()) + .init(); + }) } diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index decad613..2f96e7c6 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -83,8 +83,7 @@ impl Device { Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Hash, PartialEq, Eq, )] pub enum Affector { - CleanSensor, - CalibrateCo2, + Bed(bed::Affector), } impl Affector { diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 21b1b49b..bb241646 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -378,9 +378,9 @@ impl core::fmt::Display for Device { } macro_rules! tree { - [$($reading:expr),+] => { - [$(crate::Reading::LargeBedroom( - crate::large_bedroom::Reading::Bed($reading), + [$thing:ident; $($item:expr),+] => { + [$(crate::$thing::LargeBedroom( + crate::large_bedroom::$thing::Bed($item), )),+] }; } @@ -396,7 +396,7 @@ impl Device { match self { Device::Sht31 => crate::DeviceInfo { name: "Sht31", - affects_readings: &tree![Reading::Temperature(0.0), Reading::Humidity(0.0)], + affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Humidity(0.0)], temporal_resolution, min_sample_interval, max_sample_interval, @@ -404,7 +404,10 @@ impl Device { }, Device::Bme680 => crate::DeviceInfo { name: "Bme680", - affects_readings: &tree![Reading::GassResistance(0.0), Reading::Pressure(0.0)], + affects_readings: &tree![Reading; + Reading::GassResistance(0.0), + Reading::Pressure(0.0) + ], temporal_resolution, min_sample_interval, max_sample_interval, @@ -412,7 +415,7 @@ impl Device { }, Device::Max44 => crate::DeviceInfo { name: "Max44", - affects_readings: &tree![Reading::Brightness(0.0)], + affects_readings: &tree![Reading; Reading::Brightness(0.0)], temporal_resolution: Duration::from_millis(50), min_sample_interval: Duration::from_millis(50), max_sample_interval, @@ -420,15 +423,15 @@ impl Device { }, Device::Mhz14 => crate::DeviceInfo { name: "Mhz14", - affects_readings: &tree![Reading::Co2(0)], + affects_readings: &tree![Reading; Reading::Co2(0)], temporal_resolution, min_sample_interval, max_sample_interval, - affectors: &[], + affectors: &tree!(Affector; Affector::MhzZeroPointCalib), }, Device::Sps30 => crate::DeviceInfo { name: "Sps30", - affects_readings: &tree![ + affects_readings: &tree![Reading; Reading::MassPm1_0(0.0), Reading::MassPm2_5(0.0), Reading::MassPm4_0(0.0), @@ -443,11 +446,11 @@ impl Device { temporal_resolution, min_sample_interval, max_sample_interval, - affectors: &[], + affectors: &tree!(Affector; Affector::Sps30FanClean), }, Device::Nau7802Left => crate::DeviceInfo { name: "Nau7802Left", - affects_readings: &tree![Reading::WeightLeft(0)], + affects_readings: &tree![Reading; Reading::WeightLeft(0)], temporal_resolution: Duration::from_millis(100), min_sample_interval: Duration::from_millis(100), max_sample_interval, @@ -455,7 +458,7 @@ impl Device { }, Device::Nau7802Right => crate::DeviceInfo { name: "Nau7802Right", - affects_readings: &tree![Reading::WeightRight(0)], + affects_readings: &tree![Reading; Reading::WeightRight(0)], temporal_resolution: Duration::from_millis(100), min_sample_interval: Duration::from_millis(100), max_sample_interval, @@ -463,7 +466,7 @@ impl Device { }, Device::Gpio => crate::DeviceInfo { name: "Gpio", - affects_readings: &tree![ + affects_readings: &tree![Reading; Reading::Button(Button::TopLeft(Press(0))), Reading::Button(Button::TopRight(Press(0))), Reading::Button(Button::MiddleInner(Press(0))), @@ -483,7 +486,15 @@ impl Device { #[cfg(feature = "alloc")] #[must_use] - fn rooted(self) -> crate::Device { + const fn rooted(self) -> crate::Device { crate::Device::LargeBedroom(crate::large_bedroom::Device::Bed(self)) } } + +#[derive( + Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Hash, PartialEq, Eq, +)] +pub enum Affector { + Sps30FanClean, + MhzZeroPointCalib, +} From 1fce0cd17318bda61d27f349d01616ca5e6b32dc Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 19 Aug 2024 13:46:17 +0200 Subject: [PATCH 204/687] add list affector to reconn-client --- .../src/api/client/reconnecting.rs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/crates/data-server/src/api/client/reconnecting.rs b/crates/data-server/src/api/client/reconnecting.rs index 42952951..abe3f1f7 100644 --- a/crates/data-server/src/api/client/reconnecting.rs +++ b/crates/data-server/src/api/client/reconnecting.rs @@ -59,6 +59,32 @@ impl Client { }; } } + + /// # Cancel safety + /// This is cancel safe however the connection will need to be re-established + /// the next time its called. This will retry forever, you should call this + /// in a timeout future. + pub async fn list_affectors(&mut self) -> Vec { + loop { + let mut conn = if let Some(conn) = self.connection.take() { + conn + } else { + get_connection_or_reconnect(self.addr, &self.name, &mut self.retry_period).await + }; + + match conn.list_affectors().await { + Ok(list) => { + self.retry_period /= 2; + self.retry_period = self.retry_period.max(Duration::from_millis(200)); + self.connection = Some(conn); + return list; + } + Err(issue) => { + warn!("Conn issue while getting next_msg: {issue}, reconnecting"); + } + }; + } + } } #[derive(Debug)] From 92283d807014c3d38320188ec291c9fff6a281db Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 20 Aug 2024 12:50:43 +0200 Subject: [PATCH 205/687] refactor tui into seperate render/update/key handle for each tab --- crates/protocol/src/large_bedroom/bed.rs | 6 +- crates/sensor-tui/src/fetch.rs | 10 +- crates/sensor-tui/src/tui.rs | 209 +++--------- crates/sensor-tui/src/tui/affectors.rs | 49 +++ crates/sensor-tui/src/tui/readings.rs | 228 +++++++++++++ .../src/tui/{ => readings}/history_len.rs | 0 crates/sensor-tui/src/tui/readings/render.rs | 264 +++++++++++++++ .../src/tui/{ => readings}/render/chart.rs | 8 +- .../tui/{ => readings}/render/chart/labels.rs | 2 +- .../src/tui/{ => readings}/render/logs.rs | 0 .../src/tui/{ => readings}/render/time.rs | 0 .../{reading.rs => readings/sensor_info.rs} | 35 +- .../{reading => readings/sensor_info}/logs.rs | 0 crates/sensor-tui/src/tui/render.rs | 300 +----------------- 14 files changed, 620 insertions(+), 491 deletions(-) create mode 100644 crates/sensor-tui/src/tui/affectors.rs create mode 100644 crates/sensor-tui/src/tui/readings.rs rename crates/sensor-tui/src/tui/{ => readings}/history_len.rs (100%) create mode 100644 crates/sensor-tui/src/tui/readings/render.rs rename crates/sensor-tui/src/tui/{ => readings}/render/chart.rs (90%) rename crates/sensor-tui/src/tui/{ => readings}/render/chart/labels.rs (96%) rename crates/sensor-tui/src/tui/{ => readings}/render/logs.rs (100%) rename crates/sensor-tui/src/tui/{ => readings}/render/time.rs (100%) rename crates/sensor-tui/src/tui/{reading.rs => readings/sensor_info.rs} (94%) rename crates/sensor-tui/src/tui/{reading => readings/sensor_info}/logs.rs (100%) diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index bb241646..1034d609 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -454,7 +454,7 @@ impl Device { temporal_resolution: Duration::from_millis(100), min_sample_interval: Duration::from_millis(100), max_sample_interval, - affectors: &[], + affectors: &tree!(Affector; Affector::Nau7802LeftCalib), }, Device::Nau7802Right => crate::DeviceInfo { name: "Nau7802Right", @@ -462,7 +462,7 @@ impl Device { temporal_resolution: Duration::from_millis(100), min_sample_interval: Duration::from_millis(100), max_sample_interval, - affectors: &[], + affectors: &tree!(Affector; Affector::Nau7802RightCalib), }, Device::Gpio => crate::DeviceInfo { name: "Gpio", @@ -497,4 +497,6 @@ impl Device { pub enum Affector { Sps30FanClean, MhzZeroPointCalib, + Nau7802LeftCalib, + Nau7802RightCalib, } diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index 50a6fcd1..4a546f86 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -3,7 +3,7 @@ use std::future::Future; use std::net::SocketAddr; use std::ops::RangeInclusive; use std::sync::mpsc; -use std::time::Instant; +use std::time::Duration; use color_eyre::Result; use jiff::{Span, Timestamp}; @@ -12,7 +12,6 @@ use protocol::Reading; use tokio::task; use tracing::debug; -use crate::tui::history_len; use crate::{client_name, Fetchable, Update}; const MAX_IN_FLIGHT_REQUESTS: usize = 6; @@ -85,13 +84,14 @@ impl Fetch { pub fn assure_up_to_date( &mut self, - history_len: &mut history_len::HistoryLen, + history_len: Duration, + on_fetch_start: impl FnOnce() -> (), reading: Reading, oldest_in_data: Timestamp, logs_cover_from: Option, hist_cover: Option>, ) { - let history_spans = Span::try_from(history_len.dur).unwrap(); + let history_spans = Span::try_from(history_len).unwrap(); let start_needed = Timestamp::now() - history_spans; if self.history_outdated_not_updating(&reading, start_needed, oldest_in_data) { debug!("Requesting history for {reading:?}"); @@ -99,7 +99,7 @@ impl Fetch { reading: reading.clone(), range: start_needed..=Timestamp::now(), })); - history_len.state = history_len::State::Fetching(Instant::now()); + (on_fetch_start)(); } if self.logs_outdated_not_updating(&reading, start_needed, logs_cover_from) { debug!("Requesting logs for {reading:?}"); diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index 804bd67a..dfce5d4b 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -1,28 +1,24 @@ use crossterm::{ - event::{self, KeyCode, KeyEvent, KeyEventKind, KeyModifiers}, + event::{self, KeyCode, KeyEventKind}, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, ExecutableCommand, }; use ratatui::{ prelude::{CrosstermBackend, Terminal}, - widgets::TableState, + style::{Color, Style}, }; +use render::render_tab; use std::{ - collections::HashMap, io::{stdout, Stdout}, sync::mpsc, time::Duration, }; -use tui_tree_widget::TreeState; -mod reading; -use reading::{Readings, TreeKey}; +use crate::{Fetch, Update, UserIntent}; +mod affectors; +mod readings; mod render; -use crate::{fetch::Fetch, Update, UserIntent}; - -pub(crate) mod history_len; -use history_len::HistoryLen; #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] enum ActiveTab { @@ -47,11 +43,18 @@ impl ActiveTab { } } -#[derive(Debug, Default, Clone, Copy)] -enum InputMode { - #[default] - Normal, - EditingBounds, +pub(crate) struct Theme { + bars: Style, + centered_text: Style, +} + +impl Default for Theme { + fn default() -> Self { + Self { + bars: Style::new().bg(Color::Gray).fg(Color::Black), + centered_text: Style::new(), + } + } } pub fn run( @@ -75,15 +78,10 @@ pub fn run( #[derive(Default)] struct App { - theme: render::Theme, - input_mode: InputMode, + theme: Theme, active_tab: ActiveTab, - show_histogram: bool, - show_logs: bool, - reading_tree_state: TreeState, - affector_tree_state: TreeState, - logs_table_state: TableState, - history_length: HistoryLen, + readings_tab: readings::Tab, + affectors_tab: affectors::Tab, } impl App { @@ -93,168 +91,49 @@ impl App { rx: mpsc::Receiver, mut fetcher: Fetch, ) -> Result<(), std::io::Error> { - let mut readings = Readings { - ground: Vec::new(), - data: HashMap::new(), - }; - - let affectors = Vec::new(); - let mut plot_buf = Vec::new(); - loop { - let mut data = self - .reading_tree_state - .selected() - .last() // unique leaf id - .and_then(|key| readings.data.get_mut(key)); - - let plot_open = data.is_some(); - let (chart, histogram, details, logs) = if let Some(data) = data.as_mut() { - fetcher.assure_up_to_date( - &mut self.history_length, - data.reading.clone(), - data.oldest_in_history(), - data.logs_from_store_hist, - data.histogram_range.clone(), - ); - ( - data.chart(&mut plot_buf), - data.histogram(), - Some(data.details()), - Some(data.logs()), - ) - } else { - (None, Vec::new(), None, None) - }; - terminal.draw(|frame| { - render::app( - frame, - self, - &readings.ground, - &affectors, - details, - chart, - logs, - &histogram, - ); + let layout = render_tab(frame, self); + match self.active_tab { + ActiveTab::Readings => { + self.readings_tab + .render(&mut fetcher, frame, layout, &self.theme) + } + ActiveTab::Affectors => self.affectors_tab.render(frame, layout, &self.theme), + } })?; - if self.reading_tree_state.selected().is_empty() { - self.reading_tree_state.select_first(); - } - if event::poll(Duration::from_millis(16))? { if let event::Event::Key(key) = event::read()? { tracing::trace!("key pressed: {key:?}"); if key.kind == KeyEventKind::Press { - let res = self.handle_key_all_modes(key); - if let ShouldExit::Yes = res { - break; + match key.code { + KeyCode::Left => { + self.active_tab = self.active_tab.swap(); + } + KeyCode::Right => { + self.active_tab = self.active_tab.swap(); + } + _ => (), } - let res = match self.input_mode { - InputMode::Normal => self.handle_key_normal_mode(key, plot_open), - InputMode::EditingBounds => self.handle_key_bounds_mode(key), - }; + let res = match self.active_tab { + ActiveTab::Readings => self.readings_tab.handle_key(key), + ActiveTab::Affectors => self.affectors_tab.handle_key(key), + }; if let ShouldExit::Yes = res { - break; + return Ok(()); } } } - }; + } let Ok(update) = rx.try_recv() else { continue; }; - match update { - Update::SensorReading(reading) => { - readings.add(reading); - } - Update::ReadingList(list) => { - readings.populate_from_reading_list(list); - } - Update::DeviceList(list) => { - readings.populate_from_device_list(list); - } - Update::SensorError(err) => readings.add_error(err), - Update::Fetched { - reading, - thing: fetched, - } => { - if data - .as_ref() - .is_some_and(|i| i.reading.is_same_as(&reading)) - { - self.history_length.state = history_len::State::Fetched; - } - readings.add_fetched(reading, fetched); - } - - _ => (), - } - } - - Ok(()) - } - - fn handle_key_normal_mode(&mut self, key: KeyEvent, plot_open: bool) -> ShouldExit { - match key.code { - KeyCode::Char('q') | KeyCode::Esc => { - return ShouldExit::Yes; - } - KeyCode::Left => { - self.active_tab = self.active_tab.swap(); - } - KeyCode::Right => { - self.active_tab = self.active_tab.swap(); - } - KeyCode::Char('b') => { - if plot_open { - self.history_length.start_editing(); - self.input_mode = InputMode::EditingBounds; - } - } - KeyCode::Char('h') => { - self.show_histogram = !self.show_histogram; - } - KeyCode::Char('l') => { - self.show_logs = !self.show_logs; - } - _other => (), - } - ShouldExit::No - } - - fn handle_key_bounds_mode(&mut self, key: KeyEvent) -> ShouldExit { - match key.code { - KeyCode::Char('q') | KeyCode::Esc => { - self.history_length.exit_editing(); - self.input_mode = InputMode::Normal; - } - other => self.history_length.process(other), - } - ShouldExit::No - } - - fn handle_key_all_modes(&mut self, key: KeyEvent) -> ShouldExit { - match key.code { - KeyCode::Down => { - self.reading_tree_state.key_down(); - } - KeyCode::Up => { - self.reading_tree_state.key_up(); - } - KeyCode::Enter => { - self.reading_tree_state.toggle_selected(); - } - KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => { - return ShouldExit::Yes; - } - _other => (), + self.readings_tab.process_update(update); } - ShouldExit::No } } diff --git a/crates/sensor-tui/src/tui/affectors.rs b/crates/sensor-tui/src/tui/affectors.rs new file mode 100644 index 00000000..bf8492ad --- /dev/null +++ b/crates/sensor-tui/src/tui/affectors.rs @@ -0,0 +1,49 @@ +use crossterm::event::KeyEvent; +use ratatui::layout::Rect; +use ratatui::Frame; +use tui_tree_widget::TreeState; + +use crate::Update; + +use super::{ShouldExit, Theme}; + +pub type TreeKey = [u8; 6]; + +pub struct Tab { + affector_tree_state: TreeState, + // affectors +} + +impl Default for Tab { + fn default() -> Self { + Self { + affector_tree_state: Default::default(), + } + } +} + +impl Tab { + pub fn render(&mut self, _frame: &mut Frame, _layout: Rect, _theme: &Theme) { + // frame.render_stateful_widget( + // Tree::new(affectors) + // .expect("all item identifiers should be unique") + // .block( + // Block::default() + // .title("Controllable affectors") + // .borders(Borders::ALL), + // ) + // .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) + // .highlight_symbol(">>"), + // layout, + // &mut app.affector_tree_state, + // ); + } + + pub fn handle_key(&mut self, _key: KeyEvent) -> ShouldExit { + todo!() + } + + pub fn process_update(&mut self, _update: Update) { + todo!() + } +} diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs new file mode 100644 index 00000000..f510d1b6 --- /dev/null +++ b/crates/sensor-tui/src/tui/readings.rs @@ -0,0 +1,228 @@ +use std::time::Instant; + +use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; +use log_store::api::{ErrorEvent, Percentile}; +use ratatui::layout::Rect; +use ratatui::widgets::TableState; +use ratatui::Frame; +use tui_tree_widget::TreeState; + +pub(crate) mod history_len; +pub mod sensor_info; +mod render; +use history_len::HistoryLen; + +use crate::{fetch::Fetch, Update}; +use sensor_info::{ChartParts, Details, Readings, TreeKey}; + +use super::{ShouldExit, Theme}; + +#[derive(Debug, Default, Clone, Copy)] +enum InputMode { + #[default] + Normal, + EditingBounds, +} + +#[derive(Default)] +pub struct UiState { + show_histogram: bool, + show_logs: bool, + history_length: HistoryLen, + input_mode: InputMode, + reading_tree_state: TreeState, + logs_table_state: TableState, +} + +pub struct Tab { + ui_state: UiState, + readings: Readings, + plot_buf: Vec<(f64, f64)>, +} + +impl Default for Tab { + fn default() -> Self { + Self { + ui_state: UiState::default(), + readings: Readings::new(), + plot_buf: Vec::new(), + } + } +} + +impl Tab { + pub fn render(&mut self, fetcher: &mut Fetch, frame: &mut Frame, layout: Rect, theme: &Theme) { + let Self { + ui_state, + readings, + plot_buf, + } = self; + + let (chart, histogram, details, logs) = fun_name(ui_state, readings, fetcher, plot_buf); + + let percentiles = histogram.clone(); + render::app( + frame, + layout, + ui_state, + readings, + details, + chart, + logs, + percentiles, + theme, + ); + } + + pub fn handle_key(&mut self, key: KeyEvent) -> ShouldExit { + let res = self.ui_state.handle_key_all_modes(key); + if let ShouldExit::Yes = res { + return ShouldExit::Yes; + } + let plot_open = !self.plot_buf.is_empty(); + let res = match self.ui_state.input_mode { + InputMode::Normal => self.ui_state.handle_key_normal_mode(key, plot_open), + InputMode::EditingBounds => self.ui_state.handle_key_bounds_mode(key), + }; + + if let ShouldExit::Yes = res { + return ShouldExit::Yes; + } + + ShouldExit::No + } + + pub fn process_update(&mut self, update: Update) { + let data = self + .ui_state + .reading_tree_state + .selected() + .last() // unique leaf id + .and_then(|key| self.readings.data.get_mut(key)); + + match update { + Update::SensorReading(reading) => { + self.readings.add(reading); + } + Update::ReadingList(list) => { + self.readings.populate_from_reading_list(list); + } + Update::DeviceList(list) => { + self.readings.populate_from_device_list(list); + } + Update::SensorError(err) => self.readings.add_error(err), + Update::Fetched { + reading, + thing: fetched, + } => { + if data + .as_ref() + .is_some_and(|i| i.reading.is_same_as(&reading)) + { + self.ui_state.history_length.state = history_len::State::Fetched; + } + self.readings.add_fetched(reading, fetched); + } + + _ => (), + } + + if self.ui_state.reading_tree_state.selected().is_empty() { + self.ui_state.reading_tree_state.select_first(); + } + } +} + +fn fun_name<'a>( + ui_state: &mut UiState, + readings: &mut Readings, + fetcher: &mut Fetch, + plot_buf: &'a mut Vec<(f64, f64)>, +) -> ( + Option>, + Vec, + Option
, + Option>, +) { + let data = ui_state + .reading_tree_state + .selected() + .last() // unique leaf id + .and_then(|key| readings.data.get_mut(key)); + + let dur = ui_state.history_length.dur; + let history_len = &mut ui_state.history_length.state; + if let Some(data) = data { + fetcher.assure_up_to_date( + dur, + || *history_len = history_len::State::Fetching(Instant::now()), + data.reading.clone(), + data.oldest_in_history(), + data.logs_from_store_hist, + data.histogram_range.clone(), + ); + ( + data.chart(plot_buf), + data.percentiles(), + Some(data.details()), + Some(data.logs()), + ) + } else { + plot_buf.clear(); + (None, Vec::new(), None, None) + } +} + +impl UiState { + fn handle_key_normal_mode(&mut self, key: KeyEvent, plot_open: bool) -> ShouldExit { + match key.code { + KeyCode::Char('q') | KeyCode::Esc => { + return ShouldExit::Yes; + } + KeyCode::Char('b') => { + if plot_open { + self.history_length.start_editing(); + self.input_mode = InputMode::EditingBounds; + } + } + KeyCode::Char('h') => { + self.show_histogram = !self.show_histogram; + } + KeyCode::Char('l') => { + self.show_logs = !self.show_logs; + } + _other => (), + } + ShouldExit::No + } + + fn handle_key_bounds_mode(&mut self, key: KeyEvent) -> ShouldExit { + match key.code { + KeyCode::Char('q') | KeyCode::Esc => { + self.history_length.exit_editing(); + self.input_mode = InputMode::Normal; + } + other => self.history_length.process(other), + } + ShouldExit::No + } + + fn handle_key_all_modes(&mut self, key: KeyEvent) -> ShouldExit { + match key.code { + KeyCode::Down => { + self.reading_tree_state.key_down(); + } + KeyCode::Up => { + self.reading_tree_state.key_up(); + } + KeyCode::Enter => { + self.reading_tree_state.toggle_selected(); + } + KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => { + return ShouldExit::Yes; + } + _other => (), + } + ShouldExit::No + } +} diff --git a/crates/sensor-tui/src/tui/history_len.rs b/crates/sensor-tui/src/tui/readings/history_len.rs similarity index 100% rename from crates/sensor-tui/src/tui/history_len.rs rename to crates/sensor-tui/src/tui/readings/history_len.rs diff --git a/crates/sensor-tui/src/tui/readings/render.rs b/crates/sensor-tui/src/tui/readings/render.rs new file mode 100644 index 00000000..f8325e39 --- /dev/null +++ b/crates/sensor-tui/src/tui/readings/render.rs @@ -0,0 +1,264 @@ +use jiff::Timestamp; +use log_store::api::{ErrorEvent, Percentile}; +use ratatui::{ + self, + layout::{Alignment, Constraint, Direction, Flex, Layout, Rect}, + style::{Modifier, Style}, + text::{Line, Text}, + widgets::{self, Bar, BarChart, BarGroup, Block, Borders}, + Frame, +}; +use tui_tree_widget::Tree; + +use crate::tui::Theme; + +use super::{ + sensor_info::{ChartParts, Details, ErrorDensity, Readings}, + UiState, +}; + +mod chart; +mod logs; + +pub(crate) fn app( + frame: &mut Frame, + layout: Rect, + ui_state: &mut UiState, + readings: &Readings, + details: Option
, + chart: Option, + logs: Option>, + percentiles: Vec, + theme: &Theme, +) { + let [list_constraint, graph_constraint] = if chart.is_some() { + let tree_height = 2 + ui_state.reading_tree_state.flatten(&readings.ground).len(); + let details_height = 9; + if (frame.area().height as f32) / 3. > tree_height as f32 { + [ + Constraint::Min(tree_height.max(details_height) as u16), + Constraint::Percentage(100), + ] + } else { + [Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)] + } + } else if logs.is_some() { + [Constraint::Percentage(60), Constraint::Percentage(40)] + } else { + [Constraint::Percentage(100), Constraint::Percentage(0)] + }; + + let [top, bottom, footer] = + Layout::vertical([list_constraint, graph_constraint, Constraint::Min(1)]) + .flex(Flex::Legacy) + .areas(layout); + + let have_details = details.is_some(); + render_readings_and_details(frame, top, ui_state, readings, details); + if have_details { + render_graph_hist_logs(frame, bottom, ui_state, &percentiles, logs, chart, theme); + } + render_footer(frame, footer, ui_state, theme); +} + +fn render_footer(frame: &mut Frame, layout: Rect, app: &mut UiState, theme: &Theme) { + let mut footer = Vec::new(); + + if app.history_length.editing { + footer.push("ESC or q: stop bound editing"); + } else { + footer.push("ESC or q: quit"); + footer.push("b: edit graph start"); + } + + if app.show_histogram { + footer.push("h: hide histogram"); + } else { + footer.push("h: show histogram"); + } + + if app.show_logs { + footer.push("l: hide logs"); + } else { + footer.push("l: show logs"); + } + + let footer = footer.join(" "); + let footer = Text::raw(footer) + .alignment(Alignment::Center) + .style(theme.bars); + frame.render_widget(footer, layout) +} + +fn render_graph_hist_logs( + frame: &mut Frame, + layout: Rect, + app: &mut UiState, + percentiles: &[Percentile], + logs: Option>, + chart: Option, + theme: &Theme, +) { + let num_elems = 1usize + app.show_histogram as usize + app.show_logs as usize; + + let mut constraints = [Constraint::Max(2); 3]; + if chart.is_some() { + constraints[0] = Constraint::Fill(10); + } + if logs.as_ref().is_some_and(|logs| !logs.is_empty()) && app.show_logs { + constraints[1] = Constraint::Fill(10); + } + if !percentiles.is_empty() && app.show_histogram { + let idx = 1 + app.show_logs as usize; + constraints[idx] = Constraint::Fill(10); + } + + let layout = Layout::default() + .direction(Direction::Vertical) + .constraints(&constraints[..num_elems]) + .flex(Flex::Legacy) + .split(layout); + + let mut layout = layout.into_iter().cloned(); + + if let Some(chart) = chart { + chart::render(frame, layout.next().unwrap(), app, chart); + } else { + centered_text( + "No chart as there is no data", + frame, + layout.next().unwrap(), + theme, + ) + } + + if app.show_logs { + logs::render( + frame, + layout.next().unwrap(), + &mut app.logs_table_state, + logs, + theme, + ) + } + + if app.show_histogram { + if percentiles.is_empty() { + centered_text( + "No histogram as there is no timing information", + frame, + layout.next().unwrap(), + theme, + ) + } else { + render_histogram(frame, layout.next().unwrap(), percentiles); + } + } +} + +fn render_histogram(frame: &mut Frame, lower: Rect, percentiles: &[Percentile]) { + let histogram = histogram_bars(&percentiles); + let barchart = BarChart::default() + .block(Block::bordered().title("Histogram")) + .data(BarGroup::default().bars(&histogram)) + .bar_width(12); + frame.render_widget(barchart, lower) +} + +fn histogram_bars(percentiles: &[log_store::api::Percentile]) -> Vec> { + percentiles + .into_iter() + .map( + |log_store::api::Percentile { + bucket_ends, + percentile, + count_in_bucket, + }| { + Bar::default() + .value(*count_in_bucket) + .text_value(format!("p{percentile}: {}", count_in_bucket)) + .label(Line::from(format!("..{}", bucket_ends))) + }, + ) + .collect() +} + +pub(crate) fn render_readings_and_details( + frame: &mut Frame, + layout: Rect, + app: &mut UiState, + readings: &Readings, + details: Option
, +) { + let readings = &readings.ground; + let [left, right] = + Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]) + .flex(Flex::Legacy) + .areas(layout); + + frame.render_stateful_widget( + Tree::new(readings) + .expect("all item identifiers should be unique") + .block( + Block::default() + .title("Sensor readings") + .borders(Borders::ALL), + ) + .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) + .highlight_symbol(">>"), + left, + &mut app.reading_tree_state, + ); + if let Some(details) = details { + render_details(frame, right, details); + } +} + +fn render_details(frame: &mut Frame, layout: Rect, details: Details) { + let Details { + last_reading, + condition, + description, + errors_since, + } = details; + let last_reading = match last_reading { + None => "last read: Never".to_owned(), + Some((ts, val)) => { + let seconds_ago = Timestamp::now() + .since(ts) + .expect("should make sense") + .get_seconds(); + let time_ago = crate::time::format::fmt_seconds(seconds_ago as f64); + format!("last read: {time_ago} ago, value: {val}") + } + }; + + let condition = match condition { + Ok(()) => String::new(), + Err(err) => format!("error: {err}\n"), + }; + + let ErrorDensity { + t5_min, + t15_min, + t30_min, + t45_min, + t60_min, + } = errors_since; + let errors_since = format!("errors in the past:\n5min: {t5_min:.2}, 15min: {t15_min:.2}, 30min: {t30_min:.2}, 45min {t45_min:.2}, 60m: {t60_min:.2}"); + + let text = format!("{description}\n{last_reading}\n{condition}{errors_since}"); + frame.render_widget( + widgets::Paragraph::new(text) + .block(Block::bordered().title("Details")) + .wrap(widgets::Wrap { trim: true }), + layout, + ) +} + +fn centered_text(text: &str, frame: &mut Frame, area: Rect, theme: &Theme) { + let footer = Text::raw(text) + .alignment(Alignment::Center) + .style(theme.centered_text); + frame.render_widget(footer, area) +} diff --git a/crates/sensor-tui/src/tui/render/chart.rs b/crates/sensor-tui/src/tui/readings/render/chart.rs similarity index 90% rename from crates/sensor-tui/src/tui/render/chart.rs rename to crates/sensor-tui/src/tui/readings/render/chart.rs index 5da3b63a..afc52fa7 100644 --- a/crates/sensor-tui/src/tui/render/chart.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart.rs @@ -6,14 +6,12 @@ use ratatui::{ Frame, }; -use crate::tui::reading::ChartParts; - -use super::App; +use crate::tui::readings::{sensor_info::ChartParts, UiState}; mod labels; use labels::labels; -pub fn render(frame: &mut Frame, layout: Rect, app: &mut App, chart: ChartParts) { +pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, chart: ChartParts) { let dataset = Dataset::default() .marker(symbols::Marker::Dot) .graph_type(GraphType::Line) @@ -25,7 +23,7 @@ pub fn render(frame: &mut Frame, layout: Rect, app: &mut App, chart: ChartParts) let borrowed = x_labels.first_mut().expect("min labels is 2"); let owned = std::mem::take(borrowed); - x_labels[0] = app.history_length.style_left_x_label(owned); + x_labels[0] = tab.history_length.style_left_x_label(owned); let x_axis = Axis::default() .title("Time") diff --git a/crates/sensor-tui/src/tui/render/chart/labels.rs b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs similarity index 96% rename from crates/sensor-tui/src/tui/render/chart/labels.rs rename to crates/sensor-tui/src/tui/readings/render/chart/labels.rs index d068980d..e98208ea 100644 --- a/crates/sensor-tui/src/tui/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs @@ -2,7 +2,7 @@ use protocol::reading_tree::ReadingInfo; use ratatui::layout::Rect; use ratatui::text::Span; -use crate::tui::reading::ChartParts; +use crate::tui::readings::sensor_info::ChartParts; use super::Bounds; diff --git a/crates/sensor-tui/src/tui/render/logs.rs b/crates/sensor-tui/src/tui/readings/render/logs.rs similarity index 100% rename from crates/sensor-tui/src/tui/render/logs.rs rename to crates/sensor-tui/src/tui/readings/render/logs.rs diff --git a/crates/sensor-tui/src/tui/render/time.rs b/crates/sensor-tui/src/tui/readings/render/time.rs similarity index 100% rename from crates/sensor-tui/src/tui/render/time.rs rename to crates/sensor-tui/src/tui/readings/render/time.rs diff --git a/crates/sensor-tui/src/tui/reading.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs similarity index 94% rename from crates/sensor-tui/src/tui/reading.rs rename to crates/sensor-tui/src/tui/readings/sensor_info.rs index 825cb2b3..2ddfe173 100644 --- a/crates/sensor-tui/src/tui/reading.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -1,13 +1,12 @@ use hdrhistogram::Histogram; use itertools::Itertools; use jiff::Unit; -use log_store::api::{ErrorEvent, Percentile}; +use log_store::api::{self, ErrorEvent, Percentile}; use protocol::reading_tree::ReadingInfo; use protocol::reading_tree::{Item, Tree}; use protocol::Reading; use protocol::{Device, Error}; -use ratatui::{text::Line, widgets::Bar}; use std::collections::HashMap; use std::ops::RangeInclusive; use tui_tree_widget::TreeItem; @@ -82,7 +81,7 @@ impl SensorInfo { } } - pub fn histogram(&self) -> Vec { + pub fn percentiles(&self) -> Vec { let older_then_15s = |range: &RangeInclusive| { jiff::Timestamp::now() .since(*range.end()) @@ -91,14 +90,13 @@ impl SensorInfo { > 15 }; - let percentiles = if self.histogram_range.is_none() + if self.histogram_range.is_none() || self.histogram_range.as_ref().is_some_and(older_then_15s) { self.fallback_local_hist() } else { self.percentiles_from_store.clone() - }; - histogram_bars(&percentiles) + } } pub fn fallback_local_hist(&self) -> Vec { @@ -463,6 +461,13 @@ impl Readings { } } } + + pub(crate) fn new() -> Self { + Self { + ground: Vec::new(), + data: HashMap::new(), + } + } } pub struct ChartParts<'a> { @@ -470,20 +475,4 @@ pub struct ChartParts<'a> { pub data: &'a [(f64, f64)], } -fn histogram_bars(percentiles: &[log_store::api::Percentile]) -> Vec> { - percentiles - .into_iter() - .map( - |log_store::api::Percentile { - bucket_ends, - percentile, - count_in_bucket, - }| { - Bar::default() - .value(*count_in_bucket) - .text_value(format!("p{percentile}: {}", count_in_bucket)) - .label(Line::from(format!("..{}", bucket_ends))) - }, - ) - .collect() -} + diff --git a/crates/sensor-tui/src/tui/reading/logs.rs b/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs similarity index 100% rename from crates/sensor-tui/src/tui/reading/logs.rs rename to crates/sensor-tui/src/tui/readings/sensor_info/logs.rs diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs index a1e12955..bd49bbb9 100644 --- a/crates/sensor-tui/src/tui/render.rs +++ b/crates/sensor-tui/src/tui/render.rs @@ -1,300 +1,20 @@ -use jiff::Timestamp; -use log_store::api::ErrorEvent; -use ratatui::{ - self, - layout::{Alignment, Constraint, Direction, Flex, Layout, Rect}, - style::{Color, Modifier, Style}, - text::Text, - widgets::{self, Bar, BarChart, BarGroup, Block, Borders, Tabs}, - Frame, -}; -use tui_tree_widget::{Tree, TreeItem}; +use ratatui::layout::{Constraint, Flex, Layout, Rect}; +use ratatui::widgets::Tabs; +use ratatui::Frame; -use super::{ - reading::{ChartParts, Details, ErrorDensity, TreeKey}, - ActiveTab, App, -}; +use super::App; -mod chart; -mod logs; - -pub(crate) struct Theme { - bars: Style, - centered_text: Style, - alt_background: Color, - background: Color, -} - -impl Default for Theme { - fn default() -> Self { - Self { - bars: Style::new().bg(Color::Gray).fg(Color::Black), - centered_text: Style::new(), - alt_background: Color::Gray, - background: Color::Black, - } - } -} - -pub(crate) fn app( - frame: &mut Frame, - app: &mut App, - readings: &[TreeItem<'static, TreeKey>], - affectors: &[TreeItem<'static, TreeKey>], - details: Option
, - chart: Option, - logs: Option>, - histogram: &[Bar], -) { - let [list_constraint, graph_constraint] = if chart.is_some() { - let tree_height = 2 + app.reading_tree_state.flatten(readings).len(); - let details_height = 9; - if (frame.area().height as f32) / 3. > tree_height as f32 { - [ - Constraint::Min(tree_height.max(details_height) as u16), - Constraint::Percentage(100), - ] - } else { - [Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)] - } - } else if logs.is_some() { - [Constraint::Percentage(60), Constraint::Percentage(40)] - } else { - [Constraint::Percentage(100), Constraint::Percentage(0)] - }; - - let area = frame.area(); - let [top_line, top, bottom, footer] = Layout::vertical([ - Constraint::Min(1), - list_constraint, - graph_constraint, - Constraint::Min(1), - ]) - .flex(Flex::Legacy) - .areas(area); - - render_tab(frame, top_line, app); - - match app.active_tab { - ActiveTab::Readings => { - let have_details = details.is_some(); - render_readings_and_details(frame, top, app, readings, details); - if have_details { - render_graph_hist_logs(frame, bottom, app, histogram, logs, chart); - } - } - ActiveTab::Affectors => render_affectors(frame, top, app, affectors), - } - render_footer(frame, footer, app); -} +pub(super) fn render_tab(frame: &mut Frame, app: &App) -> Rect { + let [topline, rest] = Layout::vertical([Constraint::Min(1), Constraint::Fill(1)]) + .flex(Flex::Legacy) + .areas(frame.area()); -fn render_tab(frame: &mut Frame, layout: Rect, app: &App) { let tabs = Tabs::new(vec!["Readings", "Affectors"]) .style(app.theme.bars) .select(app.active_tab.number()) .divider("|") .padding(" ", " "); - frame.render_widget(tabs, layout); -} - -fn render_footer(frame: &mut Frame, layout: Rect, app: &mut App) { - let mut footer = Vec::new(); - - if app.history_length.editing { - footer.push("ESC or q: stop bound editing"); - } else { - footer.push("ESC or q: quit"); - footer.push("b: edit graph start"); - } - - if app.show_histogram { - footer.push("h: hide histogram"); - } else { - footer.push("h: show histogram"); - } - - if app.show_logs { - footer.push("l: hide logs"); - } else { - footer.push("l: show logs"); - } - - let footer = footer.join(" "); - let footer = Text::raw(footer) - .alignment(Alignment::Center) - .style(app.theme.bars); - frame.render_widget(footer, layout) -} - -fn render_graph_hist_logs( - frame: &mut Frame, - layout: Rect, - app: &mut App, - histogram: &[Bar], - logs: Option>, - chart: Option, -) { - let num_elems = 1usize + app.show_histogram as usize + app.show_logs as usize; - - let mut constraints = [Constraint::Max(2); 3]; - if chart.is_some() { - constraints[0] = Constraint::Fill(10); - } - if logs.as_ref().is_some_and(|logs| !logs.is_empty()) && app.show_logs { - constraints[1] = Constraint::Fill(10); - } - if !histogram.is_empty() && app.show_histogram { - let idx = 1 + app.show_logs as usize; - constraints[idx] = Constraint::Fill(10); - } - - let layout = Layout::default() - .direction(Direction::Vertical) - .constraints(&constraints[..num_elems]) - .flex(Flex::Legacy) - .split(layout); - - let mut layout = layout.into_iter().cloned(); - - if let Some(chart) = chart { - chart::render(frame, layout.next().unwrap(), app, chart); - } else { - centered_text( - "No chart as there is no data", - frame, - layout.next().unwrap(), - &app.theme, - ) - } - - if app.show_logs { - logs::render( - frame, - layout.next().unwrap(), - &mut app.logs_table_state, - logs, - &app.theme, - ) - } - - if app.show_histogram { - if histogram.is_empty() { - centered_text( - "No histogram as there is no timing information", - frame, - layout.next().unwrap(), - &app.theme, - ) - } else { - render_histogram(frame, layout.next().unwrap(), histogram); - } - } -} - -fn render_histogram(frame: &mut Frame, lower: Rect, histogram: &[Bar]) { - let barchart = BarChart::default() - .block(Block::bordered().title("Histogram")) - .data(BarGroup::default().bars(histogram)) - .bar_width(12); - frame.render_widget(barchart, lower) -} -pub(crate) fn render_readings_and_details( - frame: &mut Frame, - layout: Rect, - app: &mut App, - readings: &[TreeItem<'static, TreeKey>], - details: Option
, -) { - let [left, right] = - Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]) - .flex(Flex::Legacy) - .areas(layout); - - frame.render_stateful_widget( - Tree::new(readings) - .expect("all item identifiers should be unique") - .block( - Block::default() - .title("Sensor readings") - .borders(Borders::ALL), - ) - .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) - .highlight_symbol(">>"), - left, - &mut app.reading_tree_state, - ); - if let Some(details) = details { - render_details(frame, right, details); - } -} - -fn render_details(frame: &mut Frame, layout: Rect, details: Details) { - let Details { - last_reading, - condition, - description, - errors_since, - } = details; - let last_reading = match last_reading { - None => "last read: Never".to_owned(), - Some((ts, val)) => { - let seconds_ago = Timestamp::now() - .since(ts) - .expect("should make sense") - .get_seconds(); - let time_ago = crate::time::format::fmt_seconds(seconds_ago as f64); - format!("last read: {time_ago} ago, value: {val}") - } - }; - - let condition = match condition { - Ok(()) => String::new(), - Err(err) => format!("error: {err}\n"), - }; - - let ErrorDensity { - t5_min, - t15_min, - t30_min, - t45_min, - t60_min, - } = errors_since; - let errors_since = format!("errors in the past:\n5min: {t5_min:.2}, 15min: {t15_min:.2}, 30min: {t30_min:.2}, 45min {t45_min:.2}, 60m: {t60_min:.2}"); - - let text = format!("{description}\n{last_reading}\n{condition}{errors_since}"); - frame.render_widget( - widgets::Paragraph::new(text) - .block(Block::bordered().title("Details")) - .wrap(widgets::Wrap { trim: true }), - layout, - ) -} - -fn render_affectors( - frame: &mut Frame, - layout: Rect, - app: &mut App, - affectors: &[TreeItem<'static, TreeKey>], -) { - frame.render_stateful_widget( - Tree::new(affectors) - .expect("all item identifiers should be unique") - .block( - Block::default() - .title("Controllable affectors") - .borders(Borders::ALL), - ) - .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) - .highlight_symbol(">>"), - layout, - &mut app.affector_tree_state, - ); -} - -fn centered_text(text: &str, frame: &mut Frame, area: Rect, theme: &Theme) { - let footer = Text::raw(text) - .alignment(Alignment::Center) - .style(theme.centered_text); - frame.render_widget(footer, area) + frame.render_widget(tabs, topline); + rest } From 3c024ac0309d777eca73c3e5500fd558ee94b761 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 20 Aug 2024 13:25:53 +0200 Subject: [PATCH 206/687] add rate limited logging for pre-ratelimited client log statements --- Cargo.lock | 12 +++ Cargo.toml | 1 + crates/data-server/Cargo.toml | 1 + crates/data-server/src/server/client.rs | 31 +++--- crates/log-store/Cargo.toml | 1 + crates/log-store/src/server/clients.rs | 4 +- crates/ratelimited-logger/Cargo.toml | 13 +++ .../src/lib.rs} | 8 +- crates/sensor-tui/src/tui/readings.rs | 96 ++++++++----------- crates/sensor-tui/src/tui/readings/render.rs | 31 ++---- 10 files changed, 102 insertions(+), 96 deletions(-) create mode 100644 crates/ratelimited-logger/Cargo.toml rename crates/{log-store/src/server/clients/logger.rs => ratelimited-logger/src/lib.rs} (88%) diff --git a/Cargo.lock b/Cargo.lock index 11d9055a..531f1862 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -871,6 +871,7 @@ dependencies = [ "futures", "futures-concurrency", "protocol", + "ratelimited-logger", "reserve-port", "serde", "slotmap", @@ -2037,6 +2038,7 @@ dependencies = [ "nucleo-matcher", "num", "protocol", + "ratelimited-logger", "reserve-port", "serde", "smallvec 2.0.0-alpha.7", @@ -2757,6 +2759,16 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "ratelimited-logger" +version = "0.1.0" +dependencies = [ + "governor", + "tracing", + "tracing-error", + "tracing-subscriber", +] + [[package]] name = "raw-cpuid" version = "11.1.0" diff --git a/Cargo.toml b/Cargo.toml index 7fafe2ed..c70bf5b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ data-server = { path = "crates/data-server" } data-store = { path = "crates/data-store" } log-store = { path = "crates/log-store" } protocol = { path = "crates/protocol" } +ratelimited-logger = { path = "crates/ratelimited-logger" } byteseries = { git = "https://github.com/dvdsk/byteseries" } diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index b883b93d..0d4a707b 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -15,6 +15,7 @@ color-eyre = { workspace = true } tracing = { workspace = true } tracing-error = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } +ratelimited-logger = { workspace = true } protocol = { workspace = true, features = ["alloc", "thiserror"] } tokio = { workspace = true, features = ["rt", "macros", "net", "sync", "io-util"] } diff --git a/crates/data-server/src/server/client.rs b/crates/data-server/src/server/client.rs index 8b82f23c..5248df0e 100644 --- a/crates/data-server/src/server/client.rs +++ b/crates/data-server/src/server/client.rs @@ -2,6 +2,7 @@ use std::net::SocketAddr; use color_eyre::eyre::Context; use futures::SinkExt; +use ratelimited_logger::RateLimitedLogger; use tokio::net::{TcpListener, TcpStream}; use tokio::sync::mpsc; use tokio_serde::formats::Bincode; @@ -10,10 +11,10 @@ use tokio_util::codec::{Framed, LengthDelimitedCodec}; use color_eyre::{Result, Section}; -use tracing::{info, warn}; +use tracing::warn; use crate::api; -use crate::api::{AffectorError, Response}; +use crate::api::AffectorError; use super::{affector::Offline, affector::Registar, Conn, Event}; @@ -78,12 +79,13 @@ pub async fn handle(addr: SocketAddr, tx: mpsc::Sender, affectors: Regist .await .wrap_err("Could not start receiving updates") .with_note(|| format!("trying to listen on: {addr}"))?; + let mut logger = RateLimitedLogger::new(); loop { let res = listener.accept().await; match res { Ok((stream, source)) => { - if let Some((conn, name)) = handshake(stream, source).await { + if let Some((conn, name)) = handshake(stream, source, &mut logger).await { let id = format!("{name}@{source}"); tokio::task::spawn(handle_client(conn, id, tx.clone(), affectors.clone())); } @@ -96,8 +98,12 @@ pub async fn handle(addr: SocketAddr, tx: mpsc::Sender, affectors: Regist } } -#[tracing::instrument(skip(stream))] -async fn handshake(stream: TcpStream, source: SocketAddr) -> Option<(Conn, String)> { +#[tracing::instrument(skip(stream, logger))] +async fn handshake( + stream: TcpStream, + source: SocketAddr, + logger: &mut RateLimitedLogger, +) -> Option<(Conn, String)> { let length_delimited = Framed::new( stream, LengthDelimitedCodec::builder() @@ -109,15 +115,16 @@ async fn handshake(stream: TcpStream, source: SocketAddr) -> Option<(Conn, Strin match stream.try_next().await { Ok(Some(api::Request::Handshake { name })) => { - info!("Client {name} connected from {source}"); - if let Err(e) = stream.send(Response::Handshake).await { - warn!("Failed to acknowledge handshake, error: {e}"); - }; + logger.info(&format!("Client {name} connected from {source}")); return Some((stream, name)); } - Ok(Some(other)) => warn!("client tried to connected without handshake, it send: {other:?}"), - Ok(None) => warn!("client closed connection immediately"), - Err(e) => warn!("connection or decoding issue while receiving handshake: {e:?}"), + Ok(Some(other)) => logger.warn(&format!( + "client tried to connected without handshake, it send: {other:?}" + )), + Ok(None) => logger.warn("client closed connection immediately"), + Err(e) => logger.warn(&format!( + "connection or decoding issue while receiving handshake: {e:?}" + )), } None diff --git a/crates/log-store/Cargo.toml b/crates/log-store/Cargo.toml index f0088ca5..bddabdf5 100644 --- a/crates/log-store/Cargo.toml +++ b/crates/log-store/Cargo.toml @@ -22,6 +22,7 @@ jiff = { workspace =true, features = ["serde"] } protocol = { workspace = true, features = ["alloc", "thiserror"] } data-server = { workspace = true } byteseries = { workspace = true } +ratelimited-logger = { workspace = true } tokio = { workspace = true, features = ["fs", "net", "rt-multi-thread", "sync"] } futures-concurrency = "7.6.1" diff --git a/crates/log-store/src/server/clients.rs b/crates/log-store/src/server/clients.rs index 13524be4..2ef04102 100644 --- a/crates/log-store/src/server/clients.rs +++ b/crates/log-store/src/server/clients.rs @@ -7,7 +7,7 @@ use color_eyre::Section; use futures::{SinkExt, TryStreamExt}; use governor::clock::{Clock, DefaultClock}; use governor::{Quota, RateLimiter}; -use logger::RateLimitedLogger; +use ratelimited_logger::RateLimitedLogger; use tokio::net::{TcpListener, TcpStream}; use tokio_serde::formats::Bincode; use tokio_util::codec::{Framed, LengthDelimitedCodec}; @@ -16,8 +16,6 @@ use tracing::{debug, error, warn}; use super::db::{Logs, Stats}; use crate::api::{self, ServerError}; -mod logger; - type Conn = tokio_serde::Framed< Framed, api::Request, diff --git a/crates/ratelimited-logger/Cargo.toml b/crates/ratelimited-logger/Cargo.toml new file mode 100644 index 00000000..8cb70372 --- /dev/null +++ b/crates/ratelimited-logger/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "ratelimited-logger" +version = "0.1.0" +rust-version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true + +[dependencies] +tracing = { workspace = true } +tracing-error = { workspace = true } +tracing-subscriber = { workspace = true, features = ["env-filter"] } +governor = "0.6.3" diff --git a/crates/log-store/src/server/clients/logger.rs b/crates/ratelimited-logger/src/lib.rs similarity index 88% rename from crates/log-store/src/server/clients/logger.rs rename to crates/ratelimited-logger/src/lib.rs index ca3ba466..d6972c0c 100644 --- a/crates/log-store/src/server/clients/logger.rs +++ b/crates/ratelimited-logger/src/lib.rs @@ -9,13 +9,13 @@ use std::time::Duration; use tracing::info; use tracing::warn; -pub(crate) struct RateLimitedLogger { +pub struct RateLimitedLogger { pub(crate) rate_limiter: RateLimiter, pub(crate) withheld: usize, } impl RateLimitedLogger { - pub(crate) fn new() -> Self { + pub fn new() -> Self { let quota = Quota::with_period(Duration::from_secs(1)) .unwrap() .allow_burst(NonZeroU32::new(5).unwrap()); @@ -25,7 +25,7 @@ impl RateLimitedLogger { } } - pub(crate) fn warn(&mut self, txt: &str) { + pub fn warn(&mut self, txt: &str) { if self.rate_limiter.check().is_err() { self.withheld += 1; return; @@ -39,7 +39,7 @@ impl RateLimitedLogger { warn!(txt); } - pub(crate) fn info(&mut self, txt: &str) { + pub fn info(&mut self, txt: &str) { if self.rate_limiter.check().is_err() { self.withheld += 1; return; diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index f510d1b6..01d29504 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -1,19 +1,18 @@ use std::time::Instant; use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; -use log_store::api::{ErrorEvent, Percentile}; use ratatui::layout::Rect; use ratatui::widgets::TableState; use ratatui::Frame; use tui_tree_widget::TreeState; pub(crate) mod history_len; -pub mod sensor_info; mod render; +pub mod sensor_info; use history_len::HistoryLen; use crate::{fetch::Fetch, Update}; -use sensor_info::{ChartParts, Details, Readings, TreeKey}; +use sensor_info::{Readings, TreeKey}; use super::{ShouldExit, Theme}; @@ -58,20 +57,45 @@ impl Tab { plot_buf, } = self; - let (chart, histogram, details, logs) = fun_name(ui_state, readings, fetcher, plot_buf); + let (chart, percentiles, details, logs) = { + let data = ui_state + .reading_tree_state + .selected() + .last() // unique leaf id + .and_then(|key| readings.data.get_mut(key)); + + let dur = ui_state.history_length.dur; + let history_len = &mut ui_state.history_length.state; + if let Some(data) = data { + fetcher.assure_up_to_date( + dur, + || *history_len = history_len::State::Fetching(Instant::now()), + data.reading.clone(), + data.oldest_in_history(), + data.logs_from_store_hist, + data.histogram_range.clone(), + ); + ( + data.chart(plot_buf), + data.percentiles(), + Some(data.details()), + Some(data.logs()), + ) + } else { + plot_buf.clear(); + (None, Vec::new(), None, None) + } + }; - let percentiles = histogram.clone(); - render::app( - frame, - layout, - ui_state, - readings, - details, - chart, - logs, - percentiles, - theme, - ); + let [top, bottom, footer] = + render::layout(frame, layout, ui_state, readings, &chart, &logs); + + let have_details = details.is_some(); + render::readings_and_details(frame, top, ui_state, readings, details); + if have_details { + render::graph_hist_logs(frame, bottom, ui_state, &percentiles, logs, chart, theme); + } + render::footer(frame, footer, ui_state, theme); } pub fn handle_key(&mut self, key: KeyEvent) -> ShouldExit { @@ -133,46 +157,6 @@ impl Tab { } } -fn fun_name<'a>( - ui_state: &mut UiState, - readings: &mut Readings, - fetcher: &mut Fetch, - plot_buf: &'a mut Vec<(f64, f64)>, -) -> ( - Option>, - Vec, - Option
, - Option>, -) { - let data = ui_state - .reading_tree_state - .selected() - .last() // unique leaf id - .and_then(|key| readings.data.get_mut(key)); - - let dur = ui_state.history_length.dur; - let history_len = &mut ui_state.history_length.state; - if let Some(data) = data { - fetcher.assure_up_to_date( - dur, - || *history_len = history_len::State::Fetching(Instant::now()), - data.reading.clone(), - data.oldest_in_history(), - data.logs_from_store_hist, - data.histogram_range.clone(), - ); - ( - data.chart(plot_buf), - data.percentiles(), - Some(data.details()), - Some(data.logs()), - ) - } else { - plot_buf.clear(); - (None, Vec::new(), None, None) - } -} - impl UiState { fn handle_key_normal_mode(&mut self, key: KeyEvent, plot_open: bool) -> ShouldExit { match key.code { diff --git a/crates/sensor-tui/src/tui/readings/render.rs b/crates/sensor-tui/src/tui/readings/render.rs index f8325e39..943e17cc 100644 --- a/crates/sensor-tui/src/tui/readings/render.rs +++ b/crates/sensor-tui/src/tui/readings/render.rs @@ -20,17 +20,14 @@ use super::{ mod chart; mod logs; -pub(crate) fn app( +pub(crate) fn layout( frame: &mut Frame, layout: Rect, ui_state: &mut UiState, readings: &Readings, - details: Option
, - chart: Option, - logs: Option>, - percentiles: Vec, - theme: &Theme, -) { + chart: &Option, + logs: &Option>, +) -> [Rect; 3] { let [list_constraint, graph_constraint] = if chart.is_some() { let tree_height = 2 + ui_state.reading_tree_state.flatten(&readings.ground).len(); let details_height = 9; @@ -48,20 +45,12 @@ pub(crate) fn app( [Constraint::Percentage(100), Constraint::Percentage(0)] }; - let [top, bottom, footer] = - Layout::vertical([list_constraint, graph_constraint, Constraint::Min(1)]) - .flex(Flex::Legacy) - .areas(layout); - - let have_details = details.is_some(); - render_readings_and_details(frame, top, ui_state, readings, details); - if have_details { - render_graph_hist_logs(frame, bottom, ui_state, &percentiles, logs, chart, theme); - } - render_footer(frame, footer, ui_state, theme); + Layout::vertical([list_constraint, graph_constraint, Constraint::Min(1)]) + .flex(Flex::Legacy) + .areas(layout) } -fn render_footer(frame: &mut Frame, layout: Rect, app: &mut UiState, theme: &Theme) { +pub fn footer(frame: &mut Frame, layout: Rect, app: &mut UiState, theme: &Theme) { let mut footer = Vec::new(); if app.history_length.editing { @@ -90,7 +79,7 @@ fn render_footer(frame: &mut Frame, layout: Rect, app: &mut UiState, theme: &The frame.render_widget(footer, layout) } -fn render_graph_hist_logs( +pub fn graph_hist_logs( frame: &mut Frame, layout: Rect, app: &mut UiState, @@ -183,7 +172,7 @@ fn histogram_bars(percentiles: &[log_store::api::Percentile]) -> Vec Date: Tue, 20 Aug 2024 13:53:06 +0200 Subject: [PATCH 207/687] add rate limiting to data-server client --- Cargo.lock | 1 + crates/data-server/Cargo.toml | 1 + crates/data-server/src/api.rs | 6 +- crates/data-server/src/server/client.rs | 41 +++-- crates/data-server/src/subscriber.rs | 155 ------------------ .../src/subscriber/reconnecting.rs | 0 crates/log-store/src/server/clients.rs | 4 +- crates/sensor-tui/src/tui/affectors.rs | 16 +- 8 files changed, 53 insertions(+), 171 deletions(-) delete mode 100644 crates/data-server/src/subscriber.rs delete mode 100644 crates/data-server/src/subscriber/reconnecting.rs diff --git a/Cargo.lock b/Cargo.lock index 531f1862..abadae8b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -870,6 +870,7 @@ dependencies = [ "color-eyre", "futures", "futures-concurrency", + "governor", "protocol", "ratelimited-logger", "reserve-port", diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index 0d4a707b..78427bbe 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -27,6 +27,7 @@ tokio-util = { version = "0.7.11", features = ["codec"] } serde = { version = "1.0.208", features = ["derive"] } futures-concurrency = "7.6.1" slotmap = "1.0.7" +governor = "0.6.3" [dev-dependencies] reserve-port = "2" diff --git a/crates/data-server/src/api.rs b/crates/data-server/src/api.rs index 4e282352..e1527412 100644 --- a/crates/data-server/src/api.rs +++ b/crates/data-server/src/api.rs @@ -1,3 +1,5 @@ +use std::time::Duration; + use serde::{Deserialize, Serialize}; pub mod client; @@ -42,4 +44,6 @@ pub struct SubscribeError; #[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)] #[error("placeholder")] -pub struct ServerError; +pub enum ServerError { + TooManyRequests(Duration), +} diff --git a/crates/data-server/src/server/client.rs b/crates/data-server/src/server/client.rs index 5248df0e..41d7069b 100644 --- a/crates/data-server/src/server/client.rs +++ b/crates/data-server/src/server/client.rs @@ -1,7 +1,11 @@ use std::net::SocketAddr; +use std::num::NonZeroU32; +use std::time::Duration; use color_eyre::eyre::Context; use futures::SinkExt; +use governor::clock::{Clock, DefaultClock}; +use governor::{Quota, RateLimiter}; use ratelimited_logger::RateLimitedLogger; use tokio::net::{TcpListener, TcpStream}; use tokio::sync::mpsc; @@ -13,8 +17,8 @@ use color_eyre::{Result, Section}; use tracing::warn; -use crate::api; use crate::api::AffectorError; +use crate::api::{self, ServerError}; use super::{affector::Offline, affector::Registar, Conn, Event}; @@ -75,6 +79,10 @@ async fn handle_client( } pub async fn handle(addr: SocketAddr, tx: mpsc::Sender, affectors: Registar) -> Result<()> { + let quota = Quota::with_period(Duration::from_secs(1)) + .unwrap() + .allow_burst(NonZeroU32::new(5).unwrap()); + let limiter = RateLimiter::keyed(quota); let listener = TcpListener::bind(addr) .await .wrap_err("Could not start receiving updates") @@ -82,19 +90,32 @@ pub async fn handle(addr: SocketAddr, tx: mpsc::Sender, affectors: Regist let mut logger = RateLimitedLogger::new(); loop { - let res = listener.accept().await; - match res { - Ok((stream, source)) => { - if let Some((conn, name)) = handshake(stream, source, &mut logger).await { - let id = format!("{name}@{source}"); - tokio::task::spawn(handle_client(conn, id, tx.clone(), affectors.clone())); - } - } + let (socket, source) = match listener.accept().await { Err(e) => { - warn!("new connection failed: {e}"); + logger.warn(&format!("client could not connect: {e}")); continue; } + Ok(res) => res, + }; + + let Some((mut conn, name)) = handshake(socket, source, &mut logger).await else { + continue; + }; + + if let Err(allowed_again) = limiter.check_key(&(source.ip(), name.clone())) { + let allowed_in = allowed_again.wait_time_from(DefaultClock::default().now()); + let _ignore_err = conn.send(api::Response::Error(ServerError::TooManyRequests( + allowed_in, + ))); + continue; + } + + let Ok(()) = conn.send(api::Response::Handshake).await else { + continue; }; + + let id = format!("{name}@{source}"); + tokio::task::spawn(handle_client(conn, id, tx.clone(), affectors.clone())); } } diff --git a/crates/data-server/src/subscriber.rs b/crates/data-server/src/subscriber.rs deleted file mode 100644 index 7eca984c..00000000 --- a/crates/data-server/src/subscriber.rs +++ /dev/null @@ -1,155 +0,0 @@ -use std::io::{BufRead, BufReader, Write}; -use std::net::{SocketAddr, TcpStream}; -use std::time::Duration; -use std::vec; - -use protocol::Msg; -use serde::{Deserialize, Serialize}; -use tokio::io::{AsyncBufReadExt, AsyncWriteExt}; -use tracing::instrument; - -pub mod reconnecting; - - -pub struct Subscriber { - reader: BufReader, - buf: Vec, - values: vec::IntoIter, -} - -impl Subscriber { - pub fn connect(addr: impl Into, name: &str) -> Result { - let mut conn = TcpStream::connect_timeout(&addr.into(), Duration::from_millis(400)) - .map_err(SubscribeError::ConnFailed)?; - let name_len: u8 = name - .len() - .try_into() - .map_err(|_| SubscribeError::NameTooLong)?; - conn.write_all(&[name_len]) - .map_err(SubscribeError::FailedToWriteName)?; - conn.write_all(name.as_bytes()) - .map_err(SubscribeError::FailedToWriteName)?; - let reader = BufReader::new(conn); - let buf = Vec::new(); - - Ok(Self { - reader, - buf, - values: vec![].into_iter(), - }) - } - - pub fn next_msg(&mut self) -> Result { - if let Some(val) = self.values.next() { - return Ok(val); - } - - self.buf.clear(); - let n_read = self - .reader - .read_until(0, &mut self.buf) - .map_err(SubscribeError::ConnFailed)?; - decode_buffer_and_return_first(n_read, &mut self.buf, &mut self.values) - } -} - -#[allow(clippy::module_name_repetitions)] -#[derive(Debug)] -pub struct AsyncSubscriber { - reader: tokio::io::BufReader, - buf: Vec, - values: vec::IntoIter, -} - -impl AsyncSubscriber { - pub async fn connect( - addr: impl tokio::net::ToSocketAddrs, - name: &str, - ) -> Result { - let mut conn = tokio::net::TcpStream::connect(addr) - .await - .map_err(SubscribeError::ConnFailed)?; - let name_len: u8 = name - .len() - .try_into() - .map_err(|_| SubscribeError::NameTooLong)?; - conn.write_all(&[name_len]) - .await - .map_err(SubscribeError::FailedToWriteName)?; - conn.write_all(name.as_bytes()) - .await - .map_err(SubscribeError::FailedToWriteName)?; - let reader = tokio::io::BufReader::new(conn); - let buf = Vec::new(); - - Ok(Self { - reader, - buf, - values: vec![].into_iter(), - }) - } - - pub async fn next_msg(&mut self) -> Result { - if let Some(val) = self.values.next() { - return Ok(val); - } - - self.buf.clear(); - let n_read = self - .reader - .read_until(0, &mut self.buf) - .await - .map_err(SubscribeError::ConnFailed)?; - decode_buffer_and_return_first(n_read, &mut self.buf, &mut self.values) - } -} - -#[instrument(level = "trace")] -fn decode_buffer_and_return_first( - n_read: usize, - buf: &mut Vec, - buffer: &mut vec::IntoIter, -) -> Result { - assert!(buffer.next().is_none()); - - if n_read == 0 { - return Err(SubscribeError::ConnEnded); - } - - buf.resize(n_read, 0); // ensure stop delimiter in bytes - let bytes = &mut buf[0..n_read]; - let decoded: Msg<50> = Msg::decode(bytes).map_err(SubscribeError::DecodeFailed)?; - match decoded { - Msg::Readings(readings) => { - *buffer = readings - .values - .iter() - .map(Clone::clone) - .map(SubMessage::Reading) - .collect::>() - .into_iter(); - } - Msg::ErrorReport(report) => { - *buffer = vec![SubMessage::ErrorReport(Box::new(report.error))].into_iter(); - } - } - - Ok(buffer.next().expect("min values in sensormessage is one")) -} - -#[derive(Debug, thiserror::Error)] -pub enum SubscribeError { - #[error("The connection to the subscribe server failed, error: {0}")] - ConnFailed(std::io::Error), - #[error( - "Could not decode message, is protocol lib up to date on server \ - and client? Or has the server crashed? Decoderror: {0:?}" - )] - DecodeFailed(protocol::DecodeMsgError), - #[error("Connection ended")] - ConnEnded, - #[error("A subscribers name must be smaller then 256 bytes long")] - NameTooLong, - #[error("Could not send name to data-server: {0}")] - FailedToWriteName(std::io::Error), -} diff --git a/crates/data-server/src/subscriber/reconnecting.rs b/crates/data-server/src/subscriber/reconnecting.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/crates/log-store/src/server/clients.rs b/crates/log-store/src/server/clients.rs index 2ef04102..98377f44 100644 --- a/crates/log-store/src/server/clients.rs +++ b/crates/log-store/src/server/clients.rs @@ -11,7 +11,7 @@ use ratelimited_logger::RateLimitedLogger; use tokio::net::{TcpListener, TcpStream}; use tokio_serde::formats::Bincode; use tokio_util::codec::{Framed, LengthDelimitedCodec}; -use tracing::{debug, error, warn}; +use tracing::{debug, error}; use super::db::{Logs, Stats}; use crate::api::{self, ServerError}; @@ -37,7 +37,7 @@ pub(crate) async fn handle(port: u16, stats: Stats, logs: Logs) -> color_eyre::R loop { let (socket, source) = match listener.accept().await { Err(e) => { - warn!("client could not connect: {e}"); + logger.warn(&format!("client could not connect: {e}")); continue; } Ok(res) => res, diff --git a/crates/sensor-tui/src/tui/affectors.rs b/crates/sensor-tui/src/tui/affectors.rs index bf8492ad..0ccad911 100644 --- a/crates/sensor-tui/src/tui/affectors.rs +++ b/crates/sensor-tui/src/tui/affectors.rs @@ -11,7 +11,6 @@ pub type TreeKey = [u8; 6]; pub struct Tab { affector_tree_state: TreeState, - // affectors } impl Default for Tab { @@ -43,7 +42,18 @@ impl Tab { todo!() } - pub fn process_update(&mut self, _update: Update) { - todo!() + pub fn process_update(&mut self, update: Update) { + + match update { + Update::ReadingList(_) | + Update::Fetched {.. } | + Update::FetchError(_) | + Update::SubscribeError(_) => (), + Update::SensorReading(r) => { + r.device().info().affectors; + }, + Update::SensorError(_) => todo!(), + Update::DeviceList(_) => todo!(), + } } } From 977788ecbadd05e73259eb0d9dc27b71ff832c93 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 21 Aug 2024 01:21:38 +0200 Subject: [PATCH 208/687] add affector tree to protocol and tui --- crates/data-store/src/server/db/series.rs | 5 +- crates/log-store/src/server/db/log.rs | 5 +- crates/protocol/src/affector.rs | 25 ++- crates/protocol/src/affector/tree.rs | 70 +++++++ crates/protocol/src/button.rs | 10 +- crates/protocol/src/large_bedroom.rs | 21 +- crates/protocol/src/large_bedroom/bed.rs | 52 ++++- crates/protocol/src/large_bedroom/desk.rs | 14 +- crates/protocol/src/lib.rs | 4 +- crates/protocol/src/reading.rs | 60 +++++- crates/protocol/src/reading/tree.rs | 70 +++++++ crates/protocol/src/reading_tree.rs | 112 ---------- crates/protocol/src/small_bedroom.rs | 6 +- crates/sensor-tui/src/tui.rs | 18 +- crates/sensor-tui/src/tui/affectors.rs | 193 ++++++++++++++---- crates/sensor-tui/src/tui/readings.rs | 64 +++--- .../src/tui/readings/history_len.rs | 10 +- crates/sensor-tui/src/tui/readings/render.rs | 4 +- .../src/tui/readings/render/chart/labels.rs | 4 +- .../src/tui/readings/sensor_info.rs | 10 +- crates/text-widget/src/main.rs | 2 +- 21 files changed, 515 insertions(+), 244 deletions(-) create mode 100644 crates/protocol/src/affector/tree.rs create mode 100644 crates/protocol/src/reading/tree.rs delete mode 100644 crates/protocol/src/reading_tree.rs diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index 3cd282c0..28382584 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -6,7 +6,8 @@ use std::time::Instant; use byteseries::{downsample, series, ByteSeries}; use color_eyre::eyre::{eyre, WrapErr}; use color_eyre::{Result, Section}; -use protocol::reading_tree::{Item, ReadingInfo, Tree}; +use protocol::reading::tree::{Item, Tree}; +use protocol::reading; use serde::{Deserialize, Serialize}; use tracing::{info, instrument, trace}; @@ -325,7 +326,7 @@ fn base_path(reading: &protocol::Reading) -> PathBuf { let mut current = reading as &dyn Tree; loop { match current.inner() { - Item::Leaf(ReadingInfo { device, .. }) => { + Item::Leaf(reading::Info { device, .. }) => { parts.push(device.info().name.to_lowercase()); break; } diff --git a/crates/log-store/src/server/db/log.rs b/crates/log-store/src/server/db/log.rs index a336489e..82b7bd76 100644 --- a/crates/log-store/src/server/db/log.rs +++ b/crates/log-store/src/server/db/log.rs @@ -281,7 +281,8 @@ impl Logs { /// relative path without extension fn base_path(device: &protocol::Device) -> PathBuf { - use protocol::reading_tree::{Item, ReadingInfo, Tree}; + use protocol::reading::tree::{Item, Tree}; + use protocol::reading::Info; let mut parts = Vec::new(); let mut current = device @@ -291,7 +292,7 @@ fn base_path(device: &protocol::Device) -> PathBuf { .expect("a device has at least one reading it affects") as &dyn Tree; loop { match current.inner() { - Item::Leaf(ReadingInfo { device, .. }) => { + Item::Leaf(Info { device, .. }) => { parts.push(device.info().name.to_lowercase()); break; } diff --git a/crates/protocol/src/affector.rs b/crates/protocol/src/affector.rs index 129ccc19..926d6634 100644 --- a/crates/protocol/src/affector.rs +++ b/crates/protocol/src/affector.rs @@ -5,13 +5,36 @@ use serde::{Deserialize, Serialize}; use crate::large_bedroom; use crate::msg::cobs_overhead; +#[cfg(feature = "alloc")] +pub mod tree; + #[derive( - Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Hash, PartialEq, Eq, + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, + Eq, + Hash, )] +#[strum_discriminants(derive(Hash))] pub enum Affector { LargeBedroom(large_bedroom::Affector), } +#[cfg(feature = "alloc")] +tree::all_nodes!{Affector; AffectorDiscriminants; LargeBedroom} + +#[cfg(feature = "alloc")] +#[derive(Debug, Clone)] +pub struct Info { + pub description: &'static str, +} + impl Affector { const ENCODED_SIZE: usize = Affector::POSTCARD_MAX_SIZE + cobs_overhead(Affector::POSTCARD_MAX_SIZE); diff --git a/crates/protocol/src/affector/tree.rs b/crates/protocol/src/affector/tree.rs new file mode 100644 index 00000000..9067fc34 --- /dev/null +++ b/crates/protocol/src/affector/tree.rs @@ -0,0 +1,70 @@ +use super::Info; + +pub type Id = u8; +#[derive(Debug)] +pub enum Item<'a> { + Leaf(Info), + Node(&'a dyn Tree), +} + +pub trait Tree: core::fmt::Debug { + fn inner(&self) -> Item<'_>; + fn leaf(&self) -> Info + where + Self: Sized, + { + let mut current = self as &dyn Tree; + loop { + match current.inner() { + Item::Node(node) => current = node, + Item::Leaf(leaf) => return leaf, + } + } + } + fn name(&self) -> String { + let dbg_repr = format!("{self:?}"); + dbg_repr + .split_once('(') + .map_or("_", |(name, _)| name) + .to_string() + } + fn branch_id(&self) -> Id; +} + +macro_rules! impl_zero { + ($name:ident; $($var:ident),*) => { + impl $name { + #[must_use] + #[allow(unreachable_patterns)] + pub fn is_same_as(&self, other: &Self) -> bool { + match (self, other) { + $(($name::$var(a), $name::$var(b)) => a.is_same_as(b),)* + (_, _) => false, + } + } + } + + }; +} +pub(crate) use impl_zero; + +macro_rules! all_nodes { + ($name:ident; $variant:ident; $($var:ident),*) => { + impl crate::affector::tree::Tree for $name { + fn inner(&self) -> crate::affector::tree::Item<'_> { + match self { + $( + $name::$var(inner) => crate::affector::tree::Item::Node(inner as &dyn crate::affector::tree::Tree) + ),* + } + } + + fn branch_id(&self) -> crate::affector::tree::Id { + $variant::from(self) as crate::affector::tree::Id + } + + } + crate::affector::tree::impl_zero!{$name; $($var),*} + }; +} +pub(crate) use all_nodes; diff --git a/crates/protocol/src/button.rs b/crates/protocol/src/button.rs index 240d872a..f0252264 100644 --- a/crates/protocol/src/button.rs +++ b/crates/protocol/src/button.rs @@ -68,9 +68,9 @@ macro_rules! button_enum { } #[cfg(feature = "alloc")] - impl crate::reading_tree::Tree for $name { - fn inner(&self) -> crate::reading_tree::Item<'_> { - crate::reading_tree::Item::Leaf(crate::reading_tree::ReadingInfo { + impl crate::reading::tree::Tree for $name { + fn inner(&self) -> crate::reading::tree::Item<'_> { + crate::reading::tree::Item::Leaf(crate::reading::Info { val: (*self).into(), device: $device, description: "button", @@ -88,13 +88,13 @@ macro_rules! button_enum { .unwrap_or("-") .to_string() } - fn branch_id(&self) -> crate::reading_tree::Id { + fn branch_id(&self) -> crate::reading::tree::Id { // SAFETY: Because `Self` is marked `repr(u8)`, its layout is a // `repr(C)` `union` between `repr(C)` structs, each of which // has the `u8` discriminant as its first field, so we can read // the discriminant without offsetting the pointer. let discriminant = unsafe { *<*const _>::from(self).cast::() }; - discriminant as crate::reading_tree::Id + discriminant as crate::reading::tree::Id } } diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index 2f96e7c6..3c4ec4a4 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -1,9 +1,10 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; +use crate::affector; use crate::msg::DecodeMsgError; #[cfg(feature = "alloc")] -use crate::reading_tree; +use crate::reading; pub mod bed; pub mod desk; @@ -26,7 +27,7 @@ pub enum Reading { } #[cfg(feature = "alloc")] -reading_tree::all_nodes! {Reading; ReadingDiscriminants; Bed, Desk} +reading::tree::all_nodes! {Reading; ReadingDiscriminants; Bed, Desk} #[derive( strum::EnumDiscriminants, @@ -80,12 +81,26 @@ impl Device { } #[derive( - Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Hash, PartialEq, Eq, + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, + Eq, + Hash, )] +#[strum_discriminants(derive(Hash))] pub enum Affector { Bed(bed::Affector), } +#[cfg(feature = "alloc")] +affector::tree::all_nodes! {Affector; AffectorDiscriminants; Bed} + impl Affector { #[cfg(feature = "alloc")] #[must_use] diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 1034d609..e27f7cb2 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -1,11 +1,13 @@ use core::time::Duration; use crate::button::Press; -use crate::button_enum; #[cfg(feature = "alloc")] -use crate::reading_tree::{Id, Item, ReadingInfo, Tree}; +use crate::reading::tree::{Id, Item, Tree}; +#[cfg(feature = "alloc")] +use crate::reading::Info; #[cfg(feature = "alloc")] use crate::Unit; +use crate::{affector, button_enum}; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -241,7 +243,7 @@ impl Tree for Reading { ), }; - Item::Leaf(ReadingInfo { + Item::Leaf(Info { val, device, resolution, @@ -492,11 +494,51 @@ impl Device { } #[derive( - Clone, Copy, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Hash, PartialEq, Eq, + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, + Eq, + Hash, )] +#[strum_discriminants(derive(Hash))] pub enum Affector { - Sps30FanClean, + Sps30FanClean = 0, MhzZeroPointCalib, Nau7802LeftCalib, Nau7802RightCalib, } + +impl Affector { + #[must_use] + pub fn is_same_as(&self, other: &Self) -> bool { + match (self, other) { + (Affector::Sps30FanClean, Affector::Sps30FanClean) => true, + (Affector::MhzZeroPointCalib, Affector::MhzZeroPointCalib) => true, + (Affector::Nau7802LeftCalib, Affector::Nau7802LeftCalib) => true, + (Affector::Nau7802RightCalib, Affector::Nau7802RightCalib) => true, + _ => false, + } + } +} + +impl affector::tree::Tree for Affector { + fn inner(&self) -> affector::tree::Item<'_> { + let description = match self { + Affector::Sps30FanClean => "Accelerate the fan to maximum speed for 10 seconds in order to blow out the dust accumulated in the fan", + Affector::MhzZeroPointCalib => "Set the current co2 value as 400ppm", + Affector::Nau7802LeftCalib | + Affector::Nau7802RightCalib => "Detect and correct power supply and temperature variations to ADC", + }; + affector::tree::Item::Leaf(affector::Info { description }) + } + + fn branch_id(&self) -> affector::tree::Id { + AffectorDiscriminants::from(self) as Id + } +} diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index c53d975d..cea31ef4 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -5,9 +5,11 @@ use serde::{Deserialize, Serialize}; use crate::button_enum; #[cfg(feature = "alloc")] -use crate::reading_tree::{Item, ReadingInfo, Tree}; +use crate::reading::tree::{Item, Tree}; #[cfg(feature = "alloc")] use crate::Unit; +#[cfg(feature = "alloc")] +use crate::reading::Info; button_enum! { /// No these are not borg, these are buttons on a string of cat5. @@ -48,7 +50,7 @@ impl Tree for Reading { #[must_use] fn inner(&self) -> Item<'_> { let leaf = match self { - Reading::Temperature(val) => ReadingInfo { + Reading::Temperature(val) => Info { val: *val, device: Device::Bme280.rooted(), resolution: 0.01, @@ -57,7 +59,7 @@ impl Tree for Reading { description: "Temperature", branch_id: self.branch_id(), }, - Reading::Humidity(val) => ReadingInfo { + Reading::Humidity(val) => Info { val: *val, device: Device::Bme280.rooted(), resolution: 0.008, @@ -66,7 +68,7 @@ impl Tree for Reading { description: "Humidity", branch_id: self.branch_id(), }, - Reading::Pressure(val) => ReadingInfo { + Reading::Pressure(val) => Info { val: *val, device: Device::Bme280.rooted(), range: 87_000.0..108_100.0, @@ -81,8 +83,8 @@ impl Tree for Reading { } #[must_use] - fn branch_id(&self) -> crate::reading_tree::Id { - ReadingDiscriminants::from(self) as crate::reading_tree::Id + fn branch_id(&self) -> crate::reading::tree::Id { + ReadingDiscriminants::from(self) as crate::reading::tree::Id } } diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 9118b0fd..03a67292 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -3,15 +3,13 @@ use core::fmt::Display; -#[cfg(feature = "alloc")] -pub mod reading_tree; pub mod button; pub(crate) use button::button_enum; pub mod large_bedroom; pub mod small_bedroom; -mod reading; +pub mod reading; mod device; mod error; pub mod affector; diff --git a/crates/protocol/src/reading.rs b/crates/protocol/src/reading.rs index f1b2f3b9..4f6f4c59 100644 --- a/crates/protocol/src/reading.rs +++ b/crates/protocol/src/reading.rs @@ -4,6 +4,11 @@ use serde::{Deserialize, Serialize}; use crate::{large_bedroom, small_bedroom}; #[cfg(feature = "alloc")] use crate::Device; +#[cfg(feature = "alloc")] +use crate::Unit; + +#[cfg(feature = "alloc")] +pub mod tree; #[derive( strum::EnumDiscriminants, @@ -27,23 +32,23 @@ pub enum Reading { impl Reading { #[must_use] pub fn from_same_device(&self) -> &'static [Reading] { - use crate::reading_tree::Tree; + use tree::Tree; self.leaf().from_same_device() } #[must_use] pub fn range(&self) -> core::ops::Range { - use crate::reading_tree::Tree; + use tree::Tree; self.leaf().range } #[must_use] /// the step between the two closest datapoints that are not the same pub fn resolution(&self) -> f32 { - use crate::reading_tree::Tree; + use tree::Tree; self.leaf().resolution } #[must_use] pub fn device(&self) -> Device { - use crate::reading_tree::Tree; + use tree::Tree; self.leaf().device } } @@ -55,4 +60,49 @@ impl Reading { } #[cfg(feature = "alloc")] -crate::reading_tree::all_nodes! {Reading; ReadingDiscriminants; LargeBedroom, SmallBedroom} +#[derive(Debug, Clone)] +pub struct Info { + pub val: f32, + pub device: Device, + /// smallest step size the data can make + pub resolution: f32, + pub range: core::ops::Range, + pub unit: Unit, + pub description: &'static str, + pub branch_id: u8, +} + +#[cfg(feature = "alloc")] +impl Info { + #[must_use] + pub fn from_same_device(&self) -> &'static [Reading] { + self.device.info().affects_readings + } + + /// useful for printing/formatting floats + /// # Example + /// ```rust + /// use crate::Reading; + /// use crate::large_bedroom; + /// use crate::large_bedroom::desk; + /// + /// let reading = + /// Reading::LargeBedroom(large_bedroom::Reading(desk::Reading::Temperature(22.428124); + /// + /// let info = reading.leaf(); + /// let printed = format!("{0:.1$}", info.val, info.precision()); + /// assert_eq!(printed, "22.42"); + /// ``` + #[must_use] + #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] + pub fn precision(&self) -> usize { + if self.resolution > 1.0 { + 0 + } else { + self.resolution.log10().abs() as usize + } + } +} + +#[cfg(feature = "alloc")] +tree::all_nodes! {Reading; ReadingDiscriminants; LargeBedroom, SmallBedroom} diff --git a/crates/protocol/src/reading/tree.rs b/crates/protocol/src/reading/tree.rs new file mode 100644 index 00000000..8f8ea856 --- /dev/null +++ b/crates/protocol/src/reading/tree.rs @@ -0,0 +1,70 @@ +use super::Info; + +pub type Id = u8; +#[derive(Debug)] +pub enum Item<'a> { + Leaf(Info), + Node(&'a dyn Tree), +} + +pub trait Tree: core::fmt::Debug { + fn inner(&self) -> Item<'_>; + fn leaf(&self) -> Info + where + Self: Sized, + { + let mut current = self as &dyn Tree; + loop { + match current.inner() { + Item::Node(node) => current = node, + Item::Leaf(leaf) => return leaf, + } + } + } + fn name(&self) -> String { + let dbg_repr = format!("{self:?}"); + dbg_repr + .split_once('(') + .map_or("_", |(name, _)| name) + .to_string() + } + fn branch_id(&self) -> Id; +} + +macro_rules! impl_zero { + ($name:ident; $($var:ident),*) => { + impl $name { + #[must_use] + pub fn is_same_as(&self, other: &Self) -> bool { + match (self, other) { + $(($name::$var(a), $name::$var(b)) => a.is_same_as(b),)* + (_, _) => false, + } + } + } + + }; +} +pub(crate) use impl_zero; + +macro_rules! all_nodes { + ($name:ident; $variant:ident; $($var:ident),*) => { + impl crate::reading::tree::Tree for $name { + fn inner(&self) -> crate::reading::tree::Item<'_> { + match self { + $( + $name::$var(inner) => crate::reading::tree::Item::Node(inner as &dyn crate::reading::tree::Tree) + ),* + } + } + + fn branch_id(&self) -> crate::reading::tree::Id { + $variant::from(self) as crate::reading::tree::Id + } + + } + crate::reading::tree::impl_zero!{$name; $($var),*} + }; +} +pub(crate) use all_nodes; + diff --git a/crates/protocol/src/reading_tree.rs b/crates/protocol/src/reading_tree.rs deleted file mode 100644 index a2014d3b..00000000 --- a/crates/protocol/src/reading_tree.rs +++ /dev/null @@ -1,112 +0,0 @@ -use crate::{Device, Reading, Unit}; - -#[derive(Debug, Clone)] -pub struct ReadingInfo { - pub val: f32, - pub device: Device, - /// smallest step size the data can make - pub resolution: f32, - pub range: core::ops::Range, - pub unit: Unit, - pub description: &'static str, - pub branch_id: u8, -} - -impl ReadingInfo { - #[must_use] - pub fn from_same_device(&self) -> &'static [Reading] { - self.device.info().affects_readings - } - - /// useful for printing/formatting floats - /// # Example - /// ```rust - /// use crate::Reading; - /// use crate::large_bedroom; - /// use crate::large_bedroom::desk; - /// - /// let reading = - /// Reading::LargeBedroom(large_bedroom::Reading(desk::Reading::Temperature(22.428124); - /// - /// let info = reading.leaf(); - /// let printed = format!("{0:.1$}", info.val, info.precision()); - /// assert_eq!(printed, "22.42"); - /// ``` - #[must_use] - #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] - pub fn precision(&self) -> usize { - if self.resolution > 1.0 { - 0 - } else { - self.resolution.log10().abs() as usize - } - } -} - -pub type Id = u8; -#[derive(Debug)] -pub enum Item<'a> { - Leaf(ReadingInfo), - Node(&'a dyn Tree), -} - -pub trait Tree: core::fmt::Debug { - fn inner(&self) -> Item<'_>; - fn leaf(&self) -> ReadingInfo - where - Self: Sized, - { - let mut current = self as &dyn Tree; - loop { - match current.inner() { - Item::Node(node) => current = node, - Item::Leaf(leaf) => return leaf, - } - } - } - fn name(&self) -> String { - let dbg_repr = format!("{self:?}"); - dbg_repr - .split_once('(') - .map_or("_", |(name, _)| name) - .to_string() - } - fn branch_id(&self) -> Id; -} - -macro_rules! impl_zero { - ($name:ident; $($var:ident),*) => { - impl $name { - #[must_use] - pub fn is_same_as(&self, other: &Self) -> bool { - match (self, other) { - $(($name::$var(a), $name::$var(b)) => a.is_same_as(b),)* - (_, _) => false, - } - } - } - - }; -} -pub(crate) use impl_zero; - -macro_rules! all_nodes { - ($name:ident; $variant:ident; $($var:ident),*) => { - impl crate::reading_tree::Tree for $name { - fn inner(&self) -> crate::reading_tree::Item<'_> { - match self { - $( - $name::$var(inner) => crate::reading_tree::Item::Node(inner as &dyn crate::reading_tree::Tree) - ),* - } - } - - fn branch_id(&self) -> crate::reading_tree::Id { - $variant::from(self) as crate::reading_tree::Id - } - - } - crate::reading_tree::impl_zero!{$name; $($var),*} - }; -} -pub(crate) use all_nodes; diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index e6819da7..5be5796b 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; use crate::button::Press; #[cfg(feature = "alloc")] -use crate::reading_tree::{Item, Tree}; +use crate::reading::tree::{Item, Tree}; crate::button_enum! { /// +-----------------------------------------+ @@ -47,8 +47,8 @@ impl Tree for Reading { } } - fn branch_id(&self) -> crate::reading_tree::Id { - ReadingDiscriminants::from(self) as crate::reading_tree::Id + fn branch_id(&self) -> crate::reading::tree::Id { + ReadingDiscriminants::from(self) as crate::reading::tree::Id } } diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index dfce5d4b..0d42f86b 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -1,5 +1,5 @@ use crossterm::{ - event::{self, KeyCode, KeyEventKind}, + event::{self, KeyCode, KeyEventKind, KeyModifiers}, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, ExecutableCommand, }; @@ -114,6 +114,9 @@ impl App { KeyCode::Right => { self.active_tab = self.active_tab.swap(); } + KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => { + break Ok(()); + } _ => (), } @@ -121,8 +124,11 @@ impl App { ActiveTab::Readings => self.readings_tab.handle_key(key), ActiveTab::Affectors => self.affectors_tab.handle_key(key), }; - if let ShouldExit::Yes = res { - return Ok(()); + if let Some(unhandled_key) = res { + match unhandled_key.code { + KeyCode::Char('q') | KeyCode::Esc => return Ok(()), + _ => (), + } } } } @@ -132,12 +138,8 @@ impl App { continue; }; + self.affectors_tab.process_update(&update); self.readings_tab.process_update(update); } } } - -enum ShouldExit { - Yes, - No, -} diff --git a/crates/sensor-tui/src/tui/affectors.rs b/crates/sensor-tui/src/tui/affectors.rs index 0ccad911..54d58b1f 100644 --- a/crates/sensor-tui/src/tui/affectors.rs +++ b/crates/sensor-tui/src/tui/affectors.rs @@ -1,59 +1,178 @@ -use crossterm::event::KeyEvent; +use std::collections::{HashMap, HashSet}; + +use crossterm::event::{KeyCode, KeyEvent}; +use protocol::{affector, Device}; use ratatui::layout::Rect; +use ratatui::style::{Modifier, Style}; +use ratatui::widgets::{Block, Borders}; use ratatui::Frame; -use tui_tree_widget::TreeState; +use tui_tree_widget::Tree; +use tui_tree_widget::{TreeItem, TreeState}; use crate::Update; -use super::{ShouldExit, Theme}; +use super::Theme; +use protocol::affector::tree::Item; +use protocol::affector::tree::Tree as AffectorTree; pub type TreeKey = [u8; 6]; +struct AffectorState; + +#[derive(Default)] pub struct Tab { - affector_tree_state: TreeState, + tree_state: TreeState, + pub ground: Vec>, + pub data: HashMap, } -impl Default for Tab { - fn default() -> Self { - Self { - affector_tree_state: Default::default(), +impl Tab { + pub fn render(&mut self, frame: &mut Frame, layout: Rect, theme: &Theme) { + frame.render_stateful_widget( + Tree::new(&self.ground) + .expect("all item identifiers should be unique") + .block( + Block::default() + .title("Controllable affectors") + .borders(Borders::ALL), + ) + .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) + .highlight_symbol(">>"), + layout, + &mut self.tree_state, + ); + } + + pub fn handle_key(&mut self, key: KeyEvent) -> Option { + match key.code { + KeyCode::Down => { + self.tree_state.key_down(); + } + KeyCode::Up => { + self.tree_state.key_up(); + } + KeyCode::Enter => { + self.tree_state.toggle_selected(); + } + _ => return Some(key), + } + None + } + + pub fn process_update(&mut self, update: &Update) { + let devices = match update { + Update::ReadingList(_) + | Update::Fetched { .. } + | Update::FetchError(_) + | Update::SubscribeError(_) => &Vec::new(), + Update::SensorReading(r) => &vec![r.device()], + Update::SensorError(err) => &vec![err.device()], + Update::DeviceList(devices) => devices, + }; + + let affectors: HashSet<_> = devices + .iter() + .map(Device::info) + .flat_map(|info| info.affectors) + .collect(); + + for affector in affectors { + self.update_tree(affector); + } + + if self.tree_state.selected().is_empty() { + self.tree_state.select_first(); } } } impl Tab { - pub fn render(&mut self, _frame: &mut Frame, _layout: Rect, _theme: &Theme) { - // frame.render_stateful_widget( - // Tree::new(affectors) - // .expect("all item identifiers should be unique") - // .block( - // Block::default() - // .title("Controllable affectors") - // .borders(Borders::ALL), - // ) - // .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) - // .highlight_symbol(">>"), - // layout, - // &mut app.affector_tree_state, - // ); + fn update_tree(&mut self, affector: &protocol::Affector) { + let key = tree_key(affector); + + let mut tree = add_root(affector as &dyn AffectorTree, &mut self.ground); + let mut tomato = match affector.inner() { + Item::Leaf(_) => unreachable!("no values at level 0"), + Item::Node(inner) => inner, + }; + loop { + match tomato.inner() { + Item::Leaf(_) => { + let text = tomato.name(); + add_leaf(text, tree, key); + return; + } + Item::Node(inner) => { + tree = add_node(tomato, tree); + tomato = inner; + } + }; + } } +} + +fn add_leaf(text: String, tree: &mut TreeItem<'static, TreeKey>, key: TreeKey) { + let new_item = TreeItem::new_leaf(key, text.clone()); + // todo is exists its fine handle that + let _ignore_existing = tree.add_child(new_item); // errors when identifier already exists + + let new_child = tree + .children() + .iter() + .position(|item| *item.identifier() == key) + .expect("just added it"); + let existing = tree.child_mut(new_child).expect("just added it"); + existing.update_text(text); +} - pub fn handle_key(&mut self, _key: KeyEvent) -> ShouldExit { - todo!() +fn add_root<'a>( + tomato: &dyn AffectorTree, + ground: &'a mut Vec>, +) -> &'a mut TreeItem<'static, TreeKey> { + let key = [tomato.branch_id(); 6]; + let exists = ground.iter().any(|item| *item.identifier() == key); + if !exists { + let new_root = TreeItem::new(key, tomato.name(), vec![]).unwrap(); + ground.push(new_root); } - pub fn process_update(&mut self, update: Update) { - - match update { - Update::ReadingList(_) | - Update::Fetched {.. } | - Update::FetchError(_) | - Update::SubscribeError(_) => (), - Update::SensorReading(r) => { - r.device().info().affectors; - }, - Update::SensorError(_) => todo!(), - Update::DeviceList(_) => todo!(), - } + ground + .iter_mut() + .find(|item| *item.identifier() == key) + .expect("checked and added if missing") +} + +fn add_node<'a>( + tomato: &dyn AffectorTree, + tree: &'a mut TreeItem<'static, TreeKey>, +) -> &'a mut TreeItem<'static, TreeKey> { + let key = [tomato.branch_id(); 6]; + let new_item = TreeItem::new(key, tomato.name(), Vec::new()).unwrap(); + // add just in case it was not there yet + let _ignore_existing = tree.add_child(new_item); + let new_child = tree + .children() + .iter() + .position(|item| *item.identifier() == key) + .expect("just added it"); + tree.child_mut(new_child).expect("just added it") +} + +pub(crate) fn tree_key(affector: &protocol::Affector) -> TreeKey { + let mut key = [0u8; 6]; + key[0] = affector.branch_id(); + + let mut reading = affector as &dyn AffectorTree; + for byte in &mut key[1..] { + reading = match reading.inner() { + Item::Node(inner) => { + *byte = inner.branch_id(); + inner + } + Item::Leaf(affector::Info { .. }) => { + return key; + } + }; } + unreachable!("reading should not be deeper then key size") } diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index 01d29504..c7cfca6a 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -1,6 +1,6 @@ use std::time::Instant; -use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; +use crossterm::event::{KeyCode, KeyEvent}; use ratatui::layout::Rect; use ratatui::widgets::TableState; use ratatui::Frame; @@ -14,7 +14,7 @@ use history_len::HistoryLen; use crate::{fetch::Fetch, Update}; use sensor_info::{Readings, TreeKey}; -use super::{ShouldExit, Theme}; +use super::Theme; #[derive(Debug, Default, Clone, Copy)] enum InputMode { @@ -29,7 +29,7 @@ pub struct UiState { show_logs: bool, history_length: HistoryLen, input_mode: InputMode, - reading_tree_state: TreeState, + tree_state: TreeState, logs_table_state: TableState, } @@ -59,7 +59,7 @@ impl Tab { let (chart, percentiles, details, logs) = { let data = ui_state - .reading_tree_state + .tree_state .selected() .last() // unique leaf id .and_then(|key| readings.data.get_mut(key)); @@ -98,28 +98,21 @@ impl Tab { render::footer(frame, footer, ui_state, theme); } - pub fn handle_key(&mut self, key: KeyEvent) -> ShouldExit { - let res = self.ui_state.handle_key_all_modes(key); - if let ShouldExit::Yes = res { - return ShouldExit::Yes; - } + pub fn handle_key(&mut self, key: KeyEvent) -> Option { + self.ui_state.handle_key_all_modes(key)?; let plot_open = !self.plot_buf.is_empty(); - let res = match self.ui_state.input_mode { - InputMode::Normal => self.ui_state.handle_key_normal_mode(key, plot_open), - InputMode::EditingBounds => self.ui_state.handle_key_bounds_mode(key), + match self.ui_state.input_mode { + InputMode::Normal => self.ui_state.handle_key_normal_mode(key, plot_open)?, + InputMode::EditingBounds => self.ui_state.handle_key_bounds_mode(key)?, }; - if let ShouldExit::Yes = res { - return ShouldExit::Yes; - } - - ShouldExit::No + Some(key) } pub fn process_update(&mut self, update: Update) { let data = self .ui_state - .reading_tree_state + .tree_state .selected() .last() // unique leaf id .and_then(|key| self.readings.data.get_mut(key)); @@ -151,18 +144,15 @@ impl Tab { _ => (), } - if self.ui_state.reading_tree_state.selected().is_empty() { - self.ui_state.reading_tree_state.select_first(); + if self.ui_state.tree_state.selected().is_empty() { + self.ui_state.tree_state.select_first(); } } } impl UiState { - fn handle_key_normal_mode(&mut self, key: KeyEvent, plot_open: bool) -> ShouldExit { + fn handle_key_normal_mode(&mut self, key: KeyEvent, plot_open: bool) -> Option { match key.code { - KeyCode::Char('q') | KeyCode::Esc => { - return ShouldExit::Yes; - } KeyCode::Char('b') => { if plot_open { self.history_length.start_editing(); @@ -175,38 +165,36 @@ impl UiState { KeyCode::Char('l') => { self.show_logs = !self.show_logs; } - _other => (), + _ => return Some(key), } - ShouldExit::No + + None } - fn handle_key_bounds_mode(&mut self, key: KeyEvent) -> ShouldExit { + fn handle_key_bounds_mode(&mut self, key: KeyEvent) -> Option { match key.code { KeyCode::Char('q') | KeyCode::Esc => { self.history_length.exit_editing(); self.input_mode = InputMode::Normal; + None } - other => self.history_length.process(other), + _ => self.history_length.process(key), } - ShouldExit::No } - fn handle_key_all_modes(&mut self, key: KeyEvent) -> ShouldExit { + fn handle_key_all_modes(&mut self, key: KeyEvent) -> Option { match key.code { KeyCode::Down => { - self.reading_tree_state.key_down(); + self.tree_state.key_down(); } KeyCode::Up => { - self.reading_tree_state.key_up(); + self.tree_state.key_up(); } KeyCode::Enter => { - self.reading_tree_state.toggle_selected(); - } - KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => { - return ShouldExit::Yes; + self.tree_state.toggle_selected(); } - _other => (), + _ => return Some(key), } - ShouldExit::No + None } } diff --git a/crates/sensor-tui/src/tui/readings/history_len.rs b/crates/sensor-tui/src/tui/readings/history_len.rs index 028470e0..366d8cae 100644 --- a/crates/sensor-tui/src/tui/readings/history_len.rs +++ b/crates/sensor-tui/src/tui/readings/history_len.rs @@ -1,4 +1,4 @@ -use crossterm::event::KeyCode; +use crossterm::event::{KeyCode, KeyEvent}; use ratatui::{ style::{Color, Modifier, Style}, text::Span, @@ -38,15 +38,15 @@ impl Default for HistoryLen { } impl HistoryLen { - pub(crate) fn process(&mut self, key: KeyCode) { - match key { + pub(crate) fn process(&mut self, key: KeyEvent) -> Option { + match key.code { KeyCode::Char(c) => { self.text_input.push(c); } KeyCode::Backspace => { self.text_input.pop(); } - _other => (), + _other => return Some(key), } if let Ok(dur) = parse_duration(&self.text_input) { @@ -57,6 +57,8 @@ impl HistoryLen { } else { self.state = State::Invalid; } + + None } pub(crate) fn style_left_x_label(&self, org_label: Span<'static>) -> Span<'static> { diff --git a/crates/sensor-tui/src/tui/readings/render.rs b/crates/sensor-tui/src/tui/readings/render.rs index 943e17cc..7d0656e8 100644 --- a/crates/sensor-tui/src/tui/readings/render.rs +++ b/crates/sensor-tui/src/tui/readings/render.rs @@ -29,7 +29,7 @@ pub(crate) fn layout( logs: &Option>, ) -> [Rect; 3] { let [list_constraint, graph_constraint] = if chart.is_some() { - let tree_height = 2 + ui_state.reading_tree_state.flatten(&readings.ground).len(); + let tree_height = 2 + ui_state.tree_state.flatten(&readings.ground).len(); let details_height = 9; if (frame.area().height as f32) / 3. > tree_height as f32 { [ @@ -196,7 +196,7 @@ pub(crate) fn readings_and_details( .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) .highlight_symbol(">>"), left, - &mut app.reading_tree_state, + &mut app.tree_state, ); if let Some(details) = details { render_details(frame, right, details); diff --git a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs index e98208ea..f3aa2a24 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs @@ -1,4 +1,4 @@ -use protocol::reading_tree::ReadingInfo; +use protocol::reading; use ratatui::layout::Rect; use ratatui::text::Span; @@ -32,7 +32,7 @@ pub fn labels<'a>( fn evenly_spaced_labels( max_labels: u16, - reading: &ReadingInfo, + reading: &reading::Info, bounds: Bounds, ) -> impl DoubleEndedIterator { let resolution = reading.resolution as f64; diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index 2ddfe173..0839d13f 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -2,8 +2,8 @@ use hdrhistogram::Histogram; use itertools::Itertools; use jiff::Unit; use log_store::api::{self, ErrorEvent, Percentile}; -use protocol::reading_tree::ReadingInfo; -use protocol::reading_tree::{Item, Tree}; +use protocol::reading; +use protocol::reading::tree::{Item, Tree}; use protocol::Reading; use protocol::{Device, Error}; @@ -17,7 +17,7 @@ mod logs; #[derive(Debug)] pub struct SensorInfo { - pub info: ReadingInfo, + pub info: reading::Info, /// This value is not up to date, only use for requesting /// data use the last element of recent_history for printing pub reading: Reading, @@ -253,7 +253,7 @@ pub(crate) fn tree_key(reading: &Reading) -> TreeKey { *byte = inner.branch_id(); inner } - Item::Leaf(ReadingInfo { .. }) => { + Item::Leaf(reading::Info { .. }) => { return key; } }; @@ -471,7 +471,7 @@ impl Readings { } pub struct ChartParts<'a> { - pub reading: ReadingInfo, + pub reading: reading::Info, pub data: &'a [(f64, f64)], } diff --git a/crates/text-widget/src/main.rs b/crates/text-widget/src/main.rs index c6ea095a..af77ebe2 100644 --- a/crates/text-widget/src/main.rs +++ b/crates/text-widget/src/main.rs @@ -3,7 +3,7 @@ use color_eyre::Result; use data_server::api::SubMessage; use data_server::api::{ReconnectingClient, ReconnectingSubscribedClient}; use gethostname::gethostname; -use protocol::reading_tree::Tree; +use protocol::reading::tree::Tree; use protocol::Reading; use std::net::SocketAddr; use std::time::Duration; From c904397078ed1c55045dc300c54eb575edd0739a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 23 Aug 2024 12:59:57 +0200 Subject: [PATCH 209/687] port to byteseries builder api --- Cargo.lock | 258 +++++++++++++--------- crates/data-store/src/server/db/series.rs | 215 +++++++++--------- crates/log-store/src/server/db/log.rs | 86 +++----- 3 files changed, 294 insertions(+), 265 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index abadae8b..8e5abad7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "ahash" version = "0.8.11" @@ -332,7 +338,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -415,7 +421,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -428,7 +434,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object", "rustc-demangle", ] @@ -564,8 +570,8 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "byteseries" -version = "0.5.0" -source = "git+https://github.com/dvdsk/byteseries#9c724e34ccd908c31bf1047ffe7c6a7bb55a51f7" +version = "0.6.0" +source = "git+https://github.com/dvdsk/byteseries#b2d22feebdee41810f06968596ce8b10d42112f8" dependencies = [ "arraydeque", "itertools", @@ -600,9 +606,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.11" +version = "1.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fb8dd288a69fc53a1996d7ecfbf4a20d59065bff137ce7e56bbd620de191189" +checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932" dependencies = [ "shlex", ] @@ -636,9 +642,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.15" +version = "4.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d8838454fda655dafd3accb2b6e2bea645b9e4078abe84a22ceb947235c5cc" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" dependencies = [ "clap_builder", "clap_derive", @@ -665,7 +671,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -753,26 +759,6 @@ version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373e9fafaa20882876db20562275ff58d50e0caa2590077fe7ce7bef90211d0d" -[[package]] -name = "const_format" -version = "0.2.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" -dependencies = [ - "const_format_proc_macros", -] - -[[package]] -name = "const_format_proc_macros" -version = "0.2.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - [[package]] name = "convert_case" version = "0.4.0" @@ -796,9 +782,9 @@ dependencies = [ [[package]] name = "critical-section" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" +checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" [[package]] name = "crossbeam-channel" @@ -935,7 +921,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -966,7 +952,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -989,9 +975,9 @@ dependencies = [ [[package]] name = "diatomic-waker" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92a510eb4dc7fa435297888c00e0f999aa2ee3e920a357221c35ab615a80bbcf" +checksum = "ce3b3a843da2390ad9693fc640ed7081015fd73f280cab2b2081404a8ecceb99" dependencies = [ "loom", "waker-fn", @@ -1058,7 +1044,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -1098,6 +1084,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + [[package]] name = "endian-type" version = "0.1.2" @@ -1121,7 +1113,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -1240,12 +1232,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.31" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" +checksum = "9c0596c1eac1f9e04ed902702e9878208b336edc9d6fddc8a48387349bab3666" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -1389,7 +1381,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -1439,11 +1431,11 @@ dependencies = [ [[package]] name = "generator" -version = "0.7.5" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +checksum = "979f00864edc7516466d6b3157706e06c032f22715700ddd878228a91d02bc56" dependencies = [ - "cc", + "cfg-if 1.0.0", "libc", "log", "rustversion", @@ -1795,7 +1787,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -1840,7 +1832,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" dependencies = [ "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -1908,13 +1900,13 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jiff" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2e918a22c40c7671d8e7d3495983f54a3b13e63cb09e1f51f2729fa35cf108f" +checksum = "db2b7379a75544c94b3da32821b0bf41f9062e9970e23b78cc577d0d89676d16" dependencies = [ "jiff-tzdb-platform", "serde", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1958,9 +1950,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libredox" @@ -2055,9 +2047,9 @@ dependencies = [ [[package]] name = "loom" -version = "0.5.6" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" dependencies = [ "cfg-if 1.0.0", "generator", @@ -2173,6 +2165,15 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" version = "1.0.2" @@ -2495,7 +2496,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -2560,13 +2561,13 @@ checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" [[package]] name = "postcard" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" dependencies = [ "cobs", - "const_format", - "embedded-io", + "embedded-io 0.4.0", + "embedded-io 0.6.1", "heapless 0.7.17", "postcard-derive", "serde", @@ -2574,9 +2575,9 @@ dependencies = [ [[package]] name = "postcard-derive" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4b01218787dd4420daf63875163a787a78294ad48a24e9f6fa8c6507759a79" +checksum = "0239fa9c1d225d4b7eb69925c25c5e082307a141e470573fbbe3a817ce6a7a37" dependencies = [ "proc-macro2", "quote", @@ -2654,9 +2655,9 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.11.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8746739f11d39ce5ad5c2520a9b75285310dbfe78c541ccf832d38615765aec0" +checksum = "cb4e75767fbc9d92b90e4d0c011f61358cde9513b31ef07ea3631b15ffc3b4fd" dependencies = [ "bitflags 2.6.0", "memchr", @@ -2686,9 +2687,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -2799,9 +2800,9 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", @@ -2854,9 +2855,9 @@ checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "reqwest" -version = "0.12.5" +version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" dependencies = [ "base64 0.22.1", "bytes", @@ -2884,7 +2885,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg", + "windows-registry", ] [[package]] @@ -3046,14 +3047,14 @@ checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] name = "serde_json" -version = "1.0.124" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d" +checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" dependencies = [ "itoa", "memchr", @@ -3286,7 +3287,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -3302,9 +3303,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.74" +version = "2.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" dependencies = [ "proc-macro2", "quote", @@ -3322,6 +3323,9 @@ name = "sync_wrapper" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] [[package]] name = "synstructure" @@ -3373,7 +3377,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -3433,9 +3437,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.2" +version = "1.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" dependencies = [ "backtrace", "bytes", @@ -3457,7 +3461,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -3545,7 +3549,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -3696,9 +3700,9 @@ checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" [[package]] name = "unsafe-libyaml" @@ -3784,7 +3788,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", "wasm-bindgen-shared", ] @@ -3818,7 +3822,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3863,11 +3867,12 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.48.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" dependencies = [ - "windows-targets 0.48.5", + "windows-core 0.58.0", + "windows-targets 0.52.6", ] [[package]] @@ -3879,6 +3884,71 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -4027,16 +4097,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if 1.0.0", - "windows-sys 0.48.0", -] - [[package]] name = "wyz" version = "0.5.1" @@ -4064,5 +4124,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index 28382584..9f2f7d0e 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -4,10 +4,10 @@ use std::path::{Path, PathBuf}; use std::time::Instant; use byteseries::{downsample, series, ByteSeries}; -use color_eyre::eyre::{eyre, WrapErr}; +use color_eyre::eyre::WrapErr; use color_eyre::{Result, Section}; -use protocol::reading::tree::{Item, Tree}; use protocol::reading; +use protocol::reading::tree::{Item, Tree}; use serde::{Deserialize, Serialize}; use tracing::{info, instrument, trace}; @@ -32,7 +32,7 @@ struct Meta { #[derive(Debug)] pub(crate) struct Series { line: Vec, - meta: Vec, + meta_list: Vec, byteseries: ByteSeries, } @@ -48,63 +48,47 @@ impl Series { let readings = reading.device().info().affects_readings; let specs = to_speclist(readings); let fields = bitspec::speclist_to_fields(specs); - let meta = readings - .iter() - .zip(fields.iter()) - .map(|(reading, field)| Meta { - reading: reading.clone(), - field: field.clone(), - set_at: None, - }) - .collect(); - - let payload_size = fields - .iter() - .map(|spec| spec.length as usize) - .sum::() - .div_ceil(8); - let resampler = Resampler::from_fields(fields.clone(), payload_size); - let resample_configs = vec![ - downsample::Config { - max_gap: None, - bucket_size: 10, - }, - downsample::Config { - max_gap: None, - bucket_size: 100, - }, - downsample::Config { - max_gap: None, - bucket_size: 1000, - }, - ]; - - let path = base_path(reading); - let path = dir.join(path); - let res = ByteSeries::open_existing_with_resampler::( - &path, - payload_size, - resampler.clone(), - resample_configs.clone(), - ); + let (meta_list, payload_size) = meta_list_and_payload_size(readings, &fields); let expected_header = Header { readings: readings.to_vec(), encoding: fields.clone(), }; - let byteseries = try_create_new_if_open_failed( - res, - expected_header, - &path, - payload_size, - resampler, - resample_configs, - )?; + let (resampler, configs) = resample_setup(&fields, payload_size); + + let path = base_path(reading); + let path = dir.join(path); + let res = ByteSeries::builder() + .payload_size(payload_size) + .with_downsampled_cache(resampler.clone(), configs.clone()) + .with_header(expected_header.clone()) + .open(&path); + + let byteseries = match res { + Ok((byteseries, _)) => byteseries, + Err(Open(DataOpenError::File(FileOpenError::Io(e)))) + if e.kind() == io::ErrorKind::NotFound => + { + info!("creating new byteseries"); + create_dirs(&path)?; + + ByteSeries::builder() + .payload_size(payload_size) + .with_downsampled_cache(resampler, configs) + .with_header(expected_header) + .create_new(true) + .open(&path) + .wrap_err("Could not create new byteseries") + .with_note(|| format!("path: {}", path.display())) + .map(|(db, _)| db)? + } + Err(e) => return Err(e).wrap_err("Could not open existing byteseries")?, + }; Ok(Self { line: vec![0; payload_size], - meta, + meta_list, byteseries, }) } @@ -123,12 +107,12 @@ impl Series { reading.branch_id()", ); - let meta = &mut self.meta[index]; + let meta = &mut self.meta_list[index]; meta.field.encode(reading.leaf().val, &mut self.line); meta.set_at = Some(Instant::now()); if self - .meta + .meta_list .iter() .map(|Meta { set_at, .. }| set_at) .all(|set| set.map(|s| s.elapsed().as_millis() < 500).unwrap_or(false)) @@ -170,16 +154,18 @@ impl Series { let fields = readings .iter() .map(|requested| { - self.meta + self.meta_list .iter() .find(|meta| requested.is_same_as(&meta.reading)) .inspect(|meta| trace!("meta used for decoding: {meta:?}")) .map(|meta| meta.field.clone()) - .unwrap_or_else(|| panic!( - "caller of read makes sure all readings are part of this \ + .unwrap_or_else(|| { + panic!( + "caller of read makes sure all readings are part of this \ series.\n\tseries: {:?},\n\trequested: {:?}", - self.meta, readings - )) + self.meta_list, readings + ) + }) }) .collect(); let mut resampler = Resampler::from_fields(fields, self.line.len()); @@ -218,6 +204,28 @@ impl Series { } } +fn meta_list_and_payload_size( + readings: &[protocol::Reading], + fields: &[bitspec::Field], +) -> (Vec, usize) { + let meta = readings + .iter() + .zip(fields.iter()) + .map(|(reading, field)| Meta { + reading: reading.clone(), + field: field.clone(), + set_at: None, + }) + .collect(); + + let payload_size = fields + .iter() + .map(|spec| spec.length as usize) + .sum::() + .div_ceil(8); + (meta, payload_size) +} + /// Multiplying the time for this sample by this factor /// allows you to save the whole number and retain the required /// temporal_resolution and min_sample_interval. @@ -231,61 +239,6 @@ pub fn millis_to_minimal_representation(device_info: protocol::DeviceInfo) -> u6 div_factor.round() as u64 } -fn try_create_new_if_open_failed( - res: Result<(ByteSeries, Header), series::Error>, - expected_header: Header, - path: &Path, - payload_size: usize, - resampler: Resampler, - resample_configs: Vec, -) -> Result { - match res { - Ok((byteseries, opened_file_header)) => { - if opened_file_header == expected_header { - info!("Opened existing byteseries from: {}", path.display()); - Ok(byteseries) - } else { - Err(eyre!("header in file does not match readings")) - .with_note(|| { - format!( - "header in the just existing (opened) byteseries: {opened_file_header:?}", - ) - }) - .with_note(|| { - format!( - "header for the data we want to write: {expected_header:?}", - ) - }) - } - } - Err(Open(DataOpenError::File(FileOpenError::Io(e)))) - if e.kind() == io::ErrorKind::NotFound => - { - if let Some(dirs) = path.parent() { - create_dir_all(dirs) - .wrap_err("Could not create dirs structure for reading") - .with_note(|| format!("dirs: {}", dirs.display()))?; - std::fs::read_dir(dirs) - .unwrap() - .map(Result::unwrap) - .for_each(|p| println!("{p:?}")); - } - // compile_error!("create directory structure"); - info!("creating new byteseries"); - ByteSeries::new_with_resamplers( - &path, - payload_size, - expected_header, - resampler, - resample_configs, - ) - .wrap_err("Could not create new byteseries") - .with_note(|| format!("path: {}", path.display())) - } - Err(e) => Err(e).wrap_err("Could not open existing byteseries")?, - } -} - #[instrument(level = "debug", skip(data))] pub(crate) async fn store(data: &Data, reading: &protocol::Reading, data_dir: &Path) -> Result<()> { let mut data = data.0.lock().await; @@ -340,6 +293,42 @@ fn base_path(reading: &protocol::Reading) -> PathBuf { parts.into_iter().collect() } +fn resample_setup( + fields: &[bitspec::Field], + payload_size: usize, +) -> (Resampler, Vec) { + let resampler = Resampler::from_fields(fields.to_vec(), payload_size); + let resample_configs = vec![ + downsample::Config { + max_gap: None, + bucket_size: 10, + }, + downsample::Config { + max_gap: None, + bucket_size: 100, + }, + downsample::Config { + max_gap: None, + bucket_size: 1000, + }, + ]; + (resampler, resample_configs) +} + +fn create_dirs(path: &Path) -> Result<()> { + if let Some(dirs) = path.parent() { + create_dir_all(dirs) + .wrap_err("Could not create dirs structure for reading") + .with_note(|| format!("dirs: {}", dirs.display()))?; + std::fs::read_dir(dirs) + .unwrap() + .map(Result::unwrap) + .for_each(|p| println!("{p:?}")); + } + + Ok(()) +} + #[cfg(test)] mod test { use super::*; diff --git a/crates/log-store/src/server/db/log.rs b/crates/log-store/src/server/db/log.rs index 82b7bd76..8dd86071 100644 --- a/crates/log-store/src/server/db/log.rs +++ b/crates/log-store/src/server/db/log.rs @@ -3,11 +3,14 @@ use std::io::{self, Read, Write}; use std::path::{Path, PathBuf}; use std::sync::Arc; +use byteseries::file::OpenError as FileOpenError; use byteseries::{series, ByteSeries}; use color_eyre::eyre::Context; -use color_eyre::{eyre, Result, Section}; +use color_eyre::{Result, Section}; use protocol::Device; use serde::{Deserialize, Serialize}; +use series::data::OpenError as DataOpenError; +use series::Error::Open; use tokio::sync::Mutex; use tracing::{info, warn}; @@ -88,21 +91,44 @@ impl CurrentError { } } -type Header = String; - impl Log { pub fn open_or_create(dir: &Path, device: &Device) -> Result { let path = base_path(device); let path = dir.join(path); let payload_size = protocol::Error::max_size(); - let res = ByteSeries::open_existing::(&path, payload_size); - - let expected_header = format!( + let header = format!( "Bincode encoded error logs for {device:?}. \ Each line has a size: {payload_size} + 2" ); - let history = try_create_new_if_open_failed(res, expected_header, &path, payload_size)?; + + let res = ByteSeries::builder() + .payload_size(payload_size) + .create_new(true) + .with_header(header.clone()) + .open(&path); + + let history = match res { + Ok((byteseries, _)) => byteseries, + Err(Open(DataOpenError::File(FileOpenError::Io(e)))) + if e.kind() == io::ErrorKind::NotFound => + { + if let Some(dirs) = path.parent() { + std::fs::create_dir_all(dirs) + .wrap_err("Could not create dirs structure for reading") + .with_note(|| format!("dirs: {}", dirs.display()))?; + } + info!("creating new byteseries"); + ByteSeries::builder() + .payload_size(payload_size) + .with_header(header) + .open(&path) + .wrap_err("Could not create new byteseries") + .with_note(|| format!("path: {}", path.display()))? + .0 + } + Err(e) => return Err(e).wrap_err("Could not open existing byteseries"), + }; Ok(Self { history, @@ -189,52 +215,6 @@ impl byteseries::Decoder for Decoder { type ApiResult = std::result::Result; -fn try_create_new_if_open_failed( - res: Result<(ByteSeries, Header), series::Error>, - expected_header: Header, - path: &Path, - payload_size: usize, -) -> Result { - use byteseries::file::OpenError as FileOpenError; - use series::data::OpenError as DataOpenError; - use series::Error::Open; - - match res { - Ok((byteseries, opened_file_header)) => { - if opened_file_header == expected_header { - info!("Opened existing byteseries from: {}", path.display()); - Ok(byteseries) - } else { - Err(eyre::eyre!("header in file does not match readings")) - .with_note(|| { - format!( - "header in the just existing (opened) byteseries: {opened_file_header:?}", - ) - }) - .with_note(|| { - format!( - "header for the data we want to write: {expected_header:?}", - ) - }) - } - } - Err(Open(DataOpenError::File(FileOpenError::Io(e)))) - if e.kind() == io::ErrorKind::NotFound => - { - if let Some(dirs) = path.parent() { - std::fs::create_dir_all(dirs) - .wrap_err("Could not create dirs structure for reading") - .with_note(|| format!("dirs: {}", dirs.display()))?; - } - info!("creating new byteseries"); - ByteSeries::new(&path, payload_size, expected_header) - .wrap_err("Could not create new byteseries") - .with_note(|| format!("path: {}", path.display())) - } - Err(e) => Err(e).wrap_err("Could not open existing byteseries")?, - } -} - #[derive(Debug, Clone)] pub(crate) struct Logs(pub(crate) Arc>>); From 368d43ce0e348cf38b011cf6e0bd9df309f7d372 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 23 Aug 2024 14:34:54 +0200 Subject: [PATCH 210/687] fix compile on embedded --- crates/protocol/src/large_bedroom.rs | 3 +-- crates/protocol/src/large_bedroom/bed.rs | 5 +++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index 3c4ec4a4..03a499ba 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -1,10 +1,9 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; -use crate::affector; use crate::msg::DecodeMsgError; #[cfg(feature = "alloc")] -use crate::reading; +use crate::{reading, affector}; pub mod bed; pub mod desk; diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index e27f7cb2..90747f09 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -1,13 +1,13 @@ use core::time::Duration; use crate::button::Press; +use crate::button_enum; #[cfg(feature = "alloc")] use crate::reading::tree::{Id, Item, Tree}; #[cfg(feature = "alloc")] use crate::reading::Info; #[cfg(feature = "alloc")] -use crate::Unit; -use crate::{affector, button_enum}; +use crate::{affector, Unit}; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -527,6 +527,7 @@ impl Affector { } } +#[cfg(feature = "alloc")] impl affector::tree::Tree for Affector { fn inner(&self) -> affector::tree::Item<'_> { let description = match self { From 99d23ee2735999f23fb1dfb741db289d029c4381 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 23 Aug 2024 15:27:17 +0200 Subject: [PATCH 211/687] sensor-node Fix network not reconnecting on timeout - Sets a timeout 5x larger then the keepalive. - If read reads zero bytes the socket is closed return an error. - Abort the socket as soon as an error happens so reconnect is instant --- sensor-nodes/bed-sensors/Cargo.lock | 127 ++++++++++-------------- sensor-nodes/bed-sensors/src/network.rs | 33 ++++-- 2 files changed, 72 insertions(+), 88 deletions(-) diff --git a/sensor-nodes/bed-sensors/Cargo.lock b/sensor-nodes/bed-sensors/Cargo.lock index 068e730f..5f42670d 100644 --- a/sensor-nodes/bed-sensors/Cargo.lock +++ b/sensor-nodes/bed-sensors/Cargo.lock @@ -94,9 +94,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bosch-bme680" @@ -126,26 +126,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" -[[package]] -name = "const_format" -version = "0.2.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" -dependencies = [ - "const_format_proc_macros", -] - -[[package]] -name = "const_format_proc_macros" -version = "0.2.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - [[package]] name = "cortex-m" version = "0.7.7" @@ -196,15 +176,15 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "critical-section" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" +checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" [[package]] name = "darling" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ "darling_core", "darling_macro", @@ -212,27 +192,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.66", + "syn 2.0.75", ] [[package]] name = "darling_macro" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.66", + "syn 2.0.75", ] [[package]] @@ -255,7 +235,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.75", ] [[package]] @@ -279,9 +259,9 @@ dependencies = [ [[package]] name = "document-features" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" dependencies = [ "litrs", ] @@ -322,7 +302,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.75", ] [[package]] @@ -388,7 +368,7 @@ name = "embassy-stm32" version = "0.1.0" dependencies = [ "bit_field", - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "cortex-m", "cortex-m-rt", @@ -648,7 +628,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.75", ] [[package]] @@ -840,18 +820,17 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "portable-atomic" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" [[package]] name = "postcard" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" dependencies = [ "cobs", - "const_format", "heapless 0.7.17", "postcard-derive", "serde", @@ -859,9 +838,9 @@ dependencies = [ [[package]] name = "postcard-derive" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4b01218787dd4420daf63875163a787a78294ad48a24e9f6fa8c6507759a79" +checksum = "0239fa9c1d225d4b7eb69925c25c5e082307a141e470573fbbe3a817ce6a7a37" dependencies = [ "proc-macro2", "quote", @@ -894,9 +873,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -914,9 +893,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -995,22 +974,22 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.203" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.75", ] [[package]] @@ -1082,9 +1061,9 @@ dependencies = [ [[package]] name = "stm32-fmc" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830ed60f33e6194ecb377f5d6ab765dc0e37e7b65e765f1fa87df13336658d63" +checksum = "c7f0639399e2307c2446c54d91d4f1596343a1e1d5cab605b9cce11d0ab3858c" dependencies = [ "embedded-hal 0.2.7", ] @@ -1092,7 +1071,7 @@ dependencies = [ [[package]] name = "stm32-metapac" version = "15.0.0" -source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-e0cfd165fd8fffaa0df66a35eeca83b228496645#bf02c35d063e1823a156468497b448ae3350a255" +source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-5ef354f3e49f790e47f5c818f243459742c9b83b#d94c7ea2bd05428ba9fd2b5a39edb8ed99f65daa" dependencies = [ "cortex-m", "cortex-m-rt", @@ -1117,24 +1096,24 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.26.3" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7993a8e3a9e88a00351486baae9522c91b123a088f76469e5bd5cc17198ea87" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ "heck", "proc-macro2", "quote", "rustversion", - "syn 2.0.66", + "syn 2.0.75", ] [[package]] @@ -1150,9 +1129,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" dependencies = [ "proc-macro2", "quote", @@ -1161,22 +1140,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.75", ] [[package]] @@ -1185,12 +1164,6 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - [[package]] name = "vcell" version = "0.1.3" @@ -1199,9 +1172,9 @@ checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "void" diff --git a/sensor-nodes/bed-sensors/src/network.rs b/sensor-nodes/bed-sensors/src/network.rs index 41ccf050..c8bd7bbe 100644 --- a/sensor-nodes/bed-sensors/src/network.rs +++ b/sensor-nodes/bed-sensors/src/network.rs @@ -70,15 +70,16 @@ pub async fn handle(stack: &Stack, publish: &Queues) { let mut tx_buffer = [0; max(Msg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE) * 2]; let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); - socket.set_timeout(None); - socket.set_keep_alive(Some(Duration::from_secs(5))); + socket.set_timeout(Some(Duration::from_secs(5))); + socket.set_keep_alive(Some(Duration::from_secs(1))); let host_addr = Ipv4Address::new(192, 168, 1, 43); let host_port = 1234; debug!("Configured socket and connecting"); loop { + debug!("socket state: {:?}", socket.state()); if let Err(e) = socket.connect((host_addr, host_port)).await { - warn!("connect error: {:?}", e); + warn!("connect error: {}", e); Timer::after_secs(1).await; continue; } @@ -87,11 +88,13 @@ pub async fn handle(stack: &Stack, publish: &Queues) { publish.clear().await; let (reader, writer) = socket.split(); - match select(send_messages(writer, publish), receive_orders(reader)).await { - select::Either::First(e) => warn!("Error while sending messages: {:?}", e), - select::Either::Second(e) => warn!("Error receiving orders: {:?}", e), - } + select::Either::First(e) => warn!("Error while sending messages: {}", e), + select::Either::Second(e) => warn!("Error receiving orders: {}", e), + }; + // or the socket will hang for a while waiting to close this makes sure + // we can reconnect instantly + socket.abort(); } } @@ -105,15 +108,23 @@ async fn send_messages(mut tcp: TcpWriter<'_>, publish: &Queues) -> embassy_net: } } -async fn receive_orders(mut tcp: TcpReader<'_>) -> embassy_net::tcp::Error { +#[derive(defmt::Format)] +enum ReadError { + ConnectionClosed, + TcpError(embassy_net::tcp::Error), +} + +async fn receive_orders(mut tcp: TcpReader<'_>) -> ReadError { let mut buf = [0u8; 100]; loop { - let n_read = match tcp.read(&mut buf).await { + let res = tcp.read(&mut buf).await; + let n_read = match res { + Ok(0) => return ReadError::ConnectionClosed, Ok(n_read) => n_read, - Err(e) => return e, + Err(e) => return ReadError::TcpError(e), }; let mut read = &buf[..n_read]; - let mut decoder = protocol::affector::Decoder::new(); + let mut decoder = protocol::affector::Decoder::default(); while let Some((item, remaining)) = decoder.feed(read) { read = remaining; defmt::info!("received item: {:?}", item) From 8dc5df7913139d00c8ee69a0d93cf66806f41f4f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 23 Aug 2024 15:29:25 +0200 Subject: [PATCH 212/687] data-store remove debug code that causes crashes --- Cargo.lock | 2 +- crates/data-store/src/server/db/series.rs | 42 +++++++++++++---------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8e5abad7..b5ddaef5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -571,7 +571,7 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "byteseries" version = "0.6.0" -source = "git+https://github.com/dvdsk/byteseries#b2d22feebdee41810f06968596ce8b10d42112f8" +source = "git+https://github.com/dvdsk/byteseries#328e5eab83f56870311fe6e4df2aa76b3e0dd75f" dependencies = [ "arraydeque", "itertools", diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index 9f2f7d0e..76e2ce9d 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -9,7 +9,7 @@ use color_eyre::{Result, Section}; use protocol::reading; use protocol::reading::tree::{Item, Tree}; use serde::{Deserialize, Serialize}; -use tracing::{info, instrument, trace}; +use tracing::{instrument, trace}; use byteseries::file::OpenError as FileOpenError; use series::data::OpenError as DataOpenError; @@ -33,6 +33,7 @@ struct Meta { pub(crate) struct Series { line: Vec, meta_list: Vec, + last_timestamp_pushed: Option, byteseries: ByteSeries, } @@ -70,8 +71,11 @@ impl Series { Err(Open(DataOpenError::File(FileOpenError::Io(e)))) if e.kind() == io::ErrorKind::NotFound => { - info!("creating new byteseries"); - create_dirs(&path)?; + if let Some(dirs) = path.parent() { + create_dir_all(dirs) + .wrap_err("Could not create dirs structure for reading") + .with_note(|| format!("dirs: {}", dirs.display()))?; + } ByteSeries::builder() .payload_size(payload_size) @@ -89,6 +93,7 @@ impl Series { Ok(Self { line: vec![0; payload_size], meta_list, + last_timestamp_pushed: None, byteseries, }) } @@ -111,21 +116,34 @@ impl Series { meta.field.encode(reading.leaf().val, &mut self.line); meta.set_at = Some(Instant::now()); + let max_interval = reading.device().info().max_sample_interval; + if self .meta_list .iter() .map(|Meta { set_at, .. }| set_at) - .all(|set| set.map(|s| s.elapsed().as_millis() < 500).unwrap_or(false)) + .all(|set| { + set.is_some_and(|set| set.elapsed() < max_interval) + }) { let time = jiff::Timestamp::now(); let device_info = reading.leaf().device.info(); let scale_factor = millis_to_minimal_representation(device_info); let scaled_time = time.as_millisecond() as u64 / scale_factor; + let new_ts = scaled_time; + + if self.last_timestamp_pushed.is_some_and(|ts| ts == new_ts) { + tracing::warn!("Skipping datapoint with same timestamp"); + } self.byteseries - .push_line(scaled_time, &self.line) + .push_line(new_ts, &self.line) .wrap_err("Could not write to timeseries on disk")?; self.line.fill(0); + + for meta in &mut self.meta_list { + meta.set_at = None; + } } Ok(()) @@ -315,20 +333,6 @@ fn resample_setup( (resampler, resample_configs) } -fn create_dirs(path: &Path) -> Result<()> { - if let Some(dirs) = path.parent() { - create_dir_all(dirs) - .wrap_err("Could not create dirs structure for reading") - .with_note(|| format!("dirs: {}", dirs.display()))?; - std::fs::read_dir(dirs) - .unwrap() - .map(Result::unwrap) - .for_each(|p| println!("{p:?}")); - } - - Ok(()) -} - #[cfg(test)] mod test { use super::*; From 09820797981b252e53b325a03e6f6ac12a8c395c Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 24 Aug 2024 10:54:57 +0200 Subject: [PATCH 213/687] tui fix hist and logs requested while fetch already running --- crates/sensor-tui/src/fetch.rs | 16 ++++++++-------- crates/sensor-tui/src/tui/affectors.rs | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index 4a546f86..a80ad4b9 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -48,7 +48,7 @@ impl Request { _ => None, } } - fn unwrap_data(&self) -> Option<&Data> { + fn data(&self) -> Option<&Data> { match self { Request::Data(d) => Some(d), _ => None, @@ -127,17 +127,17 @@ impl Fetch { return false; } - let with_margin = oldest_needed.as_millisecond() as f64 * 1.2; - let not_too_old = |start: &i64| *start < with_margin as i64; + let margin = oldest_needed.as_millisecond() as f64 * 1.2; + let not_too_old = |start: &i64| *start < margin as i64; !self .recently_issued .iter() - .filter_map(Request::unwrap_data) - .filter(|req| &req.reading == reading) + .filter_map(Request::data) + .filter(|req| req.reading.is_same_as(reading)) .map(|req| req.range.start().as_millisecond()) .filter(not_too_old) - .any(|start| start < oldest_needed.as_millisecond()) + .any(|start| start <= oldest_needed.as_millisecond()) } fn logs_outdated_not_updating( @@ -156,7 +156,7 @@ impl Fetch { .filter_map(Request::unwrap_logs) .filter(|req| &req.reading == reading) .map(|req| req.range.start().as_millisecond()) - .any(|start| start < oldest_needed.as_millisecond()) + .any(|start| start <= oldest_needed.as_millisecond()) } fn hist_outdated_not_updating( @@ -181,7 +181,7 @@ impl Fetch { .map(|req| req.range.clone()) .filter(|range| covers_recently(*range.end())) .map(|range| range.start().as_millisecond()) - .any(|start| start < oldest_needed.as_millisecond()) + .any(|start| start <= oldest_needed.as_millisecond()) } fn request(&mut self, req: Request) { diff --git a/crates/sensor-tui/src/tui/affectors.rs b/crates/sensor-tui/src/tui/affectors.rs index 54d58b1f..67d244d0 100644 --- a/crates/sensor-tui/src/tui/affectors.rs +++ b/crates/sensor-tui/src/tui/affectors.rs @@ -23,7 +23,7 @@ struct AffectorState; pub struct Tab { tree_state: TreeState, pub ground: Vec>, - pub data: HashMap, + data: HashMap, } impl Tab { From bd7505b28c2a426c0ff02d3acf49bec13b5e399a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 24 Aug 2024 10:59:12 +0200 Subject: [PATCH 214/687] fix affector names in tree --- crates/protocol/src/affector/tree.rs | 4 ++-- crates/sensor-tui/src/tui/affectors.rs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/protocol/src/affector/tree.rs b/crates/protocol/src/affector/tree.rs index 9067fc34..18bf9f4e 100644 --- a/crates/protocol/src/affector/tree.rs +++ b/crates/protocol/src/affector/tree.rs @@ -23,9 +23,9 @@ pub trait Tree: core::fmt::Debug { } fn name(&self) -> String { let dbg_repr = format!("{self:?}"); + let split = dbg_repr.find('(').unwrap_or(dbg_repr.len()); dbg_repr - .split_once('(') - .map_or("_", |(name, _)| name) + .split_at(split).0 .to_string() } fn branch_id(&self) -> Id; diff --git a/crates/sensor-tui/src/tui/affectors.rs b/crates/sensor-tui/src/tui/affectors.rs index 67d244d0..a840e6f4 100644 --- a/crates/sensor-tui/src/tui/affectors.rs +++ b/crates/sensor-tui/src/tui/affectors.rs @@ -91,20 +91,20 @@ impl Tab { let key = tree_key(affector); let mut tree = add_root(affector as &dyn AffectorTree, &mut self.ground); - let mut tomato = match affector.inner() { + let mut tree_node = match affector.inner() { Item::Leaf(_) => unreachable!("no values at level 0"), Item::Node(inner) => inner, }; loop { - match tomato.inner() { + match tree_node.inner() { Item::Leaf(_) => { - let text = tomato.name(); + let text = tree_node.name(); add_leaf(text, tree, key); return; } Item::Node(inner) => { - tree = add_node(tomato, tree); - tomato = inner; + tree = add_node(tree_node, tree); + tree_node = inner; } }; } From 1acb24cfba83d0e0d79b05f4cb381d87eabbf549 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 26 Aug 2024 14:54:49 +0200 Subject: [PATCH 215/687] adds controls (callback) to allow changing an affector without knowing the exact type --- crates/protocol/src/affector.rs | 35 +++++++++++++- crates/protocol/src/large_bedroom.rs | 31 +++--------- crates/protocol/src/large_bedroom/bed.rs | 61 +++++++++++++++++++++++- 3 files changed, 100 insertions(+), 27 deletions(-) diff --git a/crates/protocol/src/affector.rs b/crates/protocol/src/affector.rs index 926d6634..2701dd40 100644 --- a/crates/protocol/src/affector.rs +++ b/crates/protocol/src/affector.rs @@ -1,3 +1,6 @@ +#[cfg(feature = "alloc")] +use core::ops::Range; + use postcard::accumulator::{CobsAccumulator, FeedResult}; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -27,12 +30,34 @@ pub enum Affector { } #[cfg(feature = "alloc")] -tree::all_nodes!{Affector; AffectorDiscriminants; LargeBedroom} +tree::all_nodes! {Affector; AffectorDiscriminants; LargeBedroom} #[cfg(feature = "alloc")] #[derive(Debug, Clone)] pub struct Info { pub description: &'static str, + /// affectors not related to a reading + /// and therefore not related to a read device + pub free_affectors: &'static [Affector], +} + +#[cfg(feature = "alloc")] +pub enum ControlValue<'a> { + Trigger, + /// if you need floats just map this to a float + /// in the affector device like: `range = range/x + y` + SetNum { + valid_range: Range, + /// FnOnce such that value does become outdated + setter: Option>, + value: usize, + }, +} + +#[cfg(feature = "alloc")] +pub struct Control<'a> { + pub name: &'static str, + pub value: ControlValue<'a>, } impl Affector { @@ -44,6 +69,14 @@ impl Affector { pub fn encode(&self) -> Vec { postcard::to_allocvec_cobs(self).expect("Encoding should not fail") } + + // info() is explicitly not defined, use the tree impl to get at it + #[cfg(feature = "alloc")] + pub fn controls(&mut self) -> Vec { + match self { + Affector::LargeBedroom(a) => a.controls(), + } + } } pub struct Decoder { diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index 03a499ba..515d9f99 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -1,7 +1,6 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; -use crate::msg::DecodeMsgError; #[cfg(feature = "alloc")] use crate::{reading, affector}; @@ -96,30 +95,14 @@ impl Device { pub enum Affector { Bed(bed::Affector), } - -#[cfg(feature = "alloc")] -affector::tree::all_nodes! {Affector; AffectorDiscriminants; Bed} - impl Affector { #[cfg(feature = "alloc")] - #[must_use] - pub fn encode(&self) -> Vec { - postcard::to_allocvec_cobs(self).expect("Encoding should not fail") - } - - /// Buffer should be at least `Self::ENCODED_SIZE` long. The returned slice contains - /// the serialized data. It can be shorter then the input buffer. - #[must_use] - pub fn encode_slice<'a>(&self, buf: &'a mut [u8]) -> &'a mut [u8] { - postcard::to_slice_cobs(self, buf).expect("Encoding should not fail") - } - - pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { - postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeMsgError::CorruptEncoding) - } - - #[must_use] - pub fn version(&self) -> u8 { - 0 + pub(crate) fn controls(&mut self) -> Vec { + match self { + Affector::Bed(a) => a.controls(), + } } } + +#[cfg(feature = "alloc")] +affector::tree::all_nodes! {Affector; AffectorDiscriminants; Bed} diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 90747f09..f6aa1a14 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -1,5 +1,7 @@ use core::time::Duration; +#[cfg(feature = "alloc")] +use crate::affector::{Control, ControlValue}; use crate::button::Press; use crate::button_enum; #[cfg(feature = "alloc")] @@ -508,10 +510,11 @@ impl Device { )] #[strum_discriminants(derive(Hash))] pub enum Affector { - Sps30FanClean = 0, + Sps30FanClean, MhzZeroPointCalib, Nau7802LeftCalib, Nau7802RightCalib, + RgbLed { red: u8, green: u8, blue: u8 }, } impl Affector { @@ -522,9 +525,58 @@ impl Affector { (Affector::MhzZeroPointCalib, Affector::MhzZeroPointCalib) => true, (Affector::Nau7802LeftCalib, Affector::Nau7802LeftCalib) => true, (Affector::Nau7802RightCalib, Affector::Nau7802RightCalib) => true, + (Affector::RgbLed { .. }, Affector::RgbLed { .. }) => true, _ => false, } } + + #[cfg(feature = "alloc")] + pub fn controls(&mut self) -> Vec { + match self { + Affector::Sps30FanClean => vec![Control { + name: "start fan cleaning", + value: ControlValue::Trigger, + }], + Affector::MhzZeroPointCalib => vec![Control { + name: "calibrate current reading as 400 ppm", + value: ControlValue::Trigger, + }], + Affector::Nau7802LeftCalib => vec![Control { + name: "things with ac power noise or something", + value: ControlValue::Trigger, + }], + Affector::Nau7802RightCalib => vec![Control { + name: "things with ac power noise or something", + value: ControlValue::Trigger, + }], + Affector::RgbLed { red, green, blue } => vec![ + Control { + name: "red", + value: ControlValue::SetNum { + valid_range: 0..255, + value: *red as usize, + setter: Some(Box::new(|input: usize| *red = input as u8)), + }, + }, + Control { + name: "green", + value: ControlValue::SetNum { + valid_range: 0..255, + value: *green as usize, + setter: Some(Box::new(|input: usize| *green = input as u8)), + }, + }, + Control { + name: "blue", + value: ControlValue::SetNum { + valid_range: 0..255, + value: *blue as usize, + setter: Some(Box::new(|input: usize| *blue = input as u8)), + }, + }, + ], + } + } } #[cfg(feature = "alloc")] @@ -535,8 +587,13 @@ impl affector::tree::Tree for Affector { Affector::MhzZeroPointCalib => "Set the current co2 value as 400ppm", Affector::Nau7802LeftCalib | Affector::Nau7802RightCalib => "Detect and correct power supply and temperature variations to ADC", + Affector::RgbLed {..} => "Set color & power of the RGB led at the top of the bed post" }; - affector::tree::Item::Leaf(affector::Info { description }) + + affector::tree::Item::Leaf(affector::Info { + description, + free_affectors: &tree![Affector; Affector::RgbLed { red: 0, green: 0, blue: 0 }], + }) } fn branch_id(&self) -> affector::tree::Id { From b142e71eb46e768de4fe619ba820d2faeb93ac77 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 26 Aug 2024 14:55:29 +0200 Subject: [PATCH 216/687] control affectors from tui --- crates/sensor-tui/src/main.rs | 1 + crates/sensor-tui/src/tui/affectors.rs | 99 ++++++++---- .../src/tui/affectors/handle_key.rs | 55 +++++++ crates/sensor-tui/src/tui/affectors/render.rs | 146 ++++++++++++++++++ 4 files changed, 273 insertions(+), 28 deletions(-) create mode 100644 crates/sensor-tui/src/tui/affectors/handle_key.rs create mode 100644 crates/sensor-tui/src/tui/affectors/render.rs diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index 6f4a32b8..5d7123be 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -46,6 +46,7 @@ enum Update { SensorError(Box), SubscribeError(color_eyre::Report), DeviceList(Vec), + AffectorControlled(protocol::Affector), } async fn receive_data(data_server: SocketAddr, tx: mpsc::Sender) { diff --git a/crates/sensor-tui/src/tui/affectors.rs b/crates/sensor-tui/src/tui/affectors.rs index a840e6f4..2bf7dc1d 100644 --- a/crates/sensor-tui/src/tui/affectors.rs +++ b/crates/sensor-tui/src/tui/affectors.rs @@ -1,12 +1,9 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use crossterm::event::{KeyCode, KeyEvent}; -use protocol::{affector, Device}; -use ratatui::layout::Rect; -use ratatui::style::{Modifier, Style}; -use ratatui::widgets::{Block, Borders}; +use protocol::{affector, Affector, Device}; +use ratatui::layout::{Constraint, Layout, Rect}; use ratatui::Frame; -use tui_tree_widget::Tree; use tui_tree_widget::{TreeItem, TreeState}; use crate::Update; @@ -15,35 +12,56 @@ use super::Theme; use protocol::affector::tree::Item; use protocol::affector::tree::Tree as AffectorTree; +mod handle_key; +mod render; + pub type TreeKey = [u8; 6]; -struct AffectorState; +struct AffectorState { + affector: Affector, + selected_control: usize, + info: affector::Info, +} #[derive(Default)] pub struct Tab { tree_state: TreeState, pub ground: Vec>, data: HashMap, + registered_affectors: Vec, } impl Tab { pub fn render(&mut self, frame: &mut Frame, layout: Rect, theme: &Theme) { - frame.render_stateful_widget( - Tree::new(&self.ground) - .expect("all item identifiers should be unique") - .block( - Block::default() - .title("Controllable affectors") - .borders(Borders::ALL), - ) - .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) - .highlight_symbol(">>"), - layout, - &mut self.tree_state, - ); + let [main, footer] = + Layout::vertical([Constraint::Fill(1), Constraint::Max(1)]).areas(layout); + let [left, right] = + Layout::horizontal([Constraint::Fill(1), Constraint::Fill(1)]).areas(main); + + render::tree(frame, left, &self.ground, &mut self.tree_state); + + let mut data = self + .tree_state + .selected() + .last() // unique leaf id + .and_then(|key| self.data.get_mut(key)); + + if let Some(ref mut data) = data { + let [top, bottom] = + Layout::vertical([Constraint::Fill(1), Constraint::Fill(1)]).areas(right); + render::details(frame, &data.info, top); + render::controls(frame, data, bottom); + }; + render::footer(frame, footer, data, theme) } pub fn handle_key(&mut self, key: KeyEvent) -> Option { + let data = self + .tree_state + .selected() + .last() // unique leaf id + .and_then(|key| self.data.get_mut(key)); + match key.code { KeyCode::Down => { self.tree_state.key_down(); @@ -54,7 +72,11 @@ impl Tab { KeyCode::Enter => { self.tree_state.toggle_selected(); } - _ => return Some(key), + _ => { + if let Some(state) = data { + return handle_key::handle(key, state); + } + } } None } @@ -64,20 +86,33 @@ impl Tab { Update::ReadingList(_) | Update::Fetched { .. } | Update::FetchError(_) - | Update::SubscribeError(_) => &Vec::new(), + | Update::SubscribeError(_) => return, + Update::AffectorControlled(a) => { + self.update_tree(a); + return; + } Update::SensorReading(r) => &vec![r.device()], Update::SensorError(err) => &vec![err.device()], Update::DeviceList(devices) => devices, }; - let affectors: HashSet<_> = devices + let mut possibly_new = devices .iter() .map(Device::info) - .flat_map(|info| info.affectors) - .collect(); + .flat_map(|info| info.affectors); - for affector in affectors { - self.update_tree(affector); + let first = possibly_new.next(); + let free = if let Some(first) = first { + first.leaf().free_affectors + } else { + &[] + }; + + for new in possibly_new.chain(first.into_iter()).chain(free.iter()) { + if !self.registered_affectors.iter().any(|a| a.is_same_as(new)) { + self.registered_affectors.push(*new); + self.update_tree(new); + } } if self.tree_state.selected().is_empty() { @@ -97,9 +132,17 @@ impl Tab { }; loop { match tree_node.inner() { - Item::Leaf(_) => { + Item::Leaf(info) => { let text = tree_node.name(); add_leaf(text, tree, key); + self.data.insert( + key, + AffectorState { + affector: affector.clone(), + info, + selected_control: 0, + }, + ); return; } Item::Node(inner) => { diff --git a/crates/sensor-tui/src/tui/affectors/handle_key.rs b/crates/sensor-tui/src/tui/affectors/handle_key.rs new file mode 100644 index 00000000..52f22299 --- /dev/null +++ b/crates/sensor-tui/src/tui/affectors/handle_key.rs @@ -0,0 +1,55 @@ +use crossterm::event::{KeyCode, KeyEvent}; +use protocol::affector::ControlValue as C; + +use super::AffectorState; + +pub(crate) fn handle(key: KeyEvent, state: &mut AffectorState) -> Option { + let mut controls = state.affector.controls(); + let control = &mut controls[state.selected_control].value; + + match key.code { + KeyCode::Char('f') => handle_increase(control), + KeyCode::Char('b') => handle_decrease(control), + + KeyCode::Char('d') => { + state.selected_control = (state.selected_control + 1).min(controls.len() - 1) + } + KeyCode::Char('u') => state.selected_control = state.selected_control.saturating_sub(1), + _ => return Some(key), + }; + None +} + +fn handle_increase(control: &mut C) { + match control { + C::Trigger => (), + C::SetNum { + valid_range, + setter, + value, + } => { + let new_value = *value + 1; + let new_value = new_value as u64; + let new_value = new_value.clamp(valid_range.start, valid_range.end); + let setter = setter.take().expect("just created controls"); + setter(new_value as usize); + } + } +} + +fn handle_decrease(control: &mut C) { + match control { + C::Trigger => (), + C::SetNum { + valid_range, + setter, + value, + } => { + let new_value = *value - 1; + let new_value = new_value as u64; + let new_value = new_value.clamp(valid_range.start, valid_range.end); + let setter = setter.take().expect("just created controls"); + setter(new_value as usize); + } + } +} diff --git a/crates/sensor-tui/src/tui/affectors/render.rs b/crates/sensor-tui/src/tui/affectors/render.rs new file mode 100644 index 00000000..7102c061 --- /dev/null +++ b/crates/sensor-tui/src/tui/affectors/render.rs @@ -0,0 +1,146 @@ +use core::iter; +use protocol::affector; +use ratatui::layout::{Alignment, Constraint, Layout, Rect}; +use ratatui::style::{Modifier, Style, Stylize}; +use ratatui::text::Text; +use ratatui::widgets::{self, Block, Borders, Gauge}; +use ratatui::Frame; +use tui_tree_widget::Tree; +use tui_tree_widget::{TreeItem, TreeState}; + +use crate::tui::Theme; + +use super::{AffectorState, TreeKey}; + +pub(super) fn tree( + frame: &mut Frame, + left: Rect, + ground: &[TreeItem], + state: &mut TreeState, +) { + frame.render_stateful_widget( + Tree::new(ground) + .expect("all item identifiers should be unique") + .block( + Block::default() + .title("Controllable affectors") + .borders(Borders::ALL), + ) + .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) + .highlight_symbol(">>"), + left, + state, + ); +} + +pub(super) fn details(frame: &mut Frame, info: &affector::Info, top: Rect) { + let text = info.description; + frame.render_widget( + widgets::Paragraph::new(text) + .block(Block::bordered().title("Details")) + .wrap(widgets::Wrap { trim: true }), + top, + ) +} + +pub(crate) fn controls(frame: &mut Frame, data: &mut &mut AffectorState, bottom: Rect) { + use affector::ControlValue as V; + + let controls = data.affector.controls(); + let constraints = + iter::once(Constraint::Max(1)).chain(controls.iter().map(|_| Constraint::Max(3))); + let layout = Layout::default().constraints(constraints).split(bottom); + let mut layout = layout.into_iter(); + + frame.render_widget( + Block::new().title("Controls").borders(Borders::TOP), + *layout.next().expect("has at least one element"), + ); + + for (i, (control, layout)) in controls.iter().zip(layout).enumerate() { + let is_selected = i == data.selected_control; + match &control.value { + V::Trigger => render_trigger(frame, *layout, i), + V::SetNum { + valid_range, value, .. + } => render_slider( + frame, + *layout, + control.name, + &valid_range, + *value, + is_selected, + ), + } + } +} + +#[tracing::instrument(skip(frame, layout))] +fn render_slider( + frame: &mut Frame, + layout: Rect, + name: &str, + valid_range: &std::ops::Range, + current_value: usize, + is_active: bool, +) { + let style = if is_active { + Style::default().black() + } else { + Style::default() + }; + + tracing::debug!("slider"); + let percentage = (current_value as u64 * 100) / (valid_range.end - valid_range.start); + frame.render_widget( + Gauge::default() + .block(Block::bordered().title(name).style(style)) + .gauge_style(Style::default().add_modifier(Modifier::ITALIC)) + .label(format!( + "{current_value} of {}-{}", + valid_range.start, valid_range.end + )) + .percent(percentage as u16), + layout, + ) +} + +fn render_trigger(frame: &mut Frame, layout: Rect, _control_idx: usize) { + frame.render_widget( + widgets::Paragraph::new("activate") + .block(Block::bordered().title("Controls")) + .wrap(widgets::Wrap { trim: true }), + layout, + ) +} + +pub(crate) fn footer( + frame: &mut Frame, + layout: Rect, + data: Option<&mut AffectorState>, + theme: &Theme, +) { + let mut footer = Vec::new(); + + use affector::ControlValue as C; + match data { + Some(AffectorState { + affector, + selected_control, + .. + }) => { + footer.push("u/d: select prev/next"); + match affector.controls()[*selected_control].value { + C::Trigger => footer.push("enter: trigger affector"), + C::SetNum { .. } => footer.push("f/b increase/decrease"), + } + }, + None => (), + } + + let footer = footer.join(" "); + let footer = Text::raw(footer) + .alignment(Alignment::Center) + .style(theme.bars); + frame.render_widget(footer, layout) +} From d09c858c0e50e08b36cc50136563ffb94d850931 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 29 Aug 2024 18:41:50 +0200 Subject: [PATCH 217/687] add 'rpc framework' --- crates/ratelimited-logger/examples/log.rs | 24 ++++ crates/ratelimited-logger/src/lib.rs | 46 +++++-- crates/rpc/Cargo.toml | 20 +++ crates/rpc/src/client.rs | 129 +++++++++++++++++++ crates/rpc/src/lib.rs | 24 ++++ crates/rpc/src/server.rs | 150 ++++++++++++++++++++++ 6 files changed, 385 insertions(+), 8 deletions(-) create mode 100644 crates/ratelimited-logger/examples/log.rs create mode 100644 crates/rpc/Cargo.toml create mode 100644 crates/rpc/src/client.rs create mode 100644 crates/rpc/src/lib.rs create mode 100644 crates/rpc/src/server.rs diff --git a/crates/ratelimited-logger/examples/log.rs b/crates/ratelimited-logger/examples/log.rs new file mode 100644 index 00000000..f8712cb5 --- /dev/null +++ b/crates/ratelimited-logger/examples/log.rs @@ -0,0 +1,24 @@ +use ratelimited_logger::{warn, RateLimitedLogger}; + +fn main() { + setup_tracing(); + let mut logger = RateLimitedLogger::new(); + + warn!(logger; "oh no the number is: {}", 5); +} + +fn setup_tracing() { + use tracing_error::ErrorLayer; + use tracing_subscriber::filter; +use tracing_subscriber::util::SubscriberInitExt; + use tracing_subscriber::{self, layer::SubscriberExt, Layer}; + + let subscriber = tracing_subscriber::fmt::layer() + .with_line_number(true) + .with_target(true) + .with_filter(filter::LevelFilter::INFO); + tracing_subscriber::registry() + .with(subscriber) + .with(ErrorLayer::default()) + .init(); +} diff --git a/crates/ratelimited-logger/src/lib.rs b/crates/ratelimited-logger/src/lib.rs index d6972c0c..8211e259 100644 --- a/crates/ratelimited-logger/src/lib.rs +++ b/crates/ratelimited-logger/src/lib.rs @@ -6,12 +6,42 @@ use governor::Quota; use governor::RateLimiter; use std::num::NonZeroU32; use std::time::Duration; -use tracing::info; -use tracing::warn; pub struct RateLimitedLogger { - pub(crate) rate_limiter: RateLimiter, - pub(crate) withheld: usize, + pub rate_limiter: RateLimiter, + pub withheld: usize, +} + +#[macro_export] +macro_rules! warn { + ($limiter:ident; $($arg:tt)*) => { + if $limiter.rate_limiter.check().is_err() { + $limiter.withheld += 1; + } else { + if $limiter.withheld > 0 { + tracing::warn!("Logs are being spammed, withheld {} logs", $limiter.withheld); + $limiter.withheld = 0; + } + + tracing::warn!($($arg)*); + } + }; +} + +#[macro_export] +macro_rules! info { + ($limiter:ident; $($arg:tt)*) => { + if $limiter.rate_limiter.check().is_err() { + $limiter.withheld += 1; + } else { + if $limiter.withheld > 0 { + tracing::info!("Logs are being spammed, withheld {} logs", $limiter.withheld); + $limiter.withheld = 0; + } + + tracing::info!($($arg)*); + } + }; } impl RateLimitedLogger { @@ -32,11 +62,11 @@ impl RateLimitedLogger { } if self.withheld > 0 { - warn!("Logs are being spammed, withheld {} logs", self.withheld); + tracing::warn!("Logs are being spammed, withheld {} logs", self.withheld); self.withheld = 0; } - warn!(txt); + tracing::warn!(txt); } pub fn info(&mut self, txt: &str) { @@ -46,10 +76,10 @@ impl RateLimitedLogger { } if self.withheld > 0 { - info!("Logs are being spammed, withheld {} logs", self.withheld); + tracing::info!("Logs are being spammed, withheld {} logs", self.withheld); self.withheld = 0; } - info!(txt); + tracing::info!(txt); } } diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml new file mode 100644 index 00000000..84c96a07 --- /dev/null +++ b/crates/rpc/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "rpc" +version = "0.1.0" +rust-version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true + +[dependencies] +color-eyre = "0.6.3" +futures = "0.3.30" +governor = "0.6.3" +tokio = { workspace = true, features = ["net", "rt", "sync", "time"] } +tokio-util = { version = "0.7.11", features = ["codec"] } +tracing.workspace = true + +ratelimited-logger = { workspace = true } +serde = { version = "1.0.209", features = ["derive"] } +tokio-serde = { version = "0.9.0", features = ["bincode"] } +thiserror.workspace = true diff --git a/crates/rpc/src/client.rs b/crates/rpc/src/client.rs new file mode 100644 index 00000000..064076ff --- /dev/null +++ b/crates/rpc/src/client.rs @@ -0,0 +1,129 @@ +use core::fmt; +use std::marker::Unpin; +use std::time::Duration; + +use futures::{SinkExt, TryStreamExt}; +use serde::de::DeserializeOwned; +use serde::Serialize; +use tokio::net::TcpStream; +use tokio::net::ToSocketAddrs; +use tokio::time::error::Elapsed; +use tokio::time::timeout_at; +use tokio::time::Instant; +use tokio_serde::formats::Bincode; +use tokio_util::codec::{Framed, LengthDelimitedCodec}; + +use crate::Request; +use crate::Response; + +pub struct RpcClient +where + RpcReq: Serialize, + RpcResp: Serialize, + RpcErr: Serialize, +{ + stream: tokio_serde::Framed< + Framed, + Response, + Request, + Bincode, Request>, + >, +} + +#[derive(Debug, thiserror::Error)] +pub enum ConnectError { + #[error("Error while connecting to server: {0}")] + Io(std::io::Error), + #[error("Could not send handshake: {0}")] + Sending(std::io::Error), + #[error("Timed out waiting for server")] + Timeout, + #[error("Server unexpectedly closed the connection")] + Closed, + #[error("Server send back an error: {0:?}")] + ServerError(ServerError), + #[error("Could not receive server response: {0:?}")] + Receiving(std::io::Error), +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Got unexpected response response to request {request:?}")] + IncorrectResponse { request: String, response: String }, + #[error("Error while sending request: {0}")] + Sending(std::io::Error), + #[error("Error while sending request: {0}")] + Receiving(std::io::Error), + #[error("Server ran into an specific error with our request: {0}")] + Request(#[from] T), + #[error("Server closed connection before it awnserd")] + ConnectionClosed, +} + +impl RpcClient +where + RpcReq: Unpin + Serialize + fmt::Debug, + RpcResp: Unpin + Serialize + DeserializeOwned + fmt::Debug, + RpcErr: Unpin + Serialize + DeserializeOwned + fmt::Debug + std::error::Error, +{ + pub async fn connect( + addr: impl ToSocketAddrs, + name: String, + ) -> Result> { + let stream = TcpStream::connect(addr).await.map_err(ConnectError::Io)?; + + let length_delimited = Framed::new( + stream, + LengthDelimitedCodec::builder() + .max_frame_length(1024) + .new_codec(), + ); + + let mut stream = tokio_serde::Framed::new(length_delimited, Bincode::default()); + stream + .send(Request::Handshake { client_name: name }) + .await + .map_err(ConnectError::Sending)?; + + match tokio::time::timeout(Duration::from_secs(2), stream.try_next()).await { + Ok(Ok(Some(Response::HandshakeOk))) => Ok(Self { stream }), + Ok(Ok(Some(Response::ServerError(e)))) => Err(ConnectError::ServerError(e)), + Ok(Ok(Some(other))) => unreachable!( + "Server should return handshake response or error after sending \ + first handshake, got impossible response: {other:?}" + ), + Ok(Ok(None)) => Err(ConnectError::Closed), + Ok(Err(e)) => Err(ConnectError::Receiving(e)), + Err(_) => Err(ConnectError::Timeout), + } + } + + pub async fn send_receive(&mut self, request: RpcReq) -> Result> { + fn send_timeout_err(_: Elapsed) -> Error { + Error::Sending(std::io::Error::new(std::io::ErrorKind::TimedOut, "")) + } + fn receive_timeout_err(_: Elapsed) -> Error { + Error::Receiving(std::io::Error::new(std::io::ErrorKind::TimedOut, "")) + } + + let deadline = Instant::now() + Duration::from_secs(5); + let request = Request::Rpc(request); + timeout_at(deadline, self.stream.send(request)) + .await + .map_err(send_timeout_err)? + .map_err(Error::Sending)?; + match timeout_at(deadline, self.stream.try_next()) + .await + .map_err(receive_timeout_err)? + .map_err(Error::Receiving)? + { + Some(Response::ServerError(e)) => Err(Error::Request(e)), + Some(Response::RpcResponse(v)) => Ok(v), + Some(Response::TooManyReq { .. }) => { + unreachable!("only creating connections is ratelimited") + } + Some(Response::HandshakeOk) => unreachable!("is only send during initial connection"), + None => Err(Error::ConnectionClosed), + } + } +} diff --git a/crates/rpc/src/lib.rs b/crates/rpc/src/lib.rs new file mode 100644 index 00000000..fea2a333 --- /dev/null +++ b/crates/rpc/src/lib.rs @@ -0,0 +1,24 @@ +use std::time::Duration; + +use serde::{Deserialize, Serialize}; + +pub mod client; +pub mod server; + +#[derive(Debug, Clone, Serialize, Deserialize)] +enum Request { + Handshake { client_name: String }, + Rpc(R), +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +enum Response +where + V: Serialize, + E: Serialize, +{ + HandshakeOk, + TooManyReq { allowed_in: Duration }, + RpcResponse(V), + ServerError(E), +} diff --git a/crates/rpc/src/server.rs b/crates/rpc/src/server.rs new file mode 100644 index 00000000..e8662046 --- /dev/null +++ b/crates/rpc/src/server.rs @@ -0,0 +1,150 @@ +use std::fmt; +use std::marker::Unpin; +use std::net::SocketAddr; +use std::num::NonZeroU32; +use std::time::Duration; + +use color_eyre::eyre::Context; +use color_eyre::Section; +use futures::{SinkExt, TryStreamExt}; +use governor::clock::{Clock, DefaultClock}; +use governor::{Quota, RateLimiter}; +use serde::de::DeserializeOwned; +use serde::Serialize; +use tokio::net::{TcpListener, TcpStream}; +use tokio_serde::formats::Bincode; +use tokio_util::codec::{Framed, LengthDelimitedCodec}; + +use ratelimited_logger::{self as rlog, RateLimitedLogger}; +use tracing::{debug, error, info}; + +type Conn = tokio_serde::Framed< + Framed, + crate::Request, + crate::Response, + Bincode, crate::Response>, +>; + +pub async fn run( + port: u16, + perform_request: impl FnOnce(RpcReq) -> Fut + Clone + Send + 'static, +) -> color_eyre::Result<()> +where + RpcReq: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, + RpcResp: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, + RpcErr: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + std::error::Error + 'static, + Fut: Future + Send + 'static, +{ + let quota = Quota::with_period(Duration::from_secs(1)) + .unwrap() + .allow_burst(NonZeroU32::new(5u32).unwrap()); + let limiter = RateLimiter::keyed(quota); + let listener = TcpListener::bind(format!("0.0.0.0:{port}")) + .await + .wrap_err("Could not bind to address") + .with_note(|| format!("port: {port}"))?; + let mut logger = RateLimitedLogger::new(); + + loop { + let (socket, source) = match listener.accept().await { + Err(e) => { + rlog::warn!(logger; "client could not connect: {e}"); + continue; + } + Ok(res) => res, + }; + + let Some((mut conn, name)) = + handshake_and_log::(socket, source, &mut logger).await + else { + continue; + }; + + if let Err(allowed_again) = limiter.check_key(&(source.ip(), name.clone())) { + let allowed_in = allowed_again.wait_time_from(DefaultClock::default().now()); + let _ignore_err = conn.send(crate::Response::TooManyReq { allowed_in }); + continue; + } + + info!("Client {name} connected from {source}"); + let Ok(()) = conn.send(crate::Response::HandshakeOk).await else { + continue; + }; + + tokio::task::spawn(handle_client(conn, perform_request.clone())); + } +} + +async fn handshake_and_log( + stream: TcpStream, + source: SocketAddr, + logger: &mut RateLimitedLogger, +) -> Option<(Conn, String)> +where + RpcReq: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, + RpcResp: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, + RpcErr: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + std::error::Error + 'static, +{ + let length_delimited = Framed::new( + stream, + LengthDelimitedCodec::builder() + .max_frame_length(1024) + .new_codec(), + ); + let mut stream: tokio_serde::Framed< + _, + crate::Request, + crate::Response, + _, + > = tokio_serde::Framed::new(length_delimited, Bincode::default()); + + match stream.try_next().await { + Ok(Some(crate::Request::Handshake { client_name })) => { + return Some((stream, client_name)); + } + Ok(Some(other)) => { + rlog::warn!(logger; "client from {source} tried to connected without handshake, it send: {other:?}") + } + Ok(None) => rlog::warn!(logger; "client from {source} closed connection immediately"), + Err(e) => { + rlog::warn!(logger; "connection or decoding issue while receiving handshake from {source}, error: {e:?}") + } + } + + None +} + +use core::future::Future; +async fn handle_client( + mut conn: Conn, + perform_request: impl FnOnce(RpcReq) -> Fut + Clone + Send + 'static, +) where + RpcReq: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, + RpcResp: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, + RpcErr: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + std::error::Error + 'static, + Fut: Future + Send + 'static, +{ + loop { + let request = match conn.try_next().await { + Ok(Some(request)) => request, + Ok(None) => { + debug!("Connection ended"); + return; + } + Err(e) => { + error!("Could not receive request: {e:?}"); + return; + } + }; + let crate::Request::Rpc(rpc_request) = request else { + error!("Handshake request is not allowed after we send back HandshakeOk"); + return; + }; + + let response = perform_request.clone()(rpc_request).await; + if let Err(e) = conn.send(crate::Response::RpcResponse(response)).await { + error!("Error sending response to client: {e:?}"); + return; + } + } +} From 0d740c86e2cc950b16dae6713a4a167bb9069572 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 29 Aug 2024 21:30:34 +0200 Subject: [PATCH 218/687] move log store to new rpc framework --- Cargo.toml | 1 + crates/log-store/Cargo.toml | 5 +- crates/log-store/src/api.rs | 3 - crates/log-store/src/api/client.rs | 106 ++++----------------- crates/log-store/src/server/clients.rs | 124 ++----------------------- crates/log-store/src/server/db.rs | 1 + crates/log-store/src/server/db/log.rs | 8 +- crates/rpc/src/client.rs | 49 +++++----- crates/rpc/src/lib.rs | 8 +- crates/rpc/src/server.rs | 35 +++---- 10 files changed, 76 insertions(+), 264 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c70bf5b0..29456c2e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ data-server = { path = "crates/data-server" } data-store = { path = "crates/data-store" } log-store = { path = "crates/log-store" } protocol = { path = "crates/protocol" } +rpc = { path = "crates/rpc" } ratelimited-logger = { path = "crates/ratelimited-logger" } byteseries = { git = "https://github.com/dvdsk/byteseries" } diff --git a/crates/log-store/Cargo.toml b/crates/log-store/Cargo.toml index bddabdf5..a6d3d59e 100644 --- a/crates/log-store/Cargo.toml +++ b/crates/log-store/Cargo.toml @@ -22,12 +22,10 @@ jiff = { workspace =true, features = ["serde"] } protocol = { workspace = true, features = ["alloc", "thiserror"] } data-server = { workspace = true } byteseries = { workspace = true } -ratelimited-logger = { workspace = true } +rpc = { workspace = true } tokio = { workspace = true, features = ["fs", "net", "rt-multi-thread", "sync"] } futures-concurrency = "7.6.1" -tokio-serde = { version = "0.9.0", features = ["bincode"] } -tokio-util = { version = "0.7.11", features = ["codec"] } serde = { version = "1.0.203", features = ["derive"] } bincode = "1.3.3" thiserror = { workspace = true } @@ -35,7 +33,6 @@ futures = "0.3.30" smallvec = "2.0.0-alpha.6" num = "0.4.3" hdrhistogram = "7.5.4" -governor = "0.6.3" [dev-dependencies] futures-concurrency = "7.6.1" diff --git a/crates/log-store/src/api.rs b/crates/log-store/src/api.rs index e82e033e..2fd254d0 100644 --- a/crates/log-store/src/api.rs +++ b/crates/log-store/src/api.rs @@ -7,9 +7,6 @@ use serde::{Deserialize, Serialize}; pub mod client; pub use client::Client; -// 8 MB -pub(crate) const MAX_PACKAGE_SIZE: usize = 8 * 1024 * 1024; - #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) enum Request { Handshake { name: String }, diff --git a/crates/log-store/src/api/client.rs b/crates/log-store/src/api/client.rs index 79450b2c..88d81ecd 100644 --- a/crates/log-store/src/api/client.rs +++ b/crates/log-store/src/api/client.rs @@ -1,32 +1,15 @@ -use std::time::Duration; - -use futures::{SinkExt, TryStreamExt}; use protocol::Device; -use tokio::net::TcpStream; +use rpc::client::RpcClient; use tokio::net::ToSocketAddrs; -use tokio::time::error::Elapsed; -use tokio::time::timeout_at; -use tokio::time::Instant; -use tokio_serde::formats::Bincode; -use tokio_util::codec::{Framed, LengthDelimitedCodec}; use crate::api::Percentile; use super::ErrorEvent; use super::GetLogError; use super::GetStatsError; -use super::Request; use super::Response; -use super::ServerError; -pub struct Client { - stream: tokio_serde::Framed< - Framed, - Response, - super::Request, - Bincode, - >, -} +pub struct Client(rpc::client::RpcClient); #[derive(Debug, thiserror::Error)] pub enum ConnectError { @@ -48,73 +31,19 @@ pub enum ConnectError { pub enum Error { #[error("Got unexpected response response to request {request:?}")] IncorrectResponse { request: String, response: String }, - #[error("Error while sending request: {0}")] - Sending(std::io::Error), - #[error("Error while sending request: {0}")] - Receiving(std::io::Error), - #[error("General error while processing request")] - Server(ServerError), #[error("Server ran into an specific error with our request: {0}")] - Request(#[from] T), - #[error("Server closed connection before it awnserd")] - ConnectionClosed, + Request(T), + #[error("Error while communicating with server: {0}")] + Comms(#[from] rpc::client::RpcError), } impl Client { - pub async fn connect(addr: impl ToSocketAddrs, name: String) -> Result { - let stream = TcpStream::connect(addr).await.map_err(ConnectError::Io)?; - - let length_delimited = Framed::new( - stream, - LengthDelimitedCodec::builder() - .max_frame_length(super::MAX_PACKAGE_SIZE) - .new_codec(), - ); - - let mut stream = tokio_serde::Framed::new(length_delimited, Bincode::default()); - stream - .send(Request::Handshake { name }) - .await - .map_err(ConnectError::Sending)?; - - match tokio::time::timeout(Duration::from_secs(2), stream.try_next()).await { - Ok(Ok(Some(Response::Handshake))) => Ok(Self { stream }), - Ok(Ok(Some(Response::Error(e)))) => Err(ConnectError::ServerError(e)), - Ok(Ok(Some(other))) => unreachable!( - "Server should return handshake response or error after sending \ - first handshake, got impossible response: {other:?}" - ), - Ok(Ok(None)) => Err(ConnectError::Closed), - Ok(Err(e)) => Err(ConnectError::Receiving(e)), - Err(_) => Err(ConnectError::Timeout), - } - } - - async fn send_receive( - &mut self, - request: super::Request, - ) -> Result> { - fn send_timeout_err(_: Elapsed) -> Error { - Error::Sending(std::io::Error::new(std::io::ErrorKind::TimedOut, "")) - } - fn receive_timeout_err(_: Elapsed) -> Error { - Error::Receiving(std::io::Error::new(std::io::ErrorKind::TimedOut, "")) - } - - let deadline = Instant::now() + Duration::from_secs(5); - timeout_at(deadline, self.stream.send(request)) - .await - .map_err(send_timeout_err)? - .map_err(Error::Sending)?; - match timeout_at(deadline, self.stream.try_next()) - .await - .map_err(receive_timeout_err)? - .map_err(Error::Receiving)? - { - Some(Response::Error(e)) => Err(Error::Server(e)), - Some(response) => Ok(response), - None => Err(Error::ConnectionClosed), - } + pub async fn connect( + addr: impl ToSocketAddrs, + name: String, + ) -> Result { + let rpc_client = RpcClient::connect(addr, name).await?; + Ok(Self(rpc_client)) } pub async fn get_percentiles( @@ -122,9 +51,9 @@ impl Client { device: protocol::Device, ) -> Result, Error> { let request = super::Request::GetStats(device); - match self.send_receive(request.clone()).await { - Ok(Response::GetStats(percentiles)) => Ok(percentiles?), - Err(err) => Err(err), + match self.0.send_receive(request.clone()).await? { + Response::GetStats(Ok(percentiles)) => Ok(percentiles), + Response::GetStats(Err(e)) => Err(Error::Request(e)), response => Err(Error::IncorrectResponse { request: format!("{request:?}"), response: format!("{response:?}"), @@ -137,8 +66,9 @@ impl Client { device: protocol::Device, ) -> Result, Error> { let request = super::Request::GetLog(device); - match self.send_receive(request.clone()).await? { - Response::GetLog(logs) => Ok(logs?), + match self.0.send_receive(request.clone()).await? { + Response::GetLog(Ok(log)) => Ok(log), + Response::GetLog(Err(e)) => Err(Error::Request(e)), response => Err(Error::IncorrectResponse { request: format!("{request:?}"), response: format!("{response:?}"), @@ -148,7 +78,7 @@ impl Client { pub async fn list_devices(&mut self) -> Result, Error> { let request = super::Request::ListDevices; - match self.send_receive(request.clone()).await? { + match self.0.send_receive(request.clone()).await? { Response::ListDevices(logs) => Ok(logs), response => Err(Error::IncorrectResponse { request: format!("{request:?}"), diff --git a/crates/log-store/src/server/clients.rs b/crates/log-store/src/server/clients.rs index 98377f44..b92eccd4 100644 --- a/crates/log-store/src/server/clients.rs +++ b/crates/log-store/src/server/clients.rs @@ -1,127 +1,19 @@ -use std::net::SocketAddr; -use std::num::NonZeroU32; -use std::time::Duration; - -use color_eyre::eyre::Context; -use color_eyre::Section; -use futures::{SinkExt, TryStreamExt}; -use governor::clock::{Clock, DefaultClock}; -use governor::{Quota, RateLimiter}; -use ratelimited_logger::RateLimitedLogger; -use tokio::net::{TcpListener, TcpStream}; -use tokio_serde::formats::Bincode; -use tokio_util::codec::{Framed, LengthDelimitedCodec}; -use tracing::{debug, error}; - use super::db::{Logs, Stats}; use crate::api::{self, ServerError}; -type Conn = tokio_serde::Framed< - Framed, - api::Request, - api::Response, - Bincode, ->; - pub(crate) async fn handle(port: u16, stats: Stats, logs: Logs) -> color_eyre::Result<()> { - let quota = Quota::with_period(Duration::from_secs(1)) - .unwrap() - .allow_burst(NonZeroU32::new(5).unwrap()); - let limiter = RateLimiter::keyed(quota); - let listener = TcpListener::bind(format!("0.0.0.0:{port}")) - .await - .wrap_err("Could not bind to address") - .with_note(|| format!("port: {port}"))?; - let mut logger = RateLimitedLogger::new(); - - loop { - let (socket, source) = match listener.accept().await { - Err(e) => { - logger.warn(&format!("client could not connect: {e}")); - continue; - } - Ok(res) => res, - }; - - let Some((mut conn, name)) = handshake(socket, source, &mut logger).await else { - continue; - }; - - if let Err(allowed_again) = limiter.check_key(&(source.ip(), name)) { - let allowed_in = allowed_again.wait_time_from(DefaultClock::default().now()); - let _ignore_err = conn.send(api::Response::Error(ServerError::TooManyRequests( - allowed_in, - ))); - continue; - } - - let Ok(()) = conn.send(api::Response::Handshake).await else { - continue; - }; - - tokio::task::spawn(handle_client(conn, stats.clone(), logs.clone())); - } -} - -async fn handshake( - stream: TcpStream, - source: SocketAddr, - logger: &mut RateLimitedLogger, -) -> Option<(Conn, String)> { - let length_delimited = Framed::new( - stream, - LengthDelimitedCodec::builder() - .max_frame_length(api::MAX_PACKAGE_SIZE) - .new_codec(), - ); - let mut stream: tokio_serde::Framed<_, api::Request, api::Response, _> = - tokio_serde::Framed::new(length_delimited, Bincode::default()); - - match stream.try_next().await { - Ok(Some(api::Request::Handshake { name })) => { - logger.info(&format!("Client {name} connected from {source}")); - return Some((stream, name)); - } - Ok(Some(other)) => logger.warn(&format!( - "client tried to connected without handshake, it send: {other:?}" - )), - Ok(None) => logger.warn("client closed connection immediately"), - Err(e) => logger.warn(&format!( - "connection or decoding issue while receiving handshake: {e:?}" - )), - } - - None -} - -async fn handle_client(mut conn: Conn, stats: Stats, logs: Logs) { - loop { - let request = match conn.try_next().await { - Ok(Some(request)) => request, - Ok(None) => { - debug!("Connection ended"); - return; - } - Err(e) => { - error!("Could not receive request: {e:?}"); - return; - } - }; - let response = match perform_request(request, &stats, &logs).await { - Err(err) => api::Response::Error(err), - Ok(r) => r, - }; - if let Err(e) = conn.send(response).await { - error!("Error sending response to client: {e:?}"); - return; - } - } + rpc::server::run(port, move |req| { + let stats = stats.clone(); + let logs = logs.clone(); + perform_request(req, stats, logs) + }) + .await } async fn perform_request( request: api::Request, - stats: &Stats, - logs: &Logs, + stats: Stats, + logs: Logs, ) -> Result { Ok(match request { api::Request::Handshake { .. } => return Err(ServerError::AlreadyConnected), diff --git a/crates/log-store/src/server/db.rs b/crates/log-store/src/server/db.rs index 145eb686..df1b5b24 100644 --- a/crates/log-store/src/server/db.rs +++ b/crates/log-store/src/server/db.rs @@ -34,6 +34,7 @@ pub(crate) async fn run( } } SubMessage::ErrorReport(report) => logs.set_err(*report, log_dir).await, + SubMessage::AffectorControlled { .. } => continue, }; const FIVE_MIN: Duration = Duration::from_secs(60 * 5); diff --git a/crates/log-store/src/server/db/log.rs b/crates/log-store/src/server/db/log.rs index 8dd86071..08ef03c3 100644 --- a/crates/log-store/src/server/db/log.rs +++ b/crates/log-store/src/server/db/log.rs @@ -104,7 +104,6 @@ impl Log { let res = ByteSeries::builder() .payload_size(payload_size) - .create_new(true) .with_header(header.clone()) .open(&path); @@ -122,12 +121,17 @@ impl Log { ByteSeries::builder() .payload_size(payload_size) .with_header(header) + .create_new(true) .open(&path) .wrap_err("Could not create new byteseries") .with_note(|| format!("path: {}", path.display()))? .0 } - Err(e) => return Err(e).wrap_err("Could not open existing byteseries"), + Err(e) => { + return Err(e) + .wrap_err("Could not open existing byteseries") + .with_note(|| format!("path: {}", path.display())) + } }; Ok(Self { diff --git a/crates/rpc/src/client.rs b/crates/rpc/src/client.rs index 064076ff..e61e5a46 100644 --- a/crates/rpc/src/client.rs +++ b/crates/rpc/src/client.rs @@ -16,22 +16,21 @@ use tokio_util::codec::{Framed, LengthDelimitedCodec}; use crate::Request; use crate::Response; -pub struct RpcClient +pub struct RpcClient where RpcReq: Serialize, RpcResp: Serialize, - RpcErr: Serialize, { stream: tokio_serde::Framed< Framed, - Response, + Response, Request, - Bincode, Request>, + Bincode, Request>, >, } #[derive(Debug, thiserror::Error)] -pub enum ConnectError { +pub enum ConnectError { #[error("Error while connecting to server: {0}")] Io(std::io::Error), #[error("Could not send handshake: {0}")] @@ -40,42 +39,36 @@ pub enum ConnectError { Timeout, #[error("Server unexpectedly closed the connection")] Closed, - #[error("Server send back an error: {0:?}")] - ServerError(ServerError), #[error("Could not receive server response: {0:?}")] Receiving(std::io::Error), + #[error("Client was already connected")] + AlreadyConnected, } #[derive(Debug, thiserror::Error)] -pub enum Error { +pub enum RpcError { #[error("Got unexpected response response to request {request:?}")] IncorrectResponse { request: String, response: String }, #[error("Error while sending request: {0}")] Sending(std::io::Error), #[error("Error while sending request: {0}")] Receiving(std::io::Error), - #[error("Server ran into an specific error with our request: {0}")] - Request(#[from] T), #[error("Server closed connection before it awnserd")] ConnectionClosed, } -impl RpcClient +impl RpcClient where RpcReq: Unpin + Serialize + fmt::Debug, RpcResp: Unpin + Serialize + DeserializeOwned + fmt::Debug, - RpcErr: Unpin + Serialize + DeserializeOwned + fmt::Debug + std::error::Error, { - pub async fn connect( - addr: impl ToSocketAddrs, - name: String, - ) -> Result> { + pub async fn connect(addr: impl ToSocketAddrs, name: String) -> Result { let stream = TcpStream::connect(addr).await.map_err(ConnectError::Io)?; let length_delimited = Framed::new( stream, LengthDelimitedCodec::builder() - .max_frame_length(1024) + .max_frame_length(super::MAX_PACKAGE_SIZE) .new_codec(), ); @@ -87,7 +80,7 @@ where match tokio::time::timeout(Duration::from_secs(2), stream.try_next()).await { Ok(Ok(Some(Response::HandshakeOk))) => Ok(Self { stream }), - Ok(Ok(Some(Response::ServerError(e)))) => Err(ConnectError::ServerError(e)), + Ok(Ok(Some(Response::AlreadyConnected))) => Err(ConnectError::AlreadyConnected), Ok(Ok(Some(other))) => unreachable!( "Server should return handshake response or error after sending \ first handshake, got impossible response: {other:?}" @@ -98,12 +91,12 @@ where } } - pub async fn send_receive(&mut self, request: RpcReq) -> Result> { - fn send_timeout_err(_: Elapsed) -> Error { - Error::Sending(std::io::Error::new(std::io::ErrorKind::TimedOut, "")) + pub async fn send_receive(&mut self, request: RpcReq) -> Result { + fn send_timeout_err(_: Elapsed) -> RpcError { + RpcError::Sending(std::io::Error::new(std::io::ErrorKind::TimedOut, "")) } - fn receive_timeout_err(_: Elapsed) -> Error { - Error::Receiving(std::io::Error::new(std::io::ErrorKind::TimedOut, "")) + fn receive_timeout_err(_: Elapsed) -> RpcError { + RpcError::Receiving(std::io::Error::new(std::io::ErrorKind::TimedOut, "")) } let deadline = Instant::now() + Duration::from_secs(5); @@ -111,19 +104,21 @@ where timeout_at(deadline, self.stream.send(request)) .await .map_err(send_timeout_err)? - .map_err(Error::Sending)?; + .map_err(RpcError::Sending)?; match timeout_at(deadline, self.stream.try_next()) .await .map_err(receive_timeout_err)? - .map_err(Error::Receiving)? + .map_err(RpcError::Receiving)? { - Some(Response::ServerError(e)) => Err(Error::Request(e)), + Some(Response::AlreadyConnected) => { + unreachable!("not creating a connection") + } Some(Response::RpcResponse(v)) => Ok(v), Some(Response::TooManyReq { .. }) => { unreachable!("only creating connections is ratelimited") } Some(Response::HandshakeOk) => unreachable!("is only send during initial connection"), - None => Err(Error::ConnectionClosed), + None => Err(RpcError::ConnectionClosed), } } } diff --git a/crates/rpc/src/lib.rs b/crates/rpc/src/lib.rs index fea2a333..527c14cf 100644 --- a/crates/rpc/src/lib.rs +++ b/crates/rpc/src/lib.rs @@ -5,6 +5,9 @@ use serde::{Deserialize, Serialize}; pub mod client; pub mod server; +// 8 MB +pub(crate) const MAX_PACKAGE_SIZE: usize = 8 * 1024 * 1024; + #[derive(Debug, Clone, Serialize, Deserialize)] enum Request { Handshake { client_name: String }, @@ -12,13 +15,12 @@ enum Request { } #[derive(Debug, Clone, Serialize, Deserialize)] -enum Response +enum Response where V: Serialize, - E: Serialize, { HandshakeOk, + AlreadyConnected, TooManyReq { allowed_in: Duration }, RpcResponse(V), - ServerError(E), } diff --git a/crates/rpc/src/server.rs b/crates/rpc/src/server.rs index e8662046..3defc855 100644 --- a/crates/rpc/src/server.rs +++ b/crates/rpc/src/server.rs @@ -18,21 +18,20 @@ use tokio_util::codec::{Framed, LengthDelimitedCodec}; use ratelimited_logger::{self as rlog, RateLimitedLogger}; use tracing::{debug, error, info}; -type Conn = tokio_serde::Framed< +type Conn = tokio_serde::Framed< Framed, crate::Request, - crate::Response, - Bincode, crate::Response>, + crate::Response, + Bincode, crate::Response>, >; -pub async fn run( +pub async fn run( port: u16, - perform_request: impl FnOnce(RpcReq) -> Fut + Clone + Send + 'static, + perform_request: impl Fn(RpcReq) -> Fut + Clone + Send + 'static, ) -> color_eyre::Result<()> where RpcReq: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, RpcResp: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, - RpcErr: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + std::error::Error + 'static, Fut: Future + Send + 'static, { let quota = Quota::with_period(Duration::from_secs(1)) @@ -55,7 +54,7 @@ where }; let Some((mut conn, name)) = - handshake_and_log::(socket, source, &mut logger).await + handshake_and_log::(socket, source, &mut logger).await else { continue; }; @@ -75,28 +74,23 @@ where } } -async fn handshake_and_log( +async fn handshake_and_log( stream: TcpStream, source: SocketAddr, logger: &mut RateLimitedLogger, -) -> Option<(Conn, String)> +) -> Option<(Conn, String)> where RpcReq: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, RpcResp: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, - RpcErr: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + std::error::Error + 'static, { let length_delimited = Framed::new( stream, LengthDelimitedCodec::builder() - .max_frame_length(1024) + .max_frame_length(super::MAX_PACKAGE_SIZE) .new_codec(), ); - let mut stream: tokio_serde::Framed< - _, - crate::Request, - crate::Response, - _, - > = tokio_serde::Framed::new(length_delimited, Bincode::default()); + let mut stream: tokio_serde::Framed<_, crate::Request, crate::Response, _> = + tokio_serde::Framed::new(length_delimited, Bincode::default()); match stream.try_next().await { Ok(Some(crate::Request::Handshake { client_name })) => { @@ -115,13 +109,12 @@ where } use core::future::Future; -async fn handle_client( - mut conn: Conn, - perform_request: impl FnOnce(RpcReq) -> Fut + Clone + Send + 'static, +async fn handle_client( + mut conn: Conn, + perform_request: impl Fn(RpcReq) -> Fut + Clone + Send + 'static, ) where RpcReq: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, RpcResp: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, - RpcErr: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + std::error::Error + 'static, Fut: Future + Send + 'static, { loop { From 05395839410040f0af6e5d8b5076246da6852712 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 1 Sep 2024 01:42:18 +0200 Subject: [PATCH 219/687] add blocking i2c nau7802 sensor --- sensor-nodes/bed-sensors/src/error_cache.rs | 2 + sensor-nodes/bed-sensors/src/main.rs | 23 ++++++-- sensor-nodes/bed-sensors/src/sensors.rs | 54 ++++++++++++++++--- sensor-nodes/bed-sensors/src/sensors/fast.rs | 42 ++++++++++----- sensor-nodes/bed-sensors/src/sensors/retry.rs | 28 ++++++++-- .../src/sensors/retry/reinit_on_error.rs | 4 +- 6 files changed, 125 insertions(+), 28 deletions(-) diff --git a/sensor-nodes/bed-sensors/src/error_cache.rs b/sensor-nodes/bed-sensors/src/error_cache.rs index 56e2ee8c..b5c6837e 100644 --- a/sensor-nodes/bed-sensors/src/error_cache.rs +++ b/sensor-nodes/bed-sensors/src/error_cache.rs @@ -11,6 +11,7 @@ pub enum SensorError { Bme680(bosch_bme680::BmeError), Max44(max44009::Error), Nau7802Left(nau7802_async::Error), + Nau7802Right(nau7802_async::Error), } impl From for bed::SensorError { @@ -22,6 +23,7 @@ impl From for bed::SensorError { SensorError::Bme680(e) => bed::SensorError::Bme680(make_error_string(e)), SensorError::Max44(e) => bed::SensorError::Max44(make_error_string(e)), SensorError::Nau7802Left(e) => bed::SensorError::Nau7802Left(make_error_string(e)), + SensorError::Nau7802Right(e) => bed::SensorError::Nau7802Right(make_error_string(e)), } } } diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index 8899880d..b7ddd7ba 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -13,7 +13,7 @@ use embassy_stm32::mode::Async; use embassy_stm32::peripherals::IWDG; use embassy_stm32::spi::{Config as SpiConfig, Spi}; use embassy_stm32::time::Hertz; -use embassy_stm32::usart::{self, DataBits, StopBits, Uart}; +use embassy_stm32::usart::{self, DataBits, Parity, StopBits, Uart}; use embassy_stm32::wdg::IndependentWatchdog; use embassy_stm32::Config; use embassy_sync::blocking_mutex::raw::NoopRawMutex; @@ -93,7 +93,6 @@ async fn main(spawner: Spawner) { usart_config.baudrate = 9600; usart_config.data_bits = DataBits::DataBits8; usart_config.stop_bits = StopBits::STOP1; - // usart_config.parity = Parity::ParityEven; let usart_mhz = unwrap!(Uart::new( p.USART1, p.PB7, @@ -105,9 +104,10 @@ async fn main(spawner: Spawner) { )); let mut usart_config = usart::Config::default(); - usart_config.baudrate = 115_200; + usart_config.baudrate = 115_200; // sps30 only works at this baud usart_config.data_bits = DataBits::DataBits8; usart_config.stop_bits = StopBits::STOP1; + usart_config.parity = Parity::ParityNone; let usart_sps30 = unwrap!(Uart::new( p.USART2, p.PA3, @@ -118,6 +118,8 @@ async fn main(spawner: Spawner) { usart_config, )); + // we are out of DMA, so we need to use a blocking interface + // these sensors are only read once every 5s let i2c_1 = I2c::new( p.I2C1, p.PB8, @@ -125,12 +127,23 @@ async fn main(spawner: Spawner) { Irqs, p.DMA1_CH7, p.DMA1_CH0, - // extra slow, helps with longer cable runs Hertz(150_000), i2c::Config::default(), ); let i2c_1: Mutex = Mutex::new(i2c_1); + let i2c_2 = I2c::new_blocking( + p.I2C2, + p.PB10, + p.PB3, + // extra slow, helps with longer cable runs + Hertz(150_000), + i2c::Config::default(), + ); + // even though its used by only one device we still use the (zero cost) + // mutex. It allows us to match/reuse the API for syn & async nau7802 + let i2c_2: Mutex = Mutex::new(i2c_2); + let i2c_3 = I2c::new( p.I2C3, p.PA8, @@ -199,7 +212,7 @@ async fn main(spawner: Spawner) { pin_mut!(handle_network); let init_then_measure = - sensors::init_then_measure(&publish, i2c_1, i2c_3, usart_mhz, usart_sps30); + sensors::init_then_measure(&publish, i2c_1, i2c_2, i2c_3, usart_mhz, usart_sps30); let res = select::select(&mut handle_network, init_then_measure).await; let unrecoverable_err = match res { Either::First(()) | Either::Second(Ok(())) => defmt::unreachable!(), diff --git a/sensor-nodes/bed-sensors/src/sensors.rs b/sensor-nodes/bed-sensors/src/sensors.rs index 712c1523..e3c48bec 100644 --- a/sensor-nodes/bed-sensors/src/sensors.rs +++ b/sensor-nodes/bed-sensors/src/sensors.rs @@ -2,38 +2,42 @@ use defmt::info; use embassy_embedded_hal::shared_bus::I2cDeviceError; use embassy_futures::join; use embassy_stm32::i2c::I2c; -use embassy_stm32::mode::Async; +use embassy_stm32::mode::{Async, Blocking}; use embassy_stm32::usart::Uart; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; use embassy_time::Delay; use mhzx::MHZ; use protocol::large_bedroom::bed::Device; -use retry::Nau7802Driver; use sps30_async::Sps30; use crate::channel::Queues; use crate::error_cache::{Error, SensorError}; -use crate::sensors::retry::{Bme680Driver, Max44Driver, Sht31Driver, Sps30Driver}; - -use self::retry::Driver; pub mod fast; pub mod retry; pub mod slow; +use retry::{ + Bme680Driver, Driver, Max44Driver, Nau7802Driver, Nau7802DriverBlocking, Sht31Driver, + Sps30Driver, +}; + pub type I2cError = I2cDeviceError; pub type UartError = embassy_stm32::usart::Error; pub mod concrete_types { use embassy_embedded_hal::shared_bus; use embassy_stm32::i2c::I2c; - use embassy_stm32::mode::Async; + use embassy_stm32::mode::{Async, Blocking}; use embassy_stm32::usart::{RingBufferedUartRx, UartTx}; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use shared_bus::asynch::i2c::I2cDevice; + use super::I2cWrapper; + pub type ConcreteSharedI2c<'a> = I2cDevice<'a, NoopRawMutex, I2c<'static, Async>>; + pub type ConcreteBlockingI2c<'a> = &'a I2cWrapper>; pub type ConcreteTx<'a> = UartTx<'a, Async>; pub type ConcreteRx<'a> = RingBufferedUartRx<'a>; } @@ -44,6 +48,7 @@ const SPS30_DRIVER_BUF_SIZE: usize = 2 * SPS30_UART_BUF_SIZE; pub async fn init_then_measure( publish: &Queues, i2c_1: Mutex>, + i2c_2: Mutex>, i2c_3: Mutex>, usart_mhz: Uart<'static, Async>, usart_sps: Uart<'static, Async>, @@ -52,6 +57,8 @@ pub async fn init_then_measure( let bme = Bme680Driver::new(&i2c_3, Device::Bme680); let max44009 = Max44Driver::new(&i2c_1, Device::Max44); let sht = Sht31Driver::new(&i2c_1, Device::Sht31); + let i2c_2 = I2cWrapper(i2c_2); + let nau_right = Nau7802DriverBlocking::new(&i2c_2, Device::Nau7802Right); let nau_left = Nau7802Driver::new(&i2c_3, Device::Nau7802Left); let (tx, rx) = usart_mhz.split(); @@ -64,7 +71,7 @@ pub async fn init_then_measure( let rx = rx.into_ring_buffered(&mut usart_buf); let sps30 = Sps30Driver::init(tx, rx); - let sensors_fast = fast::read(max44009, nau_left, /*buttons,*/ publish); + let sensors_fast = fast::read(max44009, nau_right, nau_left, /*buttons,*/ publish); let sensors_slow = slow::read(sht, bme, mhz, sps30, publish); join::join(sensors_fast, sensors_slow).await; @@ -106,3 +113,36 @@ impl<'a> Driver for Sps30, Rx<'a>, Delay> { Device::Sps30 } } + +pub(crate) struct I2cWrapper(Mutex); + +impl embedded_hal_async::i2c::ErrorType for &I2cWrapper { + type Error = ::Error; +} + +impl embedded_hal_async::i2c::I2c for &I2cWrapper { + async fn transaction( + &mut self, + address: u8, + operations: &mut [embedded_hal_async::i2c::Operation<'_>], + ) -> Result<(), Self::Error> { + self.0.lock().await.transaction(address, operations) + } + + async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { + self.0.lock().await.read(address, read) + } + + async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { + self.0.lock().await.write(address, write) + } + + async fn write_read( + &mut self, + address: u8, + write: &[u8], + read: &mut [u8], + ) -> Result<(), Self::Error> { + self.0.lock().await.write_read(address, write, read) + } +} diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed-sensors/src/sensors/fast.rs index 745a7ee0..f2b69003 100644 --- a/sensor-nodes/bed-sensors/src/sensors/fast.rs +++ b/sensor-nodes/bed-sensors/src/sensors/fast.rs @@ -5,7 +5,7 @@ use embassy_time::{Duration, Instant, Timer}; use protocol::large_bedroom::{bed::Button, bed::Reading}; -use super::retry::{Max44Driver, Nau7802Driver}; +use super::retry::{Max44Driver, Nau7802Driver, Nau7802DriverBlocking}; use crate::channel::Queues; fn sig_lux_diff(old: f32, new: f32) -> bool { @@ -51,18 +51,35 @@ async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues) { } } -async fn report_weight(mut nau: Nau7802Driver<'_>, publish: &Queues) { +trait Nau { + async fn try_measure(&mut self) -> Result; +} + +impl Nau for Nau7802Driver<'_> { + async fn try_measure(&mut self) -> Result { + Nau7802Driver::try_measure(self).await + } +} + +impl Nau for Nau7802DriverBlocking<'_> { + async fn try_measure(&mut self) -> Result { + Nau7802DriverBlocking::try_measure(self).await + } +} + +// todo deduplicate +async fn report_weight(mut nau: impl Nau, wrap: impl Fn(u32) -> Reading, publish: &Queues) { const MAX_INTERVAL: Duration = Duration::from_secs(5); let mut prev_weight = u32::MAX; - let mut last_lux = Instant::now(); + let mut reported_at = Instant::now(); // todo!("reinit devices after error"); loop { Timer::after_millis(100).await; let weight = match nau.try_measure().await { Ok(lux) => lux, - Err(err) if last_lux.elapsed() > MAX_INTERVAL => { + Err(err) if reported_at.elapsed() > MAX_INTERVAL => { publish.queue_error(err); continue; } @@ -70,16 +87,16 @@ async fn report_weight(mut nau: Nau7802Driver<'_>, publish: &Queues) { }; if sig_weight_diff(prev_weight, weight) { - publish.send_p2(Reading::WeightLeft(weight)); - } else if last_lux.elapsed() > MAX_INTERVAL { - publish.send_p1(Reading::WeightLeft(weight)); + publish.send_p2(wrap(weight)); + } else if reported_at.elapsed() > MAX_INTERVAL { + publish.send_p1(wrap(weight)); } else { yield_now().await; continue; }; prev_weight = weight; - last_lux = Instant::now(); + reported_at = Instant::now(); } } @@ -121,8 +138,9 @@ pub struct ButtonInputs { pub lower_outer: ExtiInput<'static>, } -pub async fn read( +pub(crate) async fn read( max44: Max44Driver<'_>, + nau_right: Nau7802DriverBlocking<'_>, nau_left: Nau7802Driver<'_>, /*inputs: ButtonInputs,*/ publish: &Queues, ) { @@ -141,7 +159,7 @@ pub async fn read( // ); let watch_lux = report_lux(max44, publish); - let report_weight = report_weight(nau_left, publish); - join::join(watch_lux, report_weight).await; - // join::join3(watch_buttons_1, watch_buttons_2, watch_lux).await; + let report_right_weight = report_weight(nau_right, Reading::WeightRight, publish); + let report_left_weight = report_weight(nau_left, Reading::WeightLeft, publish); + join::join3(report_left_weight, report_right_weight, watch_lux).await; } diff --git a/sensor-nodes/bed-sensors/src/sensors/retry.rs b/sensor-nodes/bed-sensors/src/sensors/retry.rs index e509fbb5..09b73eb5 100644 --- a/sensor-nodes/bed-sensors/src/sensors/retry.rs +++ b/sensor-nodes/bed-sensors/src/sensors/retry.rs @@ -1,7 +1,7 @@ use bosch_bme680::Bme680; use embassy_embedded_hal::shared_bus; use embassy_stm32::i2c::I2c; -use embassy_stm32::mode::Async; +use embassy_stm32::mode::{Async, Blocking}; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; use embassy_time::{Delay, Timer}; @@ -10,11 +10,14 @@ use nau7802_async::Nau7802; use sht31::mode::SingleShot; use sht31::SHT31; -use super::concrete_types::ConcreteSharedI2c; +use super::concrete_types::{ConcreteBlockingI2c, ConcreteSharedI2c}; +use super::I2cWrapper; use crate::error_cache::SensorError; mod reinit_on_error; -pub use reinit_on_error::{Bme680Driver, Max44Driver, Nau7802Driver, Sht31Driver}; +pub use reinit_on_error::{ + Bme680Driver, Max44Driver, Nau7802Driver, Nau7802DriverBlocking, Sht31Driver, +}; mod retry_init; pub use retry_init::Sps30Driver; @@ -104,6 +107,25 @@ impl<'a> ReInitableDriver for Nau7802, Delay> { } } +impl<'a> ReInitableDriver for Nau7802, Delay> { + type Parts = &'a I2cWrapper>; + type Measurement = u32; + + async fn init(parts: Self::Parts) -> Result { + let shared_i2c = parts; + // wrap these two into something returning Ok or Err + // then make it a generic arg, maybe Driverfactory::init + let driver = Nau7802::new(shared_i2c, Delay) + .await + .map_err(SensorError::Nau7802Right)?; + Ok(driver) + } + + async fn measure(&mut self) -> Result { + self.read().await.map_err(SensorError::Nau7802Right) + } +} + /// a driver that can be re-initialized from copyable parts pub trait ReInitableDriver: Sized { type Parts: Clone; diff --git a/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs b/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs index d0c3bf79..831765a1 100644 --- a/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs +++ b/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs @@ -9,7 +9,9 @@ use sht31::SHT31; use super::super::concrete_types::ConcreteSharedI2c; use super::ReInitableDriver; use crate::error_cache::Error; +use crate::sensors::concrete_types::ConcreteBlockingI2c; +pub type Nau7802DriverBlocking<'a> = ReInitOnErrorDriver, Delay>>; pub type Nau7802Driver<'a> = ReInitOnErrorDriver, Delay>>; pub type Max44Driver<'a> = ReInitOnErrorDriver>>; pub type Bme680Driver<'a> = ReInitOnErrorDriver, Delay>>; @@ -103,7 +105,7 @@ async fn advance_state( } Err(err) => { // drivers might contain blocking code in their - // error path, this makes sure the executor + // error path, this makes sure the executor // will not block on retrying. embassy_time::Timer::after_millis(250).await; let new_state = State::Uninit; From 4e6edfabfb905cc38737b2951e31972c4024eb72 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 2 Sep 2024 15:37:07 +0200 Subject: [PATCH 220/687] replace each service client/server infra with new rpc crate --- Cargo.lock | 36 ++-- crates/data-server/Cargo.toml | 3 +- crates/data-server/src/api.rs | 12 +- crates/data-server/src/api/client.rs | 135 ++---------- crates/data-server/src/server.rs | 10 +- crates/data-server/src/server/affector.rs | 42 ++-- crates/data-server/src/server/client.rs | 212 +++++++------------ crates/data-server/src/server/data_source.rs | 22 +- crates/data-server/src/server/subscribe.rs | 32 +-- crates/data-store/Cargo.toml | 4 +- crates/data-store/src/api.rs | 3 - crates/data-store/src/api/client.rs | 89 ++------ crates/data-store/src/server/clients.rs | 124 ++--------- crates/data-store/src/server/db.rs | 11 +- crates/log-store/src/api/client.rs | 16 -- crates/log-store/src/server/clients.rs | 22 +- crates/rpc/src/client.rs | 75 ++++++- crates/rpc/src/lib.rs | 40 +++- crates/rpc/src/server.rs | 75 +++++-- 19 files changed, 398 insertions(+), 565 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b5ddaef5..3f046636 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -856,10 +856,9 @@ dependencies = [ "color-eyre", "futures", "futures-concurrency", - "governor", "protocol", - "ratelimited-logger", "reserve-port", + "rpc", "serde", "slotmap", "thiserror", @@ -882,20 +881,18 @@ dependencies = [ "data-server", "futures", "futures-concurrency", - "governor", "hdrhistogram", "jiff", "nucleo-matcher", "num", "protocol", "reserve-port", + "rpc", "serde", "smallvec 2.0.0-alpha.7", "temp-dir", "thiserror", "tokio", - "tokio-serde", - "tokio-util", "tracing", "tracing-error", "tracing-subscriber", @@ -2024,22 +2021,19 @@ dependencies = [ "data-server", "futures", "futures-concurrency", - "governor", "hdrhistogram", "heapless 0.8.0", "jiff", "nucleo-matcher", "num", "protocol", - "ratelimited-logger", "reserve-port", + "rpc", "serde", "smallvec 2.0.0-alpha.7", "temp-dir", "thiserror", "tokio", - "tokio-serde", - "tokio-util", "tracing", "tracing-error", "tracing-subscriber", @@ -2910,6 +2904,22 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "rpc" +version = "0.1.0" +dependencies = [ + "color-eyre", + "futures", + "governor", + "ratelimited-logger", + "serde", + "thiserror", + "tokio", + "tokio-serde", + "tokio-util", + "tracing", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -3032,18 +3042,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.208" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.208" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index 78427bbe..1131b617 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -15,7 +15,7 @@ color-eyre = { workspace = true } tracing = { workspace = true } tracing-error = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } -ratelimited-logger = { workspace = true } +rpc = { workspace = true } protocol = { workspace = true, features = ["alloc", "thiserror"] } tokio = { workspace = true, features = ["rt", "macros", "net", "sync", "io-util"] } @@ -27,7 +27,6 @@ tokio-util = { version = "0.7.11", features = ["codec"] } serde = { version = "1.0.208", features = ["derive"] } futures-concurrency = "7.6.1" slotmap = "1.0.7" -governor = "0.6.3" [dev-dependencies] reserve-port = "2" diff --git a/crates/data-server/src/api.rs b/crates/data-server/src/api.rs index e1527412..b4388d43 100644 --- a/crates/data-server/src/api.rs +++ b/crates/data-server/src/api.rs @@ -1,5 +1,3 @@ -use std::time::Duration; - use serde::{Deserialize, Serialize}; pub mod client; @@ -12,7 +10,6 @@ pub use client::Subscribed as SubscribedClient; pub enum Request { Handshake { name: String }, Actuate(protocol::Affector), - Subscribe, ListAffectors, } @@ -29,6 +26,11 @@ pub enum Response { #[derive(Debug, Clone, Serialize, Deserialize)] pub enum SubMessage { Reading(protocol::Reading), + // an affector was moved/updated + AffectorControlled { + affector: protocol::Affector, + controlled_by: String, + }, ErrorReport(Box), } @@ -43,7 +45,7 @@ pub enum AffectorError { pub struct SubscribeError; #[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)] -#[error("placeholder")] pub enum ServerError { - TooManyRequests(Duration), + #[error("Could not activate affector")] + FailedToSpread, } diff --git a/crates/data-server/src/api/client.rs b/crates/data-server/src/api/client.rs index b0b68420..d0d0e637 100644 --- a/crates/data-server/src/api/client.rs +++ b/crates/data-server/src/api/client.rs @@ -1,14 +1,5 @@ -use std::net::SocketAddr; -use std::time::Duration; - -use futures::SinkExt; -use tokio::net::TcpStream; -use tokio::time::error::Elapsed; -use tokio::time::timeout_at; -use tokio::time::Instant; -use tokio_serde::formats::Bincode; -use tokio_stream::StreamExt; -use tokio_util::codec::{Framed, LengthDelimitedCodec}; +use rpc::client::RpcClient; +use tokio::net::ToSocketAddrs; use super::AffectorError; use super::Request; @@ -20,72 +11,15 @@ use super::SubscribeError; pub(crate) mod reconnecting; #[derive(Debug)] -pub struct Client { - stream: tokio_serde::Framed< - Framed, - Response, - Request, - Bincode, - >, -} +pub struct Client(rpc::client::RpcClient); impl Client { - pub async fn connect(addr: impl Into, name: String) -> Result { - let stream = TcpStream::connect(addr.into()) - .await - .map_err(ConnectError::Io)?; - - let length_delimited = Framed::new( - stream, - LengthDelimitedCodec::builder() - .max_frame_length(1024) - .new_codec(), - ); - - let mut stream = tokio_serde::Framed::new(length_delimited, Bincode::default()); - stream - .send(Request::Handshake { name }) - .await - .map_err(ConnectError::Sending)?; - - match tokio::time::timeout(Duration::from_secs(2), stream.try_next()).await { - Ok(Ok(Some(Response::Handshake))) => Ok(Self { stream }), - Ok(Ok(Some(Response::Error(e)))) => Err(ConnectError::ServerError(e)), - Ok(Ok(Some(other))) => unreachable!( - "Server should return handshake response or error after sending \ - first handshake, got impossible response: {other:?}" - ), - Ok(Ok(None)) => Err(ConnectError::Closed), - Ok(Err(e)) => Err(ConnectError::Receiving(e)), - Err(_) => Err(ConnectError::Timeout), - } - } - - async fn send_receive( - &mut self, - request: Request, - ) -> Result> { - fn send_timeout_err(_: Elapsed) -> Error { - Error::Sending(std::io::Error::new(std::io::ErrorKind::TimedOut, "")) - } - fn receive_timeout_err(_: Elapsed) -> Error { - Error::Receiving(std::io::Error::new(std::io::ErrorKind::TimedOut, "")) - } - - let deadline = Instant::now() + Duration::from_secs(5); - timeout_at(deadline, self.stream.send(request)) - .await - .map_err(send_timeout_err)? - .map_err(Error::Sending)?; - match timeout_at(deadline, self.stream.try_next()) - .await - .map_err(receive_timeout_err)? - .map_err(Error::Receiving)? - { - Some(Response::Error(e)) => Err(Error::Server(e)), - Some(response) => Ok(response), - None => Err(Error::ConnectionClosed), - } + pub async fn connect( + addr: impl ToSocketAddrs, + name: String, + ) -> Result { + let rpc_client = RpcClient::connect(addr, name).await?; + Ok(Self(rpc_client)) } pub async fn actuate_affector( @@ -93,9 +27,8 @@ impl Client { affector: protocol::Affector, ) -> Result<(), Error> { let request = Request::Actuate(affector); - match self.send_receive(request.clone()).await { - Ok(Response::Actuate(res)) => res.map_err(Error::Request), - Err(err) => Err(err), + match self.0.send_receive(request.clone()).await? { + Response::Actuate(res) => res.map_err(Error::Request), response => Err(Error::IncorrectResponse { request: format!("{request:?}"), response: format!("{response:?}"), @@ -107,9 +40,8 @@ impl Client { &mut self, ) -> Result, Error> { let request = Request::ListAffectors; - match self.send_receive(request.clone()).await { - Ok(Response::ListAffectors(list)) => Ok(list), - Err(err) => Err(err), + match self.0.send_receive(request.clone()).await? { + Response::ListAffectors(list) => Ok(list), response => Err(Error::IncorrectResponse { request: format!("{request:?}"), response: format!("{response:?}"), @@ -118,15 +50,8 @@ impl Client { } pub async fn subscribe(mut self) -> Result> { - let request = Request::Subscribe; - match self.send_receive(request.clone()).await { - Ok(Response::Subscribe) => Ok(Subscribed(self)), - Err(err) => Err(err), - response => Err(Error::IncorrectResponse { - request: format!("{request:?}"), - response: format!("{response:?}"), - }), - } + self.0.subscribe().await?; + Ok(Subscribed(self)) } } @@ -135,13 +60,7 @@ pub struct Subscribed(Client); impl Subscribed { pub async fn next(&mut self) -> Result> { - let received = self - .0 - .stream - .try_next() - .await - .map_err(Error::Receiving)? - .ok_or(Error::ConnectionClosed)?; + let received = self.0 .0.next().await?; if let Response::SubUpdate(update) = received { Ok(update) @@ -154,22 +73,6 @@ impl Subscribed { } } -#[derive(Debug, thiserror::Error)] -pub enum ConnectError { - #[error("Error while connecting to data server: {0}")] - Io(std::io::Error), - #[error("Could not send handshake: {0}")] - Sending(std::io::Error), - #[error("Timed out waiting for ")] - Timeout, - #[error("Server unexpectedly closed the connection")] - Closed, - #[error("Server send back an error: {0:?}")] - ServerError(ServerError), - #[error("Could not receive server response: {0:?}")] - Receiving(std::io::Error), -} - #[derive(Debug, thiserror::Error)] pub enum Error { #[error("Got unexpected response response to request {request:?}")] @@ -181,7 +84,7 @@ pub enum Error { #[error("General error while processing request")] Server(ServerError), #[error("Server ran into an specific error with our request: {0}")] - Request(#[from] T), - #[error("Server closed connection before it awnserd")] - ConnectionClosed, + Request(T), + #[error("Error while communicating with server: {0}")] + Comms(#[from] rpc::client::RpcError), } diff --git a/crates/data-server/src/server.rs b/crates/data-server/src/server.rs index a5986d76..3ec5c203 100644 --- a/crates/data-server/src/server.rs +++ b/crates/data-server/src/server.rs @@ -5,9 +5,9 @@ use tokio::sync::mpsc; use tokio_serde::formats::Bincode; use tokio_util::codec::{Framed, LengthDelimitedCodec}; +mod affector; pub mod client; mod data_source; -mod affector; mod subscribe; pub use affector::Registar as AffectorRegistar; @@ -26,6 +26,12 @@ pub type Conn = tokio_serde::Framed< #[derive(Debug)] pub enum Event { - NewSub { tx: mpsc::Sender }, + NewSub { + tx: mpsc::Sender, + }, NewReading(Result>), + AffectorControlled { + affector: protocol::Affector, + controlled_by: String, + }, } diff --git a/crates/data-server/src/server/affector.rs b/crates/data-server/src/server/affector.rs index ffbd836f..f9b83eec 100644 --- a/crates/data-server/src/server/affector.rs +++ b/crates/data-server/src/server/affector.rs @@ -1,4 +1,3 @@ -use std::collections::HashSet; use std::sync::{Arc, Mutex}; use color_eyre::Result; @@ -15,7 +14,17 @@ use tracing::warn; #[derive(Debug)] pub(crate) struct Registration { tx: tokio::sync::mpsc::Sender, - controls: HashSet, + controls: Vec, +} + +impl Registration { + fn update(&mut self, new: Affector) { + if let Some(curr) = self.controls.iter_mut().find(|a| a.is_same_as(&new)) { + *curr = new; + } else { + self.controls.push(new); + } + } } #[derive(Debug, Clone, Default)] @@ -26,16 +35,16 @@ impl Registar { let mut this = self.0.lock().expect("nothing should panic"); this.insert(Registration { tx, - controls: HashSet::new(), + controls: Vec::new(), }) } - fn update_affectors(&self, key: DefaultKey, list: &[Affector]) { + fn update_affectors(&self, key: DefaultKey, affector: Affector) { let mut this = self.0.lock().expect("nothing should panic"); let registration = this .get_mut(key) .expect("items are removed when track_and_control_affectors only"); - registration.controls.extend(list.iter()); + registration.update(affector) } fn remove(&self, key: DefaultKey) { @@ -43,14 +52,15 @@ impl Registar { this.remove(key).expect("things are only removed once"); } - pub(crate) fn activate(&self, affector: Affector) -> Result<(), Offline> { - let this = self.0.lock().expect("nothing should panic"); + pub(crate) fn activate(&self, order: Affector) -> Result<(), Offline> { + let mut this = self.0.lock().expect("nothing should panic"); for possible_controller in this - .iter() + .iter_mut() .map(|(_, reg)| reg) - .filter(|reg| reg.controls.contains(&affector)) + .filter(|reg| reg.controls.contains(&order)) { - if possible_controller.tx.try_send(affector).is_ok() { + if possible_controller.tx.try_send(order).is_ok() { + possible_controller.update(order); return Ok(()); } } @@ -71,7 +81,7 @@ pub struct Offline; pub(super) async fn track_and_control_affectors( mut writer: OwnedWriteHalf, - mut update_from_same_node: Receiver, + mut update_from_same_node: Receiver, registar: Registar, ) { let (tx, mut rx) = tokio::sync::mpsc::channel(10); @@ -87,8 +97,8 @@ pub(super) async fn track_and_control_affectors( let res = (new_update, new_order).race().await; match res { Res::Disconnected => break, - Res::Update(device) => { - registar.update_affectors(key, device.info().affectors); + Res::Update(affector) => { + registar.update_affectors(key, affector); } Res::Order(affector) => { let buf = affector.encode(); @@ -105,14 +115,14 @@ pub(super) async fn track_and_control_affectors( enum Res { Disconnected, - Update(protocol::Device), + Update(protocol::Affector), Order(protocol::Affector), } impl Res { - fn from(val: Option) -> Self { + fn from(val: Option) -> Self { match val { - Some(device) => Self::Update(device), + Some(affector) => Self::Update(affector), None => Self::Disconnected, } } diff --git a/crates/data-server/src/server/client.rs b/crates/data-server/src/server/client.rs index 41d7069b..db6db3d9 100644 --- a/crates/data-server/src/server/client.rs +++ b/crates/data-server/src/server/client.rs @@ -1,152 +1,104 @@ +use futures::{stream, Stream}; use std::net::SocketAddr; -use std::num::NonZeroU32; -use std::time::Duration; - -use color_eyre::eyre::Context; -use futures::SinkExt; -use governor::clock::{Clock, DefaultClock}; -use governor::{Quota, RateLimiter}; -use ratelimited_logger::RateLimitedLogger; -use tokio::net::{TcpListener, TcpStream}; use tokio::sync::mpsc; -use tokio_serde::formats::Bincode; -use tokio_stream::StreamExt; -use tokio_util::codec::{Framed, LengthDelimitedCodec}; - -use color_eyre::{Result, Section}; -use tracing::warn; +use color_eyre::Result; use crate::api::AffectorError; use crate::api::{self, ServerError}; -use super::{affector::Offline, affector::Registar, Conn, Event}; - -async fn handle_client_inner( - conn: &mut Conn, - new_subscribers: &mut mpsc::Sender, - affectors: &Registar, -) -> color_eyre::Result<()> { - let request = conn - .try_next() - .await - .wrap_err("Could not get next client request")?; - let Some(request) = request else { - return Ok(()); - }; +use super::{affector::Offline, affector::Registar, Event}; - let response = match &request { - api::Request::Handshake { .. } => { - unreachable!("handshake only takes place during connection") - } - api::Request::Actuate(affector) => match affectors.activate(*affector) { - Ok(()) => api::Response::Actuate(Ok(())), - Err(Offline) => api::Response::Actuate(Err(AffectorError::Offline)), - }, - api::Request::Subscribe => api::Response::Subscribe, - api::Request::ListAffectors => api::Response::ListAffectors(affectors.list()), - }; +#[derive(Debug, Clone)] +struct SubHandler { + new_events: mpsc::Sender, +} - conn.send(response) +async fn do_setup( + new_events: mpsc::Sender, +) -> impl Stream + Send + 'static { + let (tx, rx) = tokio::sync::mpsc::channel(100); + new_events + .send(Event::NewSub { tx }) .await - .wrap_err("failed to send response to client")?; - - if let api::Request::Subscribe = request { - let (tx, rx) = tokio::sync::mpsc::channel(100); - new_subscribers - .send(Event::NewSub { tx }) - .await - .wrap_err("Could not register the client as subscriber")?; - return Err(crate::server::subscribe::handle_subscriber(conn, rx) + .expect("Events processor (rx) should never stop"); + stream::unfold(rx, |mut rx| async move { + rx.recv() .await - .wrap_err("Somewhing went wrong sending updates to the client")); - } - - Ok(()) + .map(api::Response::SubUpdate) + .map(|yielded| (yielded, rx)) + }) } -async fn handle_client( - mut conn: Conn, - id: String, - mut new_subscribers: mpsc::Sender, - affectors: Registar, -) { - loop { - if let Err(e) = handle_client_inner(&mut conn, &mut new_subscribers, &affectors).await { - warn!("Error while handling client {id}: {e:?}"); - } +impl rpc::SubscriberHandler for SubHandler { + type Update = crate::api::Response; + + fn setup( + &mut self, + ) -> impl std::future::Future< + Output = impl futures::prelude::Stream + Send + 'static, + > + Send + + 'static { + do_setup(self.new_events.clone()) } } -pub async fn handle(addr: SocketAddr, tx: mpsc::Sender, affectors: Registar) -> Result<()> { - let quota = Quota::with_period(Duration::from_secs(1)) - .unwrap() - .allow_burst(NonZeroU32::new(5).unwrap()); - let limiter = RateLimiter::keyed(quota); - let listener = TcpListener::bind(addr) - .await - .wrap_err("Could not start receiving updates") - .with_note(|| format!("trying to listen on: {addr}"))?; - let mut logger = RateLimitedLogger::new(); - - loop { - let (socket, source) = match listener.accept().await { - Err(e) => { - logger.warn(&format!("client could not connect: {e}")); - continue; - } - Ok(res) => res, - }; - - let Some((mut conn, name)) = handshake(socket, source, &mut logger).await else { - continue; - }; - - if let Err(allowed_again) = limiter.check_key(&(source.ip(), name.clone())) { - let allowed_in = allowed_again.wait_time_from(DefaultClock::default().now()); - let _ignore_err = conn.send(api::Response::Error(ServerError::TooManyRequests( - allowed_in, - ))); - continue; - } - - let Ok(()) = conn.send(api::Response::Handshake).await else { - continue; - }; +pub async fn handle( + addr: SocketAddr, + tx: mpsc::Sender, + affectors: Registar, +) -> color_eyre::Result<()> { + let port = addr.port(); + let handler = SubHandler { + new_events: tx.clone(), + }; + rpc::server::run( + port, + move |req, name| { + let tx = tx.clone(); + let affectors = affectors.clone(); + perform_request(req, name.to_owned(), tx, affectors) + }, + Some(handler), + ) + .await +} - let id = format!("{name}@{source}"); - tokio::task::spawn(handle_client(conn, id, tx.clone(), affectors.clone())); +async fn perform_request( + request: api::Request, + client_name: String, + new_event: mpsc::Sender, + affectors: Registar, +) -> api::Response { + match perform_request_inner(request, client_name, new_event, affectors).await { + Ok(response) => response, + Err(error) => api::Response::Error(error), } } -#[tracing::instrument(skip(stream, logger))] -async fn handshake( - stream: TcpStream, - source: SocketAddr, - logger: &mut RateLimitedLogger, -) -> Option<(Conn, String)> { - let length_delimited = Framed::new( - stream, - LengthDelimitedCodec::builder() - .max_frame_length(1024) - .new_codec(), - ); - let mut stream: tokio_serde::Framed<_, api::Request, api::Response, _> = - tokio_serde::Framed::new(length_delimited, Bincode::default()); - - match stream.try_next().await { - Ok(Some(api::Request::Handshake { name })) => { - logger.info(&format!("Client {name} connected from {source}")); - return Some((stream, name)); +async fn perform_request_inner( + request: api::Request, + client_name: String, + new_event: mpsc::Sender, + affectors: Registar, +) -> Result { + Ok(match request { + api::Request::Handshake { .. } => { + unreachable!("handshake only takes place during connection") } - Ok(Some(other)) => logger.warn(&format!( - "client tried to connected without handshake, it send: {other:?}" - )), - Ok(None) => logger.warn("client closed connection immediately"), - Err(e) => logger.warn(&format!( - "connection or decoding issue while receiving handshake: {e:?}" - )), - } - - None + api::Request::Actuate(affector) => match affectors.activate(affector) { + Ok(()) => { + new_event + .send(Event::AffectorControlled { + affector, + controlled_by: client_name.to_owned(), + }) + .await + .map_err(|_| ServerError::FailedToSpread)?; + api::Response::Actuate(Ok(())) + } + Err(Offline) => api::Response::Actuate(Err(AffectorError::Offline)), + }, + api::Request::ListAffectors => api::Response::ListAffectors(affectors.list()), + }) } diff --git a/crates/data-server/src/server/data_source.rs b/crates/data-server/src/server/data_source.rs index 1a77acea..bf1cbc9e 100644 --- a/crates/data-server/src/server/data_source.rs +++ b/crates/data-server/src/server/data_source.rs @@ -70,7 +70,7 @@ async fn handle_node(stream: TcpStream, queue: Sender, registar: Registar async fn receive_and_spread_updates( mut reader: BufReader, queue: Sender, - affectors: Sender, + affectors: Sender, ) { let mut buf = Vec::new(); @@ -84,12 +84,8 @@ async fn receive_and_spread_updates( }; match msg { - protocol::Msg::Readings(readings) => { - for value in readings.values { - affectors - .send(value.device()) - .await - .expect("fn track_and_control_affectors should not end"); + protocol::Msg::Readings(list) => { + for value in list.values { queue .send(Event::NewReading(Ok(value))) .await @@ -97,16 +93,20 @@ async fn receive_and_spread_updates( } } protocol::Msg::ErrorReport(report) => { - affectors - .send(report.error.device()) - .await - .expect("fn track_and_control_affectors should not end"); let boxed = Box::new(report.error); queue .send(Event::NewReading(Err(boxed))) .await .expect("fn spread_updates should stay running"); } + protocol::Msg::AffectorList(list) => { + for affector_state in list.values { + affectors + .send(affector_state) + .await + .expect("fn track_and_control_affectors should not end") + } + } } } // loop } diff --git a/crates/data-server/src/server/subscribe.rs b/crates/data-server/src/server/subscribe.rs index ab3d65a4..1aa9f5a1 100644 --- a/crates/data-server/src/server/subscribe.rs +++ b/crates/data-server/src/server/subscribe.rs @@ -1,32 +1,11 @@ -use std::time::Duration; - -use color_eyre::eyre::eyre; -use futures::SinkExt; use std::mem; use tokio::sync::mpsc; -use tokio::time::timeout; use tracing::debug; use color_eyre::Result; -use super::{Conn, Event}; -use crate::api::{Response, SubMessage}; - -pub async fn handle_subscriber( - sub: &mut Conn, - mut rx: mpsc::Receiver, -) -> color_eyre::Report { - loop { - let update = rx.recv().await.expect("updates always keep coming"); - let message = Response::SubUpdate(update); - if timeout(Duration::from_secs(2), sub.send(message)) - .await - .is_err() - { - return eyre!("Timed out while sending update"); - } - } -} +use super::Event; +use crate::api::SubMessage; pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { let mut subscribers = Vec::new(); @@ -45,6 +24,13 @@ pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { } Event::NewReading(Ok(reading)) => SubMessage::Reading(reading), Event::NewReading(Err(err)) => SubMessage::ErrorReport(err), + Event::AffectorControlled { + affector, + controlled_by, + } => SubMessage::AffectorControlled { + affector, + controlled_by, + }, }; let subs = mem::take(&mut subscribers); diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index 616f8d50..f20ce859 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -18,6 +18,7 @@ tracing = { workspace = true } tracing-error = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } jiff = { workspace =true, features = ["serde"] } +rpc = { workspace = true } protocol = { workspace = true, features = ["alloc", "thiserror"] } data-server = { workspace = true } @@ -25,15 +26,12 @@ data-server = { workspace = true } byteseries = { workspace = true } tokio = { workspace = true, features = ["fs", "net", "rt-multi-thread", "sync"] } futures-concurrency = "7.6.1" -tokio-serde = { version = "0.9.0", features = ["bincode"] } -tokio-util = { version = "0.7.11", features = ["codec"] } serde = { version = "1.0.203", features = ["derive"] } thiserror = { workspace = true } futures = "0.3.30" smallvec = "2.0.0-alpha.6" num = "0.4.3" hdrhistogram = "7.5.4" -governor = "0.6.3" [dev-dependencies] futures-concurrency = "7.6.1" diff --git a/crates/data-store/src/api.rs b/crates/data-store/src/api.rs index ab49d733..527c6d9a 100644 --- a/crates/data-store/src/api.rs +++ b/crates/data-store/src/api.rs @@ -7,9 +7,6 @@ use serde::{Deserialize, Serialize}; pub mod client; pub use client::Client; -// 8 MB -pub(crate) const MAX_PACKAGE_SIZE: usize = 8 * 1024 * 1024; - #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) enum Request { Handshake { diff --git a/crates/data-store/src/api/client.rs b/crates/data-store/src/api/client.rs index fbe1a563..58256a17 100644 --- a/crates/data-store/src/api/client.rs +++ b/crates/data-store/src/api/client.rs @@ -1,95 +1,30 @@ -use std::time::Duration; - -use futures::{SinkExt, TryStreamExt}; -use tokio::net::TcpStream; +use rpc::client::RpcClient; use tokio::net::ToSocketAddrs; -use tokio_serde::formats::Bincode; -use tokio_util::codec::{Framed, LengthDelimitedCodec}; -use super::Request; use super::Response; -pub struct Client { - stream: tokio_serde::Framed< - Framed, - Response, - super::Request, - Bincode, - >, -} - -#[derive(Debug, thiserror::Error)] -pub enum ConnectError { - #[error("Error while connecting to data server: {0}")] - Io(std::io::Error), - #[error("Could not send handshake: {0}")] - Sending(std::io::Error), - #[error("Timed out waiting for ")] - Timeout, - #[error("Server unexpectedly closed the connection")] - Closed, - #[error("Server send back an error: {0:?}")] - ServerError(super::ServerError), - #[error("Could not receive server response: {0:?}")] - Receiving(std::io::Error), -} +pub struct Client(rpc::client::RpcClient); #[derive(Debug, thiserror::Error)] pub enum Error { #[error("Got unexpected response response to request {request:?}")] IncorrectResponse { request: String, response: String }, - #[error("Error while sending request: {0}")] - Sending(std::io::Error), - #[error("Error while sending request: {0}")] - Receiving(std::io::Error), - #[error("Server ran into an error while processing our request: {0}")] - Server(super::ServerError), - #[error("Server closed connection before it awnserd")] - ConnectionClosed, + #[error("Error while communicating with server: {0}")] + Comms(#[from] rpc::client::RpcError), } impl Client { - pub async fn connect(addr: impl ToSocketAddrs, name: String) -> Result { - let stream = TcpStream::connect(addr).await.map_err(ConnectError::Io)?; - - let length_delimited = Framed::new( - stream, - LengthDelimitedCodec::builder() - .max_frame_length(super::MAX_PACKAGE_SIZE) - .new_codec(), - ); - - let mut stream = tokio_serde::Framed::new(length_delimited, Bincode::default()); - stream - .send(Request::Handshake { name }) - .await - .map_err(ConnectError::Sending)?; - - match tokio::time::timeout(Duration::from_secs(2), stream.try_next()).await { - Ok(Ok(Some(Response::Handshake))) => Ok(Self { stream }), - Ok(Ok(Some(Response::Error(e)))) => Err(ConnectError::ServerError(e)), - Ok(Ok(Some(other))) => unreachable!( - "Server should return handshake response or error after sending \ - first handshake, got impossible response: {other:?}" - ), - Ok(Ok(None)) => Err(ConnectError::Closed), - Ok(Err(e)) => Err(ConnectError::Receiving(e)), - Err(_) => Err(ConnectError::Timeout), - } - } - - async fn send_receive(&mut self, request: super::Request) -> Result { - self.stream.send(request).await.map_err(Error::Sending)?; - match self.stream.try_next().await.map_err(Error::Receiving)? { - Some(Response::Error(e)) => Err(Error::Server(e)), - Some(response) => Ok(response), - None => Err(Error::ConnectionClosed), - } + pub async fn connect( + addr: impl ToSocketAddrs, + name: String, + ) -> Result { + let rpc_client = RpcClient::connect(addr, name).await?; + Ok(Self(rpc_client)) } pub async fn list_data(&mut self) -> Result, Error> { let request = super::Request::ListData; - match self.send_receive(request.clone()).await? { + match self.0.send_receive(request.clone()).await? { Response::ListData(list) => Ok(list), response => Err(Error::IncorrectResponse { request: format!("{request:?}"), @@ -111,7 +46,7 @@ impl Client { end, n, }; - match self.send_receive(request.clone()).await? { + match self.0.send_receive(request.clone()).await? { Response::GetData { time, data } => Ok((time, data)), response => Err(Error::IncorrectResponse { request: format!("{request:?}"), diff --git a/crates/data-store/src/server/clients.rs b/crates/data-store/src/server/clients.rs index 45988d3a..54c774dd 100644 --- a/crates/data-store/src/server/clients.rs +++ b/crates/data-store/src/server/clients.rs @@ -1,118 +1,28 @@ -use std::net::SocketAddr; -use std::num::NonZeroU32; -use std::time::Duration; - -use color_eyre::eyre::Context; -use color_eyre::Section; -use futures::{SinkExt, TryStreamExt}; -use governor::clock::{Clock, DefaultClock}; -use governor::{Quota, RateLimiter}; -use tokio::net::{TcpListener, TcpStream}; -use tokio_serde::formats::Bincode; -use tokio_util::codec::{Framed, LengthDelimitedCodec}; -use tracing::{debug, error, info, warn}; - use super::db::Data; use crate::api::{self, ServerError}; -type Conn = tokio_serde::Framed< - Framed, - api::Request, - api::Response, - Bincode, ->; - pub(crate) async fn handle(port: u16, data: Data) -> color_eyre::Result<()> { - let quota = Quota::with_period(Duration::from_secs(1)) - .unwrap() - .allow_burst(NonZeroU32::new(5u32).unwrap()); - let limiter = RateLimiter::keyed(quota); - let listener = TcpListener::bind(format!("0.0.0.0:{port}")) - .await - .wrap_err("Could not bind to address") - .with_note(|| format!("port: {port}"))?; - - loop { - let (socket, source) = match listener.accept().await { - Err(e) => { - warn!("client could not connect: {e}"); - continue; - } - Ok(res) => res, - }; - - let Some((mut conn, name)) = handshake_and_log(socket, source).await else { - continue; - }; - - if let Err(allowed_again) = limiter.check_key(&(source.ip(), name.clone())) { - let allowed_in = allowed_again.wait_time_from(DefaultClock::default().now()); - let _ignore_err = conn.send(api::Response::Error(ServerError::TooManyRequests( - allowed_in, - ))); - continue; - } - - info!("Client {name} connected from {source}"); - let Ok(()) = conn.send(api::Response::Handshake).await else { - continue; - }; - - tokio::task::spawn(handle_client(conn, data.clone())); - } + rpc::server::run( + port, + move |req, _| { + let data = data.clone(); + perform_request(req, data) + }, + Option::>::None, + ) + .await } - -async fn handshake_and_log(stream: TcpStream, source: SocketAddr) -> Option<(Conn, String)> { - let length_delimited = Framed::new( - stream, - LengthDelimitedCodec::builder() - .max_frame_length(api::MAX_PACKAGE_SIZE) - .new_codec(), - ); - let mut stream: tokio_serde::Framed<_, api::Request, api::Response, _> = - tokio_serde::Framed::new(length_delimited, Bincode::default()); - - match stream.try_next().await { - Ok(Some(api::Request::Handshake { name })) => { - return Some((stream, name)); - } - Ok(Some(other)) => { - warn!("client from {source} tried to connected without handshake, it send: {other:?}") - } - Ok(None) => warn!("client from {source} closed connection immediately"), - Err(e) => warn!( - "connection or decoding issue while receiving handshake from {source}, error: {e:?}" - ), - } - - None -} - -async fn handle_client(mut conn: Conn, data: Data) { - loop { - let request = match conn.try_next().await { - Ok(Some(request)) => request, - Ok(None) => { - debug!("Connection ended"); - return; - } - Err(e) => { - error!("Could not receive request: {e:?}"); - return; - } - }; - let response = match perform_request(request, &data).await { - Err(err) => api::Response::Error(err), - Ok(r) => r, - }; - if let Err(e) = conn.send(response).await { - error!("Error sending response to client: {e:?}"); - return; - } +async fn perform_request(request: api::Request, data: Data) -> api::Response { + match perform_request_inner(request, data).await { + Ok(resp) => resp, + Err(e) => api::Response::Error(e), } } -async fn perform_request(request: api::Request, data: &Data) -> Result { +async fn perform_request_inner( + request: api::Request, + data: Data, +) -> Result { Ok(match request { api::Request::Handshake { .. } => return Err(ServerError::AlreadyConnected), api::Request::ListData => api::Response::ListData(data.list().await), diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index ab09dbae..ca2b4419 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -22,13 +22,14 @@ pub(crate) async fn run(data_server_addr: SocketAddr, data: Data, data_dir: &Pat let mut recently_logged = (Instant::now(), String::new()); loop { let msg = sub.next().await; - let res = match msg { - SubMessage::Reading(reading) => series::store(&data, &reading, data_dir) - .await - .with_note(|| format!("reading: {reading:?}")), - SubMessage::ErrorReport(_) => Ok(()), + let SubMessage::Reading(reading) = msg else { + continue; }; + let res = series::store(&data, &reading, data_dir) + .await + .with_note(|| format!("reading: {reading:?}")); + const FIVE_MIN: Duration = Duration::from_secs(60 * 5); if let Err(report) = res { let e = format!("got error with report: {report:?}"); diff --git a/crates/log-store/src/api/client.rs b/crates/log-store/src/api/client.rs index 88d81ecd..54b60e7a 100644 --- a/crates/log-store/src/api/client.rs +++ b/crates/log-store/src/api/client.rs @@ -11,22 +11,6 @@ use super::Response; pub struct Client(rpc::client::RpcClient); -#[derive(Debug, thiserror::Error)] -pub enum ConnectError { - #[error("Error while connecting to data server: {0}")] - Io(std::io::Error), - #[error("Could not send handshake: {0}")] - Sending(std::io::Error), - #[error("Timed out waiting for ")] - Timeout, - #[error("Server unexpectedly closed the connection")] - Closed, - #[error("Server send back an error: {0:?}")] - ServerError(super::ServerError), - #[error("Could not receive server response: {0:?}")] - Receiving(std::io::Error), -} - #[derive(Debug, thiserror::Error)] pub enum Error { #[error("Got unexpected response response to request {request:?}")] diff --git a/crates/log-store/src/server/clients.rs b/crates/log-store/src/server/clients.rs index b92eccd4..88b6fe84 100644 --- a/crates/log-store/src/server/clients.rs +++ b/crates/log-store/src/server/clients.rs @@ -2,15 +2,25 @@ use super::db::{Logs, Stats}; use crate::api::{self, ServerError}; pub(crate) async fn handle(port: u16, stats: Stats, logs: Logs) -> color_eyre::Result<()> { - rpc::server::run(port, move |req| { - let stats = stats.clone(); - let logs = logs.clone(); - perform_request(req, stats, logs) - }) + rpc::server::run( + port, + move |req, _| { + let stats = stats.clone(); + let logs = logs.clone(); + perform_request(req, stats, logs) + }, + Option::>::None, + ) .await } -async fn perform_request( +async fn perform_request(request: api::Request, stats: Stats, logs: Logs) -> api::Response { + match perform_request_inner(request, stats, logs).await { + Ok(resp) => resp, + Err(e) => api::Response::Error(e), + } +} +async fn perform_request_inner( request: api::Request, stats: Stats, logs: Logs, diff --git a/crates/rpc/src/client.rs b/crates/rpc/src/client.rs index e61e5a46..ff3580bf 100644 --- a/crates/rpc/src/client.rs +++ b/crates/rpc/src/client.rs @@ -18,7 +18,6 @@ use crate::Response; pub struct RpcClient where - RpcReq: Serialize, RpcResp: Serialize, { stream: tokio_serde::Framed< @@ -29,6 +28,12 @@ where >, } +impl fmt::Debug for RpcClient { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RpcClient").finish() + } +} + #[derive(Debug, thiserror::Error)] pub enum ConnectError { #[error("Error while connecting to server: {0}")] @@ -91,6 +96,58 @@ where } } + pub async fn subscribe(&mut self) -> Result<(), RpcError> { + fn send_timeout_err(_: Elapsed) -> RpcError { + RpcError::Sending(std::io::Error::new(std::io::ErrorKind::TimedOut, "")) + } + fn receive_timeout_err(_: Elapsed) -> RpcError { + RpcError::Receiving(std::io::Error::new(std::io::ErrorKind::TimedOut, "")) + } + + let deadline = Instant::now() + Duration::from_secs(5); + let request = Request::Subscribe; + timeout_at(deadline, self.stream.send(request)) + .await + .map_err(send_timeout_err)? + .map_err(RpcError::Sending)?; + + let response = timeout_at(deadline, self.stream.try_next()) + .await + .map_err(receive_timeout_err)? + .map_err(RpcError::Receiving)? + .ok_or(RpcError::ConnectionClosed)?; + match response { + Response::AlreadyConnected + | Response::RpcResponse(_) + | Response::Update(_) + | Response::TooManyReq { .. } + | Response::HandshakeOk => { + unreachable!("incorrect response to subscribe: {response:?}") + } + Response::SubscribeOk => Ok(()), + } + } + + pub async fn next(&mut self) -> Result { + let received = self + .stream + .try_next() + .await + .map_err(RpcError::Receiving)? + .ok_or(RpcError::ConnectionClosed)?; + + match received { + Response::AlreadyConnected + | Response::RpcResponse(_) + | Response::TooManyReq { .. } + | Response::HandshakeOk + | Response::SubscribeOk => { + unreachable!("incorrect response to get next, are we subscribed?") + } + Response::Update(v) => Ok(v), + } + } + pub async fn send_receive(&mut self, request: RpcReq) -> Result { fn send_timeout_err(_: Elapsed) -> RpcError { RpcError::Sending(std::io::Error::new(std::io::ErrorKind::TimedOut, "")) @@ -109,16 +166,14 @@ where .await .map_err(receive_timeout_err)? .map_err(RpcError::Receiving)? + .ok_or(RpcError::ConnectionClosed)? { - Some(Response::AlreadyConnected) => { - unreachable!("not creating a connection") - } - Some(Response::RpcResponse(v)) => Ok(v), - Some(Response::TooManyReq { .. }) => { - unreachable!("only creating connections is ratelimited") - } - Some(Response::HandshakeOk) => unreachable!("is only send during initial connection"), - None => Err(RpcError::ConnectionClosed), + Response::AlreadyConnected + | Response::Update(_) + | Response::TooManyReq { .. } + | Response::HandshakeOk + | Response::SubscribeOk => unreachable!("only expected after a subscribe"), + Response::RpcResponse(v) => Ok(v), } } } diff --git a/crates/rpc/src/lib.rs b/crates/rpc/src/lib.rs index 527c14cf..ad87484a 100644 --- a/crates/rpc/src/lib.rs +++ b/crates/rpc/src/lib.rs @@ -1,5 +1,8 @@ +use std::future; +use std::marker::PhantomData; use std::time::Duration; +use futures::{stream, Stream}; use serde::{Deserialize, Serialize}; pub mod client; @@ -8,19 +11,52 @@ pub mod server; // 8 MB pub(crate) const MAX_PACKAGE_SIZE: usize = 8 * 1024 * 1024; +pub trait SubscriberHandler: Send + 'static { + type Update; + #[allow(async_fn_in_trait)] + fn setup( + &mut self, + ) -> impl std::future::Future + Send + 'static> + + Send + + 'static; +} + +/// needed (I know ugly) to give the Option::None a complete type +/// for the server::run function (which takes a Option) +#[derive(Debug, Clone)] +pub struct SubscribersUnsupported { + phantom: PhantomData, +} + +impl SubscriberHandler for SubscribersUnsupported { + type Update = Update; + + fn setup( + &mut self, + ) -> impl std::future::Future< + Output = impl futures::prelude::Stream + Send + 'static, + > + Send + + 'static { + future::pending::>() + } +} + #[derive(Debug, Clone, Serialize, Deserialize)] -enum Request { +pub enum Request { Handshake { client_name: String }, + Subscribe, Rpc(R), } #[derive(Debug, Clone, Serialize, Deserialize)] -enum Response +pub enum Response where V: Serialize, { HandshakeOk, + SubscribeOk, AlreadyConnected, TooManyReq { allowed_in: Duration }, RpcResponse(V), + Update(V), } diff --git a/crates/rpc/src/server.rs b/crates/rpc/src/server.rs index 3defc855..217628b8 100644 --- a/crates/rpc/src/server.rs +++ b/crates/rpc/src/server.rs @@ -6,17 +6,18 @@ use std::time::Duration; use color_eyre::eyre::Context; use color_eyre::Section; -use futures::{SinkExt, TryStreamExt}; +use futures::{SinkExt, StreamExt, TryStreamExt}; use governor::clock::{Clock, DefaultClock}; use governor::{Quota, RateLimiter}; use serde::de::DeserializeOwned; use serde::Serialize; use tokio::net::{TcpListener, TcpStream}; +use tokio::pin; use tokio_serde::formats::Bincode; use tokio_util::codec::{Framed, LengthDelimitedCodec}; use ratelimited_logger::{self as rlog, RateLimitedLogger}; -use tracing::{debug, error, info}; +use tracing::{debug, error, info, instrument}; type Conn = tokio_serde::Framed< Framed, @@ -25,14 +26,15 @@ type Conn = tokio_serde::Framed< Bincode, crate::Response>, >; -pub async fn run( +pub async fn run( port: u16, - perform_request: impl Fn(RpcReq) -> Fut + Clone + Send + 'static, + perform_request: impl Fn(RpcReq, &str) -> PerfFut + Clone + Send + 'static, + sub_handler: Option + Clone + Send + 'static>, ) -> color_eyre::Result<()> where RpcReq: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, RpcResp: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, - Fut: Future + Send + 'static, + PerfFut: Future + Send + 'static, { let quota = Quota::with_period(Duration::from_secs(1)) .unwrap() @@ -70,7 +72,12 @@ where continue; }; - tokio::task::spawn(handle_client(conn, perform_request.clone())); + tokio::task::spawn(handle_client( + conn, + name, + perform_request.clone(), + sub_handler.clone(), + )); } } @@ -109,13 +116,18 @@ where } use core::future::Future; -async fn handle_client( + +use crate::SubscriberHandler; +#[instrument(skip(conn, perform_request, sub_handler))] +async fn handle_client( mut conn: Conn, - perform_request: impl Fn(RpcReq) -> Fut + Clone + Send + 'static, + client_name: String, + perform_request: impl Fn(RpcReq, &str) -> PerfFut + Clone + Send + 'static, + mut sub_handler: Option + Send + 'static>, ) where RpcReq: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, RpcResp: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, - Fut: Future + Send + 'static, + PerfFut: Future + Send + 'static, { loop { let request = match conn.try_next().await { @@ -129,15 +141,42 @@ async fn handle_client( return; } }; - let crate::Request::Rpc(rpc_request) = request else { - error!("Handshake request is not allowed after we send back HandshakeOk"); - return; - }; + match request { + crate::Request::Rpc(rpc_request) => { + let response = perform_request(rpc_request, &client_name).await; + if let Err(e) = conn.send(crate::Response::RpcResponse(response)).await { + error!("Error sending response to client: {e:?}"); + return; + } + } + crate::Request::Subscribe => { + if let Some(mut sub_handler) = sub_handler.take() { + let stream = sub_handler.setup().await; + pin!(stream); + if let Err(e) = conn.send(crate::Response::SubscribeOk).await { + error!("Error sending response to client: {e:?}"); + return; + } - let response = perform_request.clone()(rpc_request).await; - if let Err(e) = conn.send(crate::Response::RpcResponse(response)).await { - error!("Error sending response to client: {e:?}"); - return; - } + loop { + let Some(update) = stream.next().await else { + error!("Error subscribe stream should never end"); + return; + }; + if let Err(e) = conn.send(crate::Response::Update(update)).await { + error!("Error sending response to client: {e:?}"); + return; + } + } + } else { + error!("Got subscribe request but no subscribe possible"); + return; + } + } + crate::Request::Handshake { .. } => { + error!("Handshake request only allowed during connect"); + return; + } + }; } } From cdfc1ffbf17f075a7dcfde9135d15bcb27590967 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 2 Sep 2024 15:37:38 +0200 Subject: [PATCH 221/687] add support for controlling affectors --- crates/brain/src/input/sensors.rs | 2 +- crates/protocol/src/affector.rs | 22 ++++++++++++++++++++-- crates/protocol/src/large_bedroom/bed.rs | 6 +++--- crates/protocol/src/msg.rs | 10 ++++++++++ crates/sensor-tui/src/main.rs | 17 +++++++++++++++-- crates/sensor-tui/src/tui/affectors.rs | 4 ++-- 6 files changed, 51 insertions(+), 10 deletions(-) diff --git a/crates/brain/src/input/sensors.rs b/crates/brain/src/input/sensors.rs index bfdc23c3..c8fc0724 100644 --- a/crates/brain/src/input/sensors.rs +++ b/crates/brain/src/input/sensors.rs @@ -12,7 +12,7 @@ pub async fn subscribe(event_tx: broadcast::Sender, data_server: SocketAd SubMessage::Reading(reading) => { event_tx.send(Event::Sensor(reading)).unwrap(); } - SubMessage::ErrorReport(_) => continue, + SubMessage::ErrorReport(_) | SubMessage::AffectorControlled { .. } => continue, } } } diff --git a/crates/protocol/src/affector.rs b/crates/protocol/src/affector.rs index 2701dd40..aada5371 100644 --- a/crates/protocol/src/affector.rs +++ b/crates/protocol/src/affector.rs @@ -5,8 +5,8 @@ use postcard::accumulator::{CobsAccumulator, FeedResult}; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; -use crate::large_bedroom; use crate::msg::cobs_overhead; +use crate::{large_bedroom, DecodeMsgError}; #[cfg(feature = "alloc")] pub mod tree; @@ -50,7 +50,7 @@ pub enum ControlValue<'a> { valid_range: Range, /// FnOnce such that value does become outdated setter: Option>, - value: usize, + value: usize, }, } @@ -105,3 +105,21 @@ impl Decoder { None } } + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ListMessage { + pub values: heapless::Vec, + pub version: u8, +} + +impl ListMessage { + #[cfg(feature = "alloc")] + #[must_use] + pub fn encode(&self) -> Vec { + postcard::to_allocvec_cobs(self).expect("Encoding should not fail") + } + + pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { + postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeMsgError::CorruptEncoding) + } +} diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index f6aa1a14..179c3433 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -148,7 +148,7 @@ impl Tree for Reading { ), Reading::WeightLeft(val) => ( *val as f32, - Device::Nau7802Left.rooted(), + Device::Nau7802Right.rooted(), 0.0..24.0_f32.exp2(), 1.0, Unit::Ohm, @@ -357,7 +357,7 @@ impl SensorError { SensorError::Max44(_) => Device::Max44, SensorError::Mhz14(_) => Device::Mhz14, SensorError::Sps30(_) => Device::Sps30, - SensorError::Nau7802Left(_) => Device::Nau7802Left, + SensorError::Nau7802Left(_) => Device::Nau7802Right, SensorError::Nau7802Right(_) => Device::Nau7802Right, } } @@ -370,8 +370,8 @@ pub enum Device { Max44, Mhz14, Sps30, - Nau7802Left, Nau7802Right, + Nau7802Left, Gpio, } diff --git a/crates/protocol/src/msg.rs b/crates/protocol/src/msg.rs index c654f954..338e66d0 100644 --- a/crates/protocol/src/msg.rs +++ b/crates/protocol/src/msg.rs @@ -1,3 +1,5 @@ +use crate::affector; + pub(crate) mod error; pub(crate) mod sensor; @@ -6,17 +8,20 @@ pub(crate) mod sensor; pub enum Msg { Readings(sensor::SensorMessage), ErrorReport(error::ErrorReport), + AffectorList(affector::ListMessage), } impl Msg { pub const READINGS: u8 = 1; pub const ERROR_REPORT: u8 = 2; + pub const AFFECTOR_LIST: u8 = 3; #[must_use] pub fn header(&self) -> u8 { let header = match self { Msg::Readings(_) => Self::READINGS, Msg::ErrorReport(_) => Self::ERROR_REPORT, + Msg::AffectorList(_) => Self::AFFECTOR_LIST, }; assert_ne!(header, 0, "0 is reserved for cobs encoding"); header @@ -33,6 +38,10 @@ impl Msg { Ok(Self::Readings(sensor::SensorMessage::::decode(bytes)?)) } else if msg_type == Self::ERROR_REPORT { Ok(Self::ErrorReport(error::ErrorReport::decode(bytes)?)) + } else if msg_type == Self::AFFECTOR_LIST { + Ok(Self::AffectorList(affector::ListMessage::::decode( + bytes, + )?)) } else { Err(DecodeMsgError::IncorrectMsgType(msg_type)) } @@ -44,6 +53,7 @@ impl Msg { let mut bytes = match self { Msg::Readings(readings) => readings.encode(), Msg::ErrorReport(report) => report.encode(), + Msg::AffectorList(list) => list.encode(), }; bytes.insert(0, self.header()); diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index 5d7123be..aa588f43 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -40,13 +40,19 @@ enum Fetchable { enum Update { ReadingList(Vec), - Fetched { reading: Reading, thing: Fetchable }, + Fetched { + reading: Reading, + thing: Fetchable, + }, FetchError(color_eyre::Report), SensorReading(protocol::Reading), SensorError(Box), SubscribeError(color_eyre::Report), DeviceList(Vec), - AffectorControlled(protocol::Affector), + AffectorControlled { + affector: protocol::Affector, + controlled_by: String, + }, } async fn receive_data(data_server: SocketAddr, tx: mpsc::Sender) { @@ -78,6 +84,13 @@ async fn receive_data(data_server: SocketAddr, tx: mpsc::Sender) { .map(|msg| match msg { SubMessage::Reading(reading) => Update::SensorReading(reading), SubMessage::ErrorReport(error) => Update::SensorError(error), + SubMessage::AffectorControlled { + affector, + controlled_by, + } => Update::AffectorControlled { + affector, + controlled_by, + }, }); match res { diff --git a/crates/sensor-tui/src/tui/affectors.rs b/crates/sensor-tui/src/tui/affectors.rs index 2bf7dc1d..ed7c337d 100644 --- a/crates/sensor-tui/src/tui/affectors.rs +++ b/crates/sensor-tui/src/tui/affectors.rs @@ -87,8 +87,8 @@ impl Tab { | Update::Fetched { .. } | Update::FetchError(_) | Update::SubscribeError(_) => return, - Update::AffectorControlled(a) => { - self.update_tree(a); + Update::AffectorControlled { affector, .. } => { + self.update_tree(affector); return; } Update::SensorReading(r) => &vec![r.device()], From 6e6c7cb8ba27a6aa2f6ff9e7d2e02a409abf0f46 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 2 Sep 2024 15:37:56 +0200 Subject: [PATCH 222/687] adds button logic to bed sensor node --- sensor-nodes/bed-sensors/src/main.rs | 34 +++++++++------ sensor-nodes/bed-sensors/src/sensors.rs | 4 +- sensor-nodes/bed-sensors/src/sensors/fast.rs | 45 ++++++++++++-------- 3 files changed, 51 insertions(+), 32 deletions(-) diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index b7ddd7ba..60062306 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -22,6 +22,7 @@ use embassy_time::{Delay, Timer}; use embedded_hal_bus::spi::ExclusiveDevice; use futures::pin_mut; use heapless::Vec; +use sensors::fast::ButtonInputs; use static_cell::StaticCell; use defmt::{error, trace, unwrap}; @@ -156,18 +157,16 @@ async fn main(spawner: Spawner) { i2c::Config::default(), ); let i2c_3: Mutex = Mutex::new(i2c_3); - /* - // let buttons = ButtonInputs { - // top_left: ExtiInput::new(p.PA13, p.EXTI13, Pull::Down), - // top_right: ExtiInput::new(p.PA14, p.EXTI14, Pull::Down), - // middle_inner: ExtiInput::new(p.PA9, p.EXTI9, Pull::Down), - // middle_center: ExtiInput::new(p.PA10, p.EXTI10, Pull::Down), - // middle_outer: ExtiInput::new(p.PA11, p.EXTI11, Pull::Down), - // lower_inner: ExtiInput::new(p.PA12, p.EXTI12, Pull::Down), - // lower_center: ExtiInput::new(p.PA15, p.EXTI15, Pull::Down), - // lower_outer: ExtiInput::new(p.PB5, p.EXTI5, Pull::Down), - // }; - */ + + let buttons = ButtonInputs { + top: ExtiInput::new(p.PC14, p.EXTI14, Pull::Down), + middle_inner: ExtiInput::new(p.PA9, p.EXTI9, Pull::Down), + middle_center: ExtiInput::new(p.PA10, p.EXTI10, Pull::Down), + middle_outer: ExtiInput::new(p.PA11, p.EXTI11, Pull::Down), + lower_inner: ExtiInput::new(p.PA12, p.EXTI12, Pull::Down), + lower_center: ExtiInput::new(p.PA15, p.EXTI15, Pull::Down), + lower_outer: ExtiInput::new(p.PB5, p.EXTI5, Pull::Down), + }; let mut spi_cfg = SpiConfig::default(); spi_cfg.frequency = Hertz(5_000_000); // up to 50m works @@ -211,8 +210,15 @@ async fn main(spawner: Spawner) { let handle_network = network::handle(stack, &publish); pin_mut!(handle_network); - let init_then_measure = - sensors::init_then_measure(&publish, i2c_1, i2c_2, i2c_3, usart_mhz, usart_sps30); + let init_then_measure = sensors::init_then_measure( + &publish, + i2c_1, + i2c_2, + i2c_3, + usart_mhz, + usart_sps30, + buttons, + ); let res = select::select(&mut handle_network, init_then_measure).await; let unrecoverable_err = match res { Either::First(()) | Either::Second(Ok(())) => defmt::unreachable!(), diff --git a/sensor-nodes/bed-sensors/src/sensors.rs b/sensor-nodes/bed-sensors/src/sensors.rs index e3c48bec..19d9a7ac 100644 --- a/sensor-nodes/bed-sensors/src/sensors.rs +++ b/sensor-nodes/bed-sensors/src/sensors.rs @@ -7,6 +7,7 @@ use embassy_stm32::usart::Uart; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; use embassy_time::Delay; +use fast::ButtonInputs; use mhzx::MHZ; use protocol::large_bedroom::bed::Device; use sps30_async::Sps30; @@ -52,6 +53,7 @@ pub async fn init_then_measure( i2c_3: Mutex>, usart_mhz: Uart<'static, Async>, usart_sps: Uart<'static, Async>, + buttons: ButtonInputs, ) -> Result<(), Error> { info!("initializing sensors"); let bme = Bme680Driver::new(&i2c_3, Device::Bme680); @@ -71,7 +73,7 @@ pub async fn init_then_measure( let rx = rx.into_ring_buffered(&mut usart_buf); let sps30 = Sps30Driver::init(tx, rx); - let sensors_fast = fast::read(max44009, nau_right, nau_left, /*buttons,*/ publish); + let sensors_fast = fast::read(max44009, nau_right, nau_left, buttons, publish); let sensors_slow = slow::read(sht, bme, mhz, sps30, publish); join::join(sensors_fast, sensors_slow).await; diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed-sensors/src/sensors/fast.rs index f2b69003..37c11270 100644 --- a/sensor-nodes/bed-sensors/src/sensors/fast.rs +++ b/sensor-nodes/bed-sensors/src/sensors/fast.rs @@ -1,4 +1,5 @@ use defmt::warn; +use embassy_futures::join::{join3, join4}; use embassy_futures::{join, yield_now}; use embassy_stm32::exti::ExtiInput; use embassy_time::{Duration, Instant, Timer}; @@ -128,8 +129,7 @@ async fn watch_button( #[allow(dead_code)] pub struct ButtonInputs { - pub top_left: ExtiInput<'static>, - pub top_right: ExtiInput<'static>, + pub top: ExtiInput<'static>, pub middle_inner: ExtiInput<'static>, pub middle_center: ExtiInput<'static>, pub middle_outer: ExtiInput<'static>, @@ -142,24 +142,35 @@ pub(crate) async fn read( max44: Max44Driver<'_>, nau_right: Nau7802DriverBlocking<'_>, nau_left: Nau7802Driver<'_>, - /*inputs: ButtonInputs,*/ publish: &Queues, + inputs: ButtonInputs, + publish: &Queues, ) { - // let watch_buttons_1 = join5( - // watch_button(inputs.top_left, BedButton::TopLeft, publish), - // watch_button(inputs.top_right, BedButton::TopRight, publish), - // watch_button(inputs.middle_inner, BedButton::MiddleInner, publish), - // watch_button(inputs.middle_center, BedButton::MiddleCenter, publish), - // watch_button(inputs.middle_outer, BedButton::MiddleOuter, publish), - // ); - // - // let watch_buttons_2 = join3( - // watch_button(inputs.lower_inner, BedButton::LowerInner, publish), - // watch_button(inputs.lower_center, BedButton::LowerCenter, publish), - // watch_button(inputs.lower_outer, BedButton::LowerOuter, publish), - // ); + use protocol::large_bedroom::bed::Button; + + let watch_buttons_1 = join4( + watch_button(inputs.top, Button::TopLeft, publish), + watch_button(inputs.middle_inner, Button::MiddleInner, publish), + watch_button(inputs.middle_center, Button::MiddleCenter, publish), + watch_button(inputs.middle_outer, Button::MiddleOuter, publish), + ); + + let watch_buttons_2 = join3( + watch_button(inputs.lower_inner, Button::LowerInner, publish), + watch_button(inputs.lower_center, Button::LowerCenter, publish), + watch_button(inputs.lower_outer, Button::LowerOuter, publish), + ); + + let watch_buttons = join::join(watch_buttons_1, watch_buttons_2); let watch_lux = report_lux(max44, publish); let report_right_weight = report_weight(nau_right, Reading::WeightRight, publish); let report_left_weight = report_weight(nau_left, Reading::WeightLeft, publish); - join::join3(report_left_weight, report_right_weight, watch_lux).await; + + join::join4( + report_left_weight, + report_right_weight, + watch_lux, + watch_buttons, + ) + .await; } From 7aa2abcac92ec9adcbcb35890b76fd35b2888a7a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 2 Sep 2024 17:18:32 +0200 Subject: [PATCH 223/687] affector list now required as first message --- Cargo.lock | 11 +++ crates/data-server/Cargo.toml | 1 + crates/data-server/src/server/affector.rs | 63 ++++----------- crates/data-server/src/server/data_source.rs | 82 ++++++++++++++------ crates/data-server/tests/api.rs | 17 +++- crates/protocol/src/affector.rs | 8 ++ 6 files changed, 104 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3f046636..1fba7e8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -868,6 +868,7 @@ dependencies = [ "tokio-util", "tracing", "tracing-error", + "tracing-futures", "tracing-subscriber", ] @@ -3582,6 +3583,16 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + [[package]] name = "tracing-journald" version = "0.3.0" diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index 1131b617..35fabd75 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -27,6 +27,7 @@ tokio-util = { version = "0.7.11", features = ["codec"] } serde = { version = "1.0.208", features = ["derive"] } futures-concurrency = "7.6.1" slotmap = "1.0.7" +tracing-futures = "0.2.5" [dev-dependencies] reserve-port = "2" diff --git a/crates/data-server/src/server/affector.rs b/crates/data-server/src/server/affector.rs index f9b83eec..e29fb16c 100644 --- a/crates/data-server/src/server/affector.rs +++ b/crates/data-server/src/server/affector.rs @@ -1,15 +1,13 @@ use std::sync::{Arc, Mutex}; use color_eyre::Result; -use futures::FutureExt; -use futures_concurrency::future::Race; use protocol::Affector; use slotmap::{DefaultKey, SlotMap}; use tokio::io::AsyncWriteExt; use tokio::net::tcp::OwnedWriteHalf; use tokio::sync::mpsc::{Receiver, Sender}; -use tracing::warn; +use tracing::{debug, instrument, warn}; #[derive(Debug)] pub(crate) struct Registration { @@ -22,6 +20,7 @@ impl Registration { if let Some(curr) = self.controls.iter_mut().find(|a| a.is_same_as(&new)) { *curr = new; } else { + debug!("new affector: {new:?} registered"); self.controls.push(new); } } @@ -31,7 +30,7 @@ impl Registration { pub struct Registar(Arc>>); impl Registar { - fn register(&self, tx: Sender) -> DefaultKey { + pub(crate) fn register(&self, tx: Sender) -> DefaultKey { let mut this = self.0.lock().expect("nothing should panic"); this.insert(Registration { tx, @@ -39,7 +38,7 @@ impl Registar { }) } - fn update_affectors(&self, key: DefaultKey, affector: Affector) { + pub(crate) fn update_affectors(&self, key: DefaultKey, affector: Affector) { let mut this = self.0.lock().expect("nothing should panic"); let registration = this .get_mut(key) @@ -47,7 +46,7 @@ impl Registar { registration.update(affector) } - fn remove(&self, key: DefaultKey) { + pub(crate) fn remove(&self, key: DefaultKey) { let mut this = self.0.lock().expect("nothing should panic"); this.remove(key).expect("things are only removed once"); } @@ -79,51 +78,15 @@ impl Registar { pub struct Offline; -pub(super) async fn track_and_control_affectors( - mut writer: OwnedWriteHalf, - mut update_from_same_node: Receiver, - registar: Registar, -) { - let (tx, mut rx) = tokio::sync::mpsc::channel(10); - let key = registar.register(tx); +#[instrument(skip_all)] +pub(super) async fn control_affectors(mut writer: OwnedWriteHalf, mut rx: Receiver) { + debug!("controlling newly connected node's affectors"); - loop { - let new_update = update_from_same_node.recv().map(Res::from); - let new_order = rx - .recv() - .map(|opt| opt.expect("Register never drops")) - .map(Res::Order); - - let res = (new_update, new_order).race().await; - match res { - Res::Disconnected => break, - Res::Update(affector) => { - registar.update_affectors(key, affector); - } - Res::Order(affector) => { - let buf = affector.encode(); - if let Err(e) = writer.write_all(&buf).await { - warn!("Could not send affector order: {e}"); - break; - } - } - } - } - - registar.remove(key); -} - -enum Res { - Disconnected, - Update(protocol::Affector), - Order(protocol::Affector), -} - -impl Res { - fn from(val: Option) -> Self { - match val { - Some(affector) => Self::Update(affector), - None => Self::Disconnected, + while let Some(new_order) = rx.recv().await { + let buf = new_order.encode(); + if let Err(e) = writer.write_all(&buf).await { + warn!("Could not send affector order: {e}"); + break; } } } diff --git a/crates/data-server/src/server/data_source.rs b/crates/data-server/src/server/data_source.rs index bf1cbc9e..70999c9f 100644 --- a/crates/data-server/src/server/data_source.rs +++ b/crates/data-server/src/server/data_source.rs @@ -2,16 +2,18 @@ use std::net::SocketAddr; use color_eyre::eyre::{eyre, Context}; use color_eyre::{Result, Section}; +use futures_concurrency::future::Race; +use protocol::Affector; use tokio::io::{AsyncBufReadExt, BufReader}; use tokio::net::tcp::OwnedReadHalf; use tokio::net::TcpListener; use tokio::net::TcpStream; -use tokio::sync::mpsc::{self, Sender}; +use tokio::sync::mpsc::Sender; use super::Event; -use tracing::{info, warn}; +use tracing::{error, info, instrument, warn}; -use super::affector::{track_and_control_affectors, Registar}; +use super::affector::{control_affectors, Registar}; pub async fn handle_nodes( addr: SocketAddr, @@ -28,10 +30,10 @@ pub async fn handle_nodes( match res { Ok((stream, source)) => { info!("new data source connected from: {source}"); - tokio::spawn(handle_node(stream, share.clone(), registar.clone())); + tokio::spawn(handle_node(stream, source, share.clone(), registar.clone())); } Err(e) => { - println!("new connection failed: {e}"); + warn!("new connection failed: {e}"); continue; } }; @@ -56,29 +58,63 @@ pub async fn read_and_decode_packet( protocol::Msg::<50>::decode(bytes).wrap_err("decode failed") } -async fn handle_node(stream: TcpStream, queue: Sender, registar: Registar) { +#[instrument(skip(stream, queue, registar))] +async fn handle_node( + stream: TcpStream, + source: SocketAddr, + queue: Sender, + registar: Registar, +) { + use tracing_futures::Instrument; let (reader, writer) = stream.into_split(); - let reader = BufReader::new(reader); + let mut reader = BufReader::new(reader); + + let affectors = match handshake(&mut reader).await { + Ok(affectors) => affectors, + Err(e) => { + error!("failed handshake: {e}"); + return; + } + }; + let (tx, rx) = tokio::sync::mpsc::channel(10); + let key = registar.register(tx); + for affector in affectors { + registar.update_affectors(key, affector); + } - let (tx, rx) = mpsc::channel(100); - tokio::join!( - receive_and_spread_updates(reader, queue, tx), - track_and_control_affectors(writer, rx, registar), - ); + ( + receive_and_spread_updates(reader, queue).in_current_span(), + control_affectors(writer, rx).in_current_span(), + ) + .race() + .await; + + registar.remove(key); } -async fn receive_and_spread_updates( - mut reader: BufReader, - queue: Sender, - affectors: Sender, -) { +async fn handshake(reader: &mut BufReader) -> Result, String> { let mut buf = Vec::new(); + let msg = match read_and_decode_packet(reader, &mut buf).await { + Ok(decoded) => decoded, + Err(e) => { + return Err(format!("Error while reading and decoding packet: {e}")); + } + }; + let protocol::Msg::AffectorList(list) = msg else { + return Err("Must get affector list as first message (handshake)".to_owned()); + }; + + Ok(list.values.to_vec()) +} +#[instrument(skip_all)] +async fn receive_and_spread_updates(mut reader: BufReader, queue: Sender) { + let mut buf = Vec::new(); loop { let msg = match read_and_decode_packet(&mut reader, &mut buf).await { Ok(decoded) => decoded, Err(e) => { - warn!("Error while reading and decoding packet: {e}"); + error!("Error while reading and decoding packet: {e}"); return; } }; @@ -99,13 +135,9 @@ async fn receive_and_spread_updates( .await .expect("fn spread_updates should stay running"); } - protocol::Msg::AffectorList(list) => { - for affector_state in list.values { - affectors - .send(affector_state) - .await - .expect("fn track_and_control_affectors should not end") - } + protocol::Msg::AffectorList(_) => { + error!("Affector list should only be send at the start of the connection"); + return; } } } // loop diff --git a/crates/data-server/tests/api.rs b/crates/data-server/tests/api.rs index dfa766cc..11f09f4d 100644 --- a/crates/data-server/tests/api.rs +++ b/crates/data-server/tests/api.rs @@ -40,12 +40,23 @@ const TEST_READING: Reading = async fn send_sensor_value(data_port: u16) -> Result { tokio::time::sleep(Duration::from_millis(500)).await; + + let mut list = protocol::affector::ListMessage::<50>::empty(); + list.values + .push(protocol::Affector::LargeBedroom( + large_bedroom::Affector::Bed(bed::Affector::Sps30FanClean), + )) + .unwrap(); + let handshake = protocol::Msg::AffectorList(list).encode(); + + let mut conn = TcpStream::connect(("127.0.0.1", data_port)).await.unwrap(); + conn.write_all(&handshake).await.unwrap(); + let mut sensor_msg = protocol::SensorMessage::<50>::default(); sensor_msg.values.push(TEST_READING).unwrap(); - let encoded = protocol::Msg::Readings(sensor_msg).encode(); + let sensor_msg = protocol::Msg::Readings(sensor_msg).encode(); + conn.write_all(&sensor_msg).await.unwrap(); - let mut conn = TcpStream::connect(("127.0.0.1", data_port)).await.unwrap(); - conn.write_all(&encoded).await.unwrap(); sleep(Duration::from_secs(999)).await; Ok(Done::SendValue) } diff --git a/crates/protocol/src/affector.rs b/crates/protocol/src/affector.rs index aada5371..93f991d1 100644 --- a/crates/protocol/src/affector.rs +++ b/crates/protocol/src/affector.rs @@ -119,6 +119,14 @@ impl ListMessage { postcard::to_allocvec_cobs(self).expect("Encoding should not fail") } + #[must_use] + pub fn empty() -> Self { + Self { + values: heapless::Vec::new(), + version: 1, + } + } + pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeMsgError::CorruptEncoding) } From ae7fac045c1dcc2b28d149eea35977c32f8e5a2b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 2 Sep 2024 20:26:47 +0200 Subject: [PATCH 224/687] fix log store set_err --- crates/log-store/Cargo.toml | 1 + crates/log-store/src/server/db.rs | 4 ++- crates/log-store/src/server/db/log.rs | 45 ++++++++++++++++++++++++--- crates/log-store/tests/list_data.rs | 29 ++++++++++------- 4 files changed, 62 insertions(+), 17 deletions(-) diff --git a/crates/log-store/Cargo.toml b/crates/log-store/Cargo.toml index a6d3d59e..1adc8aab 100644 --- a/crates/log-store/Cargo.toml +++ b/crates/log-store/Cargo.toml @@ -33,6 +33,7 @@ futures = "0.3.30" smallvec = "2.0.0-alpha.6" num = "0.4.3" hdrhistogram = "7.5.4" +derivative = "2.2.0" [dev-dependencies] futures-concurrency = "7.6.1" diff --git a/crates/log-store/src/server/db.rs b/crates/log-store/src/server/db.rs index df1b5b24..d3395d89 100644 --- a/crates/log-store/src/server/db.rs +++ b/crates/log-store/src/server/db.rs @@ -12,6 +12,7 @@ pub(crate) use log::Logs; mod stats; pub(crate) use stats::Stats; +use tracing::debug; pub(crate) async fn run( data_server_addr: SocketAddr, @@ -20,11 +21,12 @@ pub(crate) async fn run( log_dir: &Path, ) -> Result<()> { let mut sub = - ReconnectingClient::new(data_server_addr, "ha-data-store".to_string()).subscribe(); + ReconnectingClient::new(data_server_addr, "ha-log-store".to_string()).subscribe(); let mut recently_logged = (Instant::now(), String::new()); loop { let msg = sub.next().await; + debug!("Got msg from data-server: {msg:?}"); let res = match msg { SubMessage::Reading(reading) => { if let Err(e) = stats.increment(reading.device()).await { diff --git a/crates/log-store/src/server/db/log.rs b/crates/log-store/src/server/db/log.rs index 08ef03c3..53894832 100644 --- a/crates/log-store/src/server/db/log.rs +++ b/crates/log-store/src/server/db/log.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; use std::io::{self, Read, Write}; +use std::iter; use std::path::{Path, PathBuf}; use std::sync::Arc; @@ -12,12 +13,14 @@ use serde::{Deserialize, Serialize}; use series::data::OpenError as DataOpenError; use series::Error::Open; use tokio::sync::Mutex; -use tracing::{info, warn}; +use tracing::{debug, info, instrument, warn}; use crate::api::{self, ErrorEvent}; -#[derive(Debug)] +#[derive(derivative::Derivative)] +#[derivative(Debug)] pub(crate) struct Log { + #[derivative(Debug = "ignore")] history: ByteSeries, current: CurrentError, } @@ -83,6 +86,8 @@ impl CurrentError { self.file .flush() .wrap_err("failed to flush current err backup to disk")?; + + self.value = Some(value); Ok(()) } @@ -92,6 +97,7 @@ impl CurrentError { } impl Log { + #[instrument] pub fn open_or_create(dir: &Path, device: &Device) -> Result { let path = base_path(device); let path = dir.join(path); @@ -143,6 +149,7 @@ impl Log { }) } + #[instrument] pub fn set_err(&mut self, new_report: protocol::Error) -> Result<()> { if let Some((started, report)) = self.current.get() { if report == &new_report { @@ -153,20 +160,30 @@ impl Log { error: report.clone(), }; let line = bincode::serialize(&line).wrap_err("Could not serialize ErrorEvent")?; + let payload_size = protocol::Error::max_size(); + let line: Vec<_> = line + .into_iter() + .chain(iter::repeat(0)) + .take(payload_size) + .collect(); + self.history .push_line(started.as_second() as u64, line) .wrap_err("Could not push new ErrorEvent into history")?; } + debug!("Registered new error: {new_report}"); self.current .set(new_report) .wrap_err("Failed to set new error in current error store") } + #[instrument] fn clear(&mut self) -> Result<()> { self.current .take() .wrap_err("failed to set value of current error to None")?; + debug!("Cleared any error"); Ok(()) } @@ -183,11 +200,27 @@ impl Log { found: n_lines, })); } + + let current = self + .current + .value + .as_ref() + .map(|(ts, event)| api::ErrorEvent { + start: *ts, + end: None, + error: event.clone(), + }) + .into_iter(); + + if n_lines == 0 { + return Ok(Ok(current.collect())); + } + self.history .read_all(.., &mut Decoder, &mut timestamps, &mut data) - .wrap_err("Could not read log events form disk")?; + .wrap_err("Could not read log events from disk")?; - let res = timestamps + let mut res: Vec<_> = timestamps .into_iter() .zip(data) .map(|(start, StoredErrorEvent { end, error })| api::ErrorEvent { @@ -197,6 +230,8 @@ impl Log { error, }) .collect(); + res.extend(current); + Ok(Ok(res)) } } @@ -241,7 +276,7 @@ impl Logs { let mut map = self.0.lock().await; if let Some(log) = map.get_mut(device) { match log.get_all() { - Err(report) => Err(api::GetLogError::InternalError(report.to_string())), + Err(report) => Err(api::GetLogError::InternalError(format!("{report:#}"))), Ok(res) => res, } } else { diff --git a/crates/log-store/tests/list_data.rs b/crates/log-store/tests/list_data.rs index f4435fb5..32fb0034 100644 --- a/crates/log-store/tests/list_data.rs +++ b/crates/log-store/tests/list_data.rs @@ -24,11 +24,9 @@ const fn test_readings(v: f32) -> [Reading; 2] { ] } -fn test_error() -> protocol::Error { +fn test_error(text: &str) -> protocol::Error { protocol::Error::LargeBedroom(large_bedroom::Error::Bed(bed::Error::Setup( - bed::SensorError::Sht31( - heapless::String::from_str("log server integration test error").unwrap(), - ), + bed::SensorError::Sht31(heapless::String::from_str(text).unwrap()), ))) } @@ -46,6 +44,10 @@ async fn data_server(client_addr: impl Into, data_port: impl Into::empty(); + let handshake = protocol::Msg::AffectorList(list).encode(); + conn.write_all(&handshake).await.unwrap(); + for v in [0.1, 0.2, 0.3] { let mut sensor_msg = protocol::SensorMessage::<50>::default(); for val in test_readings(v) { @@ -61,8 +63,14 @@ async fn send_sensor_values(data_port: u16, data_send: &Notify) { async fn send_sensor_errors(data_port: u16, data_send: &Notify) { let mut conn = TcpStream::connect(("127.0.0.1", data_port)).await.unwrap(); - for _ in [1, 2, 3, 4] { - let report = protocol::ErrorReport::new(test_error()); + let list = protocol::affector::ListMessage::<50>::empty(); + let handshake = protocol::Msg::AffectorList(list).encode(); + conn.write_all(&handshake).await.unwrap(); + + for error_type in [1, 1, 2, 1] { + let report = protocol::ErrorReport::new(test_error(&format!( + "log server integration test error: {error_type}" + ))); let encoded = protocol::Msg::<50>::ErrorReport(report).encode(); conn.write_all(&encoded).await.unwrap(); sleep(Duration::from_secs_f32(1.1)).await; @@ -91,15 +99,14 @@ async fn check_client_get_percentiles(data_store_addr: SocketAddr, data_send: &N async fn check_client_get_logs(data_store_addr: SocketAddr, data_send: &Notify) { data_send.notified().await; sleep(Duration::from_secs_f32(0.1)).await; - let mut client = - log_store::api::Client::connect(data_store_addr, "data_store_example".to_owned()) - .await - .unwrap(); + let mut client = log_store::api::Client::connect(data_store_addr, "log_store_test".to_owned()) + .await + .unwrap(); let test_device = test_readings(0.0).first().unwrap().device(); let logs = client.get_logs(test_device).await.unwrap(); - assert_eq!(logs.len(), 4); + assert_eq!(logs.len(), 3); } static SETUP_REPORTING: Once = Once::new(); From 3aaf3392d305518634cf1d6418065849cfdc768d Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 3 Sep 2024 00:06:04 +0200 Subject: [PATCH 225/687] fix: send affectorlist as handshake --- crates/desk-sensors/src/main.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/crates/desk-sensors/src/main.rs b/crates/desk-sensors/src/main.rs index 54867f1e..7c4b9ec7 100644 --- a/crates/desk-sensors/src/main.rs +++ b/crates/desk-sensors/src/main.rs @@ -44,12 +44,22 @@ fn main() { Err(err) => panic!("could not connect to server: {}", err), }; + let bytes = + protocol::Msg::AffectorList(protocol::affector::ListMessage::<50>::empty()).encode(); + if stream.write_all(&bytes).is_err() { + std::thread::sleep(Duration::from_secs(5)); + break; // reconnect + } + loop { let result = rx.recv().unwrap(); let msg = match result { Ok(reading) => { let mut readings = SensorMessage::<1>::default(); - readings.values.push(reading).expect("capacity allows one push"); + readings + .values + .push(reading) + .expect("capacity allows one push"); Msg::Readings(readings) } Err(report) => Msg::ErrorReport(protocol::ErrorReport::new(report)), From 421db81bc0278e946f8dbd7d6f210d8799bd4910 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 3 Sep 2024 13:19:35 +0200 Subject: [PATCH 226/687] fix tests (sends affector list now) --- crates/data-store/tests/list_data.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/data-store/tests/list_data.rs b/crates/data-store/tests/list_data.rs index 3cbfe853..f1e3d1e9 100644 --- a/crates/data-store/tests/list_data.rs +++ b/crates/data-store/tests/list_data.rs @@ -37,6 +37,10 @@ async fn data_server(client_addr: impl Into, data_port: impl Into::empty(); + let handshake = protocol::Msg::AffectorList(list).encode(); + conn.write_all(&handshake).await.unwrap(); + for v in values { let mut sensor_msg = protocol::SensorMessage::<50>::default(); for val in test_readings(*v) { From 57545cdde2e6acb5abd6109d934eba2acc0c1f98 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 4 Sep 2024 18:13:45 +0200 Subject: [PATCH 227/687] remove free_affectors from affector info + fix cobsdecodor for affectors --- crates/protocol/src/affector.rs | 54 +++++++++++++++++++++--- crates/protocol/src/large_bedroom/bed.rs | 7 +-- crates/protocol/src/reading.rs | 13 +++--- 3 files changed, 56 insertions(+), 18 deletions(-) diff --git a/crates/protocol/src/affector.rs b/crates/protocol/src/affector.rs index 93f991d1..23b8d868 100644 --- a/crates/protocol/src/affector.rs +++ b/crates/protocol/src/affector.rs @@ -36,15 +36,12 @@ tree::all_nodes! {Affector; AffectorDiscriminants; LargeBedroom} #[derive(Debug, Clone)] pub struct Info { pub description: &'static str, - /// affectors not related to a reading - /// and therefore not related to a read device - pub free_affectors: &'static [Affector], } #[cfg(feature = "alloc")] pub enum ControlValue<'a> { Trigger, - /// if you need floats just map this to a float + /// If you need floats just map this to a float /// in the affector device like: `range = range/x + y` SetNum { valid_range: Range, @@ -70,7 +67,7 @@ impl Affector { postcard::to_allocvec_cobs(self).expect("Encoding should not fail") } - // info() is explicitly not defined, use the tree impl to get at it + // Info() is explicitly not defined, use the tree impl to get at it #[cfg(feature = "alloc")] pub fn controls(&mut self) -> Vec { match self { @@ -80,7 +77,7 @@ impl Affector { } pub struct Decoder { - cobs_buf: CobsAccumulator<{ Affector::ENCODED_SIZE }>, + cobs_buf: CobsAccumulator<{ 2 * Affector::ENCODED_SIZE }>, } impl Default for Decoder { @@ -92,7 +89,7 @@ impl Default for Decoder { } impl Decoder { - /// if this returns Some(_, remaining) move the remaining into it again + /// If this returns Some(_, remaining) move the remaining into it again pub fn feed<'a>(&mut self, read_bytes: &'a [u8]) -> Option<(Affector, &'a [u8])> { let mut window = read_bytes; while !window.is_empty() { @@ -113,12 +110,26 @@ pub struct ListMessage { } impl ListMessage { + /// +2 is for the version + /// +4 covers the length of the heapless list + pub const HALF_ENCODED_SIZE: usize = (MAX_ITEMS * Affector::POSTCARD_MAX_SIZE + 2 + 4); + /// cobs and postcard encoded + pub const ENCODED_SIZE: usize = + Self::HALF_ENCODED_SIZE + cobs_overhead(Self::HALF_ENCODED_SIZE); + #[cfg(feature = "alloc")] #[must_use] pub fn encode(&self) -> Vec { postcard::to_allocvec_cobs(self).expect("Encoding should not fail") } + /// Buffer should be at least `Self::ENCODED_SIZE` long. The returned slice contains + /// the serialized data. It can be shorter then the input buffer. + #[must_use] + pub fn encode_slice<'a>(&self, buf: &'a mut [u8]) -> &'a mut [u8] { + postcard::to_slice_cobs(self, buf).expect("Encoding should not fail") + } + #[must_use] pub fn empty() -> Self { Self { @@ -131,3 +142,32 @@ impl ListMessage { postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeMsgError::CorruptEncoding) } } + +#[cfg(all(test, feature = "alloc"))] +mod test { + use super::*; + use large_bedroom::bed; + + #[test] + fn decoder_decodes_encoded() { + let test_affector = + Affector::LargeBedroom(large_bedroom::Affector::Bed(bed::Affector::RgbLed { + red: 0, + green: 5, + blue: 0, + })); + + let encoded = test_affector.encode(); + let mut encoded_copy = encoded.clone(); + let decoded: Affector = postcard::from_bytes_cobs(encoded_copy.as_mut_slice()).unwrap(); + assert_eq!(decoded, test_affector); + + let mut decoder = Decoder::default(); + + decoder.feed(&encoded); + let res = decoder.feed(&encoded); + + let empty_slice = [].as_slice(); + assert_eq!(res, Some((test_affector, empty_slice))); + } +} diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 179c3433..e041627e 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -148,7 +148,7 @@ impl Tree for Reading { ), Reading::WeightLeft(val) => ( *val as f32, - Device::Nau7802Right.rooted(), + Device::Nau7802Left.rooted(), 0.0..24.0_f32.exp2(), 1.0, Unit::Ohm, @@ -590,10 +590,7 @@ impl affector::tree::Tree for Affector { Affector::RgbLed {..} => "Set color & power of the RGB led at the top of the bed post" }; - affector::tree::Item::Leaf(affector::Info { - description, - free_affectors: &tree![Affector; Affector::RgbLed { red: 0, green: 0, blue: 0 }], - }) + affector::tree::Item::Leaf(affector::Info { description }) } fn branch_id(&self) -> affector::tree::Id { diff --git a/crates/protocol/src/reading.rs b/crates/protocol/src/reading.rs index 4f6f4c59..df7c3ab2 100644 --- a/crates/protocol/src/reading.rs +++ b/crates/protocol/src/reading.rs @@ -1,11 +1,11 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; -use crate::{large_bedroom, small_bedroom}; #[cfg(feature = "alloc")] use crate::Device; #[cfg(feature = "alloc")] use crate::Unit; +use crate::{large_bedroom, small_bedroom}; #[cfg(feature = "alloc")] pub mod tree; @@ -82,16 +82,17 @@ impl Info { /// useful for printing/formatting floats /// # Example /// ```rust - /// use crate::Reading; - /// use crate::large_bedroom; - /// use crate::large_bedroom::desk; + /// use protocol::Reading; + /// use protocol::large_bedroom; + /// use protocol::large_bedroom::desk; + /// use protocol::reading::tree::Tree; /// /// let reading = - /// Reading::LargeBedroom(large_bedroom::Reading(desk::Reading::Temperature(22.428124); + /// Reading::LargeBedroom(large_bedroom::Reading::Desk(desk::Reading::Temperature(22.428124))); /// /// let info = reading.leaf(); /// let printed = format!("{0:.1$}", info.val, info.precision()); - /// assert_eq!(printed, "22.42"); + /// assert_eq!(printed, "22.43"); /// ``` #[must_use] #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] From 8e421b79f1c56618820692ce6f24e9ef11f95f47 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 4 Sep 2024 23:57:54 +0200 Subject: [PATCH 228/687] respond to led orders + send affectorlist on handshake +improve button debounce --- sensor-nodes/bed-sensors/.cargo/config.toml | 2 +- sensor-nodes/bed-sensors/src/main.rs | 39 +++-- sensor-nodes/bed-sensors/src/network.rs | 83 ++++++++-- sensor-nodes/bed-sensors/src/rgb_led.rs | 163 +++++++++++++++++++ sensor-nodes/bed-sensors/src/sensors.rs | 4 +- sensor-nodes/bed-sensors/src/sensors/fast.rs | 35 ++-- 6 files changed, 284 insertions(+), 42 deletions(-) create mode 100644 sensor-nodes/bed-sensors/src/rgb_led.rs diff --git a/sensor-nodes/bed-sensors/.cargo/config.toml b/sensor-nodes/bed-sensors/.cargo/config.toml index 72829582..f5a36213 100644 --- a/sensor-nodes/bed-sensors/.cargo/config.toml +++ b/sensor-nodes/bed-sensors/.cargo/config.toml @@ -10,7 +10,7 @@ target = "thumbv7em-none-eabihf" [env] DEFMT_LOG = "debug,sps30_async=info,bosch_bme680=info" -EMBASSY_EXECUTOR_TASK_ARENA_SIZE="9000" +EMBASSY_EXECUTOR_TASK_ARENA_SIZE="10000" # [unstable] # build-std = ["core"] diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index 60062306..7e1c52b0 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -2,8 +2,7 @@ #![no_main] use embassy_executor::Spawner; -use embassy_futures::select; -use embassy_futures::select::Either; +use embassy_futures::select::{self, Either3}; use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources}; use embassy_net_wiznet::{chip::W5500, Device, Runner, State}; use embassy_stm32::exti::ExtiInput; @@ -17,6 +16,7 @@ use embassy_stm32::usart::{self, DataBits, Parity, StopBits, Uart}; use embassy_stm32::wdg::IndependentWatchdog; use embassy_stm32::Config; use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::channel::Channel; use embassy_sync::mutex::Mutex; use embassy_time::{Delay, Timer}; use embedded_hal_bus::spi::ExclusiveDevice; @@ -31,6 +31,7 @@ use {defmt_rtt as _, panic_probe as _}; mod channel; mod error_cache; mod network; +mod rgb_led; mod rng; mod sensors; use crate::channel::Queues; @@ -119,7 +120,7 @@ async fn main(spawner: Spawner) { usart_config, )); - // we are out of DMA, so we need to use a blocking interface + // We are out of DMA, so we need to use a blocking interface // these sensors are only read once every 5s let i2c_1 = I2c::new( p.I2C1, @@ -137,11 +138,12 @@ async fn main(spawner: Spawner) { p.I2C2, p.PB10, p.PB3, - // extra slow, helps with longer cable runs - Hertz(150_000), + // Extra slow, helps with longer cable run + // to the right weight sensor + Hertz(100_000), i2c::Config::default(), ); - // even though its used by only one device we still use the (zero cost) + // Even though its used by only one device we still use the (zero cost) // mutex. It allows us to match/reuse the API for syn & async nau7802 let i2c_2: Mutex = Mutex::new(i2c_2); @@ -152,12 +154,12 @@ async fn main(spawner: Spawner) { Irqs, p.DMA1_CH4, p.DMA1_CH1, - // extra slow, helps with longer cable runs + // Extra slow, helps with longer cable runs Hertz(150_000), i2c::Config::default(), ); let i2c_3: Mutex = Mutex::new(i2c_3); - + let buttons = ButtonInputs { top: ExtiInput::new(p.PC14, p.EXTI14, Pull::Down), middle_inner: ExtiInput::new(p.PA9, p.EXTI9, Pull::Down), @@ -169,7 +171,7 @@ async fn main(spawner: Spawner) { }; let mut spi_cfg = SpiConfig::default(); - spi_cfg.frequency = Hertz(5_000_000); // up to 50m works + spi_cfg.frequency = Hertz(5_000_000); // Up to 50m works let (miso, mosi, clk) = (p.PA6, p.PA7, p.PA5); let spi = Spi::new(p.SPI1, clk, mosi, miso, p.DMA2_CH3, p.DMA2_CH0, spi_cfg); let cs = Output::new(p.PA4, Level::High, Speed::VeryHigh); @@ -206,12 +208,17 @@ async fn main(spawner: Spawner) { // Launch network task unwrap!(spawner.spawn(net_task(stack))); + let comms = Channel::new(); + let (mut led_controller, led_handle) = + rgb_led::controller_and_handle(p.TIM1, p.PB14, p.PB13, p.PB15, &comms); + let publish = Queues::new(); - let handle_network = network::handle(stack, &publish); + let handle_network = network::handle(stack, &publish, led_handle.clone()); pin_mut!(handle_network); let init_then_measure = sensors::init_then_measure( &publish, + led_handle, i2c_1, i2c_2, i2c_3, @@ -219,10 +226,16 @@ async fn main(spawner: Spawner) { usart_sps30, buttons, ); - let res = select::select(&mut handle_network, init_then_measure).await; + + let res = select::select3( + &mut handle_network, + init_then_measure, + led_controller.control(), + ) + .await; let unrecoverable_err = match res { - Either::First(()) | Either::Second(Ok(())) => defmt::unreachable!(), - Either::Second(Err(err)) => err, + Either3::First(()) | Either3::Third(()) | Either3::Second(Ok(())) => defmt::unreachable!(), + Either3::Second(Err(err)) => err, }; // at this point no other errors have occurred diff --git a/sensor-nodes/bed-sensors/src/network.rs b/sensor-nodes/bed-sensors/src/network.rs index c8bd7bbe..45212240 100644 --- a/sensor-nodes/bed-sensors/src/network.rs +++ b/sensor-nodes/bed-sensors/src/network.rs @@ -5,14 +5,16 @@ use embassy_net::tcp::{TcpReader, TcpSocket, TcpWriter}; use embassy_net::{Ipv4Address, Stack}; use embassy_time::{with_timeout, Duration, Instant, Timer}; use embedded_io_async::Write; -use protocol::{ErrorReport, SensorMessage}; +use protocol::large_bedroom::{self, bed}; +use protocol::{affector, Affector, ErrorReport, SensorMessage}; use crate::channel::{PriorityValue, QueueItem, Queues}; +use crate::rgb_led::LedHandle; -type Msg = SensorMessage<10>; +type SensMsg = SensorMessage<10>; async fn collect_pending(publish: &Queues, reading: PriorityValue) -> SensorMessage<10> { - let mut msg = Msg::default(); + let mut msg = SensMsg::default(); let low_priority = reading.low_priority(); unwrap!(msg.values.push(reading.value)); @@ -65,9 +67,9 @@ const fn max(a: usize, b: usize) -> usize { [a, b][(a < b) as usize] } -pub async fn handle(stack: &Stack, publish: &Queues) { +pub async fn handle(stack: &Stack, publish: &Queues, led: LedHandle<'_>) { let mut rx_buffer = [0; 1024]; - let mut tx_buffer = [0; max(Msg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE) * 2]; + let mut tx_buffer = [0; max(SensMsg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE) * 2]; let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); socket.set_timeout(Some(Duration::from_secs(5))); @@ -88,7 +90,7 @@ pub async fn handle(stack: &Stack, publish: &Queues) { publish.clear().await; let (reader, writer) = socket.split(); - match select(send_messages(writer, publish), receive_orders(reader)).await { + match select(send_messages(writer, publish), receive_orders(reader, &led)).await { select::Either::First(e) => warn!("Error while sending messages: {}", e), select::Either::Second(e) => warn!("Error receiving orders: {}", e), }; @@ -98,10 +100,45 @@ pub async fn handle(stack: &Stack, publish: &Queues) { } } +fn affector_list() -> affector::ListMessage<5> { + let mut list = affector::ListMessage::<5>::empty(); + unwrap!(list.values.push(Affector::LargeBedroom( + protocol::large_bedroom::Affector::Bed(bed::Affector::RgbLed { + red: 0, + green: 0, + blue: 0, + }), + ))); + unwrap!(list.values.push(Affector::LargeBedroom( + protocol::large_bedroom::Affector::Bed(bed::Affector::Sps30FanClean), + ))); + unwrap!(list.values.push(Affector::LargeBedroom( + protocol::large_bedroom::Affector::Bed(bed::Affector::MhzZeroPointCalib), + ))); + unwrap!(list.values.push(Affector::LargeBedroom( + protocol::large_bedroom::Affector::Bed(bed::Affector::Nau7802LeftCalib), + ))); + unwrap!(list.values.push(Affector::LargeBedroom( + protocol::large_bedroom::Affector::Bed(bed::Affector::Nau7802RightCalib), + ))); + + list +} + async fn send_messages(mut tcp: TcpWriter<'_>, publish: &Queues) -> embassy_net::tcp::Error { - let mut encoded_msg_buffer = [0; max(Msg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE)]; + let mut buf = [0; 1 + max( + max(SensMsg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE), + affector::ListMessage::<5>::ENCODED_SIZE, + )]; + let encoded_len = affector_list().encode_slice(&mut buf[1..]).len(); + buf[0] = protocol::Msg::<0>::AFFECTOR_LIST; + let to_send = &buf[..=encoded_len]; + if let Err(e) = tcp.write_all(to_send).await { + return e; + } + loop { - let to_send = get_messages(publish, &mut encoded_msg_buffer).await; + let to_send = get_messages(publish, &mut buf).await; if let Err(e) = tcp.write_all(to_send).await { return e; } @@ -114,7 +151,9 @@ enum ReadError { TcpError(embassy_net::tcp::Error), } -async fn receive_orders(mut tcp: TcpReader<'_>) -> ReadError { +async fn receive_orders(mut tcp: TcpReader<'_>, led: &LedHandle<'_>) -> ReadError { + defmt::debug!("ready to receive orders"); + let mut decoder = affector::Decoder::default(); let mut buf = [0u8; 100]; loop { let res = tcp.read(&mut buf).await; @@ -124,10 +163,32 @@ async fn receive_orders(mut tcp: TcpReader<'_>) -> ReadError { Err(e) => return ReadError::TcpError(e), }; let mut read = &buf[..n_read]; - let mut decoder = protocol::affector::Decoder::default(); while let Some((item, remaining)) = decoder.feed(read) { read = remaining; - defmt::info!("received item: {:?}", item) + + #[allow(irrefutable_let_patterns)] // Will change in the future + let Affector::LargeBedroom(large_bedroom::Affector::Bed(affector)) = item + else { + defmt::warn!("Got affector for other node"); + continue; + }; + + match affector { + bed::Affector::MhzZeroPointCalib + | bed::Affector::Nau7802LeftCalib + | bed::Affector::Nau7802RightCalib + | bed::Affector::Sps30FanClean => { + defmt::warn!("unimplemented affector: {:?}", affector) + } + bed::Affector::RgbLed { red, green, blue } => { + led.set_color( + red as f32 / u8::MAX as f32, + green as f32 / u8::MAX as f32, + blue as f32 / u8::MAX as f32, + ) + .await + } + } } } } diff --git a/sensor-nodes/bed-sensors/src/rgb_led.rs b/sensor-nodes/bed-sensors/src/rgb_led.rs new file mode 100644 index 00000000..1f593416 --- /dev/null +++ b/sensor-nodes/bed-sensors/src/rgb_led.rs @@ -0,0 +1,163 @@ +use embassy_stm32::gpio::OutputType; +use embassy_stm32::peripherals::{PB13, PB14, PB15, TIM1}; +use embassy_stm32::time::khz; +use embassy_stm32::timer; +use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::channel::Channel; + +struct RgbLed { + pwm: ComplementaryPwm<'static, TIM1>, + r: f32, + g: f32, + b: f32, +} + +impl RgbLed { + fn new(timer: TIM1, b: PB15, r: PB14, g: PB13) -> Self { + use embassy_stm32::timer::Channel; + + let b = ComplementaryPwmPin::new_ch3(b, OutputType::PushPull); + let r = ComplementaryPwmPin::new_ch2(r, OutputType::PushPull); + let g = ComplementaryPwmPin::new_ch1(g, OutputType::PushPull); + + let mut pwm = ComplementaryPwm::new( + timer, + None, + Some(g), + None, + Some(r), + None, + Some(b), + None, + None, + khz(10), + Default::default(), + ); + + for channel in [Channel::Ch1, Channel::Ch2, Channel::Ch3] { + pwm.set_duty(channel, pwm.get_max_duty()); + pwm.enable(channel); + } + + Self { + pwm, + r: 1.0, + g: 1.0, + b: 1.0, + } + } + + fn set(&mut self, channel: timer::Channel, brightness: f32) { + let max = self.pwm.get_max_duty(); + let scaled = (brightness * max as f32) as u16; + let complementary_duty = max - scaled; + self.pwm.set_duty(channel, complementary_duty); + } + + fn set_red(&mut self, brightness: f32) { + self.set(timer::Channel::Ch2, brightness); + } + + fn set_blue(&mut self, brightness: f32) { + self.set(timer::Channel::Ch1, brightness); + } + + fn set_green(&mut self, brightness: f32) { + self.set(timer::Channel::Ch3, brightness); + } + + fn update(&mut self, bri: f32) { + let sum = (self.r + self.b + self.g).min(1.0); + let r = self.r / sum; + let b = self.b / sum; + let g = self.g / sum; + defmt::debug!("bri: {}, r: {}, g: {}, b: {}", bri, r, b, g); + self.set_red(bri * r); + self.set_blue(bri * b); + self.set_green(bri * g); + } +} + +pub(crate) enum Event { + SetColor { r: f32, g: f32, b: f32 }, + LuxChanged(f32), +} + +#[derive(Clone)] +pub struct LedHandle<'a> { + sender: &'a Channel, +} + +impl<'a> LedHandle<'a> { + pub async fn set_color(&self, r: f32, g: f32, b: f32) { + self.sender.send(Event::SetColor { r, g, b }).await + } + + pub async fn update_lux(&self, lux: f32) { + self.sender.send(Event::LuxChanged(lux)).await + } +} + +fn lookup_bri(lux: f32) -> f32 { + const LOOKUP_TABLE: [(f32, f32); 7] = [ + (5., 0.01), + (10., 0.05), + (20., 0.1), + (40., 0.2), + (80., 0.4), + (160., 0.5), + (320., 0.6), + ]; + + LOOKUP_TABLE + .iter() + .find(|(lux_entry, _)| *lux_entry > lux) + .map(|(_, bri)| bri) + .copied() + .unwrap_or(0.6) +} + +pub(crate) struct LedController<'a> { + orders: &'a Channel, + led: RgbLed, +} + +impl<'a> LedController<'a> { + pub(crate) async fn control(&mut self) { + let mut bri = 0.01; // Start with minimal bri + + loop { + let order = self.orders.receive().await; + match order { + Event::SetColor { r, g, b } => { + self.led.r = r; + self.led.g = g; + self.led.b = b; + } + Event::LuxChanged(new) => { + bri = lookup_bri(new); + } + } + + self.led.update(bri); + } + } +} + +pub fn controller_and_handle<'a>( + timer: TIM1, + r: PB14, + g: PB13, + b: PB15, + channel: &'a Channel, +) -> (LedController<'a>, LedHandle<'a>) { + let led = RgbLed::new(timer, b, r, g); + ( + LedController { + led, + orders: channel, + }, + LedHandle { sender: channel }, + ) +} diff --git a/sensor-nodes/bed-sensors/src/sensors.rs b/sensor-nodes/bed-sensors/src/sensors.rs index 19d9a7ac..5834c795 100644 --- a/sensor-nodes/bed-sensors/src/sensors.rs +++ b/sensor-nodes/bed-sensors/src/sensors.rs @@ -14,6 +14,7 @@ use sps30_async::Sps30; use crate::channel::Queues; use crate::error_cache::{Error, SensorError}; +use crate::rgb_led; pub mod fast; pub mod retry; @@ -48,6 +49,7 @@ const SPS30_DRIVER_BUF_SIZE: usize = 2 * SPS30_UART_BUF_SIZE; pub async fn init_then_measure( publish: &Queues, + rgb_led: rgb_led::LedHandle<'_>, i2c_1: Mutex>, i2c_2: Mutex>, i2c_3: Mutex>, @@ -73,7 +75,7 @@ pub async fn init_then_measure( let rx = rx.into_ring_buffered(&mut usart_buf); let sps30 = Sps30Driver::init(tx, rx); - let sensors_fast = fast::read(max44009, nau_right, nau_left, buttons, publish); + let sensors_fast = fast::read(max44009, nau_right, nau_left, buttons, publish, rgb_led); let sensors_slow = slow::read(sht, bme, mhz, sps30, publish); join::join(sensors_fast, sensors_slow).await; diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed-sensors/src/sensors/fast.rs index 37c11270..288b08b0 100644 --- a/sensor-nodes/bed-sensors/src/sensors/fast.rs +++ b/sensor-nodes/bed-sensors/src/sensors/fast.rs @@ -2,12 +2,14 @@ use defmt::warn; use embassy_futures::join::{join3, join4}; use embassy_futures::{join, yield_now}; use embassy_stm32::exti::ExtiInput; +use embassy_stm32::gpio::Level; use embassy_time::{Duration, Instant, Timer}; use protocol::large_bedroom::{bed::Button, bed::Reading}; use super::retry::{Max44Driver, Nau7802Driver, Nau7802DriverBlocking}; use crate::channel::Queues; +use crate::rgb_led; fn sig_lux_diff(old: f32, new: f32) -> bool { let diff = old - new; @@ -20,7 +22,7 @@ fn sig_weight_diff(old: u32, new: u32) -> bool { diff > 2000 } -async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues) { +async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues, rgb_led: rgb_led::LedHandle<'_>) { const MAX_INTERVAL: Duration = Duration::from_secs(5); let mut prev_lux = f32::MAX; @@ -40,6 +42,7 @@ async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues) { if sig_lux_diff(prev_lux, lux) { publish.send_p2(Reading::Brightness(lux)); + rgb_led.update_lux(lux).await; } else if last_lux.elapsed() > MAX_INTERVAL { publish.send_p1(Reading::Brightness(lux)); } else { @@ -101,33 +104,32 @@ async fn report_weight(mut nau: impl Nau, wrap: impl Fn(u32) -> Reading, publish } } -#[allow(dead_code)] async fn watch_button( mut input: ExtiInput<'static>, event: impl Fn(protocol::button::Press) -> Button, channel: &Queues, ) { - let mut went_high_at: Option = None; + let mut went_high_at: Option<(Instant)> = None; loop { if let Some(went_high_at) = went_high_at.take() { - input.wait_for_falling_edge().await; + input.wait_for_low().await; let press = went_high_at.elapsed(); - if press > Duration::from_millis(5) { - let Ok(press) = press.as_millis().try_into() else { - warn!("extremely long button press registered, skipping"); - continue; - }; - let event = (event)(protocol::button::Press(press)); - channel.send_p2(Reading::Button(event)); - } + let Ok(press) = press.as_millis().try_into() else { + warn!("extremely long button press registered, skipping"); + continue; + }; + let event = (event)(protocol::button::Press(press)); + channel.send_p2(Reading::Button(event)); } else { input.wait_for_rising_edge().await; - went_high_at = Some(Instant::now()); + Timer::after(Duration::from_millis(50)).await; + if input.is_high() { + went_high_at = Some(Instant::now()); + } } } } -#[allow(dead_code)] pub struct ButtonInputs { pub top: ExtiInput<'static>, pub middle_inner: ExtiInput<'static>, @@ -144,11 +146,12 @@ pub(crate) async fn read( nau_left: Nau7802Driver<'_>, inputs: ButtonInputs, publish: &Queues, + rgb_led: rgb_led::LedHandle<'_>, ) { use protocol::large_bedroom::bed::Button; let watch_buttons_1 = join4( - watch_button(inputs.top, Button::TopLeft, publish), + watch_button(inputs.top, Button::Top, publish), watch_button(inputs.middle_inner, Button::MiddleInner, publish), watch_button(inputs.middle_center, Button::MiddleCenter, publish), watch_button(inputs.middle_outer, Button::MiddleOuter, publish), @@ -162,7 +165,7 @@ pub(crate) async fn read( let watch_buttons = join::join(watch_buttons_1, watch_buttons_2); - let watch_lux = report_lux(max44, publish); + let watch_lux = report_lux(max44, publish, rgb_led); let report_right_weight = report_weight(nau_right, Reading::WeightRight, publish); let report_left_weight = report_weight(nau_left, Reading::WeightLeft, publish); From 712f3143f6ac3f66c27cd1a53fa9f005dbcd69e2 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 5 Sep 2024 01:22:09 +0200 Subject: [PATCH 229/687] send affector activations to client, fix affector controls overriden by new affector updates --- crates/sensor-tui/src/control.rs | 34 +++++++++ crates/sensor-tui/src/main.rs | 62 +++------------ crates/sensor-tui/src/populate.rs | 34 +++++---- crates/sensor-tui/src/receive.rs | 57 ++++++++++++++ crates/sensor-tui/src/tui.rs | 9 ++- crates/sensor-tui/src/tui/affectors.rs | 76 ++++++++++--------- .../src/tui/affectors/handle_key.rs | 27 ++++++- crates/sensor-tui/src/tui/affectors/render.rs | 20 +++-- crates/sensor-tui/src/tui/readings.rs | 2 +- .../src/tui/readings/sensor_info.rs | 15 ++-- 10 files changed, 213 insertions(+), 123 deletions(-) create mode 100644 crates/sensor-tui/src/control.rs create mode 100644 crates/sensor-tui/src/receive.rs diff --git a/crates/sensor-tui/src/control.rs b/crates/sensor-tui/src/control.rs new file mode 100644 index 00000000..bd2a9ebc --- /dev/null +++ b/crates/sensor-tui/src/control.rs @@ -0,0 +1,34 @@ +use std::net::SocketAddr; + +use data_server::api::Client; +use protocol::Affector; +use tokio::sync::mpsc; +use tracing::error; + +use crate::client_name; + +pub(crate) async fn watch_and_send(data_server: SocketAddr, mut rx: mpsc::Receiver) { + let mut connected_client: Option = None; + let mut queued = None; + + loop { + let order = match queued.take() { + Some(order) => order, + None => match rx.recv().await { + Some(order) => order, + None => return, + }, + }; + + if let Some(mut client) = connected_client.take() { + if let Err(e) = client.actuate_affector(order).await { + error!("Could not actuate affector: {e:?}"); + } + connected_client = Some(client) + } else { + if let Ok(c) = Client::connect(data_server, client_name()).await { + connected_client = Some(c) + } + } + } +} diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index aa588f43..a9642a1f 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -4,11 +4,11 @@ use std::sync::mpsc; use std::thread; use clap::Parser; -use color_eyre::eyre::{Report, WrapErr}; use color_eyre::Result; -use data_server::api::{Client, SubMessage}; +mod receive; mod fetch; +mod control; mod populate; mod time; mod tui; @@ -53,57 +53,10 @@ enum Update { affector: protocol::Affector, controlled_by: String, }, + AffectorList(Vec), } -async fn receive_data(data_server: SocketAddr, tx: mpsc::Sender) { - let client = match Client::connect(data_server, client_name()).await { - Ok(client) => client, - Err(err) => { - let _ignore_panicked_ui = tx.send(Update::SubscribeError( - Report::new(err).wrap_err("Could not connect to data server"), - )); - return; - } - }; - - let mut subbed = match client.subscribe().await { - Ok(client) => client, - Err(err) => { - let _ignore_panicked_ui = tx.send(Update::SubscribeError( - Report::new(err).wrap_err("Could not subscribe to data server"), - )); - return; - } - }; - loop { - let res = subbed - .next() - .await - .wrap_err("Error getting next reading from server") - .map(|msg| match msg { - SubMessage::Reading(reading) => Update::SensorReading(reading), - SubMessage::ErrorReport(error) => Update::SensorError(error), - SubMessage::AffectorControlled { - affector, - controlled_by, - } => Update::AffectorControlled { - affector, - controlled_by, - }, - }); - - match res { - Ok(msg) => { - tx.send(msg).unwrap(); - } - Err(err) => { - tx.send(Update::SubscribeError(err)).unwrap(); - break; - } - } - } -} #[derive(Parser)] #[command(name = "sensor tui")] @@ -135,14 +88,17 @@ async fn main() -> Result<()> { let (tx1, rx1) = mpsc::channel(); let (tx2, rx2) = mpsc::channel(); + let (tx3, rx3) = tokio::sync::mpsc::channel(100); let fetcher = Fetch::new(data_store, log_store, tx1.clone()); let tx1_clone1 = tx1.clone(); let tx1_clone2 = tx1.clone(); - task::spawn(receive_data(data_server, tx1_clone1)); - thread::spawn(move || tui::run(rx1, tx2, fetcher)); - thread::spawn(move || populate::tree(data_store, log_store, tx1_clone2)); + + thread::spawn(move || tui::run(rx1, tx2, tx3, fetcher)); + task::spawn(receive::receive_data(data_server, tx1_clone1)); + thread::spawn(move || populate::tree(data_server, data_store, log_store, tx1_clone2)); + task::spawn(control::watch_and_send(data_server, rx3)); loop { let UserIntent::Shutdown = rx2.recv()?; diff --git a/crates/sensor-tui/src/populate.rs b/crates/sensor-tui/src/populate.rs index db523876..82d4756a 100644 --- a/crates/sensor-tui/src/populate.rs +++ b/crates/sensor-tui/src/populate.rs @@ -7,6 +7,7 @@ use tracing::warn; use crate::{client_name, Update}; pub fn tree( + data_server_addr: SocketAddr, data_store_addr: SocketAddr, log_store_addr: SocketAddr, tx: mpsc::Sender, @@ -17,40 +18,47 @@ pub fn tree( .build() .unwrap(); - let (res1, res2) = rt.block_on(async { + let (res1, res2, res3) = rt.block_on(async { tokio::join!( + list_from_server(data_server_addr, tx.clone()), list_from_store(data_store_addr, tx.clone()), list_from_logs(log_store_addr, tx) ) }); if let Err(e) = res1 { - warn!("Could not populate readings list from store: {e}") + warn!("Could not populate affector list from data server: {e}") } if let Err(e) = res2 { - warn!("Could not populate readings list from logs: {e}") + warn!("Could not populate readings list from data store: {e}") + } + + if let Err(e) = res3 { + warn!("Could not populate logs and histograms from log store: {e}") } } -async fn list_from_store( - data_store_addr: SocketAddr, - tx: mpsc::Sender, -) -> Result<()> { +async fn list_from_server(data_server_addr: SocketAddr, tx: mpsc::Sender) -> Result<()> { + let mut client = data_server::api::Client::connect(data_server_addr, client_name()).await?; + let list = client.list_affectors().await?; + tracing::debug!("affector list: {list:?}"); + tx.send(Update::AffectorList(list)).unwrap(); + Ok(()) +} + +async fn list_from_store(data_store_addr: SocketAddr, tx: mpsc::Sender) -> Result<()> { let mut client = data_store::api::Client::connect(data_store_addr, client_name()).await?; let list = client.list_data().await?; - tracing::debug!("list: {list:?}"); + tracing::debug!("data list: {list:?}"); tx.send(Update::ReadingList(list)).unwrap(); Ok(()) } -async fn list_from_logs( - log_store_addr: SocketAddr, - tx: mpsc::Sender, -) -> Result<()> { +async fn list_from_logs(log_store_addr: SocketAddr, tx: mpsc::Sender) -> Result<()> { let mut client = log_store::api::Client::connect(log_store_addr, client_name()).await?; let list = client.list_devices().await?; - tracing::debug!("list: {list:?}"); + tracing::debug!("log list: {list:?}"); tx.send(Update::DeviceList(list)).unwrap(); Ok(()) } diff --git a/crates/sensor-tui/src/receive.rs b/crates/sensor-tui/src/receive.rs new file mode 100644 index 00000000..e59b3c18 --- /dev/null +++ b/crates/sensor-tui/src/receive.rs @@ -0,0 +1,57 @@ +use std::net::SocketAddr; +use std::sync::mpsc; + +use color_eyre::eyre::{Report, WrapErr}; +use data_server::api::{Client, SubMessage}; + +use crate::{client_name, Update}; + +pub async fn receive_data(data_server: SocketAddr, tx: mpsc::Sender) { + let client = match Client::connect(data_server, client_name()).await { + Ok(client) => client, + Err(err) => { + let _ignore_panicked_ui = tx.send(Update::SubscribeError( + Report::new(err).wrap_err("Could not connect to data server"), + )); + return; + } + }; + + let mut subbed = match client.subscribe().await { + Ok(client) => client, + Err(err) => { + let _ignore_panicked_ui = tx.send(Update::SubscribeError( + Report::new(err).wrap_err("Could not subscribe to data server"), + )); + return; + } + }; + + loop { + let res = subbed + .next() + .await + .wrap_err("Error getting next reading from server") + .map(|msg| match msg { + SubMessage::Reading(reading) => Update::SensorReading(reading), + SubMessage::ErrorReport(error) => Update::SensorError(error), + SubMessage::AffectorControlled { + affector, + controlled_by, + } => Update::AffectorControlled { + affector, + controlled_by, + }, + }); + + match res { + Ok(msg) => { + tx.send(msg).unwrap(); + } + Err(err) => { + tx.send(Update::SubscribeError(err)).unwrap(); + break; + } + } + } +} diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index 0d42f86b..3a153aa9 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -3,6 +3,7 @@ use crossterm::{ terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, ExecutableCommand, }; +use protocol::Affector; use ratatui::{ prelude::{CrosstermBackend, Terminal}, style::{Color, Style}, @@ -60,6 +61,7 @@ impl Default for Theme { pub fn run( rx: mpsc::Receiver, shutdown_tx: mpsc::Sender, + control_tx: tokio::sync::mpsc::Sender, fetcher: Fetch, ) -> Result<(), std::io::Error> { stdout().execute(EnterAlternateScreen)?; @@ -67,7 +69,7 @@ pub fn run( let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; terminal.clear()?; - let res = App::default().run(terminal, rx, fetcher); + let res = App::default().run(terminal, rx, control_tx, fetcher); shutdown_tx.send(UserIntent::Shutdown).unwrap(); stdout().execute(LeaveAlternateScreen)?; @@ -89,6 +91,7 @@ impl App { &mut self, mut terminal: Terminal>, rx: mpsc::Receiver, + mut control_tx: tokio::sync::mpsc::Sender, mut fetcher: Fetch, ) -> Result<(), std::io::Error> { loop { @@ -122,7 +125,9 @@ impl App { let res = match self.active_tab { ActiveTab::Readings => self.readings_tab.handle_key(key), - ActiveTab::Affectors => self.affectors_tab.handle_key(key), + ActiveTab::Affectors => { + self.affectors_tab.handle_key(key, &mut control_tx) + } }; if let Some(unhandled_key) = res { match unhandled_key.code { diff --git a/crates/sensor-tui/src/tui/affectors.rs b/crates/sensor-tui/src/tui/affectors.rs index ed7c337d..cc994ffb 100644 --- a/crates/sensor-tui/src/tui/affectors.rs +++ b/crates/sensor-tui/src/tui/affectors.rs @@ -1,9 +1,10 @@ use std::collections::HashMap; use crossterm::event::{KeyCode, KeyEvent}; -use protocol::{affector, Affector, Device}; +use protocol::{affector, Affector}; use ratatui::layout::{Constraint, Layout, Rect}; use ratatui::Frame; +use tokio::sync::mpsc; use tui_tree_widget::{TreeItem, TreeState}; use crate::Update; @@ -17,10 +18,12 @@ mod render; pub type TreeKey = [u8; 6]; +#[derive(Debug)] struct AffectorState { affector: Affector, selected_control: usize, info: affector::Info, + device_broken: DeviceBroken, } #[derive(Default)] @@ -28,7 +31,7 @@ pub struct Tab { tree_state: TreeState, pub ground: Vec>, data: HashMap, - registered_affectors: Vec, + data_server: Option, } impl Tab { @@ -49,13 +52,17 @@ impl Tab { if let Some(ref mut data) = data { let [top, bottom] = Layout::vertical([Constraint::Fill(1), Constraint::Fill(1)]).areas(right); - render::details(frame, &data.info, top); + render::details(frame, &data, top); render::controls(frame, data, bottom); }; render::footer(frame, footer, data, theme) } - pub fn handle_key(&mut self, key: KeyEvent) -> Option { + pub fn handle_key( + &mut self, + key: KeyEvent, + control: &mut mpsc::Sender, + ) -> Option { let data = self .tree_state .selected() @@ -74,7 +81,7 @@ impl Tab { } _ => { if let Some(state) = data { - return handle_key::handle(key, state); + return handle_key::handle(key, state, control); } } } @@ -82,38 +89,28 @@ impl Tab { } pub fn process_update(&mut self, update: &Update) { - let devices = match update { + match update { Update::ReadingList(_) | Update::Fetched { .. } | Update::FetchError(_) + | Update::SensorReading(_) + | Update::DeviceList(_) | Update::SubscribeError(_) => return, Update::AffectorControlled { affector, .. } => { - self.update_tree(affector); - return; + self.update_tree(affector, DeviceBroken::No); } - Update::SensorReading(r) => &vec![r.device()], - Update::SensorError(err) => &vec![err.device()], - Update::DeviceList(devices) => devices, - }; - - let mut possibly_new = devices - .iter() - .map(Device::info) - .flat_map(|info| info.affectors); - - let first = possibly_new.next(); - let free = if let Some(first) = first { - first.leaf().free_affectors - } else { - &[] - }; - - for new in possibly_new.chain(first.into_iter()).chain(free.iter()) { - if !self.registered_affectors.iter().any(|a| a.is_same_as(new)) { - self.registered_affectors.push(*new); - self.update_tree(new); + Update::SensorError(err) => { + let broken = err.device().info().affectors; + for affector in broken { + self.update_tree(affector, DeviceBroken::Yes); + } } - } + Update::AffectorList(affectors) => { + for affector in affectors { + self.update_tree(affector, DeviceBroken::No); + } + } + }; if self.tree_state.selected().is_empty() { self.tree_state.select_first(); @@ -121,8 +118,14 @@ impl Tab { } } +#[derive(Debug)] +enum DeviceBroken { + Yes, + No, +} + impl Tab { - fn update_tree(&mut self, affector: &protocol::Affector) { + fn update_tree(&mut self, affector: &protocol::Affector, broken: DeviceBroken) { let key = tree_key(affector); let mut tree = add_root(affector as &dyn AffectorTree, &mut self.ground); @@ -135,14 +138,15 @@ impl Tab { Item::Leaf(info) => { let text = tree_node.name(); add_leaf(text, tree, key); - self.data.insert( - key, - AffectorState { + self.data + .entry(key) + .and_modify(|state| state.affector = affector.clone()) + .or_insert(AffectorState { affector: affector.clone(), info, selected_control: 0, - }, - ); + device_broken: broken, + }); return; } Item::Node(inner) => { diff --git a/crates/sensor-tui/src/tui/affectors/handle_key.rs b/crates/sensor-tui/src/tui/affectors/handle_key.rs index 52f22299..21782762 100644 --- a/crates/sensor-tui/src/tui/affectors/handle_key.rs +++ b/crates/sensor-tui/src/tui/affectors/handle_key.rs @@ -1,9 +1,16 @@ use crossterm::event::{KeyCode, KeyEvent}; use protocol::affector::ControlValue as C; +use tokio::sync::mpsc; +use tokio::sync::mpsc::error::TrySendError; +use tracing::{error, warn}; use super::AffectorState; -pub(crate) fn handle(key: KeyEvent, state: &mut AffectorState) -> Option { +pub(crate) fn handle( + key: KeyEvent, + state: &mut AffectorState, + control_tx: &mut mpsc::Sender, +) -> Option { let mut controls = state.affector.controls(); let control = &mut controls[state.selected_control].value; @@ -12,11 +19,23 @@ pub(crate) fn handle(key: KeyEvent, state: &mut AffectorState) -> Option handle_decrease(control), KeyCode::Char('d') => { - state.selected_control = (state.selected_control + 1).min(controls.len() - 1) + state.selected_control = (state.selected_control + 1).min(controls.len() - 1); + return None; + } + KeyCode::Char('u') => { + state.selected_control = state.selected_control.saturating_sub(1); + return None; } - KeyCode::Char('u') => state.selected_control = state.selected_control.saturating_sub(1), _ => return Some(key), }; + + core::mem::drop(controls); + match control_tx.try_send(state.affector.clone()) { + Ok(_) => (), + Err(TrySendError::Full(_)) => warn!("control lagging behind ui inputs"), + Err(TrySendError::Closed(_)) => error!("control lost connection to data-server"), + } + None } @@ -45,7 +64,7 @@ fn handle_decrease(control: &mut C) { setter, value, } => { - let new_value = *value - 1; + let new_value = value.saturating_sub(1); let new_value = new_value as u64; let new_value = new_value.clamp(valid_range.start, valid_range.end); let setter = setter.take().expect("just created controls"); diff --git a/crates/sensor-tui/src/tui/affectors/render.rs b/crates/sensor-tui/src/tui/affectors/render.rs index 7102c061..26baf18a 100644 --- a/crates/sensor-tui/src/tui/affectors/render.rs +++ b/crates/sensor-tui/src/tui/affectors/render.rs @@ -10,7 +10,7 @@ use tui_tree_widget::{TreeItem, TreeState}; use crate::tui::Theme; -use super::{AffectorState, TreeKey}; +use super::{AffectorState, DeviceBroken, TreeKey}; pub(super) fn tree( frame: &mut Frame, @@ -33,8 +33,15 @@ pub(super) fn tree( ); } -pub(super) fn details(frame: &mut Frame, info: &affector::Info, top: Rect) { - let text = info.description; +pub(super) fn details(frame: &mut Frame, data: &&mut AffectorState, top: Rect) { + let text = if let DeviceBroken::No = data.device_broken { + data.info.description.to_string() + } else { + format!( + "{}\n\nWarning: Device reports error, affector might not work", + data.info.description + ) + }; frame.render_widget( widgets::Paragraph::new(text) .block(Block::bordered().title("Details")) @@ -90,7 +97,6 @@ fn render_slider( Style::default() }; - tracing::debug!("slider"); let percentage = (current_value as u64 * 100) / (valid_range.end - valid_range.start); frame.render_widget( Gauge::default() @@ -131,10 +137,10 @@ pub(crate) fn footer( }) => { footer.push("u/d: select prev/next"); match affector.controls()[*selected_control].value { - C::Trigger => footer.push("enter: trigger affector"), - C::SetNum { .. } => footer.push("f/b increase/decrease"), + C::Trigger => footer.push("enter: trigger affector"), + C::SetNum { .. } => footer.push("f/b increase/decrease"), + } } - }, None => (), } diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index c7cfca6a..177bad22 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -119,7 +119,7 @@ impl Tab { match update { Update::SensorReading(reading) => { - self.readings.add(reading); + self.readings.update(reading); } Update::ReadingList(list) => { self.readings.populate_from_reading_list(list); diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index 0839d13f..14a757e0 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -267,7 +267,7 @@ enum IsPlaceholder { } impl Readings { - pub fn add(&mut self, reading: Reading) { + pub fn update(&mut self, reading: Reading) { self.update_tree(&reading, IsPlaceholder::No); self.record_data(reading); } @@ -385,21 +385,22 @@ impl Readings { fn update_tree(&mut self, reading: &Reading, placeholder: IsPlaceholder) { let key = tree_key(reading); + tracing::debug!("reading: {reading:?}"); let mut tree = add_root(reading as &dyn Tree, &mut self.ground); - let mut tomato = match reading.inner() { + let mut node = match reading.inner() { Item::Leaf(_) => unreachable!("no values at level 0"), Item::Node(inner) => inner, }; loop { - match tomato.inner() { + match node.inner() { Item::Leaf(info) => { let text = if let IsPlaceholder::Yes = placeholder { - tomato.name() + node.name() } else { format!( "{0}: {1:.2$} {3}", - tomato.name(), + node.name(), info.val, info.precision(), info.unit @@ -409,8 +410,8 @@ impl Readings { return; } Item::Node(inner) => { - tree = add_node(tomato, tree); - tomato = inner; + tree = add_node(node, tree); + node = inner; } }; } From d1172b6b480d5c6aba9533501751ee4b385cc8b6 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 5 Sep 2024 01:22:56 +0200 Subject: [PATCH 230/687] remove top left/right distinction (now only one button) --- crates/protocol/src/large_bedroom/bed.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index e041627e..3d002384 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -27,8 +27,7 @@ button_enum! { /// L: TopLeft, R: TopRight, 1: MiddleInner, 2: MiddleCenter, 3: MiddleOuter, /// 4: OuterInner, 5: OuterCenter, 6: OuterOuter Button { - TopLeft, - TopRight, + Top, MiddleInner, MiddleCenter, MiddleOuter, @@ -162,7 +161,7 @@ impl Tree for Reading { Unit::Ohm, "Right weight sensor resistance", ), - Reading::Button(button) => return button.inner(), + Reading::Button(button) => return Item::Node(button), Reading::MassPm1_0(val) => ( *val, Device::Sps30.rooted(), @@ -471,8 +470,7 @@ impl Device { Device::Gpio => crate::DeviceInfo { name: "Gpio", affects_readings: &tree![Reading; - Reading::Button(Button::TopLeft(Press(0))), - Reading::Button(Button::TopRight(Press(0))), + Reading::Button(Button::Top(Press(0))), Reading::Button(Button::MiddleInner(Press(0))), Reading::Button(Button::MiddleCenter(Press(0))), Reading::Button(Button::MiddleOuter(Press(0))), From 2fd71542e3e5e5df6947c8c9d8ca6b6a6f370c0d Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 5 Sep 2024 01:23:58 +0200 Subject: [PATCH 231/687] ignore any rpc errors --- crates/rpc/src/client.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/rpc/src/client.rs b/crates/rpc/src/client.rs index ff3580bf..8a850a61 100644 --- a/crates/rpc/src/client.rs +++ b/crates/rpc/src/client.rs @@ -69,6 +69,7 @@ where { pub async fn connect(addr: impl ToSocketAddrs, name: String) -> Result { let stream = TcpStream::connect(addr).await.map_err(ConnectError::Io)?; + let _ignore_error = stream.set_nodelay(true); let length_delimited = Framed::new( stream, From 0ac232f8dcbcaaf2805a849fa52a6ef0465fe8fb Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 5 Sep 2024 01:24:26 +0200 Subject: [PATCH 232/687] mark nonworking buttons with comments that they are broken --- sensor-nodes/bed-sensors/src/main.rs | 4 ++-- sensor-nodes/bed-sensors/src/sensors/fast.rs | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index 7e1c52b0..ccdcddfa 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -162,10 +162,10 @@ async fn main(spawner: Spawner) { let buttons = ButtonInputs { top: ExtiInput::new(p.PC14, p.EXTI14, Pull::Down), - middle_inner: ExtiInput::new(p.PA9, p.EXTI9, Pull::Down), + middle_inner: ExtiInput::new(p.PA9, p.EXTI9, Pull::Down), // Not working middle_center: ExtiInput::new(p.PA10, p.EXTI10, Pull::Down), middle_outer: ExtiInput::new(p.PA11, p.EXTI11, Pull::Down), - lower_inner: ExtiInput::new(p.PA12, p.EXTI12, Pull::Down), + lower_inner: ExtiInput::new(p.PA12, p.EXTI12, Pull::Down), // Not working lower_center: ExtiInput::new(p.PA15, p.EXTI15, Pull::Down), lower_outer: ExtiInput::new(p.PB5, p.EXTI5, Pull::Down), }; diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed-sensors/src/sensors/fast.rs index 288b08b0..4bbfcbe4 100644 --- a/sensor-nodes/bed-sensors/src/sensors/fast.rs +++ b/sensor-nodes/bed-sensors/src/sensors/fast.rs @@ -2,7 +2,6 @@ use defmt::warn; use embassy_futures::join::{join3, join4}; use embassy_futures::{join, yield_now}; use embassy_stm32::exti::ExtiInput; -use embassy_stm32::gpio::Level; use embassy_time::{Duration, Instant, Timer}; use protocol::large_bedroom::{bed::Button, bed::Reading}; @@ -71,14 +70,12 @@ impl Nau for Nau7802DriverBlocking<'_> { } } -// todo deduplicate async fn report_weight(mut nau: impl Nau, wrap: impl Fn(u32) -> Reading, publish: &Queues) { const MAX_INTERVAL: Duration = Duration::from_secs(5); let mut prev_weight = u32::MAX; let mut reported_at = Instant::now(); - // todo!("reinit devices after error"); loop { Timer::after_millis(100).await; let weight = match nau.try_measure().await { @@ -109,7 +106,7 @@ async fn watch_button( event: impl Fn(protocol::button::Press) -> Button, channel: &Queues, ) { - let mut went_high_at: Option<(Instant)> = None; + let mut went_high_at: Option = None; loop { if let Some(went_high_at) = went_high_at.take() { input.wait_for_low().await; From 0caa1e78d0a756320870e7b8afe79b926763dd29 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 5 Sep 2024 01:34:06 +0200 Subject: [PATCH 233/687] set tcp keep-alive to abort dead connections --- Cargo.lock | 206 +++++++------------ crates/data-server/Cargo.toml | 1 + crates/data-server/src/main.rs | 4 +- crates/data-server/src/server/affector.rs | 56 ++--- crates/data-server/src/server/data_source.rs | 25 ++- crates/data-server/src/server/subscribe.rs | 4 +- 6 files changed, 124 insertions(+), 172 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1fba7e8c..f24eff85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -161,7 +161,7 @@ checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" dependencies = [ "async-task", "concurrent-queue", - "fastrand 2.1.0", + "fastrand 2.1.1", "futures-lite 2.3.0", "slab", ] @@ -214,7 +214,7 @@ dependencies = [ "futures-lite 2.3.0", "parking", "polling 3.7.3", - "rustix 0.38.34", + "rustix 0.38.35", "slab", "tracing", "windows-sys 0.59.0", @@ -253,7 +253,7 @@ dependencies = [ "cfg-if 1.0.0", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.34", + "rustix 0.38.35", "windows-sys 0.48.0", ] @@ -269,7 +269,7 @@ dependencies = [ "cfg-if 1.0.0", "futures-core", "futures-io", - "rustix 0.38.34", + "rustix 0.38.35", "signal-hook-registry", "slab", "windows-sys 0.59.0", @@ -332,13 +332,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -421,7 +421,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -571,7 +571,7 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "byteseries" version = "0.6.0" -source = "git+https://github.com/dvdsk/byteseries#328e5eab83f56870311fe6e4df2aa76b3e0dd75f" +source = "git+https://github.com/dvdsk/byteseries#03fd66109fc167a4665c8290a2b6a03d476daf65" dependencies = [ "arraydeque", "itertools", @@ -606,9 +606,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.14" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" dependencies = [ "shlex", ] @@ -671,7 +671,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -820,7 +820,7 @@ dependencies = [ "crossterm_winapi", "mio", "parking_lot 0.12.3", - "rustix 0.38.34", + "rustix 0.38.35", "signal-hook", "signal-hook-mio", "winapi", @@ -861,6 +861,7 @@ dependencies = [ "rpc", "serde", "slotmap", + "socket2 0.5.7", "thiserror", "tokio", "tokio-serde", @@ -919,7 +920,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -940,6 +941,17 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.18" @@ -950,7 +962,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -973,13 +985,9 @@ dependencies = [ [[package]] name = "diatomic-waker" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce3b3a843da2390ad9693fc640ed7081015fd73f280cab2b2081404a8ecceb99" -dependencies = [ - "loom", - "waker-fn", -] +checksum = "af873b6853650fb206431c52fa7bbf6917146b70a8a9979d6d141f5d5394086b" [[package]] name = "dirs" @@ -1042,7 +1050,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1111,7 +1119,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1213,9 +1221,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fd-lock" @@ -1224,15 +1232,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef033ed5e9bad94e55838ca0ca906db0e043f517adda0c8b79c7a8c66c93c1b5" dependencies = [ "cfg-if 1.0.0", - "rustix 0.38.34", + "rustix 0.38.35", "windows-sys 0.48.0", ] [[package]] name = "flate2" -version = "1.0.32" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c0596c1eac1f9e04ed902702e9878208b336edc9d6fddc8a48387349bab3666" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", "miniz_oxide 0.8.0", @@ -1364,7 +1372,7 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ - "fastrand 2.1.0", + "fastrand 2.1.1", "futures-core", "futures-io", "parking", @@ -1379,7 +1387,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1427,26 +1435,13 @@ dependencies = [ "byteorder", ] -[[package]] -name = "generator" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "979f00864edc7516466d6b3157706e06c032f22715700ddd878228a91d02bc56" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "log", - "rustversion", - "windows", -] - [[package]] name = "gethostname" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc3655aa6818d65bc620d6911f05aa7b6aeb596291e1e9f79e52df85583d1e30" dependencies = [ - "rustix 0.38.34", + "rustix 0.38.35", "windows-targets 0.52.6", ] @@ -1785,7 +1780,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core 0.52.0", + "windows-core", ] [[package]] @@ -1815,9 +1810,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown", @@ -1830,7 +1825,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" dependencies = [ "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1898,9 +1893,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jiff" -version = "0.1.8" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2b7379a75544c94b3da32821b0bf41f9062e9970e23b78cc577d0d89676d16" +checksum = "437651126da47900d4d70255ab15f5c69510ca4e0d88c9f01b5b8d41a45c3a9b" dependencies = [ "jiff-tzdb-platform", "serde", @@ -2020,6 +2015,7 @@ dependencies = [ "clap", "color-eyre", "data-server", + "derivative", "futures", "futures-concurrency", "hdrhistogram", @@ -2040,19 +2036,6 @@ dependencies = [ "tracing-subscriber", ] -[[package]] -name = "loom" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" -dependencies = [ - "cfg-if 1.0.0", - "generator", - "scoped-tls", - "tracing", - "tracing-subscriber", -] - [[package]] name = "lru" version = "0.12.4" @@ -2491,7 +2474,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -2513,7 +2496,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand 2.1.0", + "fastrand 2.1.1", "futures-io", ] @@ -2543,7 +2526,7 @@ dependencies = [ "concurrent-queue", "hermit-abi 0.4.0", "pin-project-lite", - "rustix 0.38.34", + "rustix 0.38.35", "tracing", "windows-sys 0.59.0", ] @@ -2737,9 +2720,9 @@ dependencies = [ [[package]] name = "ratatui" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ba6a365afbe5615999275bea2446b970b10a41102500e27ce7678d50d978303" +checksum = "fdef7f9be5c0122f890d58bdf4d964349ba6a6161f705907526d891efabba57d" dependencies = [ "bitflags 2.6.0", "cassowary", @@ -2929,9 +2912,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] @@ -2952,9 +2935,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" dependencies = [ "bitflags 2.6.0", "errno", @@ -2999,12 +2982,6 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scopeguard" version = "1.2.0" @@ -3058,14 +3035,14 @@ checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] name = "serde_json" -version = "1.0.125" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "itoa", "memchr", @@ -3298,7 +3275,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -3314,9 +3291,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.75" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -3388,7 +3365,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -3448,9 +3425,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.3" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", @@ -3472,7 +3449,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -3560,7 +3537,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -3809,7 +3786,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", "wasm-bindgen-shared", ] @@ -3843,7 +3820,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3886,16 +3863,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" -dependencies = [ - "windows-core 0.58.0", - "windows-targets 0.52.6", -] - [[package]] name = "windows-core" version = "0.52.0" @@ -3905,41 +3872,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-core" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-result", - "windows-strings", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-implement" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.75", -] - -[[package]] -name = "windows-interface" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.75", -] - [[package]] name = "windows-registry" version = "0.2.0" @@ -4145,5 +4077,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index 35fabd75..1da97afa 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -28,6 +28,7 @@ serde = { version = "1.0.208", features = ["derive"] } futures-concurrency = "7.6.1" slotmap = "1.0.7" tracing-futures = "0.2.5" +socket2 = "0.5.7" [dev-dependencies] reserve-port = "2" diff --git a/crates/data-server/src/main.rs b/crates/data-server/src/main.rs index 201d0f6c..98da55a1 100644 --- a/crates/data-server/src/main.rs +++ b/crates/data-server/src/main.rs @@ -14,11 +14,11 @@ use data_server::server; #[command(version = "1.0")] #[command(about = "Receives sensor events and spreads those to subscribed services")] struct Cli { - /// addr to which subscribers can connect + /// Addr to which subscribers can connect #[arg(short, long)] subscribe_addr: SocketAddr, - /// addr to which data-source can supply msg's + /// Addr to which data-source can supply messages #[arg(short, long)] update_addr: SocketAddr, } diff --git a/crates/data-server/src/server/affector.rs b/crates/data-server/src/server/affector.rs index e29fb16c..91d8cc6d 100644 --- a/crates/data-server/src/server/affector.rs +++ b/crates/data-server/src/server/affector.rs @@ -7,7 +7,7 @@ use tokio::io::AsyncWriteExt; use tokio::net::tcp::OwnedWriteHalf; use tokio::sync::mpsc::{Receiver, Sender}; -use tracing::{debug, instrument, warn}; +use tracing::{instrument, warn}; #[derive(Debug)] pub(crate) struct Registration { @@ -17,12 +17,12 @@ pub(crate) struct Registration { impl Registration { fn update(&mut self, new: Affector) { - if let Some(curr) = self.controls.iter_mut().find(|a| a.is_same_as(&new)) { - *curr = new; - } else { - debug!("new affector: {new:?} registered"); - self.controls.push(new); - } + let curr = self + .controls + .iter_mut() + .find(|a| a.is_same_as(&new)) + .unwrap(); + *curr = new; } } @@ -30,22 +30,32 @@ impl Registration { pub struct Registar(Arc>>); impl Registar { - pub(crate) fn register(&self, tx: Sender) -> DefaultKey { + pub(crate) fn register(&self, tx: Sender, affectors: Vec) -> DefaultKey { let mut this = self.0.lock().expect("nothing should panic"); + + let to_remove: Vec<_> = this + .iter_mut() + .filter(|(_, reg)| { + reg.controls.iter().any(|control| { + affectors + .iter() + .any(|affector| affector.is_same_as(control)) + }) + }) + .map(|(key, _)| key) + .collect(); + + for key in to_remove { + this.remove(key) + .expect("held lock so can not have been removed"); + } + this.insert(Registration { tx, - controls: Vec::new(), + controls: affectors, }) } - pub(crate) fn update_affectors(&self, key: DefaultKey, affector: Affector) { - let mut this = self.0.lock().expect("nothing should panic"); - let registration = this - .get_mut(key) - .expect("items are removed when track_and_control_affectors only"); - registration.update(affector) - } - pub(crate) fn remove(&self, key: DefaultKey) { let mut this = self.0.lock().expect("nothing should panic"); this.remove(key).expect("things are only removed once"); @@ -53,11 +63,11 @@ impl Registar { pub(crate) fn activate(&self, order: Affector) -> Result<(), Offline> { let mut this = self.0.lock().expect("nothing should panic"); - for possible_controller in this - .iter_mut() - .map(|(_, reg)| reg) - .filter(|reg| reg.controls.contains(&order)) - { + for possible_controller in this.iter_mut().map(|(_, reg)| reg).filter(|reg| { + reg.controls + .iter() + .any(|control| control.is_same_as(&order)) + }) { if possible_controller.tx.try_send(order).is_ok() { possible_controller.update(order); return Ok(()); @@ -80,8 +90,6 @@ pub struct Offline; #[instrument(skip_all)] pub(super) async fn control_affectors(mut writer: OwnedWriteHalf, mut rx: Receiver) { - debug!("controlling newly connected node's affectors"); - while let Some(new_order) = rx.recv().await { let buf = new_order.encode(); if let Err(e) = writer.write_all(&buf).await { diff --git a/crates/data-server/src/server/data_source.rs b/crates/data-server/src/server/data_source.rs index 70999c9f..7ad83b23 100644 --- a/crates/data-server/src/server/data_source.rs +++ b/crates/data-server/src/server/data_source.rs @@ -1,9 +1,11 @@ use std::net::SocketAddr; +use std::time::Duration; use color_eyre::eyre::{eyre, Context}; use color_eyre::{Result, Section}; use futures_concurrency::future::Race; use protocol::Affector; +use socket2::TcpKeepalive; use tokio::io::{AsyncBufReadExt, BufReader}; use tokio::net::tcp::OwnedReadHalf; use tokio::net::TcpListener; @@ -11,7 +13,7 @@ use tokio::net::TcpStream; use tokio::sync::mpsc::Sender; use super::Event; -use tracing::{error, info, instrument, warn}; +use tracing::{debug, error, info, instrument, warn}; use super::affector::{control_affectors, Registar}; @@ -66,6 +68,16 @@ async fn handle_node( registar: Registar, ) { use tracing_futures::Instrument; + + let sock_ref = socket2::SockRef::from(&stream); + sock_ref + .set_tcp_keepalive( + &TcpKeepalive::new() + .with_time(Duration::from_secs(5)) + .with_retries(1) // 1 is minimum + .with_interval(Duration::from_secs(1)), + ) + .expect("4 sec keepalive should work on tcp stream"); let (reader, writer) = stream.into_split(); let mut reader = BufReader::new(reader); @@ -76,12 +88,10 @@ async fn handle_node( return; } }; - let (tx, rx) = tokio::sync::mpsc::channel(10); - let key = registar.register(tx); - for affector in affectors { - registar.update_affectors(key, affector); - } + debug!("new node connected with affectors: {affectors:?}"); + let (tx, rx) = tokio::sync::mpsc::channel(10); + let key = registar.register(tx, affectors); ( receive_and_spread_updates(reader, queue).in_current_span(), control_affectors(writer, rx).in_current_span(), @@ -90,6 +100,7 @@ async fn handle_node( .await; registar.remove(key); + debug!("node removed"); } async fn handshake(reader: &mut BufReader) -> Result, String> { @@ -140,5 +151,5 @@ async fn receive_and_spread_updates(mut reader: BufReader, queue: return; } } - } // loop + } // Loop } diff --git a/crates/data-server/src/server/subscribe.rs b/crates/data-server/src/server/subscribe.rs index 1aa9f5a1..58b3e8db 100644 --- a/crates/data-server/src/server/subscribe.rs +++ b/crates/data-server/src/server/subscribe.rs @@ -1,6 +1,6 @@ use std::mem; use tokio::sync::mpsc; -use tracing::debug; +use tracing::trace; use color_eyre::Result; @@ -15,7 +15,7 @@ pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { .recv() .await .expect("queue is kept open by register_subs"); - debug!("event: {event:?}"); + trace!("event: {event:?}"); let msg = match event { Event::NewSub { tx } => { From f69b3de5a9ed7d5f2caa13f63fb5767019ba773a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 5 Sep 2024 16:12:50 +0200 Subject: [PATCH 234/687] protocol: give enum variants explicit number to make serialization more stable --- crates/protocol/src/large_bedroom.rs | 5 ++- crates/protocol/src/large_bedroom/bed.rs | 45 ++++++++++++----------- crates/protocol/src/large_bedroom/desk.rs | 9 +++-- crates/protocol/src/reading.rs | 5 ++- crates/protocol/src/small_bedroom.rs | 3 +- 5 files changed, 36 insertions(+), 31 deletions(-) diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index 515d9f99..d560c557 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -19,9 +19,10 @@ pub mod desk; PartialEq, )] #[strum_discriminants(derive(Hash))] +#[repr(u8)] pub enum Reading { - Bed(bed::Reading), - Desk(desk::Reading), + Bed(bed::Reading) = 0, + Desk(desk::Reading) = 1, } #[cfg(feature = "alloc")] diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 3d002384..7547da0d 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -50,40 +50,41 @@ button_enum! { PartialEq, )] #[strum_discriminants(derive(Hash))] +#[repr(u8)] pub enum Reading { - Button(Button), - Brightness(f32), - Temperature(f32), - Humidity(f32), - GassResistance(f32), // in Ohm - Pressure(f32), - /// parts per million - Co2(u16), - /// weight on the left side of the bed - WeightLeft(u32), - /// weight on the right side of the bed - WeightRight(u32), + Button(Button) = 0, + Brightness(f32) = 1, + Temperature(f32) = 2, + Humidity(f32) = 3, + GassResistance(f32) = 4, // In Ohm + Pressure(f32) = 5, + /// Parts per million + Co2(u16) = 6, + /// Weight on the left side of the bed + WeightLeft(u32) = 7, + /// Weight on the right side of the bed + WeightRight(u32) = 8, /// Mass Concentration PM1.0 \[μg/m³\] - MassPm1_0(f32), + MassPm1_0(f32) = 9, /// Mass Concentration PM2.5 \[μg/m³\] - MassPm2_5(f32), + MassPm2_5(f32) = 10, /// Mass Concentration PM4.0 \[μg/m³\] - MassPm4_0(f32), + MassPm4_0(f32) = 11, /// Mass Concentration PM10 \[μg/m³\] - MassPm10(f32), + MassPm10(f32) = 12, /// Number Concentration PM0.5 \[#/cm³\] - NumberPm0_5(f32), + NumberPm0_5(f32) = 13, /// Number Concentration PM1.0 \[#/cm³\] - NumberPm1_0(f32), + NumberPm1_0(f32) = 14, /// Number Concentration PM2.5 \[#/cm³\] - NumberPm2_5(f32), + NumberPm2_5(f32) = 15, /// Number Concentration PM4.0 \[#/cm³\] - NumberPm4_0(f32), + NumberPm4_0(f32) = 16, /// Number Concentration PM10 \[#/cm³\] - NumberPm10(f32), + NumberPm10(f32) = 17, /// Typical Particle Size8 \[μm\] - TypicalParticleSize(f32), + TypicalParticleSize(f32) = 18, } #[cfg(feature = "alloc")] diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index cea31ef4..0cc4a710 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -38,11 +38,12 @@ button_enum! { PartialEq, )] #[strum_discriminants(derive(Hash))] +#[repr(u8)] pub enum Reading { - Temperature(f32), - Humidity(f32), - Pressure(f32), - Button(Button), + Temperature(f32) = 0, + Humidity(f32) = 1, + Pressure(f32) = 2, + Button(Button) = 3, } #[cfg(feature = "alloc")] diff --git a/crates/protocol/src/reading.rs b/crates/protocol/src/reading.rs index df7c3ab2..2a727af7 100644 --- a/crates/protocol/src/reading.rs +++ b/crates/protocol/src/reading.rs @@ -22,9 +22,10 @@ pub mod tree; PartialEq, )] #[strum_discriminants(derive(Hash))] +#[repr(u8)] pub enum Reading { - LargeBedroom(large_bedroom::Reading), - SmallBedroom(small_bedroom::Reading), + LargeBedroom(large_bedroom::Reading) = 0, + SmallBedroom(small_bedroom::Reading) = 1, // Test, } diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index 5be5796b..8ad6557a 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -35,8 +35,9 @@ crate::button_enum! { MaxSize, PartialEq, )] +#[repr(u8)] pub enum Reading { - ButtonPanel(ButtonPanel), + ButtonPanel(ButtonPanel) = 0, } #[cfg(feature = "alloc")] From e550c115df8224a3614b21092e3246b7b5482261 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 5 Sep 2024 20:47:13 +0200 Subject: [PATCH 235/687] data-server: move subscriber api, add data_source api --- Cargo.lock | 1 + crates/brain/src/input/sensors.rs | 2 +- crates/data-server/src/api.rs | 53 +----- crates/data-server/src/api/data_source.rs | 137 ++++++++++++++++ .../src/api/data_source/reconnecting.rs | 110 +++++++++++++ crates/data-server/src/api/subscriber.rs | 51 ++++++ .../src/api/{ => subscriber}/client.rs | 12 +- .../{ => subscriber}/client/reconnecting.rs | 4 +- crates/data-server/src/server.rs | 9 +- crates/data-server/src/server/client.rs | 31 ++-- crates/data-server/src/server/subscribe.rs | 2 +- crates/data-server/tests/api.rs | 153 ------------------ crates/data-store/src/server/db.rs | 6 +- crates/desk-sensors/Cargo.toml | 4 +- crates/desk-sensors/src/main.rs | 62 ++----- crates/desk-sensors/src/sensors.rs | 2 +- crates/log-store/src/server/db.rs | 4 +- crates/sensor-tui/src/control.rs | 2 +- crates/sensor-tui/src/populate.rs | 3 +- crates/sensor-tui/src/receive.rs | 2 +- crates/sensor-tui/src/tui/affectors.rs | 1 - crates/text-widget/src/main.rs | 4 +- crates/text-widget/src/resolve.rs | 2 +- crates/text-widget/src/resolve/fetch.rs | 4 +- 24 files changed, 362 insertions(+), 299 deletions(-) create mode 100644 crates/data-server/src/api/data_source.rs create mode 100644 crates/data-server/src/api/data_source/reconnecting.rs create mode 100644 crates/data-server/src/api/subscriber.rs rename crates/data-server/src/api/{ => subscriber}/client.rs (90%) rename crates/data-server/src/api/{ => subscriber}/client/reconnecting.rs (98%) delete mode 100644 crates/data-server/tests/api.rs diff --git a/Cargo.lock b/Cargo.lock index f24eff85..6c541fed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -972,6 +972,7 @@ dependencies = [ "bme280", "clap", "color-eyre", + "data-server", "embedded-hal-async", "gpiocdev-embedded-hal", "heapless 0.8.0", diff --git a/crates/brain/src/input/sensors.rs b/crates/brain/src/input/sensors.rs index c8fc0724..54382384 100644 --- a/crates/brain/src/input/sensors.rs +++ b/crates/brain/src/input/sensors.rs @@ -1,6 +1,6 @@ use std::net::SocketAddr; -use data_server::api::{ReconnectingClient, SubMessage}; +use data_server::api::subscriber::{ReconnectingClient, SubMessage}; use tokio::sync::broadcast; use crate::controller::Event; diff --git a/crates/data-server/src/api.rs b/crates/data-server/src/api.rs index b4388d43..42a6d58e 100644 --- a/crates/data-server/src/api.rs +++ b/crates/data-server/src/api.rs @@ -1,51 +1,2 @@ -use serde::{Deserialize, Serialize}; - -pub mod client; -pub use client::reconnecting::Client as ReconnectingClient; -pub use client::reconnecting::SubscribedClient as ReconnectingSubscribedClient; -pub use client::Client; -pub use client::Subscribed as SubscribedClient; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum Request { - Handshake { name: String }, - Actuate(protocol::Affector), - ListAffectors, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum Response { - Handshake, - Error(ServerError), - Actuate(Result<(), AffectorError>), - ListAffectors(Vec), - SubUpdate(SubMessage), - Subscribe, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum SubMessage { - Reading(protocol::Reading), - // an affector was moved/updated - AffectorControlled { - affector: protocol::Affector, - controlled_by: String, - }, - ErrorReport(Box), -} - -#[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)] -pub enum AffectorError { - #[error("We do not have a connection to the actuator's node")] - Offline, -} - -#[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)] -#[error("placeholder")] -pub struct SubscribeError; - -#[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)] -pub enum ServerError { - #[error("Could not activate affector")] - FailedToSpread, -} +pub mod data_source; +pub mod subscriber; diff --git a/crates/data-server/src/api/data_source.rs b/crates/data-server/src/api/data_source.rs new file mode 100644 index 00000000..dc8110b6 --- /dev/null +++ b/crates/data-server/src/api/data_source.rs @@ -0,0 +1,137 @@ +use protocol::affector; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf}; +use tokio::net::{TcpStream, ToSocketAddrs}; + +pub mod reconnecting; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Could not connect to data-server: {0}")] + Connecting(std::io::Error), + #[error("Could not send handshake to data-server: {0}")] + Handshake(std::io::Error), + #[error("Too many affectors, max: {max}, requires: {requires}")] + TooManyAffectors { max: usize, requires: usize }, +} + +pub struct Client { + sender: Sender, + receiver: Receiver, +} + +impl Client { + /// Needs a list of the affectors that can be controlled through this + /// node as an argument. If your node provides not controllable affectors + /// pass in an empty Vec. + pub async fn connect( + addr: impl ToSocketAddrs, + affectors: Vec, + ) -> Result { + let mut stream = TcpStream::connect(addr).await.map_err(Error::Connecting)?; + let mut list = protocol::affector::ListMessage::<50>::empty(); + + if affectors.len() > list.values.capacity() { + return Err(Error::TooManyAffectors { + max: list.values.capacity(), + requires: affectors.len(), + }); + } + for affector in affectors { + list.values.push(affector).expect("Is checked right above"); + } + let handshake = protocol::Msg::AffectorList(list); + let handshake = handshake.encode(); + stream + .write_all(&handshake) + .await + .map_err(Error::Handshake)?; + + let (reader, writer) = stream.into_split(); + + Ok(Self { + receiver: Receiver { + reader, + decoder: affector::Decoder::default(), + buffer: vec![0u8; 100], + }, + sender: Sender(writer), + }) + } + + /// # Cancel safety + /// This is cancel safe, if it is canceled the reading has not been send yet + pub async fn send_reading(&mut self, reading: protocol::Reading) -> Result<(), std::io::Error> { + self.sender.send_reading(reading).await + } + + /// # Cancel safety + /// This is cancel safe, if it is canceled the report has not been send yet + pub async fn send_error(&mut self, report: protocol::Error) -> Result<(), std::io::Error> { + self.sender.send_error(report).await + } + + pub fn split(self) -> (Sender, Receiver) { + (self.sender, self.receiver) + } +} + +pub struct Sender(OwnedWriteHalf); +pub struct Receiver { + reader: OwnedReadHalf, + decoder: affector::Decoder, + buffer: Vec, +} + +impl Sender { + pub async fn send_reading(&mut self, reading: protocol::Reading) -> Result<(), std::io::Error> { + let mut readings = protocol::SensorMessage::<1>::default(); + readings + .values + .push(reading) + .expect("capacity allows one push"); + let msg = protocol::Msg::Readings(readings); + let bytes = msg.encode(); + + self.0.write_all(&bytes).await + } + + pub async fn send_error(&mut self, report: protocol::Error) -> Result<(), std::io::Error> { + let msg = protocol::Msg::<1>::ErrorReport(protocol::ErrorReport::new(report)); + let bytes = msg.encode(); + + self.0.write_all(&bytes).await + } +} + +#[derive(Debug, thiserror::Error)] +pub enum ReceiveError { + #[error("General io error while receiving data from data-server")] + Io(std::io::Error), + #[error("The connection was closed by the data-server")] + ConnClosed, +} + +impl Receiver { + pub async fn receive(&mut self) -> Result { + loop { + if !self.buffer.is_empty() { + if let Some((item, remaining)) = self.decoder.feed(&mut self.buffer) { + let new_buffer = remaining.to_vec(); + self.buffer = new_buffer; + return Ok(item); + } + } + + self.buffer.resize(100, 0); + let res = self.reader.read(&mut self.buffer).await; + + let n_read = match res { + Ok(0) => return Err(ReceiveError::ConnClosed), + Ok(n_read) => n_read, + Err(e) => return Err(ReceiveError::Io(e)), + }; + self.buffer.truncate(n_read); + } + } +} diff --git a/crates/data-server/src/api/data_source/reconnecting.rs b/crates/data-server/src/api/data_source/reconnecting.rs new file mode 100644 index 00000000..b435bc1b --- /dev/null +++ b/crates/data-server/src/api/data_source/reconnecting.rs @@ -0,0 +1,110 @@ +use std::net::SocketAddr; +use std::time::Duration; +use tokio::time::{sleep, timeout}; +use tracing::{info, warn}; + +pub struct Client { + retry_period: Duration, + connection: Option, + addr: SocketAddr, + affectors: Vec, +} + +impl Client { + /// Needs a list of the affectors that can be controlled through this + /// node as an argument. If your node provides not controllable affectors + /// pass in an empty Vec. + #[must_use] + pub fn new(addr: SocketAddr, affectors: Vec) -> Self { + Self { + retry_period: Duration::from_millis(200), + connection: None, + addr, + affectors, + } + } + + /// # Cancel safety + /// This is cancel safe however the connection will need to be re-established + /// the next time its called. This will retry forever, you should call this + /// in a timeout future if that is a problem. + pub async fn send_reading(&mut self, reading: protocol::Reading) { + loop { + let mut conn = if let Some(conn) = self.connection.take() { + conn + } else { + get_connection_or_reconnect(self.addr, &self.affectors, &mut self.retry_period).await + }; + + match conn.send_reading(reading.clone()).await { + Ok(msg) => { + self.retry_period /= 2; + self.retry_period = self.retry_period.max(Duration::from_millis(200)); + self.connection = Some(conn); + return msg; + } + Err(issue) => { + warn!("Conn issue while getting next_msg: {issue}, reconnecting"); + } + }; + } + } + + /// # Cancel safety + /// This is cancel safe however the connection will need to be re-established + /// the next time its called. This will retry forever, you should call this + /// in a timeout future if that is a problem. + pub async fn send_error(&mut self, error: protocol::Error) { + loop { + let mut conn = if let Some(conn) = self.connection.take() { + conn + } else { + get_connection_or_reconnect(self.addr, &self.affectors, &mut self.retry_period).await + }; + + match conn.send_error(error.clone()).await { + Ok(msg) => { + self.retry_period /= 2; + self.retry_period = self.retry_period.max(Duration::from_millis(200)); + self.connection = Some(conn); + return msg; + } + Err(issue) => { + warn!("Conn issue while getting next_msg: {issue}, reconnecting"); + } + }; + } + } +} + +async fn get_connection_or_reconnect( + addr: SocketAddr, + affectors: &[protocol::Affector], + retry_period: &mut Duration, +) -> super::Client { + loop { + match timeout( + Duration::from_millis(500), + super::Client::connect(addr, affectors.to_vec()), + ) + .await + { + Ok(Ok(conn)) => { + info!("Successfully (re)connected to data-server"); + return conn; + } + Ok(Err(e)) => warn!( + "Failed to (re)connect: {e}\n\ + retrying in {:?}", + retry_period + ), + Err(_) => warn!( + "Failed to (re)connect, timed out.\n\ + retrying in {:?}", + retry_period + ), + } + sleep(*retry_period).await; + *retry_period = (*retry_period * 2).min(Duration::from_secs(5)); + } +} diff --git a/crates/data-server/src/api/subscriber.rs b/crates/data-server/src/api/subscriber.rs new file mode 100644 index 00000000..9283b847 --- /dev/null +++ b/crates/data-server/src/api/subscriber.rs @@ -0,0 +1,51 @@ +use serde::{Deserialize, Serialize}; +pub use client::reconnecting::Client as ReconnectingClient; +pub use client::reconnecting::SubscribedClient as ReconnectingSubscribedClient; +pub use client::Client; +pub use client::Subscribed as SubscribedClient; +pub mod client; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum Request { + Handshake { name: String }, + Actuate(protocol::Affector), + ListAffectors, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum Response { + Handshake, + Error(ServerError), + Actuate(Result<(), AffectorError>), + ListAffectors(Vec), + SubUpdate(SubMessage), + Subscribe, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum SubMessage { + Reading(protocol::Reading), + // An affector was moved/updated + AffectorControlled { + affector: protocol::Affector, + controlled_by: String, + }, + ErrorReport(Box), +} + +#[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)] +pub enum AffectorError { + #[error("We do not have a connection to the actuator's node")] + Offline, +} + +#[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)] +#[error("placeholder")] +pub struct SubscribeError; + +#[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)] +pub enum ServerError { + #[error("Could not activate affector")] + FailedToSpread, +} + diff --git a/crates/data-server/src/api/client.rs b/crates/data-server/src/api/subscriber/client.rs similarity index 90% rename from crates/data-server/src/api/client.rs rename to crates/data-server/src/api/subscriber/client.rs index d0d0e637..a1c62b7a 100644 --- a/crates/data-server/src/api/client.rs +++ b/crates/data-server/src/api/subscriber/client.rs @@ -4,10 +4,8 @@ use tokio::net::ToSocketAddrs; use super::AffectorError; use super::Request; use super::Response; -use super::ServerError; -use super::SubMessage; -use super::SubscribeError; +use crate::api::subscriber; pub(crate) mod reconnecting; #[derive(Debug)] @@ -49,7 +47,7 @@ impl Client { } } - pub async fn subscribe(mut self) -> Result> { + pub async fn subscribe(mut self) -> Result> { self.0.subscribe().await?; Ok(Subscribed(self)) } @@ -59,10 +57,10 @@ impl Client { pub struct Subscribed(Client); impl Subscribed { - pub async fn next(&mut self) -> Result> { + pub async fn next(&mut self) -> Result> { let received = self.0 .0.next().await?; - if let Response::SubUpdate(update) = received { + if let subscriber::Response::SubUpdate(update) = received { Ok(update) } else { Err(Error::IncorrectResponse { @@ -82,7 +80,7 @@ pub enum Error { #[error("Error while sending request: {0}")] Receiving(std::io::Error), #[error("General error while processing request")] - Server(ServerError), + Server(subscriber::ServerError), #[error("Server ran into an specific error with our request: {0}")] Request(T), #[error("Error while communicating with server: {0}")] diff --git a/crates/data-server/src/api/client/reconnecting.rs b/crates/data-server/src/api/subscriber/client/reconnecting.rs similarity index 98% rename from crates/data-server/src/api/client/reconnecting.rs rename to crates/data-server/src/api/subscriber/client/reconnecting.rs index abe3f1f7..5f0b5271 100644 --- a/crates/data-server/src/api/client/reconnecting.rs +++ b/crates/data-server/src/api/subscriber/client/reconnecting.rs @@ -1,4 +1,4 @@ -use crate::api::SubMessage; +use crate::api::subscriber; use std::net::SocketAddr; use std::time::Duration; @@ -102,7 +102,7 @@ pub struct SubscribedClient { } impl SubscribedClient { - pub async fn next(&mut self) -> SubMessage { + pub async fn next(&mut self) -> subscriber::SubMessage { loop { let conn = if let Some(conn) = self.connection.take() { conn diff --git a/crates/data-server/src/server.rs b/crates/data-server/src/server.rs index 3ec5c203..0a2f9677 100644 --- a/crates/data-server/src/server.rs +++ b/crates/data-server/src/server.rs @@ -14,14 +14,13 @@ pub use affector::Registar as AffectorRegistar; pub use data_source::handle_nodes; pub use subscribe::spread_updates; -use crate::api; -use crate::api::SubMessage; +use crate::api::subscriber::{self, SubMessage}; pub type Conn = tokio_serde::Framed< Framed, - api::Request, - api::Response, - Bincode, + subscriber::Request, + subscriber::Response, + Bincode, >; #[derive(Debug)] diff --git a/crates/data-server/src/server/client.rs b/crates/data-server/src/server/client.rs index db6db3d9..be679823 100644 --- a/crates/data-server/src/server/client.rs +++ b/crates/data-server/src/server/client.rs @@ -4,8 +4,7 @@ use tokio::sync::mpsc; use color_eyre::Result; -use crate::api::AffectorError; -use crate::api::{self, ServerError}; +use crate::api::subscriber; use super::{affector::Offline, affector::Registar, Event}; @@ -16,7 +15,7 @@ struct SubHandler { async fn do_setup( new_events: mpsc::Sender, -) -> impl Stream + Send + 'static { +) -> impl Stream + Send + 'static { let (tx, rx) = tokio::sync::mpsc::channel(100); new_events .send(Event::NewSub { tx }) @@ -25,13 +24,13 @@ async fn do_setup( stream::unfold(rx, |mut rx| async move { rx.recv() .await - .map(api::Response::SubUpdate) + .map(subscriber::Response::SubUpdate) .map(|yielded| (yielded, rx)) }) } impl rpc::SubscriberHandler for SubHandler { - type Update = crate::api::Response; + type Update = subscriber::Response; fn setup( &mut self, @@ -65,28 +64,28 @@ pub async fn handle( } async fn perform_request( - request: api::Request, + request: subscriber::Request, client_name: String, new_event: mpsc::Sender, affectors: Registar, -) -> api::Response { +) -> subscriber::Response { match perform_request_inner(request, client_name, new_event, affectors).await { Ok(response) => response, - Err(error) => api::Response::Error(error), + Err(error) => subscriber::Response::Error(error), } } async fn perform_request_inner( - request: api::Request, + request: subscriber::Request, client_name: String, new_event: mpsc::Sender, affectors: Registar, -) -> Result { +) -> Result { Ok(match request { - api::Request::Handshake { .. } => { + subscriber::Request::Handshake { .. } => { unreachable!("handshake only takes place during connection") } - api::Request::Actuate(affector) => match affectors.activate(affector) { + subscriber::Request::Actuate(affector) => match affectors.activate(affector) { Ok(()) => { new_event .send(Event::AffectorControlled { @@ -94,11 +93,11 @@ async fn perform_request_inner( controlled_by: client_name.to_owned(), }) .await - .map_err(|_| ServerError::FailedToSpread)?; - api::Response::Actuate(Ok(())) + .map_err(|_| subscriber::ServerError::FailedToSpread)?; + subscriber::Response::Actuate(Ok(())) } - Err(Offline) => api::Response::Actuate(Err(AffectorError::Offline)), + Err(Offline) => subscriber::Response::Actuate(Err(subscriber::AffectorError::Offline)), }, - api::Request::ListAffectors => api::Response::ListAffectors(affectors.list()), + subscriber::Request::ListAffectors => subscriber::Response::ListAffectors(affectors.list()), }) } diff --git a/crates/data-server/src/server/subscribe.rs b/crates/data-server/src/server/subscribe.rs index 58b3e8db..4d90c4dd 100644 --- a/crates/data-server/src/server/subscribe.rs +++ b/crates/data-server/src/server/subscribe.rs @@ -5,7 +5,7 @@ use tracing::trace; use color_eyre::Result; use super::Event; -use crate::api::SubMessage; +use crate::api::subscriber::SubMessage; pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { let mut subscribers = Vec::new(); diff --git a/crates/data-server/tests/api.rs b/crates/data-server/tests/api.rs deleted file mode 100644 index 11f09f4d..00000000 --- a/crates/data-server/tests/api.rs +++ /dev/null @@ -1,153 +0,0 @@ -use std::net::{Ipv4Addr, SocketAddr}; -use std::time::Duration; - -use color_eyre::Result; -use data_server::api::{Client, SubMessage}; -use data_server::server::{self, AffectorRegistar}; -use protocol::large_bedroom; -use protocol::large_bedroom::bed; -use protocol::Reading; -use tokio::io::AsyncWriteExt; -use tokio::net::TcpStream; -use tokio::select; -use tokio::sync::mpsc; -use tokio::time::sleep; - -#[derive(Debug, PartialEq)] -enum Done { - RunServer, - SendValue, - Test, -} - -async fn run_server( - client_addr: impl Into, - data_port: impl Into, -) -> Result { - let (tx, rx) = mpsc::channel(2000); - let affectors = AffectorRegistar::default(); - select! { - e = server::client::handle(client_addr.into(), tx.clone(), affectors.clone()) => e.unwrap(), - e = server::handle_nodes(data_port.into(), &tx, affectors) => e.unwrap(), - e = server::spread_updates(rx) => e?, - }; - - Ok(Done::RunServer) -} - -const TEST_READING: Reading = - Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::NumberPm2_5(0.0))); - -async fn send_sensor_value(data_port: u16) -> Result { - tokio::time::sleep(Duration::from_millis(500)).await; - - let mut list = protocol::affector::ListMessage::<50>::empty(); - list.values - .push(protocol::Affector::LargeBedroom( - large_bedroom::Affector::Bed(bed::Affector::Sps30FanClean), - )) - .unwrap(); - let handshake = protocol::Msg::AffectorList(list).encode(); - - let mut conn = TcpStream::connect(("127.0.0.1", data_port)).await.unwrap(); - conn.write_all(&handshake).await.unwrap(); - - let mut sensor_msg = protocol::SensorMessage::<50>::default(); - sensor_msg.values.push(TEST_READING).unwrap(); - let sensor_msg = protocol::Msg::Readings(sensor_msg).encode(); - conn.write_all(&sensor_msg).await.unwrap(); - - sleep(Duration::from_secs(999)).await; - Ok(Done::SendValue) -} - -async fn subscribe_and_receive_inner(sub_port: u16) -> Result { - tokio::time::sleep(Duration::from_millis(100)).await; - let mut sub = Client::connect( - (Ipv4Addr::LOCALHOST, sub_port), - "api_integration_tests".to_owned(), - ) - .await - .unwrap() - .subscribe() - .await - .unwrap(); - - let received = sub.next().await.unwrap(); - assert!(matches!(received, SubMessage::Reading(TEST_READING))); - - Ok(Done::Test) -} - -async fn list_affectors_inner(sub_port: u16) -> Result { - tokio::time::sleep(Duration::from_millis(500)).await; - let list = Client::connect( - (Ipv4Addr::LOCALHOST, sub_port), - "api_integration_tests".to_owned(), - ) - .await - .unwrap() - .list_affectors() - .await - .unwrap(); - - assert_eq!( - list, - [protocol::Affector::LargeBedroom( - large_bedroom::Affector::Bed(bed::Affector::Sps30FanClean) - )] - ); - - Ok(Done::Test) -} - -#[tokio::test] -async fn subscribe_and_receive() { - setup_tracing(); - - let sub_port = reserve_port::ReservedPort::random().unwrap(); - let data_port = reserve_port::ReservedPort::random().unwrap(); - let res = select! { - e = run_server(([127,0,0,1], sub_port.port()), ([127,0,0,1], data_port.port())) => e, - e = send_sensor_value(data_port.port()) => e, - e = subscribe_and_receive_inner(sub_port.port()) => e, - }; - assert_eq!(res.unwrap(), Done::Test); -} - -#[tokio::test] -async fn list_affectors() { - setup_tracing(); - - let sub_port = reserve_port::ReservedPort::random().unwrap(); - let data_port = reserve_port::ReservedPort::random().unwrap(); - let res = select! { - e = run_server(([127,0,0,1], sub_port.port()), ([127,0,0,1], data_port.port())) => e, - e = send_sensor_value(data_port.port()) => e, - e = list_affectors_inner(sub_port.port()) => e, - }; - assert_eq!(res.unwrap(), Done::Test); -} - -fn setup_tracing() { - use std::sync::Once; - use tracing_error::ErrorLayer; - use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt, Layer}; - - static INIT: Once = Once::new(); - - INIT.call_once(|| { - color_eyre::install().unwrap(); - - let file_subscriber = tracing_subscriber::fmt::layer() - .with_file(true) - .with_line_number(true) - .with_target(false) - .with_ansi(false) - .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()); - tracing_subscriber::registry() - .with(file_subscriber) - .with(ErrorLayer::default()) - .init(); - }) -} diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index ca2b4419..8df8766a 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -4,11 +4,11 @@ use std::path::Path; use std::sync::Arc; use std::time::{Duration, Instant}; -use data_server::api::ReconnectingClient; -use tokio::sync::Mutex; +use data_server::api::subscriber::ReconnectingClient; +use data_server::api::subscriber::SubMessage; +use tokio::sync::Mutex; use color_eyre::{Result, Section}; -use data_server::api::SubMessage; mod series; use series::Series; diff --git a/crates/desk-sensors/Cargo.toml b/crates/desk-sensors/Cargo.toml index a63a10c9..d01e2128 100644 --- a/crates/desk-sensors/Cargo.toml +++ b/crates/desk-sensors/Cargo.toml @@ -10,13 +10,15 @@ linux-embedded-hal = "0.4" gpiocdev-embedded-hal = { version = "0.1.1", features = ["async_tokio"] } bme280 = { version = "0.5", git = "https://github.com/dvdsk/bme280-rs", features = ["postcard", "serde", "with_std"] } +data-server = { workspace = true } +protocol = { workspace = true, features = ["alloc"] } + clap = { workspace = true} color-eyre = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace =true, features = ["env-filter"] } tracing-error = { workspace = true } -protocol = { workspace = true, features = ["alloc"] } tokio = { workspace = true, features = ["rt", "time", "macros"] } embedded-hal-async = "1.0.0" heapless = "0.8.0" diff --git a/crates/desk-sensors/src/main.rs b/crates/desk-sensors/src/main.rs index 7c4b9ec7..c95049e5 100644 --- a/crates/desk-sensors/src/main.rs +++ b/crates/desk-sensors/src/main.rs @@ -1,11 +1,11 @@ use clap::Parser; use color_eyre::Result; -use protocol::{Msg, SensorMessage}; -use std::io::{ErrorKind, Write}; -use std::net::{SocketAddr, TcpStream}; -use std::sync::mpsc::{self, Sender}; -use std::time::Duration; -use tracing::{debug, info, warn}; +use data_server::api::data_source; +use std::net::SocketAddr; + +use tokio::sync::mpsc::{self, Sender}; + +use tracing::info; mod sensors; @@ -19,58 +19,26 @@ struct Cli { update_port: u16, } -fn main() { +#[tokio::main(flavor = "current_thread")] +async fn main() { color_eyre::install().unwrap(); let cli = Cli::parse(); setup_tracing().unwrap(); - let (tx, rx) = mpsc::channel(); + let (tx, mut rx) = mpsc::channel(100); if let Err(error) = sensors::start_monitoring(tx.clone()) { send_error(&tx, error); } let addr = SocketAddr::from(([127, 0, 0, 1], cli.update_port)); info!("connecting to dataserver on: {}", cli.update_port); + let mut client = data_source::reconnecting::Client::new(addr, Vec::new()); loop { - let mut stream = match TcpStream::connect(addr) { - Ok(stream) => stream, - Err(err) if err.kind() == ErrorKind::ConnectionRefused => { - warn!("could not connect to data server, retrying in 5 seconds"); - std::thread::sleep(Duration::from_secs(5)); - continue; - } - Err(err) => panic!("could not connect to server: {}", err), - }; - - let bytes = - protocol::Msg::AffectorList(protocol::affector::ListMessage::<50>::empty()).encode(); - if stream.write_all(&bytes).is_err() { - std::thread::sleep(Duration::from_secs(5)); - break; // reconnect - } - - loop { - let result = rx.recv().unwrap(); - let msg = match result { - Ok(reading) => { - let mut readings = SensorMessage::<1>::default(); - readings - .values - .push(reading) - .expect("capacity allows one push"); - Msg::Readings(readings) - } - Err(report) => Msg::ErrorReport(protocol::ErrorReport::new(report)), - }; - - debug!("Sending message: {msg:?}"); - let bytes = msg.encode(); - if stream.write_all(&bytes).is_err() { - std::thread::sleep(Duration::from_secs(5)); - break; // reconnect - } + match rx.recv().await.expect("sensor monitoring never stops") { + Ok(reading) => client.send_reading(reading).await, + Err(report) => client.send_error(report).await, } } } @@ -98,7 +66,7 @@ fn send_error( ) { use protocol::large_bedroom::Error::Desk as DeskE; use protocol::Error::LargeBedroom as LbE; - tx.send(Err(LbE(DeskE(error)))).unwrap(); + tx.blocking_send(Err(LbE(DeskE(error)))).unwrap(); } fn send_reading( @@ -107,5 +75,5 @@ fn send_reading( ) { use protocol::large_bedroom::Reading::Desk; use protocol::Reading::LargeBedroom as Lb; - tx.send(Ok(Lb(Desk(reading)))).unwrap(); + tx.blocking_send(Ok(Lb(Desk(reading)))).unwrap(); } diff --git a/crates/desk-sensors/src/sensors.rs b/crates/desk-sensors/src/sensors.rs index 83c9f87a..e2decd81 100644 --- a/crates/desk-sensors/src/sensors.rs +++ b/crates/desk-sensors/src/sensors.rs @@ -4,7 +4,7 @@ use hal::{Delay, I2cdev}; use linux_embedded_hal as hal; use tracing::debug; -use std::sync::mpsc::Sender; +use tokio::sync::mpsc::Sender; use std::thread; use std::time::{Duration, Instant}; diff --git a/crates/log-store/src/server/db.rs b/crates/log-store/src/server/db.rs index d3395d89..251015b4 100644 --- a/crates/log-store/src/server/db.rs +++ b/crates/log-store/src/server/db.rs @@ -2,10 +2,10 @@ use std::net::SocketAddr; use std::path::Path; use std::time::{Duration, Instant}; -use data_server::api::ReconnectingClient; +use data_server::api::subscriber::ReconnectingClient; +use data_server::api::subscriber::SubMessage; use color_eyre::Result; -use data_server::api::SubMessage; mod log; pub(crate) use log::Logs; diff --git a/crates/sensor-tui/src/control.rs b/crates/sensor-tui/src/control.rs index bd2a9ebc..d15174a8 100644 --- a/crates/sensor-tui/src/control.rs +++ b/crates/sensor-tui/src/control.rs @@ -1,6 +1,6 @@ use std::net::SocketAddr; -use data_server::api::Client; +use data_server::api::subscriber::Client; use protocol::Affector; use tokio::sync::mpsc; use tracing::error; diff --git a/crates/sensor-tui/src/populate.rs b/crates/sensor-tui/src/populate.rs index 82d4756a..20bfe735 100644 --- a/crates/sensor-tui/src/populate.rs +++ b/crates/sensor-tui/src/populate.rs @@ -2,6 +2,7 @@ use std::net::SocketAddr; use std::sync::mpsc; use color_eyre::Result; +use data_server::api::subscriber; use tracing::warn; use crate::{client_name, Update}; @@ -40,7 +41,7 @@ pub fn tree( } async fn list_from_server(data_server_addr: SocketAddr, tx: mpsc::Sender) -> Result<()> { - let mut client = data_server::api::Client::connect(data_server_addr, client_name()).await?; + let mut client = subscriber::Client::connect(data_server_addr, client_name()).await?; let list = client.list_affectors().await?; tracing::debug!("affector list: {list:?}"); tx.send(Update::AffectorList(list)).unwrap(); diff --git a/crates/sensor-tui/src/receive.rs b/crates/sensor-tui/src/receive.rs index e59b3c18..811f6375 100644 --- a/crates/sensor-tui/src/receive.rs +++ b/crates/sensor-tui/src/receive.rs @@ -2,7 +2,7 @@ use std::net::SocketAddr; use std::sync::mpsc; use color_eyre::eyre::{Report, WrapErr}; -use data_server::api::{Client, SubMessage}; +use data_server::api::subscriber::{Client, SubMessage}; use crate::{client_name, Update}; diff --git a/crates/sensor-tui/src/tui/affectors.rs b/crates/sensor-tui/src/tui/affectors.rs index cc994ffb..50aea166 100644 --- a/crates/sensor-tui/src/tui/affectors.rs +++ b/crates/sensor-tui/src/tui/affectors.rs @@ -31,7 +31,6 @@ pub struct Tab { tree_state: TreeState, pub ground: Vec>, data: HashMap, - data_server: Option, } impl Tab { diff --git a/crates/text-widget/src/main.rs b/crates/text-widget/src/main.rs index af77ebe2..e5bafce7 100644 --- a/crates/text-widget/src/main.rs +++ b/crates/text-widget/src/main.rs @@ -1,7 +1,7 @@ use color_eyre::eyre::{eyre, Context}; use color_eyre::Result; -use data_server::api::SubMessage; -use data_server::api::{ReconnectingClient, ReconnectingSubscribedClient}; +use data_server::api::subscriber::SubMessage; +use data_server::api::subscriber::{ReconnectingClient, ReconnectingSubscribedClient}; use gethostname::gethostname; use protocol::reading::tree::Tree; use protocol::Reading; diff --git a/crates/text-widget/src/resolve.rs b/crates/text-widget/src/resolve.rs index 1723a4e2..fdfb122b 100644 --- a/crates/text-widget/src/resolve.rs +++ b/crates/text-widget/src/resolve.rs @@ -1,5 +1,5 @@ use color_eyre::eyre::eyre; -use data_server::api::ReconnectingSubscribedClient; +use data_server::api::subscriber::ReconnectingSubscribedClient; use nucleo_matcher::pattern::Pattern; use protocol::Reading; use std::time::Duration; diff --git a/crates/text-widget/src/resolve/fetch.rs b/crates/text-widget/src/resolve/fetch.rs index c9ba6761..b55f2bf7 100644 --- a/crates/text-widget/src/resolve/fetch.rs +++ b/crates/text-widget/src/resolve/fetch.rs @@ -1,6 +1,6 @@ use color_eyre::eyre::Context; -use data_server::api::ReconnectingSubscribedClient; -use data_server::api::SubMessage; +use data_server::api::subscriber::ReconnectingSubscribedClient; +use data_server::api::subscriber::SubMessage; use std::net::SocketAddr; use data_store::api::Client; From f086990d22dc7094042166f5dd3efefa29add258 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 6 Sep 2024 13:24:15 +0200 Subject: [PATCH 236/687] add small_bedroom desk sensor + make desk sensors program work for both rooms --- crates/desk-sensors/src/main.rs | 30 +--- crates/desk-sensors/src/room.rs | 95 +++++++++++ crates/desk-sensors/src/sensors.rs | 83 +++++----- crates/protocol/src/error.rs | 5 +- crates/protocol/src/lib.rs | 16 +- crates/protocol/src/small_bedroom.rs | 40 +++++ crates/protocol/src/small_bedroom/desk.rs | 183 ++++++++++++++++++++++ 7 files changed, 383 insertions(+), 69 deletions(-) create mode 100644 crates/desk-sensors/src/room.rs create mode 100644 crates/protocol/src/small_bedroom/desk.rs diff --git a/crates/desk-sensors/src/main.rs b/crates/desk-sensors/src/main.rs index c95049e5..7bc6b958 100644 --- a/crates/desk-sensors/src/main.rs +++ b/crates/desk-sensors/src/main.rs @@ -3,10 +3,11 @@ use color_eyre::Result; use data_server::api::data_source; use std::net::SocketAddr; -use tokio::sync::mpsc::{self, Sender}; +use tokio::sync::mpsc; use tracing::info; +mod room; mod sensors; #[derive(Parser)] @@ -14,9 +15,12 @@ mod sensors; #[command(version = "1.0")] #[command(about = "reads sensors attached to rpi gpio pins and i2c perhipheral")] struct Cli { - /// where to send the data on the local system + /// Where to send the data on the local system #[arg(short, long, default_value = "1234")] update_port: u16, + /// Is this the pi in the large bedroom or small bedroom? + #[arg(short, long)] + room: room::Bedroom, } #[tokio::main(flavor = "current_thread")] @@ -27,9 +31,7 @@ async fn main() { setup_tracing().unwrap(); let (tx, mut rx) = mpsc::channel(100); - if let Err(error) = sensors::start_monitoring(tx.clone()) { - send_error(&tx, error); - } + sensors::start_monitoring(tx.clone(), cli.room); let addr = SocketAddr::from(([127, 0, 0, 1], cli.update_port)); info!("connecting to dataserver on: {}", cli.update_port); @@ -59,21 +61,3 @@ fn setup_tracing() -> Result<()> { .init(); Ok(()) } - -fn send_error( - tx: &Sender>, - error: protocol::large_bedroom::desk::Error, -) { - use protocol::large_bedroom::Error::Desk as DeskE; - use protocol::Error::LargeBedroom as LbE; - tx.blocking_send(Err(LbE(DeskE(error)))).unwrap(); -} - -fn send_reading( - tx: &Sender>, - reading: protocol::large_bedroom::desk::Reading, -) { - use protocol::large_bedroom::Reading::Desk; - use protocol::Reading::LargeBedroom as Lb; - tx.blocking_send(Ok(Lb(Desk(reading)))).unwrap(); -} diff --git a/crates/desk-sensors/src/room.rs b/crates/desk-sensors/src/room.rs new file mode 100644 index 00000000..028d6ff9 --- /dev/null +++ b/crates/desk-sensors/src/room.rs @@ -0,0 +1,95 @@ +use protocol::Reading; + +#[derive(Debug, Clone, Copy, clap::ValueEnum)] +pub(crate) enum Bedroom { + Large, + Small, +} + +impl Bedroom { + pub(crate) fn make_temperature_reading(&self, value: f32) -> Reading { + match self { + Self::Large => { + use protocol::large_bedroom::desk::Reading as DeskReading; + wrap_large(DeskReading::Temperature(value)) + } + Self::Small => { + use protocol::small_bedroom::desk::Reading as DeskReading; + wrap_small(DeskReading::Temperature(value)) + } + } + } + pub(crate) fn make_humidity_reading(&self, value: f32) -> Reading { + match self { + Self::Large => { + use protocol::large_bedroom::desk::Reading as DeskReading; + wrap_large(DeskReading::Humidity(value)) + } + Self::Small => { + use protocol::small_bedroom::desk::Reading as DeskReading; + wrap_small(DeskReading::Humidity(value)) + } + } + } + pub(crate) fn make_pressure_reading(&self, value: f32) -> Reading { + match self { + Self::Large => { + use protocol::large_bedroom::desk::Reading as DeskReading; + wrap_large(DeskReading::Pressure(value)) + } + Self::Small => { + use protocol::small_bedroom::desk::Reading as DeskReading; + wrap_small(DeskReading::Pressure(value)) + } + } + } + + pub(crate) fn make_setup_error(&self, e: heapless::String<200>) -> protocol::Error { + match self { + Self::Large => { + use protocol::large_bedroom::desk; + let e = desk::SensorError::BmeError(e); + let e = desk::Error::Setup(e); + let e = protocol::large_bedroom::Error::Desk(e); + protocol::Error::LargeBedroom(e) + } + Self::Small => { + use protocol::small_bedroom::desk; + let e = desk::SensorError::BmeError(e); + let e = desk::Error::Setup(e); + let e = protocol::small_bedroom::Error::Desk(e); + protocol::Error::SmallBedroom(e) + } + } + } + + pub(crate) fn make_run_error(&self, e: heapless::String<200>) -> protocol::Error { + match self { + Self::Large => { + use protocol::large_bedroom::desk; + let e = desk::SensorError::BmeError(e); + let e = desk::Error::Running(e); + let e = protocol::large_bedroom::Error::Desk(e); + protocol::Error::LargeBedroom(e) + } + Self::Small => { + use protocol::small_bedroom::desk; + let e = desk::SensorError::BmeError(e); + let e = desk::Error::Running(e); + let e = protocol::small_bedroom::Error::Desk(e); + protocol::Error::SmallBedroom(e) + } + } + } +} + +fn wrap_small(reading: protocol::small_bedroom::desk::Reading) -> Reading { + use protocol::small_bedroom::Reading::Desk; + use protocol::Reading::SmallBedroom; + SmallBedroom(Desk(reading)) +} +fn wrap_large(reading: protocol::large_bedroom::desk::Reading) -> Reading { + use protocol::large_bedroom::Reading::Desk; + use protocol::Reading::LargeBedroom; + LargeBedroom(Desk(reading)) +} diff --git a/crates/desk-sensors/src/sensors.rs b/crates/desk-sensors/src/sensors.rs index e2decd81..ffac9042 100644 --- a/crates/desk-sensors/src/sensors.rs +++ b/crates/desk-sensors/src/sensors.rs @@ -2,64 +2,75 @@ use bme280::i2c::BME280 as Bme280; use bme280::{self, Measurements}; use hal::{Delay, I2cdev}; use linux_embedded_hal as hal; +use protocol::{ErrorString, Reading}; use tracing::debug; -use tokio::sync::mpsc::Sender; use std::thread; use std::time::{Duration, Instant}; +use tokio::sync::mpsc::Sender; -use protocol::large_bedroom::desk::Reading as DeskReading; -use protocol::large_bedroom::desk::{Error, SensorError}; -use protocol::Reading; - -use crate::{send_error, send_reading}; +use crate::room; -pub fn init() -> Result, Error> { +pub fn init() -> Result, ErrorString> { let i2c_bus = I2cdev::new("/dev/i2c-1") .inspect_err(|e| tracing::error!("Could not open i2c bus: {e}")) - .map_err(|e| protocol::make_error_string(e)) - .map_err(|e| Error::Setup(SensorError::BmeError(e)))?; + .map_err(|e| protocol::make_error_string(e))?; let mut bme280 = Bme280::new_primary(i2c_bus); bme280 .init(&mut Delay) .inspect_err(|e| tracing::error!("Could not init bme280 sensor: {e}")) - .map_err(|e| protocol::make_error_string(e)) - .map_err(|e| Error::Setup(SensorError::BmeError(e)))?; + .map_err(|e| protocol::make_error_string(e))?; Ok(bme280) } -pub fn start_monitoring(tx: Sender>) -> Result<(), Error> { - let mut bme = init()?; - +pub fn start_monitoring(tx: Sender>, room: room::Bedroom) { let mut last_warning = Instant::now() - Duration::from_secs(10_000); thread::spawn(move || loop { - match bme.measure(&mut Delay) { - Ok( - m @ Measurements { - temperature, - pressure, - humidity, - .. - }, - ) => { - debug!("got measurements: {m:?}"); - send_reading(&tx, DeskReading::Temperature(temperature)); - send_reading(&tx, DeskReading::Humidity(humidity)); - send_reading(&tx, DeskReading::Pressure(pressure)); - } + let mut bme = match init() { + Ok(driver) => driver, Err(e) => { - if last_warning.elapsed() > Duration::from_secs(300) { - last_warning = Instant::now(); - tracing::error!("Could not read bme280 sensor: {e}"); + tracing::error!("Could not setup bme280 sensor: {e}"); + tx.blocking_send(Err(room.make_setup_error(e))) + .expect("main should not return or panic"); + continue; + } + }; + + loop { + match bme.measure(&mut Delay) { + Ok( + m @ Measurements { + temperature, + pressure, + humidity, + .. + }, + ) => { + debug!("got measurements: {m:?}"); + tx.blocking_send(Ok(room.make_temperature_reading(temperature))) + .expect("main should not return or panic"); + tx.blocking_send(Ok(room.make_humidity_reading(humidity))) + .expect("main should not return or panic"); + tx.blocking_send(Ok(room.make_pressure_reading(pressure))) + .expect("main should not return or panic"); + } + Err(e) => { + if last_warning.elapsed() > Duration::from_secs(300) { + last_warning = Instant::now(); + tracing::error!("Could not read bme280 sensor: {e}"); + } + let e = protocol::make_error_string(e); + tx.blocking_send(Err(room.make_run_error(e))) + .expect("main should not return or panic"); + break; } - let err = protocol::make_error_string(e); - send_error(&tx, Error::Running(SensorError::BmeError(err))) } - } - std::thread::sleep(Duration::from_secs(5)); + std::thread::sleep(Duration::from_secs(5)); + } + std::thread::sleep(Duration::from_secs(20)); }); - Ok(()) + unreachable!() } diff --git a/crates/protocol/src/error.rs b/crates/protocol/src/error.rs index a84dd378..d7d3de14 100644 --- a/crates/protocol/src/error.rs +++ b/crates/protocol/src/error.rs @@ -1,7 +1,7 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; -use crate::{large_bedroom, Device}; +use crate::{large_bedroom, small_bedroom, Device}; #[derive( strum::EnumDiscriminants, @@ -17,6 +17,7 @@ use crate::{large_bedroom, Device}; )] pub enum Error { LargeBedroom(large_bedroom::Error), + SmallBedroom(small_bedroom::Error), } impl Error { @@ -24,6 +25,7 @@ impl Error { pub fn device(&self) -> Device { match self { Error::LargeBedroom(error) => Device::LargeBedroom(error.device()), + Error::SmallBedroom(error) => Device::SmallBedroom(error.device()), } } @@ -37,6 +39,7 @@ impl core::fmt::Display for Error { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { Error::LargeBedroom(error) => write!(f, "{error}"), + Error::SmallBedroom(error) => write!(f, "{error}"), } } } diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 03a67292..3b042f00 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -9,22 +9,20 @@ pub(crate) use button::button_enum; pub mod large_bedroom; pub mod small_bedroom; -pub mod reading; +pub mod affector; mod device; mod error; -pub mod affector; +pub mod reading; mod msg; -pub use msg::{Msg, DecodeMsgError}; -pub use msg::sensor::SensorMessage; -pub use msg::error::ErrorReport; -pub use msg::error::make_error_string; -pub use reading::Reading; +pub use affector::Affector; pub use device::Device; pub use device::Info as DeviceInfo; pub use error::Error; -pub use affector::Affector; - +pub use msg::error::{make_error_string, ErrorReport, ErrorString}; +pub use msg::sensor::SensorMessage; +pub use msg::{DecodeMsgError, Msg}; +pub use reading::Reading; #[derive(Debug, Clone)] pub enum Unit { diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index 8ad6557a..fa8a123c 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -7,6 +7,8 @@ use crate::button::Press; #[cfg(feature = "alloc")] use crate::reading::tree::{Item, Tree}; +pub mod desk; + crate::button_enum! { /// +-----------------------------------------+ /// | TopLeft | TopMiddle | TopRight | @@ -38,6 +40,7 @@ crate::button_enum! { #[repr(u8)] pub enum Reading { ButtonPanel(ButtonPanel) = 0, + Desk(desk::Reading) = 1, } #[cfg(feature = "alloc")] @@ -45,6 +48,7 @@ impl Tree for Reading { fn inner(&self) -> Item<'_> { match self { Reading::ButtonPanel(inner) => return Item::Node(inner), + Reading::Desk(inner) => return Item::Node(inner), } } @@ -58,6 +62,40 @@ impl Reading { pub fn is_same_as(&self, other: &Self) -> bool { match (self, other) { (Self::ButtonPanel(a), Self::ButtonPanel(b)) => a.is_same_as(b), + (Self::Desk(a), Self::Desk(b)) => a.is_same_as(b), + _ => false, + } + } +} + +#[derive( + strum::EnumDiscriminants, + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + Eq, + PartialEq, +)] +pub enum Error { + Desk(desk::Error), +} + +impl Error { + #[must_use] + pub fn device(&self) -> Device { + match self { + Error::Desk(error) => Device::Desk(error.device()), + } + } +} + +impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Error::Desk(error) => write!(f, "{error}"), } } } @@ -65,6 +103,7 @@ impl Reading { #[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Hash, PartialEq, Eq)] pub enum Device { Gpio, + Desk(desk::Device), } macro_rules! tree { @@ -96,6 +135,7 @@ impl Device { min_sample_interval: Duration::from_millis(2), max_sample_interval: Duration::MAX, }, + Device::Desk(device) => device.info(), } } } diff --git a/crates/protocol/src/small_bedroom/desk.rs b/crates/protocol/src/small_bedroom/desk.rs new file mode 100644 index 00000000..3325e032 --- /dev/null +++ b/crates/protocol/src/small_bedroom/desk.rs @@ -0,0 +1,183 @@ +use core::time::Duration; + +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "alloc")] +use crate::reading::tree::{Item, Tree}; +#[cfg(feature = "alloc")] +use crate::reading::Info; +#[cfg(feature = "alloc")] +use crate::Unit; + +#[derive( + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, +)] +#[strum_discriminants(derive(Hash))] +#[repr(u8)] +pub enum Reading { + Temperature(f32) = 0, + Humidity(f32) = 1, + Pressure(f32) = 2, +} + +#[cfg(feature = "alloc")] +impl Tree for Reading { + #[must_use] + fn inner(&self) -> Item<'_> { + let leaf = match self { + Reading::Temperature(val) => Info { + val: *val, + device: Device::Bme280.rooted(), + resolution: 0.01, + range: -10.0..45.0, + unit: Unit::C, + description: "Temperature", + branch_id: self.branch_id(), + }, + Reading::Humidity(val) => Info { + val: *val, + device: Device::Bme280.rooted(), + resolution: 0.008, + range: 0.0..100.0, + unit: Unit::RH, + description: "Humidity", + branch_id: self.branch_id(), + }, + Reading::Pressure(val) => Info { + val: *val, + device: Device::Bme280.rooted(), + range: 87_000.0..108_100.0, + resolution: 0.18, + unit: Unit::Pa, + description: "Air pressure", + branch_id: self.branch_id(), + }, + }; + Item::Leaf(leaf) + } + + #[must_use] + fn branch_id(&self) -> crate::reading::tree::Id { + ReadingDiscriminants::from(self) as crate::reading::tree::Id + } +} + +impl Reading { + #[must_use] + pub fn is_same_as(&self, other: &Self) -> bool { + match (self, other) { + (Reading::Temperature(_), Self::Temperature(_)) + | (Reading::Humidity(_), Self::Humidity(_)) + | (Reading::Pressure(_), Self::Pressure(_)) => true, + _ => false, + } + } +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +pub enum Error { + Running(SensorError), + Setup(SensorError), + SetupTimedOut(Device), + Timeout(Device), +} + +impl Error { + #[must_use] + pub fn device(&self) -> Device { + match self { + Self::Running(sensor_err) | Self::Setup(sensor_err) => sensor_err.device(), + Self::SetupTimedOut(device) | Self::Timeout(device) => device.clone(), + } + } +} + +impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Error::Running(e) => write!(f, "{} ran into error: {e}", e.device()), + Error::Setup(e) => write!(f, "{} errored during setup: {e}", e.device()), + Error::SetupTimedOut(d) => write!(f, "{d} timed out during setup"), + Error::Timeout(d) => write!(f, "{d} timed out while running"), + } + } +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, Eq, PartialEq)] +pub enum SensorError { + BmeError(heapless::String<200>), +} + +impl MaxSize for SensorError { + const POSTCARD_MAX_SIZE: usize = 200 + 1; +} + +impl SensorError { + #[must_use] + pub fn device(&self) -> Device { + match self { + SensorError::BmeError(_) => Device::Bme280, + } + } +} + +impl core::fmt::Display for SensorError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + SensorError::BmeError(e) => write!(f, "{e}"), + } + } +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq, Hash)] +pub enum Device { + Bme280, +} + +impl core::fmt::Display for Device { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.info().name) + } +} + +macro_rules! rtree { + [$($reading:expr),+] => { + [$(crate::Reading::SmallBedroom( + crate::small_bedroom::Reading::Desk($reading), + )),+] + }; +} + +impl Device { + #[must_use] + pub fn rooted(self) -> crate::Device { + crate::Device::SmallBedroom(crate::small_bedroom::Device::Desk(self)) + } + + #[must_use] + pub const fn info(&self) -> crate::DeviceInfo { + match self { + Device::Bme280 => crate::DeviceInfo { + name: "Bme280", + affects_readings: &rtree![ + Reading::Temperature(0.0), + Reading::Humidity(0.0), + Reading::Pressure(0.0) + ], + affectors: &[], + min_sample_interval: Duration::from_secs(5), + max_sample_interval: Duration::from_secs(5), + temporal_resolution: Duration::from_secs(1), + }, + } + } +} From 6c072bf19598be6e9099f329a099c9419efd1d7d Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 6 Sep 2024 13:24:42 +0200 Subject: [PATCH 237/687] data-server: fix re-add renamed integration test --- crates/data-server/tests/subscriber_api.rs | 153 +++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 crates/data-server/tests/subscriber_api.rs diff --git a/crates/data-server/tests/subscriber_api.rs b/crates/data-server/tests/subscriber_api.rs new file mode 100644 index 00000000..e99b1580 --- /dev/null +++ b/crates/data-server/tests/subscriber_api.rs @@ -0,0 +1,153 @@ +use std::net::{Ipv4Addr, SocketAddr}; +use std::time::Duration; + +use color_eyre::Result; +use data_server::api::subscriber::{Client, SubMessage}; +use data_server::server::{self, AffectorRegistar}; +use protocol::large_bedroom; +use protocol::large_bedroom::bed; +use protocol::Reading; +use tokio::io::AsyncWriteExt; +use tokio::net::TcpStream; +use tokio::select; +use tokio::sync::mpsc; +use tokio::time::sleep; + +#[derive(Debug, PartialEq)] +enum Done { + RunServer, + SendValue, + Test, +} + +async fn run_server( + client_addr: impl Into, + data_port: impl Into, +) -> Result { + let (tx, rx) = mpsc::channel(2000); + let affectors = AffectorRegistar::default(); + select! { + e = server::client::handle(client_addr.into(), tx.clone(), affectors.clone()) => e.unwrap(), + e = server::handle_nodes(data_port.into(), &tx, affectors) => e.unwrap(), + e = server::spread_updates(rx) => e?, + }; + + Ok(Done::RunServer) +} + +const TEST_READING: Reading = + Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::NumberPm2_5(0.0))); + +async fn send_sensor_value(data_port: u16) -> Result { + tokio::time::sleep(Duration::from_millis(500)).await; + + let mut list = protocol::affector::ListMessage::<50>::empty(); + list.values + .push(protocol::Affector::LargeBedroom( + large_bedroom::Affector::Bed(bed::Affector::Sps30FanClean), + )) + .unwrap(); + let handshake = protocol::Msg::AffectorList(list).encode(); + + let mut conn = TcpStream::connect(("127.0.0.1", data_port)).await.unwrap(); + conn.write_all(&handshake).await.unwrap(); + + let mut sensor_msg = protocol::SensorMessage::<50>::default(); + sensor_msg.values.push(TEST_READING).unwrap(); + let sensor_msg = protocol::Msg::Readings(sensor_msg).encode(); + conn.write_all(&sensor_msg).await.unwrap(); + + sleep(Duration::from_secs(999)).await; + Ok(Done::SendValue) +} + +async fn subscribe_and_receive_inner(sub_port: u16) -> Result { + tokio::time::sleep(Duration::from_millis(100)).await; + let mut sub = Client::connect( + (Ipv4Addr::LOCALHOST, sub_port), + "api_integration_tests".to_owned(), + ) + .await + .unwrap() + .subscribe() + .await + .unwrap(); + + let received = sub.next().await.unwrap(); + assert!(matches!(received, SubMessage::Reading(TEST_READING))); + + Ok(Done::Test) +} + +async fn list_affectors_inner(sub_port: u16) -> Result { + tokio::time::sleep(Duration::from_millis(500)).await; + let list = Client::connect( + (Ipv4Addr::LOCALHOST, sub_port), + "api_integration_tests".to_owned(), + ) + .await + .unwrap() + .list_affectors() + .await + .unwrap(); + + assert_eq!( + list, + [protocol::Affector::LargeBedroom( + large_bedroom::Affector::Bed(bed::Affector::Sps30FanClean) + )] + ); + + Ok(Done::Test) +} + +#[tokio::test] +async fn subscribe_and_receive() { + setup_tracing(); + + let sub_port = reserve_port::ReservedPort::random().unwrap(); + let data_port = reserve_port::ReservedPort::random().unwrap(); + let res = select! { + e = run_server(([127,0,0,1], sub_port.port()), ([127,0,0,1], data_port.port())) => e, + e = send_sensor_value(data_port.port()) => e, + e = subscribe_and_receive_inner(sub_port.port()) => e, + }; + assert_eq!(res.unwrap(), Done::Test); +} + +#[tokio::test] +async fn list_affectors() { + setup_tracing(); + + let sub_port = reserve_port::ReservedPort::random().unwrap(); + let data_port = reserve_port::ReservedPort::random().unwrap(); + let res = select! { + e = run_server(([127,0,0,1], sub_port.port()), ([127,0,0,1], data_port.port())) => e, + e = send_sensor_value(data_port.port()) => e, + e = list_affectors_inner(sub_port.port()) => e, + }; + assert_eq!(res.unwrap(), Done::Test); +} + +fn setup_tracing() { + use std::sync::Once; + use tracing_error::ErrorLayer; + use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt, Layer}; + + static INIT: Once = Once::new(); + + INIT.call_once(|| { + color_eyre::install().unwrap(); + + let file_subscriber = tracing_subscriber::fmt::layer() + .with_file(true) + .with_line_number(true) + .with_target(false) + .with_ansi(false) + .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()); + tracing_subscriber::registry() + .with(file_subscriber) + .with(ErrorLayer::default()) + .init(); + }) +} From c82baf4370f7fd0fa7e7132073e9cc9edf2c3096 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 6 Sep 2024 13:26:27 +0200 Subject: [PATCH 238/687] rename argument --- crates/desk-sensors/src/{room.rs => bedroom.rs} | 0 crates/desk-sensors/src/main.rs | 6 +++--- crates/desk-sensors/src/sensors.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename crates/desk-sensors/src/{room.rs => bedroom.rs} (100%) diff --git a/crates/desk-sensors/src/room.rs b/crates/desk-sensors/src/bedroom.rs similarity index 100% rename from crates/desk-sensors/src/room.rs rename to crates/desk-sensors/src/bedroom.rs diff --git a/crates/desk-sensors/src/main.rs b/crates/desk-sensors/src/main.rs index 7bc6b958..c6f49153 100644 --- a/crates/desk-sensors/src/main.rs +++ b/crates/desk-sensors/src/main.rs @@ -7,7 +7,7 @@ use tokio::sync::mpsc; use tracing::info; -mod room; +mod bedroom; mod sensors; #[derive(Parser)] @@ -20,7 +20,7 @@ struct Cli { update_port: u16, /// Is this the pi in the large bedroom or small bedroom? #[arg(short, long)] - room: room::Bedroom, + bedroom: bedroom::Bedroom, } #[tokio::main(flavor = "current_thread")] @@ -31,7 +31,7 @@ async fn main() { setup_tracing().unwrap(); let (tx, mut rx) = mpsc::channel(100); - sensors::start_monitoring(tx.clone(), cli.room); + sensors::start_monitoring(tx.clone(), cli.bedroom); let addr = SocketAddr::from(([127, 0, 0, 1], cli.update_port)); info!("connecting to dataserver on: {}", cli.update_port); diff --git a/crates/desk-sensors/src/sensors.rs b/crates/desk-sensors/src/sensors.rs index ffac9042..598baaa4 100644 --- a/crates/desk-sensors/src/sensors.rs +++ b/crates/desk-sensors/src/sensors.rs @@ -9,7 +9,7 @@ use std::thread; use std::time::{Duration, Instant}; use tokio::sync::mpsc::Sender; -use crate::room; +use crate::bedroom; pub fn init() -> Result, ErrorString> { let i2c_bus = I2cdev::new("/dev/i2c-1") @@ -24,7 +24,7 @@ pub fn init() -> Result, ErrorString> { Ok(bme280) } -pub fn start_monitoring(tx: Sender>, room: room::Bedroom) { +pub fn start_monitoring(tx: Sender>, room: bedroom::Bedroom) { let mut last_warning = Instant::now() - Duration::from_secs(10_000); thread::spawn(move || loop { let mut bme = match init() { From b0afb14370bcd8def0e68bd6b10b1f76ddb251ba Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 6 Sep 2024 20:38:31 +0200 Subject: [PATCH 239/687] tui: adds error reporting --- crates/sensor-tui/src/tui.rs | 43 +++++++-- crates/sensor-tui/src/tui/affectors.rs | 17 ++-- crates/sensor-tui/src/tui/render.rs | 25 ++++- crates/sensor-tui/src/tui/reports.rs | 123 +++++++++++++++++++++++++ 4 files changed, 190 insertions(+), 18 deletions(-) create mode 100644 crates/sensor-tui/src/tui/reports.rs diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index 3a153aa9..67e4cebc 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -8,7 +8,7 @@ use ratatui::{ prelude::{CrosstermBackend, Terminal}, style::{Color, Style}, }; -use render::render_tab; +use render::render; use std::{ io::{stdout, Stdout}, sync::mpsc, @@ -20,6 +20,7 @@ use crate::{Fetch, Update, UserIntent}; mod affectors; mod readings; mod render; +mod reports; #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] enum ActiveTab { @@ -84,6 +85,7 @@ struct App { active_tab: ActiveTab, readings_tab: readings::Tab, affectors_tab: affectors::Tab, + reports: reports::Reports, } impl App { @@ -96,7 +98,7 @@ impl App { ) -> Result<(), std::io::Error> { loop { terminal.draw(|frame| { - let layout = render_tab(frame, self); + let layout = render(frame, self); match self.active_tab { ActiveTab::Readings => { self.readings_tab @@ -110,25 +112,28 @@ impl App { if let event::Event::Key(key) = event::read()? { tracing::trace!("key pressed: {key:?}"); if key.kind == KeyEventKind::Press { - match key.code { + let res = match key.code { KeyCode::Left => { self.active_tab = self.active_tab.swap(); + None } KeyCode::Right => { self.active_tab = self.active_tab.swap(); + None } KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => { break Ok(()); } - _ => (), + _ => Some(key), } - - let res = match self.active_tab { + .and_then(|key| match self.active_tab { ActiveTab::Readings => self.readings_tab.handle_key(key), ActiveTab::Affectors => { self.affectors_tab.handle_key(key, &mut control_tx) } - }; + }) + .and_then(|key| self.reports.handle_key(key)); + if let Some(unhandled_key) = res { match unhandled_key.code { KeyCode::Char('q') | KeyCode::Esc => return Ok(()), @@ -143,8 +148,30 @@ impl App { continue; }; - self.affectors_tab.process_update(&update); + let Some(update) = self.register_errors(update) else { + continue; + }; + let Some(update) = self.affectors_tab.process_update(update) else { + continue; + }; self.readings_tab.process_update(update); } } + + fn register_errors(&mut self, update: Update) -> Option { + match update { + Update::AffectorControlled { .. } + | Update::AffectorList(_) + | Update::DeviceList(_) + | Update::Fetched { .. } + | Update::ReadingList(_) + | Update::SensorError(_) + | Update::SensorReading(_) => return Some(update), + Update::FetchError(e) => self.reports.add(e.wrap_err("Error fetching data")), + Update::SubscribeError(e) => self + .reports + .add(e.wrap_err("Error while subscribing to data-server")), + } + None + } } diff --git a/crates/sensor-tui/src/tui/affectors.rs b/crates/sensor-tui/src/tui/affectors.rs index 50aea166..f877f936 100644 --- a/crates/sensor-tui/src/tui/affectors.rs +++ b/crates/sensor-tui/src/tui/affectors.rs @@ -87,33 +87,38 @@ impl Tab { None } - pub fn process_update(&mut self, update: &Update) { - match update { + pub fn process_update(&mut self, update: Update) -> Option { + let update = match update { Update::ReadingList(_) | Update::Fetched { .. } | Update::FetchError(_) | Update::SensorReading(_) | Update::DeviceList(_) - | Update::SubscribeError(_) => return, + | Update::SubscribeError(_) => Some(update), Update::AffectorControlled { affector, .. } => { - self.update_tree(affector, DeviceBroken::No); + self.update_tree(&affector, DeviceBroken::No); + None } - Update::SensorError(err) => { + Update::SensorError(ref err) => { let broken = err.device().info().affectors; for affector in broken { self.update_tree(affector, DeviceBroken::Yes); } + Some(update) } Update::AffectorList(affectors) => { for affector in affectors { - self.update_tree(affector, DeviceBroken::No); + self.update_tree(&affector, DeviceBroken::No); } + None } }; if self.tree_state.selected().is_empty() { self.tree_state.select_first(); } + + update } } diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs index bd49bbb9..f15fa934 100644 --- a/crates/sensor-tui/src/tui/render.rs +++ b/crates/sensor-tui/src/tui/render.rs @@ -4,11 +4,29 @@ use ratatui::Frame; use super::App; -pub(super) fn render_tab(frame: &mut Frame, app: &App) -> Rect { - let [topline, rest] = Layout::vertical([Constraint::Min(1), Constraint::Fill(1)]) +pub(super) fn render(frame: &mut Frame, app: &App) -> Rect { + let report_needs_lines = app.reports.needed_lines(); + let constraints = report_needs_lines + .map(|l| Constraint::Max(l)) + .into_iter() + .chain([Constraint::Min(1), Constraint::Fill(1)]); + let layout = Layout::default() + .constraints(constraints) .flex(Flex::Legacy) - .areas(frame.area()); + .split(frame.area()); + let mut layout = layout.into_iter(); + if report_needs_lines.is_some() { + app.reports + .render(frame, *layout.next().expect("is long enough")) + } + + render_tab_bar(app, frame, *layout.next().expect("is long enough")); + + *layout.next().expect("is long enough") +} + +fn render_tab_bar(app: &App, frame: &mut Frame, topline: Rect) { let tabs = Tabs::new(vec!["Readings", "Affectors"]) .style(app.theme.bars) .select(app.active_tab.number()) @@ -16,5 +34,4 @@ pub(super) fn render_tab(frame: &mut Frame, app: &App) -> Rect { .padding(" ", " "); frame.render_widget(tabs, topline); - rest } diff --git a/crates/sensor-tui/src/tui/reports.rs b/crates/sensor-tui/src/tui/reports.rs new file mode 100644 index 00000000..1f3e060d --- /dev/null +++ b/crates/sensor-tui/src/tui/reports.rs @@ -0,0 +1,123 @@ +use std::collections::{HashSet, VecDeque}; + +use color_eyre::eyre; +use crossterm::event::{KeyCode, KeyEvent}; +use ratatui::layout::{Alignment, Constraint, Layout, Rect}; +use ratatui::style::{Color, Style, Styled, Stylize}; +use ratatui::text::Text; +use ratatui::Frame; + +#[derive(Debug, PartialEq, Eq, Hash)] +struct Report { + short: String, + detailed: String, +} + +impl From for Report { + fn from(value: eyre::Report) -> Self { + Self { + short: value.to_string(), + detailed: format!("{value:#}"), + } + } +} + +#[derive(Debug, Default)] +pub(super) struct Reports { + list: VecDeque, + current: Option, + to_ignore: HashSet, + show_details: bool, +} + +impl Reports { + pub(super) fn add(&mut self, raw_report: eyre::Report) { + let report = Report::from(raw_report); + if self.to_ignore.contains(&report) { + return; + } + + if let Some(prev) = self.current.take() { + self.list.push_front(prev); + } + self.current = Some(report); + } + + pub(super) fn render(&self, frame: &mut Frame, layout: Rect) { + let current = self + .current + .as_ref() + .expect("should only be called when current is Some/needed lines > 0"); + + let [hint, error] = + Layout::vertical(&[Constraint::Max(1), Constraint::Min(1)]).areas(layout); + + let error_style = Style::default().on_light_red().fg(Color::White); + + if self.show_details { + frame.render_widget( + Text::raw("e: hide details, x: close this error, i: ignore this error") + .alignment(Alignment::Center) + .style(error_style), + hint, + ); + frame.render_widget(Text::raw(¤t.detailed).style(error_style), error); + } else { + frame.render_widget( + Text::raw("e: show details, x: close this error, i: ignore this error") + .alignment(Alignment::Center) + .style(error_style), + hint, + ); + frame.render_widget(Text::raw(¤t.short).style(error_style), error); + } + } + + pub(super) fn needed_lines(&self) -> Option { + let Some(ref current) = self.current else { + return None; + }; + + Some(if self.show_details { + 1 + current.detailed.lines().count() as u16 + } else { + 1 + current.short.lines().count() as u16 + }) + } + + fn close_current(&mut self) { + let Some(current) = self.current.take() else { + return + }; + + self.list.retain(|report| *report != current); + self.current = self.list.pop_front(); + } + + fn ignore_current(&mut self) { + let Some(current) = self.current.take() else { + return; // may have closed + }; + + self.list.retain(|report| *report != current); + + self.to_ignore.insert(current); + self.close_current() + } + + pub(crate) fn handle_key(&mut self, key: KeyEvent) -> Option { + match key.code { + KeyCode::Char('e') => { + self.show_details = !self.show_details; + } + KeyCode::Char('x') => { + self.close_current(); + } + KeyCode::Char('i') => { + self.ignore_current(); + } + _ => return Some(key), + } + None + } +} From 2b76d389ef9b95717ea9db5b586aa406b1581d9b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 6 Sep 2024 20:39:29 +0200 Subject: [PATCH 240/687] fixes to desk sensors and deploy scripts --- crates/brain/deploy.sh | 2 +- crates/brain/test.sh | 4 ++-- crates/data-server/deploy.sh | 3 +-- .../src/api/data_source/reconnecting.rs | 4 ++-- crates/data-store/deploy.sh | 2 +- crates/desk-sensors/.cargo/config.toml | 3 +++ crates/desk-sensors/deploy.sh | 17 ++++++++++++++++- crates/desk-sensors/src/main.rs | 9 ++++----- crates/desk-sensors/src/sensors.rs | 2 -- crates/log-store/deploy.sh | 2 +- 10 files changed, 31 insertions(+), 17 deletions(-) diff --git a/crates/brain/deploy.sh b/crates/brain/deploy.sh index 8b9b44e1..5e05c8dd 100755 --- a/crates/brain/deploy.sh +++ b/crates/brain/deploy.sh @@ -14,4 +14,4 @@ sudo chown ha:ha /home/ha/brain sudo systemctl restart brain " -ssh -t sgc "$cmds" +ssh -t $SERVER "$cmds" diff --git a/crates/brain/test.sh b/crates/brain/test.sh index 511a4787..9ed58c4b 100755 --- a/crates/brain/test.sh +++ b/crates/brain/test.sh @@ -2,7 +2,7 @@ SERVER="sgc" # ssh config name or full address cmds="sudo systemctl stop brain" -ssh -t sgc "$cmds" +ssh -t $SERVER "$cmds" RUST_LOG=reqwest::connect=info,hyper_util=info,sled=info,trace RUST_BACKTRACE=1 cargo r -- \ --data-server 192.168.1.43:1235 \ @@ -11,4 +11,4 @@ RUST_LOG=reqwest::connect=info,hyper_util=info,sled=info,trace RUST_BACKTRACE=1 --hue-bridge-ip 192.168.1.11 cmds="sudo systemctl start brain" -ssh -t sgc "$cmds" +ssh -t $SERVER "$cmds" diff --git a/crates/data-server/deploy.sh b/crates/data-server/deploy.sh index c2c4d614..3b255fd2 100755 --- a/crates/data-server/deploy.sh +++ b/crates/data-server/deploy.sh @@ -15,5 +15,4 @@ sudo mv /tmp/$NAME /home/ha/$NAME sudo chown ha:ha /home/ha/$NAME sudo systemctl restart $NAME.service " - -ssh -t sgc "$cmds" +ssh -t $SERVER "$cmds" diff --git a/crates/data-server/src/api/data_source/reconnecting.rs b/crates/data-server/src/api/data_source/reconnecting.rs index b435bc1b..07dd621a 100644 --- a/crates/data-server/src/api/data_source/reconnecting.rs +++ b/crates/data-server/src/api/data_source/reconnecting.rs @@ -44,7 +44,7 @@ impl Client { return msg; } Err(issue) => { - warn!("Conn issue while getting next_msg: {issue}, reconnecting"); + warn!("Conn issue while sending new reading: {issue}, reconnecting"); } }; } @@ -70,7 +70,7 @@ impl Client { return msg; } Err(issue) => { - warn!("Conn issue while getting next_msg: {issue}, reconnecting"); + warn!("Conn issue while sending new error: {issue}, reconnecting"); } }; } diff --git a/crates/data-store/deploy.sh b/crates/data-store/deploy.sh index b9d23e54..f91b103d 100755 --- a/crates/data-store/deploy.sh +++ b/crates/data-store/deploy.sh @@ -16,4 +16,4 @@ sudo chown ha:ha /home/ha/$NAME sudo systemctl restart $NAME.service " -ssh -t sgc "$cmds" +ssh -t $SERVER "$cmds" diff --git a/crates/desk-sensors/.cargo/config.toml b/crates/desk-sensors/.cargo/config.toml index 1002fed4..0127ae27 100644 --- a/crates/desk-sensors/.cargo/config.toml +++ b/crates/desk-sensors/.cargo/config.toml @@ -1,2 +1,5 @@ [target.aarch64-unknown-linux-musl] rustflags = ["-Clinker=rust-lld"] + +[target.armv7-unknown-linux-musleabihf] +rustflags = ["-Clinker=rust-lld"] diff --git a/crates/desk-sensors/deploy.sh b/crates/desk-sensors/deploy.sh index 9438f703..adab4d0f 100755 --- a/crates/desk-sensors/deploy.sh +++ b/crates/desk-sensors/deploy.sh @@ -16,4 +16,19 @@ sudo chown ha:ha /home/ha/desk-sensors sudo systemctl restart desk-sensors.service " -ssh -t sgc "$cmds" +ssh -t $SERVER "$cmds" + + +SERVER="atlantis" # ssh config name or full address +cargo build --target=armv7-unknown-linux-musleabihf $BUILD_ARG +rsync -vh --progress \ + ../../target/armv7-unknown-linux-musleabihf/$RELEASE/desk-sensors \ + $SERVER:/tmp/ + +cmds=" +sudo mv /tmp/desk-sensors /home/eva/desk-sensors +sudo chown eva:eva /home/eva/desk-sensors +sudo systemctl restart desk-sensors.service +" + +ssh -t $SERVER "$cmds" diff --git a/crates/desk-sensors/src/main.rs b/crates/desk-sensors/src/main.rs index c6f49153..7b04eacf 100644 --- a/crates/desk-sensors/src/main.rs +++ b/crates/desk-sensors/src/main.rs @@ -16,8 +16,8 @@ mod sensors; #[command(about = "reads sensors attached to rpi gpio pins and i2c perhipheral")] struct Cli { /// Where to send the data on the local system - #[arg(short, long, default_value = "1234")] - update_port: u16, + #[arg(short, long("data-server"))] + data_server: SocketAddr, /// Is this the pi in the large bedroom or small bedroom? #[arg(short, long)] bedroom: bedroom::Bedroom, @@ -33,9 +33,8 @@ async fn main() { let (tx, mut rx) = mpsc::channel(100); sensors::start_monitoring(tx.clone(), cli.bedroom); - let addr = SocketAddr::from(([127, 0, 0, 1], cli.update_port)); - info!("connecting to dataserver on: {}", cli.update_port); - let mut client = data_source::reconnecting::Client::new(addr, Vec::new()); + info!("connecting to dataserver on: {}", cli.data_server); + let mut client = data_source::reconnecting::Client::new(cli.data_server, Vec::new()); loop { match rx.recv().await.expect("sensor monitoring never stops") { diff --git a/crates/desk-sensors/src/sensors.rs b/crates/desk-sensors/src/sensors.rs index 598baaa4..fdfdf809 100644 --- a/crates/desk-sensors/src/sensors.rs +++ b/crates/desk-sensors/src/sensors.rs @@ -71,6 +71,4 @@ pub fn start_monitoring(tx: Sender>, room: bedr } std::thread::sleep(Duration::from_secs(20)); }); - - unreachable!() } diff --git a/crates/log-store/deploy.sh b/crates/log-store/deploy.sh index 86304111..2896f5d5 100755 --- a/crates/log-store/deploy.sh +++ b/crates/log-store/deploy.sh @@ -16,4 +16,4 @@ sudo chown ha:ha /home/ha/$NAME sudo systemctl restart $NAME.service " -ssh -t sgc "$cmds" +ssh -t $SERVER "$cmds" From 1bc98a59ac75bc3228a8b5c42027aa19c1b19d78 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 7 Sep 2024 02:55:52 +0200 Subject: [PATCH 241/687] tui: improve graph resolution by switching marker to braille --- crates/sensor-tui/src/tui/readings/render/chart.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/sensor-tui/src/tui/readings/render/chart.rs b/crates/sensor-tui/src/tui/readings/render/chart.rs index afc52fa7..082f6b2e 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart.rs @@ -13,7 +13,7 @@ use labels::labels; pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, chart: ChartParts) { let dataset = Dataset::default() - .marker(symbols::Marker::Dot) + .marker(symbols::Marker::Braille) .graph_type(GraphType::Line) .style(Style::default()) .data(chart.data); From c18cd2758eefbdd542efc5a8f957396e324e26dc Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 8 Sep 2024 11:02:51 +0200 Subject: [PATCH 242/687] desk-sensors adds cooldown on error --- crates/desk-sensors/src/sensors.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/desk-sensors/src/sensors.rs b/crates/desk-sensors/src/sensors.rs index fdfdf809..f8ab39a2 100644 --- a/crates/desk-sensors/src/sensors.rs +++ b/crates/desk-sensors/src/sensors.rs @@ -33,6 +33,7 @@ pub fn start_monitoring(tx: Sender>, room: bedr tracing::error!("Could not setup bme280 sensor: {e}"); tx.blocking_send(Err(room.make_setup_error(e))) .expect("main should not return or panic"); + std::thread::sleep(Duration::from_secs(5)); continue; } }; From 17b2ba41be27dceef561266e839b13cb0f603d80 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 8 Sep 2024 11:12:22 +0200 Subject: [PATCH 243/687] add ratelimit to datasources --- Cargo.lock | 1 + crates/data-server/Cargo.toml | 1 + crates/data-server/src/server/data_source.rs | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 6c541fed..a69d2a6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -856,6 +856,7 @@ dependencies = [ "color-eyre", "futures", "futures-concurrency", + "governor", "protocol", "reserve-port", "rpc", diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index 1da97afa..2b745c68 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -29,6 +29,7 @@ futures-concurrency = "7.6.1" slotmap = "1.0.7" tracing-futures = "0.2.5" socket2 = "0.5.7" +governor = "0.6.3" [dev-dependencies] reserve-port = "2" diff --git a/crates/data-server/src/server/data_source.rs b/crates/data-server/src/server/data_source.rs index 7ad83b23..efb137f4 100644 --- a/crates/data-server/src/server/data_source.rs +++ b/crates/data-server/src/server/data_source.rs @@ -1,9 +1,12 @@ use std::net::SocketAddr; +use std::num::NonZeroU32; use std::time::Duration; use color_eyre::eyre::{eyre, Context}; use color_eyre::{Result, Section}; use futures_concurrency::future::Race; +use governor::clock::Clock; +use governor::{Quota, RateLimiter}; use protocol::Affector; use socket2::TcpKeepalive; use tokio::io::{AsyncBufReadExt, BufReader}; @@ -120,8 +123,23 @@ async fn handshake(reader: &mut BufReader) -> Result, queue: Sender) { + let quota = Quota::with_period(Duration::from_secs(40)) + .unwrap() + .allow_burst(NonZeroU32::new(200u32).unwrap()); + let limiter = RateLimiter::direct(quota); + let mut buf = Vec::new(); loop { + if let Err(allowed_again) = limiter.check() { + let now = governor::clock::DefaultClock::default().now(); + let allowed_in = allowed_again.wait_time_from(now); + error!( + "Refusing to read packet: (generous) ratelimit surpassed. \ + Next packet allowed in {allowed_in:?}. Sleeping till then" + ); + tokio::time::sleep(allowed_in).await; + } + let msg = match read_and_decode_packet(&mut reader, &mut buf).await { Ok(decoded) => decoded, Err(e) => { From 91a2695e882501b091ff60fbf61932fd27069a76 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 8 Sep 2024 12:35:13 +0200 Subject: [PATCH 244/687] improve error display in tui --- Cargo.lock | 30 +++++++++++++++++++ .../data-server/src/api/subscriber/client.rs | 21 ++++++------- crates/data-store/src/api/client.rs | 18 ++++------- crates/log-store/src/api/client.rs | 17 +++++------ crates/rpc/src/client.rs | 2 +- crates/sensor-tui/Cargo.toml | 1 + crates/sensor-tui/src/tui/reports.rs | 24 +++++++++++++-- 7 files changed, 77 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a69d2a6c..7cca41ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3012,6 +3012,7 @@ dependencies = [ "log-store", "protocol", "ratatui", + "strip-ansi-escapes", "thiserror", "tokio", "tracing", @@ -3252,6 +3253,15 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" +[[package]] +name = "strip-ansi-escapes" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ff8ef943b384c414f54aefa961dd2bd853add74ec75e7ac74cf91dba62bcfa" +dependencies = [ + "vte", +] + [[package]] name = "strsim" version = "0.11.1" @@ -3745,6 +3755,26 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "vte" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197" +dependencies = [ + "utf8parse", + "vte_generate_state_changes", +] + +[[package]] +name = "vte_generate_state_changes" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "waker-fn" version = "1.2.0" diff --git a/crates/data-server/src/api/subscriber/client.rs b/crates/data-server/src/api/subscriber/client.rs index a1c62b7a..50ade317 100644 --- a/crates/data-server/src/api/subscriber/client.rs +++ b/crates/data-server/src/api/subscriber/client.rs @@ -1,4 +1,5 @@ use rpc::client::RpcClient; +use rpc::client::RpcError; use tokio::net::ToSocketAddrs; use super::AffectorError; @@ -27,10 +28,10 @@ impl Client { let request = Request::Actuate(affector); match self.0.send_receive(request.clone()).await? { Response::Actuate(res) => res.map_err(Error::Request), - response => Err(Error::IncorrectResponse { + response => Err(Error::Comms(RpcError::IncorrectResponse { request: format!("{request:?}"), response: format!("{response:?}"), - }), + })), } } @@ -40,10 +41,10 @@ impl Client { let request = Request::ListAffectors; match self.0.send_receive(request.clone()).await? { Response::ListAffectors(list) => Ok(list), - response => Err(Error::IncorrectResponse { + response => Err(Error::Comms(RpcError::IncorrectResponse { request: format!("{request:?}"), response: format!("{response:?}"), - }), + })), } } @@ -57,24 +58,24 @@ impl Client { pub struct Subscribed(Client); impl Subscribed { - pub async fn next(&mut self) -> Result> { + pub async fn next( + &mut self, + ) -> Result> { let received = self.0 .0.next().await?; if let subscriber::Response::SubUpdate(update) = received { Ok(update) } else { - Err(Error::IncorrectResponse { + Err(Error::Comms(RpcError::IncorrectResponse { request: "none, we are subscribed".to_string(), response: format!("{received:?}"), - }) + })) } } } #[derive(Debug, thiserror::Error)] pub enum Error { - #[error("Got unexpected response response to request {request:?}")] - IncorrectResponse { request: String, response: String }, #[error("Error while sending request: {0}")] Sending(std::io::Error), #[error("Error while sending request: {0}")] @@ -84,5 +85,5 @@ pub enum Error { #[error("Server ran into an specific error with our request: {0}")] Request(T), #[error("Error while communicating with server: {0}")] - Comms(#[from] rpc::client::RpcError), + Comms(#[from] RpcError), } diff --git a/crates/data-store/src/api/client.rs b/crates/data-store/src/api/client.rs index 58256a17..fc93fc90 100644 --- a/crates/data-store/src/api/client.rs +++ b/crates/data-store/src/api/client.rs @@ -1,18 +1,10 @@ -use rpc::client::RpcClient; +use rpc::client::{RpcClient, RpcError}; use tokio::net::ToSocketAddrs; use super::Response; pub struct Client(rpc::client::RpcClient); -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Got unexpected response response to request {request:?}")] - IncorrectResponse { request: String, response: String }, - #[error("Error while communicating with server: {0}")] - Comms(#[from] rpc::client::RpcError), -} - impl Client { pub async fn connect( addr: impl ToSocketAddrs, @@ -22,11 +14,11 @@ impl Client { Ok(Self(rpc_client)) } - pub async fn list_data(&mut self) -> Result, Error> { + pub async fn list_data(&mut self) -> Result, RpcError> { let request = super::Request::ListData; match self.0.send_receive(request.clone()).await? { Response::ListData(list) => Ok(list), - response => Err(Error::IncorrectResponse { + response => Err(RpcError::IncorrectResponse { request: format!("{request:?}"), response: format!("{response:?}"), }), @@ -39,7 +31,7 @@ impl Client { end: jiff::Timestamp, reading: protocol::Reading, n: usize, - ) -> Result<(Vec, Vec), Error> { + ) -> Result<(Vec, Vec), RpcError> { let request = super::Request::GetData { reading, start, @@ -48,7 +40,7 @@ impl Client { }; match self.0.send_receive(request.clone()).await? { Response::GetData { time, data } => Ok((time, data)), - response => Err(Error::IncorrectResponse { + response => Err(RpcError::IncorrectResponse { request: format!("{request:?}"), response: format!("{response:?}"), }), diff --git a/crates/log-store/src/api/client.rs b/crates/log-store/src/api/client.rs index 54b60e7a..32d10951 100644 --- a/crates/log-store/src/api/client.rs +++ b/crates/log-store/src/api/client.rs @@ -1,5 +1,6 @@ use protocol::Device; use rpc::client::RpcClient; +use rpc::client::RpcError; use tokio::net::ToSocketAddrs; use crate::api::Percentile; @@ -13,12 +14,10 @@ pub struct Client(rpc::client::RpcClient); #[derive(Debug, thiserror::Error)] pub enum Error { - #[error("Got unexpected response response to request {request:?}")] - IncorrectResponse { request: String, response: String }, #[error("Server ran into an specific error with our request: {0}")] Request(T), #[error("Error while communicating with server: {0}")] - Comms(#[from] rpc::client::RpcError), + Comms(#[from] RpcError), } impl Client { @@ -38,10 +37,10 @@ impl Client { match self.0.send_receive(request.clone()).await? { Response::GetStats(Ok(percentiles)) => Ok(percentiles), Response::GetStats(Err(e)) => Err(Error::Request(e)), - response => Err(Error::IncorrectResponse { + response => Err(Error::Comms(RpcError::IncorrectResponse { request: format!("{request:?}"), response: format!("{response:?}"), - }), + })), } } @@ -53,10 +52,10 @@ impl Client { match self.0.send_receive(request.clone()).await? { Response::GetLog(Ok(log)) => Ok(log), Response::GetLog(Err(e)) => Err(Error::Request(e)), - response => Err(Error::IncorrectResponse { + response => Err(Error::Comms(RpcError::IncorrectResponse { request: format!("{request:?}"), response: format!("{response:?}"), - }), + })), } } @@ -64,10 +63,10 @@ impl Client { let request = super::Request::ListDevices; match self.0.send_receive(request.clone()).await? { Response::ListDevices(logs) => Ok(logs), - response => Err(Error::IncorrectResponse { + response => Err(Error::Comms(RpcError::IncorrectResponse { request: format!("{request:?}"), response: format!("{response:?}"), - }), + })), } } } diff --git a/crates/rpc/src/client.rs b/crates/rpc/src/client.rs index 8a850a61..085d9a9d 100644 --- a/crates/rpc/src/client.rs +++ b/crates/rpc/src/client.rs @@ -52,7 +52,7 @@ pub enum ConnectError { #[derive(Debug, thiserror::Error)] pub enum RpcError { - #[error("Got unexpected response response to request {request:?}")] + #[error("Got unexpected response response to request.\nRequest was: {request:?},\nGot response: {response:?}")] IncorrectResponse { request: String, response: String }, #[error("Error while sending request: {0}")] Sending(std::io::Error), diff --git a/crates/sensor-tui/Cargo.toml b/crates/sensor-tui/Cargo.toml index 1c480129..0451d327 100644 --- a/crates/sensor-tui/Cargo.toml +++ b/crates/sensor-tui/Cargo.toml @@ -27,3 +27,4 @@ jiff = { workspace = true } thiserror.workspace = true itertools = "0.13.0" gethostname = "0.5.0" +strip-ansi-escapes = "0.2.0" diff --git a/crates/sensor-tui/src/tui/reports.rs b/crates/sensor-tui/src/tui/reports.rs index 1f3e060d..b0470c07 100644 --- a/crates/sensor-tui/src/tui/reports.rs +++ b/crates/sensor-tui/src/tui/reports.rs @@ -5,6 +5,7 @@ use crossterm::event::{KeyCode, KeyEvent}; use ratatui::layout::{Alignment, Constraint, Layout, Rect}; use ratatui::style::{Color, Style, Styled, Stylize}; use ratatui::text::Text; +use ratatui::widgets::{Paragraph, Wrap}; use ratatui::Frame; #[derive(Debug, PartialEq, Eq, Hash)] @@ -15,9 +16,20 @@ struct Report { impl From for Report { fn from(value: eyre::Report) -> Self { + let detailed = format!("{value:?}"); + let detailed = strip_ansi_escapes::strip_str(&detailed); + let last_paragraph = detailed + .find("Location:") + .expect("Detailed report always lists a location"); + let backtrace_start = last_paragraph + + detailed[last_paragraph..] + .find("\n\n") + .expect("Should be a double line-end before backtrace"); + let detailed = &detailed[..backtrace_start]; + Self { short: value.to_string(), - detailed: format!("{value:#}"), + detailed: detailed.to_owned(), } } } @@ -33,6 +45,7 @@ pub(super) struct Reports { impl Reports { pub(super) fn add(&mut self, raw_report: eyre::Report) { let report = Report::from(raw_report); + tracing::debug!("report: {report:?}"); if self.to_ignore.contains(&report) { return; } @@ -61,7 +74,12 @@ impl Reports { .style(error_style), hint, ); - frame.render_widget(Text::raw(¤t.detailed).style(error_style), error); + frame.render_widget( + Paragraph::new(current.detailed.as_str()) + .wrap(Wrap { trim: false }) + .style(error_style), + error, + ); } else { frame.render_widget( Text::raw("e: show details, x: close this error, i: ignore this error") @@ -87,7 +105,7 @@ impl Reports { fn close_current(&mut self) { let Some(current) = self.current.take() else { - return + return; }; self.list.retain(|report| *report != current); From ddf49d5296ab79cc5127d62818a8995507ce80e2 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 8 Sep 2024 13:11:23 +0200 Subject: [PATCH 245/687] data-store refine api errors --- crates/data-store/src/api.rs | 30 +++++++++++++++++------ crates/data-store/src/api/client.rs | 32 +++++++++++++++++++++---- crates/data-store/src/server/clients.rs | 5 ++-- crates/data-store/src/server/db.rs | 23 ++++++++++++------ crates/data-store/tests/list_data.rs | 3 ++- crates/sensor-tui/src/fetch.rs | 16 ++++++++++--- 6 files changed, 84 insertions(+), 25 deletions(-) diff --git a/crates/data-store/src/api.rs b/crates/data-store/src/api.rs index 527c6d9a..b35edb69 100644 --- a/crates/data-store/src/api.rs +++ b/crates/data-store/src/api.rs @@ -9,9 +9,6 @@ pub use client::Client; #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) enum Request { - Handshake { - name: String, - }, ListData, GetData { reading: Reading, @@ -33,13 +30,32 @@ pub enum ServerError { TooManyRequests(Duration), } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Data { + pub time: Vec, + pub values: Vec, +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) enum Response { ListData(Vec), - GetData { - time: Vec, - data: Vec, - }, + GetData(Result), Error(ServerError), Handshake, } + +#[derive(Debug, Clone, Serialize, Deserialize, thiserror::Error)] +pub enum GetDataError { + #[error("could not find timestamp in this series")] + NotFound, + #[error("data file is empty")] + EmptyFile, + #[error("no data to return as the start time is after the last time in the data")] + StartAfterData, + #[error("no data to return as the stop time is before the data")] + StopBeforeData, + #[error("We do not have any data for this reading: {reading:?}")] + NotInStore { reading: Reading }, + #[error("Internal error while reading data, error: {0}")] + ReadingFromStore(String), +} diff --git a/crates/data-store/src/api/client.rs b/crates/data-store/src/api/client.rs index fc93fc90..aced70a2 100644 --- a/crates/data-store/src/api/client.rs +++ b/crates/data-store/src/api/client.rs @@ -2,6 +2,15 @@ use rpc::client::{RpcClient, RpcError}; use tokio::net::ToSocketAddrs; use super::Response; +use crate::api; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Server ran into an specific error with our request: {0}")] + Request(T), + #[error("Error while communicating with server: {0}")] + Comms(#[from] RpcError), +} pub struct Client(rpc::client::RpcClient); @@ -31,7 +40,7 @@ impl Client { end: jiff::Timestamp, reading: protocol::Reading, n: usize, - ) -> Result<(Vec, Vec), RpcError> { + ) -> Result> { let request = super::Request::GetData { reading, start, @@ -39,11 +48,26 @@ impl Client { n, }; match self.0.send_receive(request.clone()).await? { - Response::GetData { time, data } => Ok((time, data)), - response => Err(RpcError::IncorrectResponse { + Response::GetData(Ok(data)) => Ok(data), + Response::GetData(Err(err)) => Err(Error::Request(err)), + response => Err(Error::Comms(RpcError::IncorrectResponse { request: format!("{request:?}"), response: format!("{response:?}"), - }), + })), } } } + +#[derive(Debug, thiserror::Error)] +pub enum GetDataError { + #[error("could not find timestamp in this series")] + NotFound, + #[error("data file is empty")] + EmptyFile, + #[error("no data to return as the start time is after the last time in the data")] + StartAfterData, + #[error("no data to return as the stop time is before the data")] + StopBeforeData, + #[error("Error while communicating with server: {0}")] + Comms(#[from] RpcError), +} diff --git a/crates/data-store/src/server/clients.rs b/crates/data-store/src/server/clients.rs index 54c774dd..8cc09f95 100644 --- a/crates/data-store/src/server/clients.rs +++ b/crates/data-store/src/server/clients.rs @@ -24,7 +24,6 @@ async fn perform_request_inner( data: Data, ) -> Result { Ok(match request { - api::Request::Handshake { .. } => return Err(ServerError::AlreadyConnected), api::Request::ListData => api::Response::ListData(data.list().await), api::Request::GetData { reading, @@ -32,8 +31,8 @@ async fn perform_request_inner( end, n, } => { - let (time, data) = data.get(reading, start, end, n).await?; - api::Response::GetData { time, data } + let res = data.get(reading, start, end, n).await; + api::Response::GetData(res) } }) } diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index 8df8766a..522d772e 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -7,8 +7,8 @@ use std::time::{Duration, Instant}; use data_server::api::subscriber::ReconnectingClient; use data_server::api::subscriber::SubMessage; -use tokio::sync::Mutex; use color_eyre::{Result, Section}; +use tokio::sync::Mutex; mod series; use series::Series; @@ -63,21 +63,30 @@ impl Data { start: jiff::Timestamp, end: jiff::Timestamp, n: usize, - ) -> Result<(Vec, Vec), api::ServerError> { + ) -> Result { + use byteseries::seek::Error as Se; + use byteseries::series::Error as Be; + let key = reading.device(); let mut all_series = self.0.lock().await; let series = all_series .get_mut(&key) - .ok_or_else(|| api::ServerError::NotInStore { + .ok_or_else(|| api::GetDataError::NotInStore { reading: reading.clone(), })?; let (time, mut data) = series .read(&[reading], start, end, n) - .map_err(|e| api::ServerError::ReadingFromStore(e.to_string()))?; - Ok(( + .map_err(|e| match e { + Be::InvalidRange(Se::NotFound) => api::GetDataError::NotFound, + Be::InvalidRange(Se::EmptyFile) => api::GetDataError::EmptyFile, + Be::InvalidRange(Se::StartAfterData) => api::GetDataError::StartAfterData, + Be::InvalidRange(Se::StopBeforeData) => api::GetDataError::StopBeforeData, + _ => api::GetDataError::ReadingFromStore(e.to_string()), + })?; + Ok(api::Data { time, - data.pop().expect("one reading is put in so one comes out"), - )) + values: data.pop().expect("one reading is put in so one comes out"), + }) } } diff --git a/crates/data-store/tests/list_data.rs b/crates/data-store/tests/list_data.rs index f1e3d1e9..e16f0abd 100644 --- a/crates/data-store/tests/list_data.rs +++ b/crates/data-store/tests/list_data.rs @@ -3,6 +3,7 @@ use std::sync::Once; use std::time::Duration; use data_server::server::AffectorRegistar; +use data_store::api::Data; use futures::FutureExt; use futures_concurrency::future::Race; use protocol::large_bedroom::bed; @@ -95,7 +96,7 @@ async fn check_client_get_data( data_store::api::Client::connect(data_store_addr, "data_store_example".to_owned()) .await .unwrap(); - let (time, data) = client + let Data { time, values: data } = client .get_data( jiff::Timestamp::now() - jiff::Span::default().seconds(30), jiff::Timestamp::now() + jiff::Span::default().seconds(30), diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index a80ad4b9..27770d22 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -5,6 +5,7 @@ use std::ops::RangeInclusive; use std::sync::mpsc; use std::time::Duration; +use color_eyre::eyre::Context; use color_eyre::Result; use jiff::{Span, Timestamp}; use log_store::api::{ErrorEvent, Percentile}; @@ -270,12 +271,21 @@ pub async fn get_data( reading: Reading, range: RangeInclusive, ) -> Result<(Vec, Vec)> { + use data_store::api::{client::Error, Data, GetDataError}; + let mut api = data_store::api::Client::connect(data_store, client_name()).await?; - let history = api + match api .get_data(*range.start(), *range.end(), reading, 300) - .await?; - Ok(history) + .await + { + Ok(Data { time, values }) => Ok((time, values)), + Err(Error::Request(GetDataError::NotFound)) + | Err(Error::Request(GetDataError::EmptyFile)) + | Err(Error::Request(GetDataError::StartAfterData)) + | Err(Error::Request(GetDataError::StopBeforeData)) => Ok((Vec::new(), Vec::new())), + Err(other) => Err(other).wrap_err("Could not get data from store"), + } } pub async fn get_logs(log_store: SocketAddr, reading: Reading) -> Result> { From d1879c16dcd3da2d6e4a5508b480261bde71802e Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 8 Sep 2024 13:20:55 +0200 Subject: [PATCH 246/687] tui: catch another irrelevant error --- crates/sensor-tui/src/fetch.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index 27770d22..f1f53c38 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -283,7 +283,8 @@ pub async fn get_data( Err(Error::Request(GetDataError::NotFound)) | Err(Error::Request(GetDataError::EmptyFile)) | Err(Error::Request(GetDataError::StartAfterData)) - | Err(Error::Request(GetDataError::StopBeforeData)) => Ok((Vec::new(), Vec::new())), + | Err(Error::Request(GetDataError::StopBeforeData)) + | Err(Error::Request(GetDataError::NotInStore { .. })) => Ok((Vec::new(), Vec::new())), Err(other) => Err(other).wrap_err("Could not get data from store"), } } From d7718743e86d94d5a72ca90ac5a91eef165c3d57 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 8 Sep 2024 20:53:03 +0200 Subject: [PATCH 247/687] limit error report rate --- Cargo.lock | 1 + crates/desk-sensors/Cargo.toml | 1 + crates/desk-sensors/src/sensors.rs | 104 ++++++++++++++++++----------- 3 files changed, 68 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7cca41ec..ceab6e1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -975,6 +975,7 @@ dependencies = [ "color-eyre", "data-server", "embedded-hal-async", + "governor", "gpiocdev-embedded-hal", "heapless 0.8.0", "linux-embedded-hal", diff --git a/crates/desk-sensors/Cargo.toml b/crates/desk-sensors/Cargo.toml index d01e2128..6914c9bc 100644 --- a/crates/desk-sensors/Cargo.toml +++ b/crates/desk-sensors/Cargo.toml @@ -22,3 +22,4 @@ tracing-error = { workspace = true } tokio = { workspace = true, features = ["rt", "time", "macros"] } embedded-hal-async = "1.0.0" heapless = "0.8.0" +governor = "0.6.3" diff --git a/crates/desk-sensors/src/sensors.rs b/crates/desk-sensors/src/sensors.rs index f8ab39a2..7353f9db 100644 --- a/crates/desk-sensors/src/sensors.rs +++ b/crates/desk-sensors/src/sensors.rs @@ -1,12 +1,17 @@ use bme280::i2c::BME280 as Bme280; use bme280::{self, Measurements}; +use governor::clock::{QuantaClock, QuantaInstant}; +use governor::middleware::NoOpMiddleware; +use governor::state::{InMemoryState, NotKeyed}; +use governor::{Quota, RateLimiter}; use hal::{Delay, I2cdev}; use linux_embedded_hal as hal; use protocol::{ErrorString, Reading}; use tracing::debug; +use std::num::NonZeroU32; use std::thread; -use std::time::{Duration, Instant}; +use std::time::Duration; use tokio::sync::mpsc::Sender; use crate::bedroom; @@ -25,51 +30,74 @@ pub fn init() -> Result, ErrorString> { } pub fn start_monitoring(tx: Sender>, room: bedroom::Bedroom) { - let mut last_warning = Instant::now() - Duration::from_secs(10_000); + let quota = + Quota::per_hour(NonZeroU32::new(4).unwrap()).allow_burst(NonZeroU32::new(20).unwrap()); + let mut err_report_limiter = governor::RateLimiter::direct(quota); + let mut bme = None; + thread::spawn(move || loop { - let mut bme = match init() { - Ok(driver) => driver, - Err(e) => { - tracing::error!("Could not setup bme280 sensor: {e}"); - tx.blocking_send(Err(room.make_setup_error(e))) - .expect("main should not return or panic"); - std::thread::sleep(Duration::from_secs(5)); - continue; - } - }; + std::thread::sleep(Duration::from_secs(5)); - loop { - match bme.measure(&mut Delay) { - Ok( - m @ Measurements { - temperature, - pressure, - humidity, - .. - }, - ) => { - debug!("got measurements: {m:?}"); - tx.blocking_send(Ok(room.make_temperature_reading(temperature))) - .expect("main should not return or panic"); - tx.blocking_send(Ok(room.make_humidity_reading(humidity))) - .expect("main should not return or panic"); - tx.blocking_send(Ok(room.make_pressure_reading(pressure))) + if bme.is_none() { + bme = match init() { + Ok(driver) => Some(driver), + Err(e) => { + tracing::error!("Could not setup bme280 sensor: {e}"); + tx.blocking_send(Err(room.make_setup_error(e))) .expect("main should not return or panic"); + continue; + } + }; + } + + if let Some(mut driver) = bme.take() { + match driver.measure(&mut Delay) { + Ok(measurements) => { + bme = Some(driver); + send_measurements(measurements, &tx, room); } Err(e) => { - if last_warning.elapsed() > Duration::from_secs(300) { - last_warning = Instant::now(); - tracing::error!("Could not read bme280 sensor: {e}"); - } - let e = protocol::make_error_string(e); - tx.blocking_send(Err(room.make_run_error(e))) - .expect("main should not return or panic"); + send_error(e, &tx, room, &mut err_report_limiter); break; } } - - std::thread::sleep(Duration::from_secs(5)); } - std::thread::sleep(Duration::from_secs(20)); }); } + +fn send_error( + e: bme280::Error, + tx: &Sender>, + room: bedroom::Bedroom, + limiter: &mut RateLimiter>, +) { + if limiter.check().is_err() { + return; + } + + tracing::error!("Could not read bme280 sensor: {e}"); + let e = protocol::make_error_string(e); + tx.blocking_send(Err(room.make_run_error(e))) + .expect("main should not return or panic"); +} + +fn send_measurements( + measurements: Measurements, + tx: &Sender>, + room: bedroom::Bedroom, +) { + debug!("got measurements: {measurements:?}"); + + let Measurements { + temperature, + pressure, + humidity, + } = measurements; + + tx.blocking_send(Ok(room.make_temperature_reading(temperature))) + .expect("main should not return or panic"); + tx.blocking_send(Ok(room.make_humidity_reading(humidity))) + .expect("main should not return or panic"); + tx.blocking_send(Ok(room.make_pressure_reading(pressure))) + .expect("main should not return or panic"); +} From cfbdc73125d87c65bb0c6784e07e79264fb1aeb8 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 8 Sep 2024 21:10:03 +0200 Subject: [PATCH 248/687] data-server fix wrong quota in data_source handling --- crates/data-server/src/server/data_source.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/data-server/src/server/data_source.rs b/crates/data-server/src/server/data_source.rs index efb137f4..455566f7 100644 --- a/crates/data-server/src/server/data_source.rs +++ b/crates/data-server/src/server/data_source.rs @@ -123,8 +123,7 @@ async fn handshake(reader: &mut BufReader) -> Result, queue: Sender) { - let quota = Quota::with_period(Duration::from_secs(40)) - .unwrap() + let quota = Quota::per_second(NonZeroU32::new(40).unwrap()) .allow_burst(NonZeroU32::new(200u32).unwrap()); let limiter = RateLimiter::direct(quota); From 12c79d1672602ef86595d5ffc8d9b75c470da629 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 9 Sep 2024 13:38:49 +0200 Subject: [PATCH 249/687] update to latest embassy --- sensor-nodes/bed-sensors/Cargo.lock | 79 ++++++++++++++++++++++------ sensor-nodes/bed-sensors/Cargo.toml | 44 ++++++++-------- sensor-nodes/bed-sensors/src/main.rs | 8 +-- 3 files changed, 89 insertions(+), 42 deletions(-) diff --git a/sensor-nodes/bed-sensors/Cargo.lock b/sensor-nodes/bed-sensors/Cargo.lock index 5f42670d..31ce6f29 100644 --- a/sensor-nodes/bed-sensors/Cargo.lock +++ b/sensor-nodes/bed-sensors/Cargo.lock @@ -2,6 +2,24 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aligned" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "377e4c0ba83e4431b10df45c1d4666f178ea9c552cac93e60c3a88bf32785923" +dependencies = [ + "as-slice", +] + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "atomic-polyfill" version = "1.0.3" @@ -98,6 +116,15 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +[[package]] +name = "block-device-driver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c051592f59fe68053524b4c4935249b806f72c1f544cfb7abe4f57c3be258e" +dependencies = [ + "aligned", +] + [[package]] name = "bosch-bme680" version = "1.0.2" @@ -201,7 +228,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -212,7 +239,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -235,7 +262,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -269,6 +296,7 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" dependencies = [ "defmt", "embassy-futures", @@ -285,6 +313,7 @@ dependencies = [ [[package]] name = "embassy-executor" version = "0.6.0" +source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" dependencies = [ "cortex-m", "critical-section", @@ -298,20 +327,23 @@ dependencies = [ [[package]] name = "embassy-executor-macros" version = "0.5.0" +source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] name = "embassy-futures" version = "0.1.1" +source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" [[package]] name = "embassy-hal-internal" version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" dependencies = [ "cortex-m", "critical-section", @@ -322,6 +354,7 @@ dependencies = [ [[package]] name = "embassy-net" version = "0.4.0" +source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" dependencies = [ "defmt", "document-features", @@ -338,6 +371,7 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" dependencies = [ "defmt", ] @@ -345,6 +379,7 @@ dependencies = [ [[package]] name = "embassy-net-driver-channel" version = "0.3.0" +source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" dependencies = [ "embassy-futures", "embassy-net-driver", @@ -354,6 +389,7 @@ dependencies = [ [[package]] name = "embassy-net-wiznet" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" dependencies = [ "defmt", "embassy-futures", @@ -366,9 +402,12 @@ dependencies = [ [[package]] name = "embassy-stm32" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" dependencies = [ + "aligned", "bit_field", "bitflags 2.6.0", + "block-device-driver", "cfg-if", "cortex-m", "cortex-m-rt", @@ -409,6 +448,7 @@ dependencies = [ [[package]] name = "embassy-sync" version = "0.6.0" +source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" dependencies = [ "cfg-if", "critical-section", @@ -421,6 +461,7 @@ dependencies = [ [[package]] name = "embassy-time" version = "0.3.2" +source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" dependencies = [ "cfg-if", "critical-section", @@ -438,6 +479,7 @@ dependencies = [ [[package]] name = "embassy-time-driver" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" dependencies = [ "document-features", ] @@ -445,10 +487,12 @@ dependencies = [ [[package]] name = "embassy-time-queue-driver" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" [[package]] name = "embassy-usb-driver" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" dependencies = [ "defmt", ] @@ -456,6 +500,7 @@ dependencies = [ [[package]] name = "embassy-usb-synopsys-otg" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" dependencies = [ "critical-section", "embassy-sync", @@ -628,7 +673,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -683,7 +728,7 @@ checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" dependencies = [ "atomic-polyfill", "hash32 0.2.1", - "rustc_version 0.4.0", + "rustc_version 0.4.1", "serde", "spin", "stable_deref_trait", @@ -926,9 +971,9 @@ dependencies = [ [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver 1.0.23", ] @@ -974,22 +1019,22 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.208" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.208" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1113,7 +1158,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1129,9 +1174,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.75" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -1155,7 +1200,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] diff --git a/sensor-nodes/bed-sensors/Cargo.toml b/sensor-nodes/bed-sensors/Cargo.toml index 532465b9..795f075a 100644 --- a/sensor-nodes/bed-sensors/Cargo.toml +++ b/sensor-nodes/bed-sensors/Cargo.toml @@ -52,30 +52,30 @@ stm32f4 = { version = "0.15.1", default-features = false, features = ["stm32f401 rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } # fasthash = { version = "0.4.0", default-features = false } -# [patch.crates-io] -# embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } -# embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } -# embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } -# embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } -# embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } -# embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } -# embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } -# embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } -# embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } -# embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "7a26e11" } +[patch.crates-io] +embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } +embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } +embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } +embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } +embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } +embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } +embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } +embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } +embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } +embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } # [patch.'https://github.com/embassy-rs/embassy.git'] -[patch.crates-io] -embassy-stm32 = {path = "../../../embassy/embassy-stm32" } -embassy-net = {path = "../../../embassy/embassy-net" } -embassy-net-wiznet = {path = "../../../embassy/embassy-net-wiznet" } -embassy-sync = {path = "../../../embassy/embassy-sync" } -embassy-executor = {path = "../../../embassy/embassy-executor" } -embassy-embedded-hal = {path = "../../../embassy/embassy-embedded-hal" } -embassy-time = {path = "../../../embassy/embassy-time" } -embassy-futures = {path = "../../../embassy/embassy-futures" } -embassy-time-driver = {path = "../../../embassy/embassy-time-driver"} -embassy-time-queue-driver = {path = "../../../embassy/embassy-time-queue-driver"} +# [patch.crates-io] +# embassy-stm32 = {path = "../../../embassy/embassy-stm32" } +# embassy-net = {path = "../../../embassy/embassy-net" } +# embassy-net-wiznet = {path = "../../../embassy/embassy-net-wiznet" } +# embassy-sync = {path = "../../../embassy/embassy-sync" } +# embassy-executor = {path = "../../../embassy/embassy-executor" } +# embassy-embedded-hal = {path = "../../../embassy/embassy-embedded-hal" } +# embassy-time = {path = "../../../embassy/embassy-time" } +# embassy-futures = {path = "../../../embassy/embassy-futures" } +# embassy-time-driver = {path = "../../../embassy/embassy-time-driver"} +# embassy-time-queue-driver = {path = "../../../embassy/embassy-time-queue-driver"} [profile.dev] opt-level = "s" diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index ccdcddfa..6cecc1dc 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -109,7 +109,7 @@ async fn main(spawner: Spawner) { usart_config.baudrate = 115_200; // sps30 only works at this baud usart_config.data_bits = DataBits::DataBits8; usart_config.stop_bits = StopBits::STOP1; - usart_config.parity = Parity::ParityNone; + // usart_config.parity = Parity::ParityNone; let usart_sps30 = unwrap!(Uart::new( p.USART2, p.PA3, @@ -162,10 +162,12 @@ async fn main(spawner: Spawner) { let buttons = ButtonInputs { top: ExtiInput::new(p.PC14, p.EXTI14, Pull::Down), - middle_inner: ExtiInput::new(p.PA9, p.EXTI9, Pull::Down), // Not working + // Not working but is connected (continuity checked) + middle_inner: ExtiInput::new(p.PA9, p.EXTI9, Pull::Down), middle_center: ExtiInput::new(p.PA10, p.EXTI10, Pull::Down), middle_outer: ExtiInput::new(p.PA11, p.EXTI11, Pull::Down), - lower_inner: ExtiInput::new(p.PA12, p.EXTI12, Pull::Down), // Not working + // Not working but is connected (continuity checked) + lower_inner: ExtiInput::new(p.PA12, p.EXTI12, Pull::Down), lower_center: ExtiInput::new(p.PA15, p.EXTI15, Pull::Down), lower_outer: ExtiInput::new(p.PB5, p.EXTI5, Pull::Down), }; From e18fd214ef25638856c59d35200eef2f789a7d3c Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 9 Sep 2024 16:49:17 +0200 Subject: [PATCH 250/687] rng now powerd by embassy hal fixes button names --- sensor-nodes/bed-sensors/Cargo.lock | 20 +---- sensor-nodes/bed-sensors/Cargo.toml | 10 +-- sensor-nodes/bed-sensors/src/main.rs | 10 +-- sensor-nodes/bed-sensors/src/rng.rs | 91 ++++---------------- sensor-nodes/bed-sensors/src/sensors/fast.rs | 13 ++- 5 files changed, 33 insertions(+), 111 deletions(-) diff --git a/sensor-nodes/bed-sensors/Cargo.lock b/sensor-nodes/bed-sensors/Cargo.lock index 31ce6f29..b8b86477 100644 --- a/sensor-nodes/bed-sensors/Cargo.lock +++ b/sensor-nodes/bed-sensors/Cargo.lock @@ -44,12 +44,6 @@ dependencies = [ "rustc_version 0.2.3", ] -[[package]] -name = "bare-metal" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" - [[package]] name = "bed-sensors" version = "0.2.0" @@ -83,7 +77,6 @@ dependencies = [ "sht31", "sps30-async", "static_cell", - "stm32f4", ] [[package]] @@ -159,7 +152,7 @@ version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" dependencies = [ - "bare-metal 0.2.5", + "bare-metal", "bitfield 0.13.2", "critical-section", "embedded-hal 0.2.7", @@ -1122,17 +1115,6 @@ dependencies = [ "cortex-m-rt", ] -[[package]] -name = "stm32f4" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb94729242cd1aebe6dab42a2ca0131985ae93bc3ab2751b680df724bb35528d" -dependencies = [ - "bare-metal 1.0.0", - "cortex-m", - "vcell", -] - [[package]] name = "strsim" version = "0.11.1" diff --git a/sensor-nodes/bed-sensors/Cargo.toml b/sensor-nodes/bed-sensors/Cargo.toml index 795f075a..a51365fe 100644 --- a/sensor-nodes/bed-sensors/Cargo.toml +++ b/sensor-nodes/bed-sensors/Cargo.toml @@ -8,7 +8,7 @@ authors = ["David Kleingeld & Eva van Houten"] [dependencies] embassy-stm32 = { version = "0.1.0", features = [ "defmt", "stm32f401cc", -"unstable-pac", "memory-x", "time-driver-any", "time", "exti" ] } +"unstable-pac", "memory-x", "time-driver-tim9", "time", "exti" ] } embassy-net = { version = "0.4.0", features = ["defmt", "proto-ipv4", "tcp", "dhcpv4","medium-ethernet"] } embassy-net-wiznet = { version = "0.1.0", features = ["defmt"] } embassy-sync = { version = "0.6.0", features = ["defmt"] } @@ -32,6 +32,7 @@ panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.8", default-features = false } nb = "1.0.0" +rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } static_cell = "2.0.0" # sensors @@ -45,13 +46,6 @@ nau7802-async = { path = "/home/david/tmp/nau7802-rs", features = ["serde", "pos # encoding protocol = { path = "../../crates/protocol" } -# used only for RNG since embassy's adc is currently broken and we need -# an adc to get a true RNG. -# stm32f4xx-hal = { version = "0.21.0", default-features = false, features = ["stm32f401"] } -stm32f4 = { version = "0.15.1", default-features = false, features = ["stm32f401"] } -rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } -# fasthash = { version = "0.4.0", default-features = false } - [patch.crates-io] embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index 6cecc1dc..3f5672fb 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -88,7 +88,7 @@ fn config() -> Config { #[embassy_executor::main] async fn main(spawner: Spawner) { let p = embassy_stm32::init(config()); - let seed = rng::generate_seed_blocking(); + let seed = rng::generate_seed_blocking(p.ADC1).await; defmt::info!("random seed: {}", seed); let mut usart_config = usart::Config::default(); @@ -162,12 +162,10 @@ async fn main(spawner: Spawner) { let buttons = ButtonInputs { top: ExtiInput::new(p.PC14, p.EXTI14, Pull::Down), - // Not working but is connected (continuity checked) middle_inner: ExtiInput::new(p.PA9, p.EXTI9, Pull::Down), - middle_center: ExtiInput::new(p.PA10, p.EXTI10, Pull::Down), - middle_outer: ExtiInput::new(p.PA11, p.EXTI11, Pull::Down), - // Not working but is connected (continuity checked) - lower_inner: ExtiInput::new(p.PA12, p.EXTI12, Pull::Down), + middle_center: ExtiInput::new(p.PA12, p.EXTI12, Pull::Down), + middle_outer: ExtiInput::new(p.PA10, p.EXTI10, Pull::Down), + lower_inner: ExtiInput::new(p.PA11, p.EXTI11, Pull::Down), lower_center: ExtiInput::new(p.PA15, p.EXTI15, Pull::Down), lower_outer: ExtiInput::new(p.PB5, p.EXTI5, Pull::Down), }; diff --git a/sensor-nodes/bed-sensors/src/rng.rs b/sensor-nodes/bed-sensors/src/rng.rs index de60a0ba..8770b4e1 100644 --- a/sensor-nodes/bed-sensors/src/rng.rs +++ b/sensor-nodes/bed-sensors/src/rng.rs @@ -1,88 +1,29 @@ +use embassy_stm32::peripherals::ADC1; +use embassy_time::Timer; use rand::{RngCore, SeedableRng}; -use stm32f4::stm32f401; -// use stm32f4xx_hal::{ -// adc::{ -// config::{AdcConfig, Resolution, SampleTime}, -// Adc, -// }, -// pac, -// prelude::*, -// }; -// -// /// #Warning -// /// Should only be called before async tasks are spawned. This takes a lot of -// /// time to run and will disturb any async task running. -// pub fn generate_seed_once() -> u64 { -// let p = pac::Peripherals::take().expect("function generate_once should only be called once"); -// let gpioa = p.GPIOA.split(); -// let adc_pin = gpioa.pa1.into_analog(); -// -// let adc_config = AdcConfig::default().resolution(Resolution::Twelve); -// -// let mut adc = Adc::adc1(p.ADC1, true, adc_config); -// -// let mut seed = [0u8; 16]; -// for byte in &mut seed { -// let sample = adc.convert(&adc_pin, SampleTime::Cycles_3); -// let most_noisy_byte = (sample & 0b0000_0000_1111_1111) as u8; -// *byte = most_noisy_byte; -// } -// -// let mut rng = rand::rngs::SmallRng::from_seed(seed); -// rng.next_u64() -// } +use embassy_stm32::adc::{Adc, Temperature, VrefInt}; /// #Warning /// Should only be called before async tasks are spawned. This takes a lot of /// time to run and will disturb any async task running. -pub fn generate_seed_blocking() -> u64 { - let p = - stm32f401::Peripherals::take().expect("function generate_once should only be called once"); +pub async fn generate_seed_blocking(adc: ADC1) -> u64 { + let mut adc = Adc::new(adc); - // enable clock to the adc such that we can control it - p.RCC.apb2enr.modify(|_, reg| reg.adc1en().enabled()); + let mut vrefint = adc.enable_vrefint(); + let mut temp = adc.enable_temperature(); - p.ADC_COMMON.ccr.modify(|_, reg| { - reg - // disable vbat (needed to enable the temp sensor) - .vbate() - .disabled() - // enable the temperature sensor - .tsvrefe() - .enabled() - }); - - // set resolution to 12bit - p.ADC1.cr1.modify(|_, reg| reg.res().twelve_bit()); - // adc conversion sequence has only 1 value - p.ADC1.sqr1.modify(|_, reg| reg.l().bits(0b0000)); - // setup channel 18 which is connected to the internal temperature sensor - p.ADC1.sqr3.modify(|_, reg| reg.sq1().variant(18)); - // enable the end of conversion bit - p.ADC1.cr2.modify(|_, reg| reg.eocs().each_conversion()); - // disable continues conversions - p.ADC1.cr2.modify(|_, reg| reg.cont().clear_bit()); - - // finally start the adc - p.ADC1.cr2.modify(|_, reg| reg.adon().set_bit()); - - let adc_read = || { - // clear any overrun status first - p.ADC1.sr.modify(|_, reg| reg.ovr().clear_bit()); - // start single conversion mode for a regular channel (18) - p.ADC1.cr2.modify(|_, reg| reg.swstart().set_bit()); - - // while not status register end of conversion bit is set - while !p.ADC1.sr.read().eoc().bit_is_set() {} - - p.ADC1.dr.read().bits() - }; + // Startup delay can be combined to the maximum of either + Timer::after_micros(Temperature::start_time_us().max(VrefInt::start_time_us()) as u64).await; let mut seed = [0u8; 16]; - for byte in &mut seed { - let sample = adc_read(); + let mut bytes = seed.chunks_exact_mut(2); + while let Some([byte1, byte2]) = bytes.next() { + let sample = adc.blocking_read(&mut temp); + let most_noisy_byte = (sample & 0b0000_0000_1111_1111) as u8; + *byte1 = most_noisy_byte; + let sample = adc.blocking_read(&mut vrefint); let most_noisy_byte = (sample & 0b0000_0000_1111_1111) as u8; - *byte = most_noisy_byte; + *byte2 = most_noisy_byte; } let mut rng = rand::rngs::SmallRng::from_seed(seed); diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed-sensors/src/sensors/fast.rs index 4bbfcbe4..6da271fe 100644 --- a/sensor-nodes/bed-sensors/src/sensors/fast.rs +++ b/sensor-nodes/bed-sensors/src/sensors/fast.rs @@ -27,7 +27,6 @@ async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues, rgb_led: rgb_l let mut prev_lux = f32::MAX; let mut last_lux = Instant::now(); - // todo!("reinit devices after error"); loop { Timer::after_millis(50).await; let lux = match max44.try_measure().await { @@ -118,8 +117,16 @@ async fn watch_button( let event = (event)(protocol::button::Press(press)); channel.send_p2(Reading::Button(event)); } else { - input.wait_for_rising_edge().await; - Timer::after(Duration::from_millis(50)).await; + input.wait_for_high().await; + Timer::after(Duration::from_millis(20)).await; + if input.is_low() { + continue; + } + Timer::after(Duration::from_millis(20)).await; + if input.is_low() { + continue; + } + Timer::after(Duration::from_millis(10)).await; if input.is_high() { went_high_at = Some(Instant::now()); } From 2040444ba12575c9b6cc7276e8aae519e8a81c1f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 10 Sep 2024 14:01:14 +0200 Subject: [PATCH 251/687] fixes ratelimited clients never getting ratelimited msg --- crates/rpc/src/server.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rpc/src/server.rs b/crates/rpc/src/server.rs index 217628b8..21a59671 100644 --- a/crates/rpc/src/server.rs +++ b/crates/rpc/src/server.rs @@ -63,7 +63,7 @@ where if let Err(allowed_again) = limiter.check_key(&(source.ip(), name.clone())) { let allowed_in = allowed_again.wait_time_from(DefaultClock::default().now()); - let _ignore_err = conn.send(crate::Response::TooManyReq { allowed_in }); + let _ignore_err = conn.send(crate::Response::TooManyReq { allowed_in }).await; continue; } From cfbd63e30a933695e0e5ad9fd91915f522b3eafb Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 10 Sep 2024 14:01:37 +0200 Subject: [PATCH 252/687] tui: improve error displaying/tracing --- crates/sensor-tui/src/fetch.rs | 38 ++++++++++++++++++++++++---------- crates/sensor-tui/src/tui.rs | 2 +- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index f1f53c38..4ef96aa8 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -5,7 +5,7 @@ use std::ops::RangeInclusive; use std::sync::mpsc; use std::time::Duration; -use color_eyre::eyre::Context; +use color_eyre::eyre::{self, Context}; use color_eyre::Result; use jiff::{Span, Timestamp}; use log_store::api::{ErrorEvent, Percentile}; @@ -188,7 +188,7 @@ impl Fetch { fn request(&mut self, req: Request) { self.tx.blocking_send(req.clone()).unwrap(); self.recently_issued.push_front(req); - // might get out of sync with request handler, that is okay + // Might get out of sync with request handler, that is okay // false positives in self.recently_issued are allowed. They only // delay an update by a single frame. if self.recently_issued.len() > MAX_IN_FLIGHT_REQUESTS { @@ -210,6 +210,7 @@ pub(crate) async fn handle_requests( let handle = match request { Request::Data(Data { reading, range }) => tokio::spawn(get_wrap_send( get_data(data_store, reading.clone(), range), + "Could not fetch data for graph", |res| match res { Ok(data) => Update::Fetched { reading, @@ -224,6 +225,7 @@ pub(crate) async fn handle_requests( )), Request::Logs(Logs { reading, range }) => tokio::spawn(get_wrap_send( get_logs(log_store, reading.clone()), + "Could not fetch logs", move |res| match res { Ok(logs) => Update::Fetched { reading, @@ -238,6 +240,7 @@ pub(crate) async fn handle_requests( )), Request::Hist(Hist { reading, range }) => tokio::spawn(get_wrap_send( get_percentiles(log_store, reading.clone()), + "Could not fetch percentiles for histogram", move |res| match res { Ok(percentiles) => Update::Fetched { reading, @@ -257,11 +260,12 @@ pub(crate) async fn handle_requests( } pub async fn get_wrap_send( - getter: impl Future, - wrapper: impl FnOnce(T) -> Update, + getter: impl Future>, + err_text: &'static str, + wrapper: impl FnOnce(Result) -> Update, tx: mpsc::Sender, ) { - let val = getter.await; + let val = getter.await.wrap_err(err_text); let update = (wrapper)(val); tx.send(update).unwrap(); } @@ -273,7 +277,9 @@ pub async fn get_data( ) -> Result<(Vec, Vec)> { use data_store::api::{client::Error, Data, GetDataError}; - let mut api = data_store::api::Client::connect(data_store, client_name()).await?; + let mut api = data_store::api::Client::connect(data_store, client_name()) + .await + .wrap_err("Could not connect to data-store")?; match api .get_data(*range.start(), *range.end(), reading, 300) @@ -285,20 +291,30 @@ pub async fn get_data( | Err(Error::Request(GetDataError::StartAfterData)) | Err(Error::Request(GetDataError::StopBeforeData)) | Err(Error::Request(GetDataError::NotInStore { .. })) => Ok((Vec::new(), Vec::new())), - Err(other) => Err(other).wrap_err("Could not get data from store"), + Err(other) => Err(other).wrap_err("Data-store returned an error to our request"), } } pub async fn get_logs(log_store: SocketAddr, reading: Reading) -> Result> { - let mut api = log_store::api::Client::connect(log_store, client_name()).await?; + let mut api = log_store::api::Client::connect(log_store, client_name()) + .await + .wrap_err("Could not connect to log-store")?; - let history = api.get_logs(reading.device()).await?; + let history = api + .get_logs(reading.device()) + .await + .wrap_err("Log store returned an error to our request")?; Ok(history) } pub async fn get_percentiles(log_store: SocketAddr, reading: Reading) -> Result> { - let mut api = log_store::api::Client::connect(log_store, client_name()).await?; + let mut api = log_store::api::Client::connect(log_store, client_name()) + .await + .wrap_err("Could not connect to log-store")?; - let percentile = api.get_percentiles(reading.device()).await?; + let percentile = api + .get_percentiles(reading.device()) + .await + .wrap_err("Log store returned an error to our request")?; Ok(percentile) } diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index 67e4cebc..c56e0193 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -167,7 +167,7 @@ impl App { | Update::ReadingList(_) | Update::SensorError(_) | Update::SensorReading(_) => return Some(update), - Update::FetchError(e) => self.reports.add(e.wrap_err("Error fetching data")), + Update::FetchError(e) => self.reports.add(e.wrap_err("Error fetching")), Update::SubscribeError(e) => self .reports .add(e.wrap_err("Error while subscribing to data-server")), From 991dc2ca58d2a527598dcc68c171e02f250aa83e Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 10 Sep 2024 17:28:44 +0200 Subject: [PATCH 253/687] tui: handle timeout due to ratelimit --- crates/data-store/src/api/client.rs | 3 +- crates/log-store/src/api/client.rs | 1 + crates/rpc/src/client.rs | 30 +++- crates/sensor-tui/src/fetch.rs | 245 ++++++++++++++++++++-------- 4 files changed, 201 insertions(+), 78 deletions(-) diff --git a/crates/data-store/src/api/client.rs b/crates/data-store/src/api/client.rs index aced70a2..5e1455f8 100644 --- a/crates/data-store/src/api/client.rs +++ b/crates/data-store/src/api/client.rs @@ -1,4 +1,5 @@ -use rpc::client::{RpcClient, RpcError}; +pub use rpc::client::{RpcError, ConnectError}; +use rpc::client::RpcClient; use tokio::net::ToSocketAddrs; use super::Response; diff --git a/crates/log-store/src/api/client.rs b/crates/log-store/src/api/client.rs index 32d10951..b5f64222 100644 --- a/crates/log-store/src/api/client.rs +++ b/crates/log-store/src/api/client.rs @@ -11,6 +11,7 @@ use super::GetStatsError; use super::Response; pub struct Client(rpc::client::RpcClient); +pub use rpc::client::ConnectError; #[derive(Debug, thiserror::Error)] pub enum Error { diff --git a/crates/rpc/src/client.rs b/crates/rpc/src/client.rs index 085d9a9d..8f6364b1 100644 --- a/crates/rpc/src/client.rs +++ b/crates/rpc/src/client.rs @@ -8,6 +8,7 @@ use serde::Serialize; use tokio::net::TcpStream; use tokio::net::ToSocketAddrs; use tokio::time::error::Elapsed; +use tokio::time::sleep; use tokio::time::timeout_at; use tokio::time::Instant; use tokio_serde::formats::Bincode; @@ -16,16 +17,18 @@ use tokio_util::codec::{Framed, LengthDelimitedCodec}; use crate::Request; use crate::Response; +type Stream = tokio_serde::Framed< + Framed, + Response, + Request, + Bincode, Request>, +>; + pub struct RpcClient where RpcResp: Serialize, { - stream: tokio_serde::Framed< - Framed, - Response, - Request, - Bincode, Request>, - >, + stream: Stream, } impl fmt::Debug for RpcClient { @@ -48,6 +51,8 @@ pub enum ConnectError { Receiving(std::io::Error), #[error("Client was already connected")] AlreadyConnected, + #[error("Client tried to connected too many times, allowed again in: {0:?}")] + RateLimited(Duration), } #[derive(Debug, thiserror::Error)] @@ -67,7 +72,10 @@ where RpcReq: Unpin + Serialize + fmt::Debug, RpcResp: Unpin + Serialize + DeserializeOwned + fmt::Debug, { - pub async fn connect(addr: impl ToSocketAddrs, name: String) -> Result { + async fn try_connect( + addr: impl ToSocketAddrs, + name: String, + ) -> Result, ConnectError> { let stream = TcpStream::connect(addr).await.map_err(ConnectError::Io)?; let _ignore_error = stream.set_nodelay(true); @@ -83,10 +91,18 @@ where .send(Request::Handshake { client_name: name }) .await .map_err(ConnectError::Sending)?; + Ok(stream) + } + pub async fn connect(addr: impl ToSocketAddrs, name: String) -> Result { + let mut stream = Self::try_connect(addr, name).await?; match tokio::time::timeout(Duration::from_secs(2), stream.try_next()).await { Ok(Ok(Some(Response::HandshakeOk))) => Ok(Self { stream }), Ok(Ok(Some(Response::AlreadyConnected))) => Err(ConnectError::AlreadyConnected), + Ok(Ok(Some(Response::TooManyReq { allowed_in }))) => { + Err(ConnectError::RateLimited(allowed_in)) + } + Ok(Ok(Some(other))) => unreachable!( "Server should return handshake response or error after sending \ first handshake, got impossible response: {other:?}" diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index 4ef96aa8..f5d58af8 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -2,15 +2,16 @@ use std::collections::VecDeque; use std::future::Future; use std::net::SocketAddr; use std::ops::RangeInclusive; -use std::sync::mpsc; +use std::sync::{mpsc, Arc}; use std::time::Duration; -use color_eyre::eyre::{self, Context}; +use color_eyre::eyre::{self, Context, Report}; use color_eyre::Result; use jiff::{Span, Timestamp}; use log_store::api::{ErrorEvent, Percentile}; use protocol::Reading; -use tokio::task; +use std::sync::Mutex; +use tokio::time::Instant; use tracing::debug; use crate::{client_name, Fetchable, Update}; @@ -76,7 +77,7 @@ impl Fetch { ) -> Self { let (tx, rx) = tokio::sync::mpsc::channel(32); - task::spawn(handle_requests(data_store, log_store, rx, update_tx)); + tokio::spawn(handle_requests(data_store, log_store, rx, update_tx)); Self { recently_issued: VecDeque::new(), tx, @@ -203,53 +204,68 @@ pub(crate) async fn handle_requests( mut rx: tokio::sync::mpsc::Receiver, tx: mpsc::Sender, ) { + let data_store_queue = Queue::default(); + let log_store_queue = Queue::default(); + let mut inflight_request = VecDeque::new(); while let Some(request) = rx.recv().await { let data_store = data_store.clone(); let tx = tx.clone(); let handle = match request { - Request::Data(Data { reading, range }) => tokio::spawn(get_wrap_send( - get_data(data_store, reading.clone(), range), - "Could not fetch data for graph", - |res| match res { - Ok(data) => Update::Fetched { - reading, - thing: Fetchable::Data { - timestamps: data.0, - data: data.1, + Request::Data(Data { reading, range }) => { + let reading_clone = reading.clone(); + tokio::spawn(get_retry_then_wrap_send( + move || get_data(data_store, reading.clone(), range.clone()), + data_store_queue.clone(), + "Could not fetch data for graph", + move |res| match res { + Ok(data) => Update::Fetched { + reading: reading_clone, + thing: Fetchable::Data { + timestamps: data.0, + data: data.1, + }, }, + Err(err) => Update::FetchError(err), }, - Err(err) => Update::FetchError(err), - }, - tx, - )), - Request::Logs(Logs { reading, range }) => tokio::spawn(get_wrap_send( - get_logs(log_store, reading.clone()), - "Could not fetch logs", - move |res| match res { - Ok(logs) => Update::Fetched { - reading, - thing: Fetchable::Logs { - logs, - start_at: *range.start(), + tx, + )) + } + Request::Logs(Logs { reading, range }) => { + let reading_clone = reading.clone(); + tokio::spawn(get_retry_then_wrap_send( + move || get_logs(log_store, reading.clone().clone()), + log_store_queue.clone(), + "Could not fetch logs", + move |res| match res { + Ok(logs) => Update::Fetched { + reading: reading_clone, + thing: Fetchable::Logs { + logs, + start_at: *range.start(), + }, }, + Err(err) => Update::FetchError(err), }, - Err(err) => Update::FetchError(err), - }, - tx, - )), - Request::Hist(Hist { reading, range }) => tokio::spawn(get_wrap_send( - get_percentiles(log_store, reading.clone()), - "Could not fetch percentiles for histogram", - move |res| match res { - Ok(percentiles) => Update::Fetched { - reading, - thing: Fetchable::Hist { percentiles, range }, + tx, + )) + } + Request::Hist(Hist { reading, range }) => { + let reading_clone = reading.clone(); + tokio::spawn(get_retry_then_wrap_send( + move || get_percentiles(log_store, reading.clone()), + log_store_queue.clone(), + "Could not fetch percentiles for histogram", + move |res| match res { + Ok(percentiles) => Update::Fetched { + reading: reading_clone, + thing: Fetchable::Hist { percentiles, range }, + }, + Err(err) => Update::FetchError(err), }, - Err(err) => Update::FetchError(err), - }, - tx, - )), + tx, + )) + } }; inflight_request.push_front(handle); if inflight_request.len() > 6 { @@ -259,62 +275,151 @@ pub(crate) async fn handle_requests( } } -pub async fn get_wrap_send( - getter: impl Future>, +#[derive(Debug, Clone, Default)] +struct Queue(Arc>); + +impl Queue { + fn register(&self) -> usize { + let this = self.0.lock().unwrap(); + let mut most_recent_request = this.most_recent_request; + most_recent_request += 1; + most_recent_request + } + + fn set_next_allowed(&self, at: Instant) { + let mut this = self.0.lock().unwrap(); + this.next_allowed = Some(at); + } + + fn our_turn(&self, id: usize) -> Result, Instant> { + let this = self.0.lock().unwrap(); + if let Some(next_allowed) = this.next_allowed { + if this.most_recent_request == id { + Ok(Some(next_allowed)) + } else { + Err(next_allowed) + } + } else { + Ok(None) + } + } +} + +#[derive(Debug, Default)] +struct InnerLimits { + next_allowed: Option, + most_recent_request: usize, +} + +#[must_use] +enum GetResult { + Ok(T), + Err(eyre::Error), + RateLimited { allowed_in: Duration }, +} + +impl From> for GetResult { + fn from(value: Result) -> Self { + match value { + Ok(v) => Self::Ok(v), + Err(e) => Self::Err(e), + } + } +} + +async fn get_retry_then_wrap_send>>( + getter: impl Fn() -> F, + queue: Queue, err_text: &'static str, wrapper: impl FnOnce(Result) -> Update, tx: mpsc::Sender, ) { - let val = getter.await.wrap_err(err_text); - let update = (wrapper)(val); + let id = queue.register(); + + let update = loop { + match queue.our_turn(id) { + Ok(Some(allowed_at)) => tokio::time::sleep_until(allowed_at).await, + Ok(None) => (), + Err(recheck_at) => { + tokio::time::sleep_until(recheck_at).await; + continue; + } + } + + match getter().await { + GetResult::Ok(val) => break wrapper(Ok(val)), + GetResult::Err(e) => break wrapper(Err(e).wrap_err(err_text)), + GetResult::RateLimited { allowed_in } => { + queue.set_next_allowed(Instant::now() + allowed_in); + } + } + }; tx.send(update).unwrap(); } -pub async fn get_data( +async fn get_data( data_store: SocketAddr, reading: Reading, range: RangeInclusive, -) -> Result<(Vec, Vec)> { - use data_store::api::{client::Error, Data, GetDataError}; +) -> GetResult<(Vec, Vec)> { + use data_store::api::{client::ConnectError, client::Error, Data, GetDataError}; - let mut api = data_store::api::Client::connect(data_store, client_name()) - .await - .wrap_err("Could not connect to data-store")?; + let mut api = match data_store::api::Client::connect(data_store, client_name()).await { + Ok(api) => api, + Err(ConnectError::RateLimited(d)) => return GetResult::RateLimited { allowed_in: d }, + Err(other) => { + return GetResult::Err(Report::new(other).wrap_err("Could not connect to data-store")) + } + }; match api .get_data(*range.start(), *range.end(), reading, 300) .await { - Ok(Data { time, values }) => Ok((time, values)), + Ok(Data { time, values }) => GetResult::Ok((time, values)), Err(Error::Request(GetDataError::NotFound)) | Err(Error::Request(GetDataError::EmptyFile)) | Err(Error::Request(GetDataError::StartAfterData)) | Err(Error::Request(GetDataError::StopBeforeData)) - | Err(Error::Request(GetDataError::NotInStore { .. })) => Ok((Vec::new(), Vec::new())), - Err(other) => Err(other).wrap_err("Data-store returned an error to our request"), + | Err(Error::Request(GetDataError::NotInStore { .. })) => { + GetResult::Ok((Vec::new(), Vec::new())) + } + Err(other) => GetResult::Err( + Report::new(other).wrap_err("Data-store returned an error to our request"), + ), } } -pub async fn get_logs(log_store: SocketAddr, reading: Reading) -> Result> { - let mut api = log_store::api::Client::connect(log_store, client_name()) - .await - .wrap_err("Could not connect to log-store")?; +async fn get_logs(log_store: SocketAddr, reading: Reading) -> GetResult> { + use log_store::api::client::{Client, ConnectError}; + + let mut api = match Client::connect(log_store, client_name()).await { + Ok(api) => api, + Err(ConnectError::RateLimited(d)) => return GetResult::RateLimited { allowed_in: d }, + Err(other) => { + return GetResult::Err(Report::new(other).wrap_err("Could not connect to log-store")) + } + }; - let history = api - .get_logs(reading.device()) + api.get_logs(reading.device()) .await - .wrap_err("Log store returned an error to our request")?; - Ok(history) + .wrap_err("Log store returned an error to our request") + .into() } -pub async fn get_percentiles(log_store: SocketAddr, reading: Reading) -> Result> { - let mut api = log_store::api::Client::connect(log_store, client_name()) - .await - .wrap_err("Could not connect to log-store")?; +async fn get_percentiles(log_store: SocketAddr, reading: Reading) -> GetResult> { + use log_store::api::client::{Client, ConnectError}; + + let mut api = match Client::connect(log_store, client_name()).await { + Ok(api) => api, + Err(ConnectError::RateLimited(d)) => return GetResult::RateLimited { allowed_in: d }, + Err(other) => { + return GetResult::Err(Report::new(other).wrap_err("Could not connect to log-store")) + } + }; - let percentile = api - .get_percentiles(reading.device()) + api.get_percentiles(reading.device()) .await - .wrap_err("Log store returned an error to our request")?; - Ok(percentile) + .wrap_err("Log store returned an error to our request") + .into() } From 93b5d5c8a25bf82883ff5bf1b9617eddce464bc5 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 11 Sep 2024 01:33:56 +0200 Subject: [PATCH 254/687] on hanging button send error --- crates/data-server/src/server/affector.rs | 2 +- crates/protocol/src/button.rs | 13 +++++++------ crates/protocol/src/large_bedroom/bed.rs | 3 +++ sensor-nodes/bed-sensors/src/error_cache.rs | 19 +++++++++++++++---- sensor-nodes/bed-sensors/src/main.rs | 6 +++--- sensor-nodes/bed-sensors/src/network.rs | 6 ++++-- sensor-nodes/bed-sensors/src/rgb_led.rs | 4 ++-- sensor-nodes/bed-sensors/src/sensors/fast.rs | 9 +++++++-- sensor-nodes/bed-sensors/src/sensors/slow.rs | 13 ++++++++----- 9 files changed, 50 insertions(+), 25 deletions(-) diff --git a/crates/data-server/src/server/affector.rs b/crates/data-server/src/server/affector.rs index 91d8cc6d..d1404c39 100644 --- a/crates/data-server/src/server/affector.rs +++ b/crates/data-server/src/server/affector.rs @@ -58,7 +58,7 @@ impl Registar { pub(crate) fn remove(&self, key: DefaultKey) { let mut this = self.0.lock().expect("nothing should panic"); - this.remove(key).expect("things are only removed once"); + let _ = this.remove(key); // could have been removed by register } pub(crate) fn activate(&self, order: Affector) -> Result<(), Offline> { diff --git a/crates/protocol/src/button.rs b/crates/protocol/src/button.rs index f0252264..0a9e2428 100644 --- a/crates/protocol/src/button.rs +++ b/crates/protocol/src/button.rs @@ -56,6 +56,12 @@ macro_rules! button_enum { $(Self::$variant(d) => *d,)* } } + + pub fn variant_name(&self) -> &'static str { + match self { + $(Self::$variant(_) => stringify!($variant),)* + } + } } impl From<$name> for f32 { @@ -81,12 +87,7 @@ macro_rules! button_enum { }) } fn name(&self) -> String { - let dbg_repr = format!("{:?}", self); - dbg_repr - .split_once('(') - .map(|(name, _)| name) - .unwrap_or("-") - .to_string() + self.variant_name().to_owned() } fn branch_id(&self) -> crate::reading::tree::Id { // SAFETY: Because `Self` is marked `repr(u8)`, its layout is a diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 7547da0d..74e0d9f0 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -326,6 +326,7 @@ pub enum SensorError { Max44(heapless::String<200>), Mhz14(heapless::String<200>), Sps30(heapless::String<200>), + Button(heapless::String<200>), Nau7802Left(heapless::String<200>), Nau7802Right(heapless::String<200>), } @@ -338,6 +339,7 @@ impl core::fmt::Display for SensorError { | SensorError::Max44(e) | SensorError::Mhz14(e) | SensorError::Sps30(e) + | SensorError::Button(e) | SensorError::Nau7802Left(e) | SensorError::Nau7802Right(e) => write!(f, "{e}"), } @@ -357,6 +359,7 @@ impl SensorError { SensorError::Max44(_) => Device::Max44, SensorError::Mhz14(_) => Device::Mhz14, SensorError::Sps30(_) => Device::Sps30, + SensorError::Button(_) => Device::Gpio, SensorError::Nau7802Left(_) => Device::Nau7802Right, SensorError::Nau7802Right(_) => Device::Nau7802Right, } diff --git a/sensor-nodes/bed-sensors/src/error_cache.rs b/sensor-nodes/bed-sensors/src/error_cache.rs index b5c6837e..416736ee 100644 --- a/sensor-nodes/bed-sensors/src/error_cache.rs +++ b/sensor-nodes/bed-sensors/src/error_cache.rs @@ -4,7 +4,7 @@ use protocol::make_error_string; use crate::sensors::{I2cError, UartError}; #[derive(defmt::Format, PartialEq, Eq, Clone)] -pub enum SensorError { +pub(crate) enum SensorError { Mhz14(mhzx::Error), Sps30(sps30_async::Error), Sht31(sht31::SHTError), @@ -12,6 +12,18 @@ pub enum SensorError { Max44(max44009::Error), Nau7802Left(nau7802_async::Error), Nau7802Right(nau7802_async::Error), + Button(PressTooLong), +} + +#[derive(defmt::Format, PartialEq, Eq, Clone)] +pub(crate) struct PressTooLong { + pub(crate) button: &'static str, +} + +impl core::fmt::Debug for PressTooLong { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.write_fmt(format_args!("Button {}, pressed too long", self.button)) + } } impl From for bed::SensorError { @@ -24,16 +36,16 @@ impl From for bed::SensorError { SensorError::Max44(e) => bed::SensorError::Max44(make_error_string(e)), SensorError::Nau7802Left(e) => bed::SensorError::Nau7802Left(make_error_string(e)), SensorError::Nau7802Right(e) => bed::SensorError::Nau7802Right(make_error_string(e)), + SensorError::Button(e) => bed::SensorError::Button(make_error_string(e)), } } } #[derive(defmt::Format, PartialEq, Eq, Clone)] -pub enum Error { +pub(crate) enum Error { Running(SensorError), Setup(SensorError), Timeout(Device), - SetupTimedOut(Device), } impl From for bed::Error { @@ -42,7 +54,6 @@ impl From for bed::Error { Error::Running(e) => bed::Error::Running(e.into()), Error::Setup(e) => bed::Error::Setup(e.into()), Error::Timeout(dev) => bed::Error::Timeout(dev), - Error::SetupTimedOut(dev) => bed::Error::SetupTimedOut(dev), } } } diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index 3f5672fb..926f079c 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -109,7 +109,7 @@ async fn main(spawner: Spawner) { usart_config.baudrate = 115_200; // sps30 only works at this baud usart_config.data_bits = DataBits::DataBits8; usart_config.stop_bits = StopBits::STOP1; - // usart_config.parity = Parity::ParityNone; + usart_config.parity = Parity::ParityNone; let usart_sps30 = unwrap!(Uart::new( p.USART2, p.PA3, @@ -163,9 +163,9 @@ async fn main(spawner: Spawner) { let buttons = ButtonInputs { top: ExtiInput::new(p.PC14, p.EXTI14, Pull::Down), middle_inner: ExtiInput::new(p.PA9, p.EXTI9, Pull::Down), - middle_center: ExtiInput::new(p.PA12, p.EXTI12, Pull::Down), + middle_center: ExtiInput::new(p.PC13, p.EXTI13, Pull::Down), middle_outer: ExtiInput::new(p.PA10, p.EXTI10, Pull::Down), - lower_inner: ExtiInput::new(p.PA11, p.EXTI11, Pull::Down), + lower_inner: ExtiInput::new(p.PA12, p.EXTI12, Pull::Down), lower_center: ExtiInput::new(p.PA15, p.EXTI15, Pull::Down), lower_outer: ExtiInput::new(p.PB5, p.EXTI5, Pull::Down), }; diff --git a/sensor-nodes/bed-sensors/src/network.rs b/sensor-nodes/bed-sensors/src/network.rs index 45212240..c2d7104e 100644 --- a/sensor-nodes/bed-sensors/src/network.rs +++ b/sensor-nodes/bed-sensors/src/network.rs @@ -86,7 +86,7 @@ pub async fn handle(stack: &Stack, publish: &Queues, led: LedHandle continue; } info!("(re-)connected"); - // prevent out-dated data from being send + // Prevent out-dated data from being send publish.clear().await; let (reader, writer) = socket.split(); @@ -94,9 +94,11 @@ pub async fn handle(stack: &Stack, publish: &Queues, led: LedHandle select::Either::First(e) => warn!("Error while sending messages: {}", e), select::Either::Second(e) => warn!("Error receiving orders: {}", e), }; - // or the socket will hang for a while waiting to close this makes sure + // Or the socket will hang for a while waiting to close this makes sure // we can reconnect instantly socket.abort(); + // Do not trigger data-server rate-limit + Timer::after(Duration::from_secs(2)).await; } } diff --git a/sensor-nodes/bed-sensors/src/rgb_led.rs b/sensor-nodes/bed-sensors/src/rgb_led.rs index 1f593416..d7e5e7c0 100644 --- a/sensor-nodes/bed-sensors/src/rgb_led.rs +++ b/sensor-nodes/bed-sensors/src/rgb_led.rs @@ -56,11 +56,11 @@ impl RgbLed { } fn set_red(&mut self, brightness: f32) { - self.set(timer::Channel::Ch2, brightness); + self.set(timer::Channel::Ch1, brightness); } fn set_blue(&mut self, brightness: f32) { - self.set(timer::Channel::Ch1, brightness); + self.set(timer::Channel::Ch2, brightness); } fn set_green(&mut self, brightness: f32) { diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed-sensors/src/sensors/fast.rs index 6da271fe..7df50ecc 100644 --- a/sensor-nodes/bed-sensors/src/sensors/fast.rs +++ b/sensor-nodes/bed-sensors/src/sensors/fast.rs @@ -1,4 +1,3 @@ -use defmt::warn; use embassy_futures::join::{join3, join4}; use embassy_futures::{join, yield_now}; use embassy_stm32::exti::ExtiInput; @@ -105,13 +104,19 @@ async fn watch_button( event: impl Fn(protocol::button::Press) -> Button, channel: &Queues, ) { + use crate::error_cache::{Error, PressTooLong, SensorError}; + let mut went_high_at: Option = None; loop { if let Some(went_high_at) = went_high_at.take() { input.wait_for_low().await; let press = went_high_at.elapsed(); let Ok(press) = press.as_millis().try_into() else { - warn!("extremely long button press registered, skipping"); + let event_for_printing = (event)(protocol::button::Press(0)); + let name = event_for_printing.variant_name(); + channel.queue_error(Error::Running(SensorError::Button(PressTooLong { + button: name, + }))); continue; }; let event = (event)(protocol::button::Press(press)); diff --git a/sensor-nodes/bed-sensors/src/sensors/slow.rs b/sensor-nodes/bed-sensors/src/sensors/slow.rs index a9987907..73675422 100644 --- a/sensor-nodes/bed-sensors/src/sensors/slow.rs +++ b/sensor-nodes/bed-sensors/src/sensors/slow.rs @@ -19,8 +19,11 @@ use super::concrete_types::ConcreteRx as Rx; use super::concrete_types::ConcreteTx as Tx; type Signal = embassy_sync::signal::Signal; + +/// Measure when signal is received or control the device's +/// affector when it is ordered #[inline(always)] -async fn measure_and_send_on_signal(mut driver: D, send: F, signal: &Signal) +async fn measure_and_control(mut driver: D, send: F, signal: &Signal) where D: Driver, F: Fn(Result) -> (), @@ -58,10 +61,10 @@ pub async fn read( join5( order_measurements_every_period(&signals), - measure_and_send_on_signal(sht, |res| publish_sht_result(res, &publish), &signals[0]), - measure_and_send_on_signal(bme, |res| publish_bme_result(res, &publish), &signals[1]), - measure_and_send_on_signal(mhz, |res| publish_mhz_result(res, &publish), &signals[2]), - measure_and_send_on_signal(sps, |res| publish_sps_result(res, &publish), &signals[3]), + measure_and_control(sht, |res| publish_sht_result(res, &publish), &signals[0]), + measure_and_control(bme, |res| publish_bme_result(res, &publish), &signals[1]), + measure_and_control(mhz, |res| publish_mhz_result(res, &publish), &signals[2]), + measure_and_control(sps, |res| publish_sps_result(res, &publish), &signals[3]), ) .await; } From 3fe8e3b1772c2a2095cea9ee688ab58eee6c2a6f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 11 Sep 2024 01:49:07 +0200 Subject: [PATCH 255/687] show last controller of affector --- crates/rpc/src/client.rs | 1 - crates/sensor-tui/src/tui/affectors.rs | 25 +++++++++++++++---- crates/sensor-tui/src/tui/affectors/render.rs | 17 +++++++------ 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/crates/rpc/src/client.rs b/crates/rpc/src/client.rs index 8f6364b1..a0c58943 100644 --- a/crates/rpc/src/client.rs +++ b/crates/rpc/src/client.rs @@ -8,7 +8,6 @@ use serde::Serialize; use tokio::net::TcpStream; use tokio::net::ToSocketAddrs; use tokio::time::error::Elapsed; -use tokio::time::sleep; use tokio::time::timeout_at; use tokio::time::Instant; use tokio_serde::formats::Bincode; diff --git a/crates/sensor-tui/src/tui/affectors.rs b/crates/sensor-tui/src/tui/affectors.rs index f877f936..c188ebc8 100644 --- a/crates/sensor-tui/src/tui/affectors.rs +++ b/crates/sensor-tui/src/tui/affectors.rs @@ -22,6 +22,7 @@ pub type TreeKey = [u8; 6]; struct AffectorState { affector: Affector, selected_control: usize, + last_controlled_by: Option, info: affector::Info, device_broken: DeviceBroken, } @@ -95,20 +96,23 @@ impl Tab { | Update::SensorReading(_) | Update::DeviceList(_) | Update::SubscribeError(_) => Some(update), - Update::AffectorControlled { affector, .. } => { - self.update_tree(&affector, DeviceBroken::No); + Update::AffectorControlled { + affector, + controlled_by, + } => { + self.update_tree(&affector, Some(controlled_by), DeviceBroken::No); None } Update::SensorError(ref err) => { let broken = err.device().info().affectors; for affector in broken { - self.update_tree(affector, DeviceBroken::Yes); + self.update_tree(affector, None, DeviceBroken::Yes); } Some(update) } Update::AffectorList(affectors) => { for affector in affectors { - self.update_tree(&affector, DeviceBroken::No); + self.update_tree(&affector, None, DeviceBroken::No); } None } @@ -129,7 +133,12 @@ enum DeviceBroken { } impl Tab { - fn update_tree(&mut self, affector: &protocol::Affector, broken: DeviceBroken) { + fn update_tree( + &mut self, + affector: &protocol::Affector, + controller: Option, + broken: DeviceBroken, + ) { let key = tree_key(affector); let mut tree = add_root(affector as &dyn AffectorTree, &mut self.ground); @@ -145,10 +154,16 @@ impl Tab { self.data .entry(key) .and_modify(|state| state.affector = affector.clone()) + .and_modify(|state| { + if controller.is_some() { + state.last_controlled_by = controller.clone(); + } + }) .or_insert(AffectorState { affector: affector.clone(), info, selected_control: 0, + last_controlled_by: controller, device_broken: broken, }); return; diff --git a/crates/sensor-tui/src/tui/affectors/render.rs b/crates/sensor-tui/src/tui/affectors/render.rs index 26baf18a..122c6a4f 100644 --- a/crates/sensor-tui/src/tui/affectors/render.rs +++ b/crates/sensor-tui/src/tui/affectors/render.rs @@ -34,14 +34,15 @@ pub(super) fn tree( } pub(super) fn details(frame: &mut Frame, data: &&mut AffectorState, top: Rect) { - let text = if let DeviceBroken::No = data.device_broken { - data.info.description.to_string() - } else { - format!( - "{}\n\nWarning: Device reports error, affector might not work", - data.info.description - ) - }; + let mut text = vec![data.info.description.to_owned()]; + if let Some(ref name) = data.last_controlled_by { + text.push(format!("\nlast controlled by: {name}")); + } + if let DeviceBroken::Yes = data.device_broken { + text.push("\nWarning: Device reports error, affector might not work".to_owned()); + } + let text = text.join("\n"); + frame.render_widget( widgets::Paragraph::new(text) .block(Block::bordered().title("Details")) From 1fc424178fe0b3ce4ea94fde838ff33ba19bd473 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 11 Sep 2024 14:31:56 +0200 Subject: [PATCH 256/687] data-store: turn panic on out of range value into error --- crates/data-store/src/server/db.rs | 1 - crates/data-store/src/server/db/series.rs | 14 ++++++++++---- crates/protocol/src/large_bedroom/bed.rs | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index 522d772e..29e57720 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -33,7 +33,6 @@ pub(crate) async fn run(data_server_addr: SocketAddr, data: Data, data_dir: &Pat const FIVE_MIN: Duration = Duration::from_secs(60 * 5); if let Err(report) = res { let e = format!("got error with report: {report:?}"); - tracing::warn!("test: {e}"); if recently_logged.1 == e && recently_logged.0.elapsed() <= FIVE_MIN { continue; } else { diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index 76e2ce9d..133c9615 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf}; use std::time::Instant; use byteseries::{downsample, series, ByteSeries}; -use color_eyre::eyre::WrapErr; +use color_eyre::eyre::{eyre, WrapErr}; use color_eyre::{Result, Section}; use protocol::reading; use protocol::reading::tree::{Item, Tree}; @@ -113,6 +113,14 @@ impl Series { ); let meta = &mut self.meta_list[index]; + if !reading.leaf().range.contains(*reading.leaf().val) { + return Err(eyre!( + "value {} is out of range: {:?}", + reading.leaf().val, + reading.leaf().range + )); + } + meta.field.encode(reading.leaf().val, &mut self.line); meta.set_at = Some(Instant::now()); @@ -122,9 +130,7 @@ impl Series { .meta_list .iter() .map(|Meta { set_at, .. }| set_at) - .all(|set| { - set.is_some_and(|set| set.elapsed() < max_interval) - }) + .all(|set| set.is_some_and(|set| set.elapsed() < max_interval)) { let time = jiff::Timestamp::now(); diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 74e0d9f0..8bd03f8d 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -97,7 +97,7 @@ impl Tree for Reading { Reading::Brightness(val) => ( *val, Device::Max44.rooted(), - 0.045..188.000, + 0.0..188.000, 0.045, Unit::Lux, "Brightness", From a8033ab4657e6c6f77176a0f7d0b60332c692636 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 11 Sep 2024 17:00:59 +0200 Subject: [PATCH 257/687] tui: refactor --- crates/data-store/src/server/db/series.rs | 2 +- crates/sensor-tui/src/tui.rs | 6 +++- crates/sensor-tui/src/tui/readings.rs | 35 ++++++++++++++++------- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index 133c9615..051f3b1b 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -113,7 +113,7 @@ impl Series { ); let meta = &mut self.meta_list[index]; - if !reading.leaf().range.contains(*reading.leaf().val) { + if !reading.leaf().range.contains(&reading.leaf().val) { return Err(eyre!( "value {} is out of range: {:?}", reading.leaf().val, diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index c56e0193..88e3eeb6 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -102,12 +102,16 @@ impl App { match self.active_tab { ActiveTab::Readings => { self.readings_tab - .render(&mut fetcher, frame, layout, &self.theme) + .render(frame, layout, &self.theme) } ActiveTab::Affectors => self.affectors_tab.render(frame, layout, &self.theme), } })?; + if let ActiveTab::Readings = self.active_tab { + self.readings_tab.fetch_if_needed(&mut fetcher); + } + if event::poll(Duration::from_millis(16))? { if let event::Event::Key(key) = event::read()? { tracing::trace!("key pressed: {key:?}"); diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index 177bad22..492c3cd4 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -50,7 +50,7 @@ impl Default for Tab { } impl Tab { - pub fn render(&mut self, fetcher: &mut Fetch, frame: &mut Frame, layout: Rect, theme: &Theme) { + pub fn render(&mut self, frame: &mut Frame, layout: Rect, theme: &Theme) { let Self { ui_state, readings, @@ -64,17 +64,7 @@ impl Tab { .last() // unique leaf id .and_then(|key| readings.data.get_mut(key)); - let dur = ui_state.history_length.dur; - let history_len = &mut ui_state.history_length.state; if let Some(data) = data { - fetcher.assure_up_to_date( - dur, - || *history_len = history_len::State::Fetching(Instant::now()), - data.reading.clone(), - data.oldest_in_history(), - data.logs_from_store_hist, - data.histogram_range.clone(), - ); ( data.chart(plot_buf), data.percentiles(), @@ -148,6 +138,29 @@ impl Tab { self.ui_state.tree_state.select_first(); } } + + pub(crate) fn fetch_if_needed(&mut self, fetcher: &mut Fetch) { + let Some(data) = self + .ui_state + .tree_state + .selected() + .last() // Unique leaf id + .and_then(|key| self.readings.data.get_mut(key)) + else { + return; // nothing selected + }; + + let dur = self.ui_state.history_length.dur; + let history_len = &mut self.ui_state.history_length.state; + fetcher.assure_up_to_date( + dur, + || *history_len = history_len::State::Fetching(Instant::now()), + data.reading.clone(), + data.oldest_in_history(), + data.logs_from_store_hist, + data.histogram_range.clone(), + ); + } } impl UiState { From 450ebb89633a1245de7154178e1a8c270e84ba9e Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 11 Sep 2024 21:50:53 +0200 Subject: [PATCH 258/687] tui: fix chart history shrinking --- crates/sensor-tui/src/fetch.rs | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index f5d58af8..aba256a4 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -1,18 +1,19 @@ use std::collections::VecDeque; use std::future::Future; use std::net::SocketAddr; -use std::ops::RangeInclusive; +use std::ops::{Mul, RangeInclusive}; use std::sync::{mpsc, Arc}; +use std::thread; use std::time::Duration; use color_eyre::eyre::{self, Context, Report}; use color_eyre::Result; -use jiff::{Span, Timestamp}; +use jiff::{Span, Timestamp, Unit}; use log_store::api::{ErrorEvent, Percentile}; use protocol::Reading; use std::sync::Mutex; use tokio::time::Instant; -use tracing::debug; +use tracing::{debug, instrument}; use crate::{client_name, Fetchable, Update}; @@ -84,6 +85,7 @@ impl Fetch { } } + #[instrument(skip(self, on_fetch_start))] pub fn assure_up_to_date( &mut self, history_len: Duration, @@ -119,26 +121,36 @@ impl Fetch { } } + #[instrument(skip(self))] fn history_outdated_not_updating( &mut self, reading: &Reading, oldest_needed: Timestamp, oldest_in_history: Timestamp, ) -> bool { - if oldest_in_history <= oldest_needed { - return false; - } + let target_span = Timestamp::now() - oldest_needed; + let target_span = target_span.total(Unit::Millisecond).expect("fits i64"); + let max_span = (target_span as f64 * 1.2) as i64; + + let oldest_allowed = Timestamp::now().as_millisecond() - max_span; + let up_to_date = |start: &i64| *start >= oldest_allowed as i64; - let margin = oldest_needed.as_millisecond() as f64 * 1.2; - let not_too_old = |start: &i64| *start < margin as i64; + let curr_up_to_date = up_to_date(&oldest_in_history.as_millisecond()); + let curr_range_correct = oldest_in_history <= oldest_needed; + + if curr_up_to_date && curr_range_correct { + return false; // no need for update + } + // is there an ongoing request that will fix this? !self .recently_issued .iter() .filter_map(Request::data) .filter(|req| req.reading.is_same_as(reading)) .map(|req| req.range.start().as_millisecond()) - .filter(not_too_old) + .filter(up_to_date) + .inspect(|start| tracing::debug!("start: {start}")) .any(|start| start <= oldest_needed.as_millisecond()) } From a34d3bddae2782234e6471e42b91cfdedd0c4710 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 11 Sep 2024 22:51:51 +0200 Subject: [PATCH 259/687] braing/lb make buttons full bightness/normal & fadeout --- .../src/controller/rooms/large_bedroom.rs | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/crates/brain/src/controller/rooms/large_bedroom.rs b/crates/brain/src/controller/rooms/large_bedroom.rs index 76ea09eb..60e51689 100644 --- a/crates/brain/src/controller/rooms/large_bedroom.rs +++ b/crates/brain/src/controller/rooms/large_bedroom.rs @@ -43,11 +43,12 @@ enum RelevantEvent { // WeightRight(u32), // Brightness(f32), // millilux DeskButton(protocol::large_bedroom::desk::Button), + BedButton(protocol::large_bedroom::bed::Button), // BedButton(protocol::large_bedroom::bed::Button), } fn filter(event: Event) -> Option { - // use protocol::large_bedroom::bed::Reading as B; + use protocol::large_bedroom::bed::Reading as B; use protocol::large_bedroom::desk::Reading as D; use protocol::large_bedroom::Reading as R; use protocol::Reading::LargeBedroom as LB; @@ -56,7 +57,7 @@ fn filter(event: Event) -> Option { Some(match event { WakeUp => RelevantEvent::WakeUp, Sensor(LB(R::Desk(D::Button(b)))) => RelevantEvent::DeskButton(b), - // Sensor(LB(R::Bed(B::Button(b)))) => RelevantEvent::BedButton(b), + Sensor(LB(R::Bed(B::Button(b)))) => RelevantEvent::BedButton(b), // Sensor(LB(R::Bed(B::Brightness(l)))) => RelevantEvent::Brightness(l), // Sensor(LB(R::Bed(B::WeightLeft(w)))) => RelevantEvent::WeightLeft(w), // Sensor(LB(R::Bed(B::WeightRight(w)))) => RelevantEvent::WeightRight(w), @@ -121,7 +122,7 @@ async fn update(system: &mut RestrictedSystem, state: &State) -> Option { system.all_lamps_on().await; system.all_lamps_ct(1, u8::MAX).await; if started.elapsed() > Duration::from_secs(40) { - return Some(State::Off) + return Some(State::Off); } } } @@ -147,12 +148,13 @@ fn handle_event(e: RelevantEvent) -> Option { // RelevantEvent::WeightLeft(_) => (), // RelevantEvent::WeightRight(_) => (), // RelevantEvent::Brightness(_) => (), - RelevantEvent::DeskButton(b) => handle_button(b), + RelevantEvent::DeskButton(b) => handle_desk_button(b), + RelevantEvent::BedButton(b) => handle_bed_button(b), // RelevantEvent::BedButton(_) => (), } } -fn handle_button(b: protocol::large_bedroom::desk::Button) -> Option { +fn handle_desk_button(b: protocol::large_bedroom::desk::Button) -> Option { use protocol::large_bedroom::desk::Button; println!("button pressed: {b:?}"); @@ -169,3 +171,15 @@ fn handle_button(b: protocol::large_bedroom::desk::Button) -> Option { _ => None, } } + +fn handle_bed_button(b: protocol::large_bedroom::bed::Button) -> Option { + use protocol::large_bedroom::bed::Button as B; + + println!("button pressed: {b:?}"); + match b { + B::MiddleOuter(_) => Some(State::Bright), + B::MiddleInner(_) => Some(State::Normal), + B::MiddleCenter(_) => Some(State::FadeOut(Instant::now())), + _ => None, + } +} From 8f080f022fd04eec9f9e73998d2a84bb8abe9469 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 11 Sep 2024 22:52:17 +0200 Subject: [PATCH 260/687] made client errors (such as disconnect) debug --- crates/data-server/src/server/data_source.rs | 6 +++--- crates/rpc/src/lib.rs | 2 ++ crates/rpc/src/server.rs | 16 +++++++++------- crates/sensor-tui/src/fetch.rs | 3 +-- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/crates/data-server/src/server/data_source.rs b/crates/data-server/src/server/data_source.rs index 455566f7..1fac36c9 100644 --- a/crates/data-server/src/server/data_source.rs +++ b/crates/data-server/src/server/data_source.rs @@ -87,11 +87,11 @@ async fn handle_node( let affectors = match handshake(&mut reader).await { Ok(affectors) => affectors, Err(e) => { - error!("failed handshake: {e}"); + error!("failed node handshake: {e}"); return; } }; - debug!("new node connected with affectors: {affectors:?}"); + info!("new node connected with affectors: {affectors:?}"); let (tx, rx) = tokio::sync::mpsc::channel(10); let key = registar.register(tx, affectors); @@ -103,7 +103,7 @@ async fn handle_node( .await; registar.remove(key); - debug!("node removed"); + warn!("node removed (lost connection)"); } async fn handshake(reader: &mut BufReader) -> Result, String> { diff --git a/crates/rpc/src/lib.rs b/crates/rpc/src/lib.rs index ad87484a..dce82eea 100644 --- a/crates/rpc/src/lib.rs +++ b/crates/rpc/src/lib.rs @@ -13,6 +13,8 @@ pub(crate) const MAX_PACKAGE_SIZE: usize = 8 * 1024 * 1024; pub trait SubscriberHandler: Send + 'static { type Update; + + /// The returned stream should never end before the client disconnects. #[allow(async_fn_in_trait)] fn setup( &mut self, diff --git a/crates/rpc/src/server.rs b/crates/rpc/src/server.rs index 21a59671..38b0ecc5 100644 --- a/crates/rpc/src/server.rs +++ b/crates/rpc/src/server.rs @@ -67,7 +67,7 @@ where continue; } - info!("Client {name} connected from {source}"); + debug!("Client {name} connected from {source}"); let Ok(()) = conn.send(crate::Response::HandshakeOk).await else { continue; }; @@ -119,6 +119,8 @@ use core::future::Future; use crate::SubscriberHandler; #[instrument(skip(conn, perform_request, sub_handler))] +/// When the provided sub_handler is used to create a stream that stream should +/// never end before the client disconnects async fn handle_client( mut conn: Conn, client_name: String, @@ -154,17 +156,17 @@ async fn handle_client( let stream = sub_handler.setup().await; pin!(stream); if let Err(e) = conn.send(crate::Response::SubscribeOk).await { - error!("Error sending response to client: {e:?}"); + debug!("Error sending response to client: {e:?}"); return; } loop { - let Some(update) = stream.next().await else { - error!("Error subscribe stream should never end"); - return; - }; + let update = stream + .next() + .await + .expect("subscribe stream should never end"); if let Err(e) = conn.send(crate::Response::Update(update)).await { - error!("Error sending response to client: {e:?}"); + debug!("Error sending response to client: {e:?}"); return; } } diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index aba256a4..8c94d189 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -1,9 +1,8 @@ use std::collections::VecDeque; use std::future::Future; use std::net::SocketAddr; -use std::ops::{Mul, RangeInclusive}; +use std::ops::RangeInclusive; use std::sync::{mpsc, Arc}; -use std::thread; use std::time::Duration; use color_eyre::eyre::{self, Context, Report}; From 6ef60fb3c0baa4857d48049b73223a5fa2efe88b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 12 Sep 2024 01:32:32 +0200 Subject: [PATCH 261/687] fix range of lux reading --- crates/protocol/src/large_bedroom/bed.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 8bd03f8d..447fe02e 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -97,7 +97,7 @@ impl Tree for Reading { Reading::Brightness(val) => ( *val, Device::Max44.rooted(), - 0.0..188.000, + 0.0..188_000.0, 0.045, Unit::Lux, "Brightness", From c86cd04ebd96ace67a7ba45c872428d4dff2f260 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 13 Sep 2024 00:58:41 +0200 Subject: [PATCH 262/687] fix request slowing under ratelimit not working --- crates/sensor-tui/src/fetch.rs | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index 8c94d189..b157f303 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -149,7 +149,6 @@ impl Fetch { .filter(|req| req.reading.is_same_as(reading)) .map(|req| req.range.start().as_millisecond()) .filter(up_to_date) - .inspect(|start| tracing::debug!("start: {start}")) .any(|start| start <= oldest_needed.as_millisecond()) } @@ -291,10 +290,11 @@ struct Queue(Arc>); impl Queue { fn register(&self) -> usize { - let this = self.0.lock().unwrap(); - let mut most_recent_request = this.most_recent_request; - most_recent_request += 1; - most_recent_request + let mut this = self.0.lock().unwrap(); + let most_recent_request = &mut this.most_recent_request; + *most_recent_request += 1; + tracing::trace!("registered new request: {most_recent_request}"); + *most_recent_request } fn set_next_allowed(&self, at: Instant) { @@ -304,11 +304,19 @@ impl Queue { fn our_turn(&self, id: usize) -> Result, Instant> { let this = self.0.lock().unwrap(); + let until_next_allowed = match this.next_allowed { + Some(at) => at - Instant::now(), + None => Duration::ZERO, + }; + tracing::trace!("next allowed in: {until_next_allowed:?}"); if let Some(next_allowed) = this.next_allowed { - if this.most_recent_request == id { + if until_next_allowed.is_zero() { + Ok(None) + } else if this.most_recent_request == id { Ok(Some(next_allowed)) } else { - Err(next_allowed) + // Queue behind highest priority + Err(next_allowed + Duration::from_millis(10)) } } else { Ok(None) @@ -349,9 +357,13 @@ async fn get_retry_then_wrap_send>>( let update = loop { match queue.our_turn(id) { - Ok(Some(allowed_at)) => tokio::time::sleep_until(allowed_at).await, - Ok(None) => (), + Ok(Some(allowed_at)) => { + tracing::trace!("ratelimited {id}, we are next in line"); + tokio::time::sleep_until(allowed_at).await; + } + Ok(None) => tracing::trace!("{id} not ratelimited"), Err(recheck_at) => { + tracing::trace!("ratelimited {id}, we are queued"); tokio::time::sleep_until(recheck_at).await; continue; } @@ -361,6 +373,9 @@ async fn get_retry_then_wrap_send>>( GetResult::Ok(val) => break wrapper(Ok(val)), GetResult::Err(e) => break wrapper(Err(e).wrap_err(err_text)), GetResult::RateLimited { allowed_in } => { + tracing::trace!( + "request: {id} ratelimited, next request allowed in: {allowed_in:?}" + ); queue.set_next_allowed(Instant::now() + allowed_in); } } From f5fec5ffbc5b2ab127b3eceac120059b3b62b856 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 13 Sep 2024 01:01:19 +0200 Subject: [PATCH 263/687] tui: refactored request queue --- crates/sensor-tui/src/fetch.rs | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index b157f303..9c561409 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -138,7 +138,7 @@ impl Fetch { let curr_range_correct = oldest_in_history <= oldest_needed; if curr_up_to_date && curr_range_correct { - return false; // no need for update + return false; // No need for update } // is there an ongoing request that will fix this? @@ -293,7 +293,6 @@ impl Queue { let mut this = self.0.lock().unwrap(); let most_recent_request = &mut this.most_recent_request; *most_recent_request += 1; - tracing::trace!("registered new request: {most_recent_request}"); *most_recent_request } @@ -304,13 +303,10 @@ impl Queue { fn our_turn(&self, id: usize) -> Result, Instant> { let this = self.0.lock().unwrap(); - let until_next_allowed = match this.next_allowed { - Some(at) => at - Instant::now(), - None => Duration::ZERO, - }; - tracing::trace!("next allowed in: {until_next_allowed:?}"); if let Some(next_allowed) = this.next_allowed { - if until_next_allowed.is_zero() { + let until = next_allowed.saturating_duration_since(Instant::now()); + + if until.is_zero() { Ok(None) } else if this.most_recent_request == id { Ok(Some(next_allowed)) @@ -358,12 +354,10 @@ async fn get_retry_then_wrap_send>>( let update = loop { match queue.our_turn(id) { Ok(Some(allowed_at)) => { - tracing::trace!("ratelimited {id}, we are next in line"); tokio::time::sleep_until(allowed_at).await; } - Ok(None) => tracing::trace!("{id} not ratelimited"), + Ok(None) => (), Err(recheck_at) => { - tracing::trace!("ratelimited {id}, we are queued"); tokio::time::sleep_until(recheck_at).await; continue; } @@ -373,9 +367,6 @@ async fn get_retry_then_wrap_send>>( GetResult::Ok(val) => break wrapper(Ok(val)), GetResult::Err(e) => break wrapper(Err(e).wrap_err(err_text)), GetResult::RateLimited { allowed_in } => { - tracing::trace!( - "request: {id} ratelimited, next request allowed in: {allowed_in:?}" - ); queue.set_next_allowed(Instant::now() + allowed_in); } } From 1bbfc2a6c400ba11dfd1bcf04f5b24d8e8aee23d Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 13 Sep 2024 02:20:31 +0200 Subject: [PATCH 264/687] tui: refactor logs tracking/fetching --- crates/sensor-tui/src/fetch.rs | 6 +- crates/sensor-tui/src/tui/readings.rs | 8 +-- .../src/tui/readings/render/logs.rs | 31 ++++++--- .../src/tui/readings/sensor_info.rs | 42 ++++-------- .../src/tui/readings/sensor_info/logs.rs | 65 ++++++++++++++++--- 5 files changed, 98 insertions(+), 54 deletions(-) diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index 9c561409..8d4a5a4f 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -91,7 +91,7 @@ impl Fetch { on_fetch_start: impl FnOnce() -> (), reading: Reading, oldest_in_data: Timestamp, - logs_cover_from: Option, + logs_cover_from: Timestamp, hist_cover: Option>, ) { let history_spans = Span::try_from(history_len).unwrap(); @@ -156,9 +156,9 @@ impl Fetch { &mut self, reading: &Reading, oldest_needed: Timestamp, - logs_cover_from: Option, + logs_cover_from: Timestamp, ) -> bool { - if logs_cover_from.is_some_and(|oldest| oldest <= oldest_needed) { + if logs_cover_from <= oldest_needed { return false; } diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index 492c3cd4..e7357e7d 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -61,7 +61,7 @@ impl Tab { let data = ui_state .tree_state .selected() - .last() // unique leaf id + .last() // Unique leaf id .and_then(|key| readings.data.get_mut(key)); if let Some(data) = data { @@ -104,7 +104,7 @@ impl Tab { .ui_state .tree_state .selected() - .last() // unique leaf id + .last() // Unique leaf id .and_then(|key| self.readings.data.get_mut(key)); match update { @@ -147,7 +147,7 @@ impl Tab { .last() // Unique leaf id .and_then(|key| self.readings.data.get_mut(key)) else { - return; // nothing selected + return; // Nothing selected }; let dur = self.ui_state.history_length.dur; @@ -157,7 +157,7 @@ impl Tab { || *history_len = history_len::State::Fetching(Instant::now()), data.reading.clone(), data.oldest_in_history(), - data.logs_from_store_hist, + data.logs.cover_from(), data.histogram_range.clone(), ); } diff --git a/crates/sensor-tui/src/tui/readings/render/logs.rs b/crates/sensor-tui/src/tui/readings/render/logs.rs index 2c17f02c..47ca36c0 100644 --- a/crates/sensor-tui/src/tui/readings/render/logs.rs +++ b/crates/sensor-tui/src/tui/readings/render/logs.rs @@ -1,3 +1,5 @@ +use jiff::tz::TimeZone; +use jiff::Zoned; use log_store::api::ErrorEvent; use ratatui::layout::{Constraint, Flex, Rect}; use ratatui::style::{Color, Modifier, Style, Stylize}; @@ -48,6 +50,8 @@ pub fn render_table( .map(|ErrorEvent { error, .. }| error.to_string().chars().count() as u16) .max() .unwrap_or_default(); + + let now = Zoned::now(); let rows = logs .into_iter() .rev() @@ -57,16 +61,25 @@ pub fn render_table( 0 => Color::Gray, _ => Color::White, }; - let end = if let Some(timestamp) = end { - format!("{}", timestamp.strftime("%I:%M:%S")) + + let start = start.to_zoned(TimeZone::system()); + let start = if start.day() == now.day() && start.year() == now.year() { + format!("{}", start.strftime("%I:%M:%S")) + } else { + format!("{}", start.strftime("%D %I:%M:%S")) + }; + + let end = if let Some(end) = end { + let end = end.to_zoned(TimeZone::system()); + if end.day() == now.day() && end.year() == now.year() { + format!("{}", end.strftime("%I:%M:%S")) + } else { + format!("{}", end.strftime("%D %I:%M:%S")) + } } else { "ongoing".to_owned() }; - let item = [ - format!("{error}"), - format!("{}", start.strftime("%I:%M:%S")), - end, - ]; + let item = [format!("{error}"), start, end]; item.into_iter() .map(|content| Text::from(content)) .map(|content| Cell::from(content)) @@ -80,8 +93,8 @@ pub fn render_table( rows, [ Constraint::Max(longest_error_msg), - Constraint::Max(10), - Constraint::Max(10), + Constraint::Max(18), + Constraint::Max(18), ], ) .header(header) diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index 14a757e0..0d4d4dea 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -2,6 +2,7 @@ use hdrhistogram::Histogram; use itertools::Itertools; use jiff::Unit; use log_store::api::{self, ErrorEvent, Percentile}; +use logs::FromStore; use protocol::reading; use protocol::reading::tree::{Item, Tree}; use protocol::Reading; @@ -27,9 +28,7 @@ pub struct SensorInfo { pub histogram_range: Option>, pub history_from_store: Vec<(jiff::Timestamp, f32)>, condition: Result<(), Box>, - logs: logs::Logs, - pub logs_from_store: Vec, - pub logs_from_store_hist: Option, + pub logs: logs::Logs, } pub struct ErrorDensity { @@ -154,19 +153,8 @@ impl SensorInfo { } pub fn logs(&self) -> Vec { - let last = self - .logs_from_store - .last() - .map(|ErrorEvent { start, .. }| *start) - .unwrap_or(jiff::Timestamp::from_second(0).unwrap()); - let without_duplicates = self - .logs - .list() - .skip_while(|ErrorEvent { start, .. }| start < &last) - .cloned(); - let mut logs = self.logs_from_store.clone(); - logs.extend(without_duplicates); - logs + self.logs.list() + compile_error!("mark status such as loading more from store") } pub(crate) fn oldest_in_history(&self) -> jiff::Timestamp { @@ -190,15 +178,15 @@ impl SensorInfo { /// encoded with the last byte byte being the leaf's id pub type TreeKey = [u8; 6]; pub struct Readings { - // in the ground there are multiple trees + // In the ground there are multiple trees pub ground: Vec>, pub data: HashMap, } fn add_leaf(text: String, tree: &mut TreeItem<'static, TreeKey>, key: TreeKey) { let new_item = TreeItem::new_leaf(key, text.clone()); - // todo is exists its fine handle that - let _ignore_existing = tree.add_child(new_item); // errors when identifier already exists + // Todo is exists its fine handle that + let _ignore_existing = tree.add_child(new_item); // Errors when identifier already exists let new_child = tree .children() @@ -232,7 +220,7 @@ fn add_node<'a>( ) -> &'a mut TreeItem<'static, TreeKey> { let key = [tomato.branch_id(); 6]; let new_item = TreeItem::new(key, tomato.name(), Vec::new()).unwrap(); - // add just in case it was not there yet + // Add just in case it was not there yet let _ignore_existing = tree.add_child(new_item); let new_child = tree .children() @@ -311,8 +299,6 @@ impl Readings { recent_history: Vec::new(), history_from_store: Vec::new(), - logs_from_store: Vec::new(), - logs_from_store_hist: Option::None, condition: Err(error.clone()), logs, @@ -347,8 +333,6 @@ impl Readings { recent_history: history, history_from_store: Vec::new(), - logs_from_store: Vec::new(), - logs_from_store_hist: Option::None, condition: Ok(()), logs: logs::Logs::new_empty(), @@ -374,8 +358,6 @@ impl Readings { recent_history: Vec::new(), history_from_store: Vec::new(), - logs_from_store: Vec::new(), - logs_from_store_hist: Option::None, condition: Ok(()), logs: logs::Logs::new_empty(), @@ -453,8 +435,10 @@ impl Readings { timestamps.into_iter().zip(data.into_iter()).collect() } Fetchable::Logs { logs, start_at } => { - sensorinfo.logs_from_store = logs; - sensorinfo.logs_from_store_hist = Some(start_at); + sensorinfo.logs.from_store = Some(logs::FromStore { + list: logs, + since: start_at, + }) } Fetchable::Hist { percentiles, range } => { sensorinfo.percentiles_from_store = percentiles; @@ -475,5 +459,3 @@ pub struct ChartParts<'a> { pub reading: reading::Info, pub data: &'a [(f64, f64)], } - - diff --git a/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs b/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs index 110838d0..f3ab0318 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs @@ -1,11 +1,23 @@ use jiff::Unit; use log_store::api::{self, ErrorEvent}; +#[derive(Debug)] +pub(crate) struct FromStore { + pub(crate) list: Vec, + pub(crate) since: jiff::Timestamp, +} + +#[derive(Debug)] +pub(crate) struct Local { + pub(crate) list: Vec, + pub(crate) since: jiff::Timestamp, +} + #[derive(Debug)] pub(crate) struct Logs { current: Option, - /// newest items at the end - history: Vec, + pub local: Local, + pub from_store: Option, } impl Logs { @@ -16,14 +28,22 @@ impl Logs { end: None, error: error.clone(), }), - history: Vec::new(), + local: Local { + list: Vec::new(), + since: jiff::Timestamp::now(), + }, + from_store: None, } } pub(crate) fn new_empty() -> Self { Self { current: None, - history: Vec::new(), + local: Local { + list: Vec::new(), + since: jiff::Timestamp::now(), + }, + from_store: None, } } @@ -33,7 +53,7 @@ impl Logs { return; } - self.history.push(api::ErrorEvent { + self.local.list.push(api::ErrorEvent { start, end: Some(jiff::Timestamp::now()), error, @@ -50,7 +70,7 @@ impl Logs { pub(crate) fn density(&self, buckets: [jiff::Span; N]) -> [f32; N] { let now = jiff::Timestamp::now(); let mut buckets = buckets.map(|bound| (bound, 0.0)); - for ErrorEvent { start, end, .. } in self.history.iter().rev() { + for ErrorEvent { start, end, .. } in self.local.list.iter().rev() { for (bound, count) in &mut buckets { let bound_start = now - *bound; let start = start.max(&bound_start); @@ -65,7 +85,36 @@ impl Logs { buckets.map(|(_, count)| count as f32) } - pub(crate) fn list(&self) -> impl Iterator { - self.history.iter().chain(self.current.iter()) + pub(crate) fn list(&self) -> Vec { + let last = self + .from_store + .as_ref() + .map(|FromStore { list, .. }| list) + .map(|list| list.last()) + .flatten() + .map(|ErrorEvent { start, .. }| *start) + .unwrap_or(jiff::Timestamp::from_second(0).unwrap()); + let without_duplicates = self + .local + .list + .iter() + .skip_while(|ErrorEvent { start, .. }| start < &last) + .cloned(); + let mut logs = self + .from_store + .as_ref() + .map(|FromStore { list, .. }| list) + .cloned() + .unwrap_or(Vec::new()); + logs.extend(without_duplicates); + logs + } + + pub(crate) fn covers_from(&self) -> jiff::Timestamp { + *self + .from_store + .as_ref() + .map(|FromStore { since, .. }| since) + .unwrap_or(&self.local.since) } } From 4e701e427af36f1716a31124df58b7fcea5cdc68 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 13 Sep 2024 15:11:48 +0200 Subject: [PATCH 265/687] fetcher returns errors now, logs show if still loading --- crates/sensor-tui/src/main.rs | 9 +-- crates/sensor-tui/src/populate.rs | 71 ++++++++++--------- crates/sensor-tui/src/tui.rs | 6 +- crates/sensor-tui/src/tui/affectors.rs | 1 + crates/sensor-tui/src/tui/readings.rs | 12 +++- crates/sensor-tui/src/tui/readings/render.rs | 14 ++-- .../src/tui/readings/render/logs.rs | 35 ++++++--- .../src/tui/readings/sensor_info.rs | 5 +- .../src/tui/readings/sensor_info/logs.rs | 14 +++- 9 files changed, 100 insertions(+), 67 deletions(-) diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index a9642a1f..7c963cc7 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -54,6 +54,7 @@ enum Update { controlled_by: String, }, AffectorList(Vec), + PopulateError(color_eyre::Report), } @@ -63,15 +64,15 @@ enum Update { #[command(version = "1.0")] #[command(about = "View sensor values")] struct Cli { - /// server where we can subscribe for sensor data updates + /// Server where we can subscribe for sensor data updates #[arg(short, long, default_value_t = SocketAddr::from(([192,168,1,43], 1235)))] data_server: SocketAddr, - /// server where we can fetch historical sensor data + /// Server where we can fetch historical sensor data #[arg(short='s', long, default_value_t = SocketAddr::from(([192,168,1,43], 1236)))] data_store: SocketAddr, - /// server where we can fetch logs and timing information + /// Server where we can fetch logs and timing information #[arg(short, long, default_value_t = SocketAddr::from(([192,168,1,43], 1237)))] log_store: SocketAddr, } @@ -97,7 +98,7 @@ async fn main() -> Result<()> { thread::spawn(move || tui::run(rx1, tx2, tx3, fetcher)); task::spawn(receive::receive_data(data_server, tx1_clone1)); - thread::spawn(move || populate::tree(data_server, data_store, log_store, tx1_clone2)); + task::spawn(populate::tree(data_server, data_store, log_store, tx1_clone2)); task::spawn(control::watch_and_send(data_server, rx3)); loop { diff --git a/crates/sensor-tui/src/populate.rs b/crates/sensor-tui/src/populate.rs index 20bfe735..08e82cee 100644 --- a/crates/sensor-tui/src/populate.rs +++ b/crates/sensor-tui/src/populate.rs @@ -1,65 +1,66 @@ +use std::future::Future; use std::net::SocketAddr; use std::sync::mpsc; use color_eyre::Result; use data_server::api::subscriber; -use tracing::warn; use crate::{client_name, Update}; -pub fn tree( +pub async fn send_result( + f: impl Future>, + err_text: &'static str, + tx: mpsc::Sender, +) { + match f.await { + Ok(update) => tx.send(update), + Err(e) => tx.send(Update::PopulateError(e.wrap_err(err_text))), + } + .expect("ui should be listening for these updates") +} + +pub async fn tree( data_server_addr: SocketAddr, data_store_addr: SocketAddr, log_store_addr: SocketAddr, tx: mpsc::Sender, ) { - let rt = tokio::runtime::Builder::new_current_thread() - .enable_io() - .enable_time() - .build() - .unwrap(); - - let (res1, res2, res3) = rt.block_on(async { - tokio::join!( - list_from_server(data_server_addr, tx.clone()), - list_from_store(data_store_addr, tx.clone()), - list_from_logs(log_store_addr, tx) + let _ = tokio::join!( + send_result( + list_from_server(data_server_addr), + "Could not get affector list from data-server", + tx.clone() + ), + send_result( + list_from_store(data_store_addr), + "COult not get reading list from data-store", + tx.clone() + ), + send_result( + list_from_logs(log_store_addr), + "Could not get logs and histogram from log-store", + tx ) - }); - - if let Err(e) = res1 { - warn!("Could not populate affector list from data server: {e}") - } - - if let Err(e) = res2 { - warn!("Could not populate readings list from data store: {e}") - } - - if let Err(e) = res3 { - warn!("Could not populate logs and histograms from log store: {e}") - } + ); } -async fn list_from_server(data_server_addr: SocketAddr, tx: mpsc::Sender) -> Result<()> { +async fn list_from_server(data_server_addr: SocketAddr) -> Result { let mut client = subscriber::Client::connect(data_server_addr, client_name()).await?; let list = client.list_affectors().await?; tracing::debug!("affector list: {list:?}"); - tx.send(Update::AffectorList(list)).unwrap(); - Ok(()) + Ok(Update::AffectorList(list)) } -async fn list_from_store(data_store_addr: SocketAddr, tx: mpsc::Sender) -> Result<()> { +async fn list_from_store(data_store_addr: SocketAddr) -> Result { let mut client = data_store::api::Client::connect(data_store_addr, client_name()).await?; let list = client.list_data().await?; tracing::debug!("data list: {list:?}"); - tx.send(Update::ReadingList(list)).unwrap(); - Ok(()) + Ok(Update::ReadingList(list)) } -async fn list_from_logs(log_store_addr: SocketAddr, tx: mpsc::Sender) -> Result<()> { +async fn list_from_logs(log_store_addr: SocketAddr) -> Result { let mut client = log_store::api::Client::connect(log_store_addr, client_name()).await?; let list = client.list_devices().await?; tracing::debug!("log list: {list:?}"); - tx.send(Update::DeviceList(list)).unwrap(); - Ok(()) + Ok(Update::DeviceList(list)) } diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index 88e3eeb6..2d726083 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -100,10 +100,7 @@ impl App { terminal.draw(|frame| { let layout = render(frame, self); match self.active_tab { - ActiveTab::Readings => { - self.readings_tab - .render(frame, layout, &self.theme) - } + ActiveTab::Readings => self.readings_tab.render(frame, layout, &self.theme), ActiveTab::Affectors => self.affectors_tab.render(frame, layout, &self.theme), } })?; @@ -171,6 +168,7 @@ impl App { | Update::ReadingList(_) | Update::SensorError(_) | Update::SensorReading(_) => return Some(update), + Update::PopulateError(e) => self.reports.add(e.wrap_err("Error populating lists")), Update::FetchError(e) => self.reports.add(e.wrap_err("Error fetching")), Update::SubscribeError(e) => self .reports diff --git a/crates/sensor-tui/src/tui/affectors.rs b/crates/sensor-tui/src/tui/affectors.rs index c188ebc8..a4e1c5aa 100644 --- a/crates/sensor-tui/src/tui/affectors.rs +++ b/crates/sensor-tui/src/tui/affectors.rs @@ -95,6 +95,7 @@ impl Tab { | Update::FetchError(_) | Update::SensorReading(_) | Update::DeviceList(_) + | Update::PopulateError(_) | Update::SubscribeError(_) => Some(update), Update::AffectorControlled { affector, diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index e7357e7d..6dda5f4a 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -77,8 +77,14 @@ impl Tab { } }; - let [top, bottom, footer] = - render::layout(frame, layout, ui_state, readings, &chart, &logs); + let [top, bottom, footer] = render::layout( + frame, + layout, + ui_state, + readings, + chart.is_some(), + logs.is_some(), + ); let have_details = details.is_some(); render::readings_and_details(frame, top, ui_state, readings, details); @@ -157,7 +163,7 @@ impl Tab { || *history_len = history_len::State::Fetching(Instant::now()), data.reading.clone(), data.oldest_in_history(), - data.logs.cover_from(), + data.logs.covers_from(), data.histogram_range.clone(), ); } diff --git a/crates/sensor-tui/src/tui/readings/render.rs b/crates/sensor-tui/src/tui/readings/render.rs index 7d0656e8..56dd6624 100644 --- a/crates/sensor-tui/src/tui/readings/render.rs +++ b/crates/sensor-tui/src/tui/readings/render.rs @@ -13,7 +13,7 @@ use tui_tree_widget::Tree; use crate::tui::Theme; use super::{ - sensor_info::{ChartParts, Details, ErrorDensity, Readings}, + sensor_info::{ChartParts, Details, ErrorDensity, LogSource, Readings}, UiState, }; @@ -25,10 +25,10 @@ pub(crate) fn layout( layout: Rect, ui_state: &mut UiState, readings: &Readings, - chart: &Option, - logs: &Option>, + chart: bool, + logs: bool, ) -> [Rect; 3] { - let [list_constraint, graph_constraint] = if chart.is_some() { + let [list_constraint, graph_constraint] = if chart { let tree_height = 2 + ui_state.tree_state.flatten(&readings.ground).len(); let details_height = 9; if (frame.area().height as f32) / 3. > tree_height as f32 { @@ -39,7 +39,7 @@ pub(crate) fn layout( } else { [Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)] } - } else if logs.is_some() { + } else if logs { [Constraint::Percentage(60), Constraint::Percentage(40)] } else { [Constraint::Percentage(100), Constraint::Percentage(0)] @@ -84,7 +84,7 @@ pub fn graph_hist_logs( layout: Rect, app: &mut UiState, percentiles: &[Percentile], - logs: Option>, + logs: Option<(Vec, LogSource)>, chart: Option, theme: &Theme, ) { @@ -94,7 +94,7 @@ pub fn graph_hist_logs( if chart.is_some() { constraints[0] = Constraint::Fill(10); } - if logs.as_ref().is_some_and(|logs| !logs.is_empty()) && app.show_logs { + if logs.as_ref().is_some_and(|(logs, _)| !logs.is_empty()) && app.show_logs { constraints[1] = Constraint::Fill(10); } if !percentiles.is_empty() && app.show_histogram { diff --git a/crates/sensor-tui/src/tui/readings/render/logs.rs b/crates/sensor-tui/src/tui/readings/render/logs.rs index 47ca36c0..2710b0bf 100644 --- a/crates/sensor-tui/src/tui/readings/render/logs.rs +++ b/crates/sensor-tui/src/tui/readings/render/logs.rs @@ -1,29 +1,46 @@ use jiff::tz::TimeZone; use jiff::Zoned; use log_store::api::ErrorEvent; -use ratatui::layout::{Constraint, Flex, Rect}; +use ratatui::layout::{Constraint, Direction, Flex, Layout, Rect}; use ratatui::style::{Color, Modifier, Style, Stylize}; use ratatui::text::Text; use ratatui::widgets::{Cell, HighlightSpacing, Row, Table, TableState}; use ratatui::Frame; +use crate::tui::readings::sensor_info::LogSource; + use super::centered_text; pub fn render( frame: &mut Frame, layout: Rect, table_state: &mut TableState, - logs: Option>, + logs: Option<(Vec, LogSource)>, theme: &super::Theme, ) { - if let Some(logs) = logs { - if logs.is_empty() { - centered_text("Logs are empty", frame, layout, theme) - } else { - render_table(frame, layout, table_state, logs) + match logs { + Some((logs, LogSource::Store)) => { + if logs.is_empty() { + centered_text("All logs are empty", frame, layout, theme) + } else { + render_table(frame, layout, table_state, logs) + } + } + Some((logs, LogSource::Local)) => { + let [status, layout] = Layout::new( + Direction::Vertical, + [Constraint::Max(1), Constraint::Fill(1)], + ) + .areas(layout); + + centered_text("Loading logs from store ..", frame, status, theme); + if logs.is_empty() { + centered_text("Local logs are empty", frame, layout, theme); + } else { + render_table(frame, layout, table_state, logs); + } } - } else { - centered_text("No logs", frame, layout, theme) + None => centered_text("This item can not have logs", frame, layout, theme), } } diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index 0d4d4dea..416f2125 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -2,7 +2,6 @@ use hdrhistogram::Histogram; use itertools::Itertools; use jiff::Unit; use log_store::api::{self, ErrorEvent, Percentile}; -use logs::FromStore; use protocol::reading; use protocol::reading::tree::{Item, Tree}; use protocol::Reading; @@ -15,6 +14,7 @@ use tui_tree_widget::TreeItem; use crate::Fetchable; mod logs; +pub(crate) use logs::LogSource; #[derive(Debug)] pub struct SensorInfo { @@ -152,9 +152,8 @@ impl SensorInfo { }) } - pub fn logs(&self) -> Vec { + pub fn logs(&self) -> (Vec, logs::LogSource) { self.logs.list() - compile_error!("mark status such as loading more from store") } pub(crate) fn oldest_in_history(&self) -> jiff::Timestamp { diff --git a/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs b/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs index f3ab0318..969ba0f9 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs @@ -85,7 +85,7 @@ impl Logs { buckets.map(|(_, count)| count as f32) } - pub(crate) fn list(&self) -> Vec { + pub(crate) fn list(&self) -> (Vec, LogSource) { let last = self .from_store .as_ref() @@ -107,7 +107,12 @@ impl Logs { .cloned() .unwrap_or(Vec::new()); logs.extend(without_duplicates); - logs + + if self.from_store.is_some() { + (logs, LogSource::Store) + } else { + (logs, LogSource::Local) + } } pub(crate) fn covers_from(&self) -> jiff::Timestamp { @@ -118,3 +123,8 @@ impl Logs { .unwrap_or(&self.local.since) } } + +pub enum LogSource { + Local, + Store, +} From c5d124b783768a5354b1684d44145b09b244b936 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 13 Sep 2024 16:01:10 +0200 Subject: [PATCH 266/687] tui: fix chart not displaying until reading update arrives --- crates/sensor-tui/src/fetch.rs | 4 +++- crates/sensor-tui/src/tui/readings.rs | 2 +- .../src/tui/readings/sensor_info.rs | 21 ++++++++++--------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index 8d4a5a4f..eaf73b58 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -393,7 +393,9 @@ async fn get_data( .get_data(*range.start(), *range.end(), reading, 300) .await { - Ok(Data { time, values }) => GetResult::Ok((time, values)), + Ok(Data { time, values }) => { + GetResult::Ok((time, values)) + } Err(Error::Request(GetDataError::NotFound)) | Err(Error::Request(GetDataError::EmptyFile)) | Err(Error::Request(GetDataError::StartAfterData)) diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index 6dda5f4a..ba1447a2 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -66,7 +66,7 @@ impl Tab { if let Some(data) = data { ( - data.chart(plot_buf), + data.chart(plot_buf, ui_state.history_length.dur), data.percentiles(), Some(data.details()), Some(data.logs()), diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index 416f2125..ba456e9e 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -9,6 +9,7 @@ use protocol::{Device, Error}; use std::collections::HashMap; use std::ops::RangeInclusive; +use std::time::Duration; use tui_tree_widget::TreeItem; use crate::Fetchable; @@ -114,21 +115,21 @@ impl SensorInfo { .collect_vec() } - pub fn chart<'a>(&mut self, plot_buf: &'a mut Vec<(f64, f64)>) -> Option> { - let reference = self - .history_from_store - .first() - .map(|(t, _)| t) - .or_else(|| self.recent_history.first().map(|(t, _)| t))?; + pub fn chart<'a>( + &mut self, + plot_buf: &'a mut Vec<(f64, f64)>, + history_len: Duration, + ) -> Option> { + let reference = jiff::Timestamp::now() - history_len; let first_recent = self .recent_history .first() .map(|(t, _)| t) .cloned() - .unwrap_or(jiff::Timestamp::default()); - plot_buf.clear(); + .unwrap_or(jiff::Timestamp::MAX); + plot_buf.clear(); for xy in self .history_from_store .iter() @@ -136,7 +137,7 @@ impl SensorInfo { .chain(self.recent_history.iter()) .map(|(x, y)| { ( - (*x - *reference) + (*x - reference) .total(jiff::Unit::Second) .expect("unit is not a calander unit"), *y as f64, @@ -431,7 +432,7 @@ impl Readings { match fetched { Fetchable::Data { timestamps, data } => { sensorinfo.history_from_store = - timestamps.into_iter().zip(data.into_iter()).collect() + timestamps.into_iter().zip(data.into_iter()).collect(); } Fetchable::Logs { logs, start_at } => { sensorinfo.logs.from_store = Some(logs::FromStore { From de4178f0850e9c2a3de40378e761e17ce0b6f471 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 13 Sep 2024 18:04:16 +0200 Subject: [PATCH 267/687] tui: affector trigger key + fmt chart time as hh:mm sometimes --- crates/sensor-tui/src/control.rs | 1 + .../src/tui/affectors/handle_key.rs | 9 ++++++++ crates/sensor-tui/src/tui/affectors/render.rs | 2 +- .../src/tui/readings/render/chart/labels.rs | 22 +++++++++++++++++-- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/crates/sensor-tui/src/control.rs b/crates/sensor-tui/src/control.rs index d15174a8..baf4b0da 100644 --- a/crates/sensor-tui/src/control.rs +++ b/crates/sensor-tui/src/control.rs @@ -20,6 +20,7 @@ pub(crate) async fn watch_and_send(data_server: SocketAddr, mut rx: mpsc::Receiv }, }; + tracing::debug!("got affect order: {order:?}"); if let Some(mut client) = connected_client.take() { if let Err(e) = client.actuate_affector(order).await { error!("Could not actuate affector: {e:?}"); diff --git a/crates/sensor-tui/src/tui/affectors/handle_key.rs b/crates/sensor-tui/src/tui/affectors/handle_key.rs index 21782762..393d3e60 100644 --- a/crates/sensor-tui/src/tui/affectors/handle_key.rs +++ b/crates/sensor-tui/src/tui/affectors/handle_key.rs @@ -15,9 +15,11 @@ pub(crate) fn handle( let control = &mut controls[state.selected_control].value; match key.code { + KeyCode::Char('t') => handle_trigger(control), KeyCode::Char('f') => handle_increase(control), KeyCode::Char('b') => handle_decrease(control), + // Otherwise return since we have not changed the affector KeyCode::Char('d') => { state.selected_control = (state.selected_control + 1).min(controls.len() - 1); return None; @@ -39,6 +41,13 @@ pub(crate) fn handle( None } +fn handle_trigger(control: &mut C) { + match control { + C::Trigger => (), + C::SetNum { .. } => (), + } +} + fn handle_increase(control: &mut C) { match control { C::Trigger => (), diff --git a/crates/sensor-tui/src/tui/affectors/render.rs b/crates/sensor-tui/src/tui/affectors/render.rs index 122c6a4f..a850cec7 100644 --- a/crates/sensor-tui/src/tui/affectors/render.rs +++ b/crates/sensor-tui/src/tui/affectors/render.rs @@ -138,7 +138,7 @@ pub(crate) fn footer( }) => { footer.push("u/d: select prev/next"); match affector.controls()[*selected_control].value { - C::Trigger => footer.push("enter: trigger affector"), + C::Trigger => footer.push("t: trigger affector"), C::SetNum { .. } => footer.push("f/b increase/decrease"), } } diff --git a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs index f3aa2a24..dce6a233 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs @@ -1,3 +1,5 @@ +use std::time::Duration; + use protocol::reading; use ratatui::layout::Rect; use ratatui::text::Span; @@ -17,10 +19,10 @@ pub fn labels<'a>( let y_label_spacing = 10; let info = &chart.reading; - // characters are about twice as high as wide + // Characters are about twice as high as wide let x = evenly_spaced_labels(layout.width / y_label_spacing / 2, info, x_bounds) .rev() - .map(crate::time::format::fmt_seconds) + .map(fmt_seconds) .map(Into::into) .collect(); let y = evenly_spaced_labels(layout.height / y_label_spacing, info, y_bounds) @@ -30,6 +32,22 @@ pub fn labels<'a>( (x, y) } +fn fmt_seconds(secs: f64) -> String { + if secs == 0.0 { + "now".to_string() + } else if secs > 2. * 60. * 60. && secs < 24. * 60. * 60. { + fmt_hh_mm(secs) + } else { + "-".to_string() + &crate::time::format::fmt_seconds(secs) + } +} + +fn fmt_hh_mm(secs: f64) -> String { + let now = jiff::Timestamp::now(); + let label = now - Duration::from_secs_f64(secs); + label.strftime("%H:%M").to_string() +} + fn evenly_spaced_labels( max_labels: u16, reading: &reading::Info, From 9a4753e2e4a0da14f37532d20a4a0630aea4b162 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 13 Sep 2024 18:20:36 +0200 Subject: [PATCH 268/687] tui fix: labels now in local tz --- crates/sensor-tui/src/tui/readings/render/chart/labels.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs index dce6a233..2bcb3944 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs @@ -1,5 +1,6 @@ use std::time::Duration; +use jiff::tz::TimeZone; use protocol::reading; use ratatui::layout::Rect; use ratatui::text::Span; @@ -45,6 +46,7 @@ fn fmt_seconds(secs: f64) -> String { fn fmt_hh_mm(secs: f64) -> String { let now = jiff::Timestamp::now(); let label = now - Duration::from_secs_f64(secs); + let label = label.to_zoned(TimeZone::system()); label.strftime("%H:%M").to_string() } From 400f0b276757cc00f2f30f70d7f7b3be515c188a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 13 Sep 2024 18:21:44 +0200 Subject: [PATCH 269/687] sensors: drivers can start affector. Affector orders are forwarded from network to sensor loops --- sensor-nodes/bed-sensors/.cargo/config.toml | 2 +- sensor-nodes/bed-sensors/Cargo.lock | 4 +- sensor-nodes/bed-sensors/src/main.rs | 5 +- sensor-nodes/bed-sensors/src/network.rs | 41 +++++--- sensor-nodes/bed-sensors/src/rgb_led.rs | 1 - sensor-nodes/bed-sensors/src/sensors.rs | 13 ++- sensor-nodes/bed-sensors/src/sensors/retry.rs | 13 ++- .../src/sensors/retry/reinit_on_error.rs | 1 + .../src/sensors/retry/retry_init.rs | 13 +++ sensor-nodes/bed-sensors/src/sensors/slow.rs | 96 +++++++++++++++---- 10 files changed, 146 insertions(+), 43 deletions(-) diff --git a/sensor-nodes/bed-sensors/.cargo/config.toml b/sensor-nodes/bed-sensors/.cargo/config.toml index f5a36213..d2fde87a 100644 --- a/sensor-nodes/bed-sensors/.cargo/config.toml +++ b/sensor-nodes/bed-sensors/.cargo/config.toml @@ -10,7 +10,7 @@ target = "thumbv7em-none-eabihf" [env] DEFMT_LOG = "debug,sps30_async=info,bosch_bme680=info" -EMBASSY_EXECUTOR_TASK_ARENA_SIZE="10000" +EMBASSY_EXECUTOR_TASK_ARENA_SIZE="10900" # [unstable] # build-std = ["core"] diff --git a/sensor-nodes/bed-sensors/Cargo.lock b/sensor-nodes/bed-sensors/Cargo.lock index b8b86477..06c0b13b 100644 --- a/sensor-nodes/bed-sensors/Cargo.lock +++ b/sensor-nodes/bed-sensors/Cargo.lock @@ -1187,9 +1187,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "vcell" diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index 926f079c..9e778e81 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -23,6 +23,7 @@ use embedded_hal_bus::spi::ExclusiveDevice; use futures::pin_mut; use heapless::Vec; use sensors::fast::ButtonInputs; +use sensors::slow; use static_cell::StaticCell; use defmt::{error, trace, unwrap}; @@ -212,12 +213,14 @@ async fn main(spawner: Spawner) { let (mut led_controller, led_handle) = rgb_led::controller_and_handle(p.TIM1, p.PB14, p.PB13, p.PB15, &comms); + let driver_orderers = slow::DriverOrderers::new(); let publish = Queues::new(); - let handle_network = network::handle(stack, &publish, led_handle.clone()); + let handle_network = network::handle(stack, &publish, led_handle.clone(), &driver_orderers); pin_mut!(handle_network); let init_then_measure = sensors::init_then_measure( &publish, + &driver_orderers, led_handle, i2c_1, i2c_2, diff --git a/sensor-nodes/bed-sensors/src/network.rs b/sensor-nodes/bed-sensors/src/network.rs index c2d7104e..77365561 100644 --- a/sensor-nodes/bed-sensors/src/network.rs +++ b/sensor-nodes/bed-sensors/src/network.rs @@ -10,6 +10,7 @@ use protocol::{affector, Affector, ErrorReport, SensorMessage}; use crate::channel::{PriorityValue, QueueItem, Queues}; use crate::rgb_led::LedHandle; +use crate::sensors::slow; type SensMsg = SensorMessage<10>; @@ -67,7 +68,12 @@ const fn max(a: usize, b: usize) -> usize { [a, b][(a < b) as usize] } -pub async fn handle(stack: &Stack, publish: &Queues, led: LedHandle<'_>) { +pub async fn handle( + stack: &Stack, + publish: &Queues, + led: LedHandle<'_>, + driver_orderers: &slow::DriverOrderers, +) { let mut rx_buffer = [0; 1024]; let mut tx_buffer = [0; max(SensMsg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE) * 2]; @@ -82,7 +88,7 @@ pub async fn handle(stack: &Stack, publish: &Queues, led: LedHandle debug!("socket state: {:?}", socket.state()); if let Err(e) = socket.connect((host_addr, host_port)).await { warn!("connect error: {}", e); - Timer::after_secs(1).await; + Timer::after_secs(5).await; continue; } info!("(re-)connected"); @@ -90,15 +96,18 @@ pub async fn handle(stack: &Stack, publish: &Queues, led: LedHandle publish.clear().await; let (reader, writer) = socket.split(); - match select(send_messages(writer, publish), receive_orders(reader, &led)).await { + match select( + send_messages(writer, publish), + receive_orders(reader, &led, &driver_orderers), + ) + .await + { select::Either::First(e) => warn!("Error while sending messages: {}", e), select::Either::Second(e) => warn!("Error receiving orders: {}", e), }; // Or the socket will hang for a while waiting to close this makes sure // we can reconnect instantly socket.abort(); - // Do not trigger data-server rate-limit - Timer::after(Duration::from_secs(2)).await; } } @@ -133,7 +142,7 @@ async fn send_messages(mut tcp: TcpWriter<'_>, publish: &Queues) -> embassy_net: affector::ListMessage::<5>::ENCODED_SIZE, )]; let encoded_len = affector_list().encode_slice(&mut buf[1..]).len(); - buf[0] = protocol::Msg::<0>::AFFECTOR_LIST; + buf[0] = protocol::Msg::<5>::AFFECTOR_LIST; let to_send = &buf[..=encoded_len]; if let Err(e) = tcp.write_all(to_send).await { return e; @@ -153,7 +162,11 @@ enum ReadError { TcpError(embassy_net::tcp::Error), } -async fn receive_orders(mut tcp: TcpReader<'_>, led: &LedHandle<'_>) -> ReadError { +async fn receive_orders( + mut tcp: TcpReader<'_>, + led: &LedHandle<'_>, + driver_orderers: &slow::DriverOrderers, +) -> ReadError { defmt::debug!("ready to receive orders"); let mut decoder = affector::Decoder::default(); let mut buf = [0u8; 100]; @@ -171,17 +184,21 @@ async fn receive_orders(mut tcp: TcpReader<'_>, led: &LedHandle<'_>) -> ReadErro #[allow(irrefutable_let_patterns)] // Will change in the future let Affector::LargeBedroom(large_bedroom::Affector::Bed(affector)) = item else { - defmt::warn!("Got affector for other node"); + defmt::error!("Got affector for other node"); continue; }; + defmt::info!("got affector order: {:?}", affector); match affector { - bed::Affector::MhzZeroPointCalib - | bed::Affector::Nau7802LeftCalib - | bed::Affector::Nau7802RightCalib - | bed::Affector::Sps30FanClean => { + bed::Affector::Nau7802LeftCalib | bed::Affector::Nau7802RightCalib => { defmt::warn!("unimplemented affector: {:?}", affector) } + bed::Affector::MhzZeroPointCalib => { + driver_orderers.mhz.send(()).await; + } + bed::Affector::Sps30FanClean => { + driver_orderers.sps.send(()).await; + } bed::Affector::RgbLed { red, green, blue } => { led.set_color( red as f32 / u8::MAX as f32, diff --git a/sensor-nodes/bed-sensors/src/rgb_led.rs b/sensor-nodes/bed-sensors/src/rgb_led.rs index d7e5e7c0..5361186e 100644 --- a/sensor-nodes/bed-sensors/src/rgb_led.rs +++ b/sensor-nodes/bed-sensors/src/rgb_led.rs @@ -72,7 +72,6 @@ impl RgbLed { let r = self.r / sum; let b = self.b / sum; let g = self.g / sum; - defmt::debug!("bri: {}, r: {}, g: {}, b: {}", bri, r, b, g); self.set_red(bri * r); self.set_blue(bri * b); self.set_green(bri * g); diff --git a/sensor-nodes/bed-sensors/src/sensors.rs b/sensor-nodes/bed-sensors/src/sensors.rs index 5834c795..693eaeb2 100644 --- a/sensor-nodes/bed-sensors/src/sensors.rs +++ b/sensor-nodes/bed-sensors/src/sensors.rs @@ -44,11 +44,12 @@ pub mod concrete_types { pub type ConcreteRx<'a> = RingBufferedUartRx<'a>; } -const SPS30_UART_BUF_SIZE: usize = 100; +const SPS30_UART_BUF_SIZE: usize = 300; const SPS30_DRIVER_BUF_SIZE: usize = 2 * SPS30_UART_BUF_SIZE; pub async fn init_then_measure( publish: &Queues, + orderers: &slow::DriverOrderers, rgb_led: rgb_led::LedHandle<'_>, i2c_1: Mutex>, i2c_2: Mutex>, @@ -76,7 +77,13 @@ pub async fn init_then_measure( let sps30 = Sps30Driver::init(tx, rx); let sensors_fast = fast::read(max44009, nau_right, nau_left, buttons, publish, rgb_led); - let sensors_slow = slow::read(sht, bme, mhz, sps30, publish); + let drivers = slow::Drivers { + sht, + bme, + mhz, + sps: sps30, + }; + let sensors_slow = slow::read(drivers, orderers, publish); join::join(sensors_fast, sensors_slow).await; defmt::unreachable!(); @@ -86,6 +93,7 @@ use concrete_types::ConcreteRx as Rx; use concrete_types::ConcreteTx as Tx; impl<'a> Driver for MHZ, Rx<'a>> { type Measurement = mhzx::Measurement; + type Affector = (); #[inline(always)] async fn try_measure(&mut self) -> Result { @@ -103,6 +111,7 @@ impl<'a> Driver for MHZ, Rx<'a>> { impl<'a> Driver for Sps30, Rx<'a>, Delay> { type Measurement = sps30_async::Measurement; + type Affector = (); #[inline(always)] async fn try_measure(&mut self) -> Result { diff --git a/sensor-nodes/bed-sensors/src/sensors/retry.rs b/sensor-nodes/bed-sensors/src/sensors/retry.rs index 09b73eb5..6ad85fd1 100644 --- a/sensor-nodes/bed-sensors/src/sensors/retry.rs +++ b/sensor-nodes/bed-sensors/src/sensors/retry.rs @@ -74,7 +74,7 @@ impl<'a> ReInitableDriver for Max44009> { async fn init(parts: Self::Parts) -> Result { let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); - // wrap these two into something returning Ok or Err + // Wrap these two into something returning Ok or Err // then make it a generic arg, maybe Driverfactory::init let mut driver = Max44009::new(shared_i2c, SlaveAddr::default()); driver @@ -94,7 +94,7 @@ impl<'a> ReInitableDriver for Nau7802, Delay> { async fn init(parts: Self::Parts) -> Result { let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); - // wrap these two into something returning Ok or Err + // Wrap these two into something returning Ok or Err // then make it a generic arg, maybe Driverfactory::init let driver = Nau7802::new(shared_i2c, Delay) .await @@ -113,7 +113,7 @@ impl<'a> ReInitableDriver for Nau7802, Delay> { async fn init(parts: Self::Parts) -> Result { let shared_i2c = parts; - // wrap these two into something returning Ok or Err + // Wrap these two into something returning Ok or Err // then make it a generic arg, maybe Driverfactory::init let driver = Nau7802::new(shared_i2c, Delay) .await @@ -126,7 +126,7 @@ impl<'a> ReInitableDriver for Nau7802, Delay> { } } -/// a driver that can be re-initialized from copyable parts +/// A driver that can be re-initialized from copy-able parts pub trait ReInitableDriver: Sized { type Parts: Clone; type Measurement; @@ -137,6 +137,11 @@ pub trait ReInitableDriver: Sized { pub trait Driver { type Measurement; + type Affector; async fn try_measure(&mut self) -> Result; + /// For example calibrate, run sensor cleaning etc + async fn affect(&mut self, _: Self::Affector) -> Result<(), crate::error_cache::Error> { + Ok(()) + } fn device(&self) -> protocol::large_bedroom::bed::Device; } diff --git a/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs b/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs index 831765a1..2f638603 100644 --- a/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs +++ b/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs @@ -33,6 +33,7 @@ where impl super::Driver for ReInitOnErrorDriver { type Measurement = D::Measurement; + type Affector = (); #[inline(always)] async fn try_measure(&mut self) -> Result { diff --git a/sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs b/sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs index 86592990..d377b2fa 100644 --- a/sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs +++ b/sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs @@ -53,11 +53,24 @@ impl<'a> Sps30Driver<'a> { impl<'a> Driver for Sps30Driver<'a> { type Measurement = sps30_async::Measurement; + type Affector = (); async fn try_measure(&mut self) -> Result { self.measure().await } + async fn affect(&mut self, _: Self::Affector) -> Result<(), crate::error_cache::Error> { + self.driver + .start_fan_cleaning() + .await + .map_err(SensorError::Sps30) + .map_err(Error::Running)?; + // Fan cleaning takes 10 seconds, make sure its done before + // allowing the next reading + embassy_time::Timer::after(embassy_time::Duration::from_secs(11)).await; + Ok(()) + } + fn device(&self) -> protocol::large_bedroom::bed::Device { protocol::large_bedroom::bed::Device::Sps30 } diff --git a/sensor-nodes/bed-sensors/src/sensors/slow.rs b/sensor-nodes/bed-sensors/src/sensors/slow.rs index 73675422..428262f3 100644 --- a/sensor-nodes/bed-sensors/src/sensors/slow.rs +++ b/sensor-nodes/bed-sensors/src/sensors/slow.rs @@ -1,6 +1,8 @@ use defmt::unwrap; use embassy_futures::join::join5; +use embassy_futures::select; use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::channel::Channel; use embassy_time::Timer; use embassy_time::{with_timeout, Duration}; @@ -23,20 +25,36 @@ type Signal = embassy_sync::signal::Signal; /// Measure when signal is received or control the device's /// affector when it is ordered #[inline(always)] -async fn measure_and_control(mut driver: D, send: F, signal: &Signal) -where +async fn measure_and_control( + mut driver: D, + order: &Channel, + send: F, + signal: &Signal, +) where D: Driver, F: Fn(Result) -> (), { let timeout = Duration::from_secs(15); loop { - signal.wait().await; - let try_measure = Driver::try_measure(&mut driver); - let res = match with_timeout(timeout, try_measure).await { - Ok(res) => res, - Err(_) => Err(Error::Timeout(driver.device())), - }; - send(res); + match select::select(signal.wait(), order.receive()).await { + select::Either::First(_) => { + let try_measure = Driver::try_measure(&mut driver); + let res = match with_timeout(timeout, try_measure).await { + Ok(res) => res, + Err(_) => Err(Error::Timeout(driver.device())), + }; + send(res); + } + select::Either::Second(order) => { + let affect = Driver::affect(&mut driver, order); + let res = match with_timeout(timeout, affect).await { + Ok(Ok(_)) => continue, + Ok(Err(e)) => Err(e), + Err(_) => Err(Error::Timeout(driver.device())), + }; + send(res); + } + } } } @@ -49,22 +67,60 @@ async fn order_measurements_every_period(signals: &[Signal]) { } } +pub(crate) struct Drivers<'a> { + pub sht: Sht31Driver<'a>, + pub bme: Bme680Driver<'a>, + pub mhz: MHZ, Rx<'a>>, + pub sps: Sps30Driver<'a>, +} + +pub(crate) struct DriverOrderers { + pub sht: Channel, + pub bme: Channel, + pub mhz: Channel, + pub sps: Channel, +} +impl DriverOrderers { + pub(crate) fn new() -> Self { + Self { + sht: Channel::new(), + bme: Channel::new(), + mhz: Channel::new(), + sps: Channel::new(), + } + } +} + #[inline(always)] -pub async fn read( - sht: Sht31Driver<'_>, - bme: Bme680Driver<'_>, - mhz: MHZ, Rx<'_>>, - sps: Sps30Driver<'_>, - publish: &'_ Queues, -) { +pub async fn read(drivers: Drivers<'_>, orderers: &DriverOrderers, publish: &'_ Queues) { let signals = [const { Signal::new() }; 4]; join5( order_measurements_every_period(&signals), - measure_and_control(sht, |res| publish_sht_result(res, &publish), &signals[0]), - measure_and_control(bme, |res| publish_bme_result(res, &publish), &signals[1]), - measure_and_control(mhz, |res| publish_mhz_result(res, &publish), &signals[2]), - measure_and_control(sps, |res| publish_sps_result(res, &publish), &signals[3]), + measure_and_control( + drivers.sht, + &orderers.sht, + |res| publish_sht_result(res, &publish), + &signals[0], + ), + measure_and_control( + drivers.bme, + &orderers.bme, + |res| publish_bme_result(res, &publish), + &signals[1], + ), + measure_and_control( + drivers.mhz, + &orderers.mhz, + |res| publish_mhz_result(res, &publish), + &signals[2], + ), + measure_and_control( + drivers.sps, + &orderers.sps, + |res| publish_sps_result(res, &publish), + &signals[3], + ), ) .await; } From bc3a486c66af03f67c51e181451c3652de386fca Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 14 Sep 2024 11:34:23 +0200 Subject: [PATCH 270/687] imports/lints --- crates/data-server/src/server/affector.rs | 3 ++- crates/data-server/src/server/data_source.rs | 2 +- crates/rpc/src/server.rs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/data-server/src/server/affector.rs b/crates/data-server/src/server/affector.rs index d1404c39..050cfa1a 100644 --- a/crates/data-server/src/server/affector.rs +++ b/crates/data-server/src/server/affector.rs @@ -58,10 +58,11 @@ impl Registar { pub(crate) fn remove(&self, key: DefaultKey) { let mut this = self.0.lock().expect("nothing should panic"); - let _ = this.remove(key); // could have been removed by register + let _ = this.remove(key); // Could have been removed by register } pub(crate) fn activate(&self, order: Affector) -> Result<(), Offline> { + tracing::info!("client is trying to activate: {order:?}"); let mut this = self.0.lock().expect("nothing should panic"); for possible_controller in this.iter_mut().map(|(_, reg)| reg).filter(|reg| { reg.controls diff --git a/crates/data-server/src/server/data_source.rs b/crates/data-server/src/server/data_source.rs index 1fac36c9..e3ffda35 100644 --- a/crates/data-server/src/server/data_source.rs +++ b/crates/data-server/src/server/data_source.rs @@ -16,7 +16,7 @@ use tokio::net::TcpStream; use tokio::sync::mpsc::Sender; use super::Event; -use tracing::{debug, error, info, instrument, warn}; +use tracing::{error, info, instrument, warn}; use super::affector::{control_affectors, Registar}; diff --git a/crates/rpc/src/server.rs b/crates/rpc/src/server.rs index 38b0ecc5..cfdb2b0e 100644 --- a/crates/rpc/src/server.rs +++ b/crates/rpc/src/server.rs @@ -17,7 +17,7 @@ use tokio_serde::formats::Bincode; use tokio_util::codec::{Framed, LengthDelimitedCodec}; use ratelimited_logger::{self as rlog, RateLimitedLogger}; -use tracing::{debug, error, info, instrument}; +use tracing::{debug, error, instrument}; type Conn = tokio_serde::Framed< Framed, From 017c7a8a30c93abc431da7ec7b3a4942b5f3e3fc Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 14 Sep 2024 11:42:11 +0200 Subject: [PATCH 271/687] tui: fix am/pm -> 24h clock in log screen --- crates/sensor-tui/src/tui/readings/render/logs.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/sensor-tui/src/tui/readings/render/logs.rs b/crates/sensor-tui/src/tui/readings/render/logs.rs index 2710b0bf..8e2fe98f 100644 --- a/crates/sensor-tui/src/tui/readings/render/logs.rs +++ b/crates/sensor-tui/src/tui/readings/render/logs.rs @@ -81,17 +81,17 @@ pub fn render_table( let start = start.to_zoned(TimeZone::system()); let start = if start.day() == now.day() && start.year() == now.year() { - format!("{}", start.strftime("%I:%M:%S")) + format!("{}", start.strftime("%H:%M:%S")) } else { - format!("{}", start.strftime("%D %I:%M:%S")) + format!("{}", start.strftime("%D %H:%M:%S")) }; let end = if let Some(end) = end { let end = end.to_zoned(TimeZone::system()); if end.day() == now.day() && end.year() == now.year() { - format!("{}", end.strftime("%I:%M:%S")) + format!("{}", end.strftime("%H:%M:%S")) } else { - format!("{}", end.strftime("%D %I:%M:%S")) + format!("{}", end.strftime("%D %H:%M:%S")) } } else { "ongoing".to_owned() From f25d3a43d28a5b49a069996099eadd50f9918c72 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 16 Sep 2024 01:57:59 +0200 Subject: [PATCH 272/687] sensor: fix sps30 readings + try long sleep before reconnect --- sensor-nodes/bed-sensors/src/network.rs | 1 + sensor-nodes/bed-sensors/src/sensors/slow.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sensor-nodes/bed-sensors/src/network.rs b/sensor-nodes/bed-sensors/src/network.rs index 77365561..947ddd78 100644 --- a/sensor-nodes/bed-sensors/src/network.rs +++ b/sensor-nodes/bed-sensors/src/network.rs @@ -108,6 +108,7 @@ pub async fn handle( // Or the socket will hang for a while waiting to close this makes sure // we can reconnect instantly socket.abort(); + Timer::after_secs(60).await; // Experiment: does this help? } } diff --git a/sensor-nodes/bed-sensors/src/sensors/slow.rs b/sensor-nodes/bed-sensors/src/sensors/slow.rs index 428262f3..a3661401 100644 --- a/sensor-nodes/bed-sensors/src/sensors/slow.rs +++ b/sensor-nodes/bed-sensors/src/sensors/slow.rs @@ -132,19 +132,19 @@ fn publish_sps_result(sps_res: Result, publish: &Queu mass_pm2_5, mass_pm4_0, mass_pm10, + number_pm0_5, number_pm1_0, number_pm2_5, number_pm4_0, number_pm10, typical_particle_size, .. - // mass_pm0_5, }) => { publish.send_p0(Reading::MassPm1_0(mass_pm1_0)); publish.send_p0(Reading::MassPm2_5(mass_pm2_5)); publish.send_p0(Reading::MassPm4_0(mass_pm4_0)); publish.send_p0(Reading::MassPm10(mass_pm10)); - // publish.send_p0(Reading::MassPm0_5(mass_pm0_5)); + publish.send_p0(Reading::NumberPm0_5(number_pm0_5)); publish.send_p0(Reading::NumberPm1_0(number_pm1_0)); publish.send_p0(Reading::NumberPm2_5(number_pm2_5)); publish.send_p0(Reading::NumberPm4_0(number_pm4_0)); From 3c3b4adc2a0153d241f7cd1a793cb875bd21e09b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 17 Sep 2024 16:15:48 +0200 Subject: [PATCH 273/687] tui: unify chart and log time formatting, improve format --- crates/sensor-tui/src/fetch.rs | 21 ++++--- crates/sensor-tui/src/time/format.rs | 12 ++-- .../format/progressively_more_specified.rs | 52 ++++++++++++++++ .../src/tui/readings/history_len.rs | 4 +- crates/sensor-tui/src/tui/readings/render.rs | 14 +++-- .../src/tui/readings/render/chart/labels.rs | 28 ++++----- .../src/tui/readings/render/logs.rs | 59 +++++++++++++++---- .../src/tui/readings/sensor_info.rs | 5 +- .../src/tui/readings/sensor_info/logs.rs | 33 +++++++++-- crates/sensor-tui/src/tui/reports.rs | 2 +- 10 files changed, 175 insertions(+), 55 deletions(-) create mode 100644 crates/sensor-tui/src/time/format/progressively_more_specified.rs diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index eaf73b58..3ef45962 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -141,7 +141,7 @@ impl Fetch { return false; // No need for update } - // is there an ongoing request that will fix this? + // Is there an ongoing request that will fix this? !self .recently_issued .iter() @@ -200,7 +200,7 @@ impl Fetch { self.tx.blocking_send(req.clone()).unwrap(); self.recently_issued.push_front(req); // Might get out of sync with request handler, that is okay - // false positives in self.recently_issued are allowed. They only + // false positives in `self.recently_issued` are allowed. They only // delay an update by a single frame. if self.recently_issued.len() > MAX_IN_FLIGHT_REQUESTS { self.recently_issued.pop_back(); @@ -243,8 +243,9 @@ pub(crate) async fn handle_requests( } Request::Logs(Logs { reading, range }) => { let reading_clone = reading.clone(); + let range_clone = range.clone(); tokio::spawn(get_retry_then_wrap_send( - move || get_logs(log_store, reading.clone().clone()), + move || get_logs(log_store, reading.clone(), range.clone()), log_store_queue.clone(), "Could not fetch logs", move |res| match res { @@ -252,7 +253,7 @@ pub(crate) async fn handle_requests( reading: reading_clone, thing: Fetchable::Logs { logs, - start_at: *range.start(), + start_at: *range_clone.start(), }, }, Err(err) => Update::FetchError(err), @@ -393,9 +394,7 @@ async fn get_data( .get_data(*range.start(), *range.end(), reading, 300) .await { - Ok(Data { time, values }) => { - GetResult::Ok((time, values)) - } + Ok(Data { time, values }) => GetResult::Ok((time, values)), Err(Error::Request(GetDataError::NotFound)) | Err(Error::Request(GetDataError::EmptyFile)) | Err(Error::Request(GetDataError::StartAfterData)) @@ -409,7 +408,11 @@ async fn get_data( } } -async fn get_logs(log_store: SocketAddr, reading: Reading) -> GetResult> { +async fn get_logs( + log_store: SocketAddr, + reading: Reading, + range: RangeInclusive, +) -> GetResult> { use log_store::api::client::{Client, ConnectError}; let mut api = match Client::connect(log_store, client_name()).await { @@ -420,7 +423,7 @@ async fn get_logs(log_store: SocketAddr, reading: Reading) -> GetResult String { +pub fn duration(secs: f64) -> String { #[rustfmt::skip] let mut options = [ - // next is purposefully set wrong, we set it in a loop below + // Next is purposefully set wrong, we set it in a loop below FmtOption{unit: "s", factor: 1, next: 0}, FmtOption{unit: "m", factor: 60, next: 0}, FmtOption{unit: "h", factor: 60 * 60, next: 0}, @@ -57,7 +58,6 @@ pub fn fmt_seconds(secs: f64) -> String { unreachable!() } - #[cfg(test)] mod tests { use super::*; @@ -75,7 +75,7 @@ mod tests { ]; for (input, correct_output) in cases { - assert_eq!(fmt_seconds(input as f64), correct_output); + assert_eq!(duration(input as f64), correct_output); } } } diff --git a/crates/sensor-tui/src/time/format/progressively_more_specified.rs b/crates/sensor-tui/src/time/format/progressively_more_specified.rs new file mode 100644 index 00000000..ae4b15fa --- /dev/null +++ b/crates/sensor-tui/src/time/format/progressively_more_specified.rs @@ -0,0 +1,52 @@ +use std::time::Duration; + +use super::duration; + +pub(crate) enum FmtScale { + RelativeDuration, + HourMinute, + DayHour, + MonthDayHour, + YearMonthDayHour, +} + +impl FmtScale { + pub fn optimal_for(t: jiff::Timestamp, elapsed: Duration) -> Self { + pub(crate) const HOUR: Duration = Duration::from_secs(60 * 60); + + let t = t.to_zoned(jiff::tz::TimeZone::system()); + let one_month_ago = t.checked_sub(jiff::Span::new().months(1)).unwrap(); + let one_year_ago = t.checked_sub(jiff::Span::new().years(1)).unwrap(); + + if elapsed < 2 * HOUR { + Self::RelativeDuration + } else if elapsed < 24 * HOUR { + Self::HourMinute + } else if t < one_month_ago { + Self::DayHour + } else if t < one_year_ago { + Self::MonthDayHour + } else { + Self::YearMonthDayHour + } + } + + pub(crate) fn render( + &self, + t: jiff::Timestamp, + elapsed: Duration, + duration_postfix: &str, + ) -> String { + if elapsed.is_zero() { + return "now".to_string(); + } + + match self { + FmtScale::RelativeDuration => duration(elapsed.as_secs_f64()) + duration_postfix, + FmtScale::HourMinute => t.strftime("%H:%M").to_string(), + FmtScale::DayHour => t.strftime("%D %H").to_string(), + FmtScale::MonthDayHour => t.strftime("%M %D %H").to_string(), + FmtScale::YearMonthDayHour => t.strftime("%Y %M %D %H").to_string(), + } + } +} diff --git a/crates/sensor-tui/src/tui/readings/history_len.rs b/crates/sensor-tui/src/tui/readings/history_len.rs index 366d8cae..05cedeaf 100644 --- a/crates/sensor-tui/src/tui/readings/history_len.rs +++ b/crates/sensor-tui/src/tui/readings/history_len.rs @@ -5,7 +5,7 @@ use ratatui::{ }; use std::time::{Duration, Instant}; -use crate::time::format::fmt_seconds; +use crate::time::format::duration; use crate::time::parse::parse_duration; #[derive(Debug, Clone, Copy)] @@ -27,7 +27,7 @@ pub struct HistoryLen { impl Default for HistoryLen { fn default() -> Self { let dur = Duration::from_secs(15 * 60); - let text_input = fmt_seconds(dur.as_secs_f64()); + let text_input = duration(dur.as_secs_f64()); Self { text_input, editing: false, diff --git a/crates/sensor-tui/src/tui/readings/render.rs b/crates/sensor-tui/src/tui/readings/render.rs index 56dd6624..47f4265f 100644 --- a/crates/sensor-tui/src/tui/readings/render.rs +++ b/crates/sensor-tui/src/tui/readings/render.rs @@ -1,5 +1,5 @@ use jiff::Timestamp; -use log_store::api::{ErrorEvent, Percentile}; +use log_store::api::Percentile; use ratatui::{ self, layout::{Alignment, Constraint, Direction, Flex, Layout, Rect}, @@ -13,7 +13,7 @@ use tui_tree_widget::Tree; use crate::tui::Theme; use super::{ - sensor_info::{ChartParts, Details, ErrorDensity, LogSource, Readings}, + sensor_info::{ChartParts, Details, ErrorDensity, LogList, Readings}, UiState, }; @@ -84,7 +84,7 @@ pub fn graph_hist_logs( layout: Rect, app: &mut UiState, percentiles: &[Percentile], - logs: Option<(Vec, LogSource)>, + logs: Option, chart: Option, theme: &Theme, ) { @@ -94,7 +94,11 @@ pub fn graph_hist_logs( if chart.is_some() { constraints[0] = Constraint::Fill(10); } - if logs.as_ref().is_some_and(|(logs, _)| !logs.is_empty()) && app.show_logs { + if logs + .as_ref() + .is_some_and(|LogList { items, .. }| !items.is_empty()) + && app.show_logs + { constraints[1] = Constraint::Fill(10); } if !percentiles.is_empty() && app.show_histogram { @@ -217,7 +221,7 @@ fn render_details(frame: &mut Frame, layout: Rect, details: Details) { .since(ts) .expect("should make sense") .get_seconds(); - let time_ago = crate::time::format::fmt_seconds(seconds_ago as f64); + let time_ago = crate::time::format::duration(seconds_ago as f64); format!("last read: {time_ago} ago, value: {val}") } }; diff --git a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs index 2bcb3944..c0c242ee 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs @@ -1,10 +1,10 @@ use std::time::Duration; -use jiff::tz::TimeZone; use protocol::reading; use ratatui::layout::Rect; use ratatui::text::Span; +use crate::time::format::progressively_more_specified; use crate::tui::readings::sensor_info::ChartParts; use super::Bounds; @@ -20,10 +20,12 @@ pub fn labels<'a>( let y_label_spacing = 10; let info = &chart.reading; + let scale = scale(x_bounds[1]); + // Characters are about twice as high as wide let x = evenly_spaced_labels(layout.width / y_label_spacing / 2, info, x_bounds) .rev() - .map(fmt_seconds) + .map(|x| fmt(x, &scale)) .map(Into::into) .collect(); let y = evenly_spaced_labels(layout.height / y_label_spacing, info, y_bounds) @@ -33,21 +35,19 @@ pub fn labels<'a>( (x, y) } -fn fmt_seconds(secs: f64) -> String { - if secs == 0.0 { - "now".to_string() - } else if secs > 2. * 60. * 60. && secs < 24. * 60. * 60. { - fmt_hh_mm(secs) - } else { - "-".to_string() + &crate::time::format::fmt_seconds(secs) - } +fn fmt(x: f64, scale: &progressively_more_specified::FmtScale) -> String { + let now = jiff::Timestamp::now(); + let elapsed = Duration::from_secs_f64(x); + let time = now - elapsed; + scale.render(time, elapsed, "") } -fn fmt_hh_mm(secs: f64) -> String { +fn scale(secs: f64) -> progressively_more_specified::FmtScale { let now = jiff::Timestamp::now(); - let label = now - Duration::from_secs_f64(secs); - let label = label.to_zoned(TimeZone::system()); - label.strftime("%H:%M").to_string() + let elapsed = Duration::from_secs_f64(secs); + let time = now - elapsed; + + progressively_more_specified::FmtScale::optimal_for(time, elapsed) } fn evenly_spaced_labels( diff --git a/crates/sensor-tui/src/tui/readings/render/logs.rs b/crates/sensor-tui/src/tui/readings/render/logs.rs index 8e2fe98f..4feb3bcf 100644 --- a/crates/sensor-tui/src/tui/readings/render/logs.rs +++ b/crates/sensor-tui/src/tui/readings/render/logs.rs @@ -1,3 +1,5 @@ +use std::ops::Bound; + use jiff::tz::TimeZone; use jiff::Zoned; use log_store::api::ErrorEvent; @@ -7,37 +9,72 @@ use ratatui::text::Text; use ratatui::widgets::{Cell, HighlightSpacing, Row, Table, TableState}; use ratatui::Frame; -use crate::tui::readings::sensor_info::LogSource; +use crate::time::format::progressively_more_specified::FmtScale; +use crate::tui::readings::sensor_info::{LogList, LogSource}; use super::centered_text; +pub fn render_log_range((start, stop): (Bound, Bound)) -> String { + let start = match start { + Bound::Included(start) | Bound::Excluded(start) => { + let elapsed = start.duration_until(jiff::Timestamp::now()).unsigned_abs(); + FmtScale::optimal_for(start, elapsed).render(start, elapsed, " ago") + } + Bound::Unbounded => unreachable!("unbounded not allowed for log range start"), + }; + let stop = match stop { + Bound::Included(stop) | Bound::Excluded(stop) => { + let elapsed = stop.duration_until(jiff::Timestamp::now()).unsigned_abs(); + FmtScale::optimal_for(stop, elapsed).render(stop, elapsed, " ago") + } + Bound::Unbounded => "now".to_owned(), + }; + + format!("{start} and {stop}") +} + pub fn render( frame: &mut Frame, layout: Rect, table_state: &mut TableState, - logs: Option<(Vec, LogSource)>, + logs: Option, theme: &super::Theme, ) { match logs { - Some((logs, LogSource::Store)) => { - if logs.is_empty() { - centered_text("All logs are empty", frame, layout, theme) + Some(LogList { + items, + source: LogSource::Store, + covers, + }) => { + if items.is_empty() { + let text = format!("No logs between {}", render_log_range(covers)); + centered_text(&text, frame, layout, theme) } else { - render_table(frame, layout, table_state, logs) + render_table(frame, layout, table_state, items) } } - Some((logs, LogSource::Local)) => { + Some(LogList { + items, + source: LogSource::Local, + covers, + }) => { let [status, layout] = Layout::new( Direction::Vertical, [Constraint::Max(1), Constraint::Fill(1)], ) .areas(layout); - centered_text("Loading logs from store ..", frame, status, theme); - if logs.is_empty() { - centered_text("Local logs are empty", frame, layout, theme); + centered_text( + "Loading additional logs from store ..", + frame, + status, + theme, + ); + if items.is_empty() { + let text = format!("No local logs between {}", render_log_range(covers)); + centered_text(&text, frame, layout, theme) } else { - render_table(frame, layout, table_state, logs); + render_table(frame, layout, table_state, items); } } None => centered_text("This item can not have logs", frame, layout, theme), diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index ba456e9e..9f3ccc35 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -1,7 +1,7 @@ use hdrhistogram::Histogram; use itertools::Itertools; use jiff::Unit; -use log_store::api::{self, ErrorEvent, Percentile}; +use log_store::api::{self, Percentile}; use protocol::reading; use protocol::reading::tree::{Item, Tree}; use protocol::Reading; @@ -15,6 +15,7 @@ use tui_tree_widget::TreeItem; use crate::Fetchable; mod logs; +pub(crate) use logs::List as LogList; pub(crate) use logs::LogSource; #[derive(Debug)] @@ -153,7 +154,7 @@ impl SensorInfo { }) } - pub fn logs(&self) -> (Vec, logs::LogSource) { + pub fn logs(&self) -> logs::List { self.logs.list() } diff --git a/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs b/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs index 969ba0f9..ae20d5a6 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs @@ -1,3 +1,5 @@ +use std::ops::{Bound, RangeBounds}; + use jiff::Unit; use log_store::api::{self, ErrorEvent}; @@ -85,7 +87,7 @@ impl Logs { buckets.map(|(_, count)| count as f32) } - pub(crate) fn list(&self) -> (Vec, LogSource) { + pub(crate) fn list(&self) -> List { let last = self .from_store .as_ref() @@ -100,18 +102,33 @@ impl Logs { .iter() .skip_while(|ErrorEvent { start, .. }| start < &last) .cloned(); - let mut logs = self + let mut items = self .from_store .as_ref() .map(|FromStore { list, .. }| list) .cloned() .unwrap_or(Vec::new()); - logs.extend(without_duplicates); + items.extend(without_duplicates); + + let covers = if let Some(ref from_store) = self.from_store { + from_store.since.. + } else { + self.local.since.. + }; + let covers = (covers.start_bound().cloned(), covers.end_bound().cloned()); if self.from_store.is_some() { - (logs, LogSource::Store) + List { + items, + source: LogSource::Store, + covers, + } } else { - (logs, LogSource::Local) + List { + items, + source: LogSource::Local, + covers, + } } } @@ -124,6 +141,12 @@ impl Logs { } } +pub(crate) struct List { + pub items: Vec, + pub source: LogSource, + pub covers: (Bound, Bound), +} + pub enum LogSource { Local, Store, diff --git a/crates/sensor-tui/src/tui/reports.rs b/crates/sensor-tui/src/tui/reports.rs index b0470c07..f412e756 100644 --- a/crates/sensor-tui/src/tui/reports.rs +++ b/crates/sensor-tui/src/tui/reports.rs @@ -3,7 +3,7 @@ use std::collections::{HashSet, VecDeque}; use color_eyre::eyre; use crossterm::event::{KeyCode, KeyEvent}; use ratatui::layout::{Alignment, Constraint, Layout, Rect}; -use ratatui::style::{Color, Style, Styled, Stylize}; +use ratatui::style::{Color, Style, Stylize}; use ratatui::text::Text; use ratatui::widgets::{Paragraph, Wrap}; use ratatui::Frame; From 16fe410e79ded1357dd8ef103ebf553f4c7e0c9b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 18 Sep 2024 16:18:38 +0200 Subject: [PATCH 274/687] log-store/api: pass time range when getting logs --- crates/log-store/src/api.rs | 10 +++++-- crates/log-store/src/api/client.rs | 5 +++- crates/log-store/src/server/clients.rs | 2 +- crates/log-store/src/server/db/log.rs | 37 ++++++++++++++++++++------ crates/log-store/tests/list_data.rs | 3 ++- 5 files changed, 44 insertions(+), 13 deletions(-) diff --git a/crates/log-store/src/api.rs b/crates/log-store/src/api.rs index 2fd254d0..fe8bd289 100644 --- a/crates/log-store/src/api.rs +++ b/crates/log-store/src/api.rs @@ -1,3 +1,4 @@ +use std::ops::RangeInclusive; use std::time::Duration; use protocol::{Device, Reading}; @@ -9,8 +10,13 @@ pub use client::Client; #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) enum Request { - Handshake { name: String }, - GetLog(protocol::Device), + Handshake { + name: String, + }, + GetLog { + device: protocol::Device, + range: RangeInclusive, + }, GetStats(protocol::Device), ListDevices, } diff --git a/crates/log-store/src/api/client.rs b/crates/log-store/src/api/client.rs index b5f64222..e2701d30 100644 --- a/crates/log-store/src/api/client.rs +++ b/crates/log-store/src/api/client.rs @@ -1,3 +1,5 @@ +use std::ops::RangeInclusive; + use protocol::Device; use rpc::client::RpcClient; use rpc::client::RpcError; @@ -48,8 +50,9 @@ impl Client { pub async fn get_logs( &mut self, device: protocol::Device, + range: RangeInclusive, ) -> Result, Error> { - let request = super::Request::GetLog(device); + let request = super::Request::GetLog { device, range }; match self.0.send_receive(request.clone()).await? { Response::GetLog(Ok(log)) => Ok(log), Response::GetLog(Err(e)) => Err(Error::Request(e)), diff --git a/crates/log-store/src/server/clients.rs b/crates/log-store/src/server/clients.rs index 88b6fe84..19a88944 100644 --- a/crates/log-store/src/server/clients.rs +++ b/crates/log-store/src/server/clients.rs @@ -27,7 +27,7 @@ async fn perform_request_inner( ) -> Result { Ok(match request { api::Request::Handshake { .. } => return Err(ServerError::AlreadyConnected), - api::Request::GetLog(device) => api::Response::GetLog(logs.get(&device).await), + api::Request::GetLog { device, range } => api::Response::GetLog(logs.get(&device, range).await), api::Request::GetStats(device) => api::Response::GetStats(stats.get(&device).await), api::Request::ListDevices => api::Response::ListDevices(logs.list_devices().await), }) diff --git a/crates/log-store/src/server/db/log.rs b/crates/log-store/src/server/db/log.rs index 53894832..39582b77 100644 --- a/crates/log-store/src/server/db/log.rs +++ b/crates/log-store/src/server/db/log.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use std::io::{self, Read, Write}; use std::iter; +use std::ops::RangeInclusive; use std::path::{Path, PathBuf}; use std::sync::Arc; @@ -187,13 +188,29 @@ impl Log { Ok(()) } - fn get_all(&mut self) -> Result>> { + fn get( + &mut self, + range: RangeInclusive, + ) -> Result>> { let mut timestamps = Vec::new(); let mut data = Vec::new(); - let n_lines = self.history.n_lines_between(..).wrap_err( - "Could not check if there is not too much data \ - between the requested points", - )?; + let range = RangeInclusive::new( + range.start().as_second() as u64, + range.end().as_second() as u64, + ); + let n_lines = match self.history.n_lines_between(range) { + Ok(n_lines) => n_lines, + Err(byteseries::series::Error::InvalidRange( + byteseries::seek::Error::StartAfterData | byteseries::seek::Error::StopBeforeData, + )) => return Ok(Ok(Vec::new())), + Err(other) => { + return Err(other).wrap_err( + "Could not check if there is not too much data between \ + the requested points", + ) + } + }; + if n_lines > 200 { return Ok(Err(api::GetLogError::TooMuchData { max: 200, @@ -272,10 +289,14 @@ impl Logs { Ok(()) } - pub async fn get(&self, device: &protocol::Device) -> ApiResult> { + pub async fn get( + &self, + device: &protocol::Device, + range: RangeInclusive, + ) -> ApiResult> { let mut map = self.0.lock().await; if let Some(log) = map.get_mut(device) { - match log.get_all() { + match log.get(range) { Err(report) => Err(api::GetLogError::InternalError(format!("{report:#}"))), Ok(res) => res, } @@ -298,7 +319,7 @@ impl Logs { } } -/// relative path without extension +/// Relative path without extension fn base_path(device: &protocol::Device) -> PathBuf { use protocol::reading::tree::{Item, Tree}; use protocol::reading::Info; diff --git a/crates/log-store/tests/list_data.rs b/crates/log-store/tests/list_data.rs index 32fb0034..4cc23f53 100644 --- a/crates/log-store/tests/list_data.rs +++ b/crates/log-store/tests/list_data.rs @@ -104,7 +104,8 @@ async fn check_client_get_logs(data_store_addr: SocketAddr, data_send: &Notify) .unwrap(); let test_device = test_readings(0.0).first().unwrap().device(); - let logs = client.get_logs(test_device).await.unwrap(); + let range = jiff::Timestamp::new(0, 0).unwrap()..=jiff::Timestamp::now(); + let logs = client.get_logs(test_device, range).await.unwrap(); assert_eq!(logs.len(), 3); } From d7f033faff1a7f45941a6d9ddd0565a1908c043f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 19 Sep 2024 15:55:04 +0200 Subject: [PATCH 275/687] update embassy to lastest version --- sensor-nodes/bed-sensors/Cargo.lock | 37 ++++++++++++------------- sensor-nodes/bed-sensors/Cargo.toml | 20 ++++++------- sensor-nodes/bed-sensors/src/main.rs | 28 ++++++++----------- sensor-nodes/bed-sensors/src/network.rs | 5 ++-- 4 files changed, 42 insertions(+), 48 deletions(-) diff --git a/sensor-nodes/bed-sensors/Cargo.lock b/sensor-nodes/bed-sensors/Cargo.lock index 06c0b13b..c336f465 100644 --- a/sensor-nodes/bed-sensors/Cargo.lock +++ b/sensor-nodes/bed-sensors/Cargo.lock @@ -289,7 +289,7 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" dependencies = [ "defmt", "embassy-futures", @@ -306,7 +306,7 @@ dependencies = [ [[package]] name = "embassy-executor" version = "0.6.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" dependencies = [ "cortex-m", "critical-section", @@ -320,7 +320,7 @@ dependencies = [ [[package]] name = "embassy-executor-macros" version = "0.5.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" dependencies = [ "darling", "proc-macro2", @@ -331,12 +331,12 @@ dependencies = [ [[package]] name = "embassy-futures" version = "0.1.1" -source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" [[package]] name = "embassy-hal-internal" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" dependencies = [ "cortex-m", "critical-section", @@ -347,7 +347,7 @@ dependencies = [ [[package]] name = "embassy-net" version = "0.4.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" dependencies = [ "defmt", "document-features", @@ -364,7 +364,7 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" dependencies = [ "defmt", ] @@ -372,7 +372,7 @@ dependencies = [ [[package]] name = "embassy-net-driver-channel" version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" dependencies = [ "embassy-futures", "embassy-net-driver", @@ -382,7 +382,7 @@ dependencies = [ [[package]] name = "embassy-net-wiznet" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" dependencies = [ "defmt", "embassy-futures", @@ -395,7 +395,7 @@ dependencies = [ [[package]] name = "embassy-stm32" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" dependencies = [ "aligned", "bit_field", @@ -441,7 +441,7 @@ dependencies = [ [[package]] name = "embassy-sync" version = "0.6.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" dependencies = [ "cfg-if", "critical-section", @@ -454,7 +454,7 @@ dependencies = [ [[package]] name = "embassy-time" version = "0.3.2" -source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" dependencies = [ "cfg-if", "critical-section", @@ -472,7 +472,7 @@ dependencies = [ [[package]] name = "embassy-time-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" dependencies = [ "document-features", ] @@ -480,12 +480,12 @@ dependencies = [ [[package]] name = "embassy-time-queue-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" [[package]] name = "embassy-usb-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" dependencies = [ "defmt", ] @@ -493,7 +493,7 @@ dependencies = [ [[package]] name = "embassy-usb-synopsys-otg" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0ef06cc#0ef06cc19b61c8196fea941514ec313a0f15d145" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" dependencies = [ "critical-section", "embassy-sync", @@ -1044,8 +1044,7 @@ dependencies = [ [[package]] name = "smoltcp" version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a1a996951e50b5971a2c8c0fa05a381480d70a933064245c4a223ddc87ccc97" +source = "git+https://github.com/smoltcp-rs/smoltcp?rev=dd43c8f189178b0ab3bda798ed8578b5b0a6f094#dd43c8f189178b0ab3bda798ed8578b5b0a6f094" dependencies = [ "bitflags 1.3.2", "byteorder", @@ -1109,7 +1108,7 @@ dependencies = [ [[package]] name = "stm32-metapac" version = "15.0.0" -source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-5ef354f3e49f790e47f5c818f243459742c9b83b#d94c7ea2bd05428ba9fd2b5a39edb8ed99f65daa" +source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-ad00827345b4b758b2453082809d6e3b634b5364#e442835159a7a311410cd4a2879da52c6f57af52" dependencies = [ "cortex-m", "cortex-m-rt", diff --git a/sensor-nodes/bed-sensors/Cargo.toml b/sensor-nodes/bed-sensors/Cargo.toml index a51365fe..aaf80b6f 100644 --- a/sensor-nodes/bed-sensors/Cargo.toml +++ b/sensor-nodes/bed-sensors/Cargo.toml @@ -47,16 +47,16 @@ nau7802-async = { path = "/home/david/tmp/nau7802-rs", features = ["serde", "pos protocol = { path = "../../crates/protocol" } [patch.crates-io] -embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } -embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } -embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } -embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } -embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } -embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } -embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } -embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } -embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } -embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "0ef06cc" } +embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } +embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } +embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } +embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } +embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } +embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } +embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } +embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } +embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } +embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } # [patch.'https://github.com/embassy-rs/embassy.git'] # [patch.crates-io] diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed-sensors/src/main.rs index 9e778e81..5661932b 100644 --- a/sensor-nodes/bed-sensors/src/main.rs +++ b/sensor-nodes/bed-sensors/src/main.rs @@ -3,7 +3,7 @@ use embassy_executor::Spawner; use embassy_futures::select::{self, Either3}; -use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources}; +use embassy_net::{Ipv4Address, Ipv4Cidr, StackResources}; use embassy_net_wiznet::{chip::W5500, Device, Runner, State}; use embassy_stm32::exti::ExtiInput; use embassy_stm32::gpio::{Level, Output, Pull, Speed}; @@ -55,8 +55,8 @@ async fn ethernet_task( } #[embassy_executor::task] -async fn net_task(stack: &'static Stack>) -> ! { - stack.run().await +async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { + runner.run().await } // 84 Mhz clock stm32f401 @@ -193,21 +193,17 @@ async fn main(spawner: Spawner) { unwrap!(dns_servers.push(Ipv4Address([192, 168, 1, 1]))); unwrap!(dns_servers.push(Ipv4Address([192, 168, 1, 1]))); unwrap!(dns_servers.push(Ipv4Address([192, 168, 1, 1]))); - static STACK: StaticCell> = StaticCell::new(); static RESOURCES: StaticCell> = StaticCell::new(); - let stack = &*STACK.init(Stack::new( - device, - embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { - address: Ipv4Cidr::new(Ipv4Address([192, 168, 1, 7]), 24), - gateway: Some(Ipv4Address([192, 168, 1, 1])), - dns_servers, - }), - RESOURCES.init(StackResources::<3>::new()), - seed, - )); + let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { + address: Ipv4Cidr::new(Ipv4Address([192, 168, 1, 7]), 24), + gateway: Some(Ipv4Address([192, 168, 1, 1])), + dns_servers, + }); + let (stack, runner) = + embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); // Launch network task - unwrap!(spawner.spawn(net_task(stack))); + unwrap!(spawner.spawn(net_task(runner))); let comms = Channel::new(); let (mut led_controller, led_handle) = @@ -215,7 +211,7 @@ async fn main(spawner: Spawner) { let driver_orderers = slow::DriverOrderers::new(); let publish = Queues::new(); - let handle_network = network::handle(stack, &publish, led_handle.clone(), &driver_orderers); + let handle_network = network::handle(&stack, &publish, led_handle.clone(), &driver_orderers); pin_mut!(handle_network); let init_then_measure = sensors::init_then_measure( diff --git a/sensor-nodes/bed-sensors/src/network.rs b/sensor-nodes/bed-sensors/src/network.rs index 947ddd78..03a36709 100644 --- a/sensor-nodes/bed-sensors/src/network.rs +++ b/sensor-nodes/bed-sensors/src/network.rs @@ -1,6 +1,5 @@ use defmt::{debug, info, unwrap, warn}; use embassy_futures::select::{self, select}; -use embassy_net::driver::Driver; use embassy_net::tcp::{TcpReader, TcpSocket, TcpWriter}; use embassy_net::{Ipv4Address, Stack}; use embassy_time::{with_timeout, Duration, Instant, Timer}; @@ -69,7 +68,7 @@ const fn max(a: usize, b: usize) -> usize { } pub async fn handle( - stack: &Stack, + stack: &Stack<'_>, publish: &Queues, led: LedHandle<'_>, driver_orderers: &slow::DriverOrderers, @@ -77,7 +76,7 @@ pub async fn handle( let mut rx_buffer = [0; 1024]; let mut tx_buffer = [0; max(SensMsg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE) * 2]; - let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + let mut socket = TcpSocket::new(*stack, &mut rx_buffer, &mut tx_buffer); socket.set_timeout(Some(Duration::from_secs(5))); socket.set_keep_alive(Some(Duration::from_secs(1))); let host_addr = Ipv4Address::new(192, 168, 1, 43); From 74c28533ca853b04757a4df2a3250d8f2732cf7b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 22 Sep 2024 16:43:34 +0200 Subject: [PATCH 276/687] update versions, actually implement reinit for sps --- sensor-nodes/bed-sensors/.cargo/config.toml | 2 +- sensor-nodes/bed-sensors/Cargo.lock | 3 +- sensor-nodes/bed-sensors/Cargo.toml | 2 +- sensor-nodes/bed-sensors/src/sensors.rs | 2 +- .../src/sensors/retry/reset_on_error.rs | 54 ------------------- .../src/sensors/retry/retry_init.rs | 20 ++++--- 6 files changed, 18 insertions(+), 65 deletions(-) delete mode 100644 sensor-nodes/bed-sensors/src/sensors/retry/reset_on_error.rs diff --git a/sensor-nodes/bed-sensors/.cargo/config.toml b/sensor-nodes/bed-sensors/.cargo/config.toml index d2fde87a..161b3118 100644 --- a/sensor-nodes/bed-sensors/.cargo/config.toml +++ b/sensor-nodes/bed-sensors/.cargo/config.toml @@ -9,7 +9,7 @@ linker = "flip-link" target = "thumbv7em-none-eabihf" [env] -DEFMT_LOG = "debug,sps30_async=info,bosch_bme680=info" +DEFMT_LOG = "debug,sps30_async=warn,bosch_bme680=info" EMBASSY_EXECUTOR_TASK_ARENA_SIZE="10900" # [unstable] diff --git a/sensor-nodes/bed-sensors/Cargo.lock b/sensor-nodes/bed-sensors/Cargo.lock index c336f465..ee2fcc0e 100644 --- a/sensor-nodes/bed-sensors/Cargo.lock +++ b/sensor-nodes/bed-sensors/Cargo.lock @@ -1065,11 +1065,12 @@ dependencies = [ [[package]] name = "sps30-async" -version = "0.2.0" +version = "0.3.0" dependencies = [ "defmt", "embedded-hal-async", "embedded-io-async", + "futures", "heapless 0.8.0", "postcard", "serde", diff --git a/sensor-nodes/bed-sensors/Cargo.toml b/sensor-nodes/bed-sensors/Cargo.toml index aaf80b6f..7a0298b4 100644 --- a/sensor-nodes/bed-sensors/Cargo.toml +++ b/sensor-nodes/bed-sensors/Cargo.toml @@ -40,7 +40,7 @@ bosch-bme680 = { version = "1.0.2", path = "/home/david/Documents/async-bosch-bm max44009 = { version = "0.2", git = "https://github.com/dvdsk/max44009-rs" } sht31 = { version = "0.3.0", git = "https://github.com/dvdsk/SHT31-rs", features = ["postcard"] } mhzx = { version = "0.3.0", path = "/home/david/tmp/mh-zx-driver", features = ["serde", "postcard"] } -sps30-async = { version = "0.2.0", path = "/home/david/tmp/sps30", features = ["serde", "postcard"] } +sps30-async = { version = "0.3.0", path = "/home/david/tmp/sps30", features = ["serde", "postcard"] } nau7802-async = { path = "/home/david/tmp/nau7802-rs", features = ["serde", "postcard", "defmt"] } # encoding diff --git a/sensor-nodes/bed-sensors/src/sensors.rs b/sensor-nodes/bed-sensors/src/sensors.rs index 693eaeb2..3b067d6d 100644 --- a/sensor-nodes/bed-sensors/src/sensors.rs +++ b/sensor-nodes/bed-sensors/src/sensors.rs @@ -44,7 +44,7 @@ pub mod concrete_types { pub type ConcreteRx<'a> = RingBufferedUartRx<'a>; } -const SPS30_UART_BUF_SIZE: usize = 300; +const SPS30_UART_BUF_SIZE: usize = 150; const SPS30_DRIVER_BUF_SIZE: usize = 2 * SPS30_UART_BUF_SIZE; pub async fn init_then_measure( diff --git a/sensor-nodes/bed-sensors/src/sensors/retry/reset_on_error.rs b/sensor-nodes/bed-sensors/src/sensors/retry/reset_on_error.rs deleted file mode 100644 index 0f4f40d7..00000000 --- a/sensor-nodes/bed-sensors/src/sensors/retry/reset_on_error.rs +++ /dev/null @@ -1,54 +0,0 @@ -// use bosch_bme680::Bme680; -// use embassy_embedded_hal::shared_bus; -// use embassy_stm32::i2c::I2c; -// use embassy_stm32::mode::Async; -// use embassy_sync::blocking_mutex::raw::NoopRawMutex; -// use embassy_sync::mutex::Mutex; -// use embassy_time::{Delay, Timer}; -// use max44009::{Max44009, SlaveAddr}; -// use sht31::mode::SingleShot; -// use sht31::SHT31; -// -use super::super::concrete_types::{ConcreteRx, ConcreteTx}; - -use crate::error_cache::{Error, SensorError}; - -pub trait ResettableDriver: Sized { - type Measurement; - - async fn reset(&mut self) -> Result; - async fn measure(&mut self) -> Result; -} - -pub struct ResetOnErrorDriver -where - D: ResettableDriver, -{ - driver: D, -} - -impl ResetOnErrorDriver { - pub fn new(driver: D) -> Self { - Self { driver } - } - - pub async fn try_measure(&mut self) -> Result { - let res = self.driver.measure().await.map_err(Error::Running); - if res.is_err() { - self.driver.reset().await.map_err(Error::Setup)?; - } - res - } -} - -impl<'a> ResettableDriver for mhzx::MHZ, ConcreteRx<'a>> { - type Measurement = f32; - - async fn reset(&mut self) -> Result { - self. - } - - async fn measure(&mut self) -> Result { - todo!() - } -} diff --git a/sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs b/sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs index d377b2fa..706be28e 100644 --- a/sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs +++ b/sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs @@ -3,13 +3,14 @@ use sps30_async::Sps30; use crate::error_cache::{Error, SensorError}; use crate::sensors::concrete_types::{ConcreteRx, ConcreteTx}; -use crate::sensors::SPS30_UART_BUF_SIZE; +use crate::sensors::SPS30_DRIVER_BUF_SIZE; use super::Driver; +/// reset the device when an error occurs pub struct Sps30Driver<'a> { is_init: bool, - driver: Sps30, ConcreteRx<'a>, Delay>, + driver: Sps30, ConcreteRx<'a>, Delay>, } impl<'a> Sps30Driver<'a> { @@ -23,12 +24,14 @@ impl<'a> Sps30Driver<'a> { async fn measure(&mut self) -> Result { if self.is_init { - return self + let res = self .driver .read_measurement() .await .map_err(SensorError::Sps30) .map_err(Error::Running); + self.is_init = res.is_ok(); + return res; } self.driver @@ -42,12 +45,15 @@ impl<'a> Sps30Driver<'a> { .map_err(SensorError::Sps30) .map_err(Error::Setup)?; - self.is_init = true; - self.driver + let res = self + .driver .read_measurement() .await .map_err(SensorError::Sps30) - .map_err(Error::Running) + .map_err(Error::Running); + + self.is_init = res.is_ok(); + res } } @@ -65,7 +71,7 @@ impl<'a> Driver for Sps30Driver<'a> { .await .map_err(SensorError::Sps30) .map_err(Error::Running)?; - // Fan cleaning takes 10 seconds, make sure its done before + // Fan cleaning takes 10 seconds, make sure its done before // allowing the next reading embassy_time::Timer::after(embassy_time::Duration::from_secs(11)).await; Ok(()) From 4c9b2f6f3eebebffc42c3657cd1a5c59d98b4fb8 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 22 Sep 2024 16:44:08 +0200 Subject: [PATCH 277/687] logs now come in ranges --- Cargo.lock | 279 ++++++------------ crates/data-store/src/server/db/series.rs | 3 +- crates/log-store/src/api.rs | 21 +- crates/log-store/src/api/client.rs | 55 +++- crates/log-store/src/server/db/log.rs | 83 +++--- .../src/tui/readings/sensor_info.rs | 3 +- 6 files changed, 190 insertions(+), 254 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ceab6e1d..26fe8a22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -155,9 +155,9 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ "async-task", "concurrent-queue", @@ -174,61 +174,32 @@ checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ "async-channel 2.3.1", "async-executor", - "async-io 2.3.4", - "async-lock 3.4.0", + "async-io", + "async-lock", "blocking", "futures-lite 2.3.0", "once_cell", ] -[[package]] -name = "async-io" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" -dependencies = [ - "async-lock 2.8.0", - "autocfg", - "cfg-if 1.0.0", - "concurrent-queue", - "futures-lite 1.13.0", - "log", - "parking", - "polling 2.8.0", - "rustix 0.37.27", - "slab", - "socket2 0.4.10", - "waker-fn", -] - [[package]] name = "async-io" version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" dependencies = [ - "async-lock 3.4.0", + "async-lock", "cfg-if 1.0.0", "concurrent-queue", "futures-io", "futures-lite 2.3.0", "parking", - "polling 3.7.3", - "rustix 0.38.35", + "polling", + "rustix", "slab", "tracing", "windows-sys 0.59.0", ] -[[package]] -name = "async-lock" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" -dependencies = [ - "event-listener 2.5.3", -] - [[package]] name = "async-lock" version = "3.4.0" @@ -242,19 +213,21 @@ dependencies = [ [[package]] name = "async-process" -version = "1.8.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" dependencies = [ - "async-io 1.13.0", - "async-lock 2.8.0", + "async-channel 2.3.1", + "async-io", + "async-lock", "async-signal", + "async-task", "blocking", "cfg-if 1.0.0", - "event-listener 3.1.0", - "futures-lite 1.13.0", - "rustix 0.38.35", - "windows-sys 0.48.0", + "event-listener 5.3.1", + "futures-lite 2.3.0", + "rustix", + "tracing", ] [[package]] @@ -263,13 +236,13 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" dependencies = [ - "async-io 2.3.4", - "async-lock 3.4.0", + "async-io", + "async-lock", "atomic-waker", "cfg-if 1.0.0", "futures-core", "futures-io", - "rustix 0.38.35", + "rustix", "signal-hook-registry", "slab", "windows-sys 0.59.0", @@ -277,21 +250,21 @@ dependencies = [ [[package]] name = "async-std" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" dependencies = [ "async-attributes", "async-channel 1.9.0", "async-global-executor", - "async-io 1.13.0", - "async-lock 2.8.0", + "async-io", + "async-lock", "async-process", "crossbeam-utils", "futures-channel", "futures-core", "futures-io", - "futures-lite 1.13.0", + "futures-lite 2.3.0", "gloo-timers", "kv-log-macro", "log", @@ -564,14 +537,14 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "byteseries" -version = "0.6.0" -source = "git+https://github.com/dvdsk/byteseries#03fd66109fc167a4665c8290a2b6a03d476daf65" +version = "0.7.1" +source = "git+https://github.com/dvdsk/byteseries#edc1c89c580c35b411de68feab4f665303d4c5cc" dependencies = [ "arraydeque", "itertools", @@ -606,9 +579,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.15" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" dependencies = [ "shlex", ] @@ -642,9 +615,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.16" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" dependencies = [ "clap_builder", "clap_derive", @@ -652,9 +625,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.15" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" dependencies = [ "anstream", "anstyle", @@ -820,7 +793,7 @@ dependencies = [ "crossterm_winapi", "mio", "parking_lot 0.12.3", - "rustix 0.38.35", + "rustix", "signal-hook", "signal-hook-mio", "winapi", @@ -862,7 +835,7 @@ dependencies = [ "rpc", "serde", "slotmap", - "socket2 0.5.7", + "socket2", "thiserror", "tokio", "tokio-serde", @@ -988,9 +961,9 @@ dependencies = [ [[package]] name = "diatomic-waker" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af873b6853650fb206431c52fa7bbf6917146b70a8a9979d6d141f5d5394086b" +checksum = "ab03c107fafeb3ee9f5925686dbb7a73bc76e3932abb0d2b365cb64b169cf04c" [[package]] name = "dirs" @@ -1171,17 +1144,6 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" -[[package]] -name = "event-listener" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - [[package]] name = "event-listener" version = "5.3.1" @@ -1235,7 +1197,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef033ed5e9bad94e55838ca0ca906db0e043f517adda0c8b79c7a8c66c93c1b5" dependencies = [ "cfg-if 1.0.0", - "rustix 0.38.35", + "rustix", "windows-sys 0.48.0", ] @@ -1444,7 +1406,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc3655aa6818d65bc620d6911f05aa7b6aeb596291e1e9f79e52df85583d1e30" dependencies = [ - "rustix 0.38.35", + "rustix", "windows-targets 0.52.6", ] @@ -1467,9 +1429,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "gloo-timers" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" dependencies = [ "futures-channel", "futures-core", @@ -1742,9 +1704,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" dependencies = [ "bytes", "futures-channel", @@ -1753,7 +1715,7 @@ dependencies = [ "http-body", "hyper", "pin-project-lite", - "socket2 0.5.7", + "socket2", "tokio", "tower", "tower-service", @@ -1774,9 +1736,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1850,17 +1812,6 @@ dependencies = [ "mach2", ] -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.9", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "ioctl-sys" version = "0.8.0" @@ -1869,9 +1820,9 @@ checksum = "8bd11f3a29434026f5ff98c730b668ba74b1033637b8817940b54d040696133c" [[package]] name = "ipnet" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" [[package]] name = "is_terminal_polyfill" @@ -1896,9 +1847,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jiff" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "437651126da47900d4d70255ab15f5c69510ca4e0d88c9f01b5b8d41a45c3a9b" +checksum = "8a45489186a6123c128fdf6016183fcfab7113e1820eb813127e036e287233fb" dependencies = [ "jiff-tzdb-platform", "serde", @@ -1907,15 +1858,15 @@ dependencies = [ [[package]] name = "jiff-tzdb" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05fac328b3df1c0f18a3c2ab6cb7e06e4e549f366017d796e3e66b6d6889abe6" +checksum = "91335e575850c5c4c673b9bd467b0e025f164ca59d0564f69d0c2ee0ffad4653" [[package]] name = "jiff-tzdb-platform" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8da387d5feaf355954c2c122c194d6df9c57d865125a67984bb453db5336940" +checksum = "9835f0060a626fe59f160437bc725491a6af23133ea906500027d1bd2f8f4329" dependencies = [ "jiff-tzdb", ] @@ -1978,12 +1929,6 @@ dependencies = [ "sysfs_gpio", ] -[[package]] -name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -2396,9 +2341,9 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "parking" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" @@ -2443,7 +2388,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.5.3", + "redox_syscall 0.5.4", "smallvec 1.13.2", "windows-targets 0.52.6", ] @@ -2503,22 +2448,6 @@ dependencies = [ "futures-io", ] -[[package]] -name = "polling" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if 1.0.0", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys 0.48.0", -] - [[package]] name = "polling" version = "3.7.3" @@ -2529,16 +2458,16 @@ dependencies = [ "concurrent-queue", "hermit-abi 0.4.0", "pin-project-lite", - "rustix 0.38.35", + "rustix", "tracing", "windows-sys 0.59.0", ] [[package]] name = "portable-atomic" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" +checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce" [[package]] name = "postcard" @@ -2636,9 +2565,9 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4e75767fbc9d92b90e4d0c011f61358cde9513b31ef07ea3631b15ffc3b4fd" +checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625" dependencies = [ "bitflags 2.6.0", "memchr", @@ -2772,9 +2701,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" dependencies = [ "bitflags 2.6.0", ] @@ -2924,28 +2853,14 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustix" -version = "0.38.35" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys 0.4.14", + "linux-raw-sys", "windows-sys 0.52.0", ] @@ -3024,18 +2939,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -3044,9 +2959,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.127" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", @@ -3081,9 +2996,9 @@ dependencies = [ [[package]] name = "serialport" -version = "4.5.0" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241ebb629ed9bf598b2b392ba42aa429f9ef2a0099001246a36ac4c084ee183f" +checksum = "3ba776acc8c373b9175829206229366273225436845c04f9c20aab8099960e2e" dependencies = [ "bitflags 2.6.0", "cfg-if 1.0.0", @@ -3187,16 +3102,6 @@ version = "2.0.0-alpha.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6a96cb564e12be8458b004bd829787ebe887de197d94516d2ba5a2a32235a0c" -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "socket2" version = "0.5.7" @@ -3449,7 +3354,7 @@ dependencies = [ "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.7", + "socket2", "tokio-macros", "windows-sys 0.52.0", ] @@ -3482,9 +3387,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -3493,9 +3398,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -3673,24 +3578,24 @@ checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-truncate" @@ -3705,15 +3610,15 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-xid" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unsafe-libyaml" diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index 051f3b1b..c26f59a6 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -98,7 +98,7 @@ impl Series { }) } - #[instrument] + #[instrument(skip(self))] fn append(&mut self, reading: &protocol::Reading) -> Result<()> { let index = reading .device() @@ -282,6 +282,7 @@ pub(crate) async fn store(data: &Data, reading: &protocol::Reading, data_dir: &P let existing = data.insert(key, series); assert!(existing.is_none(), "should not race we still hold the lock"); } + trace!("stored new reading"); Ok(()) } diff --git a/crates/log-store/src/api.rs b/crates/log-store/src/api.rs index fe8bd289..0523b57d 100644 --- a/crates/log-store/src/api.rs +++ b/crates/log-store/src/api.rs @@ -37,14 +37,6 @@ pub enum GetStatsError { InternalError(String), } -#[derive(Debug, Clone, Serialize, Deserialize, thiserror::Error)] -pub enum GetLogError { - #[error("Too many error events ({found}) between requested timepoints, max is: {max}")] - TooMuchData { max: i32, found: u64 }, - #[error("Internal error while reading data, error: {0}")] - InternalError(String), -} - #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Percentile { pub bucket_ends: u64, @@ -60,9 +52,20 @@ pub struct ErrorEvent { pub error: protocol::Error, } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub(crate) enum GetLogResponse { + Err(String), + /// all logs between requested ranges + All(Vec), + /// could not send more logs due to rate limits + /// user should request more starting at the last + /// item in the list + Partial(Vec), +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) enum Response { - GetLog(Result, GetLogError>), + GetLog(GetLogResponse), ListDevices(Vec), GetStats(Result, GetStatsError>), Error(ServerError), diff --git a/crates/log-store/src/api/client.rs b/crates/log-store/src/api/client.rs index e2701d30..cb167680 100644 --- a/crates/log-store/src/api/client.rs +++ b/crates/log-store/src/api/client.rs @@ -1,14 +1,17 @@ use std::ops::RangeInclusive; +use std::time::Duration; use protocol::Device; use rpc::client::RpcClient; use rpc::client::RpcError; use tokio::net::ToSocketAddrs; +use tokio::time::sleep; +use tracing::instrument; use crate::api::Percentile; use super::ErrorEvent; -use super::GetLogError; +use super::GetLogResponse; use super::GetStatsError; use super::Response; @@ -16,7 +19,7 @@ pub struct Client(rpc::client::RpcClient); pub use rpc::client::ConnectError; #[derive(Debug, thiserror::Error)] -pub enum Error { +pub enum Error { #[error("Server ran into an specific error with our request: {0}")] Request(T), #[error("Error while communicating with server: {0}")] @@ -47,23 +50,49 @@ impl Client { } } + #[instrument(err, skip(self))] pub async fn get_logs( &mut self, device: protocol::Device, - range: RangeInclusive, - ) -> Result, Error> { - let request = super::Request::GetLog { device, range }; - match self.0.send_receive(request.clone()).await? { - Response::GetLog(Ok(log)) => Ok(log), - Response::GetLog(Err(e)) => Err(Error::Request(e)), - response => Err(Error::Comms(RpcError::IncorrectResponse { - request: format!("{request:?}"), - response: format!("{response:?}"), - })), + mut range: RangeInclusive, + ) -> Result, Error> { + tracing::debug!("get all logs between: {range:?}"); + let mut all = Vec::new(); + + while !range.is_empty() { + let request = super::Request::GetLog { + device: device.clone(), + range: range.clone(), + }; + let partial = match self.0.send_receive(request.clone()).await? { + Response::GetLog(GetLogResponse::All(log)) => { + all.extend_from_slice(&log); + return Ok(all); + } + Response::GetLog(GetLogResponse::Partial(log)) => log, + Response::GetLog(GetLogResponse::Err(e)) => return Err(Error::Request(e)), + response => { + return Err(Error::Comms(RpcError::IncorrectResponse { + request: format!("{request:?}"), + response: format!("{response:?}"), + })) + } + }; + + let partial_ends = partial + .last() + .expect("if log.len() == 0 then response is GetLogResponse::All") + .start; + range = RangeInclusive::new(partial_ends + jiff::Span::new().seconds(1), *range.end()); + tracing::debug!("Got logs up till {partial_ends}, next requesting: {range:?}"); + all.extend_from_slice(&partial); + // do not overburden the server + sleep(Duration::from_millis(100)).await; } + Ok(all) } - pub async fn list_devices(&mut self) -> Result, Error> { + pub async fn list_devices(&mut self) -> Result, Error> { let request = super::Request::ListDevices; match self.0.send_receive(request.clone()).await? { Response::ListDevices(logs) => Ok(logs), diff --git a/crates/log-store/src/server/db/log.rs b/crates/log-store/src/server/db/log.rs index 39582b77..c2546528 100644 --- a/crates/log-store/src/server/db/log.rs +++ b/crates/log-store/src/server/db/log.rs @@ -16,7 +16,7 @@ use series::Error::Open; use tokio::sync::Mutex; use tracing::{debug, info, instrument, warn}; -use crate::api::{self, ErrorEvent}; +use crate::api::{self, ErrorEvent, GetLogResponse}; #[derive(derivative::Derivative)] #[derivative(Debug)] @@ -188,35 +188,15 @@ impl Log { Ok(()) } - fn get( - &mut self, - range: RangeInclusive, - ) -> Result>> { - let mut timestamps = Vec::new(); - let mut data = Vec::new(); - let range = RangeInclusive::new( + fn get(&mut self, range: RangeInclusive) -> GetLogResponse { + use byteseries::seek::Error::{StartAfterData, StopBeforeData}; + use byteseries::series::Error::InvalidRange; + const MAX_IN_ONE_READ: usize = 200; + + let ts_range = RangeInclusive::new( range.start().as_second() as u64, range.end().as_second() as u64, ); - let n_lines = match self.history.n_lines_between(range) { - Ok(n_lines) => n_lines, - Err(byteseries::series::Error::InvalidRange( - byteseries::seek::Error::StartAfterData | byteseries::seek::Error::StopBeforeData, - )) => return Ok(Ok(Vec::new())), - Err(other) => { - return Err(other).wrap_err( - "Could not check if there is not too much data between \ - the requested points", - ) - } - }; - - if n_lines > 200 { - return Ok(Err(api::GetLogError::TooMuchData { - max: 200, - found: n_lines, - })); - } let current = self .current @@ -229,14 +209,27 @@ impl Log { }) .into_iter(); - if n_lines == 0 { - return Ok(Ok(current.collect())); + let mut timestamps = Vec::new(); + let mut data = Vec::new(); + match self.history.read_first_n( + MAX_IN_ONE_READ, + &mut Decoder, + ts_range, + &mut timestamps, + &mut data, + ) { + Ok(()) => (), + Err(InvalidRange(StartAfterData | StopBeforeData)) => { + return GetLogResponse::All(current.collect()) + } + Err(other) => { + let report = color_eyre::eyre::Report::new(other) + .wrap_err("Could not read log events from disk") + .to_string(); + return GetLogResponse::Err(report); + } } - self.history - .read_all(.., &mut Decoder, &mut timestamps, &mut data) - .wrap_err("Could not read log events from disk")?; - let mut res: Vec<_> = timestamps .into_iter() .zip(data) @@ -247,9 +240,18 @@ impl Log { error, }) .collect(); - res.extend(current); - Ok(Ok(res)) + if res.len() < MAX_IN_ONE_READ { + res.extend( + current.filter(|ErrorEvent { start, .. }| { + start >= range.start() && start <= range.end() + }), + ); + + GetLogResponse::All(res) + } else { + GetLogResponse::Partial(res) + } } } @@ -269,8 +271,6 @@ impl byteseries::Decoder for Decoder { } } -type ApiResult = std::result::Result; - #[derive(Debug, Clone)] pub(crate) struct Logs(pub(crate) Arc>>); @@ -293,15 +293,12 @@ impl Logs { &self, device: &protocol::Device, range: RangeInclusive, - ) -> ApiResult> { + ) -> api::GetLogResponse { let mut map = self.0.lock().await; if let Some(log) = map.get_mut(device) { - match log.get(range) { - Err(report) => Err(api::GetLogError::InternalError(format!("{report:#}"))), - Ok(res) => res, - } + log.get(range) } else { - Ok(Vec::new()) + api::GetLogResponse::All(Vec::new()) } } diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index 9f3ccc35..27ef6237 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -144,6 +144,7 @@ impl SensorInfo { *y as f64, ) }) + .skip_while(|(x, _)| *x > history_len.as_secs_f64()) { plot_buf.push(xy); } @@ -368,7 +369,7 @@ impl Readings { fn update_tree(&mut self, reading: &Reading, placeholder: IsPlaceholder) { let key = tree_key(reading); - tracing::debug!("reading: {reading:?}"); + tracing::trace!("reading: {reading:?}"); let mut tree = add_root(reading as &dyn Tree, &mut self.ground); let mut node = match reading.inner() { From 89f25511c81e6af741f71a465774aed57b00f65c Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 22 Sep 2024 16:45:22 +0200 Subject: [PATCH 278/687] rename bed node to account for second node --- .../.cargo/config.toml | 0 .../{bed-sensors => bed_lb}/.gitignore | 0 .../{bed-sensors => bed_lb}/Cargo.lock | 0 .../{bed-sensors => bed_lb}/Cargo.toml | 0 sensor-nodes/{bed-sensors => bed_lb}/build.rs | 0 sensor-nodes/bed_lb/output.txt | 19660 ++++++++++++++++ .../rust-toolchain.toml | 0 .../{bed-sensors => bed_lb}/src/channel.rs | 0 .../src/error_cache.rs | 0 .../{bed-sensors => bed_lb}/src/main.rs | 0 .../{bed-sensors => bed_lb}/src/network.rs | 0 .../{bed-sensors => bed_lb}/src/rgb_led.rs | 0 .../{bed-sensors => bed_lb}/src/rng.rs | 0 .../{bed-sensors => bed_lb}/src/sensors.rs | 0 .../src/sensors/fast.rs | 0 .../src/sensors/retry.rs | 0 .../src/sensors/retry/reinit_on_error.rs | 0 .../src/sensors/retry/retry_init.rs | 0 .../src/sensors/slow.rs | 0 .../{bed-sensors => bed_lb}/stm32f401.svd | 0 20 files changed, 19660 insertions(+) rename sensor-nodes/{bed-sensors => bed_lb}/.cargo/config.toml (100%) rename sensor-nodes/{bed-sensors => bed_lb}/.gitignore (100%) rename sensor-nodes/{bed-sensors => bed_lb}/Cargo.lock (100%) rename sensor-nodes/{bed-sensors => bed_lb}/Cargo.toml (100%) rename sensor-nodes/{bed-sensors => bed_lb}/build.rs (100%) create mode 100644 sensor-nodes/bed_lb/output.txt rename sensor-nodes/{bed-sensors => bed_lb}/rust-toolchain.toml (100%) rename sensor-nodes/{bed-sensors => bed_lb}/src/channel.rs (100%) rename sensor-nodes/{bed-sensors => bed_lb}/src/error_cache.rs (100%) rename sensor-nodes/{bed-sensors => bed_lb}/src/main.rs (100%) rename sensor-nodes/{bed-sensors => bed_lb}/src/network.rs (100%) rename sensor-nodes/{bed-sensors => bed_lb}/src/rgb_led.rs (100%) rename sensor-nodes/{bed-sensors => bed_lb}/src/rng.rs (100%) rename sensor-nodes/{bed-sensors => bed_lb}/src/sensors.rs (100%) rename sensor-nodes/{bed-sensors => bed_lb}/src/sensors/fast.rs (100%) rename sensor-nodes/{bed-sensors => bed_lb}/src/sensors/retry.rs (100%) rename sensor-nodes/{bed-sensors => bed_lb}/src/sensors/retry/reinit_on_error.rs (100%) rename sensor-nodes/{bed-sensors => bed_lb}/src/sensors/retry/retry_init.rs (100%) rename sensor-nodes/{bed-sensors => bed_lb}/src/sensors/slow.rs (100%) rename sensor-nodes/{bed-sensors => bed_lb}/stm32f401.svd (100%) diff --git a/sensor-nodes/bed-sensors/.cargo/config.toml b/sensor-nodes/bed_lb/.cargo/config.toml similarity index 100% rename from sensor-nodes/bed-sensors/.cargo/config.toml rename to sensor-nodes/bed_lb/.cargo/config.toml diff --git a/sensor-nodes/bed-sensors/.gitignore b/sensor-nodes/bed_lb/.gitignore similarity index 100% rename from sensor-nodes/bed-sensors/.gitignore rename to sensor-nodes/bed_lb/.gitignore diff --git a/sensor-nodes/bed-sensors/Cargo.lock b/sensor-nodes/bed_lb/Cargo.lock similarity index 100% rename from sensor-nodes/bed-sensors/Cargo.lock rename to sensor-nodes/bed_lb/Cargo.lock diff --git a/sensor-nodes/bed-sensors/Cargo.toml b/sensor-nodes/bed_lb/Cargo.toml similarity index 100% rename from sensor-nodes/bed-sensors/Cargo.toml rename to sensor-nodes/bed_lb/Cargo.toml diff --git a/sensor-nodes/bed-sensors/build.rs b/sensor-nodes/bed_lb/build.rs similarity index 100% rename from sensor-nodes/bed-sensors/build.rs rename to sensor-nodes/bed_lb/build.rs diff --git a/sensor-nodes/bed_lb/output.txt b/sensor-nodes/bed_lb/output.txt new file mode 100644 index 00000000..48b0ff76 --- /dev/null +++ b/sensor-nodes/bed_lb/output.txt @@ -0,0 +1,19660 @@ +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 867502111134296087 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 14599460162574367279 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 8070402030576215694 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 4334505959795280607 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 12614019627889602978 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 13081958469941311299 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 17908139605922323881 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 2841131338015846188 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 13356480873848707970 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 1656018264575584532 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 14091470885172412432 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::handle::{async_fn#0} @ src/network.rs:78 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +INFO (re-)connected +└─ bed_sensors::network::handle::{async_fn#0} @ src/network.rs:85 +INFO link_up = false +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG retransmitting at t+0.899s +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG retransmitting at t+0.899s +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG retransmitting at t+0.899s +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG retransmitting at t+1.102s +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG retransmitting at t+1.102s +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG retransmitting at t+1.102s +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG retransmitting at t+1.508s +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 diff --git a/sensor-nodes/bed-sensors/rust-toolchain.toml b/sensor-nodes/bed_lb/rust-toolchain.toml similarity index 100% rename from sensor-nodes/bed-sensors/rust-toolchain.toml rename to sensor-nodes/bed_lb/rust-toolchain.toml diff --git a/sensor-nodes/bed-sensors/src/channel.rs b/sensor-nodes/bed_lb/src/channel.rs similarity index 100% rename from sensor-nodes/bed-sensors/src/channel.rs rename to sensor-nodes/bed_lb/src/channel.rs diff --git a/sensor-nodes/bed-sensors/src/error_cache.rs b/sensor-nodes/bed_lb/src/error_cache.rs similarity index 100% rename from sensor-nodes/bed-sensors/src/error_cache.rs rename to sensor-nodes/bed_lb/src/error_cache.rs diff --git a/sensor-nodes/bed-sensors/src/main.rs b/sensor-nodes/bed_lb/src/main.rs similarity index 100% rename from sensor-nodes/bed-sensors/src/main.rs rename to sensor-nodes/bed_lb/src/main.rs diff --git a/sensor-nodes/bed-sensors/src/network.rs b/sensor-nodes/bed_lb/src/network.rs similarity index 100% rename from sensor-nodes/bed-sensors/src/network.rs rename to sensor-nodes/bed_lb/src/network.rs diff --git a/sensor-nodes/bed-sensors/src/rgb_led.rs b/sensor-nodes/bed_lb/src/rgb_led.rs similarity index 100% rename from sensor-nodes/bed-sensors/src/rgb_led.rs rename to sensor-nodes/bed_lb/src/rgb_led.rs diff --git a/sensor-nodes/bed-sensors/src/rng.rs b/sensor-nodes/bed_lb/src/rng.rs similarity index 100% rename from sensor-nodes/bed-sensors/src/rng.rs rename to sensor-nodes/bed_lb/src/rng.rs diff --git a/sensor-nodes/bed-sensors/src/sensors.rs b/sensor-nodes/bed_lb/src/sensors.rs similarity index 100% rename from sensor-nodes/bed-sensors/src/sensors.rs rename to sensor-nodes/bed_lb/src/sensors.rs diff --git a/sensor-nodes/bed-sensors/src/sensors/fast.rs b/sensor-nodes/bed_lb/src/sensors/fast.rs similarity index 100% rename from sensor-nodes/bed-sensors/src/sensors/fast.rs rename to sensor-nodes/bed_lb/src/sensors/fast.rs diff --git a/sensor-nodes/bed-sensors/src/sensors/retry.rs b/sensor-nodes/bed_lb/src/sensors/retry.rs similarity index 100% rename from sensor-nodes/bed-sensors/src/sensors/retry.rs rename to sensor-nodes/bed_lb/src/sensors/retry.rs diff --git a/sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs b/sensor-nodes/bed_lb/src/sensors/retry/reinit_on_error.rs similarity index 100% rename from sensor-nodes/bed-sensors/src/sensors/retry/reinit_on_error.rs rename to sensor-nodes/bed_lb/src/sensors/retry/reinit_on_error.rs diff --git a/sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs b/sensor-nodes/bed_lb/src/sensors/retry/retry_init.rs similarity index 100% rename from sensor-nodes/bed-sensors/src/sensors/retry/retry_init.rs rename to sensor-nodes/bed_lb/src/sensors/retry/retry_init.rs diff --git a/sensor-nodes/bed-sensors/src/sensors/slow.rs b/sensor-nodes/bed_lb/src/sensors/slow.rs similarity index 100% rename from sensor-nodes/bed-sensors/src/sensors/slow.rs rename to sensor-nodes/bed_lb/src/sensors/slow.rs diff --git a/sensor-nodes/bed-sensors/stm32f401.svd b/sensor-nodes/bed_lb/stm32f401.svd similarity index 100% rename from sensor-nodes/bed-sensors/stm32f401.svd rename to sensor-nodes/bed_lb/stm32f401.svd From a344fab6c65ebbc0acbd3095a7aea40fec583279 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 23 Sep 2024 17:11:37 +0200 Subject: [PATCH 279/687] data-server/api add check_send_encoded for sending already encoded protocol::msg --- crates/data-server/src/api/data_source.rs | 24 +++++++- .../src/api/data_source/reconnecting.rs | 60 ++++++++++--------- crates/protocol/src/msg.rs | 23 ++++++- 3 files changed, 78 insertions(+), 29 deletions(-) diff --git a/crates/data-server/src/api/data_source.rs b/crates/data-server/src/api/data_source.rs index dc8110b6..6a7ff4df 100644 --- a/crates/data-server/src/api/data_source.rs +++ b/crates/data-server/src/api/data_source.rs @@ -1,4 +1,4 @@ -use protocol::affector; +use protocol::{affector, DecodeMsgError}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf}; use tokio::net::{TcpStream, ToSocketAddrs}; @@ -71,6 +71,16 @@ impl Client { self.sender.send_error(report).await } + /// Checks if the encoded message can be decoded then sends it. + pub async fn check_send_encoded(&mut self, msg: &[u8]) -> Result<(), SendPreEncodedError> { + protocol::Msg::<50>::decode(msg.to_vec()).map_err(SendPreEncodedError::EncodingCheck)?; + self.send_bytes(msg).await.map_err(SendPreEncodedError::Io) + } + + pub(crate) async fn send_bytes(&mut self, bytes: &[u8]) -> Result<(), std::io::Error> { + self.sender.send_bytes(bytes).await + } + pub fn split(self) -> (Sender, Receiver) { (self.sender, self.receiver) } @@ -83,7 +93,19 @@ pub struct Receiver { buffer: Vec, } +#[derive(Debug, thiserror::Error)] +pub enum SendPreEncodedError { + #[error("Ran into io error while sending pre-encoded msg: {0}")] + Io(std::io::Error), + #[error("Pre-encoded message, could not be decoded it might be from a previous version: {0}")] + EncodingCheck(DecodeMsgError), +} + impl Sender { + pub(crate) async fn send_bytes(&mut self, bytes: &[u8]) -> Result<(), std::io::Error> { + self.0.write_all(&bytes).await + } + pub async fn send_reading(&mut self, reading: protocol::Reading) -> Result<(), std::io::Error> { let mut readings = protocol::SensorMessage::<1>::default(); readings diff --git a/crates/data-server/src/api/data_source/reconnecting.rs b/crates/data-server/src/api/data_source/reconnecting.rs index 07dd621a..672b529d 100644 --- a/crates/data-server/src/api/data_source/reconnecting.rs +++ b/crates/data-server/src/api/data_source/reconnecting.rs @@ -3,6 +3,8 @@ use std::time::Duration; use tokio::time::{sleep, timeout}; use tracing::{info, warn}; +use super::SendPreEncodedError; + pub struct Client { retry_period: Duration, connection: Option, @@ -11,7 +13,7 @@ pub struct Client { } impl Client { - /// Needs a list of the affectors that can be controlled through this + /// Needs a list of the affectors that can be controlled through this /// node as an argument. If your node provides not controllable affectors /// pass in an empty Vec. #[must_use] @@ -24,19 +26,16 @@ impl Client { } } - /// # Cancel safety - /// This is cancel safe however the connection will need to be re-established - /// the next time its called. This will retry forever, you should call this - /// in a timeout future if that is a problem. - pub async fn send_reading(&mut self, reading: protocol::Reading) { + async fn send_bytes(&mut self, bytes: &[u8]) { loop { let mut conn = if let Some(conn) = self.connection.take() { conn } else { - get_connection_or_reconnect(self.addr, &self.affectors, &mut self.retry_period).await + get_connection_or_reconnect(self.addr, &self.affectors, &mut self.retry_period) + .await }; - match conn.send_reading(reading.clone()).await { + match conn.send_bytes(bytes).await { Ok(msg) => { self.retry_period /= 2; self.retry_period = self.retry_period.max(Duration::from_millis(200)); @@ -54,26 +53,33 @@ impl Client { /// This is cancel safe however the connection will need to be re-established /// the next time its called. This will retry forever, you should call this /// in a timeout future if that is a problem. - pub async fn send_error(&mut self, error: protocol::Error) { - loop { - let mut conn = if let Some(conn) = self.connection.take() { - conn - } else { - get_connection_or_reconnect(self.addr, &self.affectors, &mut self.retry_period).await - }; + pub async fn send_reading(&mut self, reading: protocol::Reading) { + let mut readings = protocol::SensorMessage::<1>::default(); + readings + .values + .push(reading) + .expect("capacity allows one push"); + let msg = protocol::Msg::Readings(readings); + let bytes = msg.encode(); - match conn.send_error(error.clone()).await { - Ok(msg) => { - self.retry_period /= 2; - self.retry_period = self.retry_period.max(Duration::from_millis(200)); - self.connection = Some(conn); - return msg; - } - Err(issue) => { - warn!("Conn issue while sending new error: {issue}, reconnecting"); - } - }; - } + self.send_bytes(&bytes).await + } + + /// # Cancel safety + /// This is cancel safe however the connection will need to be re-established + /// the next time its called. This will retry forever, you should call this + /// in a timeout future if that is a problem. + pub async fn send_error(&mut self, report: protocol::Error) { + let msg = protocol::Msg::<1>::ErrorReport(protocol::ErrorReport::new(report)); + let bytes = msg.encode(); + + self.send_bytes(&bytes).await + } + + pub async fn check_send_encoded(&mut self, msg: &[u8]) -> Result<(), SendPreEncodedError> { + protocol::Msg::<50>::decode(msg.to_vec()).map_err(SendPreEncodedError::EncodingCheck)?; + self.send_bytes(&msg).await; + Ok(()) } } diff --git a/crates/protocol/src/msg.rs b/crates/protocol/src/msg.rs index 338e66d0..0009e0d9 100644 --- a/crates/protocol/src/msg.rs +++ b/crates/protocol/src/msg.rs @@ -4,7 +4,7 @@ pub(crate) mod error; pub(crate) mod sensor; #[derive(Debug)] -#[allow(clippy::large_enum_variant)] // can not use Box on embedded +#[allow(clippy::large_enum_variant)] // Can not use Box on embedded pub enum Msg { Readings(sensor::SensorMessage), ErrorReport(error::ErrorReport), @@ -59,6 +59,27 @@ impl Msg { bytes.insert(0, self.header()); bytes } + + #[must_use] + pub fn encode_slice<'a>(&self, buf: &'a mut [u8]) -> &'a mut [u8] { + match self { + Msg::Readings(msg) => { + buf[0] = Self::READINGS; + let len = msg.encode_slice(&mut buf[1..]).len(); + &mut buf[..1 + len] + } + Msg::ErrorReport(report) => { + buf[0] = Self::ERROR_REPORT; + let len = report.encode_slice(&mut buf[1..]).len(); + &mut buf[..1 + len] + } + Msg::AffectorList(list) => { + buf[0] = Self::AFFECTOR_LIST; + let len = list.encode_slice(&mut buf[1..]).len(); + &mut buf[..1 + len] + } + } + } } #[derive(Debug, Clone)] From 60daf301fa14a2609c70357598aa0ba3b4d17957 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 23 Sep 2024 18:01:41 +0200 Subject: [PATCH 280/687] add schema and host for usb based sensor node --- Cargo.toml | 2 +- .../{bed_lb => bed-lb}/.cargo/config.toml | 0 sensor-nodes/{bed_lb => bed-lb}/.gitignore | 0 sensor-nodes/{bed_lb => bed-lb}/Cargo.lock | 0 sensor-nodes/{bed_lb => bed-lb}/Cargo.toml | 0 sensor-nodes/{bed_lb => bed-lb}/build.rs | 0 sensor-nodes/{bed_lb => bed-lb}/output.txt | 0 .../{bed_lb => bed-lb}/rust-toolchain.toml | 0 .../{bed_lb => bed-lb}/src/channel.rs | 0 .../{bed_lb => bed-lb}/src/error_cache.rs | 0 sensor-nodes/{bed_lb => bed-lb}/src/main.rs | 0 .../{bed_lb => bed-lb}/src/network.rs | 0 .../{bed_lb => bed-lb}/src/rgb_led.rs | 0 sensor-nodes/{bed_lb => bed-lb}/src/rng.rs | 0 .../{bed_lb => bed-lb}/src/sensors.rs | 0 .../{bed_lb => bed-lb}/src/sensors/fast.rs | 0 .../{bed_lb => bed-lb}/src/sensors/retry.rs | 0 .../src/sensors/retry/reinit_on_error.rs | 0 .../src/sensors/retry/retry_init.rs | 0 .../{bed_lb => bed-lb}/src/sensors/slow.rs | 0 sensor-nodes/{bed_lb => bed-lb}/stm32f401.svd | 0 sensor-nodes/bed-sb/host/.cargo/config.toml | 5 + sensor-nodes/bed-sb/host/Cargo.lock | 2106 +++++++++++++++++ sensor-nodes/bed-sb/host/Cargo.toml | 24 + sensor-nodes/bed-sb/host/rust-toolchain.toml | 6 + sensor-nodes/bed-sb/host/src/main.rs | 115 + sensor-nodes/bed-sb/schema/Cargo.lock | 447 ++++ sensor-nodes/bed-sb/schema/Cargo.toml | 16 + sensor-nodes/bed-sb/schema/src/lib.rs | 53 + 29 files changed, 2773 insertions(+), 1 deletion(-) rename sensor-nodes/{bed_lb => bed-lb}/.cargo/config.toml (100%) rename sensor-nodes/{bed_lb => bed-lb}/.gitignore (100%) rename sensor-nodes/{bed_lb => bed-lb}/Cargo.lock (100%) rename sensor-nodes/{bed_lb => bed-lb}/Cargo.toml (100%) rename sensor-nodes/{bed_lb => bed-lb}/build.rs (100%) rename sensor-nodes/{bed_lb => bed-lb}/output.txt (100%) rename sensor-nodes/{bed_lb => bed-lb}/rust-toolchain.toml (100%) rename sensor-nodes/{bed_lb => bed-lb}/src/channel.rs (100%) rename sensor-nodes/{bed_lb => bed-lb}/src/error_cache.rs (100%) rename sensor-nodes/{bed_lb => bed-lb}/src/main.rs (100%) rename sensor-nodes/{bed_lb => bed-lb}/src/network.rs (100%) rename sensor-nodes/{bed_lb => bed-lb}/src/rgb_led.rs (100%) rename sensor-nodes/{bed_lb => bed-lb}/src/rng.rs (100%) rename sensor-nodes/{bed_lb => bed-lb}/src/sensors.rs (100%) rename sensor-nodes/{bed_lb => bed-lb}/src/sensors/fast.rs (100%) rename sensor-nodes/{bed_lb => bed-lb}/src/sensors/retry.rs (100%) rename sensor-nodes/{bed_lb => bed-lb}/src/sensors/retry/reinit_on_error.rs (100%) rename sensor-nodes/{bed_lb => bed-lb}/src/sensors/retry/retry_init.rs (100%) rename sensor-nodes/{bed_lb => bed-lb}/src/sensors/slow.rs (100%) rename sensor-nodes/{bed_lb => bed-lb}/stm32f401.svd (100%) create mode 100644 sensor-nodes/bed-sb/host/.cargo/config.toml create mode 100644 sensor-nodes/bed-sb/host/Cargo.lock create mode 100644 sensor-nodes/bed-sb/host/Cargo.toml create mode 100644 sensor-nodes/bed-sb/host/rust-toolchain.toml create mode 100644 sensor-nodes/bed-sb/host/src/main.rs create mode 100644 sensor-nodes/bed-sb/schema/Cargo.lock create mode 100644 sensor-nodes/bed-sb/schema/Cargo.toml create mode 100644 sensor-nodes/bed-sb/schema/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 29456c2e..98eb24d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [workspace] resolver = "2" members = ["crates/*"] -exclude = ["sensor-nodes/bed-sensors"] +exclude = ["sensor-nodes/bed-lb", "sensor-nodes/bed-sb/host", "sensor-nodes/bed-sb/node", "sensor-nodes/bed-sb/schema"] [workspace.dependencies] data-server = { path = "crates/data-server" } diff --git a/sensor-nodes/bed_lb/.cargo/config.toml b/sensor-nodes/bed-lb/.cargo/config.toml similarity index 100% rename from sensor-nodes/bed_lb/.cargo/config.toml rename to sensor-nodes/bed-lb/.cargo/config.toml diff --git a/sensor-nodes/bed_lb/.gitignore b/sensor-nodes/bed-lb/.gitignore similarity index 100% rename from sensor-nodes/bed_lb/.gitignore rename to sensor-nodes/bed-lb/.gitignore diff --git a/sensor-nodes/bed_lb/Cargo.lock b/sensor-nodes/bed-lb/Cargo.lock similarity index 100% rename from sensor-nodes/bed_lb/Cargo.lock rename to sensor-nodes/bed-lb/Cargo.lock diff --git a/sensor-nodes/bed_lb/Cargo.toml b/sensor-nodes/bed-lb/Cargo.toml similarity index 100% rename from sensor-nodes/bed_lb/Cargo.toml rename to sensor-nodes/bed-lb/Cargo.toml diff --git a/sensor-nodes/bed_lb/build.rs b/sensor-nodes/bed-lb/build.rs similarity index 100% rename from sensor-nodes/bed_lb/build.rs rename to sensor-nodes/bed-lb/build.rs diff --git a/sensor-nodes/bed_lb/output.txt b/sensor-nodes/bed-lb/output.txt similarity index 100% rename from sensor-nodes/bed_lb/output.txt rename to sensor-nodes/bed-lb/output.txt diff --git a/sensor-nodes/bed_lb/rust-toolchain.toml b/sensor-nodes/bed-lb/rust-toolchain.toml similarity index 100% rename from sensor-nodes/bed_lb/rust-toolchain.toml rename to sensor-nodes/bed-lb/rust-toolchain.toml diff --git a/sensor-nodes/bed_lb/src/channel.rs b/sensor-nodes/bed-lb/src/channel.rs similarity index 100% rename from sensor-nodes/bed_lb/src/channel.rs rename to sensor-nodes/bed-lb/src/channel.rs diff --git a/sensor-nodes/bed_lb/src/error_cache.rs b/sensor-nodes/bed-lb/src/error_cache.rs similarity index 100% rename from sensor-nodes/bed_lb/src/error_cache.rs rename to sensor-nodes/bed-lb/src/error_cache.rs diff --git a/sensor-nodes/bed_lb/src/main.rs b/sensor-nodes/bed-lb/src/main.rs similarity index 100% rename from sensor-nodes/bed_lb/src/main.rs rename to sensor-nodes/bed-lb/src/main.rs diff --git a/sensor-nodes/bed_lb/src/network.rs b/sensor-nodes/bed-lb/src/network.rs similarity index 100% rename from sensor-nodes/bed_lb/src/network.rs rename to sensor-nodes/bed-lb/src/network.rs diff --git a/sensor-nodes/bed_lb/src/rgb_led.rs b/sensor-nodes/bed-lb/src/rgb_led.rs similarity index 100% rename from sensor-nodes/bed_lb/src/rgb_led.rs rename to sensor-nodes/bed-lb/src/rgb_led.rs diff --git a/sensor-nodes/bed_lb/src/rng.rs b/sensor-nodes/bed-lb/src/rng.rs similarity index 100% rename from sensor-nodes/bed_lb/src/rng.rs rename to sensor-nodes/bed-lb/src/rng.rs diff --git a/sensor-nodes/bed_lb/src/sensors.rs b/sensor-nodes/bed-lb/src/sensors.rs similarity index 100% rename from sensor-nodes/bed_lb/src/sensors.rs rename to sensor-nodes/bed-lb/src/sensors.rs diff --git a/sensor-nodes/bed_lb/src/sensors/fast.rs b/sensor-nodes/bed-lb/src/sensors/fast.rs similarity index 100% rename from sensor-nodes/bed_lb/src/sensors/fast.rs rename to sensor-nodes/bed-lb/src/sensors/fast.rs diff --git a/sensor-nodes/bed_lb/src/sensors/retry.rs b/sensor-nodes/bed-lb/src/sensors/retry.rs similarity index 100% rename from sensor-nodes/bed_lb/src/sensors/retry.rs rename to sensor-nodes/bed-lb/src/sensors/retry.rs diff --git a/sensor-nodes/bed_lb/src/sensors/retry/reinit_on_error.rs b/sensor-nodes/bed-lb/src/sensors/retry/reinit_on_error.rs similarity index 100% rename from sensor-nodes/bed_lb/src/sensors/retry/reinit_on_error.rs rename to sensor-nodes/bed-lb/src/sensors/retry/reinit_on_error.rs diff --git a/sensor-nodes/bed_lb/src/sensors/retry/retry_init.rs b/sensor-nodes/bed-lb/src/sensors/retry/retry_init.rs similarity index 100% rename from sensor-nodes/bed_lb/src/sensors/retry/retry_init.rs rename to sensor-nodes/bed-lb/src/sensors/retry/retry_init.rs diff --git a/sensor-nodes/bed_lb/src/sensors/slow.rs b/sensor-nodes/bed-lb/src/sensors/slow.rs similarity index 100% rename from sensor-nodes/bed_lb/src/sensors/slow.rs rename to sensor-nodes/bed-lb/src/sensors/slow.rs diff --git a/sensor-nodes/bed_lb/stm32f401.svd b/sensor-nodes/bed-lb/stm32f401.svd similarity index 100% rename from sensor-nodes/bed_lb/stm32f401.svd rename to sensor-nodes/bed-lb/stm32f401.svd diff --git a/sensor-nodes/bed-sb/host/.cargo/config.toml b/sensor-nodes/bed-sb/host/.cargo/config.toml new file mode 100644 index 00000000..0127ae27 --- /dev/null +++ b/sensor-nodes/bed-sb/host/.cargo/config.toml @@ -0,0 +1,5 @@ +[target.aarch64-unknown-linux-musl] +rustflags = ["-Clinker=rust-lld"] + +[target.armv7-unknown-linux-musleabihf] +rustflags = ["-Clinker=rust-lld"] diff --git a/sensor-nodes/bed-sb/host/Cargo.lock b/sensor-nodes/bed-sb/host/Cargo.lock new file mode 100644 index 00000000..8ce9d5ac --- /dev/null +++ b/sensor-nodes/bed-sb/host/Cargo.lock @@ -0,0 +1,2106 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" + +[[package]] +name = "cc" +version = "1.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + +[[package]] +name = "color-eyre" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + +[[package]] +name = "cordyceps" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec10f0a762d93c4498d2e97a333805cb6250d60bead623f71d8034f9a4152ba3" +dependencies = [ + "loom 0.5.6", + "tracing", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "critical-section" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.77", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "data-server" +version = "0.0.0" +dependencies = [ + "clap", + "color-eyre", + "futures", + "futures-concurrency", + "governor", + "protocol", + "rpc", + "serde", + "slotmap", + "socket2", + "thiserror", + "tokio", + "tokio-serde", + "tokio-stream", + "tokio-util", + "tracing", + "tracing-error", + "tracing-futures", + "tracing-subscriber", +] + +[[package]] +name = "defmt" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb" +dependencies = [ + "defmt-parser", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "defmt-parser" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" +dependencies = [ + "thiserror", +] + +[[package]] +name = "diatomic-waker" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab03c107fafeb3ee9f5925686dbb7a73bc76e3932abb0d2b365cb64b169cf04c" + +[[package]] +name = "educe" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4bd92664bf78c4d3dba9b7cdafce6fa15b13ed3ed16175218196942e99168a8" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "enum-ordinalize" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-buffered" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91fa130f3777d0d4b0993653c20bc433026d3290627693c4ed1b18dd237357ab" +dependencies = [ + "diatomic-waker", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-concurrency" +version = "7.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b14ac911e85d57c5ea6eef76d7b4d4a3177ecd15f4bea2e61927e9e3823e19f" +dependencies = [ + "bitvec", + "futures-buffered", + "futures-core", + "futures-lite", + "pin-project", + "slab", + "smallvec", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows 0.48.0", +] + +[[package]] +name = "generator" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb949699c3e4df3a183b1d2142cb24277057055ed23c68ed58894f76c517223" +dependencies = [ + "cfg-if", + "libc", + "log", + "rustversion", + "windows 0.58.0", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "governor" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b" +dependencies = [ + "cfg-if", + "dashmap", + "futures", + "futures-timer", + "no-std-compat", + "nonzero_ext", + "parking_lot", + "portable-atomic", + "quanta", + "rand", + "smallvec", + "spinning_top", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version", + "serde", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "defmt", + "hash32 0.3.1", + "serde", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "host" +version = "0.1.0" +dependencies = [ + "clap", + "data-server", + "heapless 0.8.0", + "postcard", + "postcard-rpc", + "protocol", + "ratelimited-logger", + "schema", + "tokio", + "tracing", + "tracing-error", + "tracing-subscriber", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-kit-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b" +dependencies = [ + "core-foundation-sys", + "mach2", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator 0.7.5", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator 0.8.3", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + +[[package]] +name = "maitake-sync" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6816ab14147f80234c675b80ed6dc4f440d8a1cefc158e766067aedb84c0bcd5" +dependencies = [ + "cordyceps", + "loom 0.7.2", + "mycelium-bitfield", + "pin-project", + "portable-atomic", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "mycelium-bitfield" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e0cc5e2c585acbd15c5ce911dff71e1f4d5313f43345873311c4f5efd741cc" + +[[package]] +name = "no-std-compat" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" + +[[package]] +name = "nonzero_ext" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "nusb" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ac267a828c32759883a6097809fc4c32d76925099725aae562717cb023b431c" +dependencies = [ + "atomic-waker", + "core-foundation", + "core-foundation-sys", + "io-kit-sys", + "log", + "once_cell", + "rustix", + "slab", + "windows-sys 0.48.0", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "portable-atomic" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce" + +[[package]] +name = "postcard" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "heapless 0.7.17", + "postcard-derive", + "serde", +] + +[[package]] +name = "postcard-derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0239fa9c1d225d4b7eb69925c25c5e082307a141e470573fbbe3a817ce6a7a37" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "postcard-rpc" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b6bf6dce5532b37ad9ce1dfc70e8f892f3c241306cdd2952d5156f9b35f43a" +dependencies = [ + "heapless 0.8.0", + "maitake-sync", + "nusb", + "postcard", + "serde", + "thiserror", + "tokio", + "tracing", + "trait-variant", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "protocol" +version = "0.1.0" +dependencies = [ + "defmt", + "heapless 0.8.0", + "postcard", + "serde", + "strum", + "thiserror", +] + +[[package]] +name = "quanta" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi", + "web-sys", + "winapi", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "ratelimited-logger" +version = "0.1.0" +dependencies = [ + "governor", + "tracing", + "tracing-error", + "tracing-subscriber", +] + +[[package]] +name = "raw-cpuid" +version = "11.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb9ee317cfe3fbd54b36a511efc1edd42e216903c9cd575e686dd68a2ba90d8d" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "redox_syscall" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "rpc" +version = "0.1.0" +dependencies = [ + "color-eyre", + "futures", + "governor", + "ratelimited-logger", + "serde", + "thiserror", + "tokio", + "tokio-serde", + "tokio-util", + "tracing", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "schema" +version = "0.1.0" +dependencies = [ + "heapless 0.8.0", + "postcard", + "postcard-rpc", + "protocol", + "serde", + "serde_with", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "serde_with" +version = "3.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +dependencies = [ + "serde", + "serde_derive", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "3.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spinning_top" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.77", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "tokio-serde" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf600e7036b17782571dd44fa0a5cea3c82f60db5137f774a325a76a0d6852b" +dependencies = [ + "bincode", + "bytes", + "educe", + "futures-core", + "futures-sink", + "pin-project", + "serde", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "trait-variant" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.77", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] diff --git a/sensor-nodes/bed-sb/host/Cargo.toml b/sensor-nodes/bed-sb/host/Cargo.toml new file mode 100644 index 00000000..89cada28 --- /dev/null +++ b/sensor-nodes/bed-sb/host/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "host" +version = "0.1.0" +rust-version = "1.78" +edition = "2021" +license = "GPLv3" +authors = ["David Kleingeld & Eva van Houten"] + +[dependencies] +heapless = "0.8.0" +postcard = { version = "1.0.10", features = ["experimental-derive"] } +postcard-rpc = { version = "0.7.0", features = ["raw-nusb"] } + +protocol = { path = "../../../crates/protocol" } +data-server = { path = "../../../crates/data-server", features = ["api"] } +ratelimited-logger = { path = "../../../crates/ratelimited-logger" } + +schema = { path = "../schema" } +tokio = { version = "1.40.0", features = ["macros", "net", "rt-multi-thread", "time"] } +clap = { version = "4.5.18", features = ["derive"] } +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +tracing-error = "0.2.0" +tracing = "0.1.40" + diff --git a/sensor-nodes/bed-sb/host/rust-toolchain.toml b/sensor-nodes/bed-sb/host/rust-toolchain.toml new file mode 100644 index 00000000..42e5cea4 --- /dev/null +++ b/sensor-nodes/bed-sb/host/rust-toolchain.toml @@ -0,0 +1,6 @@ +[toolchain] +channel = "stable" +components = [ "rust-src", "rustfmt", "llvm-tools" ] +targets = [ + "x86_64-unknown-linux-gnu", +] diff --git a/sensor-nodes/bed-sb/host/src/main.rs b/sensor-nodes/bed-sb/host/src/main.rs new file mode 100644 index 00000000..a7be5d5b --- /dev/null +++ b/sensor-nodes/bed-sb/host/src/main.rs @@ -0,0 +1,115 @@ +use std::{net::SocketAddr, time::Duration}; + +use clap::Parser; + +use postcard_rpc::{ + host_client::{HostClient, IoClosed, Subscription}, + standard_icd::{WireError, ERROR_PATH}, +}; + +use data_server::api::data_source; +use schema::ProtocolMsg; +use schema::ProtocolTopic; +use tokio::time::sleep; + +#[derive(Parser)] +#[command(name = "local sensors")] +#[command(version = "1.0")] +#[command(about = "reads sensors attached to rpi gpio pins and i2c perhipheral")] +struct Cli { + /// Where to send the data on the local system + #[arg(short, long("data-server"))] + data_server: SocketAddr, + /// Serial number of the device to connect case insensitive + #[arg(short, long)] + serial_number: String, +} + +struct ReconnectingUsbSub { + serial_number: String, + conn: Option>, + sub: Option>, + logger: ratelimited_logger::RateLimitedLogger, +} + +impl ReconnectingUsbSub { + fn new(serial_number: String) -> Self { + ReconnectingUsbSub { + serial_number, + conn: None, + sub: None, + logger: ratelimited_logger::RateLimitedLogger::new(), + } + } + + async fn recv(&mut self) -> ProtocolMsg { + loop { + if let Some(sub) = &mut self.sub { + match sub.recv().await { + Some(msg) => return msg, + None => self.sub = None, + } + } + + if let Some(conn) = &mut self.conn { + match conn.subscribe::(8).await { + Ok(sub) => { + self.sub = Some(sub); + continue; + } + Err(IoClosed) => self.conn = None, + } + } + + match HostClient::try_new_raw_nusb( + |d| { + d.serial_number() + .is_some_and(|d| d.eq_ignore_ascii_case(&self.serial_number)) + }, + ERROR_PATH, + 1, + ) { + Ok(conn) => self.conn = Some(conn), + Err(e) => { + let logger = &mut self.logger; + ratelimited_logger::warn!(logger; "Could not connect to usbdevice: {e:?}"); + sleep(Duration::from_secs(1)).await; + } + } + } + } +} + +#[tokio::main(flavor = "current_thread")] +async fn main() { + setup_tracing(); + let args = Cli::parse(); + + let mut usb = ReconnectingUsbSub::new(args.serial_number); + let mut server_client = data_source::reconnecting::Client::new(args.data_server, Vec::new()); + + loop { + let msg = usb.recv().await; + let encoded_protocol_msg = msg.0; + server_client + .check_send_encoded(&encoded_protocol_msg) + .await + .expect("Should be correctly encoded"); + } +} + +fn setup_tracing() { + use tracing_error::ErrorLayer; + use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt, Layer}; + + let file_subscriber = tracing_subscriber::fmt::layer() + .with_file(true) + .with_line_number(true) + .with_target(false) + .with_ansi(false) + .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()); + tracing_subscriber::registry() + .with(file_subscriber) + .with(ErrorLayer::default()) + .init(); +} diff --git a/sensor-nodes/bed-sb/schema/Cargo.lock b/sensor-nodes/bed-sb/schema/Cargo.lock new file mode 100644 index 00000000..738ae200 --- /dev/null +++ b/sensor-nodes/bed-sb/schema/Cargo.lock @@ -0,0 +1,447 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + +[[package]] +name = "critical-section" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.77", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "defmt" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0" +dependencies = [ + "bitflags", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb" +dependencies = [ + "defmt-parser", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "defmt-parser" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" +dependencies = [ + "thiserror", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version", + "serde", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "defmt", + "hash32 0.3.1", + "serde", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "postcard" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" +dependencies = [ + "cobs", + "heapless 0.7.17", + "postcard-derive", + "serde", +] + +[[package]] +name = "postcard-derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0239fa9c1d225d4b7eb69925c25c5e082307a141e470573fbbe3a817ce6a7a37" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "postcard-rpc" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b6bf6dce5532b37ad9ce1dfc70e8f892f3c241306cdd2952d5156f9b35f43a" +dependencies = [ + "heapless 0.8.0", + "postcard", + "serde", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "protocol" +version = "0.1.0" +dependencies = [ + "defmt", + "heapless 0.8.0", + "postcard", + "serde", + "strum", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "schema" +version = "0.1.0" +dependencies = [ + "heapless 0.8.0", + "postcard", + "postcard-rpc", + "protocol", + "serde", + "serde_with", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "serde_with" +version = "3.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +dependencies = [ + "serde", + "serde_derive", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "3.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.77", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" diff --git a/sensor-nodes/bed-sb/schema/Cargo.toml b/sensor-nodes/bed-sb/schema/Cargo.toml new file mode 100644 index 00000000..9d8e19b0 --- /dev/null +++ b/sensor-nodes/bed-sb/schema/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "schema" +version = "0.1.0" +rust-version = "1.78" +edition = "2021" +license = "GPLv3" +authors = ["David Kleingeld & Eva van Houten"] + +[dependencies] +heapless = "0.8.0" +postcard = { version = "1.0.10", features = ["experimental-derive"] } +postcard-rpc = "0.7.0" + +protocol = { path = "../../../crates/protocol" } +serde = { version = "1.0.210", features = ["derive"], default-features = false } +serde_with = { version = "3.9.0", features = ["macros"], default-features = false } diff --git a/sensor-nodes/bed-sb/schema/src/lib.rs b/sensor-nodes/bed-sb/schema/src/lib.rs new file mode 100644 index 00000000..27a9ed97 --- /dev/null +++ b/sensor-nodes/bed-sb/schema/src/lib.rs @@ -0,0 +1,53 @@ +#![no_std] + +use postcard::experimental::schema::Schema; +use postcard_rpc::topic; +use serde::{Deserialize, Serialize}; +use serde_with::{serde_as, Bytes}; + +topic!(ProtocolTopic, ProtocolMsg, "protocol"); + +// Unfortunately postcard::Schema is not a thing on heapless_vec +// so we have to try things differently +// +// also serde cannot handle >32 arrays so we gotta use a helper crate +#[serde_as] +#[derive(Schema, Serialize, Deserialize)] +pub struct StackVec { + #[serde_as(as = "Bytes")] + bytes: [u8; 250], + len: u8, +} + +impl StackVec { + fn new() -> Self { + StackVec { + bytes: [0u8; 250], + len: 0, + } + } + fn as_slice(&self) -> &[u8] { + &self.bytes[..self.len as usize] + } +} + +impl core::ops::Deref for StackVec { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + self.as_slice() + } +} + +/// contains an encoded protocol::Msg +#[derive(Schema, Deserialize, Serialize)] +pub struct ProtocolMsg(pub StackVec); + +impl From> for ProtocolMsg { + fn from(value: protocol::Msg) -> Self { + let mut vec = StackVec::new(); + let len = value.encode_slice(&mut vec.bytes).len(); + vec.len = len as u8; + ProtocolMsg(vec) + } +} From c4b7bdb7055e06e97b0822e6f8a217142487207d Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 24 Sep 2024 15:41:31 +0200 Subject: [PATCH 281/687] further integration of postcard-rpc --- sensor-nodes/bed-sb/schema/src/lib.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/sensor-nodes/bed-sb/schema/src/lib.rs b/sensor-nodes/bed-sb/schema/src/lib.rs index 27a9ed97..f30c65e6 100644 --- a/sensor-nodes/bed-sb/schema/src/lib.rs +++ b/sensor-nodes/bed-sb/schema/src/lib.rs @@ -20,15 +20,24 @@ pub struct StackVec { } impl StackVec { - fn new() -> Self { + pub fn new() -> Self { StackVec { bytes: [0u8; 250], len: 0, } } - fn as_slice(&self) -> &[u8] { + pub fn capacity(&self) -> usize { + self.bytes.len() + } + pub fn set_len(&mut self, len: usize) { + self.len = len.min(self.capacity()) as u8; + } + pub fn as_slice(&self) -> &[u8] { &self.bytes[..self.len as usize] } + pub fn as_mut_slice(&mut self) -> &mut [u8] { + &mut self.bytes[..self.len as usize] + } } impl core::ops::Deref for StackVec { @@ -39,6 +48,12 @@ impl core::ops::Deref for StackVec { } } +impl core::ops::DerefMut for StackVec { + fn deref_mut(&mut self) -> &mut Self::Target { + self.as_mut_slice() + } +} + /// contains an encoded protocol::Msg #[derive(Schema, Deserialize, Serialize)] pub struct ProtocolMsg(pub StackVec); From 9c72ef878edba854aa0dc5e152257607eab5f4c8 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 24 Sep 2024 18:23:07 +0200 Subject: [PATCH 282/687] add small bedroom bed sensor node --- crates/protocol/src/affector.rs | 6 +++-- crates/protocol/src/small_bedroom.rs | 40 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/crates/protocol/src/affector.rs b/crates/protocol/src/affector.rs index 23b8d868..0b93f738 100644 --- a/crates/protocol/src/affector.rs +++ b/crates/protocol/src/affector.rs @@ -6,7 +6,7 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; use crate::msg::cobs_overhead; -use crate::{large_bedroom, DecodeMsgError}; +use crate::{large_bedroom, small_bedroom, DecodeMsgError}; #[cfg(feature = "alloc")] pub mod tree; @@ -27,10 +27,11 @@ pub mod tree; #[strum_discriminants(derive(Hash))] pub enum Affector { LargeBedroom(large_bedroom::Affector), + SmallBedroom(small_bedroom::Affector), } #[cfg(feature = "alloc")] -tree::all_nodes! {Affector; AffectorDiscriminants; LargeBedroom} +tree::all_nodes! {Affector; AffectorDiscriminants; LargeBedroom, SmallBedroom} #[cfg(feature = "alloc")] #[derive(Debug, Clone)] @@ -72,6 +73,7 @@ impl Affector { pub fn controls(&mut self) -> Vec { match self { Affector::LargeBedroom(a) => a.controls(), + Affector::SmallBedroom(a) => a.controls(), } } } diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index fa8a123c..1ea3db56 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -5,9 +5,12 @@ use serde::{Deserialize, Serialize}; use crate::button::Press; #[cfg(feature = "alloc")] +use crate::affector; +#[cfg(feature = "alloc")] use crate::reading::tree::{Item, Tree}; pub mod desk; +pub mod bed; crate::button_enum! { /// +-----------------------------------------+ @@ -41,6 +44,7 @@ crate::button_enum! { pub enum Reading { ButtonPanel(ButtonPanel) = 0, Desk(desk::Reading) = 1, + Bed(bed::Reading) = 2, } #[cfg(feature = "alloc")] @@ -49,6 +53,7 @@ impl Tree for Reading { match self { Reading::ButtonPanel(inner) => return Item::Node(inner), Reading::Desk(inner) => return Item::Node(inner), + Reading::Bed(inner) => return Item::Node(inner), } } @@ -81,6 +86,7 @@ impl Reading { )] pub enum Error { Desk(desk::Error), + Bed(bed::Error), } impl Error { @@ -88,6 +94,7 @@ impl Error { pub fn device(&self) -> Device { match self { Error::Desk(error) => Device::Desk(error.device()), + Error::Bed(error) => Device::Bed(error.device()), } } } @@ -96,6 +103,7 @@ impl core::fmt::Display for Error { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { Error::Desk(error) => write!(f, "{error}"), + Error::Bed(error) => write!(f, "{error}"), } } } @@ -104,6 +112,7 @@ impl core::fmt::Display for Error { pub enum Device { Gpio, Desk(desk::Device), + Bed(bed::Device), } macro_rules! tree { @@ -136,6 +145,37 @@ impl Device { max_sample_interval: Duration::MAX, }, Device::Desk(device) => device.info(), + Device::Bed(device) => device.info(), + } + } +} + +#[derive( + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, + Eq, + Hash, +)] +#[strum_discriminants(derive(Hash))] +pub enum Affector { + Bed(bed::Affector), +} + +impl Affector { + #[cfg(feature = "alloc")] + pub(crate) fn controls(&mut self) -> Vec { + match self { + Affector::Bed(a) => a.controls(), } } } + +#[cfg(feature = "alloc")] +affector::tree::all_nodes! {Affector; AffectorDiscriminants; Bed} From 35cff4c5f375915d1d1db41a6ccf12d46c8dfac5 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 25 Sep 2024 17:19:48 +0200 Subject: [PATCH 283/687] extends protocol with small bedroom sensors --- Cargo.lock | 1 + crates/protocol/Cargo.toml | 2 +- crates/protocol/src/affector.rs | 6 +- crates/protocol/src/msg.rs | 2 +- crates/protocol/src/small_bedroom/bed.rs | 530 +++++++++++++++++++++++ 5 files changed, 538 insertions(+), 3 deletions(-) create mode 100644 crates/protocol/src/small_bedroom/bed.rs diff --git a/Cargo.lock b/Cargo.lock index 26fe8a22..a0b10a96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2476,6 +2476,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" dependencies = [ "cobs", + "defmt", "embedded-io 0.4.0", "embedded-io 0.6.1", "heapless 0.7.17", diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index 6e6dae2f..aa740c14 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -10,7 +10,7 @@ authors.workspace = true [dependencies] serde = { version = "1.0", features = ["derive"], default-features = false } -postcard = { version = "1.0", features = ["experimental-derive"] } +postcard = { version = "1.0", features = ["experimental-derive", "use-defmt"] } heapless = { version = "0.8.0", features = ["serde", "defmt-03"] } strum = { version = "0.26.2", default-features = false, features = ["derive"] } thiserror = { workspace = true, optional = true } diff --git a/crates/protocol/src/affector.rs b/crates/protocol/src/affector.rs index 0b93f738..8c5c5513 100644 --- a/crates/protocol/src/affector.rs +++ b/crates/protocol/src/affector.rs @@ -59,7 +59,7 @@ pub struct Control<'a> { } impl Affector { - const ENCODED_SIZE: usize = + pub const ENCODED_SIZE: usize = Affector::POSTCARD_MAX_SIZE + cobs_overhead(Affector::POSTCARD_MAX_SIZE); #[cfg(feature = "alloc")] @@ -68,6 +68,10 @@ impl Affector { postcard::to_allocvec_cobs(self).expect("Encoding should not fail") } + pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { + postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeMsgError::CorruptEncoding) + } + // Info() is explicitly not defined, use the tree impl to get at it #[cfg(feature = "alloc")] pub fn controls(&mut self) -> Vec { diff --git a/crates/protocol/src/msg.rs b/crates/protocol/src/msg.rs index 0009e0d9..01b0615d 100644 --- a/crates/protocol/src/msg.rs +++ b/crates/protocol/src/msg.rs @@ -82,7 +82,7 @@ impl Msg { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, defmt::Format)] #[cfg_attr(feature = "thiserror", derive(thiserror::Error))] pub enum DecodeMsgError { #[cfg_attr(feature = "thiserror", error("Could not decode SensorMessage: {0}"))] diff --git a/crates/protocol/src/small_bedroom/bed.rs b/crates/protocol/src/small_bedroom/bed.rs new file mode 100644 index 00000000..9e6511aa --- /dev/null +++ b/crates/protocol/src/small_bedroom/bed.rs @@ -0,0 +1,530 @@ +use core::time::Duration; + +#[cfg(feature = "alloc")] +use crate::affector::{Control, ControlValue}; +use crate::button::Press; +#[cfg(feature = "alloc")] +use crate::reading::tree::{Id, Item, Tree}; +#[cfg(feature = "alloc")] +use crate::reading::Info; +#[cfg(feature = "alloc")] +use crate::{affector, Unit}; + +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +crate::button_enum! { + /// |-----------------------------------------| + /// | bed towards wall ^ | + /// | towards headboard -> | + /// +-----------------------------------------+ + /// | Left | LeftMiddle | RightMiddle | Right | + /// +-----------------------------------------+ + Button { + Left, + LeftMiddle, + RightMiddle, + Right, + } + crate::Device::SmallBedroom(crate::small_bedroom::Device::Bed(crate::small_bedroom::bed::Device::Gpio)); +} + +#[derive( + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, +)] +#[strum_discriminants(derive(Hash))] +#[repr(u8)] +pub enum Reading { + Button(Button) = 0, + Brightness(f32) = 1, + Temperature(f32) = 2, + Humidity(f32) = 3, + GassResistance(f32) = 4, // In Ohm + Pressure(f32) = 5, + /// Parts per million + Co2(u16) = 6, + /// Weight on the bed + Weight(u32) = 7, + + /// Mass Concentration PM1.0 \[μg/m³\] + MassPm1_0(f32) = 9, + /// Mass Concentration PM2.5 \[μg/m³\] + MassPm2_5(f32) = 10, + /// Mass Concentration PM4.0 \[μg/m³\] + MassPm4_0(f32) = 11, + /// Mass Concentration PM10 \[μg/m³\] + MassPm10(f32) = 12, + /// Number Concentration PM0.5 \[#/cm³\] + NumberPm0_5(f32) = 13, + /// Number Concentration PM1.0 \[#/cm³\] + NumberPm1_0(f32) = 14, + /// Number Concentration PM2.5 \[#/cm³\] + NumberPm2_5(f32) = 15, + /// Number Concentration PM4.0 \[#/cm³\] + NumberPm4_0(f32) = 16, + /// Number Concentration PM10 \[#/cm³\] + NumberPm10(f32) = 17, + /// Typical Particle Size8 \[μm\] + TypicalParticleSize(f32) = 18, +} + +#[cfg(feature = "alloc")] +impl Tree for Reading { + #[must_use] + #[allow(clippy::too_many_lines)] + #[allow(clippy::cast_precision_loss)] + fn inner(&self) -> Item<'_> { + let (val, device, range, resolution, unit, description) = match self { + Reading::Brightness(val) => ( + *val, + Device::Max44.rooted(), + 0.0..188_000.0, + 0.045, + Unit::Lux, + "Brightness", + ), + Reading::Temperature(val) => ( + *val, + Device::Sht31.rooted(), + -10.0..45.0, + 0.01, + Unit::C, + "Temperature", + ), + Reading::Humidity(val) => ( + *val, + Device::Sht31.rooted(), + 0.0..100.0, + 0.01, + Unit::RH, + "Relative humidity", + ), + // air quality: comp_gas = log(R_gas[ohm]) + 0.04 log(Ohm)/%rh * hum[%rh] + Reading::GassResistance(val) => ( + *val, + Device::Bme680.rooted(), + 0.0..1_000_000.0, + 1.0, + Unit::Ohm, + "Gass resistance", + ), + // record air pressure + // - 1.081hPa (dead sea 430 below normal sea level) + // - 870hPa (middle of a tornado) + Reading::Pressure(val) => ( + *val, + Device::Bme680.rooted(), + 87_000.0..108_100.0, + 0.18, + Unit::Pa, + "Air pressure", + ), + Reading::Co2(val) => ( + f32::from(*val), + Device::Mhz14.rooted(), + 400.0..2_000.0, + 1.0, + Unit::Ppm, + "Co2 concentration", + ), + Reading::Weight(val) => ( + *val as f32, + Device::Nau7802.rooted(), + 0.0..24.0_f32.exp2(), + 1.0, + Unit::Ohm, + "weight sensor resistance", + ), + Reading::Button(button) => return Item::Node(button), + Reading::MassPm1_0(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..1000.0, + 0.1, + Unit::MicrogramPerM3, + "Mass concentration particles between 0.3 to 1.0 μm", + ), + Reading::MassPm2_5(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..1000.0, + 0.1, + Unit::MicrogramPerM3, + "Mass concentration particles between 0.3 to 2.5 μm", + ), + Reading::MassPm4_0(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..1000.0, + 0.1, + Unit::MicrogramPerM3, + "Mass concentration particles between 0.3 to 4.0 μm", + ), + Reading::MassPm10(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..1000.0, + 0.1, + Unit::MicrogramPerM3, + "Mass concentration particles between 0.3 to 10.0 μm", + ), + Reading::NumberPm0_5(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..3000.0, + 0.1, + Unit::NumberPerCm3, + "Concentration of particles between 0.3 to 0.5 μm", + ), + Reading::NumberPm1_0(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..3000.0, + 0.1, + Unit::NumberPerCm3, + "Concentration of particles between 0.3 to 1.0 μm", + ), + Reading::NumberPm2_5(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..3000.0, + 0.1, + Unit::NumberPerCm3, + "Concentration of particles between 0.3 to 2.5 μm", + ), + Reading::NumberPm4_0(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..3000.0, + 0.1, + Unit::NumberPerCm3, + "Concentration of particles between 0.3 to 4.0 μm", + ), + Reading::NumberPm10(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..3000.0, + 0.1, + Unit::NumberPerCm3, + "Concentration of particles between 0.3 to 10.5 μm", + ), + Reading::TypicalParticleSize(val) => ( + *val, + Device::Sps30.rooted(), + 0.0..10_000.0, + 0.5, + Unit::NanoMeter, + "Typical particle size", + ), + }; + + Item::Leaf(Info { + val, + device, + resolution, + range, + unit, + description, + branch_id: self.branch_id(), + }) + } + + #[must_use] + fn branch_id(&self) -> Id { + ReadingDiscriminants::from(self) as Id + } +} + +impl Reading { + #[must_use] + pub fn is_same_as(&self, other: &Self) -> bool { + match (self, other) { + (Self::Brightness(_), Self::Brightness(_)) + | (Self::Temperature(_), Self::Temperature(_)) + | (Self::Humidity(_), Self::Humidity(_)) + | (Self::GassResistance(_), Self::GassResistance(_)) + | (Self::Pressure(_), Self::Pressure(_)) + | (Self::Co2(_), Self::Co2(_)) + | (Self::Weight(_), Self::Weight(0)) + | (Self::MassPm1_0(_), Self::MassPm1_0(_)) + | (Self::MassPm2_5(_), Self::MassPm2_5(_)) + | (Self::MassPm4_0(_), Self::MassPm4_0(_)) + | (Self::MassPm10(_), Self::MassPm10(_)) + | (Self::NumberPm0_5(_), Self::NumberPm0_5(_)) + | (Self::NumberPm1_0(_), Self::NumberPm1_0(_)) + | (Self::NumberPm2_5(_), Self::NumberPm2_5(_)) + | (Self::NumberPm4_0(_), Self::NumberPm4_0(_)) + | (Self::NumberPm10(_), Self::NumberPm10(_)) + | (Self::TypicalParticleSize(_), Self::TypicalParticleSize(_)) => true, + (Self::Button(a), Self::Button(b)) => a.is_same_as(b), + _ => false, + } + } +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +pub enum Error { + Running(SensorError), + Setup(SensorError), + SetupTimedOut(Device), + Timeout(Device), +} + +impl Error { + #[must_use] + pub(crate) fn device(&self) -> Device { + match self { + Self::Running(sensor_err) | Self::Setup(sensor_err) => sensor_err.device(), + Self::SetupTimedOut(device) | Self::Timeout(device) => device.clone(), + } + } +} + +impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Error::Running(e) => write!(f, "{e}"), + Error::Setup(e) => write!(f, "setup: {e}"), + Error::SetupTimedOut(_) => write!(f, "setup timed out"), + Error::Timeout(_) => write!(f, "timed out running"), + } + } +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, Eq, PartialEq)] +pub enum SensorError { + Sht31(heapless::String<200>), + Bme680(heapless::String<200>), + Max44(heapless::String<200>), + Mhz14(heapless::String<200>), + Sps30(heapless::String<200>), + Button(heapless::String<200>), + Nau7802(heapless::String<200>), +} + +impl core::fmt::Display for SensorError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + SensorError::Sht31(e) + | SensorError::Bme680(e) + | SensorError::Max44(e) + | SensorError::Mhz14(e) + | SensorError::Sps30(e) + | SensorError::Button(e) + | SensorError::Nau7802(e) => write!(f, "{e}"), + } + } +} + +impl MaxSize for SensorError { + const POSTCARD_MAX_SIZE: usize = 201; +} + +impl SensorError { + #[must_use] + pub fn device(&self) -> Device { + match self { + SensorError::Sht31(_) => Device::Sht31, + SensorError::Bme680(_) => Device::Bme680, + SensorError::Max44(_) => Device::Max44, + SensorError::Mhz14(_) => Device::Mhz14, + SensorError::Sps30(_) => Device::Sps30, + SensorError::Button(_) => Device::Gpio, + SensorError::Nau7802(_) => Device::Nau7802, + } + } +} + +#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq, Hash)] +pub enum Device { + Sht31, + Bme680, + Max44, + Mhz14, + Sps30, + Nau7802, + Gpio, +} + +impl core::fmt::Display for Device { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.info().name) + } +} + +macro_rules! tree { + [$thing:ident; $($item:expr),+] => { + [$(crate::$thing::SmallBedroom( + crate::small_bedroom::$thing::Bed($item), + )),+] + }; +} + +impl Device { + /// Note the order in which the `affects_readings` occur is the order in which + /// they will be stored, do not change it! + #[must_use] + pub const fn info(&self) -> crate::DeviceInfo { + let min_sample_interval = Duration::from_secs(5); + let max_sample_interval = Duration::from_secs(5); + let temporal_resolution = Duration::from_secs(1); + match self { + Device::Sht31 => crate::DeviceInfo { + name: "Sht31", + affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Humidity(0.0)], + temporal_resolution, + min_sample_interval, + max_sample_interval, + affectors: &[], + }, + Device::Bme680 => crate::DeviceInfo { + name: "Bme680", + affects_readings: &tree![Reading; + Reading::GassResistance(0.0), + Reading::Pressure(0.0) + ], + temporal_resolution, + min_sample_interval, + max_sample_interval, + affectors: &[], + }, + Device::Max44 => crate::DeviceInfo { + name: "Max44", + affects_readings: &tree![Reading; Reading::Brightness(0.0)], + temporal_resolution: Duration::from_millis(50), + min_sample_interval: Duration::from_millis(50), + max_sample_interval, + affectors: &[], + }, + Device::Mhz14 => crate::DeviceInfo { + name: "Mhz14", + affects_readings: &tree![Reading; Reading::Co2(0)], + temporal_resolution, + min_sample_interval, + max_sample_interval, + affectors: &tree!(Affector; Affector::MhzZeroPointCalib), + }, + Device::Sps30 => crate::DeviceInfo { + name: "Sps30", + affects_readings: &tree![Reading; + Reading::MassPm1_0(0.0), + Reading::MassPm2_5(0.0), + Reading::MassPm4_0(0.0), + Reading::MassPm10(0.0), + Reading::NumberPm0_5(0.0), + Reading::NumberPm1_0(0.0), + Reading::NumberPm2_5(0.0), + Reading::NumberPm4_0(0.0), + Reading::NumberPm10(0.0), + Reading::TypicalParticleSize(0.0) + ], + temporal_resolution, + min_sample_interval, + max_sample_interval, + affectors: &tree!(Affector; Affector::Sps30FanClean), + }, + Device::Nau7802 => crate::DeviceInfo { + name: "Nau7802Right", + affects_readings: &tree![Reading; Reading::Weight(0)], + temporal_resolution: Duration::from_millis(100), + min_sample_interval: Duration::from_millis(100), + max_sample_interval, + affectors: &tree!(Affector; Affector::Nau7802Calib), + }, + Device::Gpio => crate::DeviceInfo { + name: "Gpio", + affects_readings: &tree![Reading; + Reading::Button(Button::Left(Press(0))), + Reading::Button(Button::LeftMiddle(Press(0))), + Reading::Button(Button::RightMiddle(Press(0))), + Reading::Button(Button::Right(Press(0))) + ], + temporal_resolution: Duration::from_millis(1), + min_sample_interval: Duration::from_millis(2), + max_sample_interval: Duration::MAX, + affectors: &[], + }, + } + } + + #[cfg(feature = "alloc")] + #[must_use] + const fn rooted(self) -> crate::Device { + crate::Device::SmallBedroom(crate::small_bedroom::Device::Bed(self)) + } +} + +#[derive( + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, + Eq, + Hash, +)] +#[strum_discriminants(derive(Hash))] +pub enum Affector { + Sps30FanClean, + MhzZeroPointCalib, + Nau7802Calib, +} + +impl Affector { + #[must_use] + pub fn is_same_as(&self, other: &Self) -> bool { + match (self, other) { + (Affector::Sps30FanClean, Affector::Sps30FanClean) => true, + (Affector::MhzZeroPointCalib, Affector::MhzZeroPointCalib) => true, + (Affector::Nau7802Calib, Affector::Nau7802Calib) => true, + _ => false, + } + } + + #[cfg(feature = "alloc")] + pub fn controls(&mut self) -> Vec { + match self { + Affector::Sps30FanClean => vec![Control { + name: "start fan cleaning", + value: ControlValue::Trigger, + }], + Affector::MhzZeroPointCalib => vec![Control { + name: "calibrate current reading as 400 ppm", + value: ControlValue::Trigger, + }], + Affector::Nau7802Calib => vec![Control { + name: "things with ac power noise or something", + value: ControlValue::Trigger, + }], + } + } +} + +#[cfg(feature = "alloc")] +impl affector::tree::Tree for Affector { + fn inner(&self) -> affector::tree::Item<'_> { + let description = match self { + Affector::Sps30FanClean => "Accelerate the fan to maximum speed for 10 seconds in order to blow out the dust accumulated in the fan", + Affector::MhzZeroPointCalib => "Set the current co2 value as 400ppm", + Affector::Nau7802Calib => "Detect and correct power supply and temperature variations to ADC", + }; + + affector::tree::Item::Leaf(affector::Info { description }) + } + + fn branch_id(&self) -> affector::tree::Id { + AffectorDiscriminants::from(self) as Id + } +} From 03935aed905293e58fca71cd7750d00735499067 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 25 Sep 2024 17:21:42 +0200 Subject: [PATCH 284/687] removes postcard rpc in favor of raw usb for node/bed-sb --- .../usb_bridge}/.cargo/config.toml | 0 .../host => crates/usb_bridge}/Cargo.lock | 0 .../host => crates/usb_bridge}/Cargo.toml | 0 .../usb_bridge}/rust-toolchain.toml | 0 .../host => crates/usb_bridge}/src/main.rs | 0 sensor-nodes/bed-sb/.cargo/config.toml | 17 + sensor-nodes/bed-sb/Cargo.lock | 1274 + sensor-nodes/bed-sb/Cargo.toml | 68 + sensor-nodes/bed-sb/build.rs | 5 + sensor-nodes/bed-sb/output.txt | 19660 +++++++++ sensor-nodes/bed-sb/rust-toolchain.toml | 6 + sensor-nodes/bed-sb/schema/Cargo.lock | 447 - sensor-nodes/bed-sb/schema/Cargo.toml | 16 - sensor-nodes/bed-sb/schema/src/lib.rs | 68 - sensor-nodes/bed-sb/src/channel.rs | 132 + sensor-nodes/bed-sb/src/comms.rs | 142 + sensor-nodes/bed-sb/src/error_cache.rs | 57 + sensor-nodes/bed-sb/src/main.rs | 207 + sensor-nodes/bed-sb/src/sensors.rs | 149 + sensor-nodes/bed-sb/src/sensors/fast.rs | 165 + sensor-nodes/bed-sb/src/sensors/retry.rs | 127 + .../src/sensors/retry/reinit_on_error.rs | 117 + .../bed-sb/src/sensors/retry/retry_init.rs | 83 + sensor-nodes/bed-sb/src/sensors/slow.rs | 195 + sensor-nodes/bed-sb/src/usb_wrapper.rs | 229 + sensor-nodes/bed-sb/stm32f401.svd | 35196 ++++++++++++++++ 26 files changed, 57829 insertions(+), 531 deletions(-) rename {sensor-nodes/bed-sb/host => crates/usb_bridge}/.cargo/config.toml (100%) rename {sensor-nodes/bed-sb/host => crates/usb_bridge}/Cargo.lock (100%) rename {sensor-nodes/bed-sb/host => crates/usb_bridge}/Cargo.toml (100%) rename {sensor-nodes/bed-sb/host => crates/usb_bridge}/rust-toolchain.toml (100%) rename {sensor-nodes/bed-sb/host => crates/usb_bridge}/src/main.rs (100%) create mode 100644 sensor-nodes/bed-sb/.cargo/config.toml create mode 100644 sensor-nodes/bed-sb/Cargo.lock create mode 100644 sensor-nodes/bed-sb/Cargo.toml create mode 100644 sensor-nodes/bed-sb/build.rs create mode 100644 sensor-nodes/bed-sb/output.txt create mode 100644 sensor-nodes/bed-sb/rust-toolchain.toml delete mode 100644 sensor-nodes/bed-sb/schema/Cargo.lock delete mode 100644 sensor-nodes/bed-sb/schema/Cargo.toml delete mode 100644 sensor-nodes/bed-sb/schema/src/lib.rs create mode 100644 sensor-nodes/bed-sb/src/channel.rs create mode 100644 sensor-nodes/bed-sb/src/comms.rs create mode 100644 sensor-nodes/bed-sb/src/error_cache.rs create mode 100644 sensor-nodes/bed-sb/src/main.rs create mode 100644 sensor-nodes/bed-sb/src/sensors.rs create mode 100644 sensor-nodes/bed-sb/src/sensors/fast.rs create mode 100644 sensor-nodes/bed-sb/src/sensors/retry.rs create mode 100644 sensor-nodes/bed-sb/src/sensors/retry/reinit_on_error.rs create mode 100644 sensor-nodes/bed-sb/src/sensors/retry/retry_init.rs create mode 100644 sensor-nodes/bed-sb/src/sensors/slow.rs create mode 100644 sensor-nodes/bed-sb/src/usb_wrapper.rs create mode 100644 sensor-nodes/bed-sb/stm32f401.svd diff --git a/sensor-nodes/bed-sb/host/.cargo/config.toml b/crates/usb_bridge/.cargo/config.toml similarity index 100% rename from sensor-nodes/bed-sb/host/.cargo/config.toml rename to crates/usb_bridge/.cargo/config.toml diff --git a/sensor-nodes/bed-sb/host/Cargo.lock b/crates/usb_bridge/Cargo.lock similarity index 100% rename from sensor-nodes/bed-sb/host/Cargo.lock rename to crates/usb_bridge/Cargo.lock diff --git a/sensor-nodes/bed-sb/host/Cargo.toml b/crates/usb_bridge/Cargo.toml similarity index 100% rename from sensor-nodes/bed-sb/host/Cargo.toml rename to crates/usb_bridge/Cargo.toml diff --git a/sensor-nodes/bed-sb/host/rust-toolchain.toml b/crates/usb_bridge/rust-toolchain.toml similarity index 100% rename from sensor-nodes/bed-sb/host/rust-toolchain.toml rename to crates/usb_bridge/rust-toolchain.toml diff --git a/sensor-nodes/bed-sb/host/src/main.rs b/crates/usb_bridge/src/main.rs similarity index 100% rename from sensor-nodes/bed-sb/host/src/main.rs rename to crates/usb_bridge/src/main.rs diff --git a/sensor-nodes/bed-sb/.cargo/config.toml b/sensor-nodes/bed-sb/.cargo/config.toml new file mode 100644 index 00000000..161b3118 --- /dev/null +++ b/sensor-nodes/bed-sb/.cargo/config.toml @@ -0,0 +1,17 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +# replace STM32F103C8 with your chip as listed in `probe-rs chip list` +# runner = "probe-rs run --chip STM32F103C8" +runner = "probe-rs run --chip STM32F401CCUx" +linker = "flip-link" + +[build] +# target = "thumbv7m-none-eabi" for f103 +target = "thumbv7em-none-eabihf" + +[env] +DEFMT_LOG = "debug,sps30_async=warn,bosch_bme680=info" +EMBASSY_EXECUTOR_TASK_ARENA_SIZE="10900" + +# [unstable] +# build-std = ["core"] +# build-std-features = ["panic_immediate_abort"] diff --git a/sensor-nodes/bed-sb/Cargo.lock b/sensor-nodes/bed-sb/Cargo.lock new file mode 100644 index 00000000..50cd7987 --- /dev/null +++ b/sensor-nodes/bed-sb/Cargo.lock @@ -0,0 +1,1274 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aligned" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "377e4c0ba83e4431b10df45c1d4666f178ea9c552cac93e60c3a88bf32785923" +dependencies = [ + "as-slice", +] + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + +[[package]] +name = "bed-sensors" +version = "0.2.0" +dependencies = [ + "bosch-bme680", + "cortex-m", + "cortex-m-rt", + "defmt", + "defmt-rtt", + "embassy-embedded-hal", + "embassy-executor", + "embassy-futures", + "embassy-stm32", + "embassy-sync", + "embassy-time", + "embassy-usb", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-bus", + "embedded-io-async", + "futures", + "heapless 0.8.0", + "max44009", + "mhzx", + "nau7802-async", + "nb 1.1.0", + "panic-probe", + "protocol", + "rand", + "sht31", + "sps30-async", + "static_cell", +] + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "bitfield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "block-device-driver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c051592f59fe68053524b4c4935249b806f72c1f544cfb7abe4f57c3be258e" +dependencies = [ + "aligned", +] + +[[package]] +name = "bosch-bme680" +version = "1.0.2" +dependencies = [ + "bitfield 0.14.0", + "defmt", + "embedded-hal 1.0.0", + "embedded-hal-async", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal", + "bitfield 0.13.2", + "critical-section", + "embedded-hal 0.2.7", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "critical-section" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.77", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "defmt" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb" +dependencies = [ + "defmt-parser", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "defmt-parser" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" +dependencies = [ + "thiserror", +] + +[[package]] +name = "defmt-rtt" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab697b3dbbc1750b7c8b821aa6f6e7f2480b47a99bc057a2ed7b170ebef0c51" +dependencies = [ + "critical-section", + "defmt", +] + +[[package]] +name = "document-features" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" +dependencies = [ + "litrs", +] + +[[package]] +name = "embassy-embedded-hal" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "defmt", + "embassy-futures", + "embassy-sync", + "embassy-time", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-storage", + "embedded-storage-async", + "nb 1.1.0", +] + +[[package]] +name = "embassy-executor" +version = "0.6.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "cortex-m", + "critical-section", + "defmt", + "document-features", + "embassy-executor-macros", + "embassy-time-driver", + "embassy-time-queue-driver", +] + +[[package]] +name = "embassy-executor-macros" +version = "0.5.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "embassy-futures" +version = "0.1.1" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" + +[[package]] +name = "embassy-hal-internal" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "cortex-m", + "critical-section", + "defmt", + "num-traits", +] + +[[package]] +name = "embassy-net-driver" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "defmt", +] + +[[package]] +name = "embassy-net-driver-channel" +version = "0.3.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "embassy-futures", + "embassy-net-driver", + "embassy-sync", +] + +[[package]] +name = "embassy-stm32" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "aligned", + "bit_field", + "bitflags 2.6.0", + "block-device-driver", + "cfg-if", + "cortex-m", + "cortex-m-rt", + "critical-section", + "defmt", + "document-features", + "embassy-embedded-hal", + "embassy-futures", + "embassy-hal-internal", + "embassy-net-driver", + "embassy-sync", + "embassy-time", + "embassy-time-driver", + "embassy-usb-driver", + "embassy-usb-synopsys-otg", + "embedded-can", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-nb", + "embedded-io", + "embedded-io-async", + "embedded-storage", + "embedded-storage-async", + "futures-util", + "nb 1.1.0", + "proc-macro2", + "quote", + "rand_core", + "sdio-host", + "static_assertions", + "stm32-fmc", + "stm32-metapac", + "vcell", + "volatile-register", +] + +[[package]] +name = "embassy-sync" +version = "0.6.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "cfg-if", + "critical-section", + "defmt", + "embedded-io-async", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time" +version = "0.3.2" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "cfg-if", + "critical-section", + "defmt", + "document-features", + "embassy-time-driver", + "embassy-time-queue-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time-driver" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "document-features", +] + +[[package]] +name = "embassy-time-queue-driver" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" + +[[package]] +name = "embassy-usb" +version = "0.3.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "defmt", + "embassy-futures", + "embassy-net-driver-channel", + "embassy-sync", + "embassy-usb-driver", + "heapless 0.8.0", + "ssmarshal", + "usbd-hid", +] + +[[package]] +name = "embassy-usb-driver" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "defmt", +] + +[[package]] +name = "embassy-usb-synopsys-otg" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "critical-section", + "embassy-sync", + "embassy-usb-driver", +] + +[[package]] +name = "embedded-can" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "defmt", + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-hal-bus" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d3980bf28e8577db59fe2bdb3df868a419469d2cecb363644eea2b6f7797669" +dependencies = [ + "critical-section", + "defmt", + "embedded-hal 1.0.0", + "embedded-hal-async", + "portable-atomic", +] + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" +dependencies = [ + "embedded-hal 1.0.0", + "nb 1.1.0", +] + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-io-async" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" +dependencies = [ + "defmt", + "embedded-io", +] + +[[package]] +name = "embedded-storage" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" + +[[package]] +name = "embedded-storage-async" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc" +dependencies = [ + "embedded-storage", +] + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-macro", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version 0.4.1", + "serde", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "defmt", + "hash32 0.3.1", + "serde", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "max44009" +version = "0.2.0" +source = "git+https://github.com/dvdsk/max44009-rs#7b7df2e3173476c250fca3eb242f0dd366857599" +dependencies = [ + "defmt", + "embedded-hal-async", +] + +[[package]] +name = "mhzx" +version = "0.3.0" +dependencies = [ + "defmt", + "embedded-io-async", + "heapless 0.8.0", + "postcard", + "serde", +] + +[[package]] +name = "nau7802-async" +version = "0.2.0" +dependencies = [ + "byteorder", + "defmt", + "embedded-hal-async", + "postcard", + "serde", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "panic-probe" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4047d9235d1423d66cc97da7d07eddb54d4f154d6c13805c6d0793956f4f25b0" +dependencies = [ + "cortex-m", + "defmt", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "portable-atomic" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce" + +[[package]] +name = "postcard" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" +dependencies = [ + "cobs", + "defmt", + "heapless 0.7.17", + "postcard-derive", + "serde", +] + +[[package]] +name = "postcard-derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0239fa9c1d225d4b7eb69925c25c5e082307a141e470573fbbe3a817ce6a7a37" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "protocol" +version = "0.1.0" +dependencies = [ + "defmt", + "heapless 0.8.0", + "postcard", + "serde", + "strum", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver 1.0.23", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sdio-host" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93c025f9cfe4c388c328ece47d11a54a823da3b5ad0370b22d95ad47137f85a" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "sht31" +version = "0.3.1" +source = "git+https://github.com/dvdsk/SHT31-rs#a7b6bd94fb137e16bf326eff5fb591624369a2cf" +dependencies = [ + "crc", + "defmt", + "embedded-hal-async", + "postcard", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "sps30-async" +version = "0.3.0" +dependencies = [ + "defmt", + "embedded-hal-async", + "embedded-io-async", + "futures", + "heapless 0.8.0", + "postcard", + "serde", +] + +[[package]] +name = "ssmarshal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3e6ad23b128192ed337dfa4f1b8099ced0c2bf30d61e551b65fda5916dbb850" +dependencies = [ + "encode_unicode", + "serde", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "static_cell" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89b0684884a883431282db1e4343f34afc2ff6996fe1f4a1664519b66e14c1e" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "stm32-fmc" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f0639399e2307c2446c54d91d4f1596343a1e1d5cab605b9cce11d0ab3858c" +dependencies = [ + "embedded-hal 0.2.7", +] + +[[package]] +name = "stm32-metapac" +version = "15.0.0" +source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-ad00827345b4b758b2453082809d6e3b634b5364#e442835159a7a311410cd4a2879da52c6f57af52" +dependencies = [ + "cortex-m", + "cortex-m-rt", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.77", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "usb-device" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98816b1accafbb09085168b90f27e93d790b4bfa19d883466b5e53315b5f06a6" +dependencies = [ + "heapless 0.8.0", + "portable-atomic", +] + +[[package]] +name = "usbd-hid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6f291ab53d428685cc780f08a2eb9d5d6ff58622db2b36e239a4f715f1e184c" +dependencies = [ + "serde", + "ssmarshal", + "usb-device", + "usbd-hid-macros", +] + +[[package]] +name = "usbd-hid-descriptors" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee54712c5d778d2fb2da43b1ce5a7b5060886ef7b09891baeb4bf36910a3ed" +dependencies = [ + "bitfield 0.14.0", +] + +[[package]] +name = "usbd-hid-macros" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb573c76e7884035ac5e1ab4a81234c187a82b6100140af0ab45757650ccda38" +dependencies = [ + "byteorder", + "hashbrown", + "log", + "proc-macro2", + "quote", + "serde", + "syn 1.0.109", + "usbd-hid-descriptors", +] + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] diff --git a/sensor-nodes/bed-sb/Cargo.toml b/sensor-nodes/bed-sb/Cargo.toml new file mode 100644 index 00000000..5498d007 --- /dev/null +++ b/sensor-nodes/bed-sb/Cargo.toml @@ -0,0 +1,68 @@ +[package] +name = "bed-sensors" +version = "0.2.0" +rust-version = "1.78" +edition = "2021" +license = "GPLv3" +authors = ["David Kleingeld & Eva van Houten"] + +[dependencies] +embassy-stm32 = { version = "0.1.0", features = [ "defmt", "stm32f401cc", +"unstable-pac", "memory-x", "time-driver-tim9", "time", "exti" ] } +embassy-sync = { version = "0.6.0", features = ["defmt"] } +embassy-executor = { version = "0.6.0", features = ["arch-cortex-m", +"executor-thread", "defmt", "integrated-timers", "executor-interrupt"] } +embassy-embedded-hal = { version = "0.2.0" } +embassy-time = { version = "0.3.2", features = ["defmt", +"defmt-timestamp-uptime-ms", "tick-hz-32_768"] } +embassy-futures = { version = "0.1.0"} +embassy-usb = { version = "0.3.0", features = ["defmt"] } + +defmt = "0.3" +defmt-rtt = "0.4" + +cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } +cortex-m-rt = "0.7.0" +embedded-hal = "1.0.0" +embedded-hal-async = "1.0" +embedded-hal-bus = { version = "0.2", features = ["async", "defmt-03"] } +embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } +panic-probe = { version = "0.3", features = ["print-defmt"] } +futures = { version = "0.3.17", default-features = false, features = ["async-await"] } +heapless = { version = "0.8", default-features = false } +nb = "1.0.0" +rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } +static_cell = "2.0.0" + +# sensors +bosch-bme680 = { version = "1.0.2", path = "/home/david/Documents/async-bosch-bme680" } +max44009 = { version = "0.2", git = "https://github.com/dvdsk/max44009-rs" } +sht31 = { version = "0.3.0", git = "https://github.com/dvdsk/SHT31-rs", features = ["postcard"] } +mhzx = { version = "0.3.0", path = "/home/david/tmp/mh-zx-driver", features = ["serde", "postcard"] } +sps30-async = { version = "0.3.0", path = "/home/david/tmp/sps30", features = ["serde", "postcard"] } +nau7802-async = { path = "/home/david/tmp/nau7802-rs", features = ["serde", "postcard", "defmt"] } + +# encoding +protocol = { path = "../../../crates/protocol" } + +[patch.crates-io] +embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } +embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } +embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } +embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } +embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } +embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } +embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } +embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } +embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } + +[profile.dev] +opt-level = "s" + +[profile.release] +lto = "fat" +opt-level = "s" +incremental = false +codegen-units = 1 +# note: debug = true is okay - debuginfo isn't flashed to the device! +debug = true diff --git a/sensor-nodes/bed-sb/build.rs b/sensor-nodes/bed-sb/build.rs new file mode 100644 index 00000000..8cd32d7e --- /dev/null +++ b/sensor-nodes/bed-sb/build.rs @@ -0,0 +1,5 @@ +fn main() { + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tlink.x"); + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); +} diff --git a/sensor-nodes/bed-sb/output.txt b/sensor-nodes/bed-sb/output.txt new file mode 100644 index 00000000..48b0ff76 --- /dev/null +++ b/sensor-nodes/bed-sb/output.txt @@ -0,0 +1,19660 @@ +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 867502111134296087 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 14599460162574367279 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 8070402030576215694 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 4334505959795280607 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 12614019627889602978 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 13081958469941311299 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 17908139605922323881 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 2841131338015846188 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 13356480873848707970 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 1656018264575584532 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 +WARN warning connection down, resetting if not up soon +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG timeout exceeded +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +WARN write error: ConnectionReset +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +INFO (re-)connected +└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG can now write +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 +DEBUG need to read +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG tick +└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 +DEBUG flash: latency=2 +└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } +└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 +INFO random seed: 14091470885172412432 +└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 +DEBUG IPv4: UP +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG IP address: 192.168.1.7/24 +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Default gateway: Some(192.168.1.1) +└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 +DEBUG Configured socket and connecting +└─ bed_sensors::network::handle::{async_fn#0} @ src/network.rs:78 +INFO initializing sensors +└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request +└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +INFO (re-)connected +└─ bed_sensors::network::handle::{async_fn#0} @ src/network.rs:85 +INFO link_up = false +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG retransmitting at t+0.899s +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +INFO link_up = true +└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 +DEBUG retransmitting at t+0.899s +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG retransmitting at t+0.899s +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG retransmitting at t+1.102s +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG retransmitting at t+1.102s +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG retransmitting at t+1.102s +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 +DEBUG queueing error: Timeout(Sht31) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Mhz14) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG queueing error: Timeout(Sps30) +└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 +DEBUG retransmitting at t+1.508s +└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 diff --git a/sensor-nodes/bed-sb/rust-toolchain.toml b/sensor-nodes/bed-sb/rust-toolchain.toml new file mode 100644 index 00000000..c17f644e --- /dev/null +++ b/sensor-nodes/bed-sb/rust-toolchain.toml @@ -0,0 +1,6 @@ +[toolchain] +channel = "stable" +components = [ "rust-src", "rustfmt", "llvm-tools" ] +targets = [ + "thumbv7em-none-eabihf", +] diff --git a/sensor-nodes/bed-sb/schema/Cargo.lock b/sensor-nodes/bed-sb/schema/Cargo.lock deleted file mode 100644 index 738ae200..00000000 --- a/sensor-nodes/bed-sb/schema/Cargo.lock +++ /dev/null @@ -1,447 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "atomic-polyfill" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" -dependencies = [ - "critical-section", -] - -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "cobs" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" - -[[package]] -name = "critical-section" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" - -[[package]] -name = "darling" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.77", -] - -[[package]] -name = "darling_macro" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.77", -] - -[[package]] -name = "defmt" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0" -dependencies = [ - "bitflags", - "defmt-macros", -] - -[[package]] -name = "defmt-macros" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb" -dependencies = [ - "defmt-parser", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.77", -] - -[[package]] -name = "defmt-parser" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" -dependencies = [ - "thiserror", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "hash32" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hash32" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" -dependencies = [ - "byteorder", -] - -[[package]] -name = "heapless" -version = "0.7.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" -dependencies = [ - "atomic-polyfill", - "hash32 0.2.1", - "rustc_version", - "serde", - "spin", - "stable_deref_trait", -] - -[[package]] -name = "heapless" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" -dependencies = [ - "defmt", - "hash32 0.3.1", - "serde", - "stable_deref_trait", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "postcard" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" -dependencies = [ - "cobs", - "heapless 0.7.17", - "postcard-derive", - "serde", -] - -[[package]] -name = "postcard-derive" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0239fa9c1d225d4b7eb69925c25c5e082307a141e470573fbbe3a817ce6a7a37" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "postcard-rpc" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b6bf6dce5532b37ad9ce1dfc70e8f892f3c241306cdd2952d5156f9b35f43a" -dependencies = [ - "heapless 0.8.0", - "postcard", - "serde", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "protocol" -version = "0.1.0" -dependencies = [ - "defmt", - "heapless 0.8.0", - "postcard", - "serde", - "strum", -] - -[[package]] -name = "quote" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "rustversion" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" - -[[package]] -name = "schema" -version = "0.1.0" -dependencies = [ - "heapless 0.8.0", - "postcard", - "postcard-rpc", - "protocol", - "serde", - "serde_with", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - -[[package]] -name = "serde" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.77", -] - -[[package]] -name = "serde_with" -version = "3.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" -dependencies = [ - "serde", - "serde_derive", - "serde_with_macros", -] - -[[package]] -name = "serde_with_macros" -version = "3.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.77", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.77", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.77", -] - -[[package]] -name = "unicode-ident" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" diff --git a/sensor-nodes/bed-sb/schema/Cargo.toml b/sensor-nodes/bed-sb/schema/Cargo.toml deleted file mode 100644 index 9d8e19b0..00000000 --- a/sensor-nodes/bed-sb/schema/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "schema" -version = "0.1.0" -rust-version = "1.78" -edition = "2021" -license = "GPLv3" -authors = ["David Kleingeld & Eva van Houten"] - -[dependencies] -heapless = "0.8.0" -postcard = { version = "1.0.10", features = ["experimental-derive"] } -postcard-rpc = "0.7.0" - -protocol = { path = "../../../crates/protocol" } -serde = { version = "1.0.210", features = ["derive"], default-features = false } -serde_with = { version = "3.9.0", features = ["macros"], default-features = false } diff --git a/sensor-nodes/bed-sb/schema/src/lib.rs b/sensor-nodes/bed-sb/schema/src/lib.rs deleted file mode 100644 index f30c65e6..00000000 --- a/sensor-nodes/bed-sb/schema/src/lib.rs +++ /dev/null @@ -1,68 +0,0 @@ -#![no_std] - -use postcard::experimental::schema::Schema; -use postcard_rpc::topic; -use serde::{Deserialize, Serialize}; -use serde_with::{serde_as, Bytes}; - -topic!(ProtocolTopic, ProtocolMsg, "protocol"); - -// Unfortunately postcard::Schema is not a thing on heapless_vec -// so we have to try things differently -// -// also serde cannot handle >32 arrays so we gotta use a helper crate -#[serde_as] -#[derive(Schema, Serialize, Deserialize)] -pub struct StackVec { - #[serde_as(as = "Bytes")] - bytes: [u8; 250], - len: u8, -} - -impl StackVec { - pub fn new() -> Self { - StackVec { - bytes: [0u8; 250], - len: 0, - } - } - pub fn capacity(&self) -> usize { - self.bytes.len() - } - pub fn set_len(&mut self, len: usize) { - self.len = len.min(self.capacity()) as u8; - } - pub fn as_slice(&self) -> &[u8] { - &self.bytes[..self.len as usize] - } - pub fn as_mut_slice(&mut self) -> &mut [u8] { - &mut self.bytes[..self.len as usize] - } -} - -impl core::ops::Deref for StackVec { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - self.as_slice() - } -} - -impl core::ops::DerefMut for StackVec { - fn deref_mut(&mut self) -> &mut Self::Target { - self.as_mut_slice() - } -} - -/// contains an encoded protocol::Msg -#[derive(Schema, Deserialize, Serialize)] -pub struct ProtocolMsg(pub StackVec); - -impl From> for ProtocolMsg { - fn from(value: protocol::Msg) -> Self { - let mut vec = StackVec::new(); - let len = value.encode_slice(&mut vec.bytes).len(); - vec.len = len as u8; - ProtocolMsg(vec) - } -} diff --git a/sensor-nodes/bed-sb/src/channel.rs b/sensor-nodes/bed-sb/src/channel.rs new file mode 100644 index 00000000..6ad87faf --- /dev/null +++ b/sensor-nodes/bed-sb/src/channel.rs @@ -0,0 +1,132 @@ +use embassy_futures::select::{self, Either}; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::channel::Channel; +use embassy_sync::mutex::Mutex; +use embassy_sync::priority_channel::{self, PriorityChannel}; +use embassy_time::{Duration, Instant}; +use heapless::HistoryBuffer; +use protocol::small_bedroom::bed::Reading; + +use crate::error_cache; + +pub struct Queues { + sensor_queue: PriorityChannel, + error_queue: Channel, + recent_errors: Mutex>, + recent_is_since: Instant, +} + +pub enum QueueItem { + Reading(PriorityValue), + Error(error_cache::Error), +} + +impl Queues { + pub fn new() -> Self { + Self { + sensor_queue: PriorityChannel::new(), + error_queue: Channel::new(), + recent_errors: Mutex::new(HistoryBuffer::new()), + recent_is_since: Instant::now(), + } + } + + pub async fn clear(&self) { + while self.sensor_queue.try_receive().is_ok() {} + self.recent_errors.lock().await.clear(); + } + + pub async fn receive(&self) -> QueueItem { + if let Ok(val) = self.sensor_queue.try_receive() { + return QueueItem::Reading(val); + } + + let race = select::select(self.sensor_queue.receive(), self.error_queue.receive()); + match race.await { + Either::First(reading) => QueueItem::Reading(reading), + Either::Second(error) => QueueItem::Error(error), + } + } + + pub async fn receive_reading(&self) -> PriorityValue { + self.sensor_queue.receive().await + } + + pub fn next_ready(&self) -> Option { + self.sensor_queue.try_receive().ok() + } + + pub fn queue_error(&self, error: error_cache::Error) { + // unwrap safe: is not used in interrupts + let mut recent_errors = defmt::unwrap!(self.recent_errors.try_lock()); + if self.recent_is_since.elapsed() > Duration::from_secs(60 * 5) { + recent_errors.clear(); + } + if recent_errors.contains(&error) { + return; + } + + defmt::debug!("queueing error: {:?}", error); + let Ok(()) = self.error_queue.try_send(error.clone()) else { + return; + }; + recent_errors.write(error); + } + + pub fn send_p0(&self, value: Reading) { + use protocol::small_bedroom::Reading::Bed; + let entry = PriorityValue { + priority: 0, + value: protocol::Reading::SmallBedroom(Bed(value)), + }; + let _ignore_full = self.sensor_queue.try_send(entry); + } + pub fn send_p1(&self, value: Reading) { + use protocol::small_bedroom::Reading::Bed; + let entry = PriorityValue { + priority: 1, + value: protocol::Reading::SmallBedroom(Bed(value)), + }; + let _ignore_full = self.sensor_queue.try_send(entry); + } + + pub fn send_p2(&self, value: Reading) { + use protocol::small_bedroom::Reading::Bed; + let entry = PriorityValue { + priority: 2, + value: protocol::Reading::SmallBedroom(Bed(value)), + }; + let _ignore_full = self.sensor_queue.try_send(entry); + } +} + +/// Higher prio will be send earlier +pub struct PriorityValue { + priority: u8, + pub value: protocol::Reading, +} + +impl PriorityValue { + pub fn low_priority(&self) -> bool { + self.priority < 2 + } +} + +impl Eq for PriorityValue {} +impl PartialEq for PriorityValue { + fn eq(&self, other: &Self) -> bool { + self.priority.eq(&other.priority) + } +} + +impl PartialOrd for PriorityValue { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.priority.cmp(&other.priority)) + } +} + +impl Ord for PriorityValue { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.priority.cmp(&other.priority) + } +} diff --git a/sensor-nodes/bed-sb/src/comms.rs b/sensor-nodes/bed-sb/src/comms.rs new file mode 100644 index 00000000..3d18de31 --- /dev/null +++ b/sensor-nodes/bed-sb/src/comms.rs @@ -0,0 +1,142 @@ +use defmt::{unwrap, warn}; +use embassy_futures::select::{self, select}; +use embassy_time::{with_timeout, Duration, Instant}; +use protocol::small_bedroom::{self, bed}; +use protocol::{affector, Affector, ErrorReport, SensorMessage}; + +use crate::channel::{PriorityValue, QueueItem, Queues}; +use crate::sensors::slow; +use crate::usb_wrapper::{self, UsbHandle, UsbReceiver, UsbSender}; + +pub(crate) type SensMsg = SensorMessage<10>; +async fn collect_pending(publish: &Queues, reading: PriorityValue) -> SensorMessage<10> { + let mut msg = SensMsg::default(); + let low_priority = reading.low_priority(); + unwrap!(msg.values.push(reading.value)); + + if low_priority { + let deadline = Instant::now() + Duration::from_millis(200); + while msg.space_left() { + let until = deadline.saturating_duration_since(Instant::now()); + match with_timeout(until, publish.receive_reading()).await { + Ok(new) if new.low_priority() => { + unwrap!(msg.values.push(new.value)); + } + Ok(new) => { + unwrap!(msg.values.push(new.value)); + break; + } + Err(_timeout) => break, + } + } + } else { + while msg.space_left() { + let Some(next) = publish.next_ready() else { + break; + }; + unwrap!(msg.values.push(next.value)); + } + } + msg +} + +async fn get_messages<'a>(publish: &Queues, buf: &'a mut [u8]) -> &'a [u8] { + let next = publish.receive().await; + match next { + QueueItem::Reading(reading) => { + let msg = collect_pending(publish, reading).await; + let encoded_len = msg.encode_slice(&mut buf[1..]).len(); + buf[0] = protocol::Msg::<0>::READINGS; + &buf[..=encoded_len] + } + QueueItem::Error(error) => { + let error = protocol::small_bedroom::Error::Bed(error.into()); + let error = protocol::Error::SmallBedroom(error); + let encoded_len = ErrorReport::new(error).encode_slice(&mut buf[1..]).len(); + buf[0] = protocol::Msg::<0>::ERROR_REPORT; + &buf[..=encoded_len] + } + } +} + + + +pub async fn handle(usb: UsbHandle<'_>, publish: &Queues, driver_orderers: &slow::DriverOrderers) { + loop { + publish.clear().await; + + let (writer, reader) = usb.split(); + match select( + send_messages(writer, publish), + receive_orders(reader, &driver_orderers), + ) + .await + { + select::Either::First(e) => warn!("Error while sending messages: {}", e), + select::Either::Second(e) => warn!("Error receiving orders: {}", e), + }; + } +} + +fn affector_list() -> affector::ListMessage<5> { + let mut list = affector::ListMessage::<5>::empty(); + unwrap!(list.values.push(Affector::SmallBedroom( + protocol::small_bedroom::Affector::Bed(bed::Affector::Sps30FanClean), + ))); + unwrap!(list.values.push(Affector::SmallBedroom( + protocol::small_bedroom::Affector::Bed(bed::Affector::MhzZeroPointCalib), + ))); + unwrap!(list.values.push(Affector::SmallBedroom( + protocol::small_bedroom::Affector::Bed(bed::Affector::Nau7802Calib), + ))); + + list +} + +async fn send_messages(usb: UsbSender<'_>, publish: &Queues) { + let mut buf = usb_wrapper::SendItem::new(); + unwrap!(buf.resize_default(buf.capacity())); + let encoded_list_len = affector_list().encode_slice(&mut buf[1..]).len(); + buf[0] = protocol::Msg::<5>::AFFECTOR_LIST; + buf.truncate(encoded_list_len + 1); + usb.send(buf).await; + + loop { + let mut buf = usb_wrapper::SendItem::new(); + unwrap!(buf.resize_default(buf.capacity())); + let encoded_len = get_messages(publish, &mut buf).await.len(); + buf.truncate(encoded_len); + usb.send(buf).await; + } +} + +async fn receive_orders(usb: UsbReceiver<'_>, driver_orderers: &slow::DriverOrderers) { + defmt::debug!("ready to receive orders"); + loop { + let mut read = usb.recv().await; + let item = match affector::Affector::decode(&mut read) { + Ok(item) => item, + Err(e) => { + defmt::error!("Could not decode affector: {}", e); + continue; + } + }; + let Affector::SmallBedroom(small_bedroom::Affector::Bed(affector)) = item else { + defmt::error!("Got affector for other node"); + continue; + }; + + defmt::info!("got affector order: {:?}", affector); + match affector { + bed::Affector::Nau7802Calib => { + defmt::warn!("unimplemented affector: {:?}", affector) + } + bed::Affector::MhzZeroPointCalib => { + driver_orderers.mhz.send(()).await; + } + bed::Affector::Sps30FanClean => { + driver_orderers.sps.send(()).await; + } + } + } +} diff --git a/sensor-nodes/bed-sb/src/error_cache.rs b/sensor-nodes/bed-sb/src/error_cache.rs new file mode 100644 index 00000000..ab74aa72 --- /dev/null +++ b/sensor-nodes/bed-sb/src/error_cache.rs @@ -0,0 +1,57 @@ +use protocol::small_bedroom::bed::{self, Device}; +use protocol::make_error_string; + +use crate::sensors::{I2cError, UartError}; + +#[derive(defmt::Format, PartialEq, Eq, Clone)] +pub(crate) enum SensorError { + Mhz14(mhzx::Error), + Sps30(sps30_async::Error), + Sht31(sht31::SHTError), + Bme680(bosch_bme680::BmeError), + Max44(max44009::Error), + Nau7802(nau7802_async::Error), + Button(PressTooLong), +} + +#[derive(defmt::Format, PartialEq, Eq, Clone)] +pub(crate) struct PressTooLong { + pub(crate) button: &'static str, +} + +impl core::fmt::Debug for PressTooLong { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.write_fmt(format_args!("Button {}, pressed too long", self.button)) + } +} + +impl From for bed::SensorError { + fn from(val: SensorError) -> Self { + match val { + SensorError::Mhz14(e) => bed::SensorError::Mhz14(make_error_string(e)), + SensorError::Sps30(e) => bed::SensorError::Sps30(make_error_string(e)), + SensorError::Sht31(e) => bed::SensorError::Sht31(make_error_string(e)), + SensorError::Bme680(e) => bed::SensorError::Bme680(make_error_string(e)), + SensorError::Max44(e) => bed::SensorError::Max44(make_error_string(e)), + SensorError::Nau7802(e) => bed::SensorError::Nau7802(make_error_string(e)), + SensorError::Button(e) => bed::SensorError::Button(make_error_string(e)), + } + } +} + +#[derive(defmt::Format, PartialEq, Eq, Clone)] +pub(crate) enum Error { + Running(SensorError), + Setup(SensorError), + Timeout(Device), +} + +impl From for bed::Error { + fn from(val: Error) -> Self { + match val { + Error::Running(e) => bed::Error::Running(e.into()), + Error::Setup(e) => bed::Error::Setup(e.into()), + Error::Timeout(dev) => bed::Error::Timeout(dev), + } + } +} diff --git a/sensor-nodes/bed-sb/src/main.rs b/sensor-nodes/bed-sb/src/main.rs new file mode 100644 index 00000000..ebece82f --- /dev/null +++ b/sensor-nodes/bed-sb/src/main.rs @@ -0,0 +1,207 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_futures::select::{self, Either3}; +use embassy_stm32::exti::ExtiInput; +use embassy_stm32::gpio::Pull; +use embassy_stm32::i2c::{self, I2c}; +use embassy_stm32::peripherals::IWDG; +use embassy_stm32::time::Hertz; +use embassy_stm32::usart::{self, DataBits, Parity, StopBits, Uart}; +use embassy_stm32::wdg::IndependentWatchdog; +use embassy_stm32::{usb, Config}; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::mutex::Mutex; +use embassy_time::Timer; +use futures::pin_mut; +use sensors::fast::ButtonInputs; +use sensors::slow; + +use defmt::{error, trace, unwrap}; +use {defmt_rtt as _, panic_probe as _}; + +mod channel; +mod comms; +mod error_cache; +mod sensors; +mod usb_wrapper; +use crate::channel::Queues; + +embassy_stm32::bind_interrupts!(struct Irqs { + I2C1_EV => embassy_stm32::i2c::EventInterruptHandler; + I2C1_ER => embassy_stm32::i2c::ErrorInterruptHandler; + I2C3_EV => embassy_stm32::i2c::EventInterruptHandler; + I2C3_ER => embassy_stm32::i2c::ErrorInterruptHandler; + USART1 => embassy_stm32::usart::InterruptHandler; + USART2 => embassy_stm32::usart::InterruptHandler; + OTG_FS => embassy_stm32::usb::InterruptHandler; +}); + +// todo use nusb to write driver + +// 84 Mhz clock stm32f401 +fn config() -> Config { + use embassy_stm32::rcc::{ + AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllPreDiv, PllSource, + Sysclk, + }; + + let mut config = Config::default(); + config.rcc.hse = Some(Hse { + freq: Hertz(25_000_000), + mode: HseMode::Oscillator, + }); + config.rcc.pll_src = PllSource::HSE; + config.rcc.pll = Some(Pll { + prediv: PllPreDiv::DIV25, + mul: PllMul::MUL336, + divp: Some(PllPDiv::DIV4), + divq: None, + divr: None, + }); + config.rcc.ahb_pre = AHBPrescaler::DIV1; + config.rcc.apb1_pre = APBPrescaler::DIV2; + config.rcc.apb2_pre = APBPrescaler::DIV1; + config.rcc.sys = Sysclk::PLL1_P; + config +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_stm32::init(config()); + + let mut usart_config = usart::Config::default(); + usart_config.baudrate = 9600; + usart_config.data_bits = DataBits::DataBits8; + usart_config.stop_bits = StopBits::STOP1; + let usart_mhz = unwrap!(Uart::new( + p.USART1, + p.PB7, + p.PB6, + Irqs, + p.DMA2_CH7, + p.DMA2_CH2, + usart_config, + )); + + let mut usart_config = usart::Config::default(); + usart_config.baudrate = 115_200; // sps30 only works at this baud + usart_config.data_bits = DataBits::DataBits8; + usart_config.stop_bits = StopBits::STOP1; + usart_config.parity = Parity::ParityNone; + let usart_sps30 = unwrap!(Uart::new( + p.USART2, + p.PA3, + p.PA2, + Irqs, + p.DMA1_CH6, + p.DMA1_CH5, + usart_config, + )); + + let i2c_1 = I2c::new( + p.I2C1, + p.PB8, + p.PB9, + Irqs, + p.DMA1_CH7, + p.DMA1_CH0, + Hertz(150_000), + i2c::Config::default(), + ); + let i2c_1: Mutex = Mutex::new(i2c_1); + + let i2c_3 = I2c::new( + p.I2C3, + p.PA8, + p.PB4, + Irqs, + p.DMA1_CH4, + p.DMA1_CH1, + // Extra slow, helps with longer cable runs + Hertz(150_000), + i2c::Config::default(), + ); + let i2c_3: Mutex = Mutex::new(i2c_3); + + let buttons = ButtonInputs { + left: ExtiInput::new(p.PC14, p.EXTI14, Pull::Down), + left_middle: ExtiInput::new(p.PA9, p.EXTI9, Pull::Down), + right_middle: ExtiInput::new(p.PC13, p.EXTI13, Pull::Down), + right: ExtiInput::new(p.PA10, p.EXTI10, Pull::Down), + }; + + let mut usb_driver_config = embassy_stm32::usb::Config::default(); + // Do not enable vbus_detection. This is a safe default that works in all + // boards. However, if your USB device is self-powered (can stay powered on + // if USB is unplugged), you need to enable vbus_detection to comply with + // the USB spec. If you enable it, the board + usb_driver_config.vbus_detection = false; + + let mut ep_out_buffer = [0u8; 256]; + let usb_driver = usb::Driver::new_fs( + p.USB_OTG_FS, + Irqs, + p.PA12, + p.PA11, + &mut ep_out_buffer, + usb_driver_config, + ); + + let stack_a = usb_wrapper::StackA::new(); + let mut stack_b = usb_wrapper::StackB::new(&stack_a); + let (mut usb_bus, usb_handle) = usb_wrapper::new(&stack_a, &mut stack_b, usb_driver); + + let driver_orderers = slow::DriverOrderers::new(); + let publish = Queues::new(); + let handle_network = comms::handle(usb_handle, &publish, &driver_orderers); + pin_mut!(handle_network); + + let init_then_measure = sensors::init_then_measure( + &publish, + &driver_orderers, + i2c_1, + i2c_3, + usart_mhz, + usart_sps30, + buttons, + ); + + let res = select::select3(&mut handle_network, init_then_measure, usb_bus.run()).await; + let unrecoverable_err = match res { + Either3::First(()) | Either3::Third(()) | Either3::Second(Ok(())) => defmt::unreachable!(), + Either3::Second(Err(err)) => err, + }; + + // at this point no other errors have occurred + error!("unrecoverable error, resetting: {}", unrecoverable_err); + publish.queue_error(unrecoverable_err); + handle_network.await; // if this takes too long the dog will get us +} + +pub fn usb_config() -> embassy_usb::Config<'static> { + // Create embassy-usb Config + let mut config = embassy_usb::Config::new(0x16c0, 0x27DD); + config.manufacturer = Some("Vid"); + config.product = Some("Sensor node"); + config.serial_number = Some("2478437"); + + // Required for windows compatibility. + // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help + config.device_class = 0xEF; + config.device_sub_class = 0x02; + config.device_protocol = 0x01; + config.composite_with_iads = true; + + config +} + +async fn keep_dog_happy(mut dog: IndependentWatchdog<'_, IWDG>) { + loop { + dog.unleash(); + Timer::after_secs(8).await; + trace!("petting dog"); + dog.pet(); + } +} diff --git a/sensor-nodes/bed-sb/src/sensors.rs b/sensor-nodes/bed-sb/src/sensors.rs new file mode 100644 index 00000000..9840ae71 --- /dev/null +++ b/sensor-nodes/bed-sb/src/sensors.rs @@ -0,0 +1,149 @@ +use defmt::info; +use embassy_embedded_hal::shared_bus::I2cDeviceError; +use embassy_futures::join; +use embassy_stm32::i2c::I2c; +use embassy_stm32::mode::Async; +use embassy_stm32::usart::Uart; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::mutex::Mutex; +use embassy_time::Delay; +use fast::ButtonInputs; +use mhzx::MHZ; +use protocol::small_bedroom::bed::Device; +use sps30_async::Sps30; + +use crate::channel::Queues; +use crate::error_cache::{Error, SensorError}; +pub mod fast; +pub mod retry; +pub mod slow; + +use retry::{Bme680Driver, Driver, Max44Driver, Nau7802Driver, Sht31Driver, Sps30Driver}; + +pub type I2cError = I2cDeviceError; +pub type UartError = embassy_stm32::usart::Error; + +pub mod concrete_types { + use embassy_embedded_hal::shared_bus; + use embassy_stm32::i2c::I2c; + use embassy_stm32::mode::Async; + use embassy_stm32::usart::{RingBufferedUartRx, UartTx}; + use embassy_sync::blocking_mutex::raw::NoopRawMutex; + use shared_bus::asynch::i2c::I2cDevice; + + pub type ConcreteSharedI2c<'a> = I2cDevice<'a, NoopRawMutex, I2c<'static, Async>>; + pub type ConcreteTx<'a> = UartTx<'a, Async>; + pub type ConcreteRx<'a> = RingBufferedUartRx<'a>; +} + +const SPS30_UART_BUF_SIZE: usize = 150; +const SPS30_DRIVER_BUF_SIZE: usize = 2 * SPS30_UART_BUF_SIZE; + +pub async fn init_then_measure( + publish: &Queues, + orderers: &slow::DriverOrderers, + i2c_1: Mutex>, + i2c_3: Mutex>, + usart_mhz: Uart<'static, Async>, + usart_sps: Uart<'static, Async>, + buttons: ButtonInputs, +) -> Result<(), Error> { + info!("initializing sensors"); + let bme = Bme680Driver::new(&i2c_3, Device::Bme680); + let max44009 = Max44Driver::new(&i2c_1, Device::Max44); + let sht = Sht31Driver::new(&i2c_1, Device::Sht31); + let nau = Nau7802Driver::new(&i2c_3, Device::Nau7802); + + let (tx, rx) = usart_mhz.split(); + let mut usart_buf = [0u8; 9 * 10]; // 9 byte messages + let rx = rx.into_ring_buffered(&mut usart_buf); + let mhz = MHZ::from_tx_rx(tx, rx); + + let (tx, rx) = usart_sps.split(); + let mut usart_buf = [0u8; SPS30_UART_BUF_SIZE]; + let rx = rx.into_ring_buffered(&mut usart_buf); + let sps30 = Sps30Driver::init(tx, rx); + + let sensors_fast = fast::read(max44009, nau, buttons, publish); + let drivers = slow::Drivers { + sht, + bme, + mhz, + sps: sps30, + }; + let sensors_slow = slow::read(drivers, orderers, publish); + join::join(sensors_fast, sensors_slow).await; + + defmt::unreachable!(); +} + +use concrete_types::ConcreteRx as Rx; +use concrete_types::ConcreteTx as Tx; +impl<'a> Driver for MHZ, Rx<'a>> { + type Measurement = mhzx::Measurement; + type Affector = (); + + #[inline(always)] + async fn try_measure(&mut self) -> Result { + self.read_co2() + .await + .map_err(SensorError::Mhz14) + .map_err(Error::Running) + } + + #[inline(always)] + fn device(&self) -> protocol::small_bedroom::bed::Device { + Device::Mhz14 + } +} + +impl<'a> Driver for Sps30, Rx<'a>, Delay> { + type Measurement = sps30_async::Measurement; + type Affector = (); + + #[inline(always)] + async fn try_measure(&mut self) -> Result { + self.read_measurement() + .await + .map_err(SensorError::Sps30) + .map_err(Error::Running) + } + + #[inline(always)] + fn device(&self) -> protocol::small_bedroom::bed::Device { + Device::Sps30 + } +} + +pub(crate) struct I2cWrapper(Mutex); + +impl embedded_hal_async::i2c::ErrorType for &I2cWrapper { + type Error = ::Error; +} + +impl embedded_hal_async::i2c::I2c for &I2cWrapper { + async fn transaction( + &mut self, + address: u8, + operations: &mut [embedded_hal_async::i2c::Operation<'_>], + ) -> Result<(), Self::Error> { + self.0.lock().await.transaction(address, operations) + } + + async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { + self.0.lock().await.read(address, read) + } + + async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { + self.0.lock().await.write(address, write) + } + + async fn write_read( + &mut self, + address: u8, + write: &[u8], + read: &mut [u8], + ) -> Result<(), Self::Error> { + self.0.lock().await.write_read(address, write, read) + } +} diff --git a/sensor-nodes/bed-sb/src/sensors/fast.rs b/sensor-nodes/bed-sb/src/sensors/fast.rs new file mode 100644 index 00000000..e33c5e65 --- /dev/null +++ b/sensor-nodes/bed-sb/src/sensors/fast.rs @@ -0,0 +1,165 @@ +use embassy_futures::join::join4; +use embassy_futures::{join, yield_now}; +use embassy_stm32::exti::ExtiInput; +use embassy_time::{Duration, Instant, Timer}; + +use protocol::small_bedroom::{bed::Button, bed::Reading}; + +use super::retry::{Max44Driver, Nau7802Driver}; +use crate::channel::Queues; + +fn sig_lux_diff(old: f32, new: f32) -> bool { + let diff = old - new; + // we do not have f32::abs on embedded + diff > old / 20.0 || -diff > old / 20.0 +} + +fn sig_weight_diff(old: u32, new: u32) -> bool { + let diff = new.abs_diff(old); + diff > 2000 +} + +async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues) { + const MAX_INTERVAL: Duration = Duration::from_secs(5); + + let mut prev_lux = f32::MAX; + let mut last_lux = Instant::now(); + + loop { + Timer::after_millis(50).await; + let lux = match max44.try_measure().await { + Ok(lux) => lux, + Err(err) if last_lux.elapsed() > MAX_INTERVAL => { + publish.queue_error(err); + continue; + } + Err(_) => continue, + }; + + if sig_lux_diff(prev_lux, lux) { + publish.send_p2(Reading::Brightness(lux)); + } else if last_lux.elapsed() > MAX_INTERVAL { + publish.send_p1(Reading::Brightness(lux)); + } else { + yield_now().await; + continue; + }; + + prev_lux = lux; + last_lux = Instant::now(); + } +} + +trait Nau { + async fn try_measure(&mut self) -> Result; +} + +impl Nau for Nau7802Driver<'_> { + async fn try_measure(&mut self) -> Result { + Nau7802Driver::try_measure(self).await + } +} + +async fn report_weight(mut nau: impl Nau, wrap: impl Fn(u32) -> Reading, publish: &Queues) { + const MAX_INTERVAL: Duration = Duration::from_secs(5); + + let mut prev_weight = u32::MAX; + let mut reported_at = Instant::now(); + + loop { + Timer::after_millis(100).await; + let weight = match nau.try_measure().await { + Ok(lux) => lux, + Err(err) if reported_at.elapsed() > MAX_INTERVAL => { + publish.queue_error(err); + continue; + } + Err(_) => continue, + }; + + if sig_weight_diff(prev_weight, weight) { + publish.send_p2(wrap(weight)); + } else if reported_at.elapsed() > MAX_INTERVAL { + publish.send_p1(wrap(weight)); + } else { + yield_now().await; + continue; + }; + + prev_weight = weight; + reported_at = Instant::now(); + } +} + +async fn watch_button( + mut input: ExtiInput<'static>, + event: impl Fn(protocol::button::Press) -> Button, + channel: &Queues, +) { + use crate::error_cache::{Error, PressTooLong, SensorError}; + + let mut went_high_at: Option = None; + loop { + if let Some(went_high_at) = went_high_at.take() { + input.wait_for_low().await; + let press = went_high_at.elapsed(); + let Ok(press) = press.as_millis().try_into() else { + let event_for_printing = (event)(protocol::button::Press(0)); + let name = event_for_printing.variant_name(); + channel.queue_error(Error::Running(SensorError::Button(PressTooLong { + button: name, + }))); + continue; + }; + let event = (event)(protocol::button::Press(press)); + channel.send_p2(Reading::Button(event)); + } else { + input.wait_for_high().await; + Timer::after(Duration::from_millis(20)).await; + if input.is_low() { + continue; + } + Timer::after(Duration::from_millis(20)).await; + if input.is_low() { + continue; + } + Timer::after(Duration::from_millis(10)).await; + if input.is_high() { + went_high_at = Some(Instant::now()); + } + } + } +} + +pub struct ButtonInputs { + pub left: ExtiInput<'static>, + pub left_middle: ExtiInput<'static>, + pub right_middle: ExtiInput<'static>, + pub right: ExtiInput<'static>, +} + +pub(crate) async fn read( + max44: Max44Driver<'_>, + nau: Nau7802Driver<'_>, + inputs: ButtonInputs, + publish: &Queues, +) { + use protocol::small_bedroom::bed::Button; + + let watch_buttons = join4( + watch_button(inputs.left, Button::Left, publish), + watch_button(inputs.left_middle, Button::LeftMiddle, publish), + watch_button(inputs.right_middle, Button::RightMiddle, publish), + watch_button(inputs.right, Button::Right, publish), + ); + + let watch_lux = report_lux(max44, publish); + let report_weight = report_weight(nau, Reading::Weight, publish); + + join::join3( + report_weight, + watch_lux, + watch_buttons, + ) + .await; +} diff --git a/sensor-nodes/bed-sb/src/sensors/retry.rs b/sensor-nodes/bed-sb/src/sensors/retry.rs new file mode 100644 index 00000000..f25e1046 --- /dev/null +++ b/sensor-nodes/bed-sb/src/sensors/retry.rs @@ -0,0 +1,127 @@ +use bosch_bme680::Bme680; +use embassy_embedded_hal::shared_bus; +use embassy_stm32::i2c::I2c; +use embassy_stm32::mode::Async; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::mutex::Mutex; +use embassy_time::{Delay, Timer}; +use max44009::{Max44009, SlaveAddr}; +use nau7802_async::Nau7802; +use sht31::mode::SingleShot; +use sht31::SHT31; + +use super::concrete_types::ConcreteSharedI2c; +use crate::error_cache::SensorError; + +mod reinit_on_error; +pub use reinit_on_error::{ + Bme680Driver, Max44Driver, Nau7802Driver, Sht31Driver, +}; + +mod retry_init; +pub use retry_init::Sps30Driver; + +impl<'a> ReInitableDriver for SHT31> { + type Parts = &'a Mutex>; + type Measurement = sht31::Reading; + + async fn init(parts: Self::Parts) -> Result { + let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); + Ok(SHT31::new(shared_i2c, Delay) + .with_mode(SingleShot) + .with_unit(sht31::TemperatureUnit::Celsius) + .with_accuracy(sht31::Accuracy::High)) + } + + async fn measure(&mut self) -> Result { + use sht31::mode::Sht31Measure; + use sht31::mode::Sht31Reader; + + Sht31Measure::measure(self) + .await + .map_err(SensorError::Sht31)?; + Timer::after_secs(1).await; + self.read().await.map_err(SensorError::Sht31) + } +} + +impl<'a> ReInitableDriver for Bme680, Delay> { + type Parts = &'a Mutex>; + type Measurement = bosch_bme680::MeasurementData; + + async fn init(parts: Self::Parts) -> Result { + let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); + Bme680::new( + shared_i2c, + bosch_bme680::DeviceAddress::Secondary, + Delay, + &bosch_bme680::Configuration::default(), + 21, + ) + .await + .map_err(SensorError::Bme680) + } + + async fn measure(&mut self) -> Result { + self.measure().await.map_err(SensorError::Bme680) + } +} + +impl<'a> ReInitableDriver for Max44009> { + type Parts = &'a Mutex>; + type Measurement = f32; + + async fn init(parts: Self::Parts) -> Result { + let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); + // Wrap these two into something returning Ok or Err + // then make it a generic arg, maybe Driverfactory::init + let mut driver = Max44009::new(shared_i2c, SlaveAddr::default()); + driver + .set_measurement_mode(max44009::MeasurementMode::Continuous) + .await + .map_err(SensorError::Max44)?; + Ok(driver) + } + async fn measure(&mut self) -> Result { + self.read_lux().await.map_err(SensorError::Max44) + } +} + +impl<'a> ReInitableDriver for Nau7802, Delay> { + type Parts = &'a Mutex>; + type Measurement = u32; + + async fn init(parts: Self::Parts) -> Result { + let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); + // Wrap these two into something returning Ok or Err + // then make it a generic arg, maybe Driverfactory::init + let driver = Nau7802::new(shared_i2c, Delay) + .await + .map_err(SensorError::Nau7802)?; + Ok(driver) + } + + async fn measure(&mut self) -> Result { + self.read().await.map_err(SensorError::Nau7802) + } +} + +/// A driver that can be re-initialized from copy-able parts +pub trait ReInitableDriver: Sized { + type Parts: Clone; + type Measurement; + + async fn init(parts: Self::Parts) -> Result; + async fn measure(&mut self) -> Result; +} + +pub trait Driver { + type Measurement; + type Affector; + async fn try_measure(&mut self) -> Result; + /// For example calibrate, run sensor cleaning etc + async fn affect(&mut self, _: Self::Affector) -> Result<(), crate::error_cache::Error> { + Ok(()) + } + fn device(&self) -> protocol::small_bedroom::bed::Device; +} diff --git a/sensor-nodes/bed-sb/src/sensors/retry/reinit_on_error.rs b/sensor-nodes/bed-sb/src/sensors/retry/reinit_on_error.rs new file mode 100644 index 00000000..cec44184 --- /dev/null +++ b/sensor-nodes/bed-sb/src/sensors/retry/reinit_on_error.rs @@ -0,0 +1,117 @@ +use bosch_bme680::Bme680; +use embassy_time::Delay; +use max44009::Max44009; +use nau7802_async::Nau7802; +use protocol::small_bedroom::bed::Device; +use sht31::mode::SingleShot; +use sht31::SHT31; + +use super::super::concrete_types::ConcreteSharedI2c; +use super::ReInitableDriver; +use crate::error_cache::Error; + +pub type Nau7802Driver<'a> = ReInitOnErrorDriver, Delay>>; +pub type Max44Driver<'a> = ReInitOnErrorDriver>>; +pub type Bme680Driver<'a> = ReInitOnErrorDriver, Delay>>; +pub type Sht31Driver<'a> = ReInitOnErrorDriver>>; + +enum State { + Ready { driver: D }, + Uninit, +} + +pub struct ReInitOnErrorDriver +where + D: ReInitableDriver, +{ + state: State, + parts: D::Parts, + device: Device, +} + +impl super::Driver for ReInitOnErrorDriver { + type Measurement = D::Measurement; + type Affector = (); + + #[inline(always)] + async fn try_measure(&mut self) -> Result { + self.try_measure().await + } + + #[inline(always)] + fn device(&self) -> Device { + self.device.clone() + } +} + +impl ReInitOnErrorDriver +where + D: ReInitableDriver, +{ + #[inline(always)] + pub fn new(parts: D::Parts, device: Device) -> Self { + Self { + state: State::Uninit, + parts, + device, + } + } + + #[inline(always)] + pub async fn try_measure(&mut self) -> Result { + let mut owned_self = State::Uninit; + core::mem::swap(&mut owned_self, &mut self.state); + let (mut new_self, res) = advance_state(owned_self, &self.parts).await; + core::mem::swap(&mut new_self, &mut self.state); + res + } +} + +#[inline(always)] +async fn advance_state( + state: State, + parts: &D::Parts, +) -> (State, Result) { + match state { + State::Ready { + mut driver, + // make a trait over driver that has a measure method + } => match driver.measure().await { + Ok(val) => { + let new_state = State::Ready { driver }; + (new_state, Ok(val)) + } + Err(err) => { + let new_state = State::Uninit; + (new_state, Err(Error::Running(err))) + } + }, + State::Uninit => { + match D::init(parts.clone()).await { + Ok(mut driver) => { + // uses driver::measure again, make that return a SensorError + match driver.measure().await { + Ok(val) => { + let new_state = State::Ready { driver }; + (new_state, Ok(val)) + } + Err(err) => { + let new_state = State::Uninit; + let err = Error::Running(err); + (new_state, Err(err)) + } + } + } + Err(err) => { + // drivers might contain blocking code in their + // error path, this makes sure the executor + // will not block on retrying. + embassy_time::Timer::after_millis(250).await; + let new_state = State::Uninit; + let err = Error::Setup(err); + (new_state, Err(err)) + } + } + } + } +} diff --git a/sensor-nodes/bed-sb/src/sensors/retry/retry_init.rs b/sensor-nodes/bed-sb/src/sensors/retry/retry_init.rs new file mode 100644 index 00000000..8f2e0cda --- /dev/null +++ b/sensor-nodes/bed-sb/src/sensors/retry/retry_init.rs @@ -0,0 +1,83 @@ +use embassy_time::Delay; +use sps30_async::Sps30; + +use crate::error_cache::{Error, SensorError}; +use crate::sensors::concrete_types::{ConcreteRx, ConcreteTx}; +use crate::sensors::SPS30_DRIVER_BUF_SIZE; + +use super::Driver; + +/// reset the device when an error occurs +pub struct Sps30Driver<'a> { + is_init: bool, + driver: Sps30, ConcreteRx<'a>, Delay>, +} + +impl<'a> Sps30Driver<'a> { + pub fn init(tx: ConcreteTx<'a>, rx: ConcreteRx<'a>) -> Self { + let driver = Sps30::from_tx_rx_uninit(tx, rx, Delay); + Self { + is_init: false, + driver, + } + } + + async fn measure(&mut self) -> Result { + if self.is_init { + let res = self + .driver + .read_measurement() + .await + .map_err(SensorError::Sps30) + .map_err(Error::Running); + self.is_init = res.is_ok(); + return res; + } + + self.driver + .reset() + .await + .map_err(SensorError::Sps30) + .map_err(Error::Setup)?; + self.driver + .start_measurement() + .await + .map_err(SensorError::Sps30) + .map_err(Error::Setup)?; + + let res = self + .driver + .read_measurement() + .await + .map_err(SensorError::Sps30) + .map_err(Error::Running); + + self.is_init = res.is_ok(); + res + } +} + +impl<'a> Driver for Sps30Driver<'a> { + type Measurement = sps30_async::Measurement; + type Affector = (); + + async fn try_measure(&mut self) -> Result { + self.measure().await + } + + async fn affect(&mut self, _: Self::Affector) -> Result<(), crate::error_cache::Error> { + self.driver + .start_fan_cleaning() + .await + .map_err(SensorError::Sps30) + .map_err(Error::Running)?; + // Fan cleaning takes 10 seconds, make sure its done before + // allowing the next reading + embassy_time::Timer::after(embassy_time::Duration::from_secs(11)).await; + Ok(()) + } + + fn device(&self) -> protocol::small_bedroom::bed::Device { + protocol::small_bedroom::bed::Device::Sps30 + } +} diff --git a/sensor-nodes/bed-sb/src/sensors/slow.rs b/sensor-nodes/bed-sb/src/sensors/slow.rs new file mode 100644 index 00000000..097b5339 --- /dev/null +++ b/sensor-nodes/bed-sb/src/sensors/slow.rs @@ -0,0 +1,195 @@ +use defmt::unwrap; +use embassy_futures::join::join5; +use embassy_futures::select; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::channel::Channel; +use embassy_time::Timer; +use embassy_time::{with_timeout, Duration}; + +use mhzx::MHZ; +use protocol::small_bedroom::bed::Reading; + +use bosch_bme680::MeasurementData; +use sps30_async as sps30; + +use crate::channel::Queues; +use crate::error_cache::Error; + +use super::retry::{Bme680Driver, Driver, Sht31Driver, Sps30Driver}; + +use super::concrete_types::ConcreteRx as Rx; +use super::concrete_types::ConcreteTx as Tx; + +type Signal = embassy_sync::signal::Signal; + +/// Measure when signal is received or control the device's +/// affector when it is ordered +#[inline(always)] +async fn measure_and_control( + mut driver: D, + order: &Channel, + send: F, + signal: &Signal, +) where + D: Driver, + F: Fn(Result) -> (), +{ + let timeout = Duration::from_secs(15); + loop { + match select::select(signal.wait(), order.receive()).await { + select::Either::First(_) => { + let try_measure = Driver::try_measure(&mut driver); + let res = match with_timeout(timeout, try_measure).await { + Ok(res) => res, + Err(_) => Err(Error::Timeout(driver.device())), + }; + send(res); + } + select::Either::Second(order) => { + let affect = Driver::affect(&mut driver, order); + let res = match with_timeout(timeout, affect).await { + Ok(Ok(_)) => continue, + Ok(Err(e)) => Err(e), + Err(_) => Err(Error::Timeout(driver.device())), + }; + send(res); + } + } + } +} + +async fn order_measurements_every_period(signals: &[Signal]) { + loop { + for signal in signals { + signal.signal(()); + } + Timer::after_secs(5).await; + } +} + +pub(crate) struct Drivers<'a> { + pub sht: Sht31Driver<'a>, + pub bme: Bme680Driver<'a>, + pub mhz: MHZ, Rx<'a>>, + pub sps: Sps30Driver<'a>, +} + +pub(crate) struct DriverOrderers { + pub sht: Channel, + pub bme: Channel, + pub mhz: Channel, + pub sps: Channel, +} +impl DriverOrderers { + pub(crate) fn new() -> Self { + Self { + sht: Channel::new(), + bme: Channel::new(), + mhz: Channel::new(), + sps: Channel::new(), + } + } +} + +#[inline(always)] +pub async fn read(drivers: Drivers<'_>, orderers: &DriverOrderers, publish: &'_ Queues) { + let signals = [const { Signal::new() }; 4]; + + join5( + order_measurements_every_period(&signals), + measure_and_control( + drivers.sht, + &orderers.sht, + |res| publish_sht_result(res, &publish), + &signals[0], + ), + measure_and_control( + drivers.bme, + &orderers.bme, + |res| publish_bme_result(res, &publish), + &signals[1], + ), + measure_and_control( + drivers.mhz, + &orderers.mhz, + |res| publish_mhz_result(res, &publish), + &signals[2], + ), + measure_and_control( + drivers.sps, + &orderers.sps, + |res| publish_sps_result(res, &publish), + &signals[3], + ), + ) + .await; +} + +fn publish_sps_result(sps_res: Result, publish: &Queues) { + match sps_res { + Ok(sps30::Measurement { + mass_pm1_0, + mass_pm2_5, + mass_pm4_0, + mass_pm10, + number_pm0_5, + number_pm1_0, + number_pm2_5, + number_pm4_0, + number_pm10, + typical_particle_size, + .. + }) => { + publish.send_p0(Reading::MassPm1_0(mass_pm1_0)); + publish.send_p0(Reading::MassPm2_5(mass_pm2_5)); + publish.send_p0(Reading::MassPm4_0(mass_pm4_0)); + publish.send_p0(Reading::MassPm10(mass_pm10)); + publish.send_p0(Reading::NumberPm0_5(number_pm0_5)); + publish.send_p0(Reading::NumberPm1_0(number_pm1_0)); + publish.send_p0(Reading::NumberPm2_5(number_pm2_5)); + publish.send_p0(Reading::NumberPm4_0(number_pm4_0)); + publish.send_p0(Reading::NumberPm10(number_pm10)); + publish.send_p0(Reading::TypicalParticleSize(typical_particle_size)); + } + Err(err) => publish.queue_error(err), + } +} + +fn publish_mhz_result(mhz_res: Result, publish: &Queues) { + match mhz_res { + Ok(mhzx::Measurement { co2, .. }) => { + publish.send_p0(Reading::Co2(co2)); + } + Err(err) => { + publish.queue_error(err); + } + } +} + +fn publish_sht_result(sht_res: Result, publish: &Queues) { + match sht_res { + Ok(sht31::Reading { + temperature, + humidity, + }) => { + publish.send_p0(Reading::Temperature(temperature)); + publish.send_p0(Reading::Humidity(humidity)); + } + Err(err) => publish.queue_error(err), + } +} + +fn publish_bme_result(bme_res: Result, publish: &Queues) { + match bme_res { + Ok(MeasurementData { + pressure, + gas_resistance, + .. + }) => { + let gas_resistance = unwrap!(gas_resistance); // sensor is on + publish.send_p0(Reading::GassResistance(gas_resistance)); + publish.send_p0(Reading::Pressure(pressure)); + } + Err(err) => publish.queue_error(err), + } +} diff --git a/sensor-nodes/bed-sb/src/usb_wrapper.rs b/sensor-nodes/bed-sb/src/usb_wrapper.rs new file mode 100644 index 00000000..0bfdf377 --- /dev/null +++ b/sensor-nodes/bed-sb/src/usb_wrapper.rs @@ -0,0 +1,229 @@ +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::channel::Channel; +use embassy_usb::control::{InResponse, OutResponse, Recipient, RequestType}; +use embassy_usb::types::InterfaceNumber; +use embassy_usb::UsbDevice; +use protocol::{affector, ErrorReport}; + +const fn max(a: usize, b: usize) -> usize { + [a, b][(a < b) as usize] +} + +const MAX_SEND_ITEM_SIZE: usize = 1 + max( + max( + crate::comms::SensMsg::ENCODED_SIZE, + ErrorReport::ENCODED_SIZE, + ), + affector::ListMessage::<5>::ENCODED_SIZE, +); + +const MAX_RECV_ITEM_SIZE: usize = 1 + affector::Affector::ENCODED_SIZE; + +pub(crate) type SendItem = heapless::Vec; +pub(crate) type RecvItem = heapless::Vec; + +pub struct UsbControlHandler<'a> { + pub if_num: Option, + send_queue: &'a Channel, + receive_queue: &'a Channel, +} + +impl embassy_usb::Handler for UsbControlHandler<'_> { + fn control_out( + &mut self, + req: embassy_usb::control::Request, + data: &[u8], + ) -> Option { + // Log the request before filtering to help with debugging. + defmt::info!("Got control_out, request={}, buf={:a}", req, data); + + // Only handle Vendor request types to an Interface. + if req.request_type != RequestType::Vendor { + return None; + } + + if req.recipient != Recipient::Interface { + return None; + } + + // Ignore requests to other interfaces. + if req.index != defmt::unwrap!(self.if_num).0 as u16 { + return None; + } + + // Accept request 100, value 200, reject others. + if req.request == 100 && req.value == 200 && data.len() <= MAX_RECV_ITEM_SIZE { + let data = heapless::Vec::from_slice(data).expect("checked length above"); + if self.receive_queue.try_send(data).is_err() { + Some(OutResponse::Rejected) + } else { + Some(OutResponse::Accepted) + } + } else { + Some(OutResponse::Rejected) + } + } + + fn control_in<'a>( + &'a mut self, + req: embassy_usb::control::Request, + buf: &'a mut [u8], + ) -> Option> { + defmt::info!("Got control_in, request={}", req); + + // Only handle Vendor request types to an Interface. + if req.request_type != RequestType::Vendor { + return None; + } + + if req.recipient != Recipient::Interface { + return None; + } + + // Ignore requests to other interfaces. + if req.index != defmt::unwrap!(self.if_num).0 as u16 { + return None; + } + + let Ok(to_send) = self.send_queue.try_receive() else { + return None; + }; + + if to_send.len() > buf.len() { + return None; + } + + buf[0..to_send.len()].copy_from_slice(&to_send); + Some(InResponse::Accepted(buf)) + } +} + +pub struct UsbHandle<'a> { + send_queue: &'a Channel, 2>, + receive_queue: &'a Channel, 2>, +} + +impl<'a> UsbHandle<'a> { + pub(crate) fn split(&self) -> (UsbSender<'a>, UsbReceiver<'a>) { + ( + UsbSender { + send_queue: self.send_queue, + }, + UsbReceiver { + receive_queue: self.receive_queue, + }, + ) + } +} + +pub struct UsbSender<'a> { + send_queue: &'a Channel, 2>, +} + +impl UsbSender<'_> { + pub(crate) async fn send(&self, item: SendItem) { + self.send_queue.send(item).await; + } +} + +pub struct UsbReceiver<'a> { + receive_queue: &'a Channel, 2>, +} +impl UsbReceiver<'_> { + pub(crate) async fn recv(&self) -> RecvItem { + self.receive_queue.receive().await + } +} + +pub fn config() -> embassy_usb::Config<'static> { + let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); + config.manufacturer = Some("Vid"); + config.product = Some(concat!("sensor node ", env!("CARGO_PKG_NAME"))); + config.serial_number = Some("2139874"); // random, host driver finds device using this + config +} + +pub struct StackA { + send_queue: Channel, 2>, + receive_queue: Channel, 2>, +} + +impl StackA { + pub(crate) fn new() -> Self { + Self { + send_queue: Channel::new(), + receive_queue: Channel::new(), + } + } +} + +pub struct StackB<'a> { + config_descriptor: [u8; 256], + bos_descriptor: [u8; 256], + msos_descriptor: [u8; 256], + control_buf: [u8; 64], + handler: UsbControlHandler<'a>, +} + +impl<'a> StackB<'a> { + pub(crate) fn new(stack_a: &'a StackA) -> Self { + Self { + config_descriptor: [0u8; 256], + bos_descriptor: [0u8; 256], + msos_descriptor: [0u8; 256], + control_buf: [0u8; 64], + + handler: UsbControlHandler { + if_num: None, + send_queue: &stack_a.send_queue, + receive_queue: &stack_a.receive_queue, + }, + } + } +} + +pub struct Usb<'a, D: embassy_usb::driver::Driver<'a>>(UsbDevice<'a, D>); + +impl<'a, D: embassy_usb::driver::Driver<'a>> Usb<'a, D> { + pub async fn run(&mut self) { + self.0.run().await + } +} + +pub(crate) fn new<'a, D: embassy_usb::driver::Driver<'a>>( + stack_a: &'a StackA, + stack_b: &'a mut StackB<'a>, + driver: D, +) -> (Usb<'a, D>, UsbHandle<'a>) { + let StackB { + config_descriptor, + bos_descriptor, + msos_descriptor, + control_buf, + handler, + } = stack_b; + + let mut builder = embassy_usb::Builder::new( + driver, + config(), + config_descriptor, + bos_descriptor, + msos_descriptor, + control_buf, + ); + + let mut function = builder.function(0xFF, 0, 0); + let mut interface = function.interface(); + let _alternate = interface.alt_setting(0xFF, 0, 0, None); + handler.if_num = Some(interface.interface_number()); + drop(function); + builder.handler(handler); + + ( + Usb(builder.build()), + UsbHandle { + send_queue: &stack_a.send_queue, + receive_queue: &stack_a.receive_queue, + }, + ) +} diff --git a/sensor-nodes/bed-sb/stm32f401.svd b/sensor-nodes/bed-sb/stm32f401.svd new file mode 100644 index 00000000..b9353d01 --- /dev/null +++ b/sensor-nodes/bed-sb/stm32f401.svd @@ -0,0 +1,35196 @@ + + + STM32F401 + 1.1 + STM32F401 + + CM4 + r1p0 + little + false + false + 4 + false + + 8 + 32 + 0x20 + 0x00000000 + 0xFFFFFFFF + + + ADC_Common + ADC common registers + ADC_Common + 0x40012300 + + 0x0 + 0x9 + registers + + + FPU + FPU interrupt + 81 + + + + CCR + CCR + ADC common control register + 0x4 + 0x20 + read-write + 0x00000000 + + + TSVREFE + Temperature sensor and VREFINT + enable + 23 + 1 + + TSVREFE + read-write + + Disabled + Temperature sensor and V_REFINT channel disabled + 0 + + + Enabled + Temperature sensor and V_REFINT channel enabled + 1 + + + + + VBATE + VBAT enable + 22 + 1 + + VBATE + read-write + + Disabled + V_BAT channel disabled + 0 + + + Enabled + V_BAT channel enabled + 1 + + + + + ADCPRE + ADC prescaler + 16 + 2 + + ADCPRE + read-write + + Div2 + PCLK2 divided by 2 + 0 + + + Div4 + PCLK2 divided by 4 + 1 + + + Div6 + PCLK2 divided by 6 + 2 + + + Div8 + PCLK2 divided by 8 + 3 + + + + + + + + + ADC1 + Analog-to-digital converter + ADC + 0x40012000 + + 0x0 + 0x51 + registers + + + ADC + ADC1 global interrupt + 18 + + + + SR + SR + status register + 0x0 + 0x20 + read-write + 0x00000000 + + + OVR + Overrun + 5 + 1 + zeroToClear + + OVRR + read + + NoOverrun + No overrun occurred + 0 + + + Overrun + Overrun occurred + 1 + + + + OVRW + write + + Clear + Clear flag + 0 + + + + + STRT + Regular channel start flag + 4 + 1 + zeroToClear + + STRTR + read + + NotStarted + No regular channel conversion started + 0 + + + Started + Regular channel conversion has started + 1 + + + + STRTW + write + + Clear + Clear flag + 0 + + + + + JSTRT + Injected channel start + flag + 3 + 1 + zeroToClear + + JSTRTR + read + + NotStarted + No injected channel conversion started + 0 + + + Started + Injected channel conversion has started + 1 + + + + JSTRTW + write + + Clear + Clear flag + 0 + + + + + JEOC + Injected channel end of + conversion + 2 + 1 + zeroToClear + + JEOCR + read + + NotComplete + Conversion is not complete + 0 + + + Complete + Conversion complete + 1 + + + + JEOCW + write + + Clear + Clear flag + 0 + + + + + EOC + Regular channel end of + conversion + 1 + 1 + zeroToClear + + EOCR + read + + NotComplete + Conversion is not complete + 0 + + + Complete + Conversion complete + 1 + + + + EOCW + write + + Clear + Clear flag + 0 + + + + + AWD + Analog watchdog flag + 0 + 1 + zeroToClear + + AWDR + read + + NoEvent + No analog watchdog event occurred + 0 + + + Event + Analog watchdog event occurred + 1 + + + + AWDW + write + + Clear + Clear flag + 0 + + + + + + + CR1 + CR1 + control register 1 + 0x4 + 0x20 + read-write + 0x00000000 + + + OVRIE + Overrun interrupt enable + 26 + 1 + + OVRIE + read-write + + Disabled + Overrun interrupt disabled + 0 + + + Enabled + Overrun interrupt enabled + 1 + + + + + RES + Resolution + 24 + 2 + + RES + read-write + + TwelveBit + 12-bit (15 ADCCLK cycles) + 0 + + + TenBit + 10-bit (13 ADCCLK cycles) + 1 + + + EightBit + 8-bit (11 ADCCLK cycles) + 2 + + + SixBit + 6-bit (9 ADCCLK cycles) + 3 + + + + + AWDEN + Analog watchdog enable on regular + channels + 23 + 1 + + AWDEN + read-write + + Disabled + Analog watchdog disabled on regular channels + 0 + + + Enabled + Analog watchdog enabled on regular channels + 1 + + + + + JAWDEN + Analog watchdog enable on injected + channels + 22 + 1 + + JAWDEN + read-write + + Disabled + Analog watchdog disabled on injected channels + 0 + + + Enabled + Analog watchdog enabled on injected channels + 1 + + + + + DISCNUM + Discontinuous mode channel + count + 13 + 3 + + + 0 + 7 + + + + + JDISCEN + Discontinuous mode on injected + channels + 12 + 1 + + JDISCEN + read-write + + Disabled + Discontinuous mode on injected channels disabled + 0 + + + Enabled + Discontinuous mode on injected channels enabled + 1 + + + + + DISCEN + Discontinuous mode on regular + channels + 11 + 1 + + DISCEN + read-write + + Disabled + Discontinuous mode on regular channels disabled + 0 + + + Enabled + Discontinuous mode on regular channels enabled + 1 + + + + + JAUTO + Automatic injected group + conversion + 10 + 1 + + JAUTO + read-write + + Disabled + Automatic injected group conversion disabled + 0 + + + Enabled + Automatic injected group conversion enabled + 1 + + + + + AWDSGL + Enable the watchdog on a single channel + in scan mode + 9 + 1 + + AWDSGL + read-write + + AllChannels + Analog watchdog enabled on all channels + 0 + + + SingleChannel + Analog watchdog enabled on a single channel + 1 + + + + + SCAN + Scan mode + 8 + 1 + + SCAN + read-write + + Disabled + Scan mode disabled + 0 + + + Enabled + Scan mode enabled + 1 + + + + + JEOCIE + Interrupt enable for injected + channels + 7 + 1 + + JEOCIE + read-write + + Disabled + JEOC interrupt disabled + 0 + + + Enabled + JEOC interrupt enabled + 1 + + + + + AWDIE + Analog watchdog interrupt + enable + 6 + 1 + + AWDIE + read-write + + Disabled + Analogue watchdog interrupt disabled + 0 + + + Enabled + Analogue watchdog interrupt enabled + 1 + + + + + EOCIE + Interrupt enable for EOC + 5 + 1 + + EOCIE + read-write + + Disabled + EOC interrupt disabled + 0 + + + Enabled + EOC interrupt enabled + 1 + + + + + AWDCH + Analog watchdog channel select + bits + 0 + 5 + + + 0 + 18 + + + + + + + CR2 + CR2 + control register 2 + 0x8 + 0x20 + read-write + 0x00000000 + + + SWSTART + Start conversion of regular + channels + 30 + 1 + + SWSTARTW + write + + Start + Starts conversion of regular channels + 1 + + + + + EXTEN + External trigger enable for regular + channels + 28 + 2 + + EXTEN + read-write + + Disabled + Trigger detection disabled + 0 + + + RisingEdge + Trigger detection on the rising edge + 1 + + + FallingEdge + Trigger detection on the falling edge + 2 + + + BothEdges + Trigger detection on both the rising and falling edges + 3 + + + + + EXTSEL + External event select for regular + group + 24 + 4 + + EXTSEL + read-write + + TIM1CC1 + Timer 1 CC1 event + 0 + + + TIM1CC2 + Timer 1 CC2 event + 1 + + + TIM1CC3 + Timer 1 CC3 event + 2 + + + TIM2CC2 + Timer 2 CC2 event + 3 + + + TIM2CC3 + Timer 2 CC3 event + 4 + + + TIM2CC4 + Timer 2 CC4 event + 5 + + + TIM2TRGO + Timer 2 TRGO event + 6 + + + TIM3CC1 + Timer 3 CC1 event + 7 + + + TIM3TRGO + Timer 3 TRGO event + 8 + + + TIM4CC4 + Timer 4 CC4 event + 9 + + + TIM5CC1 + Timer 5 CC1 event + 10 + + + TIM5CC2 + Timer 5 CC2 event + 11 + + + TIM5CC3 + Timer 5 CC3 event + 12 + + + EXTI11 + EXTI line 11 + 15 + + + + + JSWSTART + Start conversion of injected + channels + 22 + 1 + + JSWSTARTW + write + + Start + Starts conversion of injected channels + 1 + + + + + JEXTEN + External trigger enable for injected + channels + 20 + 2 + + JEXTEN + read-write + + Disabled + Trigger detection disabled + 0 + + + RisingEdge + Trigger detection on the rising edge + 1 + + + FallingEdge + Trigger detection on the falling edge + 2 + + + BothEdges + Trigger detection on both the rising and falling edges + 3 + + + + + JEXTSEL + External event select for injected + group + 16 + 4 + + JEXTSEL + read-write + + TIM1CC4 + Timer 1 CC4 event + 0 + + + TIM1TRGO + Timer 1 TRGO event + 1 + + + TIM2CC1 + Timer 2 CC1 event + 2 + + + TIM2TRGO + Timer 2 TRGO event + 3 + + + TIM3CC2 + Timer 3 CC2 event + 4 + + + TIM3CC4 + Timer 3 CC4 event + 5 + + + TIM4CC1 + Timer 4 CC1 event + 6 + + + TIM4CC2 + Timer 4 CC2 event + 7 + + + TIM4CC3 + Timer 4 CC3 event + 8 + + + TIM4TRGO + Timer 4 TRGO event + 9 + + + TIM5CC4 + Timer 5 CC4 event + 10 + + + TIM5TRGO + Timer 5 TRGO event + 11 + + + EXTI15 + EXTI line 15 + 15 + + + + + ALIGN + Data alignment + 11 + 1 + + ALIGN + read-write + + Right + Right alignment + 0 + + + Left + Left alignment + 1 + + + + + EOCS + End of conversion + selection + 10 + 1 + + EOCS + read-write + + EachSequence + The EOC bit is set at the end of each sequence of regular conversions + 0 + + + EachConversion + The EOC bit is set at the end of each regular conversion + 1 + + + + + DDS + DMA disable selection (for single ADC + mode) + 9 + 1 + + DDS + read-write + + Single + No new DMA request is issued after the last transfer + 0 + + + Continuous + DMA requests are issued as long as data are converted and DMA=1 + 1 + + + + + DMA + Direct memory access mode (for single + ADC mode) + 8 + 1 + + DMA + read-write + + Disabled + DMA mode disabled + 0 + + + Enabled + DMA mode enabled + 1 + + + + + CONT + Continuous conversion + 1 + 1 + + CONT + read-write + + Single + Single conversion mode + 0 + + + Continuous + Continuous conversion mode + 1 + + + + + ADON + A/D Converter ON / OFF + 0 + 1 + + ADON + read-write + + Disabled + Disable ADC conversion and go to power down mode + 0 + + + Enabled + Enable ADC + 1 + + + + + + + SMPR1 + SMPR1 + sample time register 1 + 0xC + 0x20 + read-write + 0x00000000 + + + SMP18 + Channel 18 sampling time selection + 24 + 3 + + + + SMP17 + Channel 17 sampling time selection + 21 + 3 + + + + SMP16 + Channel 16 sampling time selection + 18 + 3 + + + + SMP15 + Channel 15 sampling time selection + 15 + 3 + + + + SMP14 + Channel 14 sampling time selection + 12 + 3 + + + + SMP13 + Channel 13 sampling time selection + 9 + 3 + + + + SMP12 + Channel 12 sampling time selection + 6 + 3 + + + + SMP11 + Channel 11 sampling time selection + 3 + 3 + + + + SMP10 + Channel 10 sampling time selection + 0 + 3 + + SMP10 + read-write + + Cycles3 + 3 cycles + 0 + + + Cycles15 + 15 cycles + 1 + + + Cycles28 + 28 cycles + 2 + + + Cycles56 + 56 cycles + 3 + + + Cycles84 + 84 cycles + 4 + + + Cycles112 + 112 cycles + 5 + + + Cycles144 + 144 cycles + 6 + + + Cycles480 + 480 cycles + 7 + + + + + + + SMPR2 + SMPR2 + sample time register 2 + 0x10 + 0x20 + read-write + 0x00000000 + + + SMP9 + Channel 9 sampling time selection + 27 + 3 + + + + SMP8 + Channel 8 sampling time selection + 24 + 3 + + + + SMP7 + Channel 7 sampling time selection + 21 + 3 + + + + SMP6 + Channel 6 sampling time selection + 18 + 3 + + + + SMP5 + Channel 5 sampling time selection + 15 + 3 + + + + SMP4 + Channel 4 sampling time selection + 12 + 3 + + + + SMP3 + Channel 3 sampling time selection + 9 + 3 + + + + SMP2 + Channel 2 sampling time selection + 6 + 3 + + + + SMP1 + Channel 1 sampling time selection + 3 + 3 + + + + SMP0 + Channel 0 sampling time selection + 0 + 3 + + SMP0 + read-write + + Cycles3 + 3 cycles + 0 + + + Cycles15 + 15 cycles + 1 + + + Cycles28 + 28 cycles + 2 + + + Cycles56 + 56 cycles + 3 + + + Cycles84 + 84 cycles + 4 + + + Cycles112 + 112 cycles + 5 + + + Cycles144 + 144 cycles + 6 + + + Cycles480 + 480 cycles + 7 + + + + + + + 4 + 0x4 + 1-4 + JOFR%s + JOFR1 + injected channel data offset register + x + 0x14 + 0x20 + read-write + 0x00000000 + + + JOFFSET + Data offset for injected channel + x + 0 + 12 + + + 0 + 4095 + + + + + + + HTR + HTR + watchdog higher threshold + register + 0x24 + 0x20 + read-write + 0x00000FFF + + + HT + Analog watchdog higher + threshold + 0 + 12 + + + 0 + 4095 + + + + + + + LTR + LTR + watchdog lower threshold + register + 0x28 + 0x20 + read-write + 0x00000000 + + + LT + Analog watchdog lower + threshold + 0 + 12 + + + 0 + 4095 + + + + + + + SQR1 + SQR1 + regular sequence register 1 + 0x2C + 0x20 + read-write + 0x00000000 + + + L + Regular channel sequence + length + 20 + 4 + + + 0 + 15 + + + + + SQ16 + 16th conversion in regular + sequence + 15 + 5 + + + 0 + 18 + + + + + SQ15 + 15th conversion in regular + sequence + 10 + 5 + + + 0 + 18 + + + + + SQ14 + 14th conversion in regular + sequence + 5 + 5 + + + 0 + 18 + + + + + SQ13 + 13th conversion in regular + sequence + 0 + 5 + + + 0 + 18 + + + + + + + SQR2 + SQR2 + regular sequence register 2 + 0x30 + 0x20 + read-write + 0x00000000 + + + SQ12 + 12th conversion in regular + sequence + 25 + 5 + + + 0 + 18 + + + + + SQ11 + 11th conversion in regular + sequence + 20 + 5 + + + 0 + 18 + + + + + SQ10 + 10th conversion in regular + sequence + 15 + 5 + + + 0 + 18 + + + + + SQ9 + 9th conversion in regular + sequence + 10 + 5 + + + 0 + 18 + + + + + SQ8 + 8th conversion in regular + sequence + 5 + 5 + + + 0 + 18 + + + + + SQ7 + 7th conversion in regular + sequence + 0 + 5 + + + 0 + 18 + + + + + + + SQR3 + SQR3 + regular sequence register 3 + 0x34 + 0x20 + read-write + 0x00000000 + + + SQ6 + 6th conversion in regular + sequence + 25 + 5 + + + 0 + 18 + + + + + SQ5 + 5th conversion in regular + sequence + 20 + 5 + + + 0 + 18 + + + + + SQ4 + 4th conversion in regular + sequence + 15 + 5 + + + 0 + 18 + + + + + SQ3 + 3rd conversion in regular + sequence + 10 + 5 + + + 0 + 18 + + + + + SQ2 + 2nd conversion in regular + sequence + 5 + 5 + + + 0 + 18 + + + + + SQ1 + 1st conversion in regular + sequence + 0 + 5 + + + 0 + 18 + + + + + + + JSQR + JSQR + injected sequence register + 0x38 + 0x20 + read-write + 0x00000000 + + + JL + Injected sequence length + 20 + 2 + + + 0 + 3 + + + + + JSQ4 + 4th conversion in injected + sequence + 15 + 5 + + + 0 + 18 + + + + + JSQ3 + 3rd conversion in injected + sequence + 10 + 5 + + + 0 + 18 + + + + + JSQ2 + 2nd conversion in injected + sequence + 5 + 5 + + + 0 + 18 + + + + + JSQ1 + 1st conversion in injected + sequence + 0 + 5 + + + 0 + 18 + + + + + + + 4 + 0x4 + 1-4 + JDR%s + JDR1 + injected data register x + 0x3C + 0x20 + read-only + 0x00000000 + + + JDATA + Injected data + 0 + 16 + + + + + DR + DR + regular data register + 0x4C + 0x20 + read-only + 0x00000000 + + + DATA + Regular data + 0 + 16 + + + + + + + CRC + Cryptographic processor + CRC + 0x40023000 + + 0x0 + 0x400 + registers + + + + DR + DR + Data register + 0x0 + 0x20 + read-write + 0xFFFFFFFF + + + DR + Data Register + 0 + 32 + + + 0 + 4294967295 + + + + + + + IDR + IDR + Independent Data register + 0x4 + 0x20 + read-write + 0x00000000 + + + IDR + Independent Data register + 0 + 8 + + + 0 + 255 + + + + + + + CR + CR + Control register + 0x8 + 0x20 + write-only + 0x00000000 + + + RESET + Control regidter + 0 + 1 + + RESETW + write + + Reset + Resets the CRC calculation unit and sets the data register to 0xFFFF FFFF + 1 + + + + + + + + + DBGMCU + Debug support + DBG + 0xE0042000 + + 0x0 + 0x400 + registers + + + + IDCODE + IDCODE + IDCODE + 0x0 + 0x20 + read-only + 0x10006411 + + + DEV_ID + DEV_ID + 0 + 12 + + + REV_ID + REV_ID + 16 + 16 + + + + + CR + CR + Control Register + 0x4 + 0x20 + read-write + 0x00000000 + + + DBG_SLEEP + DBG_SLEEP + 0 + 1 + + + DBG_STOP + DBG_STOP + 1 + 1 + + + DBG_STANDBY + DBG_STANDBY + 2 + 1 + + + TRACE_IOEN + TRACE_IOEN + 5 + 1 + + + TRACE_MODE + TRACE_MODE + 6 + 2 + + + + + APB1_FZ + APB1_FZ + Debug MCU APB1 Freeze registe + 0x8 + 0x20 + read-write + 0x00000000 + + + DBG_TIM2_STOP + DBG_TIM2_STOP + 0 + 1 + + + DBG_TIM3_STOP + DBG_TIM3 _STOP + 1 + 1 + + + DBG_TIM4_STOP + DBG_TIM4_STOP + 2 + 1 + + + DBG_TIM5_STOP + DBG_TIM5_STOP + 3 + 1 + + + DBG_RTC_Stop + RTC stopped when Core is + halted + 10 + 1 + + + DBG_WWDG_STOP + DBG_WWDG_STOP + 11 + 1 + + + DBG_IWDG_STOP + DBG_IWDEG_STOP + 12 + 1 + + + DBG_I2C1_SMBUS_TIMEOUT + DBG_J2C1_SMBUS_TIMEOUT + 21 + 1 + + + DBG_I2C2_SMBUS_TIMEOUT + DBG_J2C2_SMBUS_TIMEOUT + 22 + 1 + + + DBG_I2C3SMBUS_TIMEOUT + DBG_J2C3SMBUS_TIMEOUT + 23 + 1 + + + + + APB2_FZ + APB2_FZ + Debug MCU APB2 Freeze registe + 0xC + 0x20 + read-write + 0x00000000 + + + DBG_TIM1_STOP + TIM1 counter stopped when core is + halted + 0 + 1 + + + DBG_TIM9_STOP + TIM9 counter stopped when core is + halted + 16 + 1 + + + DBG_TIM10_STOP + TIM10 counter stopped when core is + halted + 17 + 1 + + + DBG_TIM11_STOP + TIM11 counter stopped when core is + halted + 18 + 1 + + + + + + + EXTI + External interrupt/event + controller + EXTI + 0x40013C00 + + 0x0 + 0x400 + registers + + + TAMP_STAMP + Tamper and TimeStamp interrupts through the + EXTI line + 2 + + + EXTI0 + EXTI Line0 interrupt + 6 + + + EXTI1 + EXTI Line1 interrupt + 7 + + + EXTI2 + EXTI Line2 interrupt + 8 + + + EXTI3 + EXTI Line3 interrupt + 9 + + + EXTI4 + EXTI Line4 interrupt + 10 + + + EXTI9_5 + EXTI Line[9:5] interrupts + 23 + + + EXTI15_10 + EXTI Line[15:10] interrupts + 40 + + + + IMR + IMR + Interrupt mask register + (EXTI_IMR) + 0x0 + 0x20 + read-write + 0x00000000 + + + MR0 + Interrupt Mask on line 0 + 0 + 1 + + MR0 + read-write + + Masked + Interrupt request line is masked + 0 + + + Unmasked + Interrupt request line is unmasked + 1 + + + + + MR1 + Interrupt Mask on line 1 + 1 + 1 + + + + MR2 + Interrupt Mask on line 2 + 2 + 1 + + + + MR3 + Interrupt Mask on line 3 + 3 + 1 + + + + MR4 + Interrupt Mask on line 4 + 4 + 1 + + + + MR5 + Interrupt Mask on line 5 + 5 + 1 + + + + MR6 + Interrupt Mask on line 6 + 6 + 1 + + + + MR7 + Interrupt Mask on line 7 + 7 + 1 + + + + MR8 + Interrupt Mask on line 8 + 8 + 1 + + + + MR9 + Interrupt Mask on line 9 + 9 + 1 + + + + MR10 + Interrupt Mask on line 10 + 10 + 1 + + + + MR11 + Interrupt Mask on line 11 + 11 + 1 + + + + MR12 + Interrupt Mask on line 12 + 12 + 1 + + + + MR13 + Interrupt Mask on line 13 + 13 + 1 + + + + MR14 + Interrupt Mask on line 14 + 14 + 1 + + + + MR15 + Interrupt Mask on line 15 + 15 + 1 + + + + MR16 + Interrupt Mask on line 16 + 16 + 1 + + + + MR17 + Interrupt Mask on line 17 + 17 + 1 + + + + MR18 + Interrupt Mask on line 18 + 18 + 1 + + + + MR19 + Interrupt Mask on line 19 + 19 + 1 + + + + MR20 + Interrupt Mask on line 20 + 20 + 1 + + + + MR21 + Interrupt Mask on line 21 + 21 + 1 + + + + MR22 + Interrupt Mask on line 22 + 22 + 1 + + + + + + EMR + EMR + Event mask register (EXTI_EMR) + 0x4 + 0x20 + read-write + 0x00000000 + + + MR0 + Event Mask on line 0 + 0 + 1 + + MR0 + read-write + + Masked + Interrupt request line is masked + 0 + + + Unmasked + Interrupt request line is unmasked + 1 + + + + + MR1 + Event Mask on line 1 + 1 + 1 + + + + MR2 + Event Mask on line 2 + 2 + 1 + + + + MR3 + Event Mask on line 3 + 3 + 1 + + + + MR4 + Event Mask on line 4 + 4 + 1 + + + + MR5 + Event Mask on line 5 + 5 + 1 + + + + MR6 + Event Mask on line 6 + 6 + 1 + + + + MR7 + Event Mask on line 7 + 7 + 1 + + + + MR8 + Event Mask on line 8 + 8 + 1 + + + + MR9 + Event Mask on line 9 + 9 + 1 + + + + MR10 + Event Mask on line 10 + 10 + 1 + + + + MR11 + Event Mask on line 11 + 11 + 1 + + + + MR12 + Event Mask on line 12 + 12 + 1 + + + + MR13 + Event Mask on line 13 + 13 + 1 + + + + MR14 + Event Mask on line 14 + 14 + 1 + + + + MR15 + Event Mask on line 15 + 15 + 1 + + + + MR16 + Event Mask on line 16 + 16 + 1 + + + + MR17 + Event Mask on line 17 + 17 + 1 + + + + MR18 + Event Mask on line 18 + 18 + 1 + + + + MR19 + Event Mask on line 19 + 19 + 1 + + + + MR20 + Event Mask on line 20 + 20 + 1 + + + + MR21 + Event Mask on line 21 + 21 + 1 + + + + MR22 + Event Mask on line 22 + 22 + 1 + + + + + + RTSR + RTSR + Rising Trigger selection register + (EXTI_RTSR) + 0x8 + 0x20 + read-write + 0x00000000 + + + TR0 + Rising trigger event configuration of + line 0 + 0 + 1 + + TR0 + read-write + + Disabled + Rising edge trigger is disabled + 0 + + + Enabled + Rising edge trigger is enabled + 1 + + + + + TR1 + Rising trigger event configuration of + line 1 + 1 + 1 + + + + TR2 + Rising trigger event configuration of + line 2 + 2 + 1 + + + + TR3 + Rising trigger event configuration of + line 3 + 3 + 1 + + + + TR4 + Rising trigger event configuration of + line 4 + 4 + 1 + + + + TR5 + Rising trigger event configuration of + line 5 + 5 + 1 + + + + TR6 + Rising trigger event configuration of + line 6 + 6 + 1 + + + + TR7 + Rising trigger event configuration of + line 7 + 7 + 1 + + + + TR8 + Rising trigger event configuration of + line 8 + 8 + 1 + + + + TR9 + Rising trigger event configuration of + line 9 + 9 + 1 + + + + TR10 + Rising trigger event configuration of + line 10 + 10 + 1 + + + + TR11 + Rising trigger event configuration of + line 11 + 11 + 1 + + + + TR12 + Rising trigger event configuration of + line 12 + 12 + 1 + + + + TR13 + Rising trigger event configuration of + line 13 + 13 + 1 + + + + TR14 + Rising trigger event configuration of + line 14 + 14 + 1 + + + + TR15 + Rising trigger event configuration of + line 15 + 15 + 1 + + + + TR16 + Rising trigger event configuration of + line 16 + 16 + 1 + + + + TR17 + Rising trigger event configuration of + line 17 + 17 + 1 + + + + TR18 + Rising trigger event configuration of + line 18 + 18 + 1 + + + + TR19 + Rising trigger event configuration of + line 19 + 19 + 1 + + + + TR20 + Rising trigger event configuration of + line 20 + 20 + 1 + + + + TR21 + Rising trigger event configuration of + line 21 + 21 + 1 + + + + TR22 + Rising trigger event configuration of + line 22 + 22 + 1 + + + + + + FTSR + FTSR + Falling Trigger selection register + (EXTI_FTSR) + 0xC + 0x20 + read-write + 0x00000000 + + + TR0 + Falling trigger event configuration of + line 0 + 0 + 1 + + TR0 + read-write + + Disabled + Falling edge trigger is disabled + 0 + + + Enabled + Falling edge trigger is enabled + 1 + + + + + TR1 + Falling trigger event configuration of + line 1 + 1 + 1 + + + + TR2 + Falling trigger event configuration of + line 2 + 2 + 1 + + + + TR3 + Falling trigger event configuration of + line 3 + 3 + 1 + + + + TR4 + Falling trigger event configuration of + line 4 + 4 + 1 + + + + TR5 + Falling trigger event configuration of + line 5 + 5 + 1 + + + + TR6 + Falling trigger event configuration of + line 6 + 6 + 1 + + + + TR7 + Falling trigger event configuration of + line 7 + 7 + 1 + + + + TR8 + Falling trigger event configuration of + line 8 + 8 + 1 + + + + TR9 + Falling trigger event configuration of + line 9 + 9 + 1 + + + + TR10 + Falling trigger event configuration of + line 10 + 10 + 1 + + + + TR11 + Falling trigger event configuration of + line 11 + 11 + 1 + + + + TR12 + Falling trigger event configuration of + line 12 + 12 + 1 + + + + TR13 + Falling trigger event configuration of + line 13 + 13 + 1 + + + + TR14 + Falling trigger event configuration of + line 14 + 14 + 1 + + + + TR15 + Falling trigger event configuration of + line 15 + 15 + 1 + + + + TR16 + Falling trigger event configuration of + line 16 + 16 + 1 + + + + TR17 + Falling trigger event configuration of + line 17 + 17 + 1 + + + + TR18 + Falling trigger event configuration of + line 18 + 18 + 1 + + + + TR19 + Falling trigger event configuration of + line 19 + 19 + 1 + + + + TR20 + Falling trigger event configuration of + line 20 + 20 + 1 + + + + TR21 + Falling trigger event configuration of + line 21 + 21 + 1 + + + + TR22 + Falling trigger event configuration of + line 22 + 22 + 1 + + + + + + SWIER + SWIER + Software interrupt event register + (EXTI_SWIER) + 0x10 + 0x20 + read-write + 0x00000000 + + + SWIER0 + Software Interrupt on line + 0 + 0 + 1 + + SWIER0W + write + + Pend + Generates an interrupt request + 1 + + + + + SWIER1 + Software Interrupt on line + 1 + 1 + 1 + + + + SWIER2 + Software Interrupt on line + 2 + 2 + 1 + + + + SWIER3 + Software Interrupt on line + 3 + 3 + 1 + + + + SWIER4 + Software Interrupt on line + 4 + 4 + 1 + + + + SWIER5 + Software Interrupt on line + 5 + 5 + 1 + + + + SWIER6 + Software Interrupt on line + 6 + 6 + 1 + + + + SWIER7 + Software Interrupt on line + 7 + 7 + 1 + + + + SWIER8 + Software Interrupt on line + 8 + 8 + 1 + + + + SWIER9 + Software Interrupt on line + 9 + 9 + 1 + + + + SWIER10 + Software Interrupt on line + 10 + 10 + 1 + + + + SWIER11 + Software Interrupt on line + 11 + 11 + 1 + + + + SWIER12 + Software Interrupt on line + 12 + 12 + 1 + + + + SWIER13 + Software Interrupt on line + 13 + 13 + 1 + + + + SWIER14 + Software Interrupt on line + 14 + 14 + 1 + + + + SWIER15 + Software Interrupt on line + 15 + 15 + 1 + + + + SWIER16 + Software Interrupt on line + 16 + 16 + 1 + + + + SWIER17 + Software Interrupt on line + 17 + 17 + 1 + + + + SWIER18 + Software Interrupt on line + 18 + 18 + 1 + + + + SWIER19 + Software Interrupt on line + 19 + 19 + 1 + + + + SWIER20 + Software Interrupt on line + 20 + 20 + 1 + + + + SWIER21 + Software Interrupt on line + 21 + 21 + 1 + + + + SWIER22 + Software Interrupt on line + 22 + 22 + 1 + + + + + + PR + PR + Pending register (EXTI_PR) + 0x14 + 0x20 + read-write + 0x00000000 + + + PR0 + Pending bit 0 + 0 + 1 + oneToClear + + PR0R + read + + NotPending + No trigger request occurred + 0 + + + Pending + Selected trigger request occurred + 1 + + + + PR0W + write + + Clear + Clears pending bit + 1 + + + + + PR1 + Pending bit 1 + 1 + 1 + oneToClear + + read + + + write + + + + PR2 + Pending bit 2 + 2 + 1 + oneToClear + + read + + + write + + + + PR3 + Pending bit 3 + 3 + 1 + oneToClear + + read + + + write + + + + PR4 + Pending bit 4 + 4 + 1 + oneToClear + + read + + + write + + + + PR5 + Pending bit 5 + 5 + 1 + oneToClear + + read + + + write + + + + PR6 + Pending bit 6 + 6 + 1 + oneToClear + + read + + + write + + + + PR7 + Pending bit 7 + 7 + 1 + oneToClear + + read + + + write + + + + PR8 + Pending bit 8 + 8 + 1 + oneToClear + + read + + + write + + + + PR9 + Pending bit 9 + 9 + 1 + oneToClear + + read + + + write + + + + PR10 + Pending bit 10 + 10 + 1 + oneToClear + + read + + + write + + + + PR11 + Pending bit 11 + 11 + 1 + oneToClear + + read + + + write + + + + PR12 + Pending bit 12 + 12 + 1 + oneToClear + + read + + + write + + + + PR13 + Pending bit 13 + 13 + 1 + oneToClear + + read + + + write + + + + PR14 + Pending bit 14 + 14 + 1 + oneToClear + + read + + + write + + + + PR15 + Pending bit 15 + 15 + 1 + oneToClear + + read + + + write + + + + PR16 + Pending bit 16 + 16 + 1 + oneToClear + + read + + + write + + + + PR17 + Pending bit 17 + 17 + 1 + oneToClear + + read + + + write + + + + PR18 + Pending bit 18 + 18 + 1 + oneToClear + + read + + + write + + + + PR19 + Pending bit 19 + 19 + 1 + oneToClear + + read + + + write + + + + PR20 + Pending bit 20 + 20 + 1 + oneToClear + + read + + + write + + + + PR21 + Pending bit 21 + 21 + 1 + oneToClear + + read + + + write + + + + PR22 + Pending bit 22 + 22 + 1 + oneToClear + + read + + + write + + + + + + + + FLASH + FLASH + FLASH + 0x40023C00 + + 0x0 + 0x400 + registers + + + FLASH + FLASH global interrupt + 4 + + + + ACR + ACR + Flash access control register + 0x0 + 0x20 + 0x00000000 + + + LATENCY + Latency + 0 + 4 + read-write + + LATENCY + read-write + + WS0 + 0 wait states + 0 + + + WS1 + 1 wait states + 1 + + + WS2 + 2 wait states + 2 + + + WS3 + 3 wait states + 3 + + + WS4 + 4 wait states + 4 + + + WS5 + 5 wait states + 5 + + + WS6 + 6 wait states + 6 + + + WS7 + 7 wait states + 7 + + + WS8 + 8 wait states + 8 + + + WS9 + 9 wait states + 9 + + + WS10 + 10 wait states + 10 + + + WS11 + 11 wait states + 11 + + + WS12 + 12 wait states + 12 + + + WS13 + 13 wait states + 13 + + + WS14 + 14 wait states + 14 + + + WS15 + 15 wait states + 15 + + + + + PRFTEN + Prefetch enable + 8 + 1 + read-write + + PRFTEN + read-write + + Disabled + Prefetch is disabled + 0 + + + Enabled + Prefetch is enabled + 1 + + + + + ICEN + Instruction cache enable + 9 + 1 + read-write + + ICEN + read-write + + Disabled + Instruction cache is disabled + 0 + + + Enabled + Instruction cache is enabled + 1 + + + + + DCEN + Data cache enable + 10 + 1 + read-write + + DCEN + read-write + + Disabled + Data cache is disabled + 0 + + + Enabled + Data cache is enabled + 1 + + + + + ICRST + Instruction cache reset + 11 + 1 + write-only + + ICRST + write + + NotReset + Instruction cache is not reset + 0 + + + Reset + Instruction cache is reset + 1 + + + + + DCRST + Data cache reset + 12 + 1 + read-write + + DCRST + read-write + + NotReset + Data cache is not reset + 0 + + + Reset + Data cache is reset + 1 + + + + + + + KEYR + KEYR + Flash key register + 0x4 + 0x20 + write-only + 0x00000000 + + + KEY + FPEC key + 0 + 32 + + + 0 + 4294967295 + + + + + + + OPTKEYR + OPTKEYR + Flash option key register + 0x8 + 0x20 + write-only + 0x00000000 + + + OPTKEY + Option byte key + 0 + 32 + + + 0 + 4294967295 + + + + + + + SR + SR + Status register + 0xC + 0x20 + 0x00000000 + + + EOP + End of operation + 0 + 1 + read-write + oneToClear + + EOPW + write + + Clear + Clear error flag + 1 + + + + + OPERR + Operation error + 1 + 1 + read-write + oneToClear + + OPERRW + write + + Clear + Clear error flag + 1 + + + + + WRPERR + Write protection error + 4 + 1 + read-write + oneToClear + + WRPERRW + write + + Clear + Clear error flag + 1 + + + + + PGAERR + Programming alignment + error + 5 + 1 + read-write + oneToClear + + PGAERRW + write + + Clear + Clear error flag + 1 + + + + + PGPERR + Programming parallelism + error + 6 + 1 + read-write + oneToClear + + PGPERRW + write + + Clear + Clear error flag + 1 + + + + + PGSERR + Programming sequence error + 7 + 1 + read-write + oneToClear + + PGSERRW + write + + Clear + Clear error flag + 1 + + + + + BSY + Busy + 16 + 1 + read-only + + BSYR + read + + NotBusy + no Flash memory operation ongoing + 0 + + + Busy + Flash memory operation ongoing + 1 + + + + + + + CR + CR + Control register + 0x10 + 0x20 + read-write + 0x80000000 + + + PG + Programming + 0 + 1 + + PG + read-write + + Program + Flash programming activated + 1 + + + + + SER + Sector Erase + 1 + 1 + + SER + read-write + + SectorErase + Erase activated for selected sector + 1 + + + + + MER + Mass Erase + 2 + 1 + + MER + read-write + + MassErase + Erase activated for all user sectors + 1 + + + + + SNB + Sector number + 3 + 4 + + + 0 + 11 + + + + + PSIZE + Program size + 8 + 2 + + PSIZE + read-write + + PSIZE8 + Program x8 + 0 + + + PSIZE16 + Program x16 + 1 + + + PSIZE32 + Program x32 + 2 + + + PSIZE64 + Program x64 + 3 + + + + + STRT + Start + 16 + 1 + + STRT + read-write + + Start + Trigger an erase operation + 1 + + + + + EOPIE + End of operation interrupt + enable + 24 + 1 + + EOPIE + read-write + + Disabled + End of operation interrupt disabled + 0 + + + Enabled + End of operation interrupt enabled + 1 + + + + + ERRIE + Error interrupt enable + 25 + 1 + + ERRIE + read-write + + Disabled + Error interrupt generation disabled + 0 + + + Enabled + Error interrupt generation enabled + 1 + + + + + LOCK + Lock + 31 + 1 + + LOCK + read-write + + Unlocked + FLASH_CR register is unlocked + 0 + + + Locked + FLASH_CR register is locked + 1 + + + + + + + OPTCR + OPTCR + Flash option control register + 0x14 + 0x20 + read-write + 0x00000014 + + + OPTLOCK + Option lock + 0 + 1 + + + OPTSTRT + Option start + 1 + 1 + + + BOR_LEV + BOR reset Level + 2 + 2 + + + WDG_SW + WDG_SW User option bytes + 5 + 1 + + + nRST_STOP + nRST_STOP User option + bytes + 6 + 1 + + + nRST_STDBY + nRST_STDBY User option + bytes + 7 + 1 + + + RDP + Read protect + 8 + 8 + + + nWRP + Not write protect + 16 + 12 + + + + + + + IWDG + Independent watchdog + IWDG + 0x40003000 + + 0x0 + 0x400 + registers + + + + KR + KR + Key register + 0x0 + 0x20 + write-only + 0x00000000 + + + KEY + Key value + 0 + 16 + + KEY + write + + Enable + Enable access to PR, RLR and WINR registers (0x5555) + 21845 + + + Reset + Reset the watchdog value (0xAAAA) + 43690 + + + Start + Start the watchdog (0xCCCC) + 52428 + + + + + + + PR + PR + Prescaler register + 0x4 + 0x20 + read-write + 0x00000000 + + + PR + Prescaler divider + 0 + 3 + + PR + read-write + + DivideBy4 + Divider /4 + 0 + + + DivideBy8 + Divider /8 + 1 + + + DivideBy16 + Divider /16 + 2 + + + DivideBy32 + Divider /32 + 3 + + + DivideBy64 + Divider /64 + 4 + + + DivideBy128 + Divider /128 + 5 + + + DivideBy256 + Divider /256 + 6 + + + DivideBy256bis + Divider /256 + 7 + + + + + + + RLR + RLR + Reload register + 0x8 + 0x20 + read-write + 0x00000FFF + + + RL + Watchdog counter reload + value + 0 + 12 + + + 0 + 4095 + + + + + + + SR + SR + Status register + 0xC + 0x20 + read-only + 0x00000000 + + + RVU + Watchdog counter reload value + update + 1 + 1 + + + PVU + Watchdog prescaler value + update + 0 + 1 + + + + + + + OTG_FS_DEVICE + USB on the go full speed + USB_OTG_FS + 0x50000800 + + 0x0 + 0x400 + registers + + + + DCFG + DCFG + OTG_FS device configuration register + (OTG_FS_DCFG) + 0x0 + 0x20 + read-write + 0x02200000 + + + DSPD + Device speed + 0 + 2 + + + NZLSOHSK + Non-zero-length status OUT + handshake + 2 + 1 + + + DAD + Device address + 4 + 7 + + + PFIVL + Periodic frame interval + 11 + 2 + + + + + DCTL + DCTL + OTG_FS device control register + (OTG_FS_DCTL) + 0x4 + 0x20 + 0x00000000 + + + RWUSIG + Remote wakeup signaling + 0 + 1 + read-write + + + SDIS + Soft disconnect + 1 + 1 + read-write + + + GINSTS + Global IN NAK status + 2 + 1 + read-only + + + GONSTS + Global OUT NAK status + 3 + 1 + read-only + + + TCTL + Test control + 4 + 3 + read-write + + + SGINAK + Set global IN NAK + 7 + 1 + read-write + + + CGINAK + Clear global IN NAK + 8 + 1 + read-write + + + SGONAK + Set global OUT NAK + 9 + 1 + read-write + + + CGONAK + Clear global OUT NAK + 10 + 1 + read-write + + + POPRGDNE + Power-on programming done + 11 + 1 + read-write + + + + + DSTS + DSTS + OTG_FS device status register + (OTG_FS_DSTS) + 0x8 + 0x20 + read-only + 0x00000010 + + + SUSPSTS + Suspend status + 0 + 1 + + + ENUMSPD + Enumerated speed + 1 + 2 + + + EERR + Erratic error + 3 + 1 + + + FNSOF + Frame number of the received + SOF + 8 + 14 + + + + + DIEPMSK + DIEPMSK + OTG_FS device IN endpoint common interrupt + mask register (OTG_FS_DIEPMSK) + 0x10 + 0x20 + read-write + 0x00000000 + + + XFRCM + Transfer completed interrupt + mask + 0 + 1 + + + EPDM + Endpoint disabled interrupt + mask + 1 + 1 + + + TOM + Timeout condition mask (Non-isochronous + endpoints) + 3 + 1 + + + ITTXFEMSK + IN token received when TxFIFO empty + mask + 4 + 1 + + + INEPNMM + IN token received with EP mismatch + mask + 5 + 1 + + + INEPNEM + IN endpoint NAK effective + mask + 6 + 1 + + + + + DOEPMSK + DOEPMSK + OTG_FS device OUT endpoint common interrupt + mask register (OTG_FS_DOEPMSK) + 0x14 + 0x20 + read-write + 0x00000000 + + + XFRCM + Transfer completed interrupt + mask + 0 + 1 + + + EPDM + Endpoint disabled interrupt + mask + 1 + 1 + + + STUPM + SETUP phase done mask + 3 + 1 + + + OTEPDM + OUT token received when endpoint + disabled mask + 4 + 1 + + + + + DAINT + DAINT + OTG_FS device all endpoints interrupt + register (OTG_FS_DAINT) + 0x18 + 0x20 + read-only + 0x00000000 + + + IEPINT + IN endpoint interrupt bits + 0 + 16 + + + OEPINT + OUT endpoint interrupt + bits + 16 + 16 + + + + + DAINTMSK + DAINTMSK + OTG_FS all endpoints interrupt mask register + (OTG_FS_DAINTMSK) + 0x1C + 0x20 + read-write + 0x00000000 + + + IEPM + IN EP interrupt mask bits + 0 + 16 + + + OEPM + OUT EP interrupt mask bits + 16 + 16 + + + + + DVBUSDIS + DVBUSDIS + OTG_FS device VBUS discharge time + register + 0x28 + 0x20 + read-write + 0x000017D7 + + + VBUSDT + Device VBUS discharge time + 0 + 16 + + + + + DVBUSPULSE + DVBUSPULSE + OTG_FS device VBUS pulsing time + register + 0x2C + 0x20 + read-write + 0x000005B8 + + + DVBUSP + Device VBUS pulsing time + 0 + 12 + + + + + DIEPEMPMSK + DIEPEMPMSK + OTG_FS device IN endpoint FIFO empty + interrupt mask register + 0x34 + 0x20 + read-write + 0x00000000 + + + INEPTXFEM + IN EP Tx FIFO empty interrupt mask + bits + 0 + 16 + + + + + DIEP0 + Device IN endpoint 0 + 0x100 + + CTL + DIEPCTL0 + OTG_FS device control IN endpoint 0 control + register (OTG_FS_DIEPCTL0) + 0x0 + 0x20 + 0x00000000 + + + MPSIZ + Maximum packet size + 0 + 2 + read-write + + + USBAEP + USB active endpoint + 15 + 1 + read-only + + + NAKSTS + NAK status + 17 + 1 + read-only + + + EPTYP + Endpoint type + 18 + 2 + read-only + + + STALL + STALL handshake + 21 + 1 + read-write + + + TXFNUM + TxFIFO number + 22 + 4 + read-write + + + CNAK + Clear NAK + 26 + 1 + write-only + + + SNAK + Set NAK + 27 + 1 + write-only + + + EPDIS + Endpoint disable + 30 + 1 + read-only + + + EPENA + Endpoint enable + 31 + 1 + read-write + + + + + INT + DIEPINT0 + device endpoint-x interrupt + register + 0x8 + 0x20 + 0x00000080 + + + TXFE + TXFE + 7 + 1 + read-only + + + INEPNE + INEPNE + 6 + 1 + read-write + + + ITTXFE + ITTXFE + 4 + 1 + read-write + + + TOC + TOC + 3 + 1 + read-write + + + EPDISD + EPDISD + 1 + 1 + read-write + + + XFRC + XFRC + 0 + 1 + read-write + + + + + TSIZ + DIEPTSIZ0 + device endpoint-0 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + PKTCNT + Packet count + 19 + 2 + + + XFRSIZ + Transfer size + 0 + 7 + + + + + TXFSTS + DTXFSTS0 + OTG_FS device IN endpoint transmit FIFO + status register + 0x18 + 0x20 + read-only + 0x00000000 + + + INEPTFSAV + IN endpoint TxFIFO space + available + 0 + 16 + + + + + + 3 + 0x20 + 1-3 + DIEP%s + Device IN endpoint X + 0x120 + + CTL + DIEPCTL1 + OTG device endpoint-1 control + register + 0x0 + 0x20 + 0x00000000 + + + EPENA + EPENA + 31 + 1 + read-write + + + EPDIS + EPDIS + 30 + 1 + read-write + + + SODDFRM_SD1PID + SODDFRM/SD1PID + 29 + 1 + write-only + + + SD0PID_SEVNFRM + SD0PID/SEVNFRM + 28 + 1 + write-only + + + SNAK + SNAK + 27 + 1 + write-only + + + CNAK + CNAK + 26 + 1 + write-only + + + TXFNUM + TXFNUM + 22 + 4 + read-write + + + STALL + STALL handshake + 21 + 1 + read-write + + + EPTYP + EPTYP + 18 + 2 + read-write + + + NAKSTS + NAKSTS + 17 + 1 + read-only + + + EONUM_DPID + EONUM/DPID + 16 + 1 + read-only + + + USBAEP + USBAEP + 15 + 1 + read-write + + + MPSIZ + MPSIZ + 0 + 11 + read-write + + + + + INT + DIEPINT1 + device endpoint-1 interrupt + register + 0x8 + 0x20 + 0x00000080 + + + TXFE + TXFE + 7 + 1 + read-only + + + INEPNE + INEPNE + 6 + 1 + read-write + + + ITTXFE + ITTXFE + 4 + 1 + read-write + + + TOC + TOC + 3 + 1 + read-write + + + EPDISD + EPDISD + 1 + 1 + read-write + + + XFRC + XFRC + 0 + 1 + read-write + + + + + TSIZ + DIEPTSIZ1 + device endpoint-1 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + MCNT + Multi count + 29 + 2 + + + PKTCNT + Packet count + 19 + 10 + + + XFRSIZ + Transfer size + 0 + 19 + + + + + TXFSTS + DTXFSTS1 + OTG_FS device IN endpoint transmit FIFO + status register + 0x18 + 0x20 + read-only + 0x00000000 + + + INEPTFSAV + IN endpoint TxFIFO space + available + 0 + 16 + + + + + + DOEP0 + Device OUT endpoint 0 + 0x300 + + CTL + DOEPCTL0 + device endpoint-0 control + register + 0x0 + 0x20 + 0x00008000 + + + EPENA + EPENA + 31 + 1 + read-write + + + EPDIS + EPDIS + 30 + 1 + read-only + + + SNAK + SNAK + 27 + 1 + write-only + + + CNAK + CNAK + 26 + 1 + write-only + + + STALL + STALL handshake + 21 + 1 + read-write + + + SNPM + SNPM + 20 + 1 + read-write + + + EPTYP + EPTYP + 18 + 2 + read-only + + + NAKSTS + NAKSTS + 17 + 1 + read-only + + + USBAEP + USBAEP + 15 + 1 + read-only + + + MPSIZ + MPSIZ + 0 + 2 + read-only + + + + + INT + DOEPINT0 + device endpoint-0 interrupt + register + 0x8 + 0x20 + read-write + 0x00000080 + + + B2BSTUP + B2BSTUP + 6 + 1 + + + OTEPDIS + OTEPDIS + 4 + 1 + + + STUP + STUP + 3 + 1 + + + EPDISD + EPDISD + 1 + 1 + + + XFRC + XFRC + 0 + 1 + + + + + TSIZ + DOEPTSIZ0 + device OUT endpoint-0 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + STUPCNT + SETUP packet count + 29 + 2 + + + PKTCNT + Packet count + 19 + 1 + + + XFRSIZ + Transfer size + 0 + 7 + + + + + + 3 + 0x20 + 1-3 + DOEP%s + Device IN endpoint X + 0x320 + + CTL + DOEPCTL1 + device endpoint-1 control + register + 0x0 + 0x20 + 0x00000000 + + + EPENA + EPENA + 31 + 1 + read-write + + + EPDIS + EPDIS + 30 + 1 + read-write + + + SODDFRM + SODDFRM + 29 + 1 + write-only + + + SD0PID_SEVNFRM + SD0PID/SEVNFRM + 28 + 1 + write-only + + + SNAK + SNAK + 27 + 1 + write-only + + + CNAK + CNAK + 26 + 1 + write-only + + + STALL + STALL handshake + 21 + 1 + read-write + + + SNPM + SNPM + 20 + 1 + read-write + + + EPTYP + EPTYP + 18 + 2 + read-write + + + NAKSTS + NAKSTS + 17 + 1 + read-only + + + EONUM_DPID + EONUM/DPID + 16 + 1 + read-only + + + USBAEP + USBAEP + 15 + 1 + read-write + + + MPSIZ + MPSIZ + 0 + 11 + read-write + + + + + INT + DOEPINT1 + device endpoint-1 interrupt + register + 0x8 + 0x20 + read-write + 0x00000080 + + + B2BSTUP + B2BSTUP + 6 + 1 + + + OTEPDIS + OTEPDIS + 4 + 1 + + + STUP + STUP + 3 + 1 + + + EPDISD + EPDISD + 1 + 1 + + + XFRC + XFRC + 0 + 1 + + + + + TSIZ + DOEPTSIZ1 + device OUT endpoint-1 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + RXDPID_STUPCNT + Received data PID/SETUP packet + count + 29 + 2 + + + PKTCNT + Packet count + 19 + 10 + + + XFRSIZ + Transfer size + 0 + 19 + + + + + + + + OTG_FS_GLOBAL + USB on the go full speed + USB_OTG_FS + 0x50000000 + + 0x0 + 0x400 + registers + + + + GOTGCTL + GOTGCTL + OTG_FS control and status register + (OTG_FS_GOTGCTL) + 0x0 + 0x20 + 0x00000800 + + + SRQSCS + Session request success + 0 + 1 + read-only + + + SRQ + Session request + 1 + 1 + read-write + + + HNGSCS + Host negotiation success + 8 + 1 + read-only + + + HNPRQ + HNP request + 9 + 1 + read-write + + + HSHNPEN + Host set HNP enable + 10 + 1 + read-write + + + DHNPEN + Device HNP enabled + 11 + 1 + read-write + + + CIDSTS + Connector ID status + 16 + 1 + read-only + + + DBCT + Long/short debounce time + 17 + 1 + read-only + + + ASVLD + A-session valid + 18 + 1 + read-only + + + BSVLD + B-session valid + 19 + 1 + read-only + + + + + GOTGINT + GOTGINT + OTG_FS interrupt register + (OTG_FS_GOTGINT) + 0x4 + 0x20 + read-write + 0x00000000 + + + SEDET + Session end detected + 2 + 1 + + + SRSSCHG + Session request success status + change + 8 + 1 + + + HNSSCHG + Host negotiation success status + change + 9 + 1 + + + HNGDET + Host negotiation detected + 17 + 1 + + + ADTOCHG + A-device timeout change + 18 + 1 + + + DBCDNE + Debounce done + 19 + 1 + + + + + GAHBCFG + GAHBCFG + OTG_FS AHB configuration register + (OTG_FS_GAHBCFG) + 0x8 + 0x20 + read-write + 0x00000000 + + + GINT + Global interrupt mask + 0 + 1 + + + TXFELVL + TxFIFO empty level + 7 + 1 + + + PTXFELVL + Periodic TxFIFO empty + level + 8 + 1 + + + + + GUSBCFG + GUSBCFG + OTG_FS USB configuration register + (OTG_FS_GUSBCFG) + 0xC + 0x20 + 0x00000A00 + + + TOCAL + FS timeout calibration + 0 + 3 + read-write + + + PHYSEL + Full Speed serial transceiver + select + 6 + 1 + write-only + + + SRPCAP + SRP-capable + 8 + 1 + read-write + + + HNPCAP + HNP-capable + 9 + 1 + read-write + + + TRDT + USB turnaround time + 10 + 4 + read-write + + + FHMOD + Force host mode + 29 + 1 + read-write + + + FDMOD + Force device mode + 30 + 1 + read-write + + + CTXPKT + Corrupt Tx packet + 31 + 1 + read-write + + + + + GRSTCTL + GRSTCTL + OTG_FS reset register + (OTG_FS_GRSTCTL) + 0x10 + 0x20 + 0x20000000 + + + CSRST + Core soft reset + 0 + 1 + read-write + + + HSRST + HCLK soft reset + 1 + 1 + read-write + + + FCRST + Host frame counter reset + 2 + 1 + read-write + + + RXFFLSH + RxFIFO flush + 4 + 1 + read-write + + + TXFFLSH + TxFIFO flush + 5 + 1 + read-write + + + TXFNUM + TxFIFO number + 6 + 5 + read-write + + + AHBIDL + AHB master idle + 31 + 1 + read-only + + + + + GINTSTS + GINTSTS + OTG_FS core interrupt register + (OTG_FS_GINTSTS) + 0x14 + 0x20 + 0x04000020 + + + CMOD + Current mode of operation + 0 + 1 + read-only + + + MMIS + Mode mismatch interrupt + 1 + 1 + read-write + + + OTGINT + OTG interrupt + 2 + 1 + read-only + + + SOF + Start of frame + 3 + 1 + read-write + + + RXFLVL + RxFIFO non-empty + 4 + 1 + read-only + + + NPTXFE + Non-periodic TxFIFO empty + 5 + 1 + read-only + + + GINAKEFF + Global IN non-periodic NAK + effective + 6 + 1 + read-only + + + GOUTNAKEFF + Global OUT NAK effective + 7 + 1 + read-only + + + ESUSP + Early suspend + 10 + 1 + read-write + + + USBSUSP + USB suspend + 11 + 1 + read-write + + + USBRST + USB reset + 12 + 1 + read-write + + + ENUMDNE + Enumeration done + 13 + 1 + read-write + + + ISOODRP + Isochronous OUT packet dropped + interrupt + 14 + 1 + read-write + + + EOPF + End of periodic frame + interrupt + 15 + 1 + read-write + + + IEPINT + IN endpoint interrupt + 18 + 1 + read-only + + + OEPINT + OUT endpoint interrupt + 19 + 1 + read-only + + + IISOIXFR + Incomplete isochronous IN + transfer + 20 + 1 + read-write + + + IPXFR_INCOMPISOOUT + Incomplete periodic transfer(Host + mode)/Incomplete isochronous OUT transfer(Device + mode) + 21 + 1 + read-write + + + HPRTINT + Host port interrupt + 24 + 1 + read-only + + + HCINT + Host channels interrupt + 25 + 1 + read-only + + + PTXFE + Periodic TxFIFO empty + 26 + 1 + read-only + + + CIDSCHG + Connector ID status change + 28 + 1 + read-write + + + DISCINT + Disconnect detected + interrupt + 29 + 1 + read-write + + + SRQINT + Session request/new session detected + interrupt + 30 + 1 + read-write + + + WKUPINT + Resume/remote wakeup detected + interrupt + 31 + 1 + read-write + + + + + GINTMSK + GINTMSK + OTG_FS interrupt mask register + (OTG_FS_GINTMSK) + 0x18 + 0x20 + 0x00000000 + + + MMISM + Mode mismatch interrupt + mask + 1 + 1 + read-write + + + OTGINT + OTG interrupt mask + 2 + 1 + read-write + + + SOFM + Start of frame mask + 3 + 1 + read-write + + + RXFLVLM + Receive FIFO non-empty + mask + 4 + 1 + read-write + + + NPTXFEM + Non-periodic TxFIFO empty + mask + 5 + 1 + read-write + + + GINAKEFFM + Global non-periodic IN NAK effective + mask + 6 + 1 + read-write + + + GONAKEFFM + Global OUT NAK effective + mask + 7 + 1 + read-write + + + ESUSPM + Early suspend mask + 10 + 1 + read-write + + + USBSUSPM + USB suspend mask + 11 + 1 + read-write + + + USBRST + USB reset mask + 12 + 1 + read-write + + + ENUMDNEM + Enumeration done mask + 13 + 1 + read-write + + + ISOODRPM + Isochronous OUT packet dropped interrupt + mask + 14 + 1 + read-write + + + EOPFM + End of periodic frame interrupt + mask + 15 + 1 + read-write + + + EPMISM + Endpoint mismatch interrupt + mask + 17 + 1 + read-write + + + IEPINT + IN endpoints interrupt + mask + 18 + 1 + read-write + + + OEPINT + OUT endpoints interrupt + mask + 19 + 1 + read-write + + + IISOIXFRM + Incomplete isochronous IN transfer + mask + 20 + 1 + read-write + + + IPXFRM_IISOOXFRM + Incomplete periodic transfer mask(Host + mode)/Incomplete isochronous OUT transfer mask(Device + mode) + 21 + 1 + read-write + + + PRTIM + Host port interrupt mask + 24 + 1 + read-write + + + HCIM + Host channels interrupt + mask + 25 + 1 + read-write + + + PTXFEM + Periodic TxFIFO empty mask + 26 + 1 + read-write + + + CIDSCHGM + Connector ID status change + mask + 28 + 1 + read-write + + + DISCINT + Disconnect detected interrupt + mask + 29 + 1 + read-write + + + SRQIM + Session request/new session detected + interrupt mask + 30 + 1 + read-write + + + WUIM + Resume/remote wakeup detected interrupt + mask + 31 + 1 + read-write + + + + + GRXSTSR_Device + GRXSTSR_Device + OTG_FS Receive status debug read(Device + mode) + 0x1C + 0x20 + read-only + 0x00000000 + + + EPNUM + Endpoint number + 0 + 4 + + + BCNT + Byte count + 4 + 11 + + + DPID + Data PID + 15 + 2 + + + PKTSTS + Packet status + 17 + 4 + + + FRMNUM + Frame number + 21 + 4 + + + + + GRXSTSR_Host + GRXSTSR_Host + OTG status debug read (host mode) + GRXSTSR_Device + 0x1C + 0x20 + read-only + 0x00000000 + + + CHNUM + Channel number + 0 + 4 + + + BCNT + Byte count + 4 + 11 + + + DPID + Data PID + 15 + 2 + + + PKTSTS + Packet status + 17 + 4 + + + + + GRXFSIZ + GRXFSIZ + OTG_FS Receive FIFO size register + (OTG_FS_GRXFSIZ) + 0x24 + 0x20 + read-write + 0x00000200 + + + RXFD + RxFIFO depth + 0 + 16 + + + + + DIEPTXF0 + DIEPTXF0 + OTG_FS non-periodic transmit FIFO size + register (Device mode) + 0x28 + 0x20 + read-write + 0x00000200 + + + TX0FSA + Endpoint 0 transmit RAM start + address + 0 + 16 + + + TX0FD + Endpoint 0 TxFIFO depth + 16 + 16 + + + + + HNPTXFSIZ + HNPTXFSIZ + OTG_FS non-periodic transmit FIFO size + register (Host mode) + DIEPTXF0 + 0x28 + 0x20 + read-write + 0x00000200 + + + NPTXFSA + Non-periodic transmit RAM start + address + 0 + 16 + + + NPTXFD + Non-periodic TxFIFO depth + 16 + 16 + + + + + GNPTXSTS + GNPTXSTS + OTG_FS non-periodic transmit FIFO/queue + status register (OTG_FS_GNPTXSTS) + 0x2C + 0x20 + read-only + 0x00080200 + + + NPTXFSAV + Non-periodic TxFIFO space + available + 0 + 16 + + + NPTQXSAV + Non-periodic transmit request queue + space available + 16 + 8 + + + NPTXQTOP + Top of the non-periodic transmit request + queue + 24 + 7 + + + + + GCCFG + GCCFG + OTG_FS general core configuration register + (OTG_FS_GCCFG) + 0x38 + 0x20 + read-write + 0x00000000 + + + PWRDWN + Power down + 16 + 1 + + + VBUSASEN + Enable the VBUS sensing + device + 18 + 1 + + + VBUSBSEN + Enable the VBUS sensing + device + 19 + 1 + + + SOFOUTEN + SOF output enable + 20 + 1 + + + NOVBUSSENS + Vbus sensing disable option + 21 + 1 + + + + + CID + CID + core ID register + 0x3C + 0x20 + read-write + 0x00001000 + + + PRODUCT_ID + Product ID field + 0 + 32 + + + + + HPTXFSIZ + HPTXFSIZ + OTG_FS Host periodic transmit FIFO size + register (OTG_FS_HPTXFSIZ) + 0x100 + 0x20 + read-write + 0x02000600 + + + PTXSA + Host periodic TxFIFO start + address + 0 + 16 + + + PTXFSIZ + Host periodic TxFIFO depth + 16 + 16 + + + + + 3 + 0x4 + 1-3 + DIEPTXF%s + DIEPTXF1 + OTF_FS device IN endpoint transmit FIFO size register + 0x104 + 0x20 + read-write + 0x02000400 + + + INEPTXSA + IN endpoint FIFO2 transmit RAM start + address + 0 + 16 + + + INEPTXFD + IN endpoint TxFIFO depth + 16 + 16 + + + + + GRXSTSP_Device + OTG status read and pop (device mode) + 0x20 + 0x20 + read-only + 0x00000000 + + + FRMNUM + Frame number + 21 + 4 + + + PKTSTS + Packet status + 17 + 4 + + + DPID + Data PID + 15 + 2 + + + BCNT + Byte count + 4 + 11 + + + EPNUM + Endpoint number + 0 + 4 + + + + + GRXSTSP_Host + OTG status read and pop (host mode) + GRXSTSP_Device + 0x20 + 0x20 + read-only + 0x00000000 + + + PKTSTS + Packet status + 17 + 4 + + + DPID + Data PID + 15 + 2 + + + BCNT + Byte count + 4 + 11 + + + CHNUM + Channel number + 0 + 4 + + + + + + + OTG_FS_HOST + USB on the go full speed + USB_OTG_FS + 0x50000400 + + 0x0 + 0x400 + registers + + + + HCFG + HCFG + OTG_FS host configuration register + (OTG_FS_HCFG) + 0x0 + 0x20 + 0x00000000 + + + FSLSPCS + FS/LS PHY clock select + 0 + 2 + read-write + + + FSLSS + FS- and LS-only support + 2 + 1 + read-write + + + + + HFIR + HFIR + OTG_FS Host frame interval + register + 0x4 + 0x20 + read-write + 0x0000EA60 + + + FRIVL + Frame interval + 0 + 16 + + + + + HFNUM + HFNUM + OTG_FS host frame number/frame time + remaining register (OTG_FS_HFNUM) + 0x8 + 0x20 + read-only + 0x00003FFF + + + FRNUM + Frame number + 0 + 16 + + + FTREM + Frame time remaining + 16 + 16 + + + + + HPTXSTS + HPTXSTS + OTG_FS_Host periodic transmit FIFO/queue + status register (OTG_FS_HPTXSTS) + 0x10 + 0x20 + 0x00080100 + + + PTXFSAVL + Periodic transmit data FIFO space + available + 0 + 16 + read-write + + + PTXQSAV + Periodic transmit request queue space + available + 16 + 8 + read-only + + + PTXQTOP + Top of the periodic transmit request + queue + 24 + 8 + read-only + + + + + HAINT + HAINT + OTG_FS Host all channels interrupt + register + 0x14 + 0x20 + read-only + 0x00000000 + + + HAINT + Channel interrupts + 0 + 16 + + + + + HAINTMSK + HAINTMSK + OTG_FS host all channels interrupt mask + register + 0x18 + 0x20 + read-write + 0x00000000 + + + HAINTM + Channel interrupt mask + 0 + 16 + + + + + HPRT + HPRT + OTG_FS host port control and status register + (OTG_FS_HPRT) + 0x40 + 0x20 + 0x00000000 + + + PCSTS + Port connect status + 0 + 1 + read-only + + + PCDET + Port connect detected + 1 + 1 + read-write + + + PENA + Port enable + 2 + 1 + read-write + + + PENCHNG + Port enable/disable change + 3 + 1 + read-write + + + POCA + Port overcurrent active + 4 + 1 + read-only + + + POCCHNG + Port overcurrent change + 5 + 1 + read-write + + + PRES + Port resume + 6 + 1 + read-write + + + PSUSP + Port suspend + 7 + 1 + read-write + + + PRST + Port reset + 8 + 1 + read-write + + + PLSTS + Port line status + 10 + 2 + read-only + + + PPWR + Port power + 12 + 1 + read-write + + + PTCTL + Port test control + 13 + 4 + read-write + + + PSPD + Port speed + 17 + 2 + read-only + + + + + 8 + 0x20 + 0-7 + HC%s + Host channel + 0x100 + + CHAR + HCCHAR0 + OTG_FS host channel-0 characteristics + register (OTG_FS_HCCHAR0) + 0x0 + 0x20 + read-write + 0x00000000 + + + MPSIZ + Maximum packet size + 0 + 11 + + + EPNUM + Endpoint number + 11 + 4 + + + EPDIR + Endpoint direction + 15 + 1 + + + LSDEV + Low-speed device + 17 + 1 + + + EPTYP + Endpoint type + 18 + 2 + + + MCNT + Multicount + 20 + 2 + + + DAD + Device address + 22 + 7 + + + ODDFRM + Odd frame + 29 + 1 + + + CHDIS + Channel disable + 30 + 1 + + + CHENA + Channel enable + 31 + 1 + + + + + INT + HCINT0 + OTG_FS host channel-0 interrupt register + (OTG_FS_HCINT0) + 0x8 + 0x20 + read-write + 0x00000000 + + + XFRC + Transfer completed + 0 + 1 + + + CHH + Channel halted + 1 + 1 + + + STALL + STALL response received + interrupt + 3 + 1 + + + NAK + NAK response received + interrupt + 4 + 1 + + + ACK + ACK response received/transmitted + interrupt + 5 + 1 + + + TXERR + Transaction error + 7 + 1 + + + BBERR + Babble error + 8 + 1 + + + FRMOR + Frame overrun + 9 + 1 + + + DTERR + Data toggle error + 10 + 1 + + + + + INTMSK + HCINTMSK0 + OTG_FS host channel-0 mask register + (OTG_FS_HCINTMSK0) + 0xC + 0x20 + read-write + 0x00000000 + + + XFRCM + Transfer completed mask + 0 + 1 + + + CHHM + Channel halted mask + 1 + 1 + + + STALLM + STALL response received interrupt + mask + 3 + 1 + + + NAKM + NAK response received interrupt + mask + 4 + 1 + + + ACKM + ACK response received/transmitted + interrupt mask + 5 + 1 + + + NYET + response received interrupt + mask + 6 + 1 + + + TXERRM + Transaction error mask + 7 + 1 + + + BBERRM + Babble error mask + 8 + 1 + + + FRMORM + Frame overrun mask + 9 + 1 + + + DTERRM + Data toggle error mask + 10 + 1 + + + + + TSIZ + HCTSIZ0 + OTG_FS host channel-0 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + XFRSIZ + Transfer size + 0 + 19 + + + PKTCNT + Packet count + 19 + 10 + + + DPID + Data PID + 29 + 2 + + + + + + + + OTG_FS_PWRCLK + USB on the go full speed + USB_OTG_FS + 0x50000E00 + + 0x0 + 0x400 + registers + + + + PCGCCTL + PCGCCTL + OTG_FS power and clock gating control + register + 0x0 + 0x20 + read-write + 0x00000000 + + + STPPCLK + Stop PHY clock + 0 + 1 + + + GATEHCLK + Gate HCLK + 1 + 1 + + + PHYSUSP + PHY Suspended + 4 + 1 + + + + + + + PWR + Power control + PWR + 0x40007000 + + 0x0 + 0x400 + registers + + + + CR + CR + power control register + 0x0 + 0x20 + read-write + 0x00000000 + + + VOS + Regulator voltage scaling output + selection + 14 + 2 + + + ADCDC1 + ADCDC1 + 13 + 1 + + + FPDS + Flash power down in Stop + mode + 9 + 1 + + + DBP + Disable backup domain write + protection + 8 + 1 + + + PLS + PVD level selection + 5 + 3 + + + PVDE + Power voltage detector + enable + 4 + 1 + + + CSBF + Clear standby flag + 3 + 1 + + + CWUF + Clear wakeup flag + 2 + 1 + + + PDDS + Power down deepsleep + 1 + 1 + + + LPDS + Low-power deep sleep + 0 + 1 + + + + + CSR + CSR + power control/status register + 0x4 + 0x20 + 0x00000000 + + + WUF + Wakeup flag + 0 + 1 + read-only + + + SBF + Standby flag + 1 + 1 + read-only + + + PVDO + PVD output + 2 + 1 + read-only + + + BRR + Backup regulator ready + 3 + 1 + read-only + + + EWUP + Enable WKUP pin + 8 + 1 + read-write + + + BRE + Backup regulator enable + 9 + 1 + read-write + + + VOSRDY + Regulator voltage scaling output + selection ready bit + 14 + 1 + read-write + + + + + + + RCC + Reset and clock control + RCC + 0x40023800 + + 0x0 + 0x400 + registers + + + I2C1_EV + I2C1 event interrupt + 31 + + + I2C1_ER + I2C1 error interrupt + 32 + + + + CR + CR + clock control register + 0x0 + 0x20 + 0x00000083 + + + PLLI2SRDY + PLLI2S clock ready flag + 27 + 1 + read-only + + + + PLLI2SON + PLLI2S enable + 26 + 1 + read-write + + + + PLLRDY + Main PLL (PLL) clock ready + flag + 25 + 1 + read-only + + + + PLLON + Main PLL (PLL) enable + 24 + 1 + read-write + + + + CSSON + Clock security system + enable + 19 + 1 + read-write + + CSSON + read-write + + Off + Clock security system disabled (clock detector OFF) + 0 + + + On + Clock security system enable (clock detector ON if the HSE is ready, OFF if not) + 1 + + + + + HSEBYP + HSE clock bypass + 18 + 1 + read-write + + HSEBYP + read-write + + NotBypassed + HSE crystal oscillator not bypassed + 0 + + + Bypassed + HSE crystal oscillator bypassed with external clock + 1 + + + + + HSERDY + HSE clock ready flag + 17 + 1 + read-only + + + + HSEON + HSE clock enable + 16 + 1 + read-write + + + + HSICAL + Internal high-speed clock + calibration + 8 + 8 + read-only + + + 0 + 255 + + + + + HSITRIM + Internal high-speed clock + trimming + 3 + 5 + read-write + + + 0 + 31 + + + + + HSIRDY + Internal high-speed clock ready + flag + 1 + 1 + read-only + + HSIRDYR + read + + NotReady + Clock not ready + 0 + + + Ready + Clock ready + 1 + + + + + HSION + Internal high-speed clock + enable + 0 + 1 + read-write + + HSION + read-write + + Off + Clock Off + 0 + + + On + Clock On + 1 + + + + + + + PLLCFGR + PLLCFGR + PLL configuration register + 0x4 + 0x20 + read-write + 0x24003010 + + + PLLSRC + Main PLL(PLL) and audio PLL (PLLI2S) + entry clock source + 22 + 1 + + PLLSRC + read-write + + HSI + HSI clock selected as PLL and PLLI2S clock entry + 0 + + + HSE + HSE oscillator clock selected as PLL and PLLI2S clock entry + 1 + + + + + PLLM + Division factor for the main PLL (PLL) + and audio PLL (PLLI2S) input clock + 0 + 6 + + + 2 + 63 + + + + + PLLN + Main PLL (PLL) multiplication factor for + VCO + 6 + 9 + + + 50 + 432 + + + + + PLLP + Main PLL (PLL) division factor for main + system clock + 16 + 2 + + PLLP + read-write + + Div2 + PLLP=2 + 0 + + + Div4 + PLLP=4 + 1 + + + Div6 + PLLP=6 + 2 + + + Div8 + PLLP=8 + 3 + + + + + PLLQ + Main PLL (PLL) division factor for USB + OTG FS, SDIO and random number generator + clocks + 24 + 4 + + + 2 + 15 + + + + + + + CFGR + CFGR + clock configuration register + 0x8 + 0x20 + 0x00000000 + + + MCO2 + Microcontroller clock output + 2 + 30 + 2 + read-write + + MCO2 + read-write + + SYSCLK + System clock (SYSCLK) selected + 0 + + + PLLI2S + PLLI2S clock selected + 1 + + + HSE + HSE oscillator clock selected + 2 + + + PLL + PLL clock selected + 3 + + + + + MCO2PRE + MCO2 prescaler + 27 + 3 + read-write + + + + MCO1PRE + MCO1 prescaler + 24 + 3 + read-write + + MCO1PRE + read-write + + Div1 + No division + 0 + + + Div2 + Division by 2 + 4 + + + Div3 + Division by 3 + 5 + + + Div4 + Division by 4 + 6 + + + Div5 + Division by 5 + 7 + + + + + I2SSRC + I2S clock selection + 23 + 1 + read-write + + I2SSRC + read-write + + PLLI2S + PLLI2S clock used as I2S clock source + 0 + + + CKIN + External clock mapped on the I2S_CKIN pin used as I2S clock source + 1 + + + + + MCO1 + Microcontroller clock output + 1 + 21 + 2 + read-write + + MCO1 + read-write + + HSI + HSI clock selected + 0 + + + LSE + LSE oscillator selected + 1 + + + HSE + HSE oscillator clock selected + 2 + + + PLL + PLL clock selected + 3 + + + + + RTCPRE + HSE division factor for RTC + clock + 16 + 5 + read-write + + + 0 + 31 + + + + + PPRE2 + APB high-speed prescaler + (APB2) + 13 + 3 + read-write + + + + PPRE1 + APB Low speed prescaler + (APB1) + 10 + 3 + read-write + + PPRE1 + read-write + + Div1 + HCLK not divided + 0 + + + Div2 + HCLK divided by 2 + 4 + + + Div4 + HCLK divided by 4 + 5 + + + Div8 + HCLK divided by 8 + 6 + + + Div16 + HCLK divided by 16 + 7 + + + + + HPRE + AHB prescaler + 4 + 4 + read-write + + HPRE + read-write + + Div1 + SYSCLK not divided + 0 + + + Div2 + SYSCLK divided by 2 + 8 + + + Div4 + SYSCLK divided by 4 + 9 + + + Div8 + SYSCLK divided by 8 + 10 + + + Div16 + SYSCLK divided by 16 + 11 + + + Div64 + SYSCLK divided by 64 + 12 + + + Div128 + SYSCLK divided by 128 + 13 + + + Div256 + SYSCLK divided by 256 + 14 + + + Div512 + SYSCLK divided by 512 + 15 + + + + + SW + System clock switch + 0 + 2 + + SW + read-write + + HSI + HSI selected as system clock + 0 + + + HSE + HSE selected as system clock + 1 + + + PLL + PLL selected as system clock + 2 + + + + + SWS + System clock switch status + 2 + 2 + + SWSR + read + + HSI + HSI oscillator used as system clock + 0 + + + HSE + HSE oscillator used as system clock + 1 + + + PLL + PLL used as system clock + 2 + + + + + + + CIR + CIR + clock interrupt register + 0xC + 0x20 + 0x00000000 + + + CSSC + Clock security system interrupt + clear + 23 + 1 + write-only + + CSSCW + write + + Clear + Clear CSSF flag + 1 + + + + + PLLI2SRDYC + PLLI2S ready interrupt + clear + 21 + 1 + write-only + + + + PLLRDYC + Main PLL(PLL) ready interrupt + clear + 20 + 1 + write-only + + + + HSERDYC + HSE ready interrupt clear + 19 + 1 + write-only + + + + HSIRDYC + HSI ready interrupt clear + 18 + 1 + write-only + + + + LSERDYC + LSE ready interrupt clear + 17 + 1 + write-only + + + + LSIRDYC + LSI ready interrupt clear + 16 + 1 + write-only + + LSIRDYCW + write + + Clear + Clear interrupt flag + 1 + + + + + PLLI2SRDYIE + PLLI2S ready interrupt + enable + 13 + 1 + read-write + + + + PLLRDYIE + Main PLL (PLL) ready interrupt + enable + 12 + 1 + read-write + + + + HSERDYIE + HSE ready interrupt enable + 11 + 1 + read-write + + + + HSIRDYIE + HSI ready interrupt enable + 10 + 1 + read-write + + + + LSERDYIE + LSE ready interrupt enable + 9 + 1 + read-write + + + + LSIRDYIE + LSI ready interrupt enable + 8 + 1 + read-write + + LSIRDYIE + read-write + + Disabled + Interrupt disabled + 0 + + + Enabled + Interrupt enabled + 1 + + + + + CSSF + Clock security system interrupt + flag + 7 + 1 + read-only + + CSSFR + read + + NotInterrupted + No clock security interrupt caused by HSE clock failure + 0 + + + Interrupted + Clock security interrupt caused by HSE clock failure + 1 + + + + + PLLI2SRDYF + PLLI2S ready interrupt + flag + 5 + 1 + read-only + + + + PLLRDYF + Main PLL (PLL) ready interrupt + flag + 4 + 1 + read-only + + + + HSERDYF + HSE ready interrupt flag + 3 + 1 + read-only + + + + HSIRDYF + HSI ready interrupt flag + 2 + 1 + read-only + + + + LSERDYF + LSE ready interrupt flag + 1 + 1 + read-only + + + + LSIRDYF + LSI ready interrupt flag + 0 + 1 + read-only + + LSIRDYFR + read + + NotInterrupted + No clock ready interrupt + 0 + + + Interrupted + Clock ready interrupt + 1 + + + + + + + AHB1RSTR + AHB1RSTR + AHB1 peripheral reset register + 0x10 + 0x20 + read-write + 0x00000000 + + + DMA2RST + DMA2 reset + 22 + 1 + + + + DMA1RST + DMA2 reset + 21 + 1 + + + + CRCRST + CRC reset + 12 + 1 + + + + GPIOHRST + IO port H reset + 7 + 1 + + + + GPIOERST + IO port E reset + 4 + 1 + + + + GPIODRST + IO port D reset + 3 + 1 + + + + GPIOCRST + IO port C reset + 2 + 1 + + + + GPIOBRST + IO port B reset + 1 + 1 + + + + GPIOARST + IO port A reset + 0 + 1 + + GPIOARST + read-write + + Reset + Reset the selected module + 1 + + + + + + + AHB2RSTR + AHB2RSTR + AHB2 peripheral reset register + 0x14 + 0x20 + read-write + 0x00000000 + + + OTGFSRST + USB OTG FS module reset + 7 + 1 + + OTGFSRST + read-write + + Reset + Reset the selected module + 1 + + + + + + + APB1RSTR + APB1RSTR + APB1 peripheral reset register + 0x20 + 0x20 + read-write + 0x00000000 + + + PWRRST + Power interface reset + 28 + 1 + + + + I2C3RST + I2C3 reset + 23 + 1 + + + + I2C2RST + I2C 2 reset + 22 + 1 + + + + I2C1RST + I2C 1 reset + 21 + 1 + + + + USART2RST + USART 2 reset + 17 + 1 + + + + SPI3RST + SPI 3 reset + 15 + 1 + + + + SPI2RST + SPI 2 reset + 14 + 1 + + + + WWDGRST + Window watchdog reset + 11 + 1 + + + + TIM5RST + TIM5 reset + 3 + 1 + + + + TIM4RST + TIM4 reset + 2 + 1 + + + + TIM3RST + TIM3 reset + 1 + 1 + + + + TIM2RST + TIM2 reset + 0 + 1 + + TIM2RST + read-write + + Reset + Reset the selected module + 1 + + + + + + + APB2RSTR + APB2RSTR + APB2 peripheral reset register + 0x24 + 0x20 + read-write + 0x00000000 + + + TIM11RST + TIM11 reset + 18 + 1 + + + + TIM10RST + TIM10 reset + 17 + 1 + + + + TIM9RST + TIM9 reset + 16 + 1 + + + + SYSCFGRST + System configuration controller + reset + 14 + 1 + + + + SPI1RST + SPI 1 reset + 12 + 1 + + + + SDIORST + SDIO reset + 11 + 1 + + + + ADCRST + ADC interface reset (common to all + ADCs) + 8 + 1 + + + + USART6RST + USART6 reset + 5 + 1 + + + + USART1RST + USART1 reset + 4 + 1 + + + + TIM1RST + TIM1 reset + 0 + 1 + + TIM1RST + read-write + + Reset + Reset the selected module + 1 + + + + + SPI4RST + SPI4 reset + 13 + 1 + + + + + + AHB1ENR + AHB1ENR + AHB1 peripheral clock register + 0x30 + 0x20 + read-write + 0x00100000 + + + DMA2EN + DMA2 clock enable + 22 + 1 + + + + DMA1EN + DMA1 clock enable + 21 + 1 + + + + CRCEN + CRC clock enable + 12 + 1 + + + + GPIOHEN + IO port H clock enable + 7 + 1 + + + + GPIOEEN + IO port E clock enable + 4 + 1 + + + + GPIODEN + IO port D clock enable + 3 + 1 + + + + GPIOCEN + IO port C clock enable + 2 + 1 + + + + GPIOBEN + IO port B clock enable + 1 + 1 + + + + GPIOAEN + IO port A clock enable + 0 + 1 + + GPIOAEN + read-write + + Disabled + The selected clock is disabled + 0 + + + Enabled + The selected clock is enabled + 1 + + + + + + + AHB2ENR + AHB2ENR + AHB2 peripheral clock enable + register + 0x34 + 0x20 + read-write + 0x00000000 + + + OTGFSEN + USB OTG FS clock enable + 7 + 1 + + OTGFSEN + read-write + + Disabled + The selected clock is disabled + 0 + + + Enabled + The selected clock is enabled + 1 + + + + + + + APB1ENR + APB1ENR + APB1 peripheral clock enable + register + 0x40 + 0x20 + read-write + 0x00000000 + + + PWREN + Power interface clock + enable + 28 + 1 + + + + I2C3EN + I2C3 clock enable + 23 + 1 + + + + I2C2EN + I2C2 clock enable + 22 + 1 + + + + I2C1EN + I2C1 clock enable + 21 + 1 + + + + USART2EN + USART 2 clock enable + 17 + 1 + + + + SPI3EN + SPI3 clock enable + 15 + 1 + + + + SPI2EN + SPI2 clock enable + 14 + 1 + + + + WWDGEN + Window watchdog clock + enable + 11 + 1 + + + + TIM5EN + TIM5 clock enable + 3 + 1 + + + + TIM4EN + TIM4 clock enable + 2 + 1 + + + + TIM3EN + TIM3 clock enable + 1 + 1 + + + + TIM2EN + TIM2 clock enable + 0 + 1 + + TIM2EN + read-write + + Disabled + The selected clock is disabled + 0 + + + Enabled + The selected clock is enabled + 1 + + + + + + + APB2ENR + APB2ENR + APB2 peripheral clock enable + register + 0x44 + 0x20 + read-write + 0x00000000 + + + TIM11EN + TIM11 clock enable + 18 + 1 + + + + TIM10EN + TIM10 clock enable + 17 + 1 + + + + TIM9EN + TIM9 clock enable + 16 + 1 + + + + SYSCFGEN + System configuration controller clock + enable + 14 + 1 + + + + SPI1EN + SPI1 clock enable + 12 + 1 + + + + SDIOEN + SDIO clock enable + 11 + 1 + + + + ADC1EN + ADC1 clock enable + 8 + 1 + + + + USART6EN + USART6 clock enable + 5 + 1 + + + + USART1EN + USART1 clock enable + 4 + 1 + + + + TIM1EN + TIM1 clock enable + 0 + 1 + + TIM1EN + read-write + + Disabled + The selected clock is disabled + 0 + + + Enabled + The selected clock is enabled + 1 + + + + + SPI4EN + SPI4 clock enable + 13 + 1 + + + + + + AHB1LPENR + AHB1LPENR + AHB1 peripheral clock enable in low power + mode register + 0x50 + 0x20 + read-write + 0x7E6791FF + + + DMA2LPEN + DMA2 clock enable during Sleep + mode + 22 + 1 + + + + DMA1LPEN + DMA1 clock enable during Sleep + mode + 21 + 1 + + + + SRAM1LPEN + SRAM 1interface clock enable during + Sleep mode + 16 + 1 + + + + FLITFLPEN + Flash interface clock enable during + Sleep mode + 15 + 1 + + + + CRCLPEN + CRC clock enable during Sleep + mode + 12 + 1 + + + + GPIOHLPEN + IO port H clock enable during Sleep + mode + 7 + 1 + + + + GPIOELPEN + IO port E clock enable during Sleep + mode + 4 + 1 + + + + GPIODLPEN + IO port D clock enable during Sleep + mode + 3 + 1 + + + + GPIOCLPEN + IO port C clock enable during Sleep + mode + 2 + 1 + + + + GPIOBLPEN + IO port B clock enable during Sleep + mode + 1 + 1 + + + + GPIOALPEN + IO port A clock enable during sleep + mode + 0 + 1 + + GPIOALPEN + read-write + + DisabledInSleep + Selected module is disabled during Sleep mode + 0 + + + EnabledInSleep + Selected module is enabled during Sleep mode + 1 + + + + + + + AHB2LPENR + AHB2LPENR + AHB2 peripheral clock enable in low power + mode register + 0x54 + 0x20 + read-write + 0x000000F1 + + + OTGFSLPEN + USB OTG FS clock enable during Sleep + mode + 7 + 1 + + OTGFSLPEN + read-write + + DisabledInSleep + Selected module is disabled during Sleep mode + 0 + + + EnabledInSleep + Selected module is enabled during Sleep mode + 1 + + + + + + + APB1LPENR + APB1LPENR + APB1 peripheral clock enable in low power + mode register + 0x60 + 0x20 + read-write + 0x36FEC9FF + + + PWRLPEN + Power interface clock enable during + Sleep mode + 28 + 1 + + + + I2C3LPEN + I2C3 clock enable during Sleep + mode + 23 + 1 + + + + I2C2LPEN + I2C2 clock enable during Sleep + mode + 22 + 1 + + + + I2C1LPEN + I2C1 clock enable during Sleep + mode + 21 + 1 + + + + USART2LPEN + USART2 clock enable during Sleep + mode + 17 + 1 + + + + SPI3LPEN + SPI3 clock enable during Sleep + mode + 15 + 1 + + + + SPI2LPEN + SPI2 clock enable during Sleep + mode + 14 + 1 + + + + WWDGLPEN + Window watchdog clock enable during + Sleep mode + 11 + 1 + + + + TIM5LPEN + TIM5 clock enable during Sleep + mode + 3 + 1 + + + + TIM4LPEN + TIM4 clock enable during Sleep + mode + 2 + 1 + + + + TIM3LPEN + TIM3 clock enable during Sleep + mode + 1 + 1 + + + + TIM2LPEN + TIM2 clock enable during Sleep + mode + 0 + 1 + + TIM2LPEN + read-write + + DisabledInSleep + Selected module is disabled during Sleep mode + 0 + + + EnabledInSleep + Selected module is enabled during Sleep mode + 1 + + + + + + + APB2LPENR + APB2LPENR + APB2 peripheral clock enabled in low power + mode register + 0x64 + 0x20 + read-write + 0x00075F33 + + + TIM11LPEN + TIM11 clock enable during Sleep + mode + 18 + 1 + + + + TIM10LPEN + TIM10 clock enable during Sleep + mode + 17 + 1 + + + + TIM9LPEN + TIM9 clock enable during sleep + mode + 16 + 1 + + + + SYSCFGLPEN + System configuration controller clock + enable during Sleep mode + 14 + 1 + + + + SPI1LPEN + SPI 1 clock enable during Sleep + mode + 12 + 1 + + + + SDIOLPEN + SDIO clock enable during Sleep + mode + 11 + 1 + + + + ADC1LPEN + ADC1 clock enable during Sleep + mode + 8 + 1 + + + + USART6LPEN + USART6 clock enable during Sleep + mode + 5 + 1 + + + + USART1LPEN + USART1 clock enable during Sleep + mode + 4 + 1 + + + + TIM1LPEN + TIM1 clock enable during Sleep + mode + 0 + 1 + + TIM1LPEN + read-write + + DisabledInSleep + Selected module is disabled during Sleep mode + 0 + + + EnabledInSleep + Selected module is enabled during Sleep mode + 1 + + + + + SPI4LPEN + SPI4 clock enable during Sleep mode + 13 + 1 + + + + + + BDCR + BDCR + Backup domain control register + 0x70 + 0x20 + 0x00000000 + + + BDRST + Backup domain software + reset + 16 + 1 + read-write + + BDRST + read-write + + Disabled + Reset not activated + 0 + + + Enabled + Reset the entire RTC domain + 1 + + + + + RTCEN + RTC clock enable + 15 + 1 + read-write + + RTCEN + read-write + + Disabled + RTC clock disabled + 0 + + + Enabled + RTC clock enabled + 1 + + + + + LSEBYP + External low-speed oscillator + bypass + 2 + 1 + read-write + + LSEBYP + read-write + + NotBypassed + LSE crystal oscillator not bypassed + 0 + + + Bypassed + LSE crystal oscillator bypassed with external clock + 1 + + + + + LSERDY + External low-speed oscillator + ready + 1 + 1 + read-only + + LSERDYR + read + + NotReady + LSE oscillator not ready + 0 + + + Ready + LSE oscillator ready + 1 + + + + + LSEON + External low-speed oscillator + enable + 0 + 1 + read-write + + LSEON + read-write + + Off + LSE oscillator Off + 0 + + + On + LSE oscillator On + 1 + + + + + RTCSEL + RTC clock source selection + 8 + 2 + + RTCSEL + read-write + + NoClock + No clock + 0 + + + LSE + LSE oscillator clock used as RTC clock + 1 + + + LSI + LSI oscillator clock used as RTC clock + 2 + + + HSE + HSE oscillator clock divided by a prescaler used as RTC clock + 3 + + + + + + + CSR + CSR + clock control & status + register + 0x74 + 0x20 + 0x0E000000 + + + LPWRRSTF + Low-power reset flag + 31 + 1 + read-write + + + + WWDGRSTF + Window watchdog reset flag + 30 + 1 + read-write + + + + WDGRSTF + Independent watchdog reset + flag + 29 + 1 + read-write + + + + SFTRSTF + Software reset flag + 28 + 1 + read-write + + + + PORRSTF + POR/PDR reset flag + 27 + 1 + read-write + + + + PADRSTF + PIN reset flag + 26 + 1 + read-write + + + + BORRSTF + BOR reset flag + 25 + 1 + read-write + + BORRSTFR + read + + NoReset + No reset has occured + 0 + + + Reset + A reset has occured + 1 + + + + + RMVF + Remove reset flag + 24 + 1 + read-write + + RMVFW + write + + Clear + Clears the reset flag + 1 + + + + + LSIRDY + Internal low-speed oscillator + ready + 1 + 1 + read-only + + LSIRDYR + read + + NotReady + LSI oscillator not ready + 0 + + + Ready + LSI oscillator ready + 1 + + + + + LSION + Internal low-speed oscillator + enable + 0 + 1 + read-write + + LSION + read-write + + Off + LSI oscillator Off + 0 + + + On + LSI oscillator On + 1 + + + + + + + SSCGR + SSCGR + spread spectrum clock generation + register + 0x80 + 0x20 + read-write + 0x00000000 + + + SSCGEN + Spread spectrum modulation + enable + 31 + 1 + + SSCGEN + read-write + + Disabled + Spread spectrum modulation disabled + 0 + + + Enabled + Spread spectrum modulation enabled + 1 + + + + + SPREADSEL + Spread Select + 30 + 1 + + SPREADSEL + read-write + + Center + Center spread + 0 + + + Down + Down spread + 1 + + + + + INCSTEP + Incrementation step + 13 + 15 + + + 0 + 32767 + + + + + MODPER + Modulation period + 0 + 13 + + + 0 + 8191 + + + + + + + PLLI2SCFGR + PLLI2SCFGR + PLLI2S configuration register + 0x84 + 0x20 + read-write + 0x20003000 + + + PLLI2SR + PLLI2S division factor for I2S + clocks + 28 + 3 + + + 2 + 7 + + + + + PLLI2SN + PLLI2S multiplication factor for + VCO + 6 + 9 + + + 50 + 432 + + + + + + + DCKCFGR + RCC Dedicated Clock Configuration Register + 0x8C + 0x20 + read-write + 0x00000000 + + + TIMPRE + Timers clocks prescalers selection + 24 + 1 + + TIMPRE + read-write + + Mul1Or2 + If the APB prescaler is configured 1, TIMxCLK = PCLKx. Otherwise, TIMxCLK = 2xPCLKx + 0 + + + Mul1Or4 + If the APB prescaler is configured 1, 2 or 4, TIMxCLK = HCLK. Otherwise, TIMxCLK = 4xPCLKx + 1 + + + + + + + + + RTC + Real-time clock + RTC + 0x40002800 + + 0x0 + 0x400 + registers + + + I2C2_EV + I2C2 event interrupt + 33 + + + I2C2_ER + I2C2 error interrupt + 34 + + + + TR + TR + time register + 0x0 + 0x20 + read-write + 0x00000000 + + + PM + AM/PM notation + 22 + 1 + + PM + read-write + + AM + AM or 24-hour format + 0 + + + PM + PM + 1 + + + + + HT + Hour tens in BCD format + 20 + 2 + + + 0 + 3 + + + + + HU + Hour units in BCD format + 16 + 4 + + + 0 + 15 + + + + + MNT + Minute tens in BCD format + 12 + 3 + + + 0 + 7 + + + + + MNU + Minute units in BCD format + 8 + 4 + + + 0 + 15 + + + + + ST + Second tens in BCD format + 4 + 3 + + + 0 + 7 + + + + + SU + Second units in BCD format + 0 + 4 + + + 0 + 15 + + + + + + + DR + DR + date register + 0x4 + 0x20 + read-write + 0x00002101 + + + YT + Year tens in BCD format + 20 + 4 + + + 0 + 15 + + + + + YU + Year units in BCD format + 16 + 4 + + + 0 + 15 + + + + + WDU + Week day units + 13 + 3 + + + 1 + 7 + + + + + MT + Month tens in BCD format + 12 + 1 + + MT + read-write + + Zero + Month tens is 0 + 0 + + + One + Month tens is 1 + 1 + + + + + MU + Month units in BCD format + 8 + 4 + + + 0 + 15 + + + + + DT + Date tens in BCD format + 4 + 2 + + + 0 + 3 + + + + + DU + Date units in BCD format + 0 + 4 + + + 0 + 15 + + + + + + + CR + CR + control register + 0x8 + 0x20 + read-write + 0x00000000 + + + COE + Calibration output enable + 23 + 1 + + COE + read-write + + Disabled + Calibration output disabled + 0 + + + Enabled + Calibration output enabled + 1 + + + + + OSEL + Output selection + 21 + 2 + + OSEL + read-write + + Disabled + Output disabled + 0 + + + AlarmA + Alarm A output enabled + 1 + + + AlarmB + Alarm B output enabled + 2 + + + Wakeup + Wakeup output enabled + 3 + + + + + POL + Output polarity + 20 + 1 + + POL + read-write + + High + The pin is high when ALRAF/ALRBF/WUTF is asserted (depending on OSEL[1:0]) + 0 + + + Low + The pin is low when ALRAF/ALRBF/WUTF is asserted (depending on OSEL[1:0]) + 1 + + + + + COSEL + Calibration Output + selection + 19 + 1 + + COSEL + read-write + + CalFreq_512Hz + Calibration output is 512 Hz (with default prescaler setting) + 0 + + + CalFreq_1Hz + Calibration output is 1 Hz (with default prescaler setting) + 1 + + + + + BKP + Backup + 18 + 1 + + BKP + read-write + + DST_Not_Changed + Daylight Saving Time change has not been performed + 0 + + + DST_Changed + Daylight Saving Time change has been performed + 1 + + + + + SUB1H + Subtract 1 hour (winter time + change) + 17 + 1 + + SUB1HW + write + + Sub1 + Subtracts 1 hour to the current time. This can be used for winter time change outside initialization mode + 1 + + + + + ADD1H + Add 1 hour (summer time + change) + 16 + 1 + + ADD1HW + write + + Add1 + Adds 1 hour to the current time. This can be used for summer time change outside initialization mode + 1 + + + + + TSIE + Time-stamp interrupt + enable + 15 + 1 + + TSIE + read-write + + Disabled + Time-stamp Interrupt disabled + 0 + + + Enabled + Time-stamp Interrupt enabled + 1 + + + + + WUTIE + Wakeup timer interrupt + enable + 14 + 1 + + WUTIE + read-write + + Disabled + Wakeup timer interrupt disabled + 0 + + + Enabled + Wakeup timer interrupt enabled + 1 + + + + + ALRBIE + Alarm B interrupt enable + 13 + 1 + + ALRBIE + read-write + + Disabled + Alarm B Interrupt disabled + 0 + + + Enabled + Alarm B Interrupt enabled + 1 + + + + + ALRAIE + Alarm A interrupt enable + 12 + 1 + + ALRAIE + read-write + + Disabled + Alarm A interrupt disabled + 0 + + + Enabled + Alarm A interrupt enabled + 1 + + + + + TSE + Time stamp enable + 11 + 1 + + TSE + read-write + + Disabled + Timestamp disabled + 0 + + + Enabled + Timestamp enabled + 1 + + + + + WUTE + Wakeup timer enable + 10 + 1 + + WUTE + read-write + + Disabled + Wakeup timer disabled + 0 + + + Enabled + Wakeup timer enabled + 1 + + + + + ALRBE + Alarm B enable + 9 + 1 + + ALRBE + read-write + + Disabled + Alarm B disabled + 0 + + + Enabled + Alarm B enabled + 1 + + + + + ALRAE + Alarm A enable + 8 + 1 + + ALRAE + read-write + + Disabled + Alarm A disabled + 0 + + + Enabled + Alarm A enabled + 1 + + + + + DCE + Coarse digital calibration + enable + 7 + 1 + + + FMT + Hour format + 6 + 1 + + FMT + read-write + + Twenty_Four_Hour + 24 hour/day format + 0 + + + AM_PM + AM/PM hour format + 1 + + + + + BYPSHAD + Bypass the shadow + registers + 5 + 1 + + BYPSHAD + read-write + + ShadowReg + Calendar values (when reading from RTC_SSR, RTC_TR, and RTC_DR) are taken from the shadow registers, which are updated once every two RTCCLK cycles + 0 + + + BypassShadowReg + Calendar values (when reading from RTC_SSR, RTC_TR, and RTC_DR) are taken directly from the calendar counters + 1 + + + + + REFCKON + Reference clock detection enable (50 or + 60 Hz) + 4 + 1 + + REFCKON + read-write + + Disabled + RTC_REFIN detection disabled + 0 + + + Enabled + RTC_REFIN detection enabled + 1 + + + + + TSEDGE + Time-stamp event active + edge + 3 + 1 + + TSEDGE + read-write + + RisingEdge + RTC_TS input rising edge generates a time-stamp event + 0 + + + FallingEdge + RTC_TS input falling edge generates a time-stamp event + 1 + + + + + WUCKSEL + Wakeup clock selection + 0 + 3 + + WUCKSEL + read-write + + Div16 + RTC/16 clock is selected + 0 + + + Div8 + RTC/8 clock is selected + 1 + + + Div4 + RTC/4 clock is selected + 2 + + + Div2 + RTC/2 clock is selected + 3 + + + ClockSpare + ck_spre (usually 1 Hz) clock is selected + 4 + + + ClockSpareWithOffset + ck_spre (usually 1 Hz) clock is selected and 2^16 is added to the WUT counter value + 6 + + + + + + + ISR + ISR + initialization and status + register + 0xC + 0x20 + 0x00000007 + + + ALRAWF + Alarm A write flag + 0 + 1 + read-only + + ALRAWFR + read + + UpdateNotAllowed + Alarm update not allowed + 0 + + + UpdateAllowed + Alarm update allowed + 1 + + + + + ALRBWF + Alarm B write flag + 1 + 1 + read-only + + + + WUTWF + Wakeup timer write flag + 2 + 1 + read-only + + WUTWFR + read + + UpdateNotAllowed + Wakeup timer configuration update not allowed + 0 + + + UpdateAllowed + Wakeup timer configuration update allowed + 1 + + + + + SHPF + Shift operation pending + 3 + 1 + read-write + + SHPFR + read + + NoShiftPending + No shift operation is pending + 0 + + + ShiftPending + A shift operation is pending + 1 + + + + + INITS + Initialization status flag + 4 + 1 + read-only + + INITSR + read + + NotInitalized + Calendar has not been initialized + 0 + + + Initalized + Calendar has been initialized + 1 + + + + + RSF + Registers synchronization + flag + 5 + 1 + read-write + zeroToClear + + RSFR + read + + NotSynced + Calendar shadow registers not yet synchronized + 0 + + + Synced + Calendar shadow registers synchronized + 1 + + + + RSFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + INITF + Initialization flag + 6 + 1 + read-only + + INITFR + read + + NotAllowed + Calendar registers update is not allowed + 0 + + + Allowed + Calendar registers update is allowed + 1 + + + + + INIT + Initialization mode + 7 + 1 + read-write + + INIT + read-write + + FreeRunningMode + Free running mode + 0 + + + InitMode + Initialization mode used to program time and date register (RTC_TR and RTC_DR), and prescaler register (RTC_PRER). Counters are stopped and start counting from the new value when INIT is reset. + 1 + + + + + ALRAF + Alarm A flag + 8 + 1 + read-write + zeroToClear + + ALRAFR + read + + Match + This flag is set by hardware when the time/date registers (RTC_TR and RTC_DR) match the Alarm A register (RTC_ALRMAR) + 1 + + + + ALRAFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + ALRBF + Alarm B flag + 9 + 1 + read-write + zeroToClear + + ALRBFR + read + + Match + This flag is set by hardware when the time/date registers (RTC_TR and RTC_DR) match the Alarm B register (RTC_ALRMBR) + 1 + + + + ALRBFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + WUTF + Wakeup timer flag + 10 + 1 + read-write + zeroToClear + + WUTFR + read + + Zero + This flag is set by hardware when the wakeup auto-reload counter reaches 0 + 1 + + + + WUTFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + TSF + Time-stamp flag + 11 + 1 + read-write + zeroToClear + + TSFR + read + + TimestampEvent + This flag is set by hardware when a time-stamp event occurs + 1 + + + + TSFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + TSOVF + Time-stamp overflow flag + 12 + 1 + read-write + zeroToClear + + TSOVFR + read + + Overflow + This flag is set by hardware when a time-stamp event occurs while TSF is already set + 1 + + + + TSOVFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + TAMP1F + Tamper detection flag + 13 + 1 + read-write + zeroToClear + + TAMP1FR + read + + Tampered + This flag is set by hardware when a tamper detection event is detected on the RTC_TAMPx input + 1 + + + + TAMP1FW + write + + Clear + Flag cleared by software writing 0 + 0 + + + + + TAMP2F + TAMPER2 detection flag + 14 + 1 + read-write + zeroToClear + + read + + + write + + + + RECALPF + Recalibration pending Flag + 16 + 1 + read-only + + RECALPFR + read + + Pending + The RECALPF status flag is automatically set to 1 when software writes to the RTC_CALR register, indicating that the RTC_CALR register is blocked. When the new calibration settings are taken into account, this bit returns to 0 + 1 + + + + + + + PRER + PRER + prescaler register + 0x10 + 0x20 + read-write + 0x007F00FF + + + PREDIV_A + Asynchronous prescaler + factor + 16 + 7 + + + 0 + 127 + + + + + PREDIV_S + Synchronous prescaler + factor + 0 + 15 + + + 0 + 32767 + + + + + + + WUTR + WUTR + wakeup timer register + 0x14 + 0x20 + read-write + 0x0000FFFF + + + WUT + Wakeup auto-reload value + bits + 0 + 16 + + + 0 + 65535 + + + + + + + CALIBR + CALIBR + calibration register + 0x18 + 0x20 + read-write + 0x00000000 + + + DCS + Digital calibration sign + 7 + 1 + + + DC + Digital calibration + 0 + 5 + + + + + 2 + 0x4 + A,B + ALRM%sR + ALRMAR + Alarm register + 0x1C + 0x20 + read-write + 0x00000000 + + + MSK4 + Alarm date mask + 31 + 1 + + + + WDSEL + Week day selection + 30 + 1 + + WDSEL + read-write + + DateUnits + DU[3:0] represents the date units + 0 + + + WeekDay + DU[3:0] represents the week day. DT[1:0] is don’t care. + 1 + + + + + DT + Date tens in BCD format + 28 + 2 + + + 0 + 3 + + + + + DU + Date units or day in BCD format + 24 + 4 + + + 0 + 15 + + + + + MSK3 + Alarm hours mask + 23 + 1 + + + + PM + AM/PM notation + 22 + 1 + + PM + read-write + + AM + AM or 24-hour format + 0 + + + PM + PM + 1 + + + + + HT + Hour tens in BCD format + 20 + 2 + + + 0 + 3 + + + + + HU + Hour units in BCD format + 16 + 4 + + + 0 + 15 + + + + + MSK2 + Alarm minutes mask + 15 + 1 + + + + MNT + Minute tens in BCD format + 12 + 3 + + + 0 + 7 + + + + + MNU + Minute units in BCD format + 8 + 4 + + + 0 + 15 + + + + + MSK1 + Alarm seconds mask + 7 + 1 + + MSK1 + read-write + + Mask + Alarm set if the date/day match + 0 + + + NotMask + Date/day don’t care in Alarm comparison + 1 + + + + + ST + Second tens in BCD format + 4 + 3 + + + 0 + 7 + + + + + SU + Second units in BCD format + 0 + 4 + + + 0 + 15 + + + + + + + WPR + WPR + write protection register + 0x24 + 0x20 + write-only + 0x00000000 + + + KEY + Write protection key + 0 + 8 + + + 0 + 255 + + + + + + + SSR + SSR + sub second register + 0x28 + 0x20 + read-only + 0x00000000 + + + SS + Sub second value + 0 + 16 + + + 0 + 65535 + + + + + + + SHIFTR + SHIFTR + shift control register + 0x2C + 0x20 + write-only + 0x00000000 + + + ADD1S + Add one second + 31 + 1 + + ADD1SW + write + + Add1 + Add one second to the clock/calendar + 1 + + + + + SUBFS + Subtract a fraction of a + second + 0 + 15 + + + 0 + 32767 + + + + + + + TSTR + TSTR + time stamp time register + 0x30 + + + TSDR + TSDR + time stamp date register + 0x34 + + + TSSSR + TSSSR + timestamp sub second register + 0x38 + + + CALR + CALR + calibration register + 0x3C + 0x20 + read-write + 0x00000000 + + + CALP + Increase frequency of RTC by 488.5 + ppm + 15 + 1 + + CALP + read-write + + NoChange + No RTCCLK pulses are added + 0 + + + IncreaseFreq + One RTCCLK pulse is effectively inserted every 2^11 pulses (frequency increased by 488.5 ppm) + 1 + + + + + CALW8 + Use an 8-second calibration cycle + period + 14 + 1 + + CALW8 + read-write + + Eight_Second + When CALW8 is set to ‘1’, the 8-second calibration cycle period is selected + 1 + + + + + CALW16 + Use a 16-second calibration cycle + period + 13 + 1 + + CALW16 + read-write + + Sixteen_Second + When CALW16 is set to ‘1’, the 16-second calibration cycle period is selected.This bit must not be set to ‘1’ if CALW8=1 + 1 + + + + + CALM + Calibration minus + 0 + 9 + + + 0 + 511 + + + + + + + TAFCR + TAFCR + tamper and alternate function configuration + register + 0x40 + 0x20 + read-write + 0x00000000 + + + ALARMOUTTYPE + AFO_ALARM output type + 18 + 1 + + + TSINSEL + TIMESTAMP mapping + 17 + 1 + + + TAMP1INSEL + TAMPER1 mapping + 16 + 1 + + + TAMPPUDIS + TAMPER pull-up disable + 15 + 1 + + + TAMPPRCH + Tamper precharge duration + 13 + 2 + + + TAMPFLT + Tamper filter count + 11 + 2 + + + TAMPFREQ + Tamper sampling frequency + 8 + 3 + + + TAMPTS + Activate timestamp on tamper detection + event + 7 + 1 + + + TAMP2TRG + Active level for tamper 2 + 4 + 1 + + + TAMP2E + Tamper 2 detection enable + 3 + 1 + + + TAMPIE + Tamper interrupt enable + 2 + 1 + + + TAMP1TRG + Active level for tamper 1 + 1 + 1 + + + TAMP1E + Tamper 1 detection enable + 0 + 1 + + + + + 2 + 0x4 + A,B + ALRM%sSSR + ALRMASSR + Alarm sub-second register + 0x44 + 0x20 + read-write + 0x00000000 + + + MASKSS + Mask the most-significant bits starting + at this bit + 24 + 4 + + + 0 + 15 + + + + + SS + Sub seconds value + 0 + 15 + + + 0 + 32767 + + + + + + + 20 + 0x4 + 0-19 + BKP%sR + BKP0R + backup register + 0x50 + 0x20 + read-write + 0x00000000 + + + BKP + BKP + 0 + 32 + + + 0 + 4294967295 + + + + + + + + + SDIO + Secure digital input/output + interface + SDIO + 0x40012C00 + + 0x0 + 0x400 + registers + + + I2C3_EV + I2C3 event interrupt + 72 + + + I2C3_ER + I2C3 error interrupt + 73 + + + + POWER + POWER + power control register + 0x0 + 0x20 + read-write + 0x00000000 + + + PWRCTRL + PWRCTRL + 0 + 2 + + PWRCTRL + read-write + + PowerOff + Power off + 0 + + + PowerOn + Power on + 3 + + + + + + + CLKCR + CLKCR + SDI clock control register + 0x4 + 0x20 + read-write + 0x00000000 + + + HWFC_EN + HW Flow Control enable + 14 + 1 + + HWFC_EN + read-write + + Disabled + HW Flow Control is disabled + 0 + + + Enabled + HW Flow Control is enabled + 1 + + + + + NEGEDGE + SDIO_CK dephasing selection + bit + 13 + 1 + + NEGEDGE + read-write + + Rising + SDIO_CK generated on the rising edge + 0 + + + Falling + SDIO_CK generated on the falling edge + 1 + + + + + WIDBUS + Wide bus mode enable bit + 11 + 2 + + WIDBUS + read-write + + BusWidth1 + 1 lane wide bus + 0 + + + BusWidth4 + 4 lane wide bus + 1 + + + BusWidth8 + 8 lane wide bus + 2 + + + + + BYPASS + Clock divider bypass enable + bit + 10 + 1 + + BYPASS + read-write + + Disabled + SDIOCLK is divided according to the CLKDIV value before driving the SDIO_CK output signal. + 0 + + + Enabled + SDIOCLK directly drives the SDIO_CK output signal + 1 + + + + + PWRSAV + Power saving configuration + bit + 9 + 1 + + PWRSAV + read-write + + Enabled + SDIO_CK clock is always enabled + 0 + + + Disabled + SDIO_CK is only enabled when the bus is active + 1 + + + + + CLKEN + Clock enable bit + 8 + 1 + + CLKEN + read-write + + Disabled + Disable clock + 0 + + + Enabled + Enable clock + 1 + + + + + CLKDIV + Clock divide factor + 0 + 8 + + + 0 + 255 + + + + + + + ARG + ARG + argument register + 0x8 + 0x20 + read-write + 0x00000000 + + + CMDARG + Command argument + 0 + 32 + + + 0 + 4294967295 + + + + + + + CMD + CMD + command register + 0xC + 0x20 + read-write + 0x00000000 + + + CE_ATACMD + CE-ATA command + 14 + 1 + + CE_ATACMD + read-write + + Disabled + CE-ATA command disabled + 0 + + + Enabled + CE-ATA command enabled + 1 + + + + + nIEN + not Interrupt Enable + 13 + 1 + + nIEN + read-write + + Disabled + Interrupts to the CE-ATA not disabled + 0 + + + Enabled + Interrupt to the CE-ATA are disabled + 1 + + + + + ENCMDcompl + Enable CMD completion + 12 + 1 + + ENCMDcompl + read-write + + Disabled + Command complete signal disabled + 0 + + + Enabled + Command complete signal enabled + 1 + + + + + SDIOSuspend + SD I/O suspend command + 11 + 1 + + SDIOSuspend + read-write + + Disabled + Next command is not a SDIO suspend command + 0 + + + Enabled + Next command send is a SDIO suspend command + 1 + + + + + CPSMEN + Command path state machine (CPSM) Enable + bit + 10 + 1 + + CPSMEN + read-write + + Disabled + Command path state machine disabled + 0 + + + Enabled + Command path state machine enabled + 1 + + + + + WAITPEND + CPSM Waits for ends of data transfer + (CmdPend internal signal). + 9 + 1 + + WAITPEND + read-write + + Disabled + Don't wait for data end + 0 + + + Enabled + Wait for end of data transfer signal before sending command + 1 + + + + + WAITINT + CPSM waits for interrupt + request + 8 + 1 + + WAITINT + read-write + + Disabled + Don't wait for interrupt request + 0 + + + Enabled + Wait for interrupt request + 1 + + + + + WAITRESP + Wait for response bits + 6 + 2 + + WAITRESP + read-write + + NoResponse + No response + 0 + + + ShortResponse + Short response + 1 + + + NoResponse2 + No reponse + 2 + + + LongResponse + Long reponse + 3 + + + + + CMDINDEX + Command index + 0 + 6 + + + 0 + 63 + + + + + + + RESPCMD + RESPCMD + command response register + 0x10 + 0x20 + read-only + 0x00000000 + + + RESPCMD + Response command index + 0 + 6 + + + 0 + 63 + + + + + + + RESP1 + RESP1 + response 1..4 register + 0x14 + 0x20 + read-only + 0x00000000 + + + CARDSTATUS1 + Card Status + 0 + 32 + + + 0 + 4294967295 + + + + + + + RESP2 + RESP2 + response 1..4 register + 0x18 + 0x20 + read-only + 0x00000000 + + + CARDSTATUS2 + Card Status + 0 + 32 + + + 0 + 4294967295 + + + + + + + RESP3 + RESP3 + response 1..4 register + 0x1C + 0x20 + read-only + 0x00000000 + + + CARDSTATUS3 + Card Status + 0 + 32 + + + 0 + 4294967295 + + + + + + + RESP4 + RESP4 + response 1..4 register + 0x20 + 0x20 + read-only + 0x00000000 + + + CARDSTATUS4 + Card Status + 0 + 32 + + + 0 + 4294967295 + + + + + + + DTIMER + DTIMER + data timer register + 0x24 + 0x20 + read-write + 0x00000000 + + + DATATIME + Data timeout period + 0 + 32 + + + 0 + 4294967295 + + + + + + + DLEN + DLEN + data length register + 0x28 + 0x20 + read-write + 0x00000000 + + + DATALENGTH + Data length value + 0 + 25 + + + 0 + 33554431 + + + + + + + DCTRL + DCTRL + data control register + 0x2C + 0x20 + read-write + 0x00000000 + + + SDIOEN + SD I/O enable functions + 11 + 1 + + SDIOEN + read-write + + Disabled + SDIO operations disabled + 0 + + + Enabled + SDIO operations enabled + 1 + + + + + RWMOD + Read wait mode + 10 + 1 + + RWMOD + read-write + + D2 + Read wait control stopping using SDIO_D2 + 0 + + + Ck + Read wait control using SDIO_CK + 1 + + + + + RWSTOP + Read wait stop + 9 + 1 + + RWSTOP + read-write + + Disabled + Read wait in progress if RWSTART is enabled + 0 + + + Enabled + Enable for read wait stop if RWSTART is enabled + 1 + + + + + RWSTART + Read wait start + 8 + 1 + + RWSTART + read-write + + Disabled + Don't start read wait operation + 0 + + + Enabled + Read wait operation starts + 1 + + + + + DBLOCKSIZE + Data block size + 4 + 4 + + + 0 + 15 + + + + + DMAEN + DMA enable bit + 3 + 1 + + DMAEN + read-write + + Disabled + Dma disabled + 0 + + + Enabled + Dma enabled + 1 + + + + + DTMODE + Data transfer mode selection 1: Stream + or SDIO multibyte data transfer. + 2 + 1 + + DTMODE + read-write + + BlockMode + Bloack data transfer + 0 + + + StreamMode + Stream or SDIO multibyte data transfer + 1 + + + + + DTDIR + Data transfer direction + selection + 1 + 1 + + DTDIR + read-write + + ControllerToCard + From controller to card + 0 + + + CardToController + From card to controller + 1 + + + + + DTEN + DTEN + 0 + 1 + + DTEN + read-write + + Disabled + Disabled + 0 + + + Enabled + Start transfer + 1 + + + + + + + DCOUNT + DCOUNT + data counter register + 0x30 + 0x20 + read-only + 0x00000000 + + + DATACOUNT + Data count value + 0 + 25 + + + 0 + 33554431 + + + + + + + STA + STA + status register + 0x34 + 0x20 + read-only + 0x00000000 + + + CEATAEND + CE-ATA command completion signal + received for CMD61 + 23 + 1 + + CEATAEND + read + + NotReceived + Completion signal not received + 0 + + + Received + CE-ATA command completion signal received for CMD61 + 1 + + + + + SDIOIT + SDIO interrupt received + 22 + 1 + + SDIOIT + read + + NotReceived + SDIO interrupt not receieved + 0 + + + Received + SDIO interrupt received + 1 + + + + + RXDAVL + Data available in receive + FIFO + 21 + 1 + + RXDAVL + read + + NotAvailable + Data not available in receive FIFO + 0 + + + Available + Data available in receive FIFO + 1 + + + + + TXDAVL + Data available in transmit + FIFO + 20 + 1 + + TXDAVL + read + + NotAvailable + Data not available in transmit FIFO + 0 + + + Available + Data available in transmit FIFO + 1 + + + + + RXFIFOE + Receive FIFO empty + 19 + 1 + + RXFIFOE + read + + NotEmpty + Receive FIFO not empty + 0 + + + Empty + Receive FIFO empty + 1 + + + + + TXFIFOE + Transmit FIFO empty + 18 + 1 + + TXFIFOE + read + + NotEmpty + Transmit FIFO not empty + 0 + + + Empty + Transmit FIFO empty. When HW Flow Control is enabled, TXFIFOE signals becomes activated when the FIFO contains 2 words. + 1 + + + + + RXFIFOF + Receive FIFO full + 17 + 1 + + RXFIFOF + read + + NotFull + Transmit FIFO not full + 0 + + + Full + Receive FIFO full. When HW Flow Control is enabled, RXFIFOF signals becomes activated 2 words before the FIFO is full. + 1 + + + + + TXFIFOF + Transmit FIFO full + 16 + 1 + + TXFIFOF + read + + NotFull + Transmit FIFO not full + 0 + + + Full + Transmit FIFO full + 1 + + + + + RXFIFOHF + Receive FIFO half full: there are at + least 8 words in the FIFO + 15 + 1 + + RXFIFOHF + read + + NotHalfFull + Receive FIFO not half full + 0 + + + HalfFull + Receive FIFO half full. At least 8 words in the FIFO + 1 + + + + + TXFIFOHE + Transmit FIFO half empty: at least 8 + words can be written into the FIFO + 14 + 1 + + TXFIFOHE + read + + NotHalfEmpty + Transmit FIFO not half empty + 0 + + + HalfEmpty + Transmit FIFO half empty. At least 8 words can be written into the FIFO + 1 + + + + + RXACT + Data receive in progress + 13 + 1 + + RXACT + read + + NotInProgress + Data receive not in progress + 0 + + + InProgress + Data receive in progress + 1 + + + + + TXACT + Data transmit in progress + 12 + 1 + + TXACT + read + + NotInProgress + Data transmit is not in progress + 0 + + + InProgress + Data transmit in progress + 1 + + + + + CMDACT + Command transfer in + progress + 11 + 1 + + CMDACT + read + + NotInProgress + Command transfer not in progress + 0 + + + InProgress + Command tranfer in progress + 1 + + + + + DBCKEND + Data block sent/received (CRC check + passed) + 10 + 1 + + DBCKEND + read + + NotTransferred + Data block not sent/received (CRC check failed) + 0 + + + Transferred + Data block sent/received (CRC check passed) + 1 + + + + + STBITERR + Start bit not detected on all data + signals in wide bus mode + 9 + 1 + + STBITERR + read + + Detected + No start bit detected error + 0 + + + NotDetected + Start bit not detected error + 1 + + + + + DATAEND + Data end (data counter, SDIDCOUNT, is + zero) + 8 + 1 + + DATAEND + read + + NotDone + Not done + 0 + + + Done + Data end (DCOUNT, is zero) + 1 + + + + + CMDSENT + Command sent (no response + required) + 7 + 1 + + CMDSENT + read + + NotSent + Command not sent + 0 + + + Sent + Command sent (no response required) + 1 + + + + + CMDREND + Command response received (CRC check + passed) + 6 + 1 + + CMDREND + read + + NotDone + Command not done + 0 + + + Done + Command response received (CRC check passed) + 1 + + + + + RXOVERR + Received FIFO overrun + error + 5 + 1 + + RXOVERR + read + + NoOverrun + No FIFO overrun error + 0 + + + Overrun + Receive FIFO overrun error + 1 + + + + + TXUNDERR + Transmit FIFO underrun + error + 4 + 1 + + TXUNDERR + read + + NoUnderrun + No transmit FIFO underrun error + 0 + + + Underrun + Transmit FIFO underrun error + 1 + + + + + DTIMEOUT + Data timeout + 3 + 1 + + DTIMEOUT + read + + NoTimeout + No data timeout + 0 + + + Timeout + Data timeout + 1 + + + + + CTIMEOUT + Command response timeout + 2 + 1 + + CTIMEOUT + read + + NoTimeout + No Command timeout + 0 + + + Timeout + Command timeout + 1 + + + + + DCRCFAIL + Data block sent/received (CRC check + failed) + 1 + 1 + + DCRCFAIL + read + + NotFailed + No Data block sent/received crc check fail + 0 + + + Failed + Data block sent/received crc failed + 1 + + + + + CCRCFAIL + Command response received (CRC check + failed) + 0 + 1 + + CCRCFAIL + read + + NotFailed + Command response received, crc check passed + 0 + + + Failed + Command response received, crc check failed + 1 + + + + + + + ICR + ICR + interrupt clear register + 0x38 + 0x20 + read-write + 0x00000000 + + + CEATAENDC + CEATAEND flag clear bit + 23 + 1 + + + + SDIOITC + SDIOIT flag clear bit + 22 + 1 + + + + DBCKENDC + DBCKEND flag clear bit + 10 + 1 + + + + STBITERRC + STBITERR flag clear bit + 9 + 1 + + + + DATAENDC + DATAEND flag clear bit + 8 + 1 + + + + CMDSENTC + CMDSENT flag clear bit + 7 + 1 + + + + CMDRENDC + CMDREND flag clear bit + 6 + 1 + + + + RXOVERRC + RXOVERR flag clear bit + 5 + 1 + + + + TXUNDERRC + TXUNDERR flag clear bit + 4 + 1 + + + + DTIMEOUTC + DTIMEOUT flag clear bit + 3 + 1 + + + + CTIMEOUTC + CTIMEOUT flag clear bit + 2 + 1 + + + + DCRCFAILC + DCRCFAIL flag clear bit + 1 + 1 + + + + CCRCFAILC + CCRCFAIL flag clear bit + 0 + 1 + + CCRCFAILCW + write + + Clear + Clear flag + 1 + + + + + + + MASK + MASK + mask register + 0x3C + 0x20 + read-write + 0x00000000 + + + CEATAENDIE + CE-ATA command completion signal + received interrupt enable + 23 + 1 + + + + SDIOITIE + SDIO mode interrupt received interrupt + enable + 22 + 1 + + + + RXDAVLIE + Data available in Rx FIFO interrupt + enable + 21 + 1 + + + + TXDAVLIE + Data available in Tx FIFO interrupt + enable + 20 + 1 + + + + RXFIFOEIE + Rx FIFO empty interrupt + enable + 19 + 1 + + + + TXFIFOEIE + Tx FIFO empty interrupt + enable + 18 + 1 + + + + RXFIFOFIE + Rx FIFO full interrupt + enable + 17 + 1 + + + + TXFIFOFIE + Tx FIFO full interrupt + enable + 16 + 1 + + + + RXFIFOHFIE + Rx FIFO half full interrupt + enable + 15 + 1 + + + + TXFIFOHEIE + Tx FIFO half empty interrupt + enable + 14 + 1 + + + + RXACTIE + Data receive acting interrupt + enable + 13 + 1 + + + + TXACTIE + Data transmit acting interrupt + enable + 12 + 1 + + + + CMDACTIE + Command acting interrupt + enable + 11 + 1 + + + + DBCKENDIE + Data block end interrupt + enable + 10 + 1 + + + + STBITERRIE + Start bit error interrupt + enable + 9 + 1 + + + + DATAENDIE + Data end interrupt enable + 8 + 1 + + + + CMDSENTIE + Command sent interrupt + enable + 7 + 1 + + + + CMDRENDIE + Command response received interrupt + enable + 6 + 1 + + + + RXOVERRIE + Rx FIFO overrun error interrupt + enable + 5 + 1 + + + + TXUNDERRIE + Tx FIFO underrun error interrupt + enable + 4 + 1 + + + + DTIMEOUTIE + Data timeout interrupt + enable + 3 + 1 + + + + CTIMEOUTIE + Command timeout interrupt + enable + 2 + 1 + + + + DCRCFAILIE + Data CRC fail interrupt + enable + 1 + 1 + + + + CCRCFAILIE + Command CRC fail interrupt + enable + 0 + 1 + + CCRCFAILIE + read-write + + Disabled + Interrupt disabled + 0 + + + Enabled + Interrupt enabled + 1 + + + + + + + FIFOCNT + FIFOCNT + FIFO counter register + 0x48 + 0x20 + read-only + 0x00000000 + + + FIFOCOUNT + Remaining number of words to be written + to or read from the FIFO. + 0 + 24 + + + 0 + 16777215 + + + + + + + FIFO + FIFO + data FIFO register + 0x80 + 0x20 + read-write + 0x00000000 + + + FIFOData + Receive and transmit FIFO + data + 0 + 32 + + + 0 + 4294967295 + + + + + + + + + SYSCFG + System configuration controller + SYSCFG + 0x40013800 + + 0x0 + 0x400 + registers + + + + MEMRM + MEMRM + memory remap register + 0x0 + 0x20 + read-write + 0x00000000 + + + MEM_MODE + MEM_MODE + 0 + 2 + + + + + PMC + PMC + peripheral mode configuration + register + 0x4 + 0x20 + read-write + 0x00000000 + + + ADC1DC2 + ADC1DC2 + 16 + 1 + + + + + EXTICR1 + EXTICR1 + external interrupt configuration register + 1 + 0x8 + 0x20 + read-write + 0x00000000 + + + EXTI3 + EXTI x configuration (x = 0 to + 3) + 12 + 4 + + + EXTI2 + EXTI x configuration (x = 0 to + 3) + 8 + 4 + + + EXTI1 + EXTI x configuration (x = 0 to + 3) + 4 + 4 + + + EXTI0 + EXTI x configuration (x = 0 to + 3) + 0 + 4 + + + + + EXTICR2 + EXTICR2 + external interrupt configuration register + 2 + 0xC + 0x20 + read-write + 0x00000000 + + + EXTI7 + EXTI x configuration (x = 4 to + 7) + 12 + 4 + + + EXTI6 + EXTI x configuration (x = 4 to + 7) + 8 + 4 + + + EXTI5 + EXTI x configuration (x = 4 to + 7) + 4 + 4 + + + EXTI4 + EXTI x configuration (x = 4 to + 7) + 0 + 4 + + + + + EXTICR3 + EXTICR3 + external interrupt configuration register + 3 + 0x10 + 0x20 + read-write + 0x00000000 + + + EXTI11 + EXTI x configuration (x = 8 to + 11) + 12 + 4 + + + EXTI10 + EXTI10 + 8 + 4 + + + EXTI9 + EXTI x configuration (x = 8 to + 11) + 4 + 4 + + + EXTI8 + EXTI x configuration (x = 8 to + 11) + 0 + 4 + + + + + EXTICR4 + EXTICR4 + external interrupt configuration register + 4 + 0x14 + 0x20 + read-write + 0x00000000 + + + EXTI15 + EXTI x configuration (x = 12 to + 15) + 12 + 4 + + + EXTI14 + EXTI x configuration (x = 12 to + 15) + 8 + 4 + + + EXTI13 + EXTI x configuration (x = 12 to + 15) + 4 + 4 + + + EXTI12 + EXTI x configuration (x = 12 to + 15) + 0 + 4 + + + + + CMPCR + CMPCR + Compensation cell control + register + 0x20 + 0x20 + read-only + 0x00000000 + + + READY + READY + 8 + 1 + + + CMP_PD + Compensation cell + power-down + 0 + 1 + + + + + + + TIM1 + Advanced-timers + TIM + 0x40010000 + + 0x0 + 0x400 + registers + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + CMS + Center-aligned mode + selection + 5 + 2 + + CMS + read-write + + EdgeAligned + The counter counts up or down depending on the direction bit + 0 + + + CenterAligned1 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting down. + 1 + + + CenterAligned2 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting up. + 2 + + + CenterAligned3 + The counter counts up and down alternatively. Output compare interrupt flags are set both when the counter is counting up or down. + 3 + + + + + DIR + Direction + 4 + 1 + + DIR + read-write + + Up + Counter used as upcounter + 0 + + + Down + Counter used as downcounter + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + OIS4 + Output Idle state 4 + 14 + 1 + + + + OIS3N + Output Idle state 3 + 13 + 1 + + + + OIS3 + Output Idle state 3 + 12 + 1 + + + + OIS2N + Output Idle state 2 + 11 + 1 + + + + OIS2 + Output Idle state 2 + 10 + 1 + + + + OIS1N + Output Idle state 1 + 9 + 1 + + OIS1N + read-write + + Reset + OCxN=0 after a dead-time when MOE=0 + 0 + + + Set + OCxN=1 after a dead-time when MOE=0 + 1 + + + + + OIS1 + Output Idle state 1 + 8 + 1 + + OIS1 + read-write + + Reset + OCx=0 (after a dead-time if OCx(N) is implemented) when MOE=0 + 0 + + + Set + OCx=1 (after a dead-time if OCx(N) is implemented) when MOE=0 + 1 + + + + + TI1S + TI1 selection + 7 + 1 + + TI1S + read-write + + Normal + The TIMx_CH1 pin is connected to TI1 input + 0 + + + XOR + The TIMx_CH1, CH2, CH3 pins are connected to TI1 input + 1 + + + + + MMS + Master mode selection + 4 + 3 + + MMS + read-write + + Reset + The UG bit from the TIMx_EGR register is used as trigger output + 0 + + + Enable + The counter enable signal, CNT_EN, is used as trigger output + 1 + + + Update + The update event is selected as trigger output + 2 + + + ComparePulse + The trigger output send a positive pulse when the CC1IF flag it to be set, as soon as a capture or a compare match occurred + 3 + + + CompareOC1 + OC1REF signal is used as trigger output + 4 + + + CompareOC2 + OC2REF signal is used as trigger output + 5 + + + CompareOC3 + OC3REF signal is used as trigger output + 6 + + + CompareOC4 + OC4REF signal is used as trigger output + 7 + + + + + CCDS + Capture/compare DMA + selection + 3 + 1 + + CCDS + read-write + + OnCompare + CCx DMA request sent when CCx event occurs + 0 + + + OnUpdate + CCx DMA request sent when update event occurs + 1 + + + + + CCUS + Capture/compare control update + selection + 2 + 1 + + + CCPC + Capture/compare preloaded + control + 0 + 1 + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + ETP + External trigger polarity + 15 + 1 + + ETP + read-write + + NotInverted + ETR is noninverted, active at high level or rising edge + 0 + + + Inverted + ETR is inverted, active at low level or falling edge + 1 + + + + + ECE + External clock enable + 14 + 1 + + ECE + read-write + + Disabled + External clock mode 2 disabled + 0 + + + Enabled + External clock mode 2 enabled. The counter is clocked by any active edge on the ETRF signal. + 1 + + + + + ETPS + External trigger prescaler + 12 + 2 + + ETPS + read-write + + Div1 + Prescaler OFF + 0 + + + Div2 + ETRP frequency divided by 2 + 1 + + + Div4 + ETRP frequency divided by 4 + 2 + + + Div8 + ETRP frequency divided by 8 + 3 + + + + + ETF + External trigger filter + 8 + 4 + + ETF + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + MSM + Master/Slave mode + 7 + 1 + + MSM + read-write + + NoSync + No action + 0 + + + Sync + The effect of an event on the trigger input (TRGI) is delayed to allow a perfect synchronization between the current timer and its slaves (through TRGO). It is useful if we want to synchronize several timers on a single external event. + 1 + + + + + TS + Trigger selection + 4 + 3 + + TS + read-write + + ITR0 + Internal Trigger 0 (ITR0) + 0 + + + ITR1 + Internal Trigger 1 (ITR1) + 1 + + + ITR2 + Internal Trigger 2 (ITR2) + 2 + + + TI1F_ED + TI1 Edge Detector (TI1F_ED) + 4 + + + TI1FP1 + Filtered Timer Input 1 (TI1FP1) + 5 + + + TI2FP2 + Filtered Timer Input 2 (TI2FP2) + 6 + + + ETRF + External Trigger input (ETRF) + 7 + + + + + SMS + Slave mode selection + 0 + 3 + + SMS + read-write + + Disabled + Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal clock. + 0 + + + Encoder_Mode_1 + Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending on TI1FP2 level. + 1 + + + Encoder_Mode_2 + Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level. + 2 + + + Encoder_Mode_3 + Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. + 3 + + + Reset_Mode + Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and generates an update of the registers. + 4 + + + Gated_Mode + Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of the counter are controlled. + 5 + + + Trigger_Mode + Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not reset). Only the start of the counter is controlled. + 6 + + + Ext_Clock_Mode + External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter. + 7 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TDE + Trigger DMA request enable + 14 + 1 + + TDE + read-write + + Disabled + Trigger DMA request disabled + 0 + + + Enabled + Trigger DMA request enabled + 1 + + + + + COMDE + COM DMA request enable + 13 + 1 + + + CC4DE + Capture/Compare 4 DMA request + enable + 12 + 1 + + + + CC3DE + Capture/Compare 3 DMA request + enable + 11 + 1 + + + + CC2DE + Capture/Compare 2 DMA request + enable + 10 + 1 + + + + CC1DE + Capture/Compare 1 DMA request + enable + 9 + 1 + + CC1DE + read-write + + Disabled + CCx DMA request disabled + 0 + + + Enabled + CCx DMA request enabled + 1 + + + + + UDE + Update DMA request enable + 8 + 1 + + UDE + read-write + + Disabled + Update DMA request disabled + 0 + + + Enabled + Update DMA request enabled + 1 + + + + + BIE + Break interrupt enable + 7 + 1 + + + TIE + Trigger interrupt enable + 6 + 1 + + TIE + read-write + + Disabled + Trigger interrupt disabled + 0 + + + Enabled + Trigger interrupt enabled + 1 + + + + + COMIE + COM interrupt enable + 5 + 1 + + + CC4IE + Capture/Compare 4 interrupt + enable + 4 + 1 + + + + CC3IE + Capture/Compare 3 interrupt + enable + 3 + 1 + + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + CC1IE + read-write + + Disabled + CCx interrupt disabled + 0 + + + Enabled + CCx interrupt enabled + 1 + + + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC4OF + Capture/Compare 4 overcapture + flag + 12 + 1 + zeroToClear + + read + + + write + + + + CC3OF + Capture/Compare 3 overcapture + flag + 11 + 1 + zeroToClear + + read + + + write + + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + zeroToClear + + read + + + write + + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + zeroToClear + + CC1OFR + read + + Overcapture + The counter value has been captured in TIMx_CCRx register while CCxIF flag was already set + 1 + + + + CC1OFW + write + + Clear + Clear flag + 0 + + + + + BIF + Break interrupt flag + 7 + 1 + + + TIF + Trigger interrupt flag + 6 + 1 + zeroToClear + + TIFR + read + + NoTrigger + No trigger event occurred + 0 + + + Trigger + Trigger interrupt pending + 1 + + + + TIFW + write + + Clear + Clear flag + 0 + + + + + COMIF + COM interrupt flag + 5 + 1 + + + CC4IF + Capture/Compare 4 interrupt + flag + 4 + 1 + zeroToClear + + read + + + write + + + + CC3IF + Capture/Compare 3 interrupt + flag + 3 + 1 + zeroToClear + + read + + + write + + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + zeroToClear + + read + + + write + + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + zeroToClear + + CC1IFR + read + + Match + If CC1 is an output: The content of the counter TIMx_CNT matches the content of the TIMx_CCR1 register. If CC1 is an input: The counter value has been captured in TIMx_CCR1 register. + 1 + + + + CC1IFW + write + + Clear + Clear flag + 0 + + + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + BG + Break generation + 7 + 1 + + + TG + Trigger generation + 6 + 1 + + TGW + write + + Trigger + The TIF flag is set in TIMx_SR register. Related interrupt or DMA transfer can occur if enabled. + 1 + + + + + COMG + Capture/Compare control update + generation + 5 + 1 + + + CC4G + Capture/compare 4 + generation + 4 + 1 + + + + CC3G + Capture/compare 3 + generation + 3 + 1 + + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + CC1GW + write + + Trigger + If CC1 is an output: CC1IF flag is set, Corresponding interrupt or DMA request is sent if enabled. If CC1 is an input: The current value of the counter is captured in TIMx_CCR1 register. + 1 + + + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2CE + Output Compare 2 clear + enable + 15 + 1 + + + OC2M + Output Compare 2 mode + 12 + 3 + + + + OC2PE + Output Compare 2 preload + enable + 11 + 1 + + OC2PE + read-write + + Disabled + Preload register on CCR2 disabled. New values written to CCR2 are taken into account immediately + 0 + + + Enabled + Preload register on CCR2 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC2FE + Output Compare 2 fast + enable + 10 + 1 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + Output + CC2 channel is configured as output + 0 + + + + + OC1CE + Output Compare 1 clear + enable + 7 + 1 + + + OC1M + Output Compare 1 mode + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + Output Compare 1 preload + enable + 3 + 1 + + OC1PE + read-write + + Disabled + Preload register on CCR1 disabled. New values written to CCR1 are taken into account immediately + 0 + + + Enabled + Preload register on CCR1 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC1FE + Output Compare 1 fast + enable + 2 + 1 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + Output + CC1 channel is configured as output + 0 + + + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 4 + + + 0 + 15 + + + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + TI2 + CC2 channel is configured as input, IC2 is mapped on TI2 + 1 + + + TI1 + CC2 channel is configured as input, IC2 is mapped on TI1 + 2 + + + TRC + CC2 channel is configured as input, IC2 is mapped on TRC + 3 + + + + + IC1F + Input capture 1 filter + 4 + 4 + + IC1F + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + TI1 + CC1 channel is configured as input, IC1 is mapped on TI1 + 1 + + + TI2 + CC1 channel is configured as input, IC1 is mapped on TI2 + 2 + + + TRC + CC1 channel is configured as input, IC1 is mapped on TRC + 3 + + + + + + + CCMR2_Output + CCMR2_Output + capture/compare mode register 2 (output + mode) + 0x1C + 0x20 + read-write + 0x00000000 + + + OC4CE + Output compare 4 clear + enable + 15 + 1 + + + OC4M + Output compare 4 mode + 12 + 3 + + + + OC4PE + Output compare 4 preload + enable + 11 + 1 + + OC4PE + read-write + + Disabled + Preload register on CCR4 disabled. New values written to CCR4 are taken into account immediately + 0 + + + Enabled + Preload register on CCR4 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC4FE + Output compare 4 fast + enable + 10 + 1 + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + Output + CC4 channel is configured as output + 0 + + + + + OC3CE + Output compare 3 clear + enable + 7 + 1 + + + OC3M + Output compare 3 mode + 4 + 3 + + OC3M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC3PE + Output compare 3 preload + enable + 3 + 1 + + OC3PE + read-write + + Disabled + Preload register on CCR3 disabled. New values written to CCR3 are taken into account immediately + 0 + + + Enabled + Preload register on CCR3 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC3FE + Output compare 3 fast + enable + 2 + 1 + + + CC3S + Capture/Compare 3 + selection + 0 + 2 + + CC3S + read-write + + Output + CC3 channel is configured as output + 0 + + + + + + + CCMR2_Input + CCMR2_Input + capture/compare mode register 2 (input + mode) + CCMR2_Output + 0x1C + 0x20 + read-write + 0x00000000 + + + IC4F + Input capture 4 filter + 12 + 4 + + + 0 + 15 + + + + + IC4PSC + Input capture 4 prescaler + 10 + 2 + + + 0 + 3 + + + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + TI4 + CC4 channel is configured as input, IC4 is mapped on TI4 + 1 + + + TI3 + CC4 channel is configured as input, IC4 is mapped on TI3 + 2 + + + TRC + CC4 channel is configured as input, IC4 is mapped on TRC + 3 + + + + + IC3F + Input capture 3 filter + 4 + 4 + + + 0 + 15 + + + + + IC3PSC + Input capture 3 prescaler + 2 + 2 + + + 0 + 3 + + + + + CC3S + Capture/compare 3 + selection + 0 + 2 + + CC3S + read-write + + TI3 + CC3 channel is configured as input, IC3 is mapped on TI3 + 1 + + + TI4 + CC3 channel is configured as input, IC3 is mapped on TI4 + 2 + + + TRC + CC3 channel is configured as input, IC3 is mapped on TRC + 3 + + + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC4P + Capture/Compare 3 output + Polarity + 13 + 1 + + + CC4E + Capture/Compare 4 output + enable + 12 + 1 + + + CC3NP + Capture/Compare 3 output + Polarity + 11 + 1 + + + CC3NE + Capture/Compare 3 complementary output + enable + 10 + 1 + + + CC3P + Capture/Compare 3 output + Polarity + 9 + 1 + + + CC3E + Capture/Compare 3 output + enable + 8 + 1 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2NE + Capture/Compare 2 complementary output + enable + 6 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1NE + Capture/Compare 1 complementary output + enable + 2 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + counter value + 0 + 16 + + + 0 + 65535 + + + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + 0 + 65535 + + + + + + + 4 + 0x4 + 1-4 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + 0 + 65535 + + + + + + + DCR + DCR + DMA control register + 0x48 + 0x20 + read-write + 0x00000000 + + + DBL + DMA burst length + 8 + 5 + + + 0 + 18 + + + + + DBA + DMA base address + 0 + 5 + + + 0 + 31 + + + + + + + DMAR + DMAR + DMA address for full transfer + 0x4C + 0x20 + read-write + 0x00000000 + + + DMAB + DMA register for burst + accesses + 0 + 16 + + + + + RCR + RCR + repetition counter register + 0x30 + 0x20 + read-write + 0x00000000 + + + REP + Repetition counter value + 0 + 8 + + + + + BDTR + BDTR + break and dead-time register + 0x44 + 0x20 + read-write + 0x00000000 + + + MOE + Main output enable + 15 + 1 + + MOE + read-write + + DisabledIdle + OC/OCN are disabled or forced idle depending on OSSI + 0 + + + Enabled + OC/OCN are enabled if CCxE/CCxNE are set + 1 + + + + + AOE + Automatic output enable + 14 + 1 + + AOE + read-write + + Manual + MOE can be set only by software + 0 + + + Automatic + MOE can be set by software or automatically at the next update event (if none of the break inputs BRK and BRK2 is active) + 1 + + + + + BKP + Break polarity + 13 + 1 + + BKP + read-write + + ActiveLow + Break input BRKx is active low + 0 + + + ActiveHigh + Break input BRKx is active high + 1 + + + + + BKE + Break enable + 12 + 1 + + BKE + read-write + + Disabled + Break function x disabled + 0 + + + Enabled + Break function x disabled + 1 + + + + + OSSR + Off-state selection for Run + mode + 11 + 1 + + OSSR + read-write + + Disabled + When inactive, OC/OCN outputs are disabled + 0 + + + IdleLevel + When inactive, OC/OCN outputs are enabled with their inactive level + 1 + + + + + OSSI + Off-state selection for Idle + mode + 10 + 1 + + OSSI + read-write + + Disabled + When inactive, OC/OCN outputs are disabled + 0 + + + IdleLevel + When inactive, OC/OCN outputs are forced to idle level + 1 + + + + + LOCK + Lock configuration + 8 + 2 + + LOCK + read-write + + Off + No bit is write protected + 0 + + + Level1 + Any bits except MOE, OSSR, OSSI and LOCK in TIMx_BDTR register, OISx and OISxN bits in TIMx_CR2 register can no longer be written + 1 + + + Level2 + LOCK Level 1 + CC Polarity bits (CCxP/CCxNP bits in TIMx_CCER register, as long as the related channel is configured in output through the CCxS bits) as well as OSSR and OSSI bits can no longer be written + 2 + + + Level3 + LOCK Level 2 + CC Control bits (OCxM and OCxPE bits in TIMx_CCMRx registers, as long as the related channel is configured in output through the CCxS bits) can no longer be written + 3 + + + + + DTG + Dead-time generator setup + 0 + 8 + + + 0 + 255 + + + + + + + + + TIM10 + General-purpose-timers + TIM + 0x40014400 + + 0x0 + 0x400 + registers + + + SPI1 + SPI1 global interrupt + 35 + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC1M + Output Compare 1 mode + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + Output Compare 1 preload + enable + 3 + 1 + + + OC1FE + Output Compare 1 fast + enable + 2 + 1 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC1F + Input capture 1 filter + 4 + 4 + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + counter value + 0 + 16 + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + + + 1 + 0x0 + 1-1 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + + + + + TIM11 + General-purpose-timers + TIM + 0x40014800 + + 0x0 + 0x400 + registers + + + SPI2 + SPI2 global interrupt + 36 + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC1M + Output Compare 1 mode + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + Output Compare 1 preload + enable + 3 + 1 + + + OC1FE + Output Compare 1 fast + enable + 2 + 1 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC1F + Input capture 1 filter + 4 + 4 + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + counter value + 0 + 16 + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + + + 1 + 0x0 + 1-1 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + + + OR + OR + option register + 0x50 + 0x20 + read-write + 0x00000000 + + + RMP + Input 1 remapping + capability + 0 + 2 + + + + + + + TIM2 + General purpose timers + TIM + 0x40000000 + + 0x0 + 0x400 + registers + + + SPI3 + SPI3 global interrupt + 51 + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + CMS + Center-aligned mode + selection + 5 + 2 + + CMS + read-write + + EdgeAligned + The counter counts up or down depending on the direction bit + 0 + + + CenterAligned1 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting down. + 1 + + + CenterAligned2 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting up. + 2 + + + CenterAligned3 + The counter counts up and down alternatively. Output compare interrupt flags are set both when the counter is counting up or down. + 3 + + + + + DIR + Direction + 4 + 1 + + DIR + read-write + + Up + Counter used as upcounter + 0 + + + Down + Counter used as downcounter + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + TI1S + TI1 selection + 7 + 1 + + TI1S + read-write + + Normal + The TIMx_CH1 pin is connected to TI1 input + 0 + + + XOR + The TIMx_CH1, CH2, CH3 pins are connected to TI1 input + 1 + + + + + MMS + Master mode selection + 4 + 3 + + MMS + read-write + + Reset + The UG bit from the TIMx_EGR register is used as trigger output + 0 + + + Enable + The counter enable signal, CNT_EN, is used as trigger output + 1 + + + Update + The update event is selected as trigger output + 2 + + + ComparePulse + The trigger output send a positive pulse when the CC1IF flag it to be set, as soon as a capture or a compare match occurred + 3 + + + CompareOC1 + OC1REF signal is used as trigger output + 4 + + + CompareOC2 + OC2REF signal is used as trigger output + 5 + + + CompareOC3 + OC3REF signal is used as trigger output + 6 + + + CompareOC4 + OC4REF signal is used as trigger output + 7 + + + + + CCDS + Capture/compare DMA + selection + 3 + 1 + + CCDS + read-write + + OnCompare + CCx DMA request sent when CCx event occurs + 0 + + + OnUpdate + CCx DMA request sent when update event occurs + 1 + + + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + ETP + External trigger polarity + 15 + 1 + + ETP + read-write + + NotInverted + ETR is noninverted, active at high level or rising edge + 0 + + + Inverted + ETR is inverted, active at low level or falling edge + 1 + + + + + ECE + External clock enable + 14 + 1 + + ECE + read-write + + Disabled + External clock mode 2 disabled + 0 + + + Enabled + External clock mode 2 enabled. The counter is clocked by any active edge on the ETRF signal. + 1 + + + + + ETPS + External trigger prescaler + 12 + 2 + + ETPS + read-write + + Div1 + Prescaler OFF + 0 + + + Div2 + ETRP frequency divided by 2 + 1 + + + Div4 + ETRP frequency divided by 4 + 2 + + + Div8 + ETRP frequency divided by 8 + 3 + + + + + ETF + External trigger filter + 8 + 4 + + ETF + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + MSM + Master/Slave mode + 7 + 1 + + MSM + read-write + + NoSync + No action + 0 + + + Sync + The effect of an event on the trigger input (TRGI) is delayed to allow a perfect synchronization between the current timer and its slaves (through TRGO). It is useful if we want to synchronize several timers on a single external event. + 1 + + + + + TS + Trigger selection + 4 + 3 + + TS + read-write + + ITR0 + Internal Trigger 0 (ITR0) + 0 + + + ITR1 + Internal Trigger 1 (ITR1) + 1 + + + ITR2 + Internal Trigger 2 (ITR2) + 2 + + + TI1F_ED + TI1 Edge Detector (TI1F_ED) + 4 + + + TI1FP1 + Filtered Timer Input 1 (TI1FP1) + 5 + + + TI2FP2 + Filtered Timer Input 2 (TI2FP2) + 6 + + + ETRF + External Trigger input (ETRF) + 7 + + + + + SMS + Slave mode selection + 0 + 3 + + SMS + read-write + + Disabled + Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal clock. + 0 + + + Encoder_Mode_1 + Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending on TI1FP2 level. + 1 + + + Encoder_Mode_2 + Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level. + 2 + + + Encoder_Mode_3 + Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. + 3 + + + Reset_Mode + Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and generates an update of the registers. + 4 + + + Gated_Mode + Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of the counter are controlled. + 5 + + + Trigger_Mode + Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not reset). Only the start of the counter is controlled. + 6 + + + Ext_Clock_Mode + External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter. + 7 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TDE + Trigger DMA request enable + 14 + 1 + + TDE + read-write + + Disabled + Trigger DMA request disabled + 0 + + + Enabled + Trigger DMA request enabled + 1 + + + + + CC4DE + Capture/Compare 4 DMA request + enable + 12 + 1 + + + + CC3DE + Capture/Compare 3 DMA request + enable + 11 + 1 + + + + CC2DE + Capture/Compare 2 DMA request + enable + 10 + 1 + + + + CC1DE + Capture/Compare 1 DMA request + enable + 9 + 1 + + CC1DE + read-write + + Disabled + CCx DMA request disabled + 0 + + + Enabled + CCx DMA request enabled + 1 + + + + + UDE + Update DMA request enable + 8 + 1 + + UDE + read-write + + Disabled + Update DMA request disabled + 0 + + + Enabled + Update DMA request enabled + 1 + + + + + TIE + Trigger interrupt enable + 6 + 1 + + TIE + read-write + + Disabled + Trigger interrupt disabled + 0 + + + Enabled + Trigger interrupt enabled + 1 + + + + + CC4IE + Capture/Compare 4 interrupt + enable + 4 + 1 + + + + CC3IE + Capture/Compare 3 interrupt + enable + 3 + 1 + + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + CC1IE + read-write + + Disabled + CCx interrupt disabled + 0 + + + Enabled + CCx interrupt enabled + 1 + + + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC4OF + Capture/Compare 4 overcapture + flag + 12 + 1 + zeroToClear + + read + + + write + + + + CC3OF + Capture/Compare 3 overcapture + flag + 11 + 1 + zeroToClear + + read + + + write + + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + zeroToClear + + read + + + write + + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + zeroToClear + + CC1OFR + read + + Overcapture + The counter value has been captured in TIMx_CCRx register while CCxIF flag was already set + 1 + + + + CC1OFW + write + + Clear + Clear flag + 0 + + + + + TIF + Trigger interrupt flag + 6 + 1 + zeroToClear + + TIFR + read + + NoTrigger + No trigger event occurred + 0 + + + Trigger + Trigger interrupt pending + 1 + + + + TIFW + write + + Clear + Clear flag + 0 + + + + + CC4IF + Capture/Compare 4 interrupt + flag + 4 + 1 + zeroToClear + + read + + + write + + + + CC3IF + Capture/Compare 3 interrupt + flag + 3 + 1 + zeroToClear + + read + + + write + + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + zeroToClear + + read + + + write + + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + zeroToClear + + CC1IFR + read + + Match + If CC1 is an output: The content of the counter TIMx_CNT matches the content of the TIMx_CCR1 register. If CC1 is an input: The counter value has been captured in TIMx_CCR1 register. + 1 + + + + CC1IFW + write + + Clear + Clear flag + 0 + + + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + TG + Trigger generation + 6 + 1 + + TGW + write + + Trigger + The TIF flag is set in TIMx_SR register. Related interrupt or DMA transfer can occur if enabled. + 1 + + + + + CC4G + Capture/compare 4 + generation + 4 + 1 + + + + CC3G + Capture/compare 3 + generation + 3 + 1 + + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + CC1GW + write + + Trigger + If CC1 is an output: CC1IF flag is set, Corresponding interrupt or DMA request is sent if enabled. If CC1 is an input: The current value of the counter is captured in TIMx_CCR1 register. + 1 + + + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2CE + OC2CE + 15 + 1 + + + OC2M + OC2M + 12 + 3 + + + + OC2PE + OC2PE + 11 + 1 + + OC2PE + read-write + + Disabled + Preload register on CCR2 disabled. New values written to CCR2 are taken into account immediately + 0 + + + Enabled + Preload register on CCR2 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC2FE + OC2FE + 10 + 1 + + + CC2S + CC2S + 8 + 2 + + CC2S + read-write + + Output + CC2 channel is configured as output + 0 + + + + + OC1CE + OC1CE + 7 + 1 + + + OC1M + OC1M + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + OC1PE + 3 + 1 + + OC1PE + read-write + + Disabled + Preload register on CCR1 disabled. New values written to CCR1 are taken into account immediately + 0 + + + Enabled + Preload register on CCR1 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC1FE + OC1FE + 2 + 1 + + + CC1S + CC1S + 0 + 2 + + CC1S + read-write + + Output + CC1 channel is configured as output + 0 + + + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 4 + + + 0 + 15 + + + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + TI2 + CC2 channel is configured as input, IC2 is mapped on TI2 + 1 + + + TI1 + CC2 channel is configured as input, IC2 is mapped on TI1 + 2 + + + TRC + CC2 channel is configured as input, IC2 is mapped on TRC + 3 + + + + + IC1F + Input capture 1 filter + 4 + 4 + + IC1F + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + TI1 + CC1 channel is configured as input, IC1 is mapped on TI1 + 1 + + + TI2 + CC1 channel is configured as input, IC1 is mapped on TI2 + 2 + + + TRC + CC1 channel is configured as input, IC1 is mapped on TRC + 3 + + + + + + + CCMR2_Output + CCMR2_Output + capture/compare mode register 2 (output + mode) + 0x1C + 0x20 + read-write + 0x00000000 + + + OC4CE + O24CE + 15 + 1 + + + OC4M + OC4M + 12 + 3 + + + + OC4PE + OC4PE + 11 + 1 + + OC4PE + read-write + + Disabled + Preload register on CCR4 disabled. New values written to CCR4 are taken into account immediately + 0 + + + Enabled + Preload register on CCR4 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC4FE + OC4FE + 10 + 1 + + + CC4S + CC4S + 8 + 2 + + CC4S + read-write + + Output + CC4 channel is configured as output + 0 + + + + + OC3CE + OC3CE + 7 + 1 + + + OC3M + OC3M + 4 + 3 + + OC3M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC3PE + OC3PE + 3 + 1 + + OC3PE + read-write + + Disabled + Preload register on CCR3 disabled. New values written to CCR3 are taken into account immediately + 0 + + + Enabled + Preload register on CCR3 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC3FE + OC3FE + 2 + 1 + + + CC3S + CC3S + 0 + 2 + + CC3S + read-write + + Output + CC3 channel is configured as output + 0 + + + + + + + CCMR2_Input + CCMR2_Input + capture/compare mode register 2 (input + mode) + CCMR2_Output + 0x1C + 0x20 + read-write + 0x00000000 + + + IC4F + Input capture 4 filter + 12 + 4 + + + 0 + 15 + + + + + IC4PSC + Input capture 4 prescaler + 10 + 2 + + + 0 + 3 + + + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + TI4 + CC4 channel is configured as input, IC4 is mapped on TI4 + 1 + + + TI3 + CC4 channel is configured as input, IC4 is mapped on TI3 + 2 + + + TRC + CC4 channel is configured as input, IC4 is mapped on TRC + 3 + + + + + IC3F + Input capture 3 filter + 4 + 4 + + + 0 + 15 + + + + + IC3PSC + Input capture 3 prescaler + 2 + 2 + + + 0 + 3 + + + + + CC3S + Capture/compare 3 + selection + 0 + 2 + + CC3S + read-write + + TI3 + CC3 channel is configured as input, IC3 is mapped on TI3 + 1 + + + TI4 + CC3 channel is configured as input, IC3 is mapped on TI4 + 2 + + + TRC + CC3 channel is configured as input, IC3 is mapped on TRC + 3 + + + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC4NP + Capture/Compare 4 output + Polarity + 15 + 1 + + + CC4P + Capture/Compare 3 output + Polarity + 13 + 1 + + + CC4E + Capture/Compare 4 output + enable + 12 + 1 + + + CC3NP + Capture/Compare 3 output + Polarity + 11 + 1 + + + CC3P + Capture/Compare 3 output + Polarity + 9 + 1 + + + CC3E + Capture/Compare 3 output + enable + 8 + 1 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + Counter value + 0 + 32 + + + 0 + 4294967295 + + + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 32 + + + 0 + 4294967295 + + + + + + + 4 + 0x4 + 1-4 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 32 + + + 0 + 4294967295 + + + + + + + DCR + DCR + DMA control register + 0x48 + 0x20 + read-write + 0x00000000 + + + DBL + DMA burst length + 8 + 5 + + + 0 + 18 + + + + + DBA + DMA base address + 0 + 5 + + + 0 + 31 + + + + + + + DMAR + DMAR + DMA address for full transfer + 0x4C + 0x20 + read-write + 0x00000000 + + + DMAB + DMA register for burst + accesses + 0 + 16 + + + + + OR + OR + TIM5 option register + 0x50 + 0x20 + read-write + 0x00000000 + + + ITR1_RMP + Timer Input 4 remap + 10 + 2 + + + + + + + TIM3 + General purpose timers + TIM + 0x40000400 + + 0x0 + 0x400 + registers + + + SPI4 + SPI4 global interrupt + 84 + + + TIM4 + TIM4 global interrupt + 30 + + + TIM5 + TIM5 global interrupt + 50 + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + CMS + Center-aligned mode + selection + 5 + 2 + + CMS + read-write + + EdgeAligned + The counter counts up or down depending on the direction bit + 0 + + + CenterAligned1 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting down. + 1 + + + CenterAligned2 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting up. + 2 + + + CenterAligned3 + The counter counts up and down alternatively. Output compare interrupt flags are set both when the counter is counting up or down. + 3 + + + + + DIR + Direction + 4 + 1 + + DIR + read-write + + Up + Counter used as upcounter + 0 + + + Down + Counter used as downcounter + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + TI1S + TI1 selection + 7 + 1 + + TI1S + read-write + + Normal + The TIMx_CH1 pin is connected to TI1 input + 0 + + + XOR + The TIMx_CH1, CH2, CH3 pins are connected to TI1 input + 1 + + + + + MMS + Master mode selection + 4 + 3 + + MMS + read-write + + Reset + The UG bit from the TIMx_EGR register is used as trigger output + 0 + + + Enable + The counter enable signal, CNT_EN, is used as trigger output + 1 + + + Update + The update event is selected as trigger output + 2 + + + ComparePulse + The trigger output send a positive pulse when the CC1IF flag it to be set, as soon as a capture or a compare match occurred + 3 + + + CompareOC1 + OC1REF signal is used as trigger output + 4 + + + CompareOC2 + OC2REF signal is used as trigger output + 5 + + + CompareOC3 + OC3REF signal is used as trigger output + 6 + + + CompareOC4 + OC4REF signal is used as trigger output + 7 + + + + + CCDS + Capture/compare DMA + selection + 3 + 1 + + CCDS + read-write + + OnCompare + CCx DMA request sent when CCx event occurs + 0 + + + OnUpdate + CCx DMA request sent when update event occurs + 1 + + + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + ETP + External trigger polarity + 15 + 1 + + ETP + read-write + + NotInverted + ETR is noninverted, active at high level or rising edge + 0 + + + Inverted + ETR is inverted, active at low level or falling edge + 1 + + + + + ECE + External clock enable + 14 + 1 + + ECE + read-write + + Disabled + External clock mode 2 disabled + 0 + + + Enabled + External clock mode 2 enabled. The counter is clocked by any active edge on the ETRF signal. + 1 + + + + + ETPS + External trigger prescaler + 12 + 2 + + ETPS + read-write + + Div1 + Prescaler OFF + 0 + + + Div2 + ETRP frequency divided by 2 + 1 + + + Div4 + ETRP frequency divided by 4 + 2 + + + Div8 + ETRP frequency divided by 8 + 3 + + + + + ETF + External trigger filter + 8 + 4 + + ETF + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + MSM + Master/Slave mode + 7 + 1 + + MSM + read-write + + NoSync + No action + 0 + + + Sync + The effect of an event on the trigger input (TRGI) is delayed to allow a perfect synchronization between the current timer and its slaves (through TRGO). It is useful if we want to synchronize several timers on a single external event. + 1 + + + + + TS + Trigger selection + 4 + 3 + + TS + read-write + + ITR0 + Internal Trigger 0 (ITR0) + 0 + + + ITR1 + Internal Trigger 1 (ITR1) + 1 + + + ITR2 + Internal Trigger 2 (ITR2) + 2 + + + TI1F_ED + TI1 Edge Detector (TI1F_ED) + 4 + + + TI1FP1 + Filtered Timer Input 1 (TI1FP1) + 5 + + + TI2FP2 + Filtered Timer Input 2 (TI2FP2) + 6 + + + ETRF + External Trigger input (ETRF) + 7 + + + + + SMS + Slave mode selection + 0 + 3 + + SMS + read-write + + Disabled + Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal clock. + 0 + + + Encoder_Mode_1 + Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending on TI1FP2 level. + 1 + + + Encoder_Mode_2 + Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level. + 2 + + + Encoder_Mode_3 + Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. + 3 + + + Reset_Mode + Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and generates an update of the registers. + 4 + + + Gated_Mode + Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of the counter are controlled. + 5 + + + Trigger_Mode + Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not reset). Only the start of the counter is controlled. + 6 + + + Ext_Clock_Mode + External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter. + 7 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TDE + Trigger DMA request enable + 14 + 1 + + TDE + read-write + + Disabled + Trigger DMA request disabled + 0 + + + Enabled + Trigger DMA request enabled + 1 + + + + + CC4DE + Capture/Compare 4 DMA request + enable + 12 + 1 + + + + CC3DE + Capture/Compare 3 DMA request + enable + 11 + 1 + + + + CC2DE + Capture/Compare 2 DMA request + enable + 10 + 1 + + + + CC1DE + Capture/Compare 1 DMA request + enable + 9 + 1 + + CC1DE + read-write + + Disabled + CCx DMA request disabled + 0 + + + Enabled + CCx DMA request enabled + 1 + + + + + UDE + Update DMA request enable + 8 + 1 + + UDE + read-write + + Disabled + Update DMA request disabled + 0 + + + Enabled + Update DMA request enabled + 1 + + + + + TIE + Trigger interrupt enable + 6 + 1 + + TIE + read-write + + Disabled + Trigger interrupt disabled + 0 + + + Enabled + Trigger interrupt enabled + 1 + + + + + CC4IE + Capture/Compare 4 interrupt + enable + 4 + 1 + + + + CC3IE + Capture/Compare 3 interrupt + enable + 3 + 1 + + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + CC1IE + read-write + + Disabled + CCx interrupt disabled + 0 + + + Enabled + CCx interrupt enabled + 1 + + + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC4OF + Capture/Compare 4 overcapture + flag + 12 + 1 + zeroToClear + + read + + + write + + + + CC3OF + Capture/Compare 3 overcapture + flag + 11 + 1 + zeroToClear + + read + + + write + + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + zeroToClear + + read + + + write + + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + zeroToClear + + CC1OFR + read + + Overcapture + The counter value has been captured in TIMx_CCRx register while CCxIF flag was already set + 1 + + + + CC1OFW + write + + Clear + Clear flag + 0 + + + + + TIF + Trigger interrupt flag + 6 + 1 + zeroToClear + + TIFR + read + + NoTrigger + No trigger event occurred + 0 + + + Trigger + Trigger interrupt pending + 1 + + + + TIFW + write + + Clear + Clear flag + 0 + + + + + CC4IF + Capture/Compare 4 interrupt + flag + 4 + 1 + zeroToClear + + read + + + write + + + + CC3IF + Capture/Compare 3 interrupt + flag + 3 + 1 + zeroToClear + + read + + + write + + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + zeroToClear + + read + + + write + + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + zeroToClear + + CC1IFR + read + + Match + If CC1 is an output: The content of the counter TIMx_CNT matches the content of the TIMx_CCR1 register. If CC1 is an input: The counter value has been captured in TIMx_CCR1 register. + 1 + + + + CC1IFW + write + + Clear + Clear flag + 0 + + + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + TG + Trigger generation + 6 + 1 + + TGW + write + + Trigger + The TIF flag is set in TIMx_SR register. Related interrupt or DMA transfer can occur if enabled. + 1 + + + + + CC4G + Capture/compare 4 + generation + 4 + 1 + + + + CC3G + Capture/compare 3 + generation + 3 + 1 + + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + CC1GW + write + + Trigger + If CC1 is an output: CC1IF flag is set, Corresponding interrupt or DMA request is sent if enabled. If CC1 is an input: The current value of the counter is captured in TIMx_CCR1 register. + 1 + + + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2CE + OC2CE + 15 + 1 + + + OC2M + OC2M + 12 + 3 + + + + OC2PE + OC2PE + 11 + 1 + + OC2PE + read-write + + Disabled + Preload register on CCR2 disabled. New values written to CCR2 are taken into account immediately + 0 + + + Enabled + Preload register on CCR2 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC2FE + OC2FE + 10 + 1 + + + CC2S + CC2S + 8 + 2 + + CC2S + read-write + + Output + CC2 channel is configured as output + 0 + + + + + OC1CE + OC1CE + 7 + 1 + + + OC1M + OC1M + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + OC1PE + 3 + 1 + + OC1PE + read-write + + Disabled + Preload register on CCR1 disabled. New values written to CCR1 are taken into account immediately + 0 + + + Enabled + Preload register on CCR1 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC1FE + OC1FE + 2 + 1 + + + CC1S + CC1S + 0 + 2 + + CC1S + read-write + + Output + CC1 channel is configured as output + 0 + + + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 4 + + + 0 + 15 + + + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + TI2 + CC2 channel is configured as input, IC2 is mapped on TI2 + 1 + + + TI1 + CC2 channel is configured as input, IC2 is mapped on TI1 + 2 + + + TRC + CC2 channel is configured as input, IC2 is mapped on TRC + 3 + + + + + IC1F + Input capture 1 filter + 4 + 4 + + IC1F + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + TI1 + CC1 channel is configured as input, IC1 is mapped on TI1 + 1 + + + TI2 + CC1 channel is configured as input, IC1 is mapped on TI2 + 2 + + + TRC + CC1 channel is configured as input, IC1 is mapped on TRC + 3 + + + + + + + CCMR2_Output + CCMR2_Output + capture/compare mode register 2 (output + mode) + 0x1C + 0x20 + read-write + 0x00000000 + + + OC4CE + O24CE + 15 + 1 + + + OC4M + OC4M + 12 + 3 + + + + OC4PE + OC4PE + 11 + 1 + + OC4PE + read-write + + Disabled + Preload register on CCR4 disabled. New values written to CCR4 are taken into account immediately + 0 + + + Enabled + Preload register on CCR4 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC4FE + OC4FE + 10 + 1 + + + CC4S + CC4S + 8 + 2 + + CC4S + read-write + + Output + CC4 channel is configured as output + 0 + + + + + OC3CE + OC3CE + 7 + 1 + + + OC3M + OC3M + 4 + 3 + + OC3M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC3PE + OC3PE + 3 + 1 + + OC3PE + read-write + + Disabled + Preload register on CCR3 disabled. New values written to CCR3 are taken into account immediately + 0 + + + Enabled + Preload register on CCR3 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC3FE + OC3FE + 2 + 1 + + + CC3S + CC3S + 0 + 2 + + CC3S + read-write + + Output + CC3 channel is configured as output + 0 + + + + + + + CCMR2_Input + CCMR2_Input + capture/compare mode register 2 (input + mode) + CCMR2_Output + 0x1C + 0x20 + read-write + 0x00000000 + + + IC4F + Input capture 4 filter + 12 + 4 + + + 0 + 15 + + + + + IC4PSC + Input capture 4 prescaler + 10 + 2 + + + 0 + 3 + + + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + TI4 + CC4 channel is configured as input, IC4 is mapped on TI4 + 1 + + + TI3 + CC4 channel is configured as input, IC4 is mapped on TI3 + 2 + + + TRC + CC4 channel is configured as input, IC4 is mapped on TRC + 3 + + + + + IC3F + Input capture 3 filter + 4 + 4 + + + 0 + 15 + + + + + IC3PSC + Input capture 3 prescaler + 2 + 2 + + + 0 + 3 + + + + + CC3S + Capture/compare 3 + selection + 0 + 2 + + CC3S + read-write + + TI3 + CC3 channel is configured as input, IC3 is mapped on TI3 + 1 + + + TI4 + CC3 channel is configured as input, IC3 is mapped on TI4 + 2 + + + TRC + CC3 channel is configured as input, IC3 is mapped on TRC + 3 + + + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC4NP + Capture/Compare 4 output + Polarity + 15 + 1 + + + CC4P + Capture/Compare 3 output + Polarity + 13 + 1 + + + CC4E + Capture/Compare 4 output + enable + 12 + 1 + + + CC3NP + Capture/Compare 3 output + Polarity + 11 + 1 + + + CC3P + Capture/Compare 3 output + Polarity + 9 + 1 + + + CC3E + Capture/Compare 3 output + enable + 8 + 1 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + Counter value + 0 + 16 + + + 0 + 65535 + + + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + 0 + 65535 + + + + + + + 4 + 0x4 + 1-4 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + 0 + 65535 + + + + + + + DCR + DCR + DMA control register + 0x48 + 0x20 + read-write + 0x00000000 + + + DBL + DMA burst length + 8 + 5 + + + 0 + 18 + + + + + DBA + DMA base address + 0 + 5 + + + 0 + 31 + + + + + + + DMAR + DMAR + DMA address for full transfer + 0x4C + 0x20 + read-write + 0x00000000 + + + DMAB + DMA register for burst + accesses + 0 + 16 + + + + + + + TIM4 + TIM + 0x40000800 + + + TIM5 + General-purpose-timers + TIM + 0x40000C00 + + 0x0 + 0x400 + registers + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + CMS + Center-aligned mode + selection + 5 + 2 + + CMS + read-write + + EdgeAligned + The counter counts up or down depending on the direction bit + 0 + + + CenterAligned1 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting down. + 1 + + + CenterAligned2 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting up. + 2 + + + CenterAligned3 + The counter counts up and down alternatively. Output compare interrupt flags are set both when the counter is counting up or down. + 3 + + + + + DIR + Direction + 4 + 1 + + DIR + read-write + + Up + Counter used as upcounter + 0 + + + Down + Counter used as downcounter + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + TI1S + TI1 selection + 7 + 1 + + TI1S + read-write + + Normal + The TIMx_CH1 pin is connected to TI1 input + 0 + + + XOR + The TIMx_CH1, CH2, CH3 pins are connected to TI1 input + 1 + + + + + MMS + Master mode selection + 4 + 3 + + MMS + read-write + + Reset + The UG bit from the TIMx_EGR register is used as trigger output + 0 + + + Enable + The counter enable signal, CNT_EN, is used as trigger output + 1 + + + Update + The update event is selected as trigger output + 2 + + + ComparePulse + The trigger output send a positive pulse when the CC1IF flag it to be set, as soon as a capture or a compare match occurred + 3 + + + CompareOC1 + OC1REF signal is used as trigger output + 4 + + + CompareOC2 + OC2REF signal is used as trigger output + 5 + + + CompareOC3 + OC3REF signal is used as trigger output + 6 + + + CompareOC4 + OC4REF signal is used as trigger output + 7 + + + + + CCDS + Capture/compare DMA + selection + 3 + 1 + + CCDS + read-write + + OnCompare + CCx DMA request sent when CCx event occurs + 0 + + + OnUpdate + CCx DMA request sent when update event occurs + 1 + + + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + ETP + External trigger polarity + 15 + 1 + + ETP + read-write + + NotInverted + ETR is noninverted, active at high level or rising edge + 0 + + + Inverted + ETR is inverted, active at low level or falling edge + 1 + + + + + ECE + External clock enable + 14 + 1 + + ECE + read-write + + Disabled + External clock mode 2 disabled + 0 + + + Enabled + External clock mode 2 enabled. The counter is clocked by any active edge on the ETRF signal. + 1 + + + + + ETPS + External trigger prescaler + 12 + 2 + + ETPS + read-write + + Div1 + Prescaler OFF + 0 + + + Div2 + ETRP frequency divided by 2 + 1 + + + Div4 + ETRP frequency divided by 4 + 2 + + + Div8 + ETRP frequency divided by 8 + 3 + + + + + ETF + External trigger filter + 8 + 4 + + ETF + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + MSM + Master/Slave mode + 7 + 1 + + MSM + read-write + + NoSync + No action + 0 + + + Sync + The effect of an event on the trigger input (TRGI) is delayed to allow a perfect synchronization between the current timer and its slaves (through TRGO). It is useful if we want to synchronize several timers on a single external event. + 1 + + + + + TS + Trigger selection + 4 + 3 + + TS + read-write + + ITR0 + Internal Trigger 0 (ITR0) + 0 + + + ITR1 + Internal Trigger 1 (ITR1) + 1 + + + ITR2 + Internal Trigger 2 (ITR2) + 2 + + + TI1F_ED + TI1 Edge Detector (TI1F_ED) + 4 + + + TI1FP1 + Filtered Timer Input 1 (TI1FP1) + 5 + + + TI2FP2 + Filtered Timer Input 2 (TI2FP2) + 6 + + + ETRF + External Trigger input (ETRF) + 7 + + + + + SMS + Slave mode selection + 0 + 3 + + SMS + read-write + + Disabled + Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal clock. + 0 + + + Encoder_Mode_1 + Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending on TI1FP2 level. + 1 + + + Encoder_Mode_2 + Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level. + 2 + + + Encoder_Mode_3 + Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. + 3 + + + Reset_Mode + Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and generates an update of the registers. + 4 + + + Gated_Mode + Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of the counter are controlled. + 5 + + + Trigger_Mode + Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not reset). Only the start of the counter is controlled. + 6 + + + Ext_Clock_Mode + External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter. + 7 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TDE + Trigger DMA request enable + 14 + 1 + + TDE + read-write + + Disabled + Trigger DMA request disabled + 0 + + + Enabled + Trigger DMA request enabled + 1 + + + + + CC4DE + Capture/Compare 4 DMA request + enable + 12 + 1 + + + + CC3DE + Capture/Compare 3 DMA request + enable + 11 + 1 + + + + CC2DE + Capture/Compare 2 DMA request + enable + 10 + 1 + + + + CC1DE + Capture/Compare 1 DMA request + enable + 9 + 1 + + CC1DE + read-write + + Disabled + CCx DMA request disabled + 0 + + + Enabled + CCx DMA request enabled + 1 + + + + + UDE + Update DMA request enable + 8 + 1 + + UDE + read-write + + Disabled + Update DMA request disabled + 0 + + + Enabled + Update DMA request enabled + 1 + + + + + TIE + Trigger interrupt enable + 6 + 1 + + TIE + read-write + + Disabled + Trigger interrupt disabled + 0 + + + Enabled + Trigger interrupt enabled + 1 + + + + + CC4IE + Capture/Compare 4 interrupt + enable + 4 + 1 + + + + CC3IE + Capture/Compare 3 interrupt + enable + 3 + 1 + + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + CC1IE + read-write + + Disabled + CCx interrupt disabled + 0 + + + Enabled + CCx interrupt enabled + 1 + + + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC4OF + Capture/Compare 4 overcapture + flag + 12 + 1 + zeroToClear + + read + + + write + + + + CC3OF + Capture/Compare 3 overcapture + flag + 11 + 1 + zeroToClear + + read + + + write + + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + zeroToClear + + read + + + write + + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + zeroToClear + + CC1OFR + read + + Overcapture + The counter value has been captured in TIMx_CCRx register while CCxIF flag was already set + 1 + + + + CC1OFW + write + + Clear + Clear flag + 0 + + + + + TIF + Trigger interrupt flag + 6 + 1 + zeroToClear + + TIFR + read + + NoTrigger + No trigger event occurred + 0 + + + Trigger + Trigger interrupt pending + 1 + + + + TIFW + write + + Clear + Clear flag + 0 + + + + + CC4IF + Capture/Compare 4 interrupt + flag + 4 + 1 + zeroToClear + + read + + + write + + + + CC3IF + Capture/Compare 3 interrupt + flag + 3 + 1 + zeroToClear + + read + + + write + + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + zeroToClear + + read + + + write + + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + zeroToClear + + CC1IFR + read + + Match + If CC1 is an output: The content of the counter TIMx_CNT matches the content of the TIMx_CCR1 register. If CC1 is an input: The counter value has been captured in TIMx_CCR1 register. + 1 + + + + CC1IFW + write + + Clear + Clear flag + 0 + + + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + TG + Trigger generation + 6 + 1 + + TGW + write + + Trigger + The TIF flag is set in TIMx_SR register. Related interrupt or DMA transfer can occur if enabled. + 1 + + + + + CC4G + Capture/compare 4 + generation + 4 + 1 + + + + CC3G + Capture/compare 3 + generation + 3 + 1 + + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + CC1GW + write + + Trigger + If CC1 is an output: CC1IF flag is set, Corresponding interrupt or DMA request is sent if enabled. If CC1 is an input: The current value of the counter is captured in TIMx_CCR1 register. + 1 + + + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2CE + OC2CE + 15 + 1 + + + OC2M + OC2M + 12 + 3 + + + + OC2PE + OC2PE + 11 + 1 + + OC2PE + read-write + + Disabled + Preload register on CCR2 disabled. New values written to CCR2 are taken into account immediately + 0 + + + Enabled + Preload register on CCR2 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC2FE + OC2FE + 10 + 1 + + + CC2S + CC2S + 8 + 2 + + CC2S + read-write + + Output + CC2 channel is configured as output + 0 + + + + + OC1CE + OC1CE + 7 + 1 + + + OC1M + OC1M + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + OC1PE + 3 + 1 + + OC1PE + read-write + + Disabled + Preload register on CCR1 disabled. New values written to CCR1 are taken into account immediately + 0 + + + Enabled + Preload register on CCR1 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC1FE + OC1FE + 2 + 1 + + + CC1S + CC1S + 0 + 2 + + CC1S + read-write + + Output + CC1 channel is configured as output + 0 + + + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 4 + + + 0 + 15 + + + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + TI2 + CC2 channel is configured as input, IC2 is mapped on TI2 + 1 + + + TI1 + CC2 channel is configured as input, IC2 is mapped on TI1 + 2 + + + TRC + CC2 channel is configured as input, IC2 is mapped on TRC + 3 + + + + + IC1F + Input capture 1 filter + 4 + 4 + + IC1F + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + TI1 + CC1 channel is configured as input, IC1 is mapped on TI1 + 1 + + + TI2 + CC1 channel is configured as input, IC1 is mapped on TI2 + 2 + + + TRC + CC1 channel is configured as input, IC1 is mapped on TRC + 3 + + + + + + + CCMR2_Output + CCMR2_Output + capture/compare mode register 2 (output + mode) + 0x1C + 0x20 + read-write + 0x00000000 + + + OC4CE + O24CE + 15 + 1 + + + OC4M + OC4M + 12 + 3 + + + + OC4PE + OC4PE + 11 + 1 + + OC4PE + read-write + + Disabled + Preload register on CCR4 disabled. New values written to CCR4 are taken into account immediately + 0 + + + Enabled + Preload register on CCR4 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC4FE + OC4FE + 10 + 1 + + + CC4S + CC4S + 8 + 2 + + CC4S + read-write + + Output + CC4 channel is configured as output + 0 + + + + + OC3CE + OC3CE + 7 + 1 + + + OC3M + OC3M + 4 + 3 + + OC3M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC3PE + OC3PE + 3 + 1 + + OC3PE + read-write + + Disabled + Preload register on CCR3 disabled. New values written to CCR3 are taken into account immediately + 0 + + + Enabled + Preload register on CCR3 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC3FE + OC3FE + 2 + 1 + + + CC3S + CC3S + 0 + 2 + + CC3S + read-write + + Output + CC3 channel is configured as output + 0 + + + + + + + CCMR2_Input + CCMR2_Input + capture/compare mode register 2 (input + mode) + CCMR2_Output + 0x1C + 0x20 + read-write + 0x00000000 + + + IC4F + Input capture 4 filter + 12 + 4 + + + 0 + 15 + + + + + IC4PSC + Input capture 4 prescaler + 10 + 2 + + + 0 + 3 + + + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + TI4 + CC4 channel is configured as input, IC4 is mapped on TI4 + 1 + + + TI3 + CC4 channel is configured as input, IC4 is mapped on TI3 + 2 + + + TRC + CC4 channel is configured as input, IC4 is mapped on TRC + 3 + + + + + IC3F + Input capture 3 filter + 4 + 4 + + + 0 + 15 + + + + + IC3PSC + Input capture 3 prescaler + 2 + 2 + + + 0 + 3 + + + + + CC3S + Capture/compare 3 + selection + 0 + 2 + + CC3S + read-write + + TI3 + CC3 channel is configured as input, IC3 is mapped on TI3 + 1 + + + TI4 + CC3 channel is configured as input, IC3 is mapped on TI4 + 2 + + + TRC + CC3 channel is configured as input, IC3 is mapped on TRC + 3 + + + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC4NP + Capture/Compare 4 output + Polarity + 15 + 1 + + + CC4P + Capture/Compare 3 output + Polarity + 13 + 1 + + + CC4E + Capture/Compare 4 output + enable + 12 + 1 + + + CC3NP + Capture/Compare 3 output + Polarity + 11 + 1 + + + CC3P + Capture/Compare 3 output + Polarity + 9 + 1 + + + CC3E + Capture/Compare 3 output + enable + 8 + 1 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + Counter value + 0 + 32 + + + 0 + 4294967295 + + + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 32 + + + 0 + 4294967295 + + + + + + + 4 + 0x4 + 1-4 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 32 + + + 0 + 4294967295 + + + + + + + DCR + DCR + DMA control register + 0x48 + 0x20 + read-write + 0x00000000 + + + DBL + DMA burst length + 8 + 5 + + + 0 + 18 + + + + + DBA + DMA base address + 0 + 5 + + + 0 + 31 + + + + + + + DMAR + DMAR + DMA address for full transfer + 0x4C + 0x20 + read-write + 0x00000000 + + + DMAB + DMA register for burst + accesses + 0 + 16 + + + + + OR + OR + TIM5 option register + 0x50 + 0x20 + read-write + 0x00000000 + + + IT4_RMP + Timer Input 4 remap + 6 + 2 + + + + + + + TIM9 + General purpose timers + TIM + 0x40014000 + + 0x0 + 0x400 + registers + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + MMS + Master mode selection + 4 + 3 + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + MSM + Master/Slave mode + 7 + 1 + + + TS + Trigger selection + 4 + 3 + + + SMS + Slave mode selection + 0 + 3 + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TIE + Trigger interrupt enable + 6 + 1 + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + + + TIF + Trigger interrupt flag + 6 + 1 + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + TG + Trigger generation + 6 + 1 + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2M + Output Compare 2 mode + 12 + 3 + + + + OC2PE + Output Compare 2 preload + enable + 11 + 1 + + + OC2FE + Output Compare 2 fast + enable + 10 + 1 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + + OC1M + Output Compare 1 mode + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + Output Compare 1 preload + enable + 3 + 1 + + + OC1FE + Output Compare 1 fast + enable + 2 + 1 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 3 + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + + IC1F + Input capture 1 filter + 4 + 3 + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + counter value + 0 + 16 + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + + + 2 + 0x4 + 1-2 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + + + + + USART1 + Universal synchronous asynchronous receiver + transmitter + USART + 0x40011000 + + 0x0 + 0x400 + registers + + + OTG_FS_WKUP + USB On-The-Go FS Wakeup through EXTI line + interrupt + 42 + + + OTG_FS + USB On The Go FS global + interrupt + 67 + + + USART1 + USART1 global interrupt + 37 + + + USART2 + USART2 global interrupt + 38 + + + USART6 + USART6 global interrupt + 71 + + + + SR + SR + Status register + 0x0 + 0x20 + 0x00C00000 + + + CTS + CTS flag + 9 + 1 + read-write + + + LBD + LIN break detection flag + 8 + 1 + read-write + + + TXE + Transmit data register + empty + 7 + 1 + read-only + + + TC + Transmission complete + 6 + 1 + read-write + + + RXNE + Read data register not + empty + 5 + 1 + read-write + + + IDLE + IDLE line detected + 4 + 1 + read-only + + + ORE + Overrun error + 3 + 1 + read-only + + + NF + Noise detected flag + 2 + 1 + read-only + + + FE + Framing error + 1 + 1 + read-only + + + PE + Parity error + 0 + 1 + read-only + + + + + DR + DR + Data register + 0x4 + 0x20 + read-write + 0x00000000 + + + DR + Data value + 0 + 9 + + + 0 + 511 + + + + + + + BRR + BRR + Baud rate register + 0x8 + 0x20 + read-write + 0x00000000 + + + DIV_Mantissa + mantissa of USARTDIV + 4 + 12 + + + 0 + 4095 + + + + + DIV_Fraction + fraction of USARTDIV + 0 + 4 + + + 0 + 15 + + + + + + + CR1 + CR1 + Control register 1 + 0xC + 0x20 + read-write + 0x00000000 + + + OVER8 + Oversampling mode + 15 + 1 + + OVER8 + read-write + + Oversample16 + Oversampling by 16 + 0 + + + Oversample8 + Oversampling by 8 + 1 + + + + + UE + USART enable + 13 + 1 + + UE + read-write + + Disabled + USART prescaler and outputs disabled + 0 + + + Enabled + USART enabled + 1 + + + + + M + Word length + 12 + 1 + + M + read-write + + M8 + 8 data bits + 0 + + + M9 + 9 data bits + 1 + + + + + WAKE + Wakeup method + 11 + 1 + + WAKE + read-write + + IdleLine + USART wakeup on idle line + 0 + + + AddressMark + USART wakeup on address mark + 1 + + + + + PCE + Parity control enable + 10 + 1 + + PCE + read-write + + Disabled + Parity control disabled + 0 + + + Enabled + Parity control enabled + 1 + + + + + PS + Parity selection + 9 + 1 + + PS + read-write + + Even + Even parity + 0 + + + Odd + Odd parity + 1 + + + + + PEIE + PE interrupt enable + 8 + 1 + + PEIE + read-write + + Disabled + PE interrupt disabled + 0 + + + Enabled + PE interrupt enabled + 1 + + + + + TXEIE + TXE interrupt enable + 7 + 1 + + TXEIE + read-write + + Disabled + TXE interrupt disabled + 0 + + + Enabled + TXE interrupt enabled + 1 + + + + + TCIE + Transmission complete interrupt + enable + 6 + 1 + + TCIE + read-write + + Disabled + TC interrupt disabled + 0 + + + Enabled + TC interrupt enabled + 1 + + + + + RXNEIE + RXNE interrupt enable + 5 + 1 + + RXNEIE + read-write + + Disabled + RXNE interrupt disabled + 0 + + + Enabled + RXNE interrupt enabled + 1 + + + + + IDLEIE + IDLE interrupt enable + 4 + 1 + + IDLEIE + read-write + + Disabled + IDLE interrupt disabled + 0 + + + Enabled + IDLE interrupt enabled + 1 + + + + + TE + Transmitter enable + 3 + 1 + + TE + read-write + + Disabled + Transmitter disabled + 0 + + + Enabled + Transmitter enabled + 1 + + + + + RE + Receiver enable + 2 + 1 + + RE + read-write + + Disabled + Receiver disabled + 0 + + + Enabled + Receiver enabled + 1 + + + + + RWU + Receiver wakeup + 1 + 1 + + RWU + read-write + + Active + Receiver in active mode + 0 + + + Mute + Receiver in mute mode + 1 + + + + + SBK + Send break + 0 + 1 + + SBK + read-write + + NoBreak + No break character is transmitted + 0 + + + Break + Break character transmitted + 1 + + + + + + + CR2 + CR2 + Control register 2 + 0x10 + 0x20 + read-write + 0x00000000 + + + LINEN + LIN mode enable + 14 + 1 + + LINEN + read-write + + Disabled + LIN mode disabled + 0 + + + Enabled + LIN mode enabled + 1 + + + + + STOP + STOP bits + 12 + 2 + + STOP + read-write + + Stop1 + 1 stop bit + 0 + + + Stop0p5 + 0.5 stop bits + 1 + + + Stop2 + 2 stop bits + 2 + + + Stop1p5 + 1.5 stop bits + 3 + + + + + CLKEN + Clock enable + 11 + 1 + + CLKEN + read-write + + Disabled + CK pin disabled + 0 + + + Enabled + CK pin enabled + 1 + + + + + CPOL + Clock polarity + 10 + 1 + + CPOL + read-write + + Low + Steady low value on CK pin outside transmission window + 0 + + + High + Steady high value on CK pin outside transmission window + 1 + + + + + CPHA + Clock phase + 9 + 1 + + CPHA + read-write + + First + The first clock transition is the first data capture edge + 0 + + + Second + The second clock transition is the first data capture edge + 1 + + + + + LBCL + Last bit clock pulse + 8 + 1 + + + LBDIE + LIN break detection interrupt + enable + 6 + 1 + + LBDIE + read-write + + Disabled + LIN break detection interrupt disabled + 0 + + + Enabled + LIN break detection interrupt enabled + 1 + + + + + LBDL + lin break detection length + 5 + 1 + + LBDL + read-write + + LBDL10 + 10-bit break detection + 0 + + + LBDL11 + 11-bit break detection + 1 + + + + + ADD + Address of the USART node + 0 + 4 + + + 0 + 15 + + + + + + + CR3 + CR3 + Control register 3 + 0x14 + 0x20 + read-write + 0x00000000 + + + ONEBIT + One sample bit method + enable + 11 + 1 + + ONEBIT + read-write + + Sample3 + Three sample bit method + 0 + + + Sample1 + One sample bit method + 1 + + + + + CTSIE + CTS interrupt enable + 10 + 1 + + CTSIE + read-write + + Disabled + CTS interrupt disabled + 0 + + + Enabled + CTS interrupt enabled + 1 + + + + + CTSE + CTS enable + 9 + 1 + + CTSE + read-write + + Disabled + CTS hardware flow control disabled + 0 + + + Enabled + CTS hardware flow control enabled + 1 + + + + + RTSE + RTS enable + 8 + 1 + + RTSE + read-write + + Disabled + RTS hardware flow control disabled + 0 + + + Enabled + RTS hardware flow control enabled + 1 + + + + + DMAT + DMA enable transmitter + 7 + 1 + + DMAT + read-write + + Disabled + DMA mode is disabled for transmission + 0 + + + Enabled + DMA mode is enabled for transmission + 1 + + + + + DMAR + DMA enable receiver + 6 + 1 + + DMAR + read-write + + Disabled + DMA mode is disabled for reception + 0 + + + Enabled + DMA mode is enabled for reception + 1 + + + + + SCEN + Smartcard mode enable + 5 + 1 + + SCEN + read-write + + Disabled + Smartcard mode disabled + 0 + + + Enabled + Smartcard mode enabled + 1 + + + + + NACK + Smartcard NACK enable + 4 + 1 + + NACK + read-write + + Disabled + NACK transmission in case of parity error is disabled + 0 + + + Enabled + NACK transmission during parity error is enabled + 1 + + + + + HDSEL + Half-duplex selection + 3 + 1 + + HDSEL + read-write + + FullDuplex + Half duplex mode is not selected + 0 + + + HalfDuplex + Half duplex mode is selected + 1 + + + + + IRLP + IrDA low-power + 2 + 1 + + IRLP + read-write + + Normal + Normal mode + 0 + + + LowPower + Low-power mode + 1 + + + + + IREN + IrDA mode enable + 1 + 1 + + IREN + read-write + + Disabled + IrDA disabled + 0 + + + Enabled + IrDA enabled + 1 + + + + + EIE + Error interrupt enable + 0 + 1 + + EIE + read-write + + Disabled + Error interrupt disabled + 0 + + + Enabled + Error interrupt enabled + 1 + + + + + + + GTPR + GTPR + Guard time and prescaler + register + 0x18 + 0x20 + read-write + 0x00000000 + + + GT + Guard time value + 8 + 8 + + + PSC + Prescaler value + 0 + 8 + + + + + + + USART2 + 0x40004400 + + + USART6 + 0x40011400 + + + WWDG + Window watchdog + WWDG + 0x40002C00 + + 0x0 + 0x400 + registers + + + PVD + PVD through EXTI line detection + interrupt + 1 + + + + CR + CR + Control register + 0x0 + 0x20 + read-write + 0x0000007F + + + WDGA + Activation bit + 7 + 1 + + WDGA + read-write + + Disabled + Watchdog disabled + 0 + + + Enabled + Watchdog enabled + 1 + + + + + T + 7-bit counter (MSB to LSB) + 0 + 7 + + + 0 + 127 + + + + + + + CFR + CFR + Configuration register + 0x4 + 0x20 + read-write + 0x0000007F + + + EWI + Early wakeup interrupt + 9 + 1 + + EWIW + write + + Enable + interrupt occurs whenever the counter reaches the value 0x40 + 1 + + + + + W + 7-bit window value + 0 + 7 + + + 0 + 127 + + + + + WDGTB + Timer base + 7 + 2 + + WDGTB + read-write + + Div1 + Counter clock (PCLK1 div 4096) div 1 + 0 + + + Div2 + Counter clock (PCLK1 div 4096) div 2 + 1 + + + Div4 + Counter clock (PCLK1 div 4096) div 4 + 2 + + + Div8 + Counter clock (PCLK1 div 4096) div 8 + 3 + + + + + + + SR + SR + Status register + 0x8 + 0x20 + read-write + 0x00000000 + + + EWIF + Early wakeup interrupt + flag + 0 + 1 + zeroToClear + + EWIFR + read + + Finished + The EWI Interrupt Service Routine has been serviced + 0 + + + Pending + The EWI Interrupt Service Routine has been triggered + 1 + + + + EWIFW + write + + Finished + The EWI Interrupt Service Routine has been serviced + 0 + + + + + + + + + DMA2 + DMA controller + DMA + 0x40026400 + + 0x0 + 0x400 + registers + + + RCC + RCC global interrupt + 5 + + + DMA1_STREAM0 + DMA1_STREAM0 global interrupt + 11 + + + DMA1_STREAM1 + DMA1_STREAM1 global interrupt + 12 + + + DMA1_STREAM2 + DMA1_STREAM2 global interrupt + 13 + + + DMA1_STREAM3 + DMA1_STREAM3 global interrupt + 14 + + + DMA1_STREAM4 + DMA1_STREAM4 global interrupt + 15 + + + DMA1_STREAM5 + DMA1_STREAM5 global interrupt + 16 + + + DMA1_STREAM6 + DMA1_STREAM6 global interrupt + 17 + + + DMA1_STREAM7 + DMA1_STREAM7 global interrupt + 47 + + + DMA2_STREAM0 + DMA2_STREAM0 global interrupt + 56 + + + DMA2_STREAM1 + DMA2_STREAM1 global interrupt + 57 + + + DMA2_STREAM2 + DMA2_STREAM2 global interrupt + 58 + + + DMA2_STREAM3 + DMA2_STREAM3 global interrupt + 59 + + + DMA2_STREAM4 + DMA2_STREAM4 global interrupt + 60 + + + DMA2_STREAM5 + DMA2_STREAM5 global interrupt + 68 + + + DMA2_STREAM6 + DMA2_STREAM6 global interrupt + 69 + + + DMA2_STREAM7 + DMA2_STREAM7 global interrupt + 70 + + + + LISR + LISR + low interrupt status register + 0x0 + 0x20 + read-only + 0x00000000 + + + TCIF3 + Stream x transfer complete interrupt + flag (x = 3..0) + 27 + 1 + + + + HTIF3 + Stream x half transfer interrupt flag + (x=3..0) + 26 + 1 + + + + TEIF3 + Stream x transfer error interrupt flag + (x=3..0) + 25 + 1 + + + + DMEIF3 + Stream x direct mode error interrupt + flag (x=3..0) + 24 + 1 + + + + FEIF3 + Stream x FIFO error interrupt flag + (x=3..0) + 22 + 1 + + + + TCIF2 + Stream x transfer complete interrupt + flag (x = 3..0) + 21 + 1 + + + + HTIF2 + Stream x half transfer interrupt flag + (x=3..0) + 20 + 1 + + + + TEIF2 + Stream x transfer error interrupt flag + (x=3..0) + 19 + 1 + + + + DMEIF2 + Stream x direct mode error interrupt + flag (x=3..0) + 18 + 1 + + + + FEIF2 + Stream x FIFO error interrupt flag + (x=3..0) + 16 + 1 + + + + TCIF1 + Stream x transfer complete interrupt + flag (x = 3..0) + 11 + 1 + + + + HTIF1 + Stream x half transfer interrupt flag + (x=3..0) + 10 + 1 + + + + TEIF1 + Stream x transfer error interrupt flag + (x=3..0) + 9 + 1 + + + + DMEIF1 + Stream x direct mode error interrupt + flag (x=3..0) + 8 + 1 + + + + FEIF1 + Stream x FIFO error interrupt flag + (x=3..0) + 6 + 1 + + + + TCIF0 + Stream x transfer complete interrupt + flag (x = 3..0) + 5 + 1 + + TCIF0 + read + + NotComplete + No transfer complete event on stream x + 0 + + + Complete + A transfer complete event occurred on stream x + 1 + + + + + HTIF0 + Stream x half transfer interrupt flag + (x=3..0) + 4 + 1 + + HTIF0 + read + + NotHalf + No half transfer event on stream x + 0 + + + Half + A half transfer event occurred on stream x + 1 + + + + + TEIF0 + Stream x transfer error interrupt flag + (x=3..0) + 3 + 1 + + TEIF0 + read + + NoError + No transfer error on stream x + 0 + + + Error + A transfer error occurred on stream x + 1 + + + + + DMEIF0 + Stream x direct mode error interrupt + flag (x=3..0) + 2 + 1 + + DMEIF0 + read + + NoError + No Direct Mode error on stream x + 0 + + + Error + A Direct Mode error occurred on stream x + 1 + + + + + FEIF0 + Stream x FIFO error interrupt flag + (x=3..0) + 0 + 1 + + FEIF0 + read + + NoError + No FIFO error event on stream x + 0 + + + Error + A FIFO error event occurred on stream x + 1 + + + + + + + HISR + HISR + high interrupt status register + 0x4 + 0x20 + read-only + 0x00000000 + + + TCIF7 + Stream x transfer complete interrupt + flag (x=7..4) + 27 + 1 + + + + HTIF7 + Stream x half transfer interrupt flag + (x=7..4) + 26 + 1 + + + + TEIF7 + Stream x transfer error interrupt flag + (x=7..4) + 25 + 1 + + + + DMEIF7 + Stream x direct mode error interrupt + flag (x=7..4) + 24 + 1 + + + + FEIF7 + Stream x FIFO error interrupt flag + (x=7..4) + 22 + 1 + + + + TCIF6 + Stream x transfer complete interrupt + flag (x=7..4) + 21 + 1 + + + + HTIF6 + Stream x half transfer interrupt flag + (x=7..4) + 20 + 1 + + + + TEIF6 + Stream x transfer error interrupt flag + (x=7..4) + 19 + 1 + + + + DMEIF6 + Stream x direct mode error interrupt + flag (x=7..4) + 18 + 1 + + + + FEIF6 + Stream x FIFO error interrupt flag + (x=7..4) + 16 + 1 + + + + TCIF5 + Stream x transfer complete interrupt + flag (x=7..4) + 11 + 1 + + + + HTIF5 + Stream x half transfer interrupt flag + (x=7..4) + 10 + 1 + + + + TEIF5 + Stream x transfer error interrupt flag + (x=7..4) + 9 + 1 + + + + DMEIF5 + Stream x direct mode error interrupt + flag (x=7..4) + 8 + 1 + + + + FEIF5 + Stream x FIFO error interrupt flag + (x=7..4) + 6 + 1 + + + + TCIF4 + Stream x transfer complete interrupt + flag (x=7..4) + 5 + 1 + + TCIF4 + read + + NotComplete + No transfer complete event on stream x + 0 + + + Complete + A transfer complete event occurred on stream x + 1 + + + + + HTIF4 + Stream x half transfer interrupt flag + (x=7..4) + 4 + 1 + + HTIF4 + read + + NotHalf + No half transfer event on stream x + 0 + + + Half + A half transfer event occurred on stream x + 1 + + + + + TEIF4 + Stream x transfer error interrupt flag + (x=7..4) + 3 + 1 + + TEIF4 + read + + NoError + No transfer error on stream x + 0 + + + Error + A transfer error occurred on stream x + 1 + + + + + DMEIF4 + Stream x direct mode error interrupt + flag (x=7..4) + 2 + 1 + + DMEIF4 + read + + NoError + No Direct Mode error on stream x + 0 + + + Error + A Direct Mode error occurred on stream x + 1 + + + + + FEIF4 + Stream x FIFO error interrupt flag + (x=7..4) + 0 + 1 + + FEIF4 + read + + NoError + No FIFO error event on stream x + 0 + + + Error + A FIFO error event occurred on stream x + 1 + + + + + + + LIFCR + LIFCR + low interrupt flag clear + register + 0x8 + 0x20 + write-only + 0x00000000 + + + CTCIF3 + Stream x clear transfer complete + interrupt flag (x = 3..0) + 27 + 1 + + + + CHTIF3 + Stream x clear half transfer interrupt + flag (x = 3..0) + 26 + 1 + + + + CTEIF3 + Stream x clear transfer error interrupt + flag (x = 3..0) + 25 + 1 + + + + CDMEIF3 + Stream x clear direct mode error + interrupt flag (x = 3..0) + 24 + 1 + + + + CFEIF3 + Stream x clear FIFO error interrupt flag + (x = 3..0) + 22 + 1 + + + + CTCIF2 + Stream x clear transfer complete + interrupt flag (x = 3..0) + 21 + 1 + + + + CHTIF2 + Stream x clear half transfer interrupt + flag (x = 3..0) + 20 + 1 + + + + CTEIF2 + Stream x clear transfer error interrupt + flag (x = 3..0) + 19 + 1 + + + + CDMEIF2 + Stream x clear direct mode error + interrupt flag (x = 3..0) + 18 + 1 + + + + CFEIF2 + Stream x clear FIFO error interrupt flag + (x = 3..0) + 16 + 1 + + + + CTCIF1 + Stream x clear transfer complete + interrupt flag (x = 3..0) + 11 + 1 + + + + CHTIF1 + Stream x clear half transfer interrupt + flag (x = 3..0) + 10 + 1 + + + + CTEIF1 + Stream x clear transfer error interrupt + flag (x = 3..0) + 9 + 1 + + + + CDMEIF1 + Stream x clear direct mode error + interrupt flag (x = 3..0) + 8 + 1 + + + + CFEIF1 + Stream x clear FIFO error interrupt flag + (x = 3..0) + 6 + 1 + + + + CTCIF0 + Stream x clear transfer complete + interrupt flag (x = 3..0) + 5 + 1 + + CTCIF0 + write + + Clear + Clear the corresponding TCIFx flag + 1 + + + + + CHTIF0 + Stream x clear half transfer interrupt + flag (x = 3..0) + 4 + 1 + + CHTIF0 + write + + Clear + Clear the corresponding HTIFx flag + 1 + + + + + CTEIF0 + Stream x clear transfer error interrupt + flag (x = 3..0) + 3 + 1 + + CTEIF0 + write + + Clear + Clear the corresponding TEIFx flag + 1 + + + + + CDMEIF0 + Stream x clear direct mode error + interrupt flag (x = 3..0) + 2 + 1 + + CDMEIF0 + write + + Clear + Clear the corresponding DMEIFx flag + 1 + + + + + CFEIF0 + Stream x clear FIFO error interrupt flag + (x = 3..0) + 0 + 1 + + CFEIF0 + write + + Clear + Clear the corresponding CFEIFx flag + 1 + + + + + + + HIFCR + HIFCR + high interrupt flag clear + register + 0xC + 0x20 + write-only + 0x00000000 + + + CTCIF7 + Stream x clear transfer complete + interrupt flag (x = 7..4) + 27 + 1 + + + + CHTIF7 + Stream x clear half transfer interrupt + flag (x = 7..4) + 26 + 1 + + + + CTEIF7 + Stream x clear transfer error interrupt + flag (x = 7..4) + 25 + 1 + + + + CDMEIF7 + Stream x clear direct mode error + interrupt flag (x = 7..4) + 24 + 1 + + + + CFEIF7 + Stream x clear FIFO error interrupt flag + (x = 7..4) + 22 + 1 + + + + CTCIF6 + Stream x clear transfer complete + interrupt flag (x = 7..4) + 21 + 1 + + + + CHTIF6 + Stream x clear half transfer interrupt + flag (x = 7..4) + 20 + 1 + + + + CTEIF6 + Stream x clear transfer error interrupt + flag (x = 7..4) + 19 + 1 + + + + CDMEIF6 + Stream x clear direct mode error + interrupt flag (x = 7..4) + 18 + 1 + + + + CFEIF6 + Stream x clear FIFO error interrupt flag + (x = 7..4) + 16 + 1 + + + + CTCIF5 + Stream x clear transfer complete + interrupt flag (x = 7..4) + 11 + 1 + + + + CHTIF5 + Stream x clear half transfer interrupt + flag (x = 7..4) + 10 + 1 + + + + CTEIF5 + Stream x clear transfer error interrupt + flag (x = 7..4) + 9 + 1 + + + + CDMEIF5 + Stream x clear direct mode error + interrupt flag (x = 7..4) + 8 + 1 + + + + CFEIF5 + Stream x clear FIFO error interrupt flag + (x = 7..4) + 6 + 1 + + + + CTCIF4 + Stream x clear transfer complete + interrupt flag (x = 7..4) + 5 + 1 + + CTCIF4 + write + + Clear + Clear the corresponding TCIFx flag + 1 + + + + + CHTIF4 + Stream x clear half transfer interrupt + flag (x = 7..4) + 4 + 1 + + CHTIF4 + write + + Clear + Clear the corresponding HTIFx flag + 1 + + + + + CTEIF4 + Stream x clear transfer error interrupt + flag (x = 7..4) + 3 + 1 + + CTEIF4 + write + + Clear + Clear the corresponding TEIFx flag + 1 + + + + + CDMEIF4 + Stream x clear direct mode error + interrupt flag (x = 7..4) + 2 + 1 + + CDMEIF4 + write + + Clear + Clear the corresponding DMEIFx flag + 1 + + + + + CFEIF4 + Stream x clear FIFO error interrupt flag + (x = 7..4) + 0 + 1 + + CFEIF4 + write + + Clear + Clear the corresponding CFEIFx flag + 1 + + + + + + + 8 + 0x18 + 0-7 + ST%s + Stream cluster: S?CR, S?NDTR, S?M0AR, S?M1AR and S?FCR registers + 0x10 + + CR + S0CR + stream x configuration + register + 0x0 + 0x20 + read-write + 0x00000000 + + + CHSEL + Channel selection + 25 + 3 + + + 0 + 7 + + + + + MBURST + Memory burst transfer + configuration + 23 + 2 + + + + PBURST + Peripheral burst transfer + configuration + 21 + 2 + + PBURST + read-write + + Single + Single transfer + 0 + + + INCR4 + Incremental burst of 4 beats + 1 + + + INCR8 + Incremental burst of 8 beats + 2 + + + INCR16 + Incremental burst of 16 beats + 3 + + + + + CT + Current target (only in double buffer + mode) + 19 + 1 + + CT + read-write + + Memory0 + The current target memory is Memory 0 + 0 + + + Memory1 + The current target memory is Memory 1 + 1 + + + + + DBM + Double buffer mode + 18 + 1 + + DBM + read-write + + Disabled + No buffer switching at the end of transfer + 0 + + + Enabled + Memory target switched at the end of the DMA transfer + 1 + + + + + PL + Priority level + 16 + 2 + + PL + read-write + + Low + Low + 0 + + + Medium + Medium + 1 + + + High + High + 2 + + + VeryHigh + Very high + 3 + + + + + PINCOS + Peripheral increment offset + size + 15 + 1 + + PINCOS + read-write + + PSIZE + The offset size for the peripheral address calculation is linked to the PSIZE + 0 + + + Fixed4 + The offset size for the peripheral address calculation is fixed to 4 (32-bit alignment) + 1 + + + + + MSIZE + Memory data size + 13 + 2 + + + + PSIZE + Peripheral data size + 11 + 2 + + PSIZE + read-write + + Bits8 + Byte (8-bit) + 0 + + + Bits16 + Half-word (16-bit) + 1 + + + Bits32 + Word (32-bit) + 2 + + + + + MINC + Memory increment mode + 10 + 1 + + + + PINC + Peripheral increment mode + 9 + 1 + + PINC + read-write + + Fixed + Address pointer is fixed + 0 + + + Incremented + Address pointer is incremented after each data transfer + 1 + + + + + CIRC + Circular mode + 8 + 1 + + CIRC + read-write + + Disabled + Circular mode disabled + 0 + + + Enabled + Circular mode enabled + 1 + + + + + DIR + Data transfer direction + 6 + 2 + + DIR + read-write + + PeripheralToMemory + Peripheral-to-memory + 0 + + + MemoryToPeripheral + Memory-to-peripheral + 1 + + + MemoryToMemory + Memory-to-memory + 2 + + + + + PFCTRL + Peripheral flow controller + 5 + 1 + + PFCTRL + read-write + + DMA + The DMA is the flow controller + 0 + + + Peripheral + The peripheral is the flow controller + 1 + + + + + TCIE + Transfer complete interrupt + enable + 4 + 1 + + TCIE + read-write + + Disabled + TC interrupt disabled + 0 + + + Enabled + TC interrupt enabled + 1 + + + + + HTIE + Half transfer interrupt + enable + 3 + 1 + + HTIE + read-write + + Disabled + HT interrupt disabled + 0 + + + Enabled + HT interrupt enabled + 1 + + + + + TEIE + Transfer error interrupt + enable + 2 + 1 + + TEIE + read-write + + Disabled + TE interrupt disabled + 0 + + + Enabled + TE interrupt enabled + 1 + + + + + DMEIE + Direct mode error interrupt + enable + 1 + 1 + + DMEIE + read-write + + Disabled + DME interrupt disabled + 0 + + + Enabled + DME interrupt enabled + 1 + + + + + EN + Stream enable / flag stream ready when + read low + 0 + 1 + + EN + read-write + + Disabled + Stream disabled + 0 + + + Enabled + Stream enabled + 1 + + + + + + + NDTR + S0NDTR + stream x number of data + register + 0x4 + 0x20 + read-write + 0x00000000 + + + NDT + Number of data items to + transfer + 0 + 16 + + + 0 + 65535 + + + + + + + PAR + S0PAR + stream x peripheral address + register + 0x8 + 0x20 + read-write + 0x00000000 + + + PA + Peripheral address + 0 + 32 + + + + + M0AR + S0M0AR + stream x memory 0 address + register + 0xC + 0x20 + read-write + 0x00000000 + + + M0A + Memory 0 address + 0 + 32 + + + + + M1AR + S0M1AR + stream x memory 1 address + register + 0x10 + 0x20 + read-write + 0x00000000 + + + M1A + Memory 1 address (used in case of Double + buffer mode) + 0 + 32 + + + + + FCR + S0FCR + stream x FIFO control register + 0x14 + 0x20 + 0x00000021 + + + FEIE + FIFO error interrupt + enable + 7 + 1 + read-write + + FEIE + read-write + + Disabled + FE interrupt disabled + 0 + + + Enabled + FE interrupt enabled + 1 + + + + + FS + FIFO status + 3 + 3 + read-only + + FS + read + + Quarter1 + 0 < fifo_level < 1/4 + 0 + + + Quarter2 + 1/4 <= fifo_level < 1/2 + 1 + + + Quarter3 + 1/2 <= fifo_level < 3/4 + 2 + + + Quarter4 + 3/4 <= fifo_level < full + 3 + + + Empty + FIFO is empty + 4 + + + Full + FIFO is full + 5 + + + + + DMDIS + Direct mode disable + 2 + 1 + read-write + + DMDIS + read-write + + Enabled + Direct mode is enabled + 0 + + + Disabled + Direct mode is disabled + 1 + + + + + FTH + FIFO threshold selection + 0 + 2 + read-write + + FTH + read-write + + Quarter + 1/4 full FIFO + 0 + + + Half + 1/2 full FIFO + 1 + + + ThreeQuarters + 3/4 full FIFO + 2 + + + Full + Full FIFO + 3 + + + + + + + + + + DMA1 + 0x40026000 + + RTC_WKUP + RTC Wakeup interrupt through the EXTI + line + 3 + + + RTC_Alarm + RTC Alarms (A and B) through EXTI line + interrupt + 41 + + + + GPIOH + General-purpose I/Os + GPIO + 0x40021C00 + + 0x0 + 0x400 + registers + + + SDIO + SDIO global interrupt + 49 + + + + MODER + MODER + GPIO port mode register + 0x0 + 0x20 + read-write + 0x00000000 + + + MODER15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + MODER14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + MODER13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + MODER12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + MODER11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + MODER10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + MODER9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + MODER8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + MODER7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + MODER6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + MODER5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + MODER4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + MODER3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + MODER2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + MODER1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + MODER0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + MODER0 + read-write + + Input + Input mode (reset state) + 0 + + + Output + General purpose output mode + 1 + + + Alternate + Alternate function mode + 2 + + + Analog + Analog mode + 3 + + + + + + + OTYPER + OTYPER + GPIO port output type register + 0x4 + 0x20 + read-write + 0x00000000 + + + OT15 + Port x configuration bits (y = + 0..15) + 15 + 1 + + + + OT14 + Port x configuration bits (y = + 0..15) + 14 + 1 + + + + OT13 + Port x configuration bits (y = + 0..15) + 13 + 1 + + + + OT12 + Port x configuration bits (y = + 0..15) + 12 + 1 + + + + OT11 + Port x configuration bits (y = + 0..15) + 11 + 1 + + + + OT10 + Port x configuration bits (y = + 0..15) + 10 + 1 + + + + OT9 + Port x configuration bits (y = + 0..15) + 9 + 1 + + + + OT8 + Port x configuration bits (y = + 0..15) + 8 + 1 + + + + OT7 + Port x configuration bits (y = + 0..15) + 7 + 1 + + + + OT6 + Port x configuration bits (y = + 0..15) + 6 + 1 + + + + OT5 + Port x configuration bits (y = + 0..15) + 5 + 1 + + + + OT4 + Port x configuration bits (y = + 0..15) + 4 + 1 + + + + OT3 + Port x configuration bits (y = + 0..15) + 3 + 1 + + + + OT2 + Port x configuration bits (y = + 0..15) + 2 + 1 + + + + OT1 + Port x configuration bits (y = + 0..15) + 1 + 1 + + + + OT0 + Port x configuration bits (y = + 0..15) + 0 + 1 + + OT0 + read-write + + PushPull + Output push-pull (reset state) + 0 + + + OpenDrain + Output open-drain + 1 + + + + + + + OSPEEDR + OSPEEDR + GPIO port output speed + register + 0x8 + 0x20 + read-write + 0x00000000 + + + OSPEEDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + OSPEEDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + OSPEEDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + OSPEEDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + OSPEEDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + OSPEEDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + OSPEEDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + OSPEEDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + OSPEEDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + OSPEEDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + OSPEEDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + OSPEEDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + OSPEEDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + OSPEEDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + OSPEEDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + OSPEEDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + OSPEEDR0 + read-write + + LowSpeed + Low speed + 0 + + + MediumSpeed + Medium speed + 1 + + + HighSpeed + High speed + 2 + + + VeryHighSpeed + Very high speed + 3 + + + + + + + PUPDR + PUPDR + GPIO port pull-up/pull-down + register + 0xC + 0x20 + read-write + 0x00000000 + + + PUPDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + PUPDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + PUPDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + PUPDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + PUPDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + PUPDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + PUPDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + PUPDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + PUPDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + PUPDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + PUPDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + PUPDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + PUPDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + PUPDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + PUPDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + PUPDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + PUPDR0 + read-write + + Floating + No pull-up, pull-down + 0 + + + PullUp + Pull-up + 1 + + + PullDown + Pull-down + 2 + + + + + + + IDR + IDR + GPIO port input data register + 0x10 + 0x20 + read-only + 0x00000000 + + + IDR15 + Port input data (y = + 0..15) + 15 + 1 + + + + IDR14 + Port input data (y = + 0..15) + 14 + 1 + + + + IDR13 + Port input data (y = + 0..15) + 13 + 1 + + + + IDR12 + Port input data (y = + 0..15) + 12 + 1 + + + + IDR11 + Port input data (y = + 0..15) + 11 + 1 + + + + IDR10 + Port input data (y = + 0..15) + 10 + 1 + + + + IDR9 + Port input data (y = + 0..15) + 9 + 1 + + + + IDR8 + Port input data (y = + 0..15) + 8 + 1 + + + + IDR7 + Port input data (y = + 0..15) + 7 + 1 + + + + IDR6 + Port input data (y = + 0..15) + 6 + 1 + + + + IDR5 + Port input data (y = + 0..15) + 5 + 1 + + + + IDR4 + Port input data (y = + 0..15) + 4 + 1 + + + + IDR3 + Port input data (y = + 0..15) + 3 + 1 + + + + IDR2 + Port input data (y = + 0..15) + 2 + 1 + + + + IDR1 + Port input data (y = + 0..15) + 1 + 1 + + + + IDR0 + Port input data (y = + 0..15) + 0 + 1 + + IDR0 + read + + Low + Input is logic low + 0 + + + High + Input is logic high + 1 + + + + + + + ODR + ODR + GPIO port output data register + 0x14 + 0x20 + read-write + 0x00000000 + + + ODR15 + Port output data (y = + 0..15) + 15 + 1 + + + + ODR14 + Port output data (y = + 0..15) + 14 + 1 + + + + ODR13 + Port output data (y = + 0..15) + 13 + 1 + + + + ODR12 + Port output data (y = + 0..15) + 12 + 1 + + + + ODR11 + Port output data (y = + 0..15) + 11 + 1 + + + + ODR10 + Port output data (y = + 0..15) + 10 + 1 + + + + ODR9 + Port output data (y = + 0..15) + 9 + 1 + + + + ODR8 + Port output data (y = + 0..15) + 8 + 1 + + + + ODR7 + Port output data (y = + 0..15) + 7 + 1 + + + + ODR6 + Port output data (y = + 0..15) + 6 + 1 + + + + ODR5 + Port output data (y = + 0..15) + 5 + 1 + + + + ODR4 + Port output data (y = + 0..15) + 4 + 1 + + + + ODR3 + Port output data (y = + 0..15) + 3 + 1 + + + + ODR2 + Port output data (y = + 0..15) + 2 + 1 + + + + ODR1 + Port output data (y = + 0..15) + 1 + 1 + + + + ODR0 + Port output data (y = + 0..15) + 0 + 1 + + ODR0 + read-write + + Low + Set output to logic low + 0 + + + High + Set output to logic high + 1 + + + + + + + BSRR + BSRR + GPIO port bit set/reset + register + 0x18 + 0x20 + write-only + 0x00000000 + + + BR15 + Port x reset bit y (y = + 0..15) + 31 + 1 + + + + BR14 + Port x reset bit y (y = + 0..15) + 30 + 1 + + + + BR13 + Port x reset bit y (y = + 0..15) + 29 + 1 + + + + BR12 + Port x reset bit y (y = + 0..15) + 28 + 1 + + + + BR11 + Port x reset bit y (y = + 0..15) + 27 + 1 + + + + BR10 + Port x reset bit y (y = + 0..15) + 26 + 1 + + + + BR9 + Port x reset bit y (y = + 0..15) + 25 + 1 + + + + BR8 + Port x reset bit y (y = + 0..15) + 24 + 1 + + + + BR7 + Port x reset bit y (y = + 0..15) + 23 + 1 + + + + BR6 + Port x reset bit y (y = + 0..15) + 22 + 1 + + + + BR5 + Port x reset bit y (y = + 0..15) + 21 + 1 + + + + BR4 + Port x reset bit y (y = + 0..15) + 20 + 1 + + + + BR3 + Port x reset bit y (y = + 0..15) + 19 + 1 + + + + BR2 + Port x reset bit y (y = + 0..15) + 18 + 1 + + + + BR1 + Port x reset bit y (y = + 0..15) + 17 + 1 + + + + BR0 + Port x set bit y (y= + 0..15) + 16 + 1 + + BR0W + write + + Reset + Resets the corresponding ODRx bit + 1 + + + + + BS15 + Port x set bit y (y= + 0..15) + 15 + 1 + + + + BS14 + Port x set bit y (y= + 0..15) + 14 + 1 + + + + BS13 + Port x set bit y (y= + 0..15) + 13 + 1 + + + + BS12 + Port x set bit y (y= + 0..15) + 12 + 1 + + + + BS11 + Port x set bit y (y= + 0..15) + 11 + 1 + + + + BS10 + Port x set bit y (y= + 0..15) + 10 + 1 + + + + BS9 + Port x set bit y (y= + 0..15) + 9 + 1 + + + + BS8 + Port x set bit y (y= + 0..15) + 8 + 1 + + + + BS7 + Port x set bit y (y= + 0..15) + 7 + 1 + + + + BS6 + Port x set bit y (y= + 0..15) + 6 + 1 + + + + BS5 + Port x set bit y (y= + 0..15) + 5 + 1 + + + + BS4 + Port x set bit y (y= + 0..15) + 4 + 1 + + + + BS3 + Port x set bit y (y= + 0..15) + 3 + 1 + + + + BS2 + Port x set bit y (y= + 0..15) + 2 + 1 + + + + BS1 + Port x set bit y (y= + 0..15) + 1 + 1 + + + + BS0 + Port x set bit y (y= + 0..15) + 0 + 1 + + BS0W + write + + Set + Sets the corresponding ODRx bit + 1 + + + + + + + LCKR + LCKR + GPIO port configuration lock + register + 0x1C + 0x20 + read-write + 0x00000000 + + + LCKK + Port x lock bit y (y= + 0..15) + 16 + 1 + + LCKK + read-write + + NotActive + Port configuration lock key not active + 0 + + + Active + Port configuration lock key active + 1 + + + + + LCK15 + Port x lock bit y (y= + 0..15) + 15 + 1 + + + + LCK14 + Port x lock bit y (y= + 0..15) + 14 + 1 + + + + LCK13 + Port x lock bit y (y= + 0..15) + 13 + 1 + + + + LCK12 + Port x lock bit y (y= + 0..15) + 12 + 1 + + + + LCK11 + Port x lock bit y (y= + 0..15) + 11 + 1 + + + + LCK10 + Port x lock bit y (y= + 0..15) + 10 + 1 + + + + LCK9 + Port x lock bit y (y= + 0..15) + 9 + 1 + + + + LCK8 + Port x lock bit y (y= + 0..15) + 8 + 1 + + + + LCK7 + Port x lock bit y (y= + 0..15) + 7 + 1 + + + + LCK6 + Port x lock bit y (y= + 0..15) + 6 + 1 + + + + LCK5 + Port x lock bit y (y= + 0..15) + 5 + 1 + + + + LCK4 + Port x lock bit y (y= + 0..15) + 4 + 1 + + + + LCK3 + Port x lock bit y (y= + 0..15) + 3 + 1 + + + + LCK2 + Port x lock bit y (y= + 0..15) + 2 + 1 + + + + LCK1 + Port x lock bit y (y= + 0..15) + 1 + 1 + + + + LCK0 + Port x lock bit y (y= + 0..15) + 0 + 1 + + LCK0 + read-write + + Unlocked + Port configuration not locked + 0 + + + Locked + Port configuration locked + 1 + + + + + + + AFRL + AFRL + GPIO alternate function low + register + 0x20 + 0x20 + read-write + 0x00000000 + + + AFRL7 + Alternate function selection for port x + bit y (y = 0..7) + 28 + 4 + + + + AFRL6 + Alternate function selection for port x + bit y (y = 0..7) + 24 + 4 + + + + AFRL5 + Alternate function selection for port x + bit y (y = 0..7) + 20 + 4 + + + + AFRL4 + Alternate function selection for port x + bit y (y = 0..7) + 16 + 4 + + + + AFRL3 + Alternate function selection for port x + bit y (y = 0..7) + 12 + 4 + + + + AFRL2 + Alternate function selection for port x + bit y (y = 0..7) + 8 + 4 + + + + AFRL1 + Alternate function selection for port x + bit y (y = 0..7) + 4 + 4 + + + + AFRL0 + Alternate function selection for port x + bit y (y = 0..7) + 0 + 4 + + AFRL0 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + AFRH + AFRH + GPIO alternate function high + register + 0x24 + 0x20 + read-write + 0x00000000 + + + AFRH15 + Alternate function selection for port x + bit y (y = 8..15) + 28 + 4 + + + + AFRH14 + Alternate function selection for port x + bit y (y = 8..15) + 24 + 4 + + + + AFRH13 + Alternate function selection for port x + bit y (y = 8..15) + 20 + 4 + + + + AFRH12 + Alternate function selection for port x + bit y (y = 8..15) + 16 + 4 + + + + AFRH11 + Alternate function selection for port x + bit y (y = 8..15) + 12 + 4 + + + + AFRH10 + Alternate function selection for port x + bit y (y = 8..15) + 8 + 4 + + + + AFRH9 + Alternate function selection for port x + bit y (y = 8..15) + 4 + 4 + + + + AFRH8 + Alternate function selection for port x + bit y (y = 8..15) + 0 + 4 + + AFRH8 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + + + GPIOE + 0x40021000 + + + GPIOD + 0x40020C00 + + TIM1_BRK_TIM9 + TIM1 Break interrupt and TIM9 global + interrupt + 24 + + + TIM1_UP_TIM10 + TIM1 Update interrupt and TIM10 global + interrupt + 25 + + + TIM1_TRG_COM_TIM11 + TIM1 Trigger and Commutation interrupts and + TIM11 global interrupt + 26 + + + TIM1_CC + TIM1 Capture Compare interrupt + 27 + + + + GPIOC + 0x40020800 + + TIM1_UP_TIM10 + TIM1 Update interrupt and TIM10 global + interrupt + 25 + + + + GPIOB + General-purpose I/Os + GPIO + 0x40020400 + + 0x0 + 0x400 + registers + + + TIM1_TRG_COM_TIM11 + TIM1 Trigger and Commutation interrupts and + TIM11 global interrupt + 26 + + + + MODER + MODER + GPIO port mode register + 0x0 + 0x20 + read-write + 0x00000280 + + + MODER15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + MODER14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + MODER13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + MODER12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + MODER11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + MODER10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + MODER9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + MODER8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + MODER7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + MODER6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + MODER5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + MODER4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + MODER3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + MODER2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + MODER1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + MODER0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + MODER0 + read-write + + Input + Input mode (reset state) + 0 + + + Output + General purpose output mode + 1 + + + Alternate + Alternate function mode + 2 + + + Analog + Analog mode + 3 + + + + + + + OTYPER + OTYPER + GPIO port output type register + 0x4 + 0x20 + read-write + 0x00000000 + + + OT15 + Port x configuration bits (y = + 0..15) + 15 + 1 + + + + OT14 + Port x configuration bits (y = + 0..15) + 14 + 1 + + + + OT13 + Port x configuration bits (y = + 0..15) + 13 + 1 + + + + OT12 + Port x configuration bits (y = + 0..15) + 12 + 1 + + + + OT11 + Port x configuration bits (y = + 0..15) + 11 + 1 + + + + OT10 + Port x configuration bits (y = + 0..15) + 10 + 1 + + + + OT9 + Port x configuration bits (y = + 0..15) + 9 + 1 + + + + OT8 + Port x configuration bits (y = + 0..15) + 8 + 1 + + + + OT7 + Port x configuration bits (y = + 0..15) + 7 + 1 + + + + OT6 + Port x configuration bits (y = + 0..15) + 6 + 1 + + + + OT5 + Port x configuration bits (y = + 0..15) + 5 + 1 + + + + OT4 + Port x configuration bits (y = + 0..15) + 4 + 1 + + + + OT3 + Port x configuration bits (y = + 0..15) + 3 + 1 + + + + OT2 + Port x configuration bits (y = + 0..15) + 2 + 1 + + + + OT1 + Port x configuration bits (y = + 0..15) + 1 + 1 + + + + OT0 + Port x configuration bits (y = + 0..15) + 0 + 1 + + OT0 + read-write + + PushPull + Output push-pull (reset state) + 0 + + + OpenDrain + Output open-drain + 1 + + + + + + + OSPEEDR + OSPEEDR + GPIO port output speed + register + 0x8 + 0x20 + read-write + 0x000000C0 + + + OSPEEDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + OSPEEDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + OSPEEDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + OSPEEDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + OSPEEDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + OSPEEDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + OSPEEDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + OSPEEDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + OSPEEDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + OSPEEDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + OSPEEDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + OSPEEDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + OSPEEDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + OSPEEDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + OSPEEDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + OSPEEDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + OSPEEDR0 + read-write + + LowSpeed + Low speed + 0 + + + MediumSpeed + Medium speed + 1 + + + HighSpeed + High speed + 2 + + + VeryHighSpeed + Very high speed + 3 + + + + + + + PUPDR + PUPDR + GPIO port pull-up/pull-down + register + 0xC + 0x20 + read-write + 0x00000100 + + + PUPDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + PUPDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + PUPDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + PUPDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + PUPDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + PUPDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + PUPDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + PUPDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + PUPDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + PUPDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + PUPDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + PUPDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + PUPDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + PUPDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + PUPDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + PUPDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + PUPDR0 + read-write + + Floating + No pull-up, pull-down + 0 + + + PullUp + Pull-up + 1 + + + PullDown + Pull-down + 2 + + + + + + + IDR + IDR + GPIO port input data register + 0x10 + 0x20 + read-only + 0x00000000 + + + IDR15 + Port input data (y = + 0..15) + 15 + 1 + + + + IDR14 + Port input data (y = + 0..15) + 14 + 1 + + + + IDR13 + Port input data (y = + 0..15) + 13 + 1 + + + + IDR12 + Port input data (y = + 0..15) + 12 + 1 + + + + IDR11 + Port input data (y = + 0..15) + 11 + 1 + + + + IDR10 + Port input data (y = + 0..15) + 10 + 1 + + + + IDR9 + Port input data (y = + 0..15) + 9 + 1 + + + + IDR8 + Port input data (y = + 0..15) + 8 + 1 + + + + IDR7 + Port input data (y = + 0..15) + 7 + 1 + + + + IDR6 + Port input data (y = + 0..15) + 6 + 1 + + + + IDR5 + Port input data (y = + 0..15) + 5 + 1 + + + + IDR4 + Port input data (y = + 0..15) + 4 + 1 + + + + IDR3 + Port input data (y = + 0..15) + 3 + 1 + + + + IDR2 + Port input data (y = + 0..15) + 2 + 1 + + + + IDR1 + Port input data (y = + 0..15) + 1 + 1 + + + + IDR0 + Port input data (y = + 0..15) + 0 + 1 + + IDR0 + read + + Low + Input is logic low + 0 + + + High + Input is logic high + 1 + + + + + + + ODR + ODR + GPIO port output data register + 0x14 + 0x20 + read-write + 0x00000000 + + + ODR15 + Port output data (y = + 0..15) + 15 + 1 + + + + ODR14 + Port output data (y = + 0..15) + 14 + 1 + + + + ODR13 + Port output data (y = + 0..15) + 13 + 1 + + + + ODR12 + Port output data (y = + 0..15) + 12 + 1 + + + + ODR11 + Port output data (y = + 0..15) + 11 + 1 + + + + ODR10 + Port output data (y = + 0..15) + 10 + 1 + + + + ODR9 + Port output data (y = + 0..15) + 9 + 1 + + + + ODR8 + Port output data (y = + 0..15) + 8 + 1 + + + + ODR7 + Port output data (y = + 0..15) + 7 + 1 + + + + ODR6 + Port output data (y = + 0..15) + 6 + 1 + + + + ODR5 + Port output data (y = + 0..15) + 5 + 1 + + + + ODR4 + Port output data (y = + 0..15) + 4 + 1 + + + + ODR3 + Port output data (y = + 0..15) + 3 + 1 + + + + ODR2 + Port output data (y = + 0..15) + 2 + 1 + + + + ODR1 + Port output data (y = + 0..15) + 1 + 1 + + + + ODR0 + Port output data (y = + 0..15) + 0 + 1 + + ODR0 + read-write + + Low + Set output to logic low + 0 + + + High + Set output to logic high + 1 + + + + + + + BSRR + BSRR + GPIO port bit set/reset + register + 0x18 + 0x20 + write-only + 0x00000000 + + + BR15 + Port x reset bit y (y = + 0..15) + 31 + 1 + + + + BR14 + Port x reset bit y (y = + 0..15) + 30 + 1 + + + + BR13 + Port x reset bit y (y = + 0..15) + 29 + 1 + + + + BR12 + Port x reset bit y (y = + 0..15) + 28 + 1 + + + + BR11 + Port x reset bit y (y = + 0..15) + 27 + 1 + + + + BR10 + Port x reset bit y (y = + 0..15) + 26 + 1 + + + + BR9 + Port x reset bit y (y = + 0..15) + 25 + 1 + + + + BR8 + Port x reset bit y (y = + 0..15) + 24 + 1 + + + + BR7 + Port x reset bit y (y = + 0..15) + 23 + 1 + + + + BR6 + Port x reset bit y (y = + 0..15) + 22 + 1 + + + + BR5 + Port x reset bit y (y = + 0..15) + 21 + 1 + + + + BR4 + Port x reset bit y (y = + 0..15) + 20 + 1 + + + + BR3 + Port x reset bit y (y = + 0..15) + 19 + 1 + + + + BR2 + Port x reset bit y (y = + 0..15) + 18 + 1 + + + + BR1 + Port x reset bit y (y = + 0..15) + 17 + 1 + + + + BR0 + Port x set bit y (y= + 0..15) + 16 + 1 + + BR0W + write + + Reset + Resets the corresponding ODRx bit + 1 + + + + + BS15 + Port x set bit y (y= + 0..15) + 15 + 1 + + + + BS14 + Port x set bit y (y= + 0..15) + 14 + 1 + + + + BS13 + Port x set bit y (y= + 0..15) + 13 + 1 + + + + BS12 + Port x set bit y (y= + 0..15) + 12 + 1 + + + + BS11 + Port x set bit y (y= + 0..15) + 11 + 1 + + + + BS10 + Port x set bit y (y= + 0..15) + 10 + 1 + + + + BS9 + Port x set bit y (y= + 0..15) + 9 + 1 + + + + BS8 + Port x set bit y (y= + 0..15) + 8 + 1 + + + + BS7 + Port x set bit y (y= + 0..15) + 7 + 1 + + + + BS6 + Port x set bit y (y= + 0..15) + 6 + 1 + + + + BS5 + Port x set bit y (y= + 0..15) + 5 + 1 + + + + BS4 + Port x set bit y (y= + 0..15) + 4 + 1 + + + + BS3 + Port x set bit y (y= + 0..15) + 3 + 1 + + + + BS2 + Port x set bit y (y= + 0..15) + 2 + 1 + + + + BS1 + Port x set bit y (y= + 0..15) + 1 + 1 + + + + BS0 + Port x set bit y (y= + 0..15) + 0 + 1 + + BS0W + write + + Set + Sets the corresponding ODRx bit + 1 + + + + + + + LCKR + LCKR + GPIO port configuration lock + register + 0x1C + 0x20 + read-write + 0x00000000 + + + LCKK + Port x lock bit y (y= + 0..15) + 16 + 1 + + LCKK + read-write + + NotActive + Port configuration lock key not active + 0 + + + Active + Port configuration lock key active + 1 + + + + + LCK15 + Port x lock bit y (y= + 0..15) + 15 + 1 + + + + LCK14 + Port x lock bit y (y= + 0..15) + 14 + 1 + + + + LCK13 + Port x lock bit y (y= + 0..15) + 13 + 1 + + + + LCK12 + Port x lock bit y (y= + 0..15) + 12 + 1 + + + + LCK11 + Port x lock bit y (y= + 0..15) + 11 + 1 + + + + LCK10 + Port x lock bit y (y= + 0..15) + 10 + 1 + + + + LCK9 + Port x lock bit y (y= + 0..15) + 9 + 1 + + + + LCK8 + Port x lock bit y (y= + 0..15) + 8 + 1 + + + + LCK7 + Port x lock bit y (y= + 0..15) + 7 + 1 + + + + LCK6 + Port x lock bit y (y= + 0..15) + 6 + 1 + + + + LCK5 + Port x lock bit y (y= + 0..15) + 5 + 1 + + + + LCK4 + Port x lock bit y (y= + 0..15) + 4 + 1 + + + + LCK3 + Port x lock bit y (y= + 0..15) + 3 + 1 + + + + LCK2 + Port x lock bit y (y= + 0..15) + 2 + 1 + + + + LCK1 + Port x lock bit y (y= + 0..15) + 1 + 1 + + + + LCK0 + Port x lock bit y (y= + 0..15) + 0 + 1 + + LCK0 + read-write + + Unlocked + Port configuration not locked + 0 + + + Locked + Port configuration locked + 1 + + + + + + + AFRL + AFRL + GPIO alternate function low + register + 0x20 + 0x20 + read-write + 0x00000000 + + + AFRL7 + Alternate function selection for port x + bit y (y = 0..7) + 28 + 4 + + + + AFRL6 + Alternate function selection for port x + bit y (y = 0..7) + 24 + 4 + + + + AFRL5 + Alternate function selection for port x + bit y (y = 0..7) + 20 + 4 + + + + AFRL4 + Alternate function selection for port x + bit y (y = 0..7) + 16 + 4 + + + + AFRL3 + Alternate function selection for port x + bit y (y = 0..7) + 12 + 4 + + + + AFRL2 + Alternate function selection for port x + bit y (y = 0..7) + 8 + 4 + + + + AFRL1 + Alternate function selection for port x + bit y (y = 0..7) + 4 + 4 + + + + AFRL0 + Alternate function selection for port x + bit y (y = 0..7) + 0 + 4 + + AFRL0 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + AFRH + AFRH + GPIO alternate function high + register + 0x24 + 0x20 + read-write + 0x00000000 + + + AFRH15 + Alternate function selection for port x + bit y (y = 8..15) + 28 + 4 + + + + AFRH14 + Alternate function selection for port x + bit y (y = 8..15) + 24 + 4 + + + + AFRH13 + Alternate function selection for port x + bit y (y = 8..15) + 20 + 4 + + + + AFRH12 + Alternate function selection for port x + bit y (y = 8..15) + 16 + 4 + + + + AFRH11 + Alternate function selection for port x + bit y (y = 8..15) + 12 + 4 + + + + AFRH10 + Alternate function selection for port x + bit y (y = 8..15) + 8 + 4 + + + + AFRH9 + Alternate function selection for port x + bit y (y = 8..15) + 4 + 4 + + + + AFRH8 + Alternate function selection for port x + bit y (y = 8..15) + 0 + 4 + + AFRH8 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + + + GPIOA + General-purpose I/Os + GPIO + 0x40020000 + + 0x0 + 0x400 + registers + + + TIM2 + TIM2 global interrupt + 28 + + + + MODER + MODER + GPIO port mode register + 0x0 + 0x20 + read-write + 0xA8000000 + + + MODER15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + MODER14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + MODER13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + MODER12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + MODER11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + MODER10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + MODER9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + MODER8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + MODER7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + MODER6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + MODER5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + MODER4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + MODER3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + MODER2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + MODER1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + MODER0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + MODER0 + read-write + + Input + Input mode (reset state) + 0 + + + Output + General purpose output mode + 1 + + + Alternate + Alternate function mode + 2 + + + Analog + Analog mode + 3 + + + + + + + OTYPER + OTYPER + GPIO port output type register + 0x4 + 0x20 + read-write + 0x00000000 + + + OT15 + Port x configuration bits (y = + 0..15) + 15 + 1 + + + + OT14 + Port x configuration bits (y = + 0..15) + 14 + 1 + + + + OT13 + Port x configuration bits (y = + 0..15) + 13 + 1 + + + + OT12 + Port x configuration bits (y = + 0..15) + 12 + 1 + + + + OT11 + Port x configuration bits (y = + 0..15) + 11 + 1 + + + + OT10 + Port x configuration bits (y = + 0..15) + 10 + 1 + + + + OT9 + Port x configuration bits (y = + 0..15) + 9 + 1 + + + + OT8 + Port x configuration bits (y = + 0..15) + 8 + 1 + + + + OT7 + Port x configuration bits (y = + 0..15) + 7 + 1 + + + + OT6 + Port x configuration bits (y = + 0..15) + 6 + 1 + + + + OT5 + Port x configuration bits (y = + 0..15) + 5 + 1 + + + + OT4 + Port x configuration bits (y = + 0..15) + 4 + 1 + + + + OT3 + Port x configuration bits (y = + 0..15) + 3 + 1 + + + + OT2 + Port x configuration bits (y = + 0..15) + 2 + 1 + + + + OT1 + Port x configuration bits (y = + 0..15) + 1 + 1 + + + + OT0 + Port x configuration bits (y = + 0..15) + 0 + 1 + + OT0 + read-write + + PushPull + Output push-pull (reset state) + 0 + + + OpenDrain + Output open-drain + 1 + + + + + + + OSPEEDR + OSPEEDR + GPIO port output speed + register + 0x8 + 0x20 + read-write + 0x00000000 + + + OSPEEDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + OSPEEDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + OSPEEDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + OSPEEDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + OSPEEDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + OSPEEDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + OSPEEDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + OSPEEDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + OSPEEDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + OSPEEDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + OSPEEDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + OSPEEDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + OSPEEDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + OSPEEDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + OSPEEDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + OSPEEDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + OSPEEDR0 + read-write + + LowSpeed + Low speed + 0 + + + MediumSpeed + Medium speed + 1 + + + HighSpeed + High speed + 2 + + + VeryHighSpeed + Very high speed + 3 + + + + + + + PUPDR + PUPDR + GPIO port pull-up/pull-down + register + 0xC + 0x20 + read-write + 0x64000000 + + + PUPDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + PUPDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + PUPDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + PUPDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + PUPDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + PUPDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + PUPDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + PUPDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + PUPDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + PUPDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + PUPDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + PUPDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + PUPDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + PUPDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + PUPDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + PUPDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + PUPDR0 + read-write + + Floating + No pull-up, pull-down + 0 + + + PullUp + Pull-up + 1 + + + PullDown + Pull-down + 2 + + + + + + + IDR + IDR + GPIO port input data register + 0x10 + 0x20 + read-only + 0x00000000 + + + IDR15 + Port input data (y = + 0..15) + 15 + 1 + + + + IDR14 + Port input data (y = + 0..15) + 14 + 1 + + + + IDR13 + Port input data (y = + 0..15) + 13 + 1 + + + + IDR12 + Port input data (y = + 0..15) + 12 + 1 + + + + IDR11 + Port input data (y = + 0..15) + 11 + 1 + + + + IDR10 + Port input data (y = + 0..15) + 10 + 1 + + + + IDR9 + Port input data (y = + 0..15) + 9 + 1 + + + + IDR8 + Port input data (y = + 0..15) + 8 + 1 + + + + IDR7 + Port input data (y = + 0..15) + 7 + 1 + + + + IDR6 + Port input data (y = + 0..15) + 6 + 1 + + + + IDR5 + Port input data (y = + 0..15) + 5 + 1 + + + + IDR4 + Port input data (y = + 0..15) + 4 + 1 + + + + IDR3 + Port input data (y = + 0..15) + 3 + 1 + + + + IDR2 + Port input data (y = + 0..15) + 2 + 1 + + + + IDR1 + Port input data (y = + 0..15) + 1 + 1 + + + + IDR0 + Port input data (y = + 0..15) + 0 + 1 + + IDR0 + read + + Low + Input is logic low + 0 + + + High + Input is logic high + 1 + + + + + + + ODR + ODR + GPIO port output data register + 0x14 + 0x20 + read-write + 0x00000000 + + + ODR15 + Port output data (y = + 0..15) + 15 + 1 + + + + ODR14 + Port output data (y = + 0..15) + 14 + 1 + + + + ODR13 + Port output data (y = + 0..15) + 13 + 1 + + + + ODR12 + Port output data (y = + 0..15) + 12 + 1 + + + + ODR11 + Port output data (y = + 0..15) + 11 + 1 + + + + ODR10 + Port output data (y = + 0..15) + 10 + 1 + + + + ODR9 + Port output data (y = + 0..15) + 9 + 1 + + + + ODR8 + Port output data (y = + 0..15) + 8 + 1 + + + + ODR7 + Port output data (y = + 0..15) + 7 + 1 + + + + ODR6 + Port output data (y = + 0..15) + 6 + 1 + + + + ODR5 + Port output data (y = + 0..15) + 5 + 1 + + + + ODR4 + Port output data (y = + 0..15) + 4 + 1 + + + + ODR3 + Port output data (y = + 0..15) + 3 + 1 + + + + ODR2 + Port output data (y = + 0..15) + 2 + 1 + + + + ODR1 + Port output data (y = + 0..15) + 1 + 1 + + + + ODR0 + Port output data (y = + 0..15) + 0 + 1 + + ODR0 + read-write + + Low + Set output to logic low + 0 + + + High + Set output to logic high + 1 + + + + + + + BSRR + BSRR + GPIO port bit set/reset + register + 0x18 + 0x20 + write-only + 0x00000000 + + + BR15 + Port x reset bit y (y = + 0..15) + 31 + 1 + + + + BR14 + Port x reset bit y (y = + 0..15) + 30 + 1 + + + + BR13 + Port x reset bit y (y = + 0..15) + 29 + 1 + + + + BR12 + Port x reset bit y (y = + 0..15) + 28 + 1 + + + + BR11 + Port x reset bit y (y = + 0..15) + 27 + 1 + + + + BR10 + Port x reset bit y (y = + 0..15) + 26 + 1 + + + + BR9 + Port x reset bit y (y = + 0..15) + 25 + 1 + + + + BR8 + Port x reset bit y (y = + 0..15) + 24 + 1 + + + + BR7 + Port x reset bit y (y = + 0..15) + 23 + 1 + + + + BR6 + Port x reset bit y (y = + 0..15) + 22 + 1 + + + + BR5 + Port x reset bit y (y = + 0..15) + 21 + 1 + + + + BR4 + Port x reset bit y (y = + 0..15) + 20 + 1 + + + + BR3 + Port x reset bit y (y = + 0..15) + 19 + 1 + + + + BR2 + Port x reset bit y (y = + 0..15) + 18 + 1 + + + + BR1 + Port x reset bit y (y = + 0..15) + 17 + 1 + + + + BR0 + Port x set bit y (y= + 0..15) + 16 + 1 + + BR0W + write + + Reset + Resets the corresponding ODRx bit + 1 + + + + + BS15 + Port x set bit y (y= + 0..15) + 15 + 1 + + + + BS14 + Port x set bit y (y= + 0..15) + 14 + 1 + + + + BS13 + Port x set bit y (y= + 0..15) + 13 + 1 + + + + BS12 + Port x set bit y (y= + 0..15) + 12 + 1 + + + + BS11 + Port x set bit y (y= + 0..15) + 11 + 1 + + + + BS10 + Port x set bit y (y= + 0..15) + 10 + 1 + + + + BS9 + Port x set bit y (y= + 0..15) + 9 + 1 + + + + BS8 + Port x set bit y (y= + 0..15) + 8 + 1 + + + + BS7 + Port x set bit y (y= + 0..15) + 7 + 1 + + + + BS6 + Port x set bit y (y= + 0..15) + 6 + 1 + + + + BS5 + Port x set bit y (y= + 0..15) + 5 + 1 + + + + BS4 + Port x set bit y (y= + 0..15) + 4 + 1 + + + + BS3 + Port x set bit y (y= + 0..15) + 3 + 1 + + + + BS2 + Port x set bit y (y= + 0..15) + 2 + 1 + + + + BS1 + Port x set bit y (y= + 0..15) + 1 + 1 + + + + BS0 + Port x set bit y (y= + 0..15) + 0 + 1 + + BS0W + write + + Set + Sets the corresponding ODRx bit + 1 + + + + + + + LCKR + LCKR + GPIO port configuration lock + register + 0x1C + 0x20 + read-write + 0x00000000 + + + LCKK + Port x lock bit y (y= + 0..15) + 16 + 1 + + LCKK + read-write + + NotActive + Port configuration lock key not active + 0 + + + Active + Port configuration lock key active + 1 + + + + + LCK15 + Port x lock bit y (y= + 0..15) + 15 + 1 + + + + LCK14 + Port x lock bit y (y= + 0..15) + 14 + 1 + + + + LCK13 + Port x lock bit y (y= + 0..15) + 13 + 1 + + + + LCK12 + Port x lock bit y (y= + 0..15) + 12 + 1 + + + + LCK11 + Port x lock bit y (y= + 0..15) + 11 + 1 + + + + LCK10 + Port x lock bit y (y= + 0..15) + 10 + 1 + + + + LCK9 + Port x lock bit y (y= + 0..15) + 9 + 1 + + + + LCK8 + Port x lock bit y (y= + 0..15) + 8 + 1 + + + + LCK7 + Port x lock bit y (y= + 0..15) + 7 + 1 + + + + LCK6 + Port x lock bit y (y= + 0..15) + 6 + 1 + + + + LCK5 + Port x lock bit y (y= + 0..15) + 5 + 1 + + + + LCK4 + Port x lock bit y (y= + 0..15) + 4 + 1 + + + + LCK3 + Port x lock bit y (y= + 0..15) + 3 + 1 + + + + LCK2 + Port x lock bit y (y= + 0..15) + 2 + 1 + + + + LCK1 + Port x lock bit y (y= + 0..15) + 1 + 1 + + + + LCK0 + Port x lock bit y (y= + 0..15) + 0 + 1 + + LCK0 + read-write + + Unlocked + Port configuration not locked + 0 + + + Locked + Port configuration locked + 1 + + + + + + + AFRL + AFRL + GPIO alternate function low + register + 0x20 + 0x20 + read-write + 0x00000000 + + + AFRL7 + Alternate function selection for port x + bit y (y = 0..7) + 28 + 4 + + + + AFRL6 + Alternate function selection for port x + bit y (y = 0..7) + 24 + 4 + + + + AFRL5 + Alternate function selection for port x + bit y (y = 0..7) + 20 + 4 + + + + AFRL4 + Alternate function selection for port x + bit y (y = 0..7) + 16 + 4 + + + + AFRL3 + Alternate function selection for port x + bit y (y = 0..7) + 12 + 4 + + + + AFRL2 + Alternate function selection for port x + bit y (y = 0..7) + 8 + 4 + + + + AFRL1 + Alternate function selection for port x + bit y (y = 0..7) + 4 + 4 + + + + AFRL0 + Alternate function selection for port x + bit y (y = 0..7) + 0 + 4 + + AFRL0 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + AFRH + AFRH + GPIO alternate function high + register + 0x24 + 0x20 + read-write + 0x00000000 + + + AFRH15 + Alternate function selection for port x + bit y (y = 8..15) + 28 + 4 + + + + AFRH14 + Alternate function selection for port x + bit y (y = 8..15) + 24 + 4 + + + + AFRH13 + Alternate function selection for port x + bit y (y = 8..15) + 20 + 4 + + + + AFRH12 + Alternate function selection for port x + bit y (y = 8..15) + 16 + 4 + + + + AFRH11 + Alternate function selection for port x + bit y (y = 8..15) + 12 + 4 + + + + AFRH10 + Alternate function selection for port x + bit y (y = 8..15) + 8 + 4 + + + + AFRH9 + Alternate function selection for port x + bit y (y = 8..15) + 4 + 4 + + + + AFRH8 + Alternate function selection for port x + bit y (y = 8..15) + 0 + 4 + + AFRH8 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + + + I2C3 + 0x40005C00 + + TIM3 + TIM3 global interrupt + 29 + + + + I2C2 + 0x40005800 + + I2C3_EV + I2C3 event interrupt + 72 + + + I2C3_ER + I2C3 error interrupt + 73 + + + + I2C1 + Inter-integrated circuit + I2C + 0x40005400 + + 0x0 + 0x400 + registers + + + I2C2_EV + I2C2 event interrupt + 33 + + + I2C2_ER + I2C2 error interrupt + 34 + + + + CR1 + CR1 + Control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + SWRST + Software reset + 15 + 1 + + SWRST + read-write + + NotReset + I2C peripheral not under reset + 0 + + + Reset + I2C peripheral under reset + 1 + + + + + ALERT + SMBus alert + 13 + 1 + + ALERT + read-write + + Release + SMBA pin released high + 0 + + + Drive + SMBA pin driven low + 1 + + + + + PEC + Packet error checking + 12 + 1 + + PEC + read-write + + Disabled + No PEC transfer + 0 + + + Enabled + PEC transfer + 1 + + + + + POS + Acknowledge/PEC Position (for data + reception) + 11 + 1 + + POS + read-write + + Current + ACK bit controls the (N)ACK of the current byte being received + 0 + + + Next + ACK bit controls the (N)ACK of the next byte to be received + 1 + + + + + ACK + Acknowledge enable + 10 + 1 + + ACK + read-write + + NAK + No acknowledge returned + 0 + + + ACK + Acknowledge returned after a byte is received + 1 + + + + + STOP + Stop generation + 9 + 1 + + STOP + read-write + + NoStop + No Stop generation + 0 + + + Stop + In master mode: stop generation after current byte/start, in slave mode: release SCL and SDA after current byte + 1 + + + + + START + Start generation + 8 + 1 + + START + read-write + + NoStart + No Start generation + 0 + + + Start + In master mode: repeated start generation, in slave mode: start generation when bus is free + 1 + + + + + NOSTRETCH + Clock stretching disable (Slave + mode) + 7 + 1 + + NOSTRETCH + read-write + + Enabled + Clock stretching enabled + 0 + + + Disabled + Clock stretching disabled + 1 + + + + + ENGC + General call enable + 6 + 1 + + ENGC + read-write + + Disabled + General call disabled + 0 + + + Enabled + General call enabled + 1 + + + + + ENPEC + PEC enable + 5 + 1 + + ENPEC + read-write + + Disabled + PEC calculation disabled + 0 + + + Enabled + PEC calculation enabled + 1 + + + + + ENARP + ARP enable + 4 + 1 + + ENARP + read-write + + Disabled + ARP disabled + 0 + + + Enabled + ARP enabled + 1 + + + + + SMBTYPE + SMBus type + 3 + 1 + + SMBTYPE + read-write + + Device + SMBus Device + 0 + + + Host + SMBus Host + 1 + + + + + SMBUS + SMBus mode + 1 + 1 + + SMBUS + read-write + + I2C + I2C Mode + 0 + + + SMBus + SMBus + 1 + + + + + PE + Peripheral enable + 0 + 1 + + PE + read-write + + Disabled + Peripheral disabled + 0 + + + Enabled + Peripheral enabled + 1 + + + + + + + CR2 + CR2 + Control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + LAST + DMA last transfer + 12 + 1 + + LAST + read-write + + NotLast + Next DMA EOT is not the last transfer + 0 + + + Last + Next DMA EOT is the last transfer + 1 + + + + + DMAEN + DMA requests enable + 11 + 1 + + DMAEN + read-write + + Disabled + DMA requests disabled + 0 + + + Enabled + DMA request enabled when TxE=1 or RxNE=1 + 1 + + + + + ITBUFEN + Buffer interrupt enable + 10 + 1 + + ITBUFEN + read-write + + Disabled + TxE=1 or RxNE=1 does not generate any interrupt + 0 + + + Enabled + TxE=1 or RxNE=1 generates Event interrupt + 1 + + + + + ITEVTEN + Event interrupt enable + 9 + 1 + + ITEVTEN + read-write + + Disabled + Event interrupt disabled + 0 + + + Enabled + Event interrupt enabled + 1 + + + + + ITERREN + Error interrupt enable + 8 + 1 + + ITERREN + read-write + + Disabled + Error interrupt disabled + 0 + + + Enabled + Error interrupt enabled + 1 + + + + + FREQ + Peripheral clock frequency + 0 + 6 + + + 2 + 50 + + + + + + + OAR1 + OAR1 + Own address register 1 + 0x8 + 0x20 + read-write + 0x00000000 + + + ADDMODE + Addressing mode (slave + mode) + 15 + 1 + + ADDMODE + read-write + + ADD7 + 7-bit slave address + 0 + + + ADD10 + 10-bit slave address + 1 + + + + + ADD + Interface address + 0 + 10 + + + 0 + 1023 + + + + + + + OAR2 + OAR2 + Own address register 2 + 0xC + 0x20 + read-write + 0x00000000 + + + ADD2 + Interface address + 1 + 7 + + + 0 + 127 + + + + + ENDUAL + Dual addressing mode + enable + 0 + 1 + + ENDUAL + read-write + + Single + Single addressing mode + 0 + + + Dual + Dual addressing mode + 1 + + + + + + + DR + DR + Data register + 0x10 + 0x20 + read-write + 0x00000000 + + + DR + 8-bit data register + 0 + 8 + + + 0 + 255 + + + + + + + SR1 + SR1 + Status register 1 + 0x14 + 0x20 + 0x00000000 + + + SMBALERT + SMBus alert + 15 + 1 + read-write + zeroToClear + + SMBALERTR + read + + NoAlert + No SMBALERT occured + 0 + + + Alert + SMBALERT occurred + 1 + + + + SMBALERTW + write + + Clear + Clear flag + 0 + + + + + TIMEOUT + Timeout or Tlow error + 14 + 1 + read-write + zeroToClear + + TIMEOUTR + read + + NoTimeout + No Timeout error + 0 + + + Timeout + SCL remained LOW for 25 ms + 1 + + + + TIMEOUTW + write + + Clear + Clear flag + 0 + + + + + PECERR + PEC Error in reception + 12 + 1 + read-write + zeroToClear + + PECERRR + read + + NoError + no PEC error: receiver returns ACK after PEC reception (if ACK=1) + 0 + + + Error + PEC error: receiver returns NACK after PEC reception (whatever ACK) + 1 + + + + PECERRW + write + + Clear + Clear flag + 0 + + + + + OVR + Overrun/Underrun + 11 + 1 + read-write + zeroToClear + + OVRR + read + + NoOverrun + No overrun/underrun occured + 0 + + + Overrun + Overrun/underrun occured + 1 + + + + OVRW + write + + Clear + Clear flag + 0 + + + + + AF + Acknowledge failure + 10 + 1 + read-write + zeroToClear + + AFR + read + + NoFailure + No acknowledge failure + 0 + + + Failure + Acknowledge failure + 1 + + + + AFW + write + + Clear + Clear flag + 0 + + + + + ARLO + Arbitration lost (master + mode) + 9 + 1 + read-write + zeroToClear + + ARLOR + read + + NoLost + No Arbitration Lost detected + 0 + + + Lost + Arbitration Lost detected + 1 + + + + ARLOW + write + + Clear + Clear flag + 0 + + + + + BERR + Bus error + 8 + 1 + read-write + zeroToClear + + BERRR + read + + NoError + No misplaced Start or Stop condition + 0 + + + Error + Misplaced Start or Stop condition + 1 + + + + BERRW + write + + Clear + Clear flag + 0 + + + + + TxE + Data register empty + (transmitters) + 7 + 1 + read-only + + TxE + read + + NotEmpty + Data register not empty + 0 + + + Empty + Data register empty + 1 + + + + + RxNE + Data register not empty + (receivers) + 6 + 1 + read-only + + RxNE + read + + Empty + Data register empty + 0 + + + NotEmpty + Data register not empty + 1 + + + + + STOPF + Stop detection (slave + mode) + 4 + 1 + read-only + + STOPF + read + + NoStop + No Stop condition detected + 0 + + + Stop + Stop condition detected + 1 + + + + + ADD10 + 10-bit header sent (Master + mode) + 3 + 1 + read-only + + + BTF + Byte transfer finished + 2 + 1 + read-only + + BTF + read + + NotFinished + Data byte transfer not done + 0 + + + Finished + Data byte transfer successful + 1 + + + + + ADDR + Address sent (master mode)/matched + (slave mode) + 1 + 1 + read-only + + ADDR + read + + NotMatch + Adress mismatched or not received + 0 + + + Match + Received slave address matched with one of the enabled slave addresses + 1 + + + + + SB + Start bit (Master mode) + 0 + 1 + read-only + + SB + read + + NoStart + No Start condition + 0 + + + Start + Start condition generated + 1 + + + + + + + SR2 + SR2 + Status register 2 + 0x18 + 0x20 + read-only + 0x00000000 + + + PEC + acket error checking + register + 8 + 8 + + + DUALF + Dual flag (Slave mode) + 7 + 1 + + + SMBHOST + SMBus host header (Slave + mode) + 6 + 1 + + + SMBDEFAULT + SMBus device default address (Slave + mode) + 5 + 1 + + + GENCALL + General call address (Slave + mode) + 4 + 1 + + + TRA + Transmitter/receiver + 2 + 1 + + + BUSY + Bus busy + 1 + 1 + + + MSL + Master/slave + 0 + 1 + + + + + CCR + CCR + Clock control register + 0x1C + 0x20 + read-write + 0x00000000 + + + F_S + I2C master mode selection + 15 + 1 + + F_S + read-write + + Standard + Standard mode I2C + 0 + + + Fast + Fast mode I2C + 1 + + + + + DUTY + Fast mode duty cycle + 14 + 1 + + DUTY + read-write + + Duty2_1 + Duty cycle t_low/t_high = 2/1 + 0 + + + Duty16_9 + Duty cycle t_low/t_high = 16/9 + 1 + + + + + CCR + Clock control register in Fast/Standard + mode (Master mode) + 0 + 12 + + + 1 + 4095 + + + + + + + TRISE + TRISE + TRISE register + 0x20 + 0x20 + read-write + 0x00000002 + + + TRISE + Maximum rise time in Fast/Standard mode + (Master mode) + 0 + 6 + + + 0 + 63 + + + + + + + FLTR + FLTR register + 0x24 + read-write + 0x00000000 + + + ANOFF + Analog noise filter + 4 + 1 + + ANOFF + read-write + + Enabled + Analog noise filter enabled + 0 + + + Disabled + Analog noise filter disabled + 1 + + + + + DNF + Digital noise filter + 0 + 4 + + DNF + read-write + + NoFilter + Digital filter disabled + 0 + + + Filter1 + Digital filter enabled and filtering capability up to 1 tI2CCLK + 1 + + + Filter2 + Digital filter enabled and filtering capability up to 2 tI2CCLK + 2 + + + Filter3 + Digital filter enabled and filtering capability up to 3 tI2CCLK + 3 + + + Filter4 + Digital filter enabled and filtering capability up to 4 tI2CCLK + 4 + + + Filter5 + Digital filter enabled and filtering capability up to 5 tI2CCLK + 5 + + + Filter6 + Digital filter enabled and filtering capability up to 6 tI2CCLK + 6 + + + Filter7 + Digital filter enabled and filtering capability up to 7 tI2CCLK + 7 + + + Filter8 + Digital filter enabled and filtering capability up to 8 tI2CCLK + 8 + + + Filter9 + Digital filter enabled and filtering capability up to 9 tI2CCLK + 9 + + + Filter10 + Digital filter enabled and filtering capability up to 10 tI2CCLK + 10 + + + Filter11 + Digital filter enabled and filtering capability up to 11 tI2CCLK + 11 + + + Filter12 + Digital filter enabled and filtering capability up to 12 tI2CCLK + 12 + + + Filter13 + Digital filter enabled and filtering capability up to 13 tI2CCLK + 13 + + + Filter14 + Digital filter enabled and filtering capability up to 14 tI2CCLK + 14 + + + Filter15 + Digital filter enabled and filtering capability up to 15 tI2CCLK + 15 + + + + + + + + + I2S2ext + 0x40003400 + + I2C1_EV + I2C1 event interrupt + 31 + + + I2C1_ER + I2C1 error interrupt + 32 + + + + I2S3ext + 0x40004000 + + + SPI1 + Serial peripheral interface + SPI + 0x40013000 + + 0x0 + 0x400 + registers + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + BIDIMODE + Bidirectional data mode + enable + 15 + 1 + + BIDIMODE + read-write + + Unidirectional + 2-line unidirectional data mode selected + 0 + + + Bidirectional + 1-line bidirectional data mode selected + 1 + + + + + BIDIOE + Output enable in bidirectional + mode + 14 + 1 + + BIDIOE + read-write + + OutputDisabled + Output disabled (receive-only mode) + 0 + + + OutputEnabled + Output enabled (transmit-only mode) + 1 + + + + + CRCEN + Hardware CRC calculation + enable + 13 + 1 + + CRCEN + read-write + + Disabled + CRC calculation disabled + 0 + + + Enabled + CRC calculation enabled + 1 + + + + + CRCNEXT + CRC transfer next + 12 + 1 + + CRCNEXT + read-write + + TxBuffer + Next transmit value is from Tx buffer + 0 + + + CRC + Next transmit value is from Tx CRC register + 1 + + + + + DFF + Data frame format + 11 + 1 + + DFF + read-write + + EightBit + 8-bit data frame format is selected for transmission/reception + 0 + + + SixteenBit + 16-bit data frame format is selected for transmission/reception + 1 + + + + + RXONLY + Receive only + 10 + 1 + + RXONLY + read-write + + FullDuplex + Full duplex (Transmit and receive) + 0 + + + OutputDisabled + Output disabled (Receive-only mode) + 1 + + + + + SSM + Software slave management + 9 + 1 + + SSM + read-write + + Disabled + Software slave management disabled + 0 + + + Enabled + Software slave management enabled + 1 + + + + + SSI + Internal slave select + 8 + 1 + + SSI + read-write + + SlaveSelected + 0 is forced onto the NSS pin and the I/O value of the NSS pin is ignored + 0 + + + SlaveNotSelected + 1 is forced onto the NSS pin and the I/O value of the NSS pin is ignored + 1 + + + + + LSBFIRST + Frame format + 7 + 1 + + LSBFIRST + read-write + + MSBFirst + Data is transmitted/received with the MSB first + 0 + + + LSBFirst + Data is transmitted/received with the LSB first + 1 + + + + + SPE + SPI enable + 6 + 1 + + SPE + read-write + + Disabled + Peripheral disabled + 0 + + + Enabled + Peripheral enabled + 1 + + + + + BR + Baud rate control + 3 + 3 + + BR + read-write + + Div2 + f_PCLK / 2 + 0 + + + Div4 + f_PCLK / 4 + 1 + + + Div8 + f_PCLK / 8 + 2 + + + Div16 + f_PCLK / 16 + 3 + + + Div32 + f_PCLK / 32 + 4 + + + Div64 + f_PCLK / 64 + 5 + + + Div128 + f_PCLK / 128 + 6 + + + Div256 + f_PCLK / 256 + 7 + + + + + MSTR + Master selection + 2 + 1 + + MSTR + read-write + + Slave + Slave configuration + 0 + + + Master + Master configuration + 1 + + + + + CPOL + Clock polarity + 1 + 1 + + CPOL + read-write + + IdleLow + CK to 0 when idle + 0 + + + IdleHigh + CK to 1 when idle + 1 + + + + + CPHA + Clock phase + 0 + 1 + + CPHA + read-write + + FirstEdge + The first clock transition is the first data capture edge + 0 + + + SecondEdge + The second clock transition is the first data capture edge + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + TXEIE + Tx buffer empty interrupt + enable + 7 + 1 + + TXEIE + read-write + + Masked + TXE interrupt masked + 0 + + + NotMasked + TXE interrupt not masked + 1 + + + + + RXNEIE + RX buffer not empty interrupt + enable + 6 + 1 + + RXNEIE + read-write + + Masked + RXE interrupt masked + 0 + + + NotMasked + RXE interrupt not masked + 1 + + + + + ERRIE + Error interrupt enable + 5 + 1 + + ERRIE + read-write + + Masked + Error interrupt masked + 0 + + + NotMasked + Error interrupt not masked + 1 + + + + + FRF + Frame format + 4 + 1 + + FRF + read-write + + Motorola + SPI Motorola mode + 0 + + + TI + SPI TI mode + 1 + + + + + SSOE + SS output enable + 2 + 1 + + SSOE + read-write + + Disabled + SS output is disabled in master mode + 0 + + + Enabled + SS output is enabled in master mode + 1 + + + + + TXDMAEN + Tx buffer DMA enable + 1 + 1 + + TXDMAEN + read-write + + Disabled + Tx buffer DMA disabled + 0 + + + Enabled + Tx buffer DMA enabled + 1 + + + + + RXDMAEN + Rx buffer DMA enable + 0 + 1 + + RXDMAEN + read-write + + Disabled + Rx buffer DMA disabled + 0 + + + Enabled + Rx buffer DMA enabled + 1 + + + + + + + SR + SR + status register + 0x8 + 0x20 + 0x00000002 + + + FRE + TI frame format error + 8 + 1 + read-only + + FRER + read + + NoError + No frame format error + 0 + + + Error + A frame format error occurred + 1 + + + + + BSY + Busy flag + 7 + 1 + read-only + + BSYR + read + + NotBusy + SPI not busy + 0 + + + Busy + SPI busy + 1 + + + + + OVR + Overrun flag + 6 + 1 + read-only + + OVRR + read + + NoOverrun + No overrun occurred + 0 + + + Overrun + Overrun occurred + 1 + + + + + MODF + Mode fault + 5 + 1 + read-only + + MODFR + read + + NoFault + No mode fault occurred + 0 + + + Fault + Mode fault occurred + 1 + + + + + CRCERR + CRC error flag + 4 + 1 + read-write + zeroToClear + + CRCERRR + read + + Match + CRC value received matches the SPIx_RXCRCR value + 0 + + + NoMatch + CRC value received does not match the SPIx_RXCRCR value + 1 + + + + CRCERRW + write + + Clear + Clear flag + 0 + + + + + UDR + Underrun flag + 3 + 1 + read-only + + UDRR + read + + NoUnderrun + No underrun occurred + 0 + + + Underrun + Underrun occurred + 1 + + + + + CHSIDE + Channel side + 2 + 1 + read-only + + CHSIDE + read + + Left + Channel left has to be transmitted or has been received + 0 + + + Right + Channel right has to be transmitted or has been received + 1 + + + + + TXE + Transmit buffer empty + 1 + 1 + read-only + + TXE + read + + NotEmpty + Tx buffer not empty + 0 + + + Empty + Tx buffer empty + 1 + + + + + RXNE + Receive buffer not empty + 0 + 1 + read-only + + RXNE + read + + Empty + Rx buffer empty + 0 + + + NotEmpty + Rx buffer not empty + 1 + + + + + + + DR + DR + data register + 0xC + 0x20 + read-write + 0x00000000 + + + DR + Data register + 0 + 16 + + + 0 + 65535 + + + + + + + CRCPR + CRCPR + CRC polynomial register + 0x10 + 0x20 + read-write + 0x00000007 + + + CRCPOLY + CRC polynomial register + 0 + 16 + + + 0 + 65535 + + + + + + + RXCRCR + RXCRCR + RX CRC register + 0x14 + 0x20 + read-only + 0x00000000 + + + RxCRC + Rx CRC register + 0 + 16 + + + 0 + 65535 + + + + + + + TXCRCR + TXCRCR + TX CRC register + 0x18 + 0x20 + read-only + 0x00000000 + + + TxCRC + Tx CRC register + 0 + 16 + + + 0 + 65535 + + + + + + + I2SCFGR + I2SCFGR + I2S configuration register + 0x1C + 0x20 + read-write + 0x00000000 + + + I2SMOD + I2S mode selection + 11 + 1 + + I2SMOD + read-write + + SPIMode + SPI mode is selected + 0 + + + I2SMode + I2S mode is selected + 1 + + + + + I2SE + I2S Enable + 10 + 1 + + I2SE + read-write + + Disabled + I2S peripheral is disabled + 0 + + + Enabled + I2S peripheral is enabled + 1 + + + + + I2SCFG + I2S configuration mode + 8 + 2 + + I2SCFG + read-write + + SlaveTx + Slave - transmit + 0 + + + SlaveRx + Slave - receive + 1 + + + MasterTx + Master - transmit + 2 + + + MasterRx + Master - receive + 3 + + + + + PCMSYNC + PCM frame synchronization + 7 + 1 + + PCMSYNC + read-write + + Short + Short frame synchronisation + 0 + + + Long + Long frame synchronisation + 1 + + + + + I2SSTD + I2S standard selection + 4 + 2 + + I2SSTD + read-write + + Philips + I2S Philips standard + 0 + + + MSB + MSB justified standard + 1 + + + LSB + LSB justified standard + 2 + + + PCM + PCM standard + 3 + + + + + CKPOL + Steady state clock + polarity + 3 + 1 + + CKPOL + read-write + + IdleLow + I2S clock inactive state is low level + 0 + + + IdleHigh + I2S clock inactive state is high level + 1 + + + + + DATLEN + Data length to be + transferred + 1 + 2 + + DATLEN + read-write + + SixteenBit + 16-bit data length + 0 + + + TwentyFourBit + 24-bit data length + 1 + + + ThirtyTwoBit + 32-bit data length + 2 + + + + + CHLEN + Channel length (number of bits per audio + channel) + 0 + 1 + + CHLEN + read-write + + SixteenBit + 16-bit wide + 0 + + + ThirtyTwoBit + 32-bit wide + 1 + + + + + + + I2SPR + I2SPR + I2S prescaler register + 0x20 + 0x20 + read-write + 0x0000000A + + + MCKOE + Master clock output enable + 9 + 1 + + MCKOE + read-write + + Disabled + Master clock output is disabled + 0 + + + Enabled + Master clock output is enabled + 1 + + + + + ODD + Odd factor for the + prescaler + 8 + 1 + + ODD + read-write + + Even + Real divider value is I2SDIV * 2 + 0 + + + Odd + Real divider value is (I2SDIV * 2) + 1 + 1 + + + + + I2SDIV + I2S Linear prescaler + 0 + 8 + + + 2 + 255 + + + + + + + + + SPI2 + 0x40003800 + + SPI1 + SPI1 global interrupt + 35 + + + + SPI3 + 0x40003C00 + + SPI2 + SPI2 global interrupt + 36 + + + + SPI4 + 0x40013400 + + SPI3 + SPI3 global interrupt + 51 + + + + NVIC + Nested Vectored Interrupt + Controller + NVIC + 0xE000E100 + + 0x0 + 0x351 + registers + + + + ISER0 + ISER0 + Interrupt Set-Enable Register + 0x0 + 0x20 + read-write + 0x00000000 + + + SETENA + SETENA + 0 + 32 + + + + + ISER1 + ISER1 + Interrupt Set-Enable Register + 0x4 + 0x20 + read-write + 0x00000000 + + + SETENA + SETENA + 0 + 32 + + + + + ISER2 + ISER2 + Interrupt Set-Enable Register + 0x8 + 0x20 + read-write + 0x00000000 + + + SETENA + SETENA + 0 + 32 + + + + + ICER0 + ICER0 + Interrupt Clear-Enable + Register + 0x80 + 0x20 + read-write + 0x00000000 + + + CLRENA + CLRENA + 0 + 32 + + + + + ICER1 + ICER1 + Interrupt Clear-Enable + Register + 0x84 + 0x20 + read-write + 0x00000000 + + + CLRENA + CLRENA + 0 + 32 + + + + + ICER2 + ICER2 + Interrupt Clear-Enable + Register + 0x88 + 0x20 + read-write + 0x00000000 + + + CLRENA + CLRENA + 0 + 32 + + + + + ISPR0 + ISPR0 + Interrupt Set-Pending Register + 0x100 + 0x20 + read-write + 0x00000000 + + + SETPEND + SETPEND + 0 + 32 + + + + + ISPR1 + ISPR1 + Interrupt Set-Pending Register + 0x104 + 0x20 + read-write + 0x00000000 + + + SETPEND + SETPEND + 0 + 32 + + + + + ISPR2 + ISPR2 + Interrupt Set-Pending Register + 0x108 + 0x20 + read-write + 0x00000000 + + + SETPEND + SETPEND + 0 + 32 + + + + + ICPR0 + ICPR0 + Interrupt Clear-Pending + Register + 0x180 + 0x20 + read-write + 0x00000000 + + + CLRPEND + CLRPEND + 0 + 32 + + + + + ICPR1 + ICPR1 + Interrupt Clear-Pending + Register + 0x184 + 0x20 + read-write + 0x00000000 + + + CLRPEND + CLRPEND + 0 + 32 + + + + + ICPR2 + ICPR2 + Interrupt Clear-Pending + Register + 0x188 + 0x20 + read-write + 0x00000000 + + + CLRPEND + CLRPEND + 0 + 32 + + + + + IABR0 + IABR0 + Interrupt Active Bit Register + 0x200 + 0x20 + read-only + 0x00000000 + + + ACTIVE + ACTIVE + 0 + 32 + + + + + IABR1 + IABR1 + Interrupt Active Bit Register + 0x204 + 0x20 + read-only + 0x00000000 + + + ACTIVE + ACTIVE + 0 + 32 + + + + + IABR2 + IABR2 + Interrupt Active Bit Register + 0x208 + 0x20 + read-only + 0x00000000 + + + ACTIVE + ACTIVE + 0 + 32 + + + + + IPR0 + IPR0 + Interrupt Priority Register + 0x300 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR1 + IPR1 + Interrupt Priority Register + 0x304 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR2 + IPR2 + Interrupt Priority Register + 0x308 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR3 + IPR3 + Interrupt Priority Register + 0x30C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR4 + IPR4 + Interrupt Priority Register + 0x310 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR5 + IPR5 + Interrupt Priority Register + 0x314 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR6 + IPR6 + Interrupt Priority Register + 0x318 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR7 + IPR7 + Interrupt Priority Register + 0x31C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR8 + IPR8 + Interrupt Priority Register + 0x320 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR9 + IPR9 + Interrupt Priority Register + 0x324 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR10 + IPR10 + Interrupt Priority Register + 0x328 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR11 + IPR11 + Interrupt Priority Register + 0x32C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR12 + IPR12 + Interrupt Priority Register + 0x330 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR13 + IPR13 + Interrupt Priority Register + 0x334 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR14 + IPR14 + Interrupt Priority Register + 0x338 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR15 + IPR15 + Interrupt Priority Register + 0x33C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR16 + IPR16 + Interrupt Priority Register + 0x340 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR17 + IPR17 + Interrupt Priority Register + 0x344 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR18 + IPR18 + Interrupt Priority Register + 0x348 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR19 + IPR19 + Interrupt Priority Register + 0x34C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + + + FPU + Floting point unit + FPU + 0xE000EF34 + + 0x0 + 0xD + registers + + + FPU + Floating point unit interrupt + 81 + + + + FPCCR + FPCCR + Floating-point context control + register + 0x0 + 0x20 + read-write + 0x00000000 + + + LSPACT + LSPACT + 0 + 1 + + + USER + USER + 1 + 1 + + + THREAD + THREAD + 3 + 1 + + + HFRDY + HFRDY + 4 + 1 + + + MMRDY + MMRDY + 5 + 1 + + + BFRDY + BFRDY + 6 + 1 + + + MONRDY + MONRDY + 8 + 1 + + + LSPEN + LSPEN + 30 + 1 + + + ASPEN + ASPEN + 31 + 1 + + + + + FPCAR + FPCAR + Floating-point context address + register + 0x4 + 0x20 + read-write + 0x00000000 + + + ADDRESS + Location of unpopulated + floating-point + 3 + 29 + + + + + FPSCR + FPSCR + Floating-point status control + register + 0x8 + 0x20 + read-write + 0x00000000 + + + IOC + Invalid operation cumulative exception + bit + 0 + 1 + + + DZC + Division by zero cumulative exception + bit. + 1 + 1 + + + OFC + Overflow cumulative exception + bit + 2 + 1 + + + UFC + Underflow cumulative exception + bit + 3 + 1 + + + IXC + Inexact cumulative exception + bit + 4 + 1 + + + IDC + Input denormal cumulative exception + bit. + 7 + 1 + + + RMode + Rounding Mode control + field + 22 + 2 + + + FZ + Flush-to-zero mode control + bit: + 24 + 1 + + + DN + Default NaN mode control + bit + 25 + 1 + + + AHP + Alternative half-precision control + bit + 26 + 1 + + + V + Overflow condition code + flag + 28 + 1 + + + C + Carry condition code flag + 29 + 1 + + + Z + Zero condition code flag + 30 + 1 + + + N + Negative condition code + flag + 31 + 1 + + + + + + + MPU + Memory protection unit + MPU + 0xE000ED90 + + 0x0 + 0x15 + registers + + + + TYPER + TYPER + MPU type register + 0x0 + 0x20 + read-only + 0x00000800 + + + SEPARATE + Separate flag + 0 + 1 + + + DREGION + Number of MPU data regions + 8 + 8 + + + IREGION + Number of MPU instruction + regions + 16 + 8 + + + + + CTRL + CTRL + MPU control register + 0x4 + 0x20 + read-only + 0x00000000 + + + ENABLE + Enables the MPU + 0 + 1 + + + HFNMIENA + Enables the operation of MPU during hard + fault + 1 + 1 + + + PRIVDEFENA + Enable priviliged software access to + default memory map + 2 + 1 + + + + + RNR + RNR + MPU region number register + 0x8 + 0x20 + read-write + 0x00000000 + + + REGION + MPU region + 0 + 8 + + + + + RBAR + RBAR + MPU region base address + register + 0xC + 0x20 + read-write + 0x00000000 + + + REGION + MPU region field + 0 + 4 + + + VALID + MPU region number valid + 4 + 1 + + + ADDR + Region base address field + 5 + 27 + + + + + RASR + RASR + MPU region attribute and size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + ENABLE + Region enable bit. + 0 + 1 + + + SIZE + Size of the MPU protection + region + 1 + 5 + + + SRD + Subregion disable bits + 8 + 8 + + + B + memory attribute + 16 + 1 + + + C + memory attribute + 17 + 1 + + + S + Shareable memory attribute + 18 + 1 + + + TEX + memory attribute + 19 + 3 + + + AP + Access permission + 24 + 3 + + + XN + Instruction access disable + bit + 28 + 1 + + + + + + + STK + SysTick timer + STK + 0xE000E010 + + 0x0 + 0x11 + registers + + + + CTRL + CTRL + SysTick control and status + register + 0x0 + 0x20 + read-write + 0x00000000 + + + ENABLE + Counter enable + 0 + 1 + + + TICKINT + SysTick exception request + enable + 1 + 1 + + + CLKSOURCE + Clock source selection + 2 + 1 + + + COUNTFLAG + COUNTFLAG + 16 + 1 + + + + + LOAD + LOAD + SysTick reload value register + 0x4 + 0x20 + read-write + 0x00000000 + + + RELOAD + RELOAD value + 0 + 24 + + + + + VAL + VAL + SysTick current value register + 0x8 + 0x20 + read-write + 0x00000000 + + + CURRENT + Current counter value + 0 + 24 + + + + + CALIB + CALIB + SysTick calibration value + register + 0xC + 0x20 + read-write + 0x00000000 + + + TENMS + Calibration value + 0 + 24 + + + SKEW + SKEW flag: Indicates whether the TENMS + value is exact + 30 + 1 + + + NOREF + NOREF flag. Reads as zero + 31 + 1 + + + + + + + SCB + System control block + SCB + 0xE000ED00 + + 0x0 + 0x41 + registers + + + + CPUID + CPUID + CPUID base register + 0x0 + 0x20 + read-only + 0x410FC241 + + + Revision + Revision number + 0 + 4 + + + PartNo + Part number of the + processor + 4 + 12 + + + Constant + Reads as 0xF + 16 + 4 + + + Variant + Variant number + 20 + 4 + + + Implementer + Implementer code + 24 + 8 + + + + + ICSR + ICSR + Interrupt control and state + register + 0x4 + 0x20 + read-write + 0x00000000 + + + VECTACTIVE + Active vector + 0 + 9 + + + RETTOBASE + Return to base level + 11 + 1 + + + VECTPENDING + Pending vector + 12 + 7 + + + ISRPENDING + Interrupt pending flag + 22 + 1 + + + PENDSTCLR + SysTick exception clear-pending + bit + 25 + 1 + + + PENDSTSET + SysTick exception set-pending + bit + 26 + 1 + + + PENDSVCLR + PendSV clear-pending bit + 27 + 1 + + + PENDSVSET + PendSV set-pending bit + 28 + 1 + + + NMIPENDSET + NMI set-pending bit. + 31 + 1 + + + + + VTOR + VTOR + Vector table offset register + 0x8 + 0x20 + read-write + 0x00000000 + + + TBLOFF + Vector table base offset + field + 9 + 21 + + + + + AIRCR + AIRCR + Application interrupt and reset control + register + 0xC + 0x20 + read-write + 0x00000000 + + + VECTRESET + VECTRESET + 0 + 1 + + + VECTCLRACTIVE + VECTCLRACTIVE + 1 + 1 + + + SYSRESETREQ + SYSRESETREQ + 2 + 1 + + + PRIGROUP + PRIGROUP + 8 + 3 + + + ENDIANESS + ENDIANESS + 15 + 1 + + + VECTKEYSTAT + Register key + 16 + 16 + + + + + SCR + SCR + System control register + 0x10 + 0x20 + read-write + 0x00000000 + + + SLEEPONEXIT + SLEEPONEXIT + 1 + 1 + + + SLEEPDEEP + SLEEPDEEP + 2 + 1 + + + SEVEONPEND + Send Event on Pending bit + 4 + 1 + + + + + CCR + CCR + Configuration and control + register + 0x14 + 0x20 + read-write + 0x00000000 + + + NONBASETHRDENA + Configures how the processor enters + Thread mode + 0 + 1 + + + USERSETMPEND + USERSETMPEND + 1 + 1 + + + UNALIGN__TRP + UNALIGN_ TRP + 3 + 1 + + + DIV_0_TRP + DIV_0_TRP + 4 + 1 + + + BFHFNMIGN + BFHFNMIGN + 8 + 1 + + + STKALIGN + STKALIGN + 9 + 1 + + + + + SHPR1 + SHPR1 + System handler priority + registers + 0x18 + 0x20 + read-write + 0x00000000 + + + PRI_4 + Priority of system handler + 4 + 0 + 8 + + + PRI_5 + Priority of system handler + 5 + 8 + 8 + + + PRI_6 + Priority of system handler + 6 + 16 + 8 + + + + + SHPR2 + SHPR2 + System handler priority + registers + 0x1C + 0x20 + read-write + 0x00000000 + + + PRI_11 + Priority of system handler + 11 + 24 + 8 + + + + + SHPR3 + SHPR3 + System handler priority + registers + 0x20 + 0x20 + read-write + 0x00000000 + + + PRI_14 + Priority of system handler + 14 + 16 + 8 + + + PRI_15 + Priority of system handler + 15 + 24 + 8 + + + + + SHCRS + SHCRS + System handler control and state + register + 0x24 + 0x20 + read-write + 0x00000000 + + + MEMFAULTACT + Memory management fault exception active + bit + 0 + 1 + + + BUSFAULTACT + Bus fault exception active + bit + 1 + 1 + + + USGFAULTACT + Usage fault exception active + bit + 3 + 1 + + + SVCALLACT + SVC call active bit + 7 + 1 + + + MONITORACT + Debug monitor active bit + 8 + 1 + + + PENDSVACT + PendSV exception active + bit + 10 + 1 + + + SYSTICKACT + SysTick exception active + bit + 11 + 1 + + + USGFAULTPENDED + Usage fault exception pending + bit + 12 + 1 + + + MEMFAULTPENDED + Memory management fault exception + pending bit + 13 + 1 + + + BUSFAULTPENDED + Bus fault exception pending + bit + 14 + 1 + + + SVCALLPENDED + SVC call pending bit + 15 + 1 + + + MEMFAULTENA + Memory management fault enable + bit + 16 + 1 + + + BUSFAULTENA + Bus fault enable bit + 17 + 1 + + + USGFAULTENA + Usage fault enable bit + 18 + 1 + + + + + CFSR_UFSR_BFSR_MMFSR + CFSR_UFSR_BFSR_MMFSR + Configurable fault status + register + 0x28 + 0x20 + read-write + 0x00000000 + + + IACCVIOL + Instruction access violation + flag + 1 + 1 + + + MUNSTKERR + Memory manager fault on unstacking for a + return from exception + 3 + 1 + + + MSTKERR + Memory manager fault on stacking for + exception entry. + 4 + 1 + + + MLSPERR + MLSPERR + 5 + 1 + + + MMARVALID + Memory Management Fault Address Register + (MMAR) valid flag + 7 + 1 + + + IBUSERR + Instruction bus error + 8 + 1 + + + PRECISERR + Precise data bus error + 9 + 1 + + + IMPRECISERR + Imprecise data bus error + 10 + 1 + + + UNSTKERR + Bus fault on unstacking for a return + from exception + 11 + 1 + + + STKERR + Bus fault on stacking for exception + entry + 12 + 1 + + + LSPERR + Bus fault on floating-point lazy state + preservation + 13 + 1 + + + BFARVALID + Bus Fault Address Register (BFAR) valid + flag + 15 + 1 + + + UNDEFINSTR + Undefined instruction usage + fault + 16 + 1 + + + INVSTATE + Invalid state usage fault + 17 + 1 + + + INVPC + Invalid PC load usage + fault + 18 + 1 + + + NOCP + No coprocessor usage + fault. + 19 + 1 + + + UNALIGNED + Unaligned access usage + fault + 24 + 1 + + + DIVBYZERO + Divide by zero usage fault + 25 + 1 + + + + + HFSR + HFSR + Hard fault status register + 0x2C + 0x20 + read-write + 0x00000000 + + + VECTTBL + Vector table hard fault + 1 + 1 + + + FORCED + Forced hard fault + 30 + 1 + + + DEBUG_VT + Reserved for Debug use + 31 + 1 + + + + + MMFAR + MMFAR + Memory management fault address + register + 0x34 + 0x20 + read-write + 0x00000000 + + + MMFAR + Memory management fault + address + 0 + 32 + + + + + BFAR + BFAR + Bus fault address register + 0x38 + 0x20 + read-write + 0x00000000 + + + BFAR + Bus fault address + 0 + 32 + + + + + AFSR + AFSR + Auxiliary fault status + register + 0x3C + 0x20 + read-write + 0x00000000 + + + IMPDEF + Implementation defined + 0 + 32 + + + + + + + NVIC_STIR + Nested vectored interrupt + controller + NVIC + 0xE000EF00 + + 0x0 + 0x5 + registers + + + + STIR + STIR + Software trigger interrupt + register + 0x0 + 0x20 + read-write + 0x00000000 + + + INTID + Software generated interrupt + ID + 0 + 9 + + + + + + + FPU_CPACR + Floating point unit CPACR + FPU + 0xE000ED88 + + 0x0 + 0x5 + registers + + + + CPACR + CPACR + Coprocessor access control + register + 0x0 + 0x20 + read-write + 0x00000000 + + + CP + CP + 20 + 4 + + + + + + + SCB_ACTRL + System control block ACTLR + SCB + 0xE000E008 + + 0x0 + 0x5 + registers + + + + ACTRL + ACTRL + Auxiliary control register + 0x0 + 0x20 + read-write + 0x00000000 + + + DISMCYCINT + DISMCYCINT + 0 + 1 + + + DISDEFWBUF + DISDEFWBUF + 1 + 1 + + + DISFOLD + DISFOLD + 2 + 1 + + + DISFPCA + DISFPCA + 8 + 1 + + + DISOOFP + DISOOFP + 9 + 1 + + + + + + + \ No newline at end of file From fa6d37e76368020a9c7028136c7bd499752b3f43 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 25 Sep 2024 21:33:12 +0200 Subject: [PATCH 285/687] usb_bridge: implement usb using nusb --- Cargo.lock | 44 +++++++++++++ Cargo.toml | 2 +- crates/usb_bridge/Cargo.toml | 21 +++--- crates/usb_bridge/rust-toolchain.toml | 2 +- crates/usb_bridge/src/main.rs | 95 +++++++++++++++------------ 5 files changed, 110 insertions(+), 54 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a0b10a96..6e4414ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -738,6 +738,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1620,6 +1630,23 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +[[package]] +name = "host" +version = "0.1.0" +dependencies = [ + "clap", + "color-eyre", + "data-server", + "heapless 0.8.0", + "nusb", + "protocol", + "ratelimited-logger", + "tokio", + "tracing", + "tracing-error", + "tracing-subscriber", +] + [[package]] name = "http" version = "1.1.0" @@ -2306,6 +2333,23 @@ dependencies = [ "autocfg", ] +[[package]] +name = "nusb" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d8beeee5c0ad012e1eaca540f5610d09a3af58ec435537d511b67e0be36ea66" +dependencies = [ + "atomic-waker", + "core-foundation", + "core-foundation-sys", + "io-kit-sys", + "log", + "once_cell", + "rustix", + "slab", + "windows-sys 0.48.0", +] + [[package]] name = "object" version = "0.32.2" diff --git a/Cargo.toml b/Cargo.toml index 98eb24d5..56b49124 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [workspace] resolver = "2" members = ["crates/*"] -exclude = ["sensor-nodes/bed-lb", "sensor-nodes/bed-sb/host", "sensor-nodes/bed-sb/node", "sensor-nodes/bed-sb/schema"] +exclude = ["sensor-nodes/bed-lb", "sensor-nodes/bed-sb"] [workspace.dependencies] data-server = { path = "crates/data-server" } diff --git a/crates/usb_bridge/Cargo.toml b/crates/usb_bridge/Cargo.toml index 89cada28..bf3476de 100644 --- a/crates/usb_bridge/Cargo.toml +++ b/crates/usb_bridge/Cargo.toml @@ -8,17 +8,16 @@ authors = ["David Kleingeld & Eva van Houten"] [dependencies] heapless = "0.8.0" -postcard = { version = "1.0.10", features = ["experimental-derive"] } -postcard-rpc = { version = "0.7.0", features = ["raw-nusb"] } -protocol = { path = "../../../crates/protocol" } -data-server = { path = "../../../crates/data-server", features = ["api"] } -ratelimited-logger = { path = "../../../crates/ratelimited-logger" } +protocol = { workspace = true } +data-server = { workspace = true } +ratelimited-logger = { workspace = true } -schema = { path = "../schema" } -tokio = { version = "1.40.0", features = ["macros", "net", "rt-multi-thread", "time"] } -clap = { version = "4.5.18", features = ["derive"] } -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -tracing-error = "0.2.0" -tracing = "0.1.40" +tokio = { workspace = true } +clap = { workspace = true } +tracing-subscriber = { workspace = true } +tracing-error = { workspace = true } +tracing = { workspace = true } +nusb = "0.1.10" +color-eyre.workspace = true diff --git a/crates/usb_bridge/rust-toolchain.toml b/crates/usb_bridge/rust-toolchain.toml index 42e5cea4..bd227cbf 100644 --- a/crates/usb_bridge/rust-toolchain.toml +++ b/crates/usb_bridge/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "stable" +channel = "nightly" components = [ "rust-src", "rustfmt", "llvm-tools" ] targets = [ "x86_64-unknown-linux-gnu", diff --git a/crates/usb_bridge/src/main.rs b/crates/usb_bridge/src/main.rs index a7be5d5b..5c81293d 100644 --- a/crates/usb_bridge/src/main.rs +++ b/crates/usb_bridge/src/main.rs @@ -2,16 +2,14 @@ use std::{net::SocketAddr, time::Duration}; use clap::Parser; -use postcard_rpc::{ - host_client::{HostClient, IoClosed, Subscription}, - standard_icd::{WireError, ERROR_PATH}, -}; - +use color_eyre::eyre::{eyre, Context}; +use color_eyre::Section; use data_server::api::data_source; -use schema::ProtocolMsg; -use schema::ProtocolTopic; +use nusb::transfer; use tokio::time::sleep; +use ratelimited_logger as rl; + #[derive(Parser)] #[command(name = "local sensors")] #[command(version = "1.0")] @@ -27,57 +25,73 @@ struct Cli { struct ReconnectingUsbSub { serial_number: String, - conn: Option>, - sub: Option>, + conn: Option, logger: ratelimited_logger::RateLimitedLogger, } +fn request_msg() -> transfer::ControlIn { + todo!() +} + +type EncodedProtocolMsg = Vec; + impl ReconnectingUsbSub { fn new(serial_number: String) -> Self { ReconnectingUsbSub { serial_number, conn: None, - sub: None, logger: ratelimited_logger::RateLimitedLogger::new(), } } - async fn recv(&mut self) -> ProtocolMsg { + async fn recv(&mut self) -> EncodedProtocolMsg { loop { - if let Some(sub) = &mut self.sub { - match sub.recv().await { - Some(msg) => return msg, - None => self.sub = None, - } - } - - if let Some(conn) = &mut self.conn { - match conn.subscribe::(8).await { - Ok(sub) => { - self.sub = Some(sub); - continue; - } - Err(IoClosed) => self.conn = None, - } - } - - match HostClient::try_new_raw_nusb( - |d| { - d.serial_number() - .is_some_and(|d| d.eq_ignore_ascii_case(&self.serial_number)) - }, - ERROR_PATH, - 1, - ) { - Ok(conn) => self.conn = Some(conn), + match self.try_recv_step().await { + Ok(Some(msg)) => return msg, + Ok(None) => (), Err(e) => { let logger = &mut self.logger; - ratelimited_logger::warn!(logger; "Could not connect to usbdevice: {e:?}"); + rl::warn!(logger; "{e}"); sleep(Duration::from_secs(1)).await; } } } } + + async fn try_recv_step(&mut self) -> color_eyre::Result> { + if let Some(device) = self.conn.take() { + let msg = device + .control_in(request_msg()) + .await + .into_result() + .wrap_err("Something went wrong with control_in request")?; + + self.conn = Some(device); + return Ok(Some(msg)); + } + + let list: Vec<_> = nusb::list_devices() + .wrap_err("Could not list usb devices")? + .filter(|d| { + d.serial_number() + .is_some_and(|d| d.eq_ignore_ascii_case(&self.serial_number)) + }) + .collect(); + + self.conn = match list.as_slice() { + [dev] => dev, + [] => return Err(eyre!("No usb device found with the correct serial")), + more => { + return Err(eyre!("Multiple usb devices have the same serial number") + .with_note(|| format!("they are: {more:?}"))) + } + } + .open() + .map(Option::Some) + .wrap_err("Could not open the usb device")?; + + Ok(None) // no errors but not done yet, call us again + } } #[tokio::main(flavor = "current_thread")] @@ -89,10 +103,9 @@ async fn main() { let mut server_client = data_source::reconnecting::Client::new(args.data_server, Vec::new()); loop { - let msg = usb.recv().await; - let encoded_protocol_msg = msg.0; + let encoded_msg = usb.recv().await; server_client - .check_send_encoded(&encoded_protocol_msg) + .check_send_encoded(&encoded_msg) .await .expect("Should be correctly encoded"); } From 32793eaf403b323496b4ee8aee324bdbee7a7e31 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 25 Sep 2024 21:33:26 +0200 Subject: [PATCH 286/687] rename --- crates/{usb_bridge => usb-bridge}/.cargo/config.toml | 0 crates/{usb_bridge => usb-bridge}/Cargo.lock | 0 crates/{usb_bridge => usb-bridge}/Cargo.toml | 0 crates/{usb_bridge => usb-bridge}/rust-toolchain.toml | 0 crates/{usb_bridge => usb-bridge}/src/main.rs | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename crates/{usb_bridge => usb-bridge}/.cargo/config.toml (100%) rename crates/{usb_bridge => usb-bridge}/Cargo.lock (100%) rename crates/{usb_bridge => usb-bridge}/Cargo.toml (100%) rename crates/{usb_bridge => usb-bridge}/rust-toolchain.toml (100%) rename crates/{usb_bridge => usb-bridge}/src/main.rs (100%) diff --git a/crates/usb_bridge/.cargo/config.toml b/crates/usb-bridge/.cargo/config.toml similarity index 100% rename from crates/usb_bridge/.cargo/config.toml rename to crates/usb-bridge/.cargo/config.toml diff --git a/crates/usb_bridge/Cargo.lock b/crates/usb-bridge/Cargo.lock similarity index 100% rename from crates/usb_bridge/Cargo.lock rename to crates/usb-bridge/Cargo.lock diff --git a/crates/usb_bridge/Cargo.toml b/crates/usb-bridge/Cargo.toml similarity index 100% rename from crates/usb_bridge/Cargo.toml rename to crates/usb-bridge/Cargo.toml diff --git a/crates/usb_bridge/rust-toolchain.toml b/crates/usb-bridge/rust-toolchain.toml similarity index 100% rename from crates/usb_bridge/rust-toolchain.toml rename to crates/usb-bridge/rust-toolchain.toml diff --git a/crates/usb_bridge/src/main.rs b/crates/usb-bridge/src/main.rs similarity index 100% rename from crates/usb_bridge/src/main.rs rename to crates/usb-bridge/src/main.rs From b50a8193db0c6c599b5e0b0b67844561196c63e6 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 25 Sep 2024 22:09:11 +0200 Subject: [PATCH 287/687] clippy lints fixed --- crates/brain/src/controller/rooms/kitchen.rs | 15 ++++++----- .../src/controller/rooms/small_bedroom.rs | 15 ++++++----- crates/brain/src/input/api.rs | 17 +++++------- crates/brain/src/input/jobs.rs | 14 +++++----- crates/brain/src/input/jobs/wakeup.rs | 13 ++++------ crates/brain/src/main.rs | 1 - .../brain/src/system/lamps/bridge_connect.rs | 14 +++++----- .../lamps/eventually_consistent_bridge.rs | 10 +++---- crates/brain/src/system/lamps/lamp.rs | 5 ++-- crates/brain/src/system/lamps/mod.rs | 5 ++-- crates/data-server/src/api/data_source.rs | 4 +-- .../src/api/data_source/reconnecting.rs | 2 +- crates/desk-sensors/src/sensors.rs | 5 ++-- crates/log-store/src/server/db/log.rs | 1 + crates/protocol/src/large_bedroom/bed.rs | 1 + crates/protocol/src/small_bedroom/bed.rs | 1 + crates/protocol/src/small_bedroom/desk.rs | 1 + crates/ratelimited-logger/src/lib.rs | 6 +++-- crates/rpc/src/server.rs | 6 ++--- crates/sensor-tui/src/control.rs | 6 ++--- crates/sensor-tui/src/fetch.rs | 9 +++---- crates/sensor-tui/src/main.rs | 19 +++++++------- crates/sensor-tui/src/tui/affectors.rs | 6 ++--- .../src/tui/affectors/handle_key.rs | 2 +- crates/sensor-tui/src/tui/affectors/render.rs | 26 +++++++++---------- .../src/tui/readings/history_len.rs | 2 +- crates/sensor-tui/src/tui/readings/render.rs | 6 ++--- .../src/tui/readings/render/chart/labels.rs | 6 ++--- .../src/tui/readings/render/logs.rs | 4 +-- .../src/tui/readings/sensor_info.rs | 4 +-- .../src/tui/readings/sensor_info/logs.rs | 3 +-- crates/sensor-tui/src/tui/render.rs | 4 +-- crates/sensor-tui/src/tui/reports.rs | 6 ++--- crates/usb-bridge/src/main.rs | 2 +- 34 files changed, 114 insertions(+), 127 deletions(-) diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index 2609fbca..c2846d47 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -36,13 +36,14 @@ enum RelevantEvent { // DeskButton(protocol::large_bedroom::DeskButton), } -fn filter(event: Event) -> Option { - match event { - // Event::Sensor(SensorValue::ButtonPress(Button::LargeBedroomDesk(desk))) => { - // Some(RelevantEvent::DeskButton(desk)) - // } - _ => None, - } +fn filter(_event: Event) -> Option { + // match event { + // // Event::Sensor(SensorValue::ButtonPress(Button::LargeBedroomDesk(desk))) => { + // // Some(RelevantEvent::DeskButton(desk)) + // // } + // _ => None, + // } + None } pub async fn run( diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 7c1c88aa..3fd214e8 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -36,13 +36,14 @@ enum RelevantEvent { // DeskButton(protocol::large_bedroom::DeskButton), } -fn filter(event: Event) -> Option { - match event { - // Event::Sensor(SensorValue::ButtonPress(Button::LargeBedroomDesk(desk))) => { - // Some(RelevantEvent::DeskButton(desk)) - // } - _ => None, - } +fn filter(_event: Event) -> Option { + // match event { + // // Event::Sensor(SensorValue::ButtonPress(Button::LargeBedroomDesk(desk))) => { + // // Some(RelevantEvent::DeskButton(desk)) + // // } + // _ => None, + // } + None } pub async fn run( diff --git a/crates/brain/src/input/api.rs b/crates/brain/src/input/api.rs index 42d35e29..b8041ce2 100644 --- a/crates/brain/src/input/api.rs +++ b/crates/brain/src/input/api.rs @@ -17,22 +17,20 @@ pub enum Error { /// sends back bincode serialized async fn usually(aState(state): aState) -> Vec { let usually = state.wakeup.usually().await; - let usually = bincode::serialize(&usually).expect("Should be serializable"); - usually + bincode::serialize(&usually).expect("Should be serializable") } /// sends back bincode serialized async fn tomorrow(aState(state): aState) -> Vec { - let usually = state.wakeup.tomorrow().await; - let usually = bincode::serialize(&usually).expect("Should be serializable"); - usually + let tomorrow = state.wakeup.tomorrow().await; + bincode::serialize(&tomorrow).expect("Should be serializable") } async fn set_usually(aState(state): aState, body: Bytes) -> StatusCode { let time: Option<(u8, u8)> = bincode::deserialize(&body[..]) .map_err(|_| "Could not deserialize into time") .unwrap(); - let _ignore = state + state .wakeup .set_usually(time) .await @@ -46,7 +44,7 @@ async fn set_tomorrow(aState(state): aState, body: Bytes) -> StatusCode { let time: Option<(u8, u8)> = bincode::deserialize(&body[..]) .map_err(|_| "Could not deserialize into time") .unwrap(); - let _ignore = state + state .wakeup .set_tomorrow(time) .await @@ -61,10 +59,7 @@ pub struct State { wakeup: WakeUp, } -pub async fn setup( - wakeup: WakeUp, - port: u16, -) -> Result<(), Error> { +pub async fn setup(wakeup: WakeUp, port: u16) -> Result<(), Error> { let app = Router::new() .route("/alarm/usually", get(usually).post(set_usually)) .route("/alarm/tomorrow", get(tomorrow).post(set_tomorrow)) diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index 58f5764d..535ac087 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -40,7 +40,7 @@ impl Job { ) -> Self { Job { time, - event: event.into(), + event, expiration, } } @@ -111,12 +111,10 @@ fn waker( } else { //no alarm to wait on, wait for instructions info!("no alarm in the future"); - loop { - //A message through the mpsc signals an alarm has been added - match waker_rx.recv() { - Ok(_) => break, //alarms were added or remove, go back and start waiting on it - Err(_) => return, //cant have timed out thus program should exit - } + //A message through the mpsc signals an alarm has been added + match waker_rx.recv() { + Ok(_) => break, //alarms were added or remove, go back and start waiting on it + Err(_) => return, //cant have timed out thus program should exit } } } @@ -190,7 +188,7 @@ impl JobList { //self.db.cas(&[1], None as Option<&[u8]>, Some(&[10]) //TODO check how this works and expand sled documentation for fail cases while let Err(_old_event) = self.db.compare_and_swap( - ×tamp_array, + timestamp_array, None as Option<&[u8]>, Some(alarm.clone()), )? { diff --git a/crates/brain/src/input/jobs/wakeup.rs b/crates/brain/src/input/jobs/wakeup.rs index 8bf40bf1..694c3721 100644 --- a/crates/brain/src/input/jobs/wakeup.rs +++ b/crates/brain/src/input/jobs/wakeup.rs @@ -93,13 +93,12 @@ impl Inner { let usually = db .get("usually")? - .map(|b| bincode::deserialize(&b).unwrap()) - .flatten(); // we want bincode to deserialize to Option<(u8,u8)> not (u8,u8) + // we want bincode to deserialize to Option<(u8,u8)> not (u8,u8) + .and_then(|b| bincode::deserialize(&b).unwrap()); let job_id = db.get("job_id")?.map(|b| bincode::deserialize(&b).unwrap()); let next_alarm = job_id .as_ref() - .map(|id| jobs.get(*id).unwrap()) - .flatten() + .and_then(|id| jobs.get(*id).unwrap()) .map(|job| job.time.into()) .map(|t: DateTime| t) .map(|t| (t.hour() as u8, t.minute() as u8)); @@ -178,10 +177,8 @@ impl Inner { self.replace_job(job).await?; } None => { - if self.job_id.is_some() { - if self.tomorrow.is_none() { - self.remove_job()?; - } + if self.job_id.is_some() && self.tomorrow.is_none() { + self.remove_job()?; } } } diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index 0b9f4046..ffcef047 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -2,7 +2,6 @@ use std::array; use std::net::{IpAddr, SocketAddr}; use clap::Parser; -use sled; use tokio::sync::broadcast; use tracing::warn; diff --git a/crates/brain/src/system/lamps/bridge_connect.rs b/crates/brain/src/system/lamps/bridge_connect.rs index e63408af..5a9525f5 100644 --- a/crates/brain/src/system/lamps/bridge_connect.rs +++ b/crates/brain/src/system/lamps/bridge_connect.rs @@ -36,12 +36,12 @@ async fn register(ip: IpAddr) -> Result { } } } - return Err(RegisterError::Timedout); + Err(RegisterError::Timedout) } fn saved_bridge_info() -> Result<(String, String), ()> { let path = Path::new("hueBridgeLogin"); - match File::open(&path) { + match File::open(path) { Err(e) => error!("find ip and login file, error: {}", e), Ok(f) => match serde_yaml::from_reader(f) { Ok((ip, login)) => return Ok((ip, login)), @@ -63,7 +63,7 @@ pub enum SaveBridgeError { } fn update_saved_bridge_info(bridge_ip: IpAddr, login: &str) -> Result<(), SaveBridgeError> { let path = Path::new("hueBridgeLogin"); - let file = File::create(&path).map_err(|err| SaveBridgeError::CreatingFile { err, path })?; + let file = File::create(path).map_err(|err| SaveBridgeError::CreatingFile { err, path })?; serde_yaml::to_writer(file, &(bridge_ip, login)).map_err(SaveBridgeError::Writing) } @@ -72,8 +72,8 @@ pub async fn get_bridge_and_status( ) -> Result<(Bridge, Vec), Error> { let ip: IpAddr = ip.parse().expect("string should be an ip"); let Ok((ip, login)) = saved_bridge_info() else { - let bridge = register(ip.clone()).await?; - update_saved_bridge_info(ip.clone(), &bridge.username)?; + let bridge = register(ip).await?; + update_saved_bridge_info(ip, &bridge.username)?; let lights_info = bridge .get_all_lights() @@ -89,8 +89,8 @@ pub async fn get_bridge_and_status( match res { Ok(lights_info) => Ok((bridge, lights_info)), Err(_) => { - let bridge = register(ip.clone()).await?; - update_saved_bridge_info(ip.clone(), &bridge.username)?; + let bridge = register(ip).await?; + update_saved_bridge_info(ip, &bridge.username)?; let lights_info = bridge .get_all_lights() diff --git a/crates/brain/src/system/lamps/eventually_consistent_bridge.rs b/crates/brain/src/system/lamps/eventually_consistent_bridge.rs index bb3b851d..1331b3d2 100644 --- a/crates/brain/src/system/lamps/eventually_consistent_bridge.rs +++ b/crates/brain/src/system/lamps/eventually_consistent_bridge.rs @@ -128,7 +128,7 @@ impl CachedBridge { } Change::Off { name } => { let Some(lamp_id) = self.lookup.get(*name) else { - self.report_missing_if_not_reported_yet(*name); + self.report_missing_if_not_reported_yet(name); return; }; if let Some(lamp) = self.needed_state.get_mut(lamp_id) { @@ -139,10 +139,10 @@ impl CachedBridge { } Change::On { name } => { let Some(lamp_id) = self.lookup.get(*name) else { - self.report_missing_if_not_reported_yet(*name); + self.report_missing_if_not_reported_yet(name); return; }; - if let Some(lamp) = self.needed_state.get_mut(&lamp_id) { + if let Some(lamp) = self.needed_state.get_mut(lamp_id) { lamp.on = true; } else { error!("no lamp with id: {lamp_id} exists"); @@ -150,7 +150,7 @@ impl CachedBridge { } Change::CtBri { name, bri, ct } => { let Some(lamp_id) = self.lookup.get(*name) else { - self.report_missing_if_not_reported_yet(*name); + self.report_missing_if_not_reported_yet(name); return; }; if let Some(lamp) = self.needed_state.get_mut(lamp_id) { @@ -161,7 +161,7 @@ impl CachedBridge { } Change::XyBri { name, bri, xy } => { let Some(lamp_id) = self.lookup.get(*name) else { - self.report_missing_if_not_reported_yet(*name); + self.report_missing_if_not_reported_yet(name); return; }; if let Some(lamp) = self.needed_state.get_mut(lamp_id) { diff --git a/crates/brain/src/system/lamps/lamp.rs b/crates/brain/src/system/lamps/lamp.rs index 513f92ea..0b90e5d8 100644 --- a/crates/brain/src/system/lamps/lamp.rs +++ b/crates/brain/src/system/lamps/lamp.rs @@ -17,14 +17,13 @@ impl Lamp { let mut light_cmd = CommandLight::default().with_bri(self.bri); light_cmd.on = Some(self.on); - let light_cmd = if let Some((x, y)) = self.xy { + if let Some((x, y)) = self.xy { light_cmd.with_xy(x, y) } else if let Some(ct) = self.ct { light_cmd.with_ct(ct) } else { unreachable!("lamp must have ct or xy set"); - }; - light_cmd + } } } diff --git a/crates/brain/src/system/lamps/mod.rs b/crates/brain/src/system/lamps/mod.rs index 525c3883..c49b62b9 100644 --- a/crates/brain/src/system/lamps/mod.rs +++ b/crates/brain/src/system/lamps/mod.rs @@ -99,9 +99,8 @@ impl Lighting { .send((tx, Change::AllXY { bri, xy })) .expect("manage_bridge should never return"); - let res = rx.blocking_recv().expect( + rx.blocking_recv().expect( "managed_bridge should not crash and thus not drop the receive end of the channel", - ); - res + ) } } diff --git a/crates/data-server/src/api/data_source.rs b/crates/data-server/src/api/data_source.rs index 6a7ff4df..bbf34034 100644 --- a/crates/data-server/src/api/data_source.rs +++ b/crates/data-server/src/api/data_source.rs @@ -103,7 +103,7 @@ pub enum SendPreEncodedError { impl Sender { pub(crate) async fn send_bytes(&mut self, bytes: &[u8]) -> Result<(), std::io::Error> { - self.0.write_all(&bytes).await + self.0.write_all(bytes).await } pub async fn send_reading(&mut self, reading: protocol::Reading) -> Result<(), std::io::Error> { @@ -138,7 +138,7 @@ impl Receiver { pub async fn receive(&mut self) -> Result { loop { if !self.buffer.is_empty() { - if let Some((item, remaining)) = self.decoder.feed(&mut self.buffer) { + if let Some((item, remaining)) = self.decoder.feed(&self.buffer) { let new_buffer = remaining.to_vec(); self.buffer = new_buffer; return Ok(item); diff --git a/crates/data-server/src/api/data_source/reconnecting.rs b/crates/data-server/src/api/data_source/reconnecting.rs index 672b529d..7a7f38e1 100644 --- a/crates/data-server/src/api/data_source/reconnecting.rs +++ b/crates/data-server/src/api/data_source/reconnecting.rs @@ -78,7 +78,7 @@ impl Client { pub async fn check_send_encoded(&mut self, msg: &[u8]) -> Result<(), SendPreEncodedError> { protocol::Msg::<50>::decode(msg.to_vec()).map_err(SendPreEncodedError::EncodingCheck)?; - self.send_bytes(&msg).await; + self.send_bytes(msg).await; Ok(()) } } diff --git a/crates/desk-sensors/src/sensors.rs b/crates/desk-sensors/src/sensors.rs index 7353f9db..80fee774 100644 --- a/crates/desk-sensors/src/sensors.rs +++ b/crates/desk-sensors/src/sensors.rs @@ -16,16 +16,17 @@ use tokio::sync::mpsc::Sender; use crate::bedroom; +#[allow(clippy::result_large_err)] // its send directly after pub fn init() -> Result, ErrorString> { let i2c_bus = I2cdev::new("/dev/i2c-1") .inspect_err(|e| tracing::error!("Could not open i2c bus: {e}")) - .map_err(|e| protocol::make_error_string(e))?; + .map_err(protocol::make_error_string)?; let mut bme280 = Bme280::new_primary(i2c_bus); bme280 .init(&mut Delay) .inspect_err(|e| tracing::error!("Could not init bme280 sensor: {e}")) - .map_err(|e| protocol::make_error_string(e))?; + .map_err(protocol::make_error_string)?; Ok(bme280) } diff --git a/crates/log-store/src/server/db/log.rs b/crates/log-store/src/server/db/log.rs index c2546528..40acd04c 100644 --- a/crates/log-store/src/server/db/log.rs +++ b/crates/log-store/src/server/db/log.rs @@ -39,6 +39,7 @@ impl CurrentError { .read(true) .write(true) .create(true) + .truncate(false) .open(path) .wrap_err("Could not open or create on disk backup")?; let mut buf = Vec::new(); diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 447fe02e..678c5933 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -522,6 +522,7 @@ pub enum Affector { impl Affector { #[must_use] pub fn is_same_as(&self, other: &Self) -> bool { + #[allow(clippy::match_like_matches_macro)] match (self, other) { (Affector::Sps30FanClean, Affector::Sps30FanClean) => true, (Affector::MhzZeroPointCalib, Affector::MhzZeroPointCalib) => true, diff --git a/crates/protocol/src/small_bedroom/bed.rs b/crates/protocol/src/small_bedroom/bed.rs index 9e6511aa..5397037c 100644 --- a/crates/protocol/src/small_bedroom/bed.rs +++ b/crates/protocol/src/small_bedroom/bed.rs @@ -485,6 +485,7 @@ pub enum Affector { impl Affector { #[must_use] pub fn is_same_as(&self, other: &Self) -> bool { + #[allow(clippy::match_like_matches_macro)] match (self, other) { (Affector::Sps30FanClean, Affector::Sps30FanClean) => true, (Affector::MhzZeroPointCalib, Affector::MhzZeroPointCalib) => true, diff --git a/crates/protocol/src/small_bedroom/desk.rs b/crates/protocol/src/small_bedroom/desk.rs index 3325e032..28bc2c3e 100644 --- a/crates/protocol/src/small_bedroom/desk.rs +++ b/crates/protocol/src/small_bedroom/desk.rs @@ -74,6 +74,7 @@ impl Tree for Reading { impl Reading { #[must_use] pub fn is_same_as(&self, other: &Self) -> bool { + #[allow(clippy::match_like_matches_macro)] match (self, other) { (Reading::Temperature(_), Self::Temperature(_)) | (Reading::Humidity(_), Self::Humidity(_)) diff --git a/crates/ratelimited-logger/src/lib.rs b/crates/ratelimited-logger/src/lib.rs index 8211e259..03998f6d 100644 --- a/crates/ratelimited-logger/src/lib.rs +++ b/crates/ratelimited-logger/src/lib.rs @@ -44,8 +44,8 @@ macro_rules! info { }; } -impl RateLimitedLogger { - pub fn new() -> Self { +impl Default for RateLimitedLogger { + fn default() -> Self { let quota = Quota::with_period(Duration::from_secs(1)) .unwrap() .allow_burst(NonZeroU32::new(5).unwrap()); @@ -54,7 +54,9 @@ impl RateLimitedLogger { withheld: 0, } } +} +impl RateLimitedLogger { pub fn warn(&mut self, txt: &str) { if self.rate_limiter.check().is_err() { self.withheld += 1; diff --git a/crates/rpc/src/server.rs b/crates/rpc/src/server.rs index cfdb2b0e..9b94b46e 100644 --- a/crates/rpc/src/server.rs +++ b/crates/rpc/src/server.rs @@ -29,7 +29,7 @@ type Conn = tokio_serde::Framed< pub async fn run( port: u16, perform_request: impl Fn(RpcReq, &str) -> PerfFut + Clone + Send + 'static, - sub_handler: Option + Clone + Send + 'static>, + sub_handler: Option + Clone + 'static>, ) -> color_eyre::Result<()> where RpcReq: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, @@ -44,7 +44,7 @@ where .await .wrap_err("Could not bind to address") .with_note(|| format!("port: {port}"))?; - let mut logger = RateLimitedLogger::new(); + let mut logger = RateLimitedLogger::default(); loop { let (socket, source) = match listener.accept().await { @@ -125,7 +125,7 @@ async fn handle_client( mut conn: Conn, client_name: String, perform_request: impl Fn(RpcReq, &str) -> PerfFut + Clone + Send + 'static, - mut sub_handler: Option + Send + 'static>, + mut sub_handler: Option + 'static>, ) where RpcReq: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, RpcResp: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, diff --git a/crates/sensor-tui/src/control.rs b/crates/sensor-tui/src/control.rs index baf4b0da..c0a85da8 100644 --- a/crates/sensor-tui/src/control.rs +++ b/crates/sensor-tui/src/control.rs @@ -26,10 +26,8 @@ pub(crate) async fn watch_and_send(data_server: SocketAddr, mut rx: mpsc::Receiv error!("Could not actuate affector: {e:?}"); } connected_client = Some(client) - } else { - if let Ok(c) = Client::connect(data_server, client_name()).await { - connected_client = Some(c) - } + } else if let Ok(c) = Client::connect(data_server, client_name()).await { + connected_client = Some(c) } } } diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index 3ef45962..65e00732 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -88,7 +88,7 @@ impl Fetch { pub fn assure_up_to_date( &mut self, history_len: Duration, - on_fetch_start: impl FnOnce() -> (), + on_fetch_start: impl FnOnce(), reading: Reading, oldest_in_data: Timestamp, logs_cover_from: Timestamp, @@ -128,11 +128,11 @@ impl Fetch { oldest_in_history: Timestamp, ) -> bool { let target_span = Timestamp::now() - oldest_needed; - let target_span = target_span.total(Unit::Millisecond).expect("fits i64"); - let max_span = (target_span as f64 * 1.2) as i64; + let target_span = target_span.total(Unit::Millisecond).expect("fits f64"); + let max_span = (target_span * 1.2) as i64; let oldest_allowed = Timestamp::now().as_millisecond() - max_span; - let up_to_date = |start: &i64| *start >= oldest_allowed as i64; + let up_to_date = |start: &i64| *start >= oldest_allowed; let curr_up_to_date = up_to_date(&oldest_in_history.as_millisecond()); let curr_range_correct = oldest_in_history <= oldest_needed; @@ -219,7 +219,6 @@ pub(crate) async fn handle_requests( let mut inflight_request = VecDeque::new(); while let Some(request) = rx.recv().await { - let data_store = data_store.clone(); let tx = tx.clone(); let handle = match request { Request::Data(Data { reading, range }) => { diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index 7c963cc7..523dc275 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -6,10 +6,10 @@ use std::thread; use clap::Parser; use color_eyre::Result; -mod receive; -mod fetch; mod control; +mod fetch; mod populate; +mod receive; mod time; mod tui; @@ -57,8 +57,6 @@ enum Update { PopulateError(color_eyre::Report), } - - #[derive(Parser)] #[command(name = "sensor tui")] #[command(version = "1.0")] @@ -98,13 +96,16 @@ async fn main() -> Result<()> { thread::spawn(move || tui::run(rx1, tx2, tx3, fetcher)); task::spawn(receive::receive_data(data_server, tx1_clone1)); - task::spawn(populate::tree(data_server, data_store, log_store, tx1_clone2)); + task::spawn(populate::tree( + data_server, + data_store, + log_store, + tx1_clone2, + )); task::spawn(control::watch_and_send(data_server, rx3)); - loop { - let UserIntent::Shutdown = rx2.recv()?; - break Ok(()); - } + let UserIntent::Shutdown = rx2.recv()?; + Ok(()) } fn setup_tracing() -> Result<()> { diff --git a/crates/sensor-tui/src/tui/affectors.rs b/crates/sensor-tui/src/tui/affectors.rs index a4e1c5aa..95505780 100644 --- a/crates/sensor-tui/src/tui/affectors.rs +++ b/crates/sensor-tui/src/tui/affectors.rs @@ -52,7 +52,7 @@ impl Tab { if let Some(ref mut data) = data { let [top, bottom] = Layout::vertical([Constraint::Fill(1), Constraint::Fill(1)]).areas(right); - render::details(frame, &data, top); + render::details(frame, data, top); render::controls(frame, data, bottom); }; render::footer(frame, footer, data, theme) @@ -154,14 +154,14 @@ impl Tab { add_leaf(text, tree, key); self.data .entry(key) - .and_modify(|state| state.affector = affector.clone()) + .and_modify(|state| state.affector = *affector) .and_modify(|state| { if controller.is_some() { state.last_controlled_by = controller.clone(); } }) .or_insert(AffectorState { - affector: affector.clone(), + affector: *affector, info, selected_control: 0, last_controlled_by: controller, diff --git a/crates/sensor-tui/src/tui/affectors/handle_key.rs b/crates/sensor-tui/src/tui/affectors/handle_key.rs index 393d3e60..6e4989a7 100644 --- a/crates/sensor-tui/src/tui/affectors/handle_key.rs +++ b/crates/sensor-tui/src/tui/affectors/handle_key.rs @@ -32,7 +32,7 @@ pub(crate) fn handle( }; core::mem::drop(controls); - match control_tx.try_send(state.affector.clone()) { + match control_tx.try_send(state.affector) { Ok(_) => (), Err(TrySendError::Full(_)) => warn!("control lagging behind ui inputs"), Err(TrySendError::Closed(_)) => error!("control lost connection to data-server"), diff --git a/crates/sensor-tui/src/tui/affectors/render.rs b/crates/sensor-tui/src/tui/affectors/render.rs index a850cec7..9220a440 100644 --- a/crates/sensor-tui/src/tui/affectors/render.rs +++ b/crates/sensor-tui/src/tui/affectors/render.rs @@ -58,7 +58,7 @@ pub(crate) fn controls(frame: &mut Frame, data: &mut &mut AffectorState, bottom: let constraints = iter::once(Constraint::Max(1)).chain(controls.iter().map(|_| Constraint::Max(3))); let layout = Layout::default().constraints(constraints).split(bottom); - let mut layout = layout.into_iter(); + let mut layout = layout.iter(); frame.render_widget( Block::new().title("Controls").borders(Borders::TOP), @@ -75,7 +75,7 @@ pub(crate) fn controls(frame: &mut Frame, data: &mut &mut AffectorState, bottom: frame, *layout, control.name, - &valid_range, + valid_range, *value, is_selected, ), @@ -130,19 +130,17 @@ pub(crate) fn footer( let mut footer = Vec::new(); use affector::ControlValue as C; - match data { - Some(AffectorState { - affector, - selected_control, - .. - }) => { - footer.push("u/d: select prev/next"); - match affector.controls()[*selected_control].value { - C::Trigger => footer.push("t: trigger affector"), - C::SetNum { .. } => footer.push("f/b increase/decrease"), - } + if let Some(AffectorState { + affector, + selected_control, + .. + }) = data + { + footer.push("u/d: select prev/next"); + match affector.controls()[*selected_control].value { + C::Trigger => footer.push("t: trigger affector"), + C::SetNum { .. } => footer.push("f/b increase/decrease"), } - None => (), } let footer = footer.join(" "); diff --git a/crates/sensor-tui/src/tui/readings/history_len.rs b/crates/sensor-tui/src/tui/readings/history_len.rs index 05cedeaf..4b8729c0 100644 --- a/crates/sensor-tui/src/tui/readings/history_len.rs +++ b/crates/sensor-tui/src/tui/readings/history_len.rs @@ -64,7 +64,7 @@ impl HistoryLen { pub(crate) fn style_left_x_label(&self, org_label: Span<'static>) -> Span<'static> { let mut text = self.text_input.clone(); if self.editing { - text.push_str("_"); + text.push('_'); } match self.state { State::Empty => { diff --git a/crates/sensor-tui/src/tui/readings/render.rs b/crates/sensor-tui/src/tui/readings/render.rs index 47f4265f..7a2297a6 100644 --- a/crates/sensor-tui/src/tui/readings/render.rs +++ b/crates/sensor-tui/src/tui/readings/render.rs @@ -112,7 +112,7 @@ pub fn graph_hist_logs( .flex(Flex::Legacy) .split(layout); - let mut layout = layout.into_iter().cloned(); + let mut layout = layout.iter().cloned(); if let Some(chart) = chart { chart::render(frame, layout.next().unwrap(), app, chart); @@ -150,7 +150,7 @@ pub fn graph_hist_logs( } fn render_histogram(frame: &mut Frame, lower: Rect, percentiles: &[Percentile]) { - let histogram = histogram_bars(&percentiles); + let histogram = histogram_bars(percentiles); let barchart = BarChart::default() .block(Block::bordered().title("Histogram")) .data(BarGroup::default().bars(&histogram)) @@ -160,7 +160,7 @@ fn render_histogram(frame: &mut Frame, lower: Rect, percentiles: &[Percentile]) fn histogram_bars(percentiles: &[log_store::api::Percentile]) -> Vec> { percentiles - .into_iter() + .iter() .map( |log_store::api::Percentile { bucket_ends, diff --git a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs index c0c242ee..81065692 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs @@ -11,7 +11,7 @@ use super::Bounds; type Labels = Vec>; -pub fn labels<'a>( +pub fn labels( chart: &ChartParts, layout: Rect, x_bounds: Bounds, @@ -61,7 +61,5 @@ fn evenly_spaced_labels( let n_labels = max_labels.min(steps_in_data as u16).max(2); let y_spacing = (bounds[1] - bounds[0]) / n_labels as f64; - (0..=n_labels) - .into_iter() - .map(move |i| bounds[0] + y_spacing * i as f64) + (0..=n_labels).map(move |i| bounds[0] + y_spacing * i as f64) } diff --git a/crates/sensor-tui/src/tui/readings/render/logs.rs b/crates/sensor-tui/src/tui/readings/render/logs.rs index 4feb3bcf..a8ff1f60 100644 --- a/crates/sensor-tui/src/tui/readings/render/logs.rs +++ b/crates/sensor-tui/src/tui/readings/render/logs.rs @@ -135,8 +135,8 @@ pub fn render_table( }; let item = [format!("{error}"), start, end]; item.into_iter() - .map(|content| Text::from(content)) - .map(|content| Cell::from(content)) + .map(Text::from) + .map(Cell::from) .collect::() .style(Style::new().fg(Color::Black).bg(color)) .height(1) diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index 27ef6237..9ead59ef 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -271,7 +271,7 @@ impl Readings { pub(crate) fn populate_from_device_list(&mut self, list: Vec) { for reading in list.iter().flat_map(|d| d.info().affects_readings) { - self.update_tree(&reading, IsPlaceholder::Yes); + self.update_tree(reading, IsPlaceholder::Yes); self.record_missing_data(reading.clone()); } } @@ -434,7 +434,7 @@ impl Readings { match fetched { Fetchable::Data { timestamps, data } => { sensorinfo.history_from_store = - timestamps.into_iter().zip(data.into_iter()).collect(); + timestamps.into_iter().zip(data).collect(); } Fetchable::Logs { logs, start_at } => { sensorinfo.logs.from_store = Some(logs::FromStore { diff --git a/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs b/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs index ae20d5a6..47965052 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs @@ -92,8 +92,7 @@ impl Logs { .from_store .as_ref() .map(|FromStore { list, .. }| list) - .map(|list| list.last()) - .flatten() + .and_then(|list| list.last()) .map(|ErrorEvent { start, .. }| *start) .unwrap_or(jiff::Timestamp::from_second(0).unwrap()); let without_duplicates = self diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/sensor-tui/src/tui/render.rs index f15fa934..1eda547a 100644 --- a/crates/sensor-tui/src/tui/render.rs +++ b/crates/sensor-tui/src/tui/render.rs @@ -7,14 +7,14 @@ use super::App; pub(super) fn render(frame: &mut Frame, app: &App) -> Rect { let report_needs_lines = app.reports.needed_lines(); let constraints = report_needs_lines - .map(|l| Constraint::Max(l)) + .map(Constraint::Max) .into_iter() .chain([Constraint::Min(1), Constraint::Fill(1)]); let layout = Layout::default() .constraints(constraints) .flex(Flex::Legacy) .split(frame.area()); - let mut layout = layout.into_iter(); + let mut layout = layout.iter(); if report_needs_lines.is_some() { app.reports diff --git a/crates/sensor-tui/src/tui/reports.rs b/crates/sensor-tui/src/tui/reports.rs index f412e756..edff9c74 100644 --- a/crates/sensor-tui/src/tui/reports.rs +++ b/crates/sensor-tui/src/tui/reports.rs @@ -63,7 +63,7 @@ impl Reports { .expect("should only be called when current is Some/needed lines > 0"); let [hint, error] = - Layout::vertical(&[Constraint::Max(1), Constraint::Min(1)]).areas(layout); + Layout::vertical([Constraint::Max(1), Constraint::Min(1)]).areas(layout); let error_style = Style::default().on_light_red().fg(Color::White); @@ -92,9 +92,7 @@ impl Reports { } pub(super) fn needed_lines(&self) -> Option { - let Some(ref current) = self.current else { - return None; - }; + let current = self.current.as_ref()?; Some(if self.show_details { 1 + current.detailed.lines().count() as u16 diff --git a/crates/usb-bridge/src/main.rs b/crates/usb-bridge/src/main.rs index 5c81293d..f691273c 100644 --- a/crates/usb-bridge/src/main.rs +++ b/crates/usb-bridge/src/main.rs @@ -40,7 +40,7 @@ impl ReconnectingUsbSub { ReconnectingUsbSub { serial_number, conn: None, - logger: ratelimited_logger::RateLimitedLogger::new(), + logger: ratelimited_logger::RateLimitedLogger::default(), } } From ec8f33a39213ee3b038ca5749678c2606eb206d6 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 25 Sep 2024 22:30:01 +0200 Subject: [PATCH 288/687] refactor size of protocol::Msg to protocol::Msg::max_size --- crates/protocol/src/msg.rs | 15 +++++++++++++++ crates/usb-bridge/src/main.rs | 11 +++++++++-- sensor-nodes/bed-sb/Cargo.toml | 2 +- sensor-nodes/bed-sb/src/usb_wrapper.rs | 15 ++------------- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/crates/protocol/src/msg.rs b/crates/protocol/src/msg.rs index 01b0615d..f135a3d2 100644 --- a/crates/protocol/src/msg.rs +++ b/crates/protocol/src/msg.rs @@ -16,6 +16,21 @@ impl Msg { pub const ERROR_REPORT: u8 = 2; pub const AFFECTOR_LIST: u8 = 3; + #[must_use] + pub const fn max_size() -> usize { + const fn max(a: usize, b: usize) -> usize { + [a, b][(a < b) as usize] + } + + 1 + max( + max( + sensor::SensorMessage::::ENCODED_SIZE, + error::ErrorReport::ENCODED_SIZE, + ), + affector::ListMessage::<5>::ENCODED_SIZE, + ) + } + #[must_use] pub fn header(&self) -> u8 { let header = match self { diff --git a/crates/usb-bridge/src/main.rs b/crates/usb-bridge/src/main.rs index f691273c..4d9dc92e 100644 --- a/crates/usb-bridge/src/main.rs +++ b/crates/usb-bridge/src/main.rs @@ -16,7 +16,7 @@ use ratelimited_logger as rl; #[command(about = "reads sensors attached to rpi gpio pins and i2c perhipheral")] struct Cli { /// Where to send the data on the local system - #[arg(short, long("data-server"))] + #[arg(short, long("data-server"), default_value = "192.168.1.43:1234")] data_server: SocketAddr, /// Serial number of the device to connect case insensitive #[arg(short, long)] @@ -30,7 +30,14 @@ struct ReconnectingUsbSub { } fn request_msg() -> transfer::ControlIn { - todo!() + transfer::ControlIn { + control_type: transfer::ControlType::Vendor, + recipient: transfer::Recipient::Interface, + request: 42, + value: 0, + index: 0, + length: protocol::Msg::<10>::max_size().try_into().expect("should fit"), + } } type EncodedProtocolMsg = Vec; diff --git a/sensor-nodes/bed-sb/Cargo.toml b/sensor-nodes/bed-sb/Cargo.toml index 5498d007..dead237c 100644 --- a/sensor-nodes/bed-sb/Cargo.toml +++ b/sensor-nodes/bed-sb/Cargo.toml @@ -43,7 +43,7 @@ sps30-async = { version = "0.3.0", path = "/home/david/tmp/sps30", features = [" nau7802-async = { path = "/home/david/tmp/nau7802-rs", features = ["serde", "postcard", "defmt"] } # encoding -protocol = { path = "../../../crates/protocol" } +protocol = { path = "../../crates/protocol" } [patch.crates-io] embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } diff --git a/sensor-nodes/bed-sb/src/usb_wrapper.rs b/sensor-nodes/bed-sb/src/usb_wrapper.rs index 0bfdf377..004507e8 100644 --- a/sensor-nodes/bed-sb/src/usb_wrapper.rs +++ b/sensor-nodes/bed-sb/src/usb_wrapper.rs @@ -3,20 +3,9 @@ use embassy_sync::channel::Channel; use embassy_usb::control::{InResponse, OutResponse, Recipient, RequestType}; use embassy_usb::types::InterfaceNumber; use embassy_usb::UsbDevice; -use protocol::{affector, ErrorReport}; - -const fn max(a: usize, b: usize) -> usize { - [a, b][(a < b) as usize] -} - -const MAX_SEND_ITEM_SIZE: usize = 1 + max( - max( - crate::comms::SensMsg::ENCODED_SIZE, - ErrorReport::ENCODED_SIZE, - ), - affector::ListMessage::<5>::ENCODED_SIZE, -); +use protocol::affector; +const MAX_SEND_ITEM_SIZE: usize = 1 + protocol::Msg::<10>::max_size(); const MAX_RECV_ITEM_SIZE: usize = 1 + affector::Affector::ENCODED_SIZE; pub(crate) type SendItem = heapless::Vec; From 003b30ba71e9ea3fb373cb6dfcca53211b41574e Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 25 Sep 2024 22:54:27 +0200 Subject: [PATCH 289/687] add sensor-nodes workspace, use workspace to centralize patching of embassy deps --- sensor-nodes/Cargo.lock | 1385 ++++++++++++++++++++++++++++++++ sensor-nodes/Cargo.toml | 48 ++ sensor-nodes/bed-lb/Cargo.toml | 40 +- sensor-nodes/bed-sb/Cargo.toml | 26 +- 4 files changed, 1437 insertions(+), 62 deletions(-) create mode 100644 sensor-nodes/Cargo.lock create mode 100644 sensor-nodes/Cargo.toml diff --git a/sensor-nodes/Cargo.lock b/sensor-nodes/Cargo.lock new file mode 100644 index 00000000..f5f04cb2 --- /dev/null +++ b/sensor-nodes/Cargo.lock @@ -0,0 +1,1385 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aligned" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "377e4c0ba83e4431b10df45c1d4666f178ea9c552cac93e60c3a88bf32785923" +dependencies = [ + "as-slice", +] + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "bitfield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "block-device-driver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c051592f59fe68053524b4c4935249b806f72c1f544cfb7abe4f57c3be258e" +dependencies = [ + "aligned", +] + +[[package]] +name = "bosch-bme680" +version = "1.0.2" +dependencies = [ + "bitfield 0.14.0", + "defmt", + "embedded-hal 1.0.0", + "embedded-hal-async", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal", + "bitfield 0.13.2", + "critical-section", + "embedded-hal 0.2.7", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "critical-section" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.77", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "defmt" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb" +dependencies = [ + "defmt-parser", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "defmt-parser" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" +dependencies = [ + "thiserror", +] + +[[package]] +name = "defmt-rtt" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab697b3dbbc1750b7c8b821aa6f6e7f2480b47a99bc057a2ed7b170ebef0c51" +dependencies = [ + "critical-section", + "defmt", +] + +[[package]] +name = "document-features" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" +dependencies = [ + "litrs", +] + +[[package]] +name = "embassy-embedded-hal" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +dependencies = [ + "defmt", + "embassy-futures", + "embassy-sync", + "embassy-time", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-storage", + "embedded-storage-async", + "nb 1.1.0", +] + +[[package]] +name = "embassy-executor" +version = "0.6.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +dependencies = [ + "cortex-m", + "critical-section", + "defmt", + "document-features", + "embassy-executor-macros", + "embassy-time-driver", + "embassy-time-queue-driver", +] + +[[package]] +name = "embassy-executor-macros" +version = "0.5.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "embassy-futures" +version = "0.1.1" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" + +[[package]] +name = "embassy-hal-internal" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +dependencies = [ + "cortex-m", + "critical-section", + "defmt", + "num-traits", +] + +[[package]] +name = "embassy-net" +version = "0.4.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +dependencies = [ + "defmt", + "document-features", + "embassy-net-driver", + "embassy-sync", + "embassy-time", + "embedded-io-async", + "embedded-nal-async", + "heapless 0.8.0", + "managed", + "smoltcp", +] + +[[package]] +name = "embassy-net-driver" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +dependencies = [ + "defmt", +] + +[[package]] +name = "embassy-net-driver-channel" +version = "0.3.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +dependencies = [ + "embassy-futures", + "embassy-net-driver", + "embassy-sync", +] + +[[package]] +name = "embassy-net-wiznet" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +dependencies = [ + "defmt", + "embassy-futures", + "embassy-net-driver-channel", + "embassy-time", + "embedded-hal 1.0.0", + "embedded-hal-async", +] + +[[package]] +name = "embassy-stm32" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +dependencies = [ + "aligned", + "bit_field", + "bitflags 2.6.0", + "block-device-driver", + "cfg-if", + "cortex-m", + "cortex-m-rt", + "critical-section", + "defmt", + "document-features", + "embassy-embedded-hal", + "embassy-futures", + "embassy-hal-internal", + "embassy-net-driver", + "embassy-sync", + "embassy-time", + "embassy-time-driver", + "embassy-usb-driver", + "embassy-usb-synopsys-otg", + "embedded-can", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-nb", + "embedded-io", + "embedded-io-async", + "embedded-storage", + "embedded-storage-async", + "futures-util", + "nb 1.1.0", + "proc-macro2", + "quote", + "rand_core", + "sdio-host", + "static_assertions", + "stm32-fmc", + "stm32-metapac", + "vcell", + "volatile-register", +] + +[[package]] +name = "embassy-sync" +version = "0.6.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +dependencies = [ + "cfg-if", + "critical-section", + "defmt", + "embedded-io-async", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time" +version = "0.3.2" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +dependencies = [ + "cfg-if", + "critical-section", + "defmt", + "document-features", + "embassy-time-driver", + "embassy-time-queue-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time-driver" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +dependencies = [ + "document-features", +] + +[[package]] +name = "embassy-time-queue-driver" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" + +[[package]] +name = "embassy-usb" +version = "0.3.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +dependencies = [ + "defmt", + "embassy-futures", + "embassy-net-driver-channel", + "embassy-sync", + "embassy-usb-driver", + "heapless 0.8.0", + "ssmarshal", + "usbd-hid", +] + +[[package]] +name = "embassy-usb-driver" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +dependencies = [ + "defmt", +] + +[[package]] +name = "embassy-usb-synopsys-otg" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +dependencies = [ + "critical-section", + "embassy-sync", + "embassy-usb-driver", +] + +[[package]] +name = "embedded-can" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "defmt", + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-hal-bus" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d3980bf28e8577db59fe2bdb3df868a419469d2cecb363644eea2b6f7797669" +dependencies = [ + "critical-section", + "defmt", + "embedded-hal 1.0.0", + "embedded-hal-async", + "portable-atomic", +] + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" +dependencies = [ + "embedded-hal 1.0.0", + "nb 1.1.0", +] + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-io-async" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" +dependencies = [ + "defmt", + "embedded-io", +] + +[[package]] +name = "embedded-nal" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a943fad5ed3d3f8a00f1e80f6bba371f1e7f0df28ec38477535eb318dc19cc" +dependencies = [ + "nb 1.1.0", + "no-std-net", +] + +[[package]] +name = "embedded-nal-async" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72229137a4fc12d239b0b7f50f04b30790678da6d782a0f3f1909bf57ec4b759" +dependencies = [ + "embedded-io-async", + "embedded-nal", + "no-std-net", +] + +[[package]] +name = "embedded-storage" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" + +[[package]] +name = "embedded-storage-async" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc" +dependencies = [ + "embedded-storage", +] + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-macro", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version 0.4.1", + "serde", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "defmt", + "hash32 0.3.1", + "serde", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "large-bedroom-bed-node" +version = "0.2.0" +dependencies = [ + "bosch-bme680", + "cortex-m", + "cortex-m-rt", + "defmt", + "defmt-rtt", + "embassy-embedded-hal", + "embassy-executor", + "embassy-futures", + "embassy-net", + "embassy-net-wiznet", + "embassy-stm32", + "embassy-sync", + "embassy-time", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-bus", + "embedded-io-async", + "futures", + "heapless 0.8.0", + "max44009", + "mhzx", + "nau7802-async", + "nb 1.1.0", + "panic-probe", + "protocol", + "rand", + "sht31", + "sps30-async", + "static_cell", +] + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "managed" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" + +[[package]] +name = "max44009" +version = "0.2.0" +source = "git+https://github.com/dvdsk/max44009-rs#7b7df2e3173476c250fca3eb242f0dd366857599" +dependencies = [ + "defmt", + "embedded-hal-async", +] + +[[package]] +name = "mhzx" +version = "0.3.0" +dependencies = [ + "defmt", + "embedded-io-async", + "heapless 0.8.0", + "postcard", + "serde", +] + +[[package]] +name = "nau7802-async" +version = "0.2.0" +dependencies = [ + "byteorder", + "defmt", + "embedded-hal-async", + "postcard", + "serde", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "panic-probe" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4047d9235d1423d66cc97da7d07eddb54d4f154d6c13805c6d0793956f4f25b0" +dependencies = [ + "cortex-m", + "defmt", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "portable-atomic" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce" + +[[package]] +name = "postcard" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" +dependencies = [ + "cobs", + "defmt", + "heapless 0.7.17", + "postcard-derive", + "serde", +] + +[[package]] +name = "postcard-derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0239fa9c1d225d4b7eb69925c25c5e082307a141e470573fbbe3a817ce6a7a37" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "protocol" +version = "0.1.0" +dependencies = [ + "defmt", + "heapless 0.8.0", + "postcard", + "serde", + "strum", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver 1.0.23", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sdio-host" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93c025f9cfe4c388c328ece47d11a54a823da3b5ad0370b22d95ad47137f85a" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "sht31" +version = "0.3.1" +source = "git+https://github.com/dvdsk/SHT31-rs#a7b6bd94fb137e16bf326eff5fb591624369a2cf" +dependencies = [ + "crc", + "defmt", + "embedded-hal-async", + "postcard", +] + +[[package]] +name = "small-bedroom-sensor-node" +version = "0.2.0" +dependencies = [ + "bosch-bme680", + "cortex-m", + "cortex-m-rt", + "defmt", + "defmt-rtt", + "embassy-embedded-hal", + "embassy-executor", + "embassy-futures", + "embassy-stm32", + "embassy-sync", + "embassy-time", + "embassy-usb", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-bus", + "embedded-io-async", + "futures", + "heapless 0.8.0", + "max44009", + "mhzx", + "nau7802-async", + "nb 1.1.0", + "panic-probe", + "protocol", + "rand", + "sht31", + "sps30-async", + "static_cell", +] + +[[package]] +name = "smoltcp" +version = "0.11.0" +source = "git+https://github.com/smoltcp-rs/smoltcp?rev=dd43c8f189178b0ab3bda798ed8578b5b0a6f094#dd43c8f189178b0ab3bda798ed8578b5b0a6f094" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "cfg-if", + "defmt", + "heapless 0.8.0", + "managed", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "sps30-async" +version = "0.3.0" +dependencies = [ + "defmt", + "embedded-hal-async", + "embedded-io-async", + "futures", + "heapless 0.8.0", + "postcard", + "serde", +] + +[[package]] +name = "ssmarshal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3e6ad23b128192ed337dfa4f1b8099ced0c2bf30d61e551b65fda5916dbb850" +dependencies = [ + "encode_unicode", + "serde", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "static_cell" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89b0684884a883431282db1e4343f34afc2ff6996fe1f4a1664519b66e14c1e" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "stm32-fmc" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f0639399e2307c2446c54d91d4f1596343a1e1d5cab605b9cce11d0ab3858c" +dependencies = [ + "embedded-hal 0.2.7", +] + +[[package]] +name = "stm32-metapac" +version = "15.0.0" +source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-9b7414490b10ffbd5beb1b0dcf14adb018cbe37f#dc782d51865ba6a0a8dd79a4d6972864b33b6f00" +dependencies = [ + "cortex-m", + "cortex-m-rt", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.77", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "usb-device" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98816b1accafbb09085168b90f27e93d790b4bfa19d883466b5e53315b5f06a6" +dependencies = [ + "heapless 0.8.0", + "portable-atomic", +] + +[[package]] +name = "usbd-hid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6f291ab53d428685cc780f08a2eb9d5d6ff58622db2b36e239a4f715f1e184c" +dependencies = [ + "serde", + "ssmarshal", + "usb-device", + "usbd-hid-macros", +] + +[[package]] +name = "usbd-hid-descriptors" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee54712c5d778d2fb2da43b1ce5a7b5060886ef7b09891baeb4bf36910a3ed" +dependencies = [ + "bitfield 0.14.0", +] + +[[package]] +name = "usbd-hid-macros" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb573c76e7884035ac5e1ab4a81234c187a82b6100140af0ab45757650ccda38" +dependencies = [ + "byteorder", + "hashbrown", + "log", + "proc-macro2", + "quote", + "serde", + "syn 1.0.109", + "usbd-hid-descriptors", +] + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] diff --git a/sensor-nodes/Cargo.toml b/sensor-nodes/Cargo.toml new file mode 100644 index 00000000..935e2f00 --- /dev/null +++ b/sensor-nodes/Cargo.toml @@ -0,0 +1,48 @@ +[workspace] +resolver = "2" +members = ["bed-sb", "bed-lb"] + +[workspace.dependencies] +protocol = { path = "../crates/protocol" } + +embassy-stm32 = { version = "0.1.0", features = [ "defmt", "stm32f401cc", +"unstable-pac", "memory-x", "time-driver-tim9", "time", "exti" ] } +embassy-net = { version = "0.4.0", features = ["defmt", "proto-ipv4", "tcp", "dhcpv4","medium-ethernet"] } +embassy-net-wiznet = { version = "0.1.0", features = ["defmt"] } +embassy-sync = { version = "0.6.0", features = ["defmt"] } +embassy-executor = { version = "0.6.0", features = ["arch-cortex-m", +"executor-thread", "defmt", "integrated-timers", "executor-interrupt"] } +embassy-embedded-hal = { version = "0.2.0" } +embassy-time = { version = "0.3.2", features = ["defmt", +"defmt-timestamp-uptime-ms", "tick-hz-32_768"] } +embassy-futures = { version = "0.1.0"} + +[patch.crates-io] +embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } + +[workspace.package] +rust-version = "1.78" +edition = "2021" +license = "GPLv3" +authors = ["David Kleingeld & Eva van Houten"] + +[profile.dev] +opt-level = "s" + +[profile.release] +lto = "fat" +opt-level = "s" +incremental = false +codegen-units = 1 +# note: debug = true is okay - debuginfo isn't flashed to the device! +debug = true diff --git a/sensor-nodes/bed-lb/Cargo.toml b/sensor-nodes/bed-lb/Cargo.toml index 7a0298b4..3ee7a2d2 100644 --- a/sensor-nodes/bed-lb/Cargo.toml +++ b/sensor-nodes/bed-lb/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "bed-sensors" +name = "large-bedroom-bed-node" version = "0.2.0" rust-version = "1.78" edition = "2021" @@ -44,40 +44,4 @@ sps30-async = { version = "0.3.0", path = "/home/david/tmp/sps30", features = [" nau7802-async = { path = "/home/david/tmp/nau7802-rs", features = ["serde", "postcard", "defmt"] } # encoding -protocol = { path = "../../crates/protocol" } - -[patch.crates-io] -embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } -embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } -embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } -embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } -embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } -embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } -embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } -embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } -embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } -embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } - -# [patch.'https://github.com/embassy-rs/embassy.git'] -# [patch.crates-io] -# embassy-stm32 = {path = "../../../embassy/embassy-stm32" } -# embassy-net = {path = "../../../embassy/embassy-net" } -# embassy-net-wiznet = {path = "../../../embassy/embassy-net-wiznet" } -# embassy-sync = {path = "../../../embassy/embassy-sync" } -# embassy-executor = {path = "../../../embassy/embassy-executor" } -# embassy-embedded-hal = {path = "../../../embassy/embassy-embedded-hal" } -# embassy-time = {path = "../../../embassy/embassy-time" } -# embassy-futures = {path = "../../../embassy/embassy-futures" } -# embassy-time-driver = {path = "../../../embassy/embassy-time-driver"} -# embassy-time-queue-driver = {path = "../../../embassy/embassy-time-queue-driver"} - -[profile.dev] -opt-level = "s" - -[profile.release] -lto = "fat" -opt-level = "s" -incremental = false -codegen-units = 1 -# note: debug = true is okay - debuginfo isn't flashed to the device! -debug = true +protocol = { workspace = true } diff --git a/sensor-nodes/bed-sb/Cargo.toml b/sensor-nodes/bed-sb/Cargo.toml index dead237c..ef49f92f 100644 --- a/sensor-nodes/bed-sb/Cargo.toml +++ b/sensor-nodes/bed-sb/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "bed-sensors" +name = "small-bedroom-sensor-node" version = "0.2.0" rust-version = "1.78" edition = "2021" @@ -43,26 +43,4 @@ sps30-async = { version = "0.3.0", path = "/home/david/tmp/sps30", features = [" nau7802-async = { path = "/home/david/tmp/nau7802-rs", features = ["serde", "postcard", "defmt"] } # encoding -protocol = { path = "../../crates/protocol" } - -[patch.crates-io] -embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } -embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } -embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } -embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } -embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } -embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } -embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } -embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } -embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "d7780fc" } - -[profile.dev] -opt-level = "s" - -[profile.release] -lto = "fat" -opt-level = "s" -incremental = false -codegen-units = 1 -# note: debug = true is okay - debuginfo isn't flashed to the device! -debug = true +protocol = { workspace = true } From 6ef7c006db75a2a80dcfcf09b9135ff91488ed5a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 26 Sep 2024 17:46:53 +0200 Subject: [PATCH 290/687] fix usb on device and add note to bridge --- Cargo.lock | 11 ++++++++++ crates/usb-bridge/Cargo.toml | 1 + crates/usb-bridge/src/main.rs | 28 +++++++++++++++++++++----- sensor-nodes/bed-sb/src/main.rs | 11 +++++----- sensor-nodes/bed-sb/src/usb_wrapper.rs | 4 ++-- 5 files changed, 43 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e4414ce..4492c8a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1645,6 +1645,7 @@ dependencies = [ "tracing", "tracing-error", "tracing-subscriber", + "users", ] [[package]] @@ -3682,6 +3683,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "users" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" +dependencies = [ + "libc", + "log", +] + [[package]] name = "utf8parse" version = "0.2.2" diff --git a/crates/usb-bridge/Cargo.toml b/crates/usb-bridge/Cargo.toml index bf3476de..d5d8dde3 100644 --- a/crates/usb-bridge/Cargo.toml +++ b/crates/usb-bridge/Cargo.toml @@ -20,4 +20,5 @@ tracing-error = { workspace = true } tracing = { workspace = true } nusb = "0.1.10" color-eyre.workspace = true +users = "0.11.0" diff --git a/crates/usb-bridge/src/main.rs b/crates/usb-bridge/src/main.rs index 4d9dc92e..d6f8a06d 100644 --- a/crates/usb-bridge/src/main.rs +++ b/crates/usb-bridge/src/main.rs @@ -6,7 +6,7 @@ use color_eyre::eyre::{eyre, Context}; use color_eyre::Section; use data_server::api::data_source; use nusb::transfer; -use tokio::time::sleep; +use tokio::time::{sleep, sleep_until, Instant}; use ratelimited_logger as rl; @@ -36,7 +36,9 @@ fn request_msg() -> transfer::ControlIn { request: 42, value: 0, index: 0, - length: protocol::Msg::<10>::max_size().try_into().expect("should fit"), + length: protocol::Msg::<10>::max_size() + .try_into() + .expect("should fit"), } } @@ -52,14 +54,17 @@ impl ReconnectingUsbSub { } async fn recv(&mut self) -> EncodedProtocolMsg { + let mut retry_period = Duration::from_millis(100); loop { match self.try_recv_step().await { Ok(Some(msg)) => return msg, Ok(None) => (), Err(e) => { let logger = &mut self.logger; - rl::warn!(logger; "{e}"); - sleep(Duration::from_secs(1)).await; + rl::warn!(logger; "{e:?}"); + retry_period *= 2; + let retry_period = retry_period.min(Duration::from_secs(30)); + sleep(retry_period).await; } } } @@ -95,7 +100,18 @@ impl ReconnectingUsbSub { } .open() .map(Option::Some) - .wrap_err("Could not open the usb device")?; + .wrap_err("Could not open the usb device") + .suggestion("Try running as sudo") + .with_suggestion(|| { + format!( + "Add a .rules file in /etc/udev/rules.d with line: \ + ATTRS{{serial}}==\"{}\", MODE=\"660\", GROUP=\"{}\", TAG+=\"uaccess\"", + self.serial_number, + users::get_current_groupname() + .expect("process should always run as a group") + .to_string_lossy() + ) + })?; Ok(None) // no errors but not done yet, call us again } @@ -110,11 +126,13 @@ async fn main() { let mut server_client = data_source::reconnecting::Client::new(args.data_server, Vec::new()); loop { + let last_poll = Instant::now(); let encoded_msg = usb.recv().await; server_client .check_send_encoded(&encoded_msg) .await .expect("Should be correctly encoded"); + sleep_until(last_poll + Duration::from_millis(100)).await; } } diff --git a/sensor-nodes/bed-sb/src/main.rs b/sensor-nodes/bed-sb/src/main.rs index ebece82f..801f9afb 100644 --- a/sensor-nodes/bed-sb/src/main.rs +++ b/sensor-nodes/bed-sb/src/main.rs @@ -38,14 +38,14 @@ embassy_stm32::bind_interrupts!(struct Irqs { OTG_FS => embassy_stm32::usb::InterruptHandler; }); -// todo use nusb to write driver - // 84 Mhz clock stm32f401 +// 48 Mhz clock for usb fn config() -> Config { use embassy_stm32::rcc::{ - AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllPreDiv, PllSource, + AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllQDiv, PllPreDiv, PllSource, Sysclk, }; + use embassy_stm32::rcc::mux; let mut config = Config::default(); config.rcc.hse = Some(Hse { @@ -56,14 +56,15 @@ fn config() -> Config { config.rcc.pll = Some(Pll { prediv: PllPreDiv::DIV25, mul: PllMul::MUL336, - divp: Some(PllPDiv::DIV4), - divq: None, + divp: Some(PllPDiv::DIV4), // 25mhz / 25 * 336 / 4 = 84Mhz. + divq: Some(PllQDiv::DIV7), // 25mhz / 25 * 336 / 7 = 48Mhz. divr: None, }); config.rcc.ahb_pre = AHBPrescaler::DIV1; config.rcc.apb1_pre = APBPrescaler::DIV2; config.rcc.apb2_pre = APBPrescaler::DIV1; config.rcc.sys = Sysclk::PLL1_P; + config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q; config } diff --git a/sensor-nodes/bed-sb/src/usb_wrapper.rs b/sensor-nodes/bed-sb/src/usb_wrapper.rs index 004507e8..bae4d4f1 100644 --- a/sensor-nodes/bed-sb/src/usb_wrapper.rs +++ b/sensor-nodes/bed-sb/src/usb_wrapper.rs @@ -150,7 +150,7 @@ pub struct StackB<'a> { config_descriptor: [u8; 256], bos_descriptor: [u8; 256], msos_descriptor: [u8; 256], - control_buf: [u8; 64], + control_buf: [u8; 208], handler: UsbControlHandler<'a>, } @@ -160,7 +160,7 @@ impl<'a> StackB<'a> { config_descriptor: [0u8; 256], bos_descriptor: [0u8; 256], msos_descriptor: [0u8; 256], - control_buf: [0u8; 64], + control_buf: [0u8; 208], handler: UsbControlHandler { if_num: None, From 93acba7e0c332c20258b3409dcc8ed609c6f89ed Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 27 Sep 2024 22:59:36 +0200 Subject: [PATCH 291/687] optimized usb protocol --- crates/sensor-tui/src/control.rs | 2 +- crates/sensor-tui/src/main.rs | 61 +++----------------------- crates/usb-bridge/src/main.rs | 60 +++++++++++++++---------- sensor-nodes/bed-sb/src/comms.rs | 18 +++----- sensor-nodes/bed-sb/src/usb_wrapper.rs | 60 ++++++++++++++++++------- 5 files changed, 97 insertions(+), 104 deletions(-) diff --git a/crates/sensor-tui/src/control.rs b/crates/sensor-tui/src/control.rs index c0a85da8..4f1a5a6a 100644 --- a/crates/sensor-tui/src/control.rs +++ b/crates/sensor-tui/src/control.rs @@ -7,7 +7,7 @@ use tracing::error; use crate::client_name; -pub(crate) async fn watch_and_send(data_server: SocketAddr, mut rx: mpsc::Receiver) { +pub async fn watch_and_send(data_server: SocketAddr, mut rx: mpsc::Receiver) { let mut connected_client: Option = None; let mut queued = None; diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index 523dc275..53059476 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -1,61 +1,18 @@ use std::net::SocketAddr; -use std::ops::RangeInclusive; use std::sync::mpsc; use std::thread; use clap::Parser; use color_eyre::Result; - -mod control; -mod fetch; -mod populate; -mod receive; -mod time; -mod tui; - -pub(crate) use fetch::Fetch; -use log_store::api::{ErrorEvent, Percentile}; -use protocol::Reading; +use sensor_tui::control; +use sensor_tui::UserIntent; use tokio::task; -#[derive(Debug, PartialEq, Eq)] -enum UserIntent { - Shutdown, -} - -enum Fetchable { - Data { - timestamps: Vec, - data: Vec, - }, - Logs { - logs: Vec, - start_at: jiff::Timestamp, - }, - Hist { - percentiles: Vec, - range: RangeInclusive, - }, -} +use sensor_tui::Fetch; +use sensor_tui::tui; +use sensor_tui::receive; +use sensor_tui::populate; -enum Update { - ReadingList(Vec), - Fetched { - reading: Reading, - thing: Fetchable, - }, - FetchError(color_eyre::Report), - SensorReading(protocol::Reading), - SensorError(Box), - SubscribeError(color_eyre::Report), - DeviceList(Vec), - AffectorControlled { - affector: protocol::Affector, - controlled_by: String, - }, - AffectorList(Vec), - PopulateError(color_eyre::Report), -} #[derive(Parser)] #[command(name = "sensor tui")] @@ -129,12 +86,6 @@ fn setup_tracing() -> Result<()> { Ok(()) } -fn client_name() -> String { - let host = gethostname::gethostname(); - let host = host.to_string_lossy(); - format!("sensor-tui@{host}") -} - /// Similar to the `std::dbg!` macro, but generates `tracing` events rather /// than printing to stdout. /// diff --git a/crates/usb-bridge/src/main.rs b/crates/usb-bridge/src/main.rs index d6f8a06d..c61c7b11 100644 --- a/crates/usb-bridge/src/main.rs +++ b/crates/usb-bridge/src/main.rs @@ -1,8 +1,9 @@ +use std::vec; use std::{net::SocketAddr, time::Duration}; use clap::Parser; -use color_eyre::eyre::{eyre, Context}; +use color_eyre::eyre::{bail, eyre, Context}; use color_eyre::Section; use data_server::api::data_source; use nusb::transfer; @@ -25,7 +26,11 @@ struct Cli { struct ReconnectingUsbSub { serial_number: String, + /// when we are allowed to poll the usb + /// device for more data again + next_poll: Instant, conn: Option, + bytes: vec::IntoIter, logger: ratelimited_logger::RateLimitedLogger, } @@ -36,42 +41,53 @@ fn request_msg() -> transfer::ControlIn { request: 42, value: 0, index: 0, - length: protocol::Msg::<10>::max_size() - .try_into() - .expect("should fit"), + // must match SEND_BUFFER_SIZE in usb nodes + length: 128, } } -type EncodedProtocolMsg = Vec; - impl ReconnectingUsbSub { fn new(serial_number: String) -> Self { ReconnectingUsbSub { serial_number, + next_poll: Instant::now(), conn: None, + bytes: Vec::new().into_iter(), logger: ratelimited_logger::RateLimitedLogger::default(), } } - async fn recv(&mut self) -> EncodedProtocolMsg { + async fn recv(&mut self) -> Vec { let mut retry_period = Duration::from_millis(100); loop { - match self.try_recv_step().await { - Ok(Some(msg)) => return msg, - Ok(None) => (), - Err(e) => { - let logger = &mut self.logger; - rl::warn!(logger; "{e:?}"); - retry_period *= 2; - let retry_period = retry_period.min(Duration::from_secs(30)); - sleep(retry_period).await; + if let Some(len) = self.bytes.next() { + if len == 0 { + self.bytes = Vec::new().into_iter(); + continue; } + return self.bytes.by_ref().take(len as usize).collect(); } + + self.bytes = loop { + match self.try_recv_step().await { + Ok(Some(bytes)) => break bytes.into_iter(), + Ok(None) => continue, + Err(e) => { + let logger = &mut self.logger; + rl::warn!(logger; "{e:?}"); + retry_period *= 2; + let retry_period = retry_period.min(Duration::from_secs(30)); + sleep(retry_period).await; + } + }; + }; } } - async fn try_recv_step(&mut self) -> color_eyre::Result> { + async fn try_recv_step(&mut self) -> color_eyre::Result>> { if let Some(device) = self.conn.take() { + sleep_until(self.next_poll).await; + self.next_poll = Instant::now() + Duration::from_millis(100); let msg = device .control_in(request_msg()) .await @@ -92,7 +108,7 @@ impl ReconnectingUsbSub { self.conn = match list.as_slice() { [dev] => dev, - [] => return Err(eyre!("No usb device found with the correct serial")), + [] => bail!("No usb device found with the correct serial"), more => { return Err(eyre!("Multiple usb devices have the same serial number") .with_note(|| format!("they are: {more:?}"))) @@ -118,7 +134,8 @@ impl ReconnectingUsbSub { } #[tokio::main(flavor = "current_thread")] -async fn main() { +async fn main() -> Result<(), color_eyre::Report> { + color_eyre::install().unwrap(); setup_tracing(); let args = Cli::parse(); @@ -126,13 +143,12 @@ async fn main() { let mut server_client = data_source::reconnecting::Client::new(args.data_server, Vec::new()); loop { - let last_poll = Instant::now(); let encoded_msg = usb.recv().await; server_client .check_send_encoded(&encoded_msg) .await - .expect("Should be correctly encoded"); - sleep_until(last_poll + Duration::from_millis(100)).await; + .wrap_err("Should be correctly encoded") + .suggestion("Check if this needs to be updated")?; } } diff --git a/sensor-nodes/bed-sb/src/comms.rs b/sensor-nodes/bed-sb/src/comms.rs index 3d18de31..601a1003 100644 --- a/sensor-nodes/bed-sb/src/comms.rs +++ b/sensor-nodes/bed-sb/src/comms.rs @@ -6,7 +6,7 @@ use protocol::{affector, Affector, ErrorReport, SensorMessage}; use crate::channel::{PriorityValue, QueueItem, Queues}; use crate::sensors::slow; -use crate::usb_wrapper::{self, UsbHandle, UsbReceiver, UsbSender}; +use crate::usb_wrapper::{UsbHandle, UsbReceiver, UsbSender}; pub(crate) type SensMsg = SensorMessage<10>; async fn collect_pending(publish: &Queues, reading: PriorityValue) -> SensorMessage<10> { @@ -94,19 +94,15 @@ fn affector_list() -> affector::ListMessage<5> { } async fn send_messages(usb: UsbSender<'_>, publish: &Queues) { - let mut buf = usb_wrapper::SendItem::new(); - unwrap!(buf.resize_default(buf.capacity())); - let encoded_list_len = affector_list().encode_slice(&mut buf[1..]).len(); + let mut buf = [0; protocol::Msg::<5>::max_size()]; + let encoded_len = affector_list().encode_slice(&mut buf[1..]).len(); buf[0] = protocol::Msg::<5>::AFFECTOR_LIST; - buf.truncate(encoded_list_len + 1); - usb.send(buf).await; + let to_send = &buf[..=encoded_len]; + usb.send(to_send).await; loop { - let mut buf = usb_wrapper::SendItem::new(); - unwrap!(buf.resize_default(buf.capacity())); - let encoded_len = get_messages(publish, &mut buf).await.len(); - buf.truncate(encoded_len); - usb.send(buf).await; + let to_send = get_messages(publish, &mut buf).await; + usb.send(to_send).await; } } diff --git a/sensor-nodes/bed-sb/src/usb_wrapper.rs b/sensor-nodes/bed-sb/src/usb_wrapper.rs index bae4d4f1..a48dec69 100644 --- a/sensor-nodes/bed-sb/src/usb_wrapper.rs +++ b/sensor-nodes/bed-sb/src/usb_wrapper.rs @@ -1,19 +1,20 @@ use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::channel::Channel; +use embassy_sync::mutex::Mutex; use embassy_usb::control::{InResponse, OutResponse, Recipient, RequestType}; use embassy_usb::types::InterfaceNumber; use embassy_usb::UsbDevice; use protocol::affector; -const MAX_SEND_ITEM_SIZE: usize = 1 + protocol::Msg::<10>::max_size(); +/// USB full speed devices such as this one have a max data packet size of 1023 +const SEND_BUFFER_SIZE: usize = 128; const MAX_RECV_ITEM_SIZE: usize = 1 + affector::Affector::ENCODED_SIZE; -pub(crate) type SendItem = heapless::Vec; pub(crate) type RecvItem = heapless::Vec; pub struct UsbControlHandler<'a> { pub if_num: Option, - send_queue: &'a Channel, + send_queue: &'a Mutex>, receive_queue: &'a Channel, } @@ -74,21 +75,34 @@ impl embassy_usb::Handler for UsbControlHandler<'_> { return None; } - let Ok(to_send) = self.send_queue.try_receive() else { + if buf.len() != SEND_BUFFER_SIZE { + defmt::warn!( + "Send buffer is incorrect size ({}), should be: {}. \ + Please adjuct host driver (usb-bridge) os the usb stack here", + buf.len(), + SEND_BUFFER_SIZE + ); + return Some(InResponse::Rejected); + } + + let Ok(mut send_queue) = self.send_queue.try_lock() else { return None; }; - if to_send.len() > buf.len() { - return None; + for byte in buf.iter_mut() { + if let Some(to_send) = send_queue.pop_front() { + *byte = to_send; + } else { + *byte = 0; // end of encoded data + } } - buf[0..to_send.len()].copy_from_slice(&to_send); Some(InResponse::Accepted(buf)) } } pub struct UsbHandle<'a> { - send_queue: &'a Channel, 2>, + send_queue: &'a Mutex>, receive_queue: &'a Channel, 2>, } @@ -106,12 +120,28 @@ impl<'a> UsbHandle<'a> { } pub struct UsbSender<'a> { - send_queue: &'a Channel, 2>, + send_queue: &'a Mutex>, } impl UsbSender<'_> { - pub(crate) async fn send(&self, item: SendItem) { - self.send_queue.send(item).await; + pub(crate) async fn send(&self, to_send: &[u8]) { + let mut queue = self.send_queue.lock().await; + let free = queue.capacity() - queue.len(); + if free < 1 + to_send.len() { + defmt::trace!("dropping package because queue is full"); + return; // drop the package + } + + defmt::unwrap!(queue.push_back( + to_send + .len() + .try_into() + .expect("send only supports buffers up to and including u8::MAX long"), + )); + + for byte in to_send { + defmt::unwrap!(queue.push_back(*byte)) + } } } @@ -133,14 +163,14 @@ pub fn config() -> embassy_usb::Config<'static> { } pub struct StackA { - send_queue: Channel, 2>, + send_queue: Mutex>, receive_queue: Channel, 2>, } impl StackA { pub(crate) fn new() -> Self { Self { - send_queue: Channel::new(), + send_queue: Mutex::new(heapless::Deque::new()), receive_queue: Channel::new(), } } @@ -150,7 +180,7 @@ pub struct StackB<'a> { config_descriptor: [u8; 256], bos_descriptor: [u8; 256], msos_descriptor: [u8; 256], - control_buf: [u8; 208], + control_buf: [u8; SEND_BUFFER_SIZE], handler: UsbControlHandler<'a>, } @@ -160,7 +190,7 @@ impl<'a> StackB<'a> { config_descriptor: [0u8; 256], bos_descriptor: [0u8; 256], msos_descriptor: [0u8; 256], - control_buf: [0u8; 208], + control_buf: [0u8; SEND_BUFFER_SIZE], handler: UsbControlHandler { if_num: None, From b587f3f7f5ebdde8805ae20f39b68a1eca2ad6fe Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 30 Sep 2024 19:06:17 +0200 Subject: [PATCH 292/687] node/usb add windows compatibility stuff in the hope that linux boot no longer breaks --- crates/usb-bridge/src/main.rs | 2 +- sensor-nodes/bed-sb/src/usb_wrapper.rs | 33 +++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/crates/usb-bridge/src/main.rs b/crates/usb-bridge/src/main.rs index c61c7b11..c452e9a2 100644 --- a/crates/usb-bridge/src/main.rs +++ b/crates/usb-bridge/src/main.rs @@ -42,7 +42,7 @@ fn request_msg() -> transfer::ControlIn { value: 0, index: 0, // must match SEND_BUFFER_SIZE in usb nodes - length: 128, + length: 208, } } diff --git a/sensor-nodes/bed-sb/src/usb_wrapper.rs b/sensor-nodes/bed-sb/src/usb_wrapper.rs index a48dec69..2d6c3027 100644 --- a/sensor-nodes/bed-sb/src/usb_wrapper.rs +++ b/sensor-nodes/bed-sb/src/usb_wrapper.rs @@ -7,7 +7,7 @@ use embassy_usb::UsbDevice; use protocol::affector; /// USB full speed devices such as this one have a max data packet size of 1023 -const SEND_BUFFER_SIZE: usize = 128; +const SEND_BUFFER_SIZE: usize = 208; const MAX_RECV_ITEM_SIZE: usize = 1 + affector::Affector::ENCODED_SIZE; pub(crate) type RecvItem = heapless::Vec; @@ -59,8 +59,6 @@ impl embassy_usb::Handler for UsbControlHandler<'_> { req: embassy_usb::control::Request, buf: &'a mut [u8], ) -> Option> { - defmt::info!("Got control_in, request={}", req); - // Only handle Vendor request types to an Interface. if req.request_type != RequestType::Vendor { return None; @@ -159,6 +157,14 @@ pub fn config() -> embassy_usb::Config<'static> { config.manufacturer = Some("Vid"); config.product = Some(concat!("sensor node ", env!("CARGO_PKG_NAME"))); config.serial_number = Some("2139874"); // random, host driver finds device using this + + // Required for windows compatibility. + // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help + config.device_class = 0xEF; + config.device_sub_class = 0x02; + config.device_protocol = 0x01; + config.composite_with_iads = true; + config } @@ -214,6 +220,8 @@ pub(crate) fn new<'a, D: embassy_usb::driver::Driver<'a>>( stack_b: &'a mut StackB<'a>, driver: D, ) -> (Usb<'a, D>, UsbHandle<'a>) { + use embassy_usb::msos::{self, windows_version}; + let StackB { config_descriptor, bos_descriptor, @@ -231,6 +239,25 @@ pub(crate) fn new<'a, D: embassy_usb::driver::Driver<'a>>( control_buf, ); + // Add the Microsoft OS Descriptor (MSOS/MOD) descriptor. + // We tell Windows that this entire device is compatible with the "WINUSB" feature, + // which causes it to use the built-in WinUSB driver automatically, which in turn + // can be used by libusb/rusb software without needing a custom driver or INF file. + // In principle you might want to call msos_feature() just on a specific function, + // if your device also has other functions that still use standard class drivers. + builder.msos_descriptor(windows_version::WIN8_1, 0); + builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); + + // Randomly generated UUID because Windows requires you provide one to use WinUSB. + // In principle WinUSB-using software could find this device (or a specific interface + // on it) by its GUID instead of using the VID/PID, but in practice that seems unhelpful. + const DEVICE_INTERFACE_GUIDS: &[&str] = &["{DAC2087C-63FA-458D-A55D-827C0762DEC7}"]; + + builder.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( + "DeviceInterfaceGUIDs", + msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), + )); + let mut function = builder.function(0xFF, 0, 0); let mut interface = function.interface(); let _alternate = interface.alt_setting(0xFF, 0, 0, None); From f915b171485a9a32e16cf1d32d87b60c6c1684e5 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 1 Oct 2024 15:30:42 +0200 Subject: [PATCH 293/687] fix label formats + add format explanation to x-label --- .../format/progressively_more_specified.rs | 56 +++++++++++++++---- .../src/tui/readings/render/chart.rs | 5 +- .../src/tui/readings/render/chart/labels.rs | 6 +- 3 files changed, 51 insertions(+), 16 deletions(-) diff --git a/crates/sensor-tui/src/time/format/progressively_more_specified.rs b/crates/sensor-tui/src/time/format/progressively_more_specified.rs index ae4b15fa..1105c2e6 100644 --- a/crates/sensor-tui/src/time/format/progressively_more_specified.rs +++ b/crates/sensor-tui/src/time/format/progressively_more_specified.rs @@ -1,33 +1,54 @@ +use std::fmt::Display; use std::time::Duration; use super::duration; +#[derive(Debug, PartialEq, Eq)] pub(crate) enum FmtScale { RelativeDuration, HourMinute, DayHour, - MonthDayHour, - YearMonthDayHour, + MonthDay, + YearMonth, +} + +impl Display for FmtScale { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + FmtScale::RelativeDuration => f.write_str("elapsed"), + FmtScale::HourMinute => f.write_str(":"), + FmtScale::DayHour => f.write_str(" "), + FmtScale::MonthDay => f.write_str("/"), + FmtScale::YearMonth => f.write_str("/"), + } + } } impl FmtScale { + /// figure out optimal time description for every label point + /// for example use 15:30 for something 3h ago but 2024/05 for + /// a label 3 years ago. pub fn optimal_for(t: jiff::Timestamp, elapsed: Duration) -> Self { pub(crate) const HOUR: Duration = Duration::from_secs(60 * 60); let t = t.to_zoned(jiff::tz::TimeZone::system()); - let one_month_ago = t.checked_sub(jiff::Span::new().months(1)).unwrap(); - let one_year_ago = t.checked_sub(jiff::Span::new().years(1)).unwrap(); + let one_month_ago = jiff::Zoned::now() + .checked_sub(jiff::Span::new().months(1)) + .unwrap(); + let one_year_ago = jiff::Zoned::now() + .checked_sub(jiff::Span::new().years(1)) + .unwrap(); if elapsed < 2 * HOUR { Self::RelativeDuration } else if elapsed < 24 * HOUR { Self::HourMinute - } else if t < one_month_ago { + } else if t > one_month_ago { Self::DayHour - } else if t < one_year_ago { - Self::MonthDayHour + } else if t > one_year_ago { + Self::MonthDay } else { - Self::YearMonthDayHour + Self::YearMonth } } @@ -44,9 +65,22 @@ impl FmtScale { match self { FmtScale::RelativeDuration => duration(elapsed.as_secs_f64()) + duration_postfix, FmtScale::HourMinute => t.strftime("%H:%M").to_string(), - FmtScale::DayHour => t.strftime("%D %H").to_string(), - FmtScale::MonthDayHour => t.strftime("%M %D %H").to_string(), - FmtScale::YearMonthDayHour => t.strftime("%Y %M %D %H").to_string(), + FmtScale::DayHour => t.strftime("%dth %Hh").to_string(), + FmtScale::MonthDay => t.strftime("%M/%d").to_string(), + FmtScale::YearMonth => t.strftime("%Y/%m").to_string(), } } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn month_ago() { + let t = jiff::Timestamp::now() - jiff::Span::new().hours(40 * 24); + let elapsed = jiff::Timestamp::now().duration_since(t).unsigned_abs(); + let res = FmtScale::optimal_for(t, elapsed); + assert_eq!(res, FmtScale::MonthDay) + } +} diff --git a/crates/sensor-tui/src/tui/readings/render/chart.rs b/crates/sensor-tui/src/tui/readings/render/chart.rs index 082f6b2e..4e727889 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart.rs @@ -19,14 +19,15 @@ pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, chart: ChartPa .data(chart.data); let (x_bounds, y_bounds) = bounds(&chart, layout); - let (mut x_labels, y_labels) = labels(&chart, layout, x_bounds, y_bounds); + let scale = labels::scale(x_bounds[1]); + let (mut x_labels, y_labels) = labels(&chart, layout, x_bounds, y_bounds, &scale); let borrowed = x_labels.first_mut().expect("min labels is 2"); let owned = std::mem::take(borrowed); x_labels[0] = tab.history_length.style_left_x_label(owned); let x_axis = Axis::default() - .title("Time") + .title(format!("Time ({scale})",)) .style(Style::default()) .bounds(x_bounds) .labels(x_labels) diff --git a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs index 81065692..8e77b7fb 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs @@ -4,7 +4,7 @@ use protocol::reading; use ratatui::layout::Rect; use ratatui::text::Span; -use crate::time::format::progressively_more_specified; +use crate::time::format::progressively_more_specified::{self, FmtScale}; use crate::tui::readings::sensor_info::ChartParts; use super::Bounds; @@ -16,11 +16,11 @@ pub fn labels( layout: Rect, x_bounds: Bounds, y_bounds: Bounds, + scale: &progressively_more_specified::FmtScale ) -> (Labels, Labels) { let y_label_spacing = 10; let info = &chart.reading; - let scale = scale(x_bounds[1]); // Characters are about twice as high as wide let x = evenly_spaced_labels(layout.width / y_label_spacing / 2, info, x_bounds) @@ -42,7 +42,7 @@ fn fmt(x: f64, scale: &progressively_more_specified::FmtScale) -> String { scale.render(time, elapsed, "") } -fn scale(secs: f64) -> progressively_more_specified::FmtScale { +pub fn scale(secs: f64) -> progressively_more_specified::FmtScale { let now = jiff::Timestamp::now(); let elapsed = Duration::from_secs_f64(secs); let time = now - elapsed; From efcb19bca8141e3c563d0e9b4953573619014691 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 1 Oct 2024 16:45:53 +0200 Subject: [PATCH 294/687] protocol: fix broken is_same_as impl --- crates/protocol/src/reading.rs | 2 +- crates/protocol/src/small_bedroom.rs | 27 +----------------------- crates/protocol/src/small_bedroom/bed.rs | 16 ++++++++++++++ 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/crates/protocol/src/reading.rs b/crates/protocol/src/reading.rs index 2a727af7..5632fd16 100644 --- a/crates/protocol/src/reading.rs +++ b/crates/protocol/src/reading.rs @@ -42,7 +42,7 @@ impl Reading { self.leaf().range } #[must_use] - /// the step between the two closest datapoints that are not the same + /// the step between the two closest data-points that are not the same pub fn resolution(&self) -> f32 { use tree::Tree; self.leaf().resolution diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index 1ea3db56..ad75478c 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -7,7 +7,6 @@ use crate::button::Press; #[cfg(feature = "alloc")] use crate::affector; #[cfg(feature = "alloc")] -use crate::reading::tree::{Item, Tree}; pub mod desk; pub mod bed; @@ -47,31 +46,7 @@ pub enum Reading { Bed(bed::Reading) = 2, } -#[cfg(feature = "alloc")] -impl Tree for Reading { - fn inner(&self) -> Item<'_> { - match self { - Reading::ButtonPanel(inner) => return Item::Node(inner), - Reading::Desk(inner) => return Item::Node(inner), - Reading::Bed(inner) => return Item::Node(inner), - } - } - - fn branch_id(&self) -> crate::reading::tree::Id { - ReadingDiscriminants::from(self) as crate::reading::tree::Id - } -} - -impl Reading { - #[must_use] - pub fn is_same_as(&self, other: &Self) -> bool { - match (self, other) { - (Self::ButtonPanel(a), Self::ButtonPanel(b)) => a.is_same_as(b), - (Self::Desk(a), Self::Desk(b)) => a.is_same_as(b), - _ => false, - } - } -} +crate::reading::tree::all_nodes!{Reading; ReadingDiscriminants; ButtonPanel, Desk, Bed} #[derive( strum::EnumDiscriminants, diff --git a/crates/protocol/src/small_bedroom/bed.rs b/crates/protocol/src/small_bedroom/bed.rs index 5397037c..30ae83d2 100644 --- a/crates/protocol/src/small_bedroom/bed.rs +++ b/crates/protocol/src/small_bedroom/bed.rs @@ -529,3 +529,19 @@ impl affector::tree::Tree for Affector { AffectorDiscriminants::from(self) as Id } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + #[cfg(feature = "alloc")] + fn test_is_same_as() { + assert!(Reading::Co2(5).is_same_as(&Reading::Co2(0))); + + let a = crate::Reading::SmallBedroom(crate::small_bedroom::Reading::Bed(Reading::Co2(5))); + let b = crate::Reading::SmallBedroom(crate::small_bedroom::Reading::Bed(Reading::Co2(0))); + + assert!(a.is_same_as(&b)); + } +} From 5605c8e1b0b425c1622187e19b01ecbe0589d549 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 1 Oct 2024 17:16:56 +0200 Subject: [PATCH 295/687] forgotten sensor-tui lib file --- crates/sensor-tui/src/lib.rs | 56 +++++++++++++++++++ .../src/tui/readings/render/chart/labels.rs | 5 +- 2 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 crates/sensor-tui/src/lib.rs diff --git a/crates/sensor-tui/src/lib.rs b/crates/sensor-tui/src/lib.rs new file mode 100644 index 00000000..bdaf4260 --- /dev/null +++ b/crates/sensor-tui/src/lib.rs @@ -0,0 +1,56 @@ +pub mod control; +mod fetch; +pub mod populate; +pub mod receive; +mod time; +pub mod tui; + +pub use fetch::Fetch; +use log_store::api::{ErrorEvent, Percentile}; +use protocol::Reading; +use std::ops::RangeInclusive; + +fn client_name() -> String { + let host = gethostname::gethostname(); + let host = host.to_string_lossy(); + format!("sensor-tui@{host}") +} + +enum Fetchable { + Data { + timestamps: Vec, + data: Vec, + }, + Logs { + logs: Vec, + start_at: jiff::Timestamp, + }, + Hist { + percentiles: Vec, + range: RangeInclusive, + }, +} + +pub enum Update { + ReadingList(Vec), + Fetched { + reading: Reading, + thing: Fetchable, + }, + FetchError(color_eyre::Report), + SensorReading(protocol::Reading), + SensorError(Box), + SubscribeError(color_eyre::Report), + DeviceList(Vec), + AffectorControlled { + affector: protocol::Affector, + controlled_by: String, + }, + AffectorList(Vec), + PopulateError(color_eyre::Report), +} + +#[derive(Debug, PartialEq, Eq)] +pub enum UserIntent { + Shutdown, +} diff --git a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs index 8e77b7fb..50cdd3b4 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs @@ -4,7 +4,7 @@ use protocol::reading; use ratatui::layout::Rect; use ratatui::text::Span; -use crate::time::format::progressively_more_specified::{self, FmtScale}; +use crate::time::format::progressively_more_specified; use crate::tui::readings::sensor_info::ChartParts; use super::Bounds; @@ -16,12 +16,11 @@ pub fn labels( layout: Rect, x_bounds: Bounds, y_bounds: Bounds, - scale: &progressively_more_specified::FmtScale + scale: &progressively_more_specified::FmtScale, ) -> (Labels, Labels) { let y_label_spacing = 10; let info = &chart.reading; - // Characters are about twice as high as wide let x = evenly_spaced_labels(layout.width / y_label_spacing / 2, info, x_bounds) .rev() From e1c13ec59219a49be732059f92eaf5b52778474c Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 5 Oct 2024 18:38:38 +0200 Subject: [PATCH 296/687] protocol: fix extra alloc that hsould not be there --- crates/protocol/src/small_bedroom.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index ad75478c..9fee9748 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -6,7 +6,6 @@ use serde::{Deserialize, Serialize}; use crate::button::Press; #[cfg(feature = "alloc")] use crate::affector; -#[cfg(feature = "alloc")] pub mod desk; pub mod bed; @@ -46,6 +45,7 @@ pub enum Reading { Bed(bed::Reading) = 2, } +#[cfg(feature = "alloc")] crate::reading::tree::all_nodes!{Reading; ReadingDiscriminants; ButtonPanel, Desk, Bed} #[derive( From fecf30f9e5047ac623e018c7a2511c795074d025 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 8 Oct 2024 21:32:52 +0200 Subject: [PATCH 297/687] add 'example' to sensor-tui for rapid iteration on graph --- crates/sensor-tui/examples/chart_gaps.rs | 52 +++++++++++++++++++ crates/sensor-tui/src/lib.rs | 2 +- crates/sensor-tui/src/tui.rs | 4 +- crates/sensor-tui/src/tui/readings.rs | 2 +- crates/sensor-tui/src/tui/readings/render.rs | 6 +-- .../src/tui/readings/sensor_info.rs | 5 +- 6 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 crates/sensor-tui/examples/chart_gaps.rs diff --git a/crates/sensor-tui/examples/chart_gaps.rs b/crates/sensor-tui/examples/chart_gaps.rs new file mode 100644 index 00000000..0a98edfa --- /dev/null +++ b/crates/sensor-tui/examples/chart_gaps.rs @@ -0,0 +1,52 @@ +use std::io::stdout; + +use crossterm::terminal::{ + disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen, +}; +use crossterm::{event, ExecutableCommand}; +use ratatui::backend::CrosstermBackend; +use ratatui::{Frame, Terminal}; +use sensor_tui::tui::readings::render::chart; +use sensor_tui::tui::readings::sensor_info::ChartParts; +use sensor_tui::tui::readings::UiState; + +fn data_with_gap(buffer: &mut Vec<(f64, f64)>) -> ChartParts<'_> { + buffer.extend((0..10).into_iter().map(|i| (i as f64, 2.0))); + buffer.extend((30..35).into_iter().map(|i| (i as f64, 5.0))); + buffer.extend((50..55).into_iter().map(|i| (i as f64, 1.0))); + + let info = protocol::reading::Info { + val: 0.0, + device: protocol::Device::SmallBedroom(protocol::small_bedroom::Device::Gpio), + resolution: 1.0, + range: 0.0..5.0, + unit: protocol::Unit::Ohm, + description: "test data with gaps", + branch_id: 0, + }; + + ChartParts { + reading: info, + data: buffer.as_slice(), + } +} + +fn chart(frame: &mut Frame) { + let layout = frame.area(); + let mut tab = UiState::default(); + let mut buffer = Vec::new(); + chart::render(frame, layout, &mut tab, data_with_gap(&mut buffer)); +} + +fn main() { + stdout().execute(EnterAlternateScreen).unwrap(); + enable_raw_mode().unwrap(); + let mut terminal = Terminal::new(CrosstermBackend::new(stdout())).unwrap(); + terminal.clear().unwrap(); + + terminal.draw(chart).unwrap(); + event::read().unwrap(); + + stdout().execute(LeaveAlternateScreen).unwrap(); + disable_raw_mode().unwrap(); +} diff --git a/crates/sensor-tui/src/lib.rs b/crates/sensor-tui/src/lib.rs index bdaf4260..d718c56e 100644 --- a/crates/sensor-tui/src/lib.rs +++ b/crates/sensor-tui/src/lib.rs @@ -16,7 +16,7 @@ fn client_name() -> String { format!("sensor-tui@{host}") } -enum Fetchable { +pub enum Fetchable { Data { timestamps: Vec, data: Vec, diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index 2d726083..fb9233ee 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -18,7 +18,7 @@ use std::{ use crate::{Fetch, Update, UserIntent}; mod affectors; -mod readings; +pub mod readings; mod render; mod reports; @@ -45,7 +45,7 @@ impl ActiveTab { } } -pub(crate) struct Theme { +pub struct Theme { bars: Style, centered_text: Style, } diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index ba1447a2..e753c106 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -7,7 +7,7 @@ use ratatui::Frame; use tui_tree_widget::TreeState; pub(crate) mod history_len; -mod render; +pub mod render; pub mod sensor_info; use history_len::HistoryLen; diff --git a/crates/sensor-tui/src/tui/readings/render.rs b/crates/sensor-tui/src/tui/readings/render.rs index 7a2297a6..d2415f5a 100644 --- a/crates/sensor-tui/src/tui/readings/render.rs +++ b/crates/sensor-tui/src/tui/readings/render.rs @@ -17,7 +17,7 @@ use super::{ UiState, }; -mod chart; +pub mod chart; mod logs; pub(crate) fn layout( @@ -50,7 +50,7 @@ pub(crate) fn layout( .areas(layout) } -pub fn footer(frame: &mut Frame, layout: Rect, app: &mut UiState, theme: &Theme) { +pub(crate) fn footer(frame: &mut Frame, layout: Rect, app: &mut UiState, theme: &Theme) { let mut footer = Vec::new(); if app.history_length.editing { @@ -79,7 +79,7 @@ pub fn footer(frame: &mut Frame, layout: Rect, app: &mut UiState, theme: &Theme) frame.render_widget(footer, layout) } -pub fn graph_hist_logs( +pub(crate) fn graph_hist_logs( frame: &mut Frame, layout: Rect, app: &mut UiState, diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index 9ead59ef..26f9d648 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -30,7 +30,7 @@ pub struct SensorInfo { pub histogram_range: Option>, pub history_from_store: Vec<(jiff::Timestamp, f32)>, condition: Result<(), Box>, - pub logs: logs::Logs, + pub(crate) logs: logs::Logs, } pub struct ErrorDensity { @@ -155,7 +155,7 @@ impl SensorInfo { }) } - pub fn logs(&self) -> logs::List { + pub(crate) fn logs(&self) -> logs::List { self.logs.list() } @@ -459,5 +459,6 @@ impl Readings { pub struct ChartParts<'a> { pub reading: reading::Info, + /// array of time, y pub data: &'a [(f64, f64)], } From 8cd0e1e6b21415cd8de315e64064c895d6b1710a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 8 Oct 2024 21:33:44 +0200 Subject: [PATCH 298/687] increase rate limit for log-store & data-store through rpc crate --- crates/log-store/src/server/db/log.rs | 8 ++++---- crates/ratelimited-logger/examples/log.rs | 2 +- crates/rpc/src/server.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/log-store/src/server/db/log.rs b/crates/log-store/src/server/db/log.rs index 40acd04c..ea3c0788 100644 --- a/crates/log-store/src/server/db/log.rs +++ b/crates/log-store/src/server/db/log.rs @@ -190,7 +190,7 @@ impl Log { } fn get(&mut self, range: RangeInclusive) -> GetLogResponse { - use byteseries::seek::Error::{StartAfterData, StopBeforeData}; + use byteseries::seek::Error::{EmptyFile, StartAfterData, StopBeforeData}; use byteseries::series::Error::InvalidRange; const MAX_IN_ONE_READ: usize = 200; @@ -220,13 +220,13 @@ impl Log { &mut data, ) { Ok(()) => (), - Err(InvalidRange(StartAfterData | StopBeforeData)) => { + Err(InvalidRange(StartAfterData | StopBeforeData | EmptyFile)) => { return GetLogResponse::All(current.collect()) } Err(other) => { let report = color_eyre::eyre::Report::new(other) - .wrap_err("Could not read log events from disk") - .to_string(); + .wrap_err("Could not read log events from disk"); + let report = format!("{report:?}"); return GetLogResponse::Err(report); } } diff --git a/crates/ratelimited-logger/examples/log.rs b/crates/ratelimited-logger/examples/log.rs index f8712cb5..10e463d1 100644 --- a/crates/ratelimited-logger/examples/log.rs +++ b/crates/ratelimited-logger/examples/log.rs @@ -2,7 +2,7 @@ use ratelimited_logger::{warn, RateLimitedLogger}; fn main() { setup_tracing(); - let mut logger = RateLimitedLogger::new(); + let mut logger = RateLimitedLogger::default(); warn!(logger; "oh no the number is: {}", 5); } diff --git a/crates/rpc/src/server.rs b/crates/rpc/src/server.rs index 9b94b46e..2be207c1 100644 --- a/crates/rpc/src/server.rs +++ b/crates/rpc/src/server.rs @@ -38,7 +38,7 @@ where { let quota = Quota::with_period(Duration::from_secs(1)) .unwrap() - .allow_burst(NonZeroU32::new(5u32).unwrap()); + .allow_burst(NonZeroU32::new(30u32).unwrap()); let limiter = RateLimiter::keyed(quota); let listener = TcpListener::bind(format!("0.0.0.0:{port}")) .await From 062a790f49f63b14a8e0faeeff36329b82ebb940 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 9 Oct 2024 16:35:52 +0200 Subject: [PATCH 299/687] tui fix: discontinuities are now shown --- .../src/tui/readings/render/chart.rs | 20 ++-- .../src/tui/readings/render/chart/split.rs | 106 ++++++++++++++++++ 2 files changed, 119 insertions(+), 7 deletions(-) create mode 100644 crates/sensor-tui/src/tui/readings/render/chart/split.rs diff --git a/crates/sensor-tui/src/tui/readings/render/chart.rs b/crates/sensor-tui/src/tui/readings/render/chart.rs index 4e727889..1dd5e316 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart.rs @@ -9,15 +9,10 @@ use ratatui::{ use crate::tui::readings::{sensor_info::ChartParts, UiState}; mod labels; +mod split; use labels::labels; pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, chart: ChartParts) { - let dataset = Dataset::default() - .marker(symbols::Marker::Braille) - .graph_type(GraphType::Line) - .style(Style::default()) - .data(chart.data); - let (x_bounds, y_bounds) = bounds(&chart, layout); let scale = labels::scale(x_bounds[1]); let (mut x_labels, y_labels) = labels(&chart, layout, x_bounds, y_bounds, &scale); @@ -37,7 +32,18 @@ pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, chart: ChartPa .style(Style::default()) .bounds(y_bounds) .labels(y_labels); - let linechart = Chart::new(vec![dataset]) + + let datasets = split::split(&chart, layout.width) + .map(|line| { + Dataset::default() + .marker(symbols::Marker::Braille) + .graph_type(GraphType::Line) + .style(Style::default()) + .data(line) + }) + .collect(); + + let linechart = Chart::new(datasets) .block(Block::bordered().title("History")) .x_axis(x_axis) .y_axis(y_axis); diff --git a/crates/sensor-tui/src/tui/readings/render/chart/split.rs b/crates/sensor-tui/src/tui/readings/render/chart/split.rs new file mode 100644 index 00000000..48b80a61 --- /dev/null +++ b/crates/sensor-tui/src/tui/readings/render/chart/split.rs @@ -0,0 +1,106 @@ +use std::iter; + +use itertools::Itertools; + +use crate::tui::readings::sensor_info::ChartParts; + +/// split data into separate lines if +/// - the gap between point groups is larger then what is expected for +/// the given sensor with 20% margin +/// and +/// - the gap is larger then the medium in the data +/// +/// # Note +/// the splits line groups are returned from right to left +/// +// An alternative would have been to use the median though that is slower and +// we have this information anyway +pub(crate) fn split<'a>( + chart: &'a ChartParts, + chart_width: u16, +) -> impl Iterator { + let min_dist = chart + .reading + .device + .info() + .max_sample_interval + .as_secs_f64() + * 1.2; // 20% margin + + let chart_resolution = chart + .data + .first() + .map(|(x, _)| x) + .and_then(|start| chart.data.last().map(|(x, _)| (start, x))) + .map(|(start, end)| end - start) + .map(|x_len| x_len / (chart_width as f64)) + .unwrap_or(f64::MIN); + + let min_dist = min_dist.max(chart_resolution); + + let splits = chart + .data + .iter() + .map(|(x, _)| x) + .enumerate() + .rev() + .tuple_windows() + .filter(move |((_, b), (_, a))| **b - **a > min_dist) + .map(|((ib, _), _)| ib); + + let mut data = chart.data; + splits.chain(iter::once(0)).map(move |mid| { + let (left, line) = data.split_at(mid); + data = left; + line + }) +} + +#[cfg(test)] +mod test { + use protocol::{large_bedroom, Device}; + + use super::*; + + fn test_data() -> Vec<(f64, f64)> { + let mut data = Vec::new(); + for segment in 0..5 { + let x = ((segment * 100)..(segment * 100 + 5)).into_iter(); + data.extend(x.map(|x| (x as f64, 5.0))); + } + data + } + + #[test] + fn test_split() { + let test_data = test_data(); + let test_chart = ChartParts { + reading: protocol::reading::Info { + val: 0.0, + device: Device::LargeBedroom(large_bedroom::Device::Bed( + large_bedroom::bed::Device::Bme680, + )), + resolution: 1.0, + range: 0.0..200.0, + unit: protocol::Unit::C, + description: "test", + branch_id: 1, + }, + data: &test_data, + }; + assert_eq!(split(&test_chart, 500).count(), 5); + assert_eq!( + split(&test_chart, 500).next(), + Some( + [ + (400.0, 5.0), + (401.0, 5.0), + (402.0, 5.0), + (403.0, 5.0), + (404.0, 5.0) + ] + .as_slice() + ) + ); + } +} From fecf4a9c1a0a4b594a23cdfbff9fd6f8358cbd39 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 9 Oct 2024 17:02:30 +0200 Subject: [PATCH 300/687] allow setting bounds on empty plot --- crates/sensor-tui/examples/chart_gaps.rs | 4 +++- crates/sensor-tui/src/tui/readings.rs | 11 ++++------- .../src/tui/readings/render/chart/labels.rs | 1 + crates/sensor-tui/src/tui/readings/sensor_info.rs | 12 ++++++++++-- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/crates/sensor-tui/examples/chart_gaps.rs b/crates/sensor-tui/examples/chart_gaps.rs index 0a98edfa..23312eb5 100644 --- a/crates/sensor-tui/examples/chart_gaps.rs +++ b/crates/sensor-tui/examples/chart_gaps.rs @@ -17,7 +17,9 @@ fn data_with_gap(buffer: &mut Vec<(f64, f64)>) -> ChartParts<'_> { let info = protocol::reading::Info { val: 0.0, - device: protocol::Device::SmallBedroom(protocol::small_bedroom::Device::Gpio), + device: protocol::Device::SmallBedroom(protocol::small_bedroom::Device::Bed( + protocol::small_bedroom::bed::Device::Bme680, + )), resolution: 1.0, range: 0.0..5.0, unit: protocol::Unit::Ohm, diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index e753c106..105865a3 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -96,9 +96,8 @@ impl Tab { pub fn handle_key(&mut self, key: KeyEvent) -> Option { self.ui_state.handle_key_all_modes(key)?; - let plot_open = !self.plot_buf.is_empty(); match self.ui_state.input_mode { - InputMode::Normal => self.ui_state.handle_key_normal_mode(key, plot_open)?, + InputMode::Normal => self.ui_state.handle_key_normal_mode(key)?, InputMode::EditingBounds => self.ui_state.handle_key_bounds_mode(key)?, }; @@ -170,13 +169,11 @@ impl Tab { } impl UiState { - fn handle_key_normal_mode(&mut self, key: KeyEvent, plot_open: bool) -> Option { + fn handle_key_normal_mode(&mut self, key: KeyEvent) -> Option { match key.code { KeyCode::Char('b') => { - if plot_open { - self.history_length.start_editing(); - self.input_mode = InputMode::EditingBounds; - } + self.history_length.start_editing(); + self.input_mode = InputMode::EditingBounds; } KeyCode::Char('h') => { self.show_histogram = !self.show_histogram; diff --git a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs index 50cdd3b4..814a3947 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs @@ -42,6 +42,7 @@ fn fmt(x: f64, scale: &progressively_more_specified::FmtScale) -> String { } pub fn scale(secs: f64) -> progressively_more_specified::FmtScale { + assert!(secs >= 0.0, "Argument must be larger then or equal to zero"); let now = jiff::Timestamp::now(); let elapsed = Duration::from_secs_f64(secs); let time = now - elapsed; diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index 26f9d648..c0b274d8 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -134,6 +134,7 @@ impl SensorInfo { for xy in self .history_from_store .iter() + .skip_while(|(t, _)| *t < reference) .take_while(|(t, _)| *t < first_recent) .chain(self.recent_history.iter()) .map(|(x, y)| { @@ -149,6 +150,14 @@ impl SensorInfo { plot_buf.push(xy); } + assert!( + plot_buf.iter().all(|(x, _)| *x > 0.0), + "negative x is not allowed. Arguments: + \thistory_len: {history_len:?} + \tfirst_recent: {first_recent} + \reference: {reference}" + ); + Some(ChartParts { reading: self.info.clone(), data: plot_buf, @@ -433,8 +442,7 @@ impl Readings { .expect("data is never removed"); match fetched { Fetchable::Data { timestamps, data } => { - sensorinfo.history_from_store = - timestamps.into_iter().zip(data).collect(); + sensorinfo.history_from_store = timestamps.into_iter().zip(data).collect(); } Fetchable::Logs { logs, start_at } => { sensorinfo.logs.from_store = Some(logs::FromStore { From 07b5d290b3bbfb7af573730b58da501dcd20c5e1 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 10 Oct 2024 14:25:38 +0200 Subject: [PATCH 301/687] fix usb-bridge crate name --- crates/usb-bridge/Cargo.toml | 2 +- crates/usb-bridge/deploy.sh | 19 +++++++++++++++++++ crates/usb-bridge/rust-toolchain.toml | 6 ------ 3 files changed, 20 insertions(+), 7 deletions(-) create mode 100755 crates/usb-bridge/deploy.sh delete mode 100644 crates/usb-bridge/rust-toolchain.toml diff --git a/crates/usb-bridge/Cargo.toml b/crates/usb-bridge/Cargo.toml index d5d8dde3..dea717f8 100644 --- a/crates/usb-bridge/Cargo.toml +++ b/crates/usb-bridge/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "host" +name = "usb-bridge" version = "0.1.0" rust-version = "1.78" edition = "2021" diff --git a/crates/usb-bridge/deploy.sh b/crates/usb-bridge/deploy.sh new file mode 100755 index 00000000..dc5995f3 --- /dev/null +++ b/crates/usb-bridge/deploy.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -e + +BUILD_ARG=--release +SERVER="sgc" # ssh config name or full address +NAME=usb-bridge + +cargo build --target=aarch64-unknown-linux-musl $BUILD_ARG +rsync -vh --progress \ + ../../target/aarch64-unknown-linux-musl/release/$NAME \ + $SERVER:/tmp/ + +cmds=" +sudo mv /tmp/$NAME /home/ha/$NAME +sudo chown ha:ha /home/ha/$NAME +sudo systemctl restart $NAME.service +" + +ssh -t $SERVER "$cmds" diff --git a/crates/usb-bridge/rust-toolchain.toml b/crates/usb-bridge/rust-toolchain.toml deleted file mode 100644 index bd227cbf..00000000 --- a/crates/usb-bridge/rust-toolchain.toml +++ /dev/null @@ -1,6 +0,0 @@ -[toolchain] -channel = "nightly" -components = [ "rust-src", "rustfmt", "llvm-tools" ] -targets = [ - "x86_64-unknown-linux-gnu", -] From c499a6b2f730c4be4ea157a9b1074b14ee2cd77f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 10 Oct 2024 14:26:32 +0200 Subject: [PATCH 302/687] add reset on error i2c --- Cargo.lock | 307 +++++++++--------- sensor-nodes/Cargo.lock | 21 +- sensor-nodes/Cargo.toml | 39 ++- sensor-nodes/bed-sb/src/main.rs | 9 +- sensor-nodes/bed-sb/src/reset_on_error_i2c.rs | 74 +++++ sensor-nodes/bed-sb/src/sensors.rs | 11 +- sensor-nodes/bed-sb/src/sensors/retry.rs | 11 +- sensor-nodes/rust-toolchain.toml | 6 + 8 files changed, 277 insertions(+), 201 deletions(-) create mode 100644 sensor-nodes/bed-sb/src/reset_on_error_i2c.rs create mode 100644 sensor-nodes/rust-toolchain.toml diff --git a/Cargo.lock b/Cargo.lock index 4492c8a6..dd78fc6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,18 +23,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if 1.0.0", - "once_cell", - "version_check", - "zerocopy", -] - [[package]] name = "aho-corasick" version = "1.1.3" @@ -305,13 +293,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.82" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -331,15 +319,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.7.5" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ "async-trait", "axum-core", @@ -367,9 +355,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", @@ -380,21 +368,20 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", ] [[package]] name = "axum-macros" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" +checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ - "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -544,7 +531,7 @@ checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "byteseries" version = "0.7.1" -source = "git+https://github.com/dvdsk/byteseries#edc1c89c580c35b411de68feab4f665303d4c5cc" +source = "git+https://github.com/dvdsk/byteseries#eb057c6363548fa1fc2fbe5a89395b81238152f5" dependencies = [ "arraydeque", "itertools", @@ -579,9 +566,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.21" +version = "1.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" dependencies = [ "shlex", ] @@ -615,9 +602,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.17" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -625,9 +612,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.17" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -637,14 +624,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -825,7 +812,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if 1.0.0", - "hashbrown", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core 0.9.10", @@ -904,7 +891,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -946,7 +933,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1036,7 +1023,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1105,7 +1092,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1213,9 +1200,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide 0.8.0", @@ -1227,6 +1214,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -1254,9 +1247,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1280,9 +1273,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1305,15 +1298,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1322,9 +1315,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" @@ -1356,26 +1349,26 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-timer" @@ -1385,9 +1378,9 @@ checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1482,9 +1475,9 @@ dependencies = [ [[package]] name = "gpiocdev" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5119c89eccee09c4f6e9ca2b112aea1cd80bac31cd29169f171a48ae5552d1c" +checksum = "4ea1a9715542f84bc7b67cbb01c02ed3a72a919750b7d8611cc5bd684449386e" dependencies = [ "futures", "gpiocdev-uapi", @@ -1507,9 +1500,9 @@ dependencies = [ [[package]] name = "gpiocdev-uapi" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a02357253f833a6ce4e93f17e8dd3e169c941ea71b83d442ed9c55f784045204" +checksum = "1d5c09e8bbed8a03e31b0fabf273da9486940091820a088215cd9fc24a1523d1" dependencies = [ "bitflags 2.6.0", "ioctl-sys", @@ -1561,9 +1554,16 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" dependencies = [ - "ahash", "allocator-api2", + "equivalent", + "foldhash", ] [[package]] @@ -1606,12 +1606,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" @@ -1630,24 +1624,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" -[[package]] -name = "host" -version = "0.1.0" -dependencies = [ - "clap", - "color-eyre", - "data-server", - "heapless 0.8.0", - "nusb", - "protocol", - "ratelimited-logger", - "tokio", - "tracing", - "tracing-error", - "tracing-subscriber", - "users", -] - [[package]] name = "http" version = "1.1.0" @@ -1684,9 +1660,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1732,9 +1708,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ "bytes", "futures-channel", @@ -1745,7 +1721,6 @@ dependencies = [ "pin-project-lite", "socket2", "tokio", - "tower", "tower-service", "tracing", ] @@ -1803,12 +1778,12 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.0", ] [[package]] @@ -1818,7 +1793,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" dependencies = [ "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1848,9 +1823,9 @@ checksum = "8bd11f3a29434026f5ff98c730b668ba74b1033637b8817940b54d040696133c" [[package]] name = "ipnet" -version = "2.10.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is_terminal_polyfill" @@ -1925,9 +1900,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libredox" @@ -2014,11 +1989,11 @@ dependencies = [ [[package]] name = "lru" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown", + "hashbrown 0.15.0", ] [[package]] @@ -2362,9 +2337,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "option-ext" @@ -2433,7 +2408,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.5.4", + "redox_syscall 0.5.7", "smallvec 1.13.2", "windows-targets 0.52.6", ] @@ -2452,22 +2427,22 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2510,9 +2485,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" [[package]] name = "postcard" @@ -2581,9 +2556,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] @@ -2729,9 +2704,9 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "11.1.0" +version = "11.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb9ee317cfe3fbd54b36a511efc1edd42e216903c9cd575e686dd68a2ba90d8d" +checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0" dependencies = [ "bitflags 2.6.0", ] @@ -2747,9 +2722,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.4" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] @@ -2767,14 +2742,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -2788,13 +2763,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -2805,15 +2780,15 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.7" +version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" dependencies = [ "base64 0.22.1", "bytes", @@ -3000,7 +2975,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3235,11 +3210,11 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "rustversion", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3255,9 +3230,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -3308,28 +3283,28 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "temp-dir" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f227968ec00f0e5322f9b8173c7a0cbcff6181a0a5b28e9892491c286277231" +checksum = "bc1ee6eef34f12f765cb94725905c6312b6610ab2b0940889cfe58dae7bc3c72" [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3413,7 +3388,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3457,14 +3432,14 @@ dependencies = [ [[package]] name = "tower" -version = "0.4.13" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" dependencies = [ "futures-core", "futures-util", - "pin-project", "pin-project-lite", + "sync_wrapper 0.1.2", "tokio", "tower-layer", "tower-service", @@ -3501,7 +3476,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3618,9 +3593,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" @@ -3683,6 +3658,24 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "usb-bridge" +version = "0.1.0" +dependencies = [ + "clap", + "color-eyre", + "data-server", + "heapless 0.8.0", + "nusb", + "protocol", + "ratelimited-logger", + "tokio", + "tracing", + "tracing-error", + "tracing-subscriber", + "users", +] + [[package]] name = "users" version = "0.11.0" @@ -3780,7 +3773,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", "wasm-bindgen-shared", ] @@ -3814,7 +3807,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4071,5 +4064,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] diff --git a/sensor-nodes/Cargo.lock b/sensor-nodes/Cargo.lock index f5f04cb2..e60edb92 100644 --- a/sensor-nodes/Cargo.lock +++ b/sensor-nodes/Cargo.lock @@ -266,7 +266,6 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "defmt", "embassy-futures", @@ -283,7 +282,6 @@ dependencies = [ [[package]] name = "embassy-executor" version = "0.6.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "cortex-m", "critical-section", @@ -297,7 +295,6 @@ dependencies = [ [[package]] name = "embassy-executor-macros" version = "0.5.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "darling", "proc-macro2", @@ -308,12 +305,10 @@ dependencies = [ [[package]] name = "embassy-futures" version = "0.1.1" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" [[package]] name = "embassy-hal-internal" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "cortex-m", "critical-section", @@ -324,7 +319,6 @@ dependencies = [ [[package]] name = "embassy-net" version = "0.4.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "defmt", "document-features", @@ -341,7 +335,6 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "defmt", ] @@ -349,7 +342,6 @@ dependencies = [ [[package]] name = "embassy-net-driver-channel" version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "embassy-futures", "embassy-net-driver", @@ -359,7 +351,6 @@ dependencies = [ [[package]] name = "embassy-net-wiznet" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "defmt", "embassy-futures", @@ -372,7 +363,6 @@ dependencies = [ [[package]] name = "embassy-stm32" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "aligned", "bit_field", @@ -418,7 +408,6 @@ dependencies = [ [[package]] name = "embassy-sync" version = "0.6.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "cfg-if", "critical-section", @@ -431,7 +420,6 @@ dependencies = [ [[package]] name = "embassy-time" version = "0.3.2" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "cfg-if", "critical-section", @@ -449,7 +437,6 @@ dependencies = [ [[package]] name = "embassy-time-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "document-features", ] @@ -457,12 +444,10 @@ dependencies = [ [[package]] name = "embassy-time-queue-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" [[package]] name = "embassy-usb" version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "defmt", "embassy-futures", @@ -477,7 +462,6 @@ dependencies = [ [[package]] name = "embassy-usb-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "defmt", ] @@ -485,7 +469,6 @@ dependencies = [ [[package]] name = "embassy-usb-synopsys-otg" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "critical-section", "embassy-sync", @@ -1065,6 +1048,10 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "sensors" +version = "0.1.0" + [[package]] name = "serde" version = "1.0.210" diff --git a/sensor-nodes/Cargo.toml b/sensor-nodes/Cargo.toml index 935e2f00..1d793955 100644 --- a/sensor-nodes/Cargo.toml +++ b/sensor-nodes/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "2" -members = ["bed-sb", "bed-lb"] +members = ["bed-sb", "bed-lb", "sensors"] [workspace.dependencies] protocol = { path = "../crates/protocol" } @@ -17,18 +17,31 @@ embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime-ms", "tick-hz-32_768"] } embassy-futures = { version = "0.1.0"} +# [patch.crates-io] +# embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +# embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +# embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +# embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +# embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +# embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +# embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +# embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +# embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +# embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +# embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } + [patch.crates-io] -embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-stm32 = {path = "/home/david/Documents/embassy/embassy-stm32" } +embassy-net = {path = "/home/david/Documents/embassy/embassy-net" } +embassy-net-wiznet = {path = "/home/david/Documents/embassy/embassy-net-wiznet" } +embassy-sync = {path = "/home/david/Documents/embassy/embassy-sync" } +embassy-executor = {path = "/home/david/Documents/embassy/embassy-executor" } +embassy-embedded-hal = {path = "/home/david/Documents/embassy/embassy-embedded-hal" } +embassy-futures = {path = "/home/david/Documents/embassy/embassy-futures" } +embassy-time = {path = "/home/david/Documents/embassy/embassy-time" } +embassy-time-driver = {path = "/home/david/Documents/embassy/embassy-time-driver" } +embassy-time-queue-driver = {path = "/home/david/Documents/embassy/embassy-time-queue-driver" } +embassy-usb = {path = "/home/david/Documents/embassy/embassy-usb" } [workspace.package] rust-version = "1.78" @@ -44,5 +57,5 @@ lto = "fat" opt-level = "s" incremental = false codegen-units = 1 -# note: debug = true is okay - debuginfo isn't flashed to the device! +# note: debug = true is okay - debug-info isn't flashed to the device! debug = true diff --git a/sensor-nodes/bed-sb/src/main.rs b/sensor-nodes/bed-sb/src/main.rs index 801f9afb..b8dab86f 100644 --- a/sensor-nodes/bed-sb/src/main.rs +++ b/sensor-nodes/bed-sb/src/main.rs @@ -24,6 +24,7 @@ use {defmt_rtt as _, panic_probe as _}; mod channel; mod comms; mod error_cache; +mod reset_on_error_i2c; mod sensors; mod usb_wrapper; use crate::channel::Queues; @@ -41,11 +42,11 @@ embassy_stm32::bind_interrupts!(struct Irqs { // 84 Mhz clock stm32f401 // 48 Mhz clock for usb fn config() -> Config { + use embassy_stm32::rcc::mux; use embassy_stm32::rcc::{ - AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllQDiv, PllPreDiv, PllSource, - Sysclk, + AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllPreDiv, PllQDiv, + PllSource, Sysclk, }; - use embassy_stm32::rcc::mux; let mut config = Config::default(); config.rcc.hse = Some(Hse { @@ -111,6 +112,7 @@ async fn main(_spawner: Spawner) { Hertz(150_000), i2c::Config::default(), ); + let i2c_1 = reset_on_error_i2c::I2c::new(i2c_1, Hertz(150_000), i2c::Config::default()); let i2c_1: Mutex = Mutex::new(i2c_1); let i2c_3 = I2c::new( @@ -124,6 +126,7 @@ async fn main(_spawner: Spawner) { Hertz(150_000), i2c::Config::default(), ); + let i2c_3 = reset_on_error_i2c::I2c::new(i2c_3, Hertz(150_000), i2c::Config::default()); let i2c_3: Mutex = Mutex::new(i2c_3); let buttons = ButtonInputs { diff --git a/sensor-nodes/bed-sb/src/reset_on_error_i2c.rs b/sensor-nodes/bed-sb/src/reset_on_error_i2c.rs new file mode 100644 index 00000000..a6b1df54 --- /dev/null +++ b/sensor-nodes/bed-sb/src/reset_on_error_i2c.rs @@ -0,0 +1,74 @@ +use embassy_stm32::i2c::{Config, Error}; +use embassy_stm32::mode::Async; +use embassy_stm32::time::Hertz; +use embedded_hal::i2c::ErrorType; + +pub struct I2c<'d> { + inner: embassy_stm32::i2c::I2c<'d, Async>, + freq: Hertz, + config: Config, +} + +// impl<'d> From> for I2c<'d> { +// fn from(value: embassy_stm32::i2c::I2c<'d, Async>) -> Self { +// Self { inner: value } +// } +// } + +impl<'d> I2c<'d> { + pub fn new(i2c: embassy_stm32::i2c::I2c<'d, Async>, freq: Hertz, config: Config) -> Self { + Self { + inner: i2c, + freq, + config, + } + } +} + +impl ErrorType for I2c<'_> { + type Error = Error; +} + +impl embedded_hal_async::i2c::I2c for I2c<'_> { + async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { + let res = self.inner.read(address, read).await; + if let Err(Error::Arbitration) = res { + self.inner.clear_error(); + self.inner.reset(self.freq, self.config) + } + return res; + } + + async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { + let res = self.inner.write(address, write).await; + if let Err(Error::Arbitration) = res { + self.inner.clear_error(); + } + return res; + } + + async fn write_read( + &mut self, + address: u8, + write: &[u8], + read: &mut [u8], + ) -> Result<(), Self::Error> { + let res = self.inner.write_read(address, write, read).await; + if let Err(Error::Arbitration) = res { + self.inner.clear_error(); + } + return res; + } + + async fn transaction( + &mut self, + address: u8, + operations: &mut [embedded_hal::i2c::Operation<'_>], + ) -> Result<(), Self::Error> { + let res = self.inner.transaction(address, operations).await; + if let Err(Error::Arbitration) = res { + self.inner.clear_error(); + } + return res; + } +} diff --git a/sensor-nodes/bed-sb/src/sensors.rs b/sensor-nodes/bed-sb/src/sensors.rs index 9840ae71..38e14523 100644 --- a/sensor-nodes/bed-sb/src/sensors.rs +++ b/sensor-nodes/bed-sb/src/sensors.rs @@ -1,7 +1,6 @@ use defmt::info; use embassy_embedded_hal::shared_bus::I2cDeviceError; use embassy_futures::join; -use embassy_stm32::i2c::I2c; use embassy_stm32::mode::Async; use embassy_stm32::usart::Uart; use embassy_sync::blocking_mutex::raw::NoopRawMutex; @@ -14,6 +13,7 @@ use sps30_async::Sps30; use crate::channel::Queues; use crate::error_cache::{Error, SensorError}; +use crate::reset_on_error_i2c::I2c; pub mod fast; pub mod retry; pub mod slow; @@ -25,13 +25,14 @@ pub type UartError = embassy_stm32::usart::Error; pub mod concrete_types { use embassy_embedded_hal::shared_bus; - use embassy_stm32::i2c::I2c; use embassy_stm32::mode::Async; use embassy_stm32::usart::{RingBufferedUartRx, UartTx}; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use shared_bus::asynch::i2c::I2cDevice; - pub type ConcreteSharedI2c<'a> = I2cDevice<'a, NoopRawMutex, I2c<'static, Async>>; + use crate::reset_on_error_i2c::I2c; + + pub type ConcreteSharedI2c<'a> = I2cDevice<'a, NoopRawMutex, I2c<'static>>; pub type ConcreteTx<'a> = UartTx<'a, Async>; pub type ConcreteRx<'a> = RingBufferedUartRx<'a>; } @@ -42,8 +43,8 @@ const SPS30_DRIVER_BUF_SIZE: usize = 2 * SPS30_UART_BUF_SIZE; pub async fn init_then_measure( publish: &Queues, orderers: &slow::DriverOrderers, - i2c_1: Mutex>, - i2c_3: Mutex>, + i2c_1: Mutex>, + i2c_3: Mutex>, usart_mhz: Uart<'static, Async>, usart_sps: Uart<'static, Async>, buttons: ButtonInputs, diff --git a/sensor-nodes/bed-sb/src/sensors/retry.rs b/sensor-nodes/bed-sb/src/sensors/retry.rs index f25e1046..52d1aa38 100644 --- a/sensor-nodes/bed-sb/src/sensors/retry.rs +++ b/sensor-nodes/bed-sb/src/sensors/retry.rs @@ -1,7 +1,5 @@ use bosch_bme680::Bme680; use embassy_embedded_hal::shared_bus; -use embassy_stm32::i2c::I2c; -use embassy_stm32::mode::Async; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; use embassy_time::{Delay, Timer}; @@ -12,6 +10,7 @@ use sht31::SHT31; use super::concrete_types::ConcreteSharedI2c; use crate::error_cache::SensorError; +use crate::reset_on_error_i2c::I2c; mod reinit_on_error; pub use reinit_on_error::{ @@ -22,7 +21,7 @@ mod retry_init; pub use retry_init::Sps30Driver; impl<'a> ReInitableDriver for SHT31> { - type Parts = &'a Mutex>; + type Parts = &'a Mutex>; type Measurement = sht31::Reading; async fn init(parts: Self::Parts) -> Result { @@ -46,7 +45,7 @@ impl<'a> ReInitableDriver for SHT31> { } impl<'a> ReInitableDriver for Bme680, Delay> { - type Parts = &'a Mutex>; + type Parts = &'a Mutex>; type Measurement = bosch_bme680::MeasurementData; async fn init(parts: Self::Parts) -> Result { @@ -68,7 +67,7 @@ impl<'a> ReInitableDriver for Bme680, Delay> { } impl<'a> ReInitableDriver for Max44009> { - type Parts = &'a Mutex>; + type Parts = &'a Mutex>; type Measurement = f32; async fn init(parts: Self::Parts) -> Result { @@ -88,7 +87,7 @@ impl<'a> ReInitableDriver for Max44009> { } impl<'a> ReInitableDriver for Nau7802, Delay> { - type Parts = &'a Mutex>; + type Parts = &'a Mutex>; type Measurement = u32; async fn init(parts: Self::Parts) -> Result { diff --git a/sensor-nodes/rust-toolchain.toml b/sensor-nodes/rust-toolchain.toml new file mode 100644 index 00000000..c17f644e --- /dev/null +++ b/sensor-nodes/rust-toolchain.toml @@ -0,0 +1,6 @@ +[toolchain] +channel = "stable" +components = [ "rust-src", "rustfmt", "llvm-tools" ] +targets = [ + "thumbv7em-none-eabihf", +] From d3d457ec07135d1ae0a45a3e323ffb2b8dd49395 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 10 Oct 2024 20:51:39 +0200 Subject: [PATCH 303/687] tui: fix labels not in correct timezone --- .../sensor-tui/src/time/format/progressively_more_specified.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/sensor-tui/src/time/format/progressively_more_specified.rs b/crates/sensor-tui/src/time/format/progressively_more_specified.rs index 1105c2e6..41c0f636 100644 --- a/crates/sensor-tui/src/time/format/progressively_more_specified.rs +++ b/crates/sensor-tui/src/time/format/progressively_more_specified.rs @@ -62,6 +62,7 @@ impl FmtScale { return "now".to_string(); } + let t = t.to_zoned(jiff::tz::TimeZone::system()); match self { FmtScale::RelativeDuration => duration(elapsed.as_secs_f64()) + duration_postfix, FmtScale::HourMinute => t.strftime("%H:%M").to_string(), From 82ce2f54ad00101724f28e371bf9f3679d153e78 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 10 Oct 2024 23:30:45 +0200 Subject: [PATCH 304/687] add a tree as reading store, tui tree is rebuild every render based on that tree --- Cargo.lock | 25 +++ crates/sensor-tui/Cargo.toml | 1 + crates/sensor-tui/src/tui/readings.rs | 1 + crates/sensor-tui/src/tui/readings/render.rs | 10 +- .../src/tui/readings/render/tree.rs | 71 +++++++ .../src/tui/readings/sensor_info.rs | 174 ++++++++++++++++++ 6 files changed, 279 insertions(+), 3 deletions(-) create mode 100644 crates/sensor-tui/src/tui/readings/render/tree.rs diff --git a/Cargo.lock b/Cargo.lock index dd78fc6d..981361c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1786,6 +1786,30 @@ dependencies = [ "hashbrown 0.15.0", ] +[[package]] +name = "indextree" +version = "4.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6f1b8dbc8f1e5a0f45e05b9293c42cbab79086baeb3e914d3936f8149edc4f" +dependencies = [ + "indextree-macros", +] + +[[package]] +name = "indextree-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357230c23ee6024223892ce0de19888a04139ca5bb94f5becb04d38b75a4bccf" +dependencies = [ + "either", + "itertools", + "proc-macro2", + "quote", + "strum", + "syn 2.0.79", + "thiserror", +] + [[package]] name = "instability" version = "0.3.2" @@ -2944,6 +2968,7 @@ dependencies = [ "data-store", "gethostname", "hdrhistogram", + "indextree", "itertools", "jiff", "log-store", diff --git a/crates/sensor-tui/Cargo.toml b/crates/sensor-tui/Cargo.toml index 0451d327..e9eb46f2 100644 --- a/crates/sensor-tui/Cargo.toml +++ b/crates/sensor-tui/Cargo.toml @@ -28,3 +28,4 @@ thiserror.workspace = true itertools = "0.13.0" gethostname = "0.5.0" strip-ansi-escapes = "0.2.0" +indextree = "4.7.2" diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index 105865a3..4ff4d6ec 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -30,6 +30,7 @@ pub struct UiState { history_length: HistoryLen, input_mode: InputMode, tree_state: TreeState, + tree_state2: TreeState, logs_table_state: TableState, } diff --git a/crates/sensor-tui/src/tui/readings/render.rs b/crates/sensor-tui/src/tui/readings/render.rs index d2415f5a..32abc4a5 100644 --- a/crates/sensor-tui/src/tui/readings/render.rs +++ b/crates/sensor-tui/src/tui/readings/render.rs @@ -19,6 +19,7 @@ use super::{ pub mod chart; mod logs; +mod tree; pub(crate) fn layout( frame: &mut Frame, @@ -183,14 +184,16 @@ pub(crate) fn readings_and_details( readings: &Readings, details: Option
, ) { - let readings = &readings.ground; + let tree_old = &readings.ground; let [left, right] = Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]) .flex(Flex::Legacy) .areas(layout); + let tree = tree::build_ui(readings); frame.render_stateful_widget( - Tree::new(readings) + Tree::new(&tree) + // Tree::new(tree_old) .expect("all item identifiers should be unique") .block( Block::default() @@ -200,7 +203,8 @@ pub(crate) fn readings_and_details( .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) .highlight_symbol(">>"), left, - &mut app.tree_state, + // &mut app.tree_state, + &mut app.tree_state2, ); if let Some(details) = details { render_details(frame, right, details); diff --git a/crates/sensor-tui/src/tui/readings/render/tree.rs b/crates/sensor-tui/src/tui/readings/render/tree.rs new file mode 100644 index 00000000..75b7f71b --- /dev/null +++ b/crates/sensor-tui/src/tui/readings/render/tree.rs @@ -0,0 +1,71 @@ +use indextree::Arena; +use tui_tree_widget::TreeItem; + +use crate::tui::readings::sensor_info::{Node, Readings, SensorInfo}; + +#[derive(Default)] +struct IdGen(u16); + +impl IdGen { + fn next(&mut self) -> u16 { + self.0 += 1; + assert!(self.0 < 10_000, "to many id's generated"); + self.0 + } +} + +pub(crate) fn build_ui<'a>(readings: &'a Readings) -> Vec> { + let mut id_gen = IdGen::default(); + + readings + .root + .children(&readings.arena) + .map( + |subroot| match readings.arena.get(subroot).expect("child exists").get() { + Node::Sensor(info) => new_leaf(info), + Node::Branch(name) => TreeItem::new( + id_gen.next(), + name.as_str(), + recusive_call(subroot, &readings.arena, &mut id_gen), + ) + .expect("no duplicate ids"), + Node::Root => unreachable!("Root is not a descendant"), + }, + ) + .collect() +} + +fn recusive_call<'a>( + root: indextree::NodeId, + arena: &'a Arena, + id_gen: &mut IdGen, +) -> Vec> { + root.children(arena) + .map(|child_id| { + let child_node = arena.get(child_id).expect("child exists").get(); + match child_node { + Node::Sensor(info) => new_leaf(info), + Node::Branch(name) => TreeItem::new( + id_gen.next(), + name.as_str(), + recusive_call(root, arena, id_gen), + ) + .expect("no duplicate ids"), + Node::Root => unreachable!("Root is not a descendant"), + } + }) + .collect() +} + +fn new_leaf(info: &SensorInfo) -> TreeItem { + use protocol::reading::tree::Tree as _; + + let text = format!( + "{0}: {1:.2$} {3}", + info.reading.name(), + info.info.val, + info.info.precision(), + info.info.unit + ); + TreeItem::new_leaf(info.id, text) +} diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index c0b274d8..15c20745 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -1,4 +1,5 @@ use hdrhistogram::Histogram; +use indextree::{Arena, NodeId}; use itertools::Itertools; use jiff::Unit; use log_store::api::{self, Percentile}; @@ -18,8 +19,16 @@ mod logs; pub(crate) use logs::List as LogList; pub(crate) use logs::LogSource; +#[derive(Debug)] +pub enum Node { + Sensor(SensorInfo), + Branch(String), + Root, +} + #[derive(Debug)] pub struct SensorInfo { + pub id: u16, pub info: reading::Info, /// This value is not up to date, only use for requesting /// data use the last element of recent_history for printing @@ -31,6 +40,7 @@ pub struct SensorInfo { pub history_from_store: Vec<(jiff::Timestamp, f32)>, condition: Result<(), Box>, pub(crate) logs: logs::Logs, + pub placeholder: bool, } pub struct ErrorDensity { @@ -184,11 +194,27 @@ impl SensorInfo { } } +pub struct IdGen(u16); +impl IdGen { + fn new() -> Self { + Self(10_000) + } + fn next(&mut self) -> u16 { + self.0 += 1; + self.0 + } +} + /// Guaranteed to be unique for a leaf, /// the path to the leaf (through branch-id's) is /// encoded with the last byte byte being the leaf's id pub type TreeKey = [u8; 6]; pub struct Readings { + // new tree, we are porting to this + pub lookup: Vec<(Reading, indextree::NodeId)>, + pub arena: indextree::Arena, + pub root: NodeId, + pub idgen: IdGen, // In the ground there are multiple trees pub ground: Vec>, pub data: HashMap, @@ -260,6 +286,7 @@ pub(crate) fn tree_key(reading: &Reading) -> TreeKey { unreachable!("reading should not be deeper then key size") } +#[derive(Debug, PartialEq, Eq)] enum IsPlaceholder { Yes, No, @@ -268,6 +295,7 @@ enum IsPlaceholder { impl Readings { pub fn update(&mut self, reading: Reading) { self.update_tree(&reading, IsPlaceholder::No); + self.update_tree2(&reading, IsPlaceholder::No); self.record_data(reading); } @@ -287,6 +315,7 @@ impl Readings { pub fn add_error(&mut self, error: Box) { self.update_tree_err(&error); + self.update_tree_err2(&error); self.record_error(error); } @@ -313,6 +342,8 @@ impl Readings { condition: Err(error.clone()), logs, + placeholder: true, + id: self.idgen.next(), }, ); } @@ -347,6 +378,8 @@ impl Readings { condition: Ok(()), logs: logs::Logs::new_empty(), + placeholder: true, + id: self.idgen.next(), }, ); } @@ -372,10 +405,64 @@ impl Readings { condition: Ok(()), logs: logs::Logs::new_empty(), + placeholder: true, + id: self.idgen.next(), }, ); } + fn update_tree2(&mut self, reading: &Reading, placeholder: IsPlaceholder) { + let existing = self + .lookup + .iter() + .find(|(r, _)| r.is_same_as(reading)) + .map(|(_, id)| id) + .and_then(|id| self.arena.get_mut(*id)) + .map(indextree::Node::get_mut); + + let time = jiff::Timestamp::now(); + if let Some(node) = existing { + let Node::Sensor(ref mut info) = node else { + panic!("got other node then Sensor for reading"); + }; + assert_eq!( + IsPlaceholder::No, + placeholder, + "cant be a placeholder if there is already a valid node" + ); + info.reading = reading.clone(); + if let Some(last_reading) = info.last_at() { + info.timing += (time - last_reading) + .total(Unit::Millisecond) + .expect("no calander units involved") as u64 + } + info.recent_history.push((time, reading.leaf().val)); + info.condition = Ok(()); + } else { + let history = vec![(time, reading.leaf().val)]; + let info = SensorInfo { + info: reading.leaf(), + reading: reading.clone(), + timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), + percentiles_from_store: Vec::new(), + histogram_range: None, + + recent_history: history, + history_from_store: Vec::new(), + + condition: Ok(()), + logs: logs::Logs::new_empty(), + placeholder: true, + id: self.idgen.next(), + }; + + let node_id = self.arena.new_node(Node::Sensor(info)); + let parent = build_parents(&mut self.arena, self.root, &reading); + parent.append(node_id, &mut self.arena); + self.lookup.push((reading.clone(), node_id)); + } + } + fn update_tree(&mut self, reading: &Reading, placeholder: IsPlaceholder) { let key = tree_key(reading); tracing::trace!("reading: {reading:?}"); @@ -435,6 +522,45 @@ impl Readings { } } + fn update_tree_err2(&mut self, error: &Error) { + for broken in error.device().info().affects_readings { + let existing = self + .lookup + .iter() + .find(|(r, _)| r.is_same_as(broken)) + .map(|(_, id)| id) + .and_then(|id| self.arena.get_mut(*id)) + .map(indextree::Node::get_mut); + + if let Some(node) = existing { + let Node::Sensor(ref mut info) = node else { + panic!("got other node then Sensor for Error"); + }; + info.condition = Err(Box::new(error.clone())); + info.logs.add(&error); + } else { + let logs = logs::Logs::new_from(&error); + let info = SensorInfo { + info: broken.leaf(), + reading: broken.clone(), + timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), + percentiles_from_store: Vec::new(), + histogram_range: None, + + recent_history: Vec::new(), + history_from_store: Vec::new(), + + condition: Err(Box::new(error.clone())), + logs, + placeholder: true, + id: self.idgen.next(), + }; + let node_id = self.arena.new_node(Node::Sensor(info)); + self.lookup.push((broken.clone(), node_id)); + } + } + } + pub(crate) fn add_fetched(&mut self, reading: Reading, fetched: Fetchable) { let sensorinfo = self .data @@ -458,13 +584,61 @@ impl Readings { } pub(crate) fn new() -> Self { + let mut arena = Arena::new(); + let root = arena.new_node(Node::Root); Self { + lookup: Vec::new(), + arena, + root, ground: Vec::new(), data: HashMap::new(), + idgen: IdGen::new(), } } } +fn build_parents(arena: &mut Arena, root: NodeId, reading: &Reading) -> NodeId { + let mut curr = match reading.inner() { + Item::Leaf(_) => unreachable!("no leafs without parents"), + Item::Node(inner) => inner, + }; + + let mut parent = get_branch_by_name(arena, root, curr.name()) + .unwrap_or_else(|| arena.new_node(Node::Branch(curr.name()))); + + loop { + match curr.inner() { + Item::Leaf(_) => return parent, + Item::Node(inner) => { + parent = get_branch_by_name(arena, root, inner.name()).unwrap_or_else(|| { + let new = arena.new_node(Node::Branch(curr.name())); + parent.append(new, arena); + new + }); + curr = inner; + } + } + } +} + +fn get_branch_by_name( + arena: &mut Arena, + root: NodeId, + name_to_find: String, +) -> Option { + root.children(arena).find(|node| { + match arena + .get(*node) + .expect("no changes since .children()") + .get() + { + Node::Root => unreachable!("root node is never a child"), + Node::Sensor(_) => false, + Node::Branch(name) => *name == name_to_find, + } + }) +} + pub struct ChartParts<'a> { pub reading: reading::Info, /// array of time, y From d16748691117278d943e4f507ceae63ae0b96779 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 11 Oct 2024 16:19:21 +0200 Subject: [PATCH 305/687] protocol fix error in is_same_as --- crates/protocol/src/large_bedroom/bed.rs | 4 ++-- crates/protocol/src/small_bedroom/bed.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 678c5933..26537fc8 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -272,8 +272,8 @@ impl Reading { | (Self::GassResistance(_), Self::GassResistance(_)) | (Self::Pressure(_), Self::Pressure(_)) | (Self::Co2(_), Self::Co2(_)) - | (Self::WeightLeft(_), Self::WeightLeft(0)) - | (Self::WeightRight(_), Self::WeightRight(0)) + | (Self::WeightLeft(_), Self::WeightLeft(_)) + | (Self::WeightRight(_), Self::WeightRight(_)) | (Self::MassPm1_0(_), Self::MassPm1_0(_)) | (Self::MassPm2_5(_), Self::MassPm2_5(_)) | (Self::MassPm4_0(_), Self::MassPm4_0(_)) diff --git a/crates/protocol/src/small_bedroom/bed.rs b/crates/protocol/src/small_bedroom/bed.rs index 30ae83d2..1748d4fb 100644 --- a/crates/protocol/src/small_bedroom/bed.rs +++ b/crates/protocol/src/small_bedroom/bed.rs @@ -253,7 +253,7 @@ impl Reading { | (Self::GassResistance(_), Self::GassResistance(_)) | (Self::Pressure(_), Self::Pressure(_)) | (Self::Co2(_), Self::Co2(_)) - | (Self::Weight(_), Self::Weight(0)) + | (Self::Weight(_), Self::Weight(_)) | (Self::MassPm1_0(_), Self::MassPm1_0(_)) | (Self::MassPm2_5(_), Self::MassPm2_5(_)) | (Self::MassPm4_0(_), Self::MassPm4_0(_)) From 9c7fb467774b2ccf1e81924c6c21bd3d2eb5e9f4 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 11 Oct 2024 16:47:55 +0200 Subject: [PATCH 306/687] fix new tree, remove updates of old tui tree --- crates/sensor-tui/Cargo.toml | 1 + crates/sensor-tui/src/tui/readings.rs | 21 +- crates/sensor-tui/src/tui/readings/render.rs | 12 +- .../src/tui/readings/render/chart/labels.rs | 2 +- .../src/tui/readings/render/chart/split.rs | 1 + .../src/tui/readings/render/tree.rs | 31 +- .../src/tui/readings/sensor_info.rs | 449 ++++++------------ 7 files changed, 170 insertions(+), 347 deletions(-) diff --git a/crates/sensor-tui/Cargo.toml b/crates/sensor-tui/Cargo.toml index e9eb46f2..8e2e1dbe 100644 --- a/crates/sensor-tui/Cargo.toml +++ b/crates/sensor-tui/Cargo.toml @@ -29,3 +29,4 @@ itertools = "0.13.0" gethostname = "0.5.0" strip-ansi-escapes = "0.2.0" indextree = "4.7.2" +derivative = "2.2.0" diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index 4ff4d6ec..dd7cfcc9 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -12,7 +12,7 @@ pub mod sensor_info; use history_len::HistoryLen; use crate::{fetch::Fetch, Update}; -use sensor_info::{Readings, TreeKey}; +use sensor_info::Readings; use super::Theme; @@ -29,8 +29,7 @@ pub struct UiState { show_logs: bool, history_length: HistoryLen, input_mode: InputMode, - tree_state: TreeState, - tree_state2: TreeState, + tree_state: TreeState, logs_table_state: TableState, } @@ -63,7 +62,7 @@ impl Tab { .tree_state .selected() .last() // Unique leaf id - .and_then(|key| readings.data.get_mut(key)); + .and_then(|key| readings.get_by_ui_id(*key)); if let Some(data) = data { ( @@ -78,14 +77,8 @@ impl Tab { } }; - let [top, bottom, footer] = render::layout( - frame, - layout, - ui_state, - readings, - chart.is_some(), - logs.is_some(), - ); + let [top, bottom, footer] = + render::layout(frame, layout, readings, chart.is_some(), logs.is_some()); let have_details = details.is_some(); render::readings_and_details(frame, top, ui_state, readings, details); @@ -111,7 +104,7 @@ impl Tab { .tree_state .selected() .last() // Unique leaf id - .and_then(|key| self.readings.data.get_mut(key)); + .and_then(|key| self.readings.get_by_ui_id(*key)); match update { Update::SensorReading(reading) => { @@ -151,7 +144,7 @@ impl Tab { .tree_state .selected() .last() // Unique leaf id - .and_then(|key| self.readings.data.get_mut(key)) + .and_then(|key| self.readings.get_by_ui_id(*key)) else { return; // Nothing selected }; diff --git a/crates/sensor-tui/src/tui/readings/render.rs b/crates/sensor-tui/src/tui/readings/render.rs index 32abc4a5..3ba0d556 100644 --- a/crates/sensor-tui/src/tui/readings/render.rs +++ b/crates/sensor-tui/src/tui/readings/render.rs @@ -24,13 +24,16 @@ mod tree; pub(crate) fn layout( frame: &mut Frame, layout: Rect, - ui_state: &mut UiState, readings: &Readings, chart: bool, logs: bool, ) -> [Rect; 3] { let [list_constraint, graph_constraint] = if chart { - let tree_height = 2 + ui_state.tree_state.flatten(&readings.ground).len(); + let tree_height = 2 + readings + .arena + .iter() + .filter(|node| node.is_removed()) + .count(); let details_height = 9; if (frame.area().height as f32) / 3. > tree_height as f32 { [ @@ -184,7 +187,6 @@ pub(crate) fn readings_and_details( readings: &Readings, details: Option
, ) { - let tree_old = &readings.ground; let [left, right] = Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]) .flex(Flex::Legacy) @@ -193,7 +195,6 @@ pub(crate) fn readings_and_details( let tree = tree::build_ui(readings); frame.render_stateful_widget( Tree::new(&tree) - // Tree::new(tree_old) .expect("all item identifiers should be unique") .block( Block::default() @@ -203,8 +204,7 @@ pub(crate) fn readings_and_details( .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) .highlight_symbol(">>"), left, - // &mut app.tree_state, - &mut app.tree_state2, + &mut app.tree_state, ); if let Some(details) = details { render_details(frame, right, details); diff --git a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs index 814a3947..521265ec 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs @@ -24,7 +24,7 @@ pub fn labels( // Characters are about twice as high as wide let x = evenly_spaced_labels(layout.width / y_label_spacing / 2, info, x_bounds) .rev() - .map(|x| fmt(x, &scale)) + .map(|x| fmt(x, scale)) .map(Into::into) .collect(); let y = evenly_spaced_labels(layout.height / y_label_spacing, info, y_bounds) diff --git a/crates/sensor-tui/src/tui/readings/render/chart/split.rs b/crates/sensor-tui/src/tui/readings/render/chart/split.rs index 48b80a61..4ef5e77d 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/split.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/split.rs @@ -7,6 +7,7 @@ use crate::tui::readings::sensor_info::ChartParts; /// split data into separate lines if /// - the gap between point groups is larger then what is expected for /// the given sensor with 20% margin +/// /// and /// - the gap is larger then the medium in the data /// diff --git a/crates/sensor-tui/src/tui/readings/render/tree.rs b/crates/sensor-tui/src/tui/readings/render/tree.rs index 75b7f71b..592c176f 100644 --- a/crates/sensor-tui/src/tui/readings/render/tree.rs +++ b/crates/sensor-tui/src/tui/readings/render/tree.rs @@ -14,7 +14,7 @@ impl IdGen { } } -pub(crate) fn build_ui<'a>(readings: &'a Readings) -> Vec> { +pub(crate) fn build_ui(readings: &Readings) -> Vec> { let mut id_gen = IdGen::default(); readings @@ -48,7 +48,7 @@ fn recusive_call<'a>( Node::Branch(name) => TreeItem::new( id_gen.next(), name.as_str(), - recusive_call(root, arena, id_gen), + recusive_call(child_id, arena, id_gen), ) .expect("no duplicate ids"), Node::Root => unreachable!("Root is not a descendant"), @@ -58,14 +58,23 @@ fn recusive_call<'a>( } fn new_leaf(info: &SensorInfo) -> TreeItem { - use protocol::reading::tree::Tree as _; + use protocol::reading::tree::{Item, Tree}; - let text = format!( - "{0}: {1:.2$} {3}", - info.reading.name(), - info.info.val, - info.info.precision(), - info.info.unit - ); - TreeItem::new_leaf(info.id, text) + let mut node = &info.reading as &dyn Tree; + while let Item::Node(inner) = node.inner() { + node = inner; + } + + if info.is_placeholder { + TreeItem::new_leaf(info.ui_id, node.name()) + } else { + let text = format!( + "{0}: {1:.2$} {3}", + node.name(), + info.info.val, + info.info.precision(), + info.info.unit + ); + TreeItem::new_leaf(info.ui_id, text) + } } diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index 15c20745..c977ff0c 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -8,10 +8,8 @@ use protocol::reading::tree::{Item, Tree}; use protocol::Reading; use protocol::{Device, Error}; -use std::collections::HashMap; use std::ops::RangeInclusive; use std::time::Duration; -use tui_tree_widget::TreeItem; use crate::Fetchable; @@ -19,6 +17,11 @@ mod logs; pub(crate) use logs::List as LogList; pub(crate) use logs::LogSource; +#[expect( + clippy::large_enum_variant, + reason = "Stored on the heap through Vec, mem waste of Branches is \ + worth the perf of not boxing SensorInfo" +)] #[derive(Debug)] pub enum Node { Sensor(SensorInfo), @@ -26,21 +29,89 @@ pub enum Node { Root, } -#[derive(Debug)] +#[derive(derivative::Derivative)] +#[derivative(Debug)] pub struct SensorInfo { - pub id: u16, + /// unique id used by the rendered tree to refer back to + /// this specific item. + pub ui_id: u16, + #[derivative(Debug = "ignore")] pub info: reading::Info, /// This value is not up to date, only use for requesting /// data use the last element of recent_history for printing pub reading: Reading, + #[derivative(Debug = "ignore")] timing: Histogram, + #[derivative(Debug = "ignore")] pub percentiles_from_store: Vec, + #[derivative(Debug = "ignore")] recent_history: Vec<(jiff::Timestamp, f32)>, pub histogram_range: Option>, + #[derivative(Debug = "ignore")] pub history_from_store: Vec<(jiff::Timestamp, f32)>, condition: Result<(), Box>, + #[derivative(Debug = "ignore")] pub(crate) logs: logs::Logs, - pub placeholder: bool, + pub is_placeholder: bool, +} + +impl SensorInfo { + fn new(reading: &Reading, is_placeholder: bool, ui_id: u16) -> Self { + let time = jiff::Timestamp::now(); + let recent_history = if is_placeholder { + Vec::new() + } else { + vec![(time, reading.leaf().val)] + }; + + Self { + info: reading.leaf(), + reading: reading.clone(), + timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), + percentiles_from_store: Vec::new(), + histogram_range: None, + + recent_history, + history_from_store: Vec::new(), + + condition: Ok(()), + logs: logs::Logs::new_empty(), + is_placeholder, + ui_id, + } + } + + fn new_err(error: &Error, broken: &Reading, ui_id: u16) -> Self { + let logs = logs::Logs::new_from(error); + SensorInfo { + info: broken.leaf(), + reading: broken.clone(), + timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), + percentiles_from_store: Vec::new(), + histogram_range: None, + + recent_history: Vec::new(), + history_from_store: Vec::new(), + + condition: Err(Box::new(error.clone())), + logs, + is_placeholder: true, + ui_id, + } + } + + fn update(&mut self, reading: &Reading) { + let time = jiff::Timestamp::now(); + self.info = reading.leaf(); + if let Some(last_reading) = self.last_at() { + self.timing += (time - last_reading) + .total(Unit::Millisecond) + .expect("no calander units involved") as u64 + } + self.recent_history.push((time, reading.leaf().val)); + self.is_placeholder = false; + self.condition = Ok(()); + } } pub struct ErrorDensity { @@ -210,322 +281,82 @@ impl IdGen { /// encoded with the last byte byte being the leaf's id pub type TreeKey = [u8; 6]; pub struct Readings { - // new tree, we are porting to this - pub lookup: Vec<(Reading, indextree::NodeId)>, + pub lookup_by_reading: Vec<(Reading, indextree::NodeId)>, + pub lookup_by_ui_id: Vec<(u16, indextree::NodeId)>, pub arena: indextree::Arena, pub root: NodeId, pub idgen: IdGen, - // In the ground there are multiple trees - pub ground: Vec>, - pub data: HashMap, -} - -fn add_leaf(text: String, tree: &mut TreeItem<'static, TreeKey>, key: TreeKey) { - let new_item = TreeItem::new_leaf(key, text.clone()); - // Todo is exists its fine handle that - let _ignore_existing = tree.add_child(new_item); // Errors when identifier already exists - - let new_child = tree - .children() - .iter() - .position(|item| *item.identifier() == key) - .expect("just added it"); - let existing = tree.child_mut(new_child).expect("just added it"); - existing.update_text(text); } -fn add_root<'a>( - tomato: &dyn Tree, - ground: &'a mut Vec>, -) -> &'a mut TreeItem<'static, TreeKey> { - let key = [tomato.branch_id(); 6]; - let exists = ground.iter().any(|item| *item.identifier() == key); - if !exists { - let new_root = TreeItem::new(key, tomato.name(), vec![]).unwrap(); - ground.push(new_root); - } - - ground - .iter_mut() - .find(|item| *item.identifier() == key) - .expect("checked and added if missing") -} - -fn add_node<'a>( - tomato: &dyn Tree, - tree: &'a mut TreeItem<'static, TreeKey>, -) -> &'a mut TreeItem<'static, TreeKey> { - let key = [tomato.branch_id(); 6]; - let new_item = TreeItem::new(key, tomato.name(), Vec::new()).unwrap(); - // Add just in case it was not there yet - let _ignore_existing = tree.add_child(new_item); - let new_child = tree - .children() - .iter() - .position(|item| *item.identifier() == key) - .expect("just added it"); - tree.child_mut(new_child).expect("just added it") -} - -pub(crate) fn tree_key(reading: &Reading) -> TreeKey { - let mut key = [0u8; 6]; - key[0] = reading.branch_id(); - - let mut reading = reading as &dyn Tree; - for byte in &mut key[1..] { - reading = match reading.inner() { - Item::Node(inner) => { - *byte = inner.branch_id(); - inner - } - Item::Leaf(reading::Info { .. }) => { - return key; - } - }; +impl Readings { + pub fn get_by_ui_id(&mut self, id: u16) -> Option<&mut SensorInfo> { + self.lookup_by_ui_id + .iter_mut() + .find(|(ui_id, _)| id == *ui_id) + .map(|(_, node_id)| node_id) + .and_then(|id| self.arena.get_mut(*id)) + .map(indextree::Node::get_mut) + .map(|node| match node { + Node::Sensor(info) => info, + Node::Branch(_) | Node::Root => { + unreachable!("Only Sensor nodes are put in the lookup table") + } + }) } - unreachable!("reading should not be deeper then key size") -} - -#[derive(Debug, PartialEq, Eq)] -enum IsPlaceholder { - Yes, - No, -} -impl Readings { pub fn update(&mut self, reading: Reading) { - self.update_tree(&reading, IsPlaceholder::No); - self.update_tree2(&reading, IsPlaceholder::No); - self.record_data(reading); + self.update_tree(&reading, false); } pub(crate) fn populate_from_reading_list(&mut self, list: Vec) { for reading in list { - self.update_tree(&reading, IsPlaceholder::Yes); - self.record_missing_data(reading); + self.update_tree(&reading, true); } } pub(crate) fn populate_from_device_list(&mut self, list: Vec) { for reading in list.iter().flat_map(|d| d.info().affects_readings) { - self.update_tree(reading, IsPlaceholder::Yes); - self.record_missing_data(reading.clone()); + self.update_tree(reading, true); } } pub fn add_error(&mut self, error: Box) { self.update_tree_err(&error); - self.update_tree_err2(&error); - self.record_error(error); - } - - fn record_error(&mut self, error: Box) { - for broken in error.device().info().affects_readings { - let key = tree_key(broken); - - if let Some(info) = self.data.get_mut(&key) { - info.condition = Err(error.clone()); - info.logs.add(&error); - } else { - let logs = logs::Logs::new_from(&error); - self.data.insert( - key, - SensorInfo { - info: broken.leaf(), - reading: broken.clone(), - timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), - percentiles_from_store: Vec::new(), - histogram_range: None, - - recent_history: Vec::new(), - history_from_store: Vec::new(), - - condition: Err(error.clone()), - logs, - placeholder: true, - id: self.idgen.next(), - }, - ); - } - } - } - - fn record_data(&mut self, reading: Reading) { - let key = tree_key(&reading); - let time = jiff::Timestamp::now(); - - if let Some(info) = self.data.get_mut(&key) { - if let Some(last_reading) = info.last_at() { - info.timing += (time - last_reading) - .total(Unit::Millisecond) - .expect("no calander units involved") as u64 - } - info.recent_history.push((time, reading.leaf().val)); - info.condition = Ok(()); - } else { - let history = vec![(time, reading.leaf().val)]; - self.data.insert( - key, - SensorInfo { - info: reading.leaf(), - reading, - timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), - percentiles_from_store: Vec::new(), - histogram_range: None, - - recent_history: history, - history_from_store: Vec::new(), - - condition: Ok(()), - logs: logs::Logs::new_empty(), - placeholder: true, - id: self.idgen.next(), - }, - ); - } - } - - fn record_missing_data(&mut self, reading: Reading) { - let key = tree_key(&reading); - if self.data.contains_key(&key) { - return; - } - - self.data.insert( - key, - SensorInfo { - info: reading.leaf(), - reading, - timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), - percentiles_from_store: Vec::new(), - histogram_range: None, - - recent_history: Vec::new(), - history_from_store: Vec::new(), - - condition: Ok(()), - logs: logs::Logs::new_empty(), - placeholder: true, - id: self.idgen.next(), - }, - ); } - fn update_tree2(&mut self, reading: &Reading, placeholder: IsPlaceholder) { + fn update_tree(&mut self, reading: &Reading, is_placeholder: bool) { let existing = self - .lookup + .lookup_by_reading .iter() .find(|(r, _)| r.is_same_as(reading)) .map(|(_, id)| id) .and_then(|id| self.arena.get_mut(*id)) .map(indextree::Node::get_mut); - let time = jiff::Timestamp::now(); if let Some(node) = existing { let Node::Sensor(ref mut info) = node else { panic!("got other node then Sensor for reading"); }; - assert_eq!( - IsPlaceholder::No, - placeholder, - "cant be a placeholder if there is already a valid node" - ); - info.reading = reading.clone(); - if let Some(last_reading) = info.last_at() { - info.timing += (time - last_reading) - .total(Unit::Millisecond) - .expect("no calander units involved") as u64 + + if is_placeholder { + return; // can receive sensor update before populating from list } - info.recent_history.push((time, reading.leaf().val)); - info.condition = Ok(()); + info.update(reading); } else { - let history = vec![(time, reading.leaf().val)]; - let info = SensorInfo { - info: reading.leaf(), - reading: reading.clone(), - timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), - percentiles_from_store: Vec::new(), - histogram_range: None, - - recent_history: history, - history_from_store: Vec::new(), - - condition: Ok(()), - logs: logs::Logs::new_empty(), - placeholder: true, - id: self.idgen.next(), - }; - + let ui_id = self.idgen.next(); + let info = SensorInfo::new(reading, is_placeholder, ui_id); let node_id = self.arena.new_node(Node::Sensor(info)); - let parent = build_parents(&mut self.arena, self.root, &reading); + let parent = build_parents(&mut self.arena, self.root, reading); parent.append(node_id, &mut self.arena); - self.lookup.push((reading.clone(), node_id)); - } - } - - fn update_tree(&mut self, reading: &Reading, placeholder: IsPlaceholder) { - let key = tree_key(reading); - tracing::trace!("reading: {reading:?}"); - - let mut tree = add_root(reading as &dyn Tree, &mut self.ground); - let mut node = match reading.inner() { - Item::Leaf(_) => unreachable!("no values at level 0"), - Item::Node(inner) => inner, - }; - loop { - match node.inner() { - Item::Leaf(info) => { - let text = if let IsPlaceholder::Yes = placeholder { - node.name() - } else { - format!( - "{0}: {1:.2$} {3}", - node.name(), - info.val, - info.precision(), - info.unit - ) - }; - add_leaf(text, tree, key); - return; - } - Item::Node(inner) => { - tree = add_node(node, tree); - node = inner; - } - }; + self.lookup_by_reading.push((reading.clone(), node_id)); + self.lookup_by_ui_id.push((ui_id, node_id)); } } fn update_tree_err(&mut self, error: &Error) { - for broken in error.device().info().affects_readings { - let key = tree_key(broken); - - let mut tree = add_root(broken as &dyn Tree, &mut self.ground); - let mut tomato = match broken.inner() { - Item::Leaf(_) => unreachable!("no values at level 0"), - Item::Node(inner) => inner, - }; - loop { - match tomato.inner() { - Item::Leaf(_) => { - let text = format!("{}: {}", tomato.name(), error); - add_leaf(text, tree, key); - break; - } - Item::Node(inner) => { - tree = add_node(tomato, tree); - tomato = inner; - } - }; - } - } - } - - fn update_tree_err2(&mut self, error: &Error) { for broken in error.device().info().affects_readings { let existing = self - .lookup + .lookup_by_reading .iter() .find(|(r, _)| r.is_same_as(broken)) .map(|(_, id)| id) @@ -537,48 +368,43 @@ impl Readings { panic!("got other node then Sensor for Error"); }; info.condition = Err(Box::new(error.clone())); - info.logs.add(&error); + info.logs.add(error); } else { - let logs = logs::Logs::new_from(&error); - let info = SensorInfo { - info: broken.leaf(), - reading: broken.clone(), - timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), - percentiles_from_store: Vec::new(), - histogram_range: None, - - recent_history: Vec::new(), - history_from_store: Vec::new(), - - condition: Err(Box::new(error.clone())), - logs, - placeholder: true, - id: self.idgen.next(), - }; + let ui_id = self.idgen.next(); + let info = SensorInfo::new_err(error, broken, ui_id); let node_id = self.arena.new_node(Node::Sensor(info)); - self.lookup.push((broken.clone(), node_id)); + self.lookup_by_reading.push((broken.clone(), node_id)); + self.lookup_by_ui_id.push((ui_id, node_id)); } } } pub(crate) fn add_fetched(&mut self, reading: Reading, fetched: Fetchable) { - let sensorinfo = self - .data - .get_mut(&tree_key(&reading)) - .expect("data is never removed"); + let Node::Sensor(info) = self + .lookup_by_reading + .iter() + .find(|(r, _)| r.is_same_as(&reading)) + .map(|(_, id)| id) + .and_then(|id| self.arena.get_mut(*id)) + .map(indextree::Node::get_mut) + .expect("Data can only be fetched if it exists in the tree") + else { + panic!("Node for a reading should always be a sensornode"); + }; + match fetched { Fetchable::Data { timestamps, data } => { - sensorinfo.history_from_store = timestamps.into_iter().zip(data).collect(); + info.history_from_store = timestamps.into_iter().zip(data).collect(); } Fetchable::Logs { logs, start_at } => { - sensorinfo.logs.from_store = Some(logs::FromStore { + info.logs.from_store = Some(logs::FromStore { list: logs, since: start_at, }) } Fetchable::Hist { percentiles, range } => { - sensorinfo.percentiles_from_store = percentiles; - sensorinfo.histogram_range = Some(range); + info.percentiles_from_store = percentiles; + info.histogram_range = Some(range); } } } @@ -587,30 +413,23 @@ impl Readings { let mut arena = Arena::new(); let root = arena.new_node(Node::Root); Self { - lookup: Vec::new(), + lookup_by_reading: Vec::new(), + lookup_by_ui_id: Vec::new(), arena, root, - ground: Vec::new(), - data: HashMap::new(), idgen: IdGen::new(), } } } fn build_parents(arena: &mut Arena, root: NodeId, reading: &Reading) -> NodeId { - let mut curr = match reading.inner() { - Item::Leaf(_) => unreachable!("no leafs without parents"), - Item::Node(inner) => inner, - }; - - let mut parent = get_branch_by_name(arena, root, curr.name()) - .unwrap_or_else(|| arena.new_node(Node::Branch(curr.name()))); - + let mut curr = reading as &dyn Tree; + let mut parent = root; loop { match curr.inner() { Item::Leaf(_) => return parent, Item::Node(inner) => { - parent = get_branch_by_name(arena, root, inner.name()).unwrap_or_else(|| { + parent = get_child_by_name(arena, parent, curr.name()).unwrap_or_else(|| { let new = arena.new_node(Node::Branch(curr.name())); parent.append(new, arena); new @@ -621,7 +440,7 @@ fn build_parents(arena: &mut Arena, root: NodeId, reading: &Reading) -> No } } -fn get_branch_by_name( +fn get_child_by_name( arena: &mut Arena, root: NodeId, name_to_find: String, From a12fcce07c8abc141bcb4e2e6f47015048780877 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 11 Oct 2024 16:48:07 +0200 Subject: [PATCH 307/687] cargo update --- Cargo.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.lock b/Cargo.lock index 981361c2..d8bc27b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2966,6 +2966,7 @@ dependencies = [ "crossterm", "data-server", "data-store", + "derivative", "gethostname", "hdrhistogram", "indextree", From 55dd7b2c6a04c68857d2b4cc9a619c02603a363a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 12 Oct 2024 14:05:44 +0200 Subject: [PATCH 308/687] tui: display multiple graphs --- crates/protocol/src/lib.rs | 2 +- crates/sensor-tui/examples/chart_gaps.rs | 4 +- crates/sensor-tui/src/tui/readings.rs | 124 ++++++++++++++---- crates/sensor-tui/src/tui/readings/render.rs | 67 +++++++--- .../src/tui/readings/render/chart.rs | 124 +++++++++++++----- .../src/tui/readings/render/chart/labels.rs | 43 +++--- .../src/tui/readings/render/chart/split.rs | 6 +- .../src/tui/readings/render/tree.rs | 39 ++++-- .../src/tui/readings/sensor_info.rs | 8 +- 9 files changed, 296 insertions(+), 121 deletions(-) diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 3b042f00..42026c18 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -24,7 +24,7 @@ pub use msg::sensor::SensorMessage; pub use msg::{DecodeMsgError, Msg}; pub use reading::Reading; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Unit { Pa, C, diff --git a/crates/sensor-tui/examples/chart_gaps.rs b/crates/sensor-tui/examples/chart_gaps.rs index 23312eb5..c2ff8215 100644 --- a/crates/sensor-tui/examples/chart_gaps.rs +++ b/crates/sensor-tui/examples/chart_gaps.rs @@ -29,7 +29,7 @@ fn data_with_gap(buffer: &mut Vec<(f64, f64)>) -> ChartParts<'_> { ChartParts { reading: info, - data: buffer.as_slice(), + data: buffer.as_mut_slice(), } } @@ -37,7 +37,7 @@ fn chart(frame: &mut Frame) { let layout = frame.area(); let mut tab = UiState::default(); let mut buffer = Vec::new(); - chart::render(frame, layout, &mut tab, data_with_gap(&mut buffer)); + chart::render(frame, layout, &mut tab, &mut [data_with_gap(&mut buffer)]); } fn main() { diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index dd7cfcc9..9d4659a9 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -1,6 +1,8 @@ +use std::collections::HashSet; use std::time::Instant; use crossterm::event::{KeyCode, KeyEvent}; +use log_store::api::Percentile; use ratatui::layout::Rect; use ratatui::widgets::TableState; use ratatui::Frame; @@ -12,7 +14,7 @@ pub mod sensor_info; use history_len::HistoryLen; use crate::{fetch::Fetch, Update}; -use sensor_info::Readings; +use sensor_info::{ChartParts, Readings}; use super::Theme; @@ -27,16 +29,19 @@ enum InputMode { pub struct UiState { show_histogram: bool, show_logs: bool, + show_complete_help: bool, history_length: HistoryLen, input_mode: InputMode, tree_state: TreeState, logs_table_state: TableState, + reading_selected: bool, + comparing: HashSet, } pub struct Tab { ui_state: UiState, readings: Readings, - plot_buf: Vec<(f64, f64)>, + plot_bufs: Vec>, } impl Default for Tab { @@ -44,46 +49,96 @@ impl Default for Tab { Self { ui_state: UiState::default(), readings: Readings::new(), - plot_buf: Vec::new(), + plot_bufs: Vec::new(), } } } +#[derive(Default)] +struct DataToDisplay<'a> { + chart_parts: Vec>, + precentiles: Vec, + details: Option, + logs: Option, +} + +fn fill_data<'a>( + to_display: Vec, + readings: &mut Readings, + plot_bufs: &'a mut Vec>, + history_len: std::time::Duration, +) -> DataToDisplay<'a> { + for buf in plot_bufs.iter_mut() { + buf.clear(); + } + plot_bufs.resize_with(to_display.len().max(plot_bufs.len()), Vec::new); + let mut res = DataToDisplay::default(); + for (i, (ui_id, buf)) in to_display.into_iter().zip(plot_bufs).enumerate() { + let Some(info) = readings.get_by_ui_id(ui_id) else { + continue; + }; + + if i == 0 { + // TODO merge? if possible; + res.precentiles = info.percentiles(); + // TODO merge to show details from all plots + res.details = Some(info.details()); + // TODO merge to show logs interleaved + res.logs = Some(info.logs()); + } + + res.chart_parts.push(info.chart(buf, history_len)); + } + res +} + impl Tab { pub fn render(&mut self, frame: &mut Frame, layout: Rect, theme: &Theme) { let Self { ui_state, readings, - plot_buf, + plot_bufs, } = self; - let (chart, percentiles, details, logs) = { - let data = ui_state - .tree_state - .selected() - .last() // Unique leaf id - .and_then(|key| readings.get_by_ui_id(*key)); - - if let Some(data) = data { - ( - data.chart(plot_buf, ui_state.history_length.dur), - data.percentiles(), - Some(data.details()), - Some(data.logs()), - ) - } else { - plot_buf.clear(); - (None, Vec::new(), None, None) - } + let DataToDisplay { + chart_parts, + precentiles, + details, + logs, + } = { + let selected = ui_state.tree_state.selected().last(); + ui_state.reading_selected = selected.is_some(); + + let mut to_display: Vec<_> = selected + .into_iter() + .chain(ui_state.comparing.iter()) + .copied() + .collect(); + to_display.dedup(); + fill_data(to_display, readings, plot_bufs, ui_state.history_length.dur) }; - let [top, bottom, footer] = - render::layout(frame, layout, readings, chart.is_some(), logs.is_some()); + let [top, bottom, footer] = render::layout( + frame, + layout, + readings, + !chart_parts.is_empty(), + logs.is_some(), + ui_state, + ); let have_details = details.is_some(); render::readings_and_details(frame, top, ui_state, readings, details); if have_details { - render::graph_hist_logs(frame, bottom, ui_state, &percentiles, logs, chart, theme); + render::graph_hist_logs( + frame, + bottom, + ui_state, + &precentiles, + logs, + chart_parts, + theme, + ); } render::footer(frame, footer, ui_state, theme); } @@ -165,16 +220,29 @@ impl Tab { impl UiState { fn handle_key_normal_mode(&mut self, key: KeyEvent) -> Option { match key.code { - KeyCode::Char('b') => { + KeyCode::Char('b') if self.reading_selected => { self.history_length.start_editing(); self.input_mode = InputMode::EditingBounds; } - KeyCode::Char('h') => { + KeyCode::Char('h') if self.reading_selected => { self.show_histogram = !self.show_histogram; } - KeyCode::Char('l') => { + KeyCode::Char('l') if self.reading_selected => { self.show_logs = !self.show_logs; } + KeyCode::Char('c') if self.reading_selected => { + let id = *self + .tree_state + .selected() + .last() + .expect("reading_selected is true"); + if !self.comparing.remove(&id) { + self.comparing.insert(id); + } + } + KeyCode::Char('?') => { + self.show_complete_help = !self.show_complete_help; + } _ => return Some(key), } diff --git a/crates/sensor-tui/src/tui/readings/render.rs b/crates/sensor-tui/src/tui/readings/render.rs index 3ba0d556..e7e3e135 100644 --- a/crates/sensor-tui/src/tui/readings/render.rs +++ b/crates/sensor-tui/src/tui/readings/render.rs @@ -27,6 +27,7 @@ pub(crate) fn layout( readings: &Readings, chart: bool, logs: bool, + ui_state: &UiState, ) -> [Rect; 3] { let [list_constraint, graph_constraint] = if chart { let tree_height = 2 + readings @@ -49,9 +50,14 @@ pub(crate) fn layout( [Constraint::Percentage(100), Constraint::Percentage(0)] }; - Layout::vertical([list_constraint, graph_constraint, Constraint::Min(1)]) - .flex(Flex::Legacy) - .areas(layout) + let help_size = 1 + ui_state.show_complete_help as u16; + Layout::vertical([ + list_constraint, + graph_constraint, + Constraint::Min(help_size), + ]) + .flex(Flex::Legacy) + .areas(layout) } pub(crate) fn footer(frame: &mut Frame, layout: Rect, app: &mut UiState, theme: &Theme) { @@ -61,20 +67,45 @@ pub(crate) fn footer(frame: &mut Frame, layout: Rect, app: &mut UiState, theme: footer.push("ESC or q: stop bound editing"); } else { footer.push("ESC or q: quit"); - footer.push("b: edit graph start"); } - if app.show_histogram { - footer.push("h: hide histogram"); - } else { - footer.push("h: show histogram"); + if app.reading_selected { + if !app.history_length.editing { + footer.push("b: edit graph start"); + } + + if app.show_histogram { + footer.push("h: hide histogram"); + } else { + footer.push("h: show histogram"); + } + + if app.show_logs { + footer.push("l: hide logs"); + } else { + footer.push("l: show logs"); + } + + if app.show_complete_help { + footer.push("?: show more help"); + } else { + footer.push("?: hide more help"); + } } - if app.show_logs { - footer.push("l: hide logs"); + let layout = if app.show_complete_help { + let [top, bottom] = Layout::vertical([Constraint::Min(1), Constraint::Min(1)]) + .flex(Flex::Legacy) + .areas(layout); + + let footer = Text::raw("c: toggle compare") + .alignment(Alignment::Center) + .style(theme.bars); + frame.render_widget(footer, bottom); + top } else { - footer.push("l: show logs"); - } + layout + }; let footer = footer.join(" "); let footer = Text::raw(footer) @@ -89,13 +120,13 @@ pub(crate) fn graph_hist_logs( app: &mut UiState, percentiles: &[Percentile], logs: Option, - chart: Option, + mut chart: Vec, theme: &Theme, ) { let num_elems = 1usize + app.show_histogram as usize + app.show_logs as usize; let mut constraints = [Constraint::Max(2); 3]; - if chart.is_some() { + if !chart.is_empty() { constraints[0] = Constraint::Fill(10); } if logs @@ -118,15 +149,15 @@ pub(crate) fn graph_hist_logs( let mut layout = layout.iter().cloned(); - if let Some(chart) = chart { - chart::render(frame, layout.next().unwrap(), app, chart); - } else { + if chart.is_empty() { centered_text( "No chart as there is no data", frame, layout.next().unwrap(), theme, ) + } else { + chart::render(frame, layout.next().unwrap(), app, &mut chart); } if app.show_logs { @@ -192,7 +223,7 @@ pub(crate) fn readings_and_details( .flex(Flex::Legacy) .areas(layout); - let tree = tree::build_ui(readings); + let tree = tree::build_ui(readings, &app.comparing); frame.render_stateful_widget( Tree::new(&tree) .expect("all item identifiers should be unique") diff --git a/crates/sensor-tui/src/tui/readings/render/chart.rs b/crates/sensor-tui/src/tui/readings/render/chart.rs index 1dd5e316..df287759 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart.rs @@ -1,3 +1,4 @@ +use protocol::reading; use ratatui::{ layout::{Alignment, Rect}, style::Style, @@ -10,38 +11,99 @@ use crate::tui::readings::{sensor_info::ChartParts, UiState}; mod labels; mod split; -use labels::labels; +use labels::{x_labels, y_labels}; -pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, chart: ChartParts) { - let (x_bounds, y_bounds) = bounds(&chart, layout); +/// mul then add to get original from points between 0 and 1 +#[derive(Debug)] +struct Scaling { + mul: f64, + add: f64, +} + +impl Scaling { + fn to_normalize([min, max]: Bounds) -> Self { + Self { + mul: max - min, + add: -min, + } + } + fn normalized(&self, y: f64) -> f64 { + (y + self.add) / self.mul + } +} + +pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, charts: &mut [ChartParts]) { + let mut merged_y_bounds: Vec<(reading::Info, [f64; 2])> = Vec::new(); + for chart in charts.iter() { + let y_bounds = ybounds(chart, layout); + for (info, existing) in merged_y_bounds.iter_mut() { + if info.unit == chart.reading.unit { + existing[0] = existing[0].min(y_bounds[0]); + existing[1] = existing[1].min(y_bounds[1]); + continue; + } + } + merged_y_bounds.push((chart.reading.clone(), y_bounds)); + } + + let mut labels_y = Vec::new(); + for new in merged_y_bounds + .iter() + .map(|(info, y_bounds)| y_labels(info, layout, *y_bounds)) + { + if labels_y.is_empty() { + labels_y = new; + } else { + for (existing, new) in labels_y.iter_mut().zip(new) { + existing.push(' '); + existing.push_str(new.as_str()); + } + } + } + + let datasets = charts + .iter_mut() + .flat_map(|chart| { + let (_info, y_bounds) = merged_y_bounds + .iter() + .find(|(info, _)| info.unit == chart.reading.unit) + .expect("made bound for every chart"); + let scaling = Scaling::to_normalize(*y_bounds); + + for (_, y) in chart.data.iter_mut() { + *y = scaling.normalized(*y) + } + + split::split(chart, layout.width).map(|line| { + Dataset::default() + .marker(symbols::Marker::Braille) + .graph_type(GraphType::Line) + .style(Style::default()) + .data(line) + }) + }) + .collect(); + + let x_bounds = [0f64, tab.history_length.dur.as_secs_f64()]; let scale = labels::scale(x_bounds[1]); - let (mut x_labels, y_labels) = labels(&chart, layout, x_bounds, y_bounds, &scale); - let borrowed = x_labels.first_mut().expect("min labels is 2"); + let mut labels_x = x_labels(layout, x_bounds, &scale); + let borrowed = labels_x.first_mut().expect("min labels is 2"); let owned = std::mem::take(borrowed); - x_labels[0] = tab.history_length.style_left_x_label(owned); + labels_x[0] = tab.history_length.style_left_x_label(owned); let x_axis = Axis::default() .title(format!("Time ({scale})",)) .style(Style::default()) .bounds(x_bounds) - .labels(x_labels) + .labels(labels_x) .labels_alignment(Alignment::Center); + let y_axis = Axis::default() - .title(chart.reading.unit.to_string()) + .title("selected readings") .style(Style::default()) - .bounds(y_bounds) - .labels(y_labels); - - let datasets = split::split(&chart, layout.width) - .map(|line| { - Dataset::default() - .marker(symbols::Marker::Braille) - .graph_type(GraphType::Line) - .style(Style::default()) - .data(line) - }) - .collect(); + .bounds([0.0, 1.0]) + .labels(labels_y); let linechart = Chart::new(datasets) .block(Block::bordered().title("History")) @@ -51,29 +113,23 @@ pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, chart: ChartPa } type Bounds = [f64; 2]; -fn bounds(chart: &ChartParts, layout: Rect) -> (Bounds, Bounds) { - let x_bounds = [ - 0f64, - chart.data.last().map(|(x, _)| x).copied().unwrap_or(0f64), - ]; - - let y_bounds = chart +fn ybounds(chart: &ChartParts, layout: Rect) -> Bounds { + let bounds = chart .data .iter() .map(|(_, y)| y) .fold([f64::MAX, f64::MIN], |[start, end], y| { [start.min(*y), end.max(*y)] }); - let y_range = y_bounds[1] - y_bounds[0]; + let y_range = bounds[1] - bounds[0]; let margin = 5.0 / layout.height as f64; let range = &chart.reading.range; let resolution = chart.reading.resolution as f64; let y_margin = f64::max(y_range * margin, resolution / 2.0); - let y_bounds = [y_bounds[0] - y_margin, y_bounds[1] + y_margin]; - let y_bounds = [ - y_bounds[0].max(range.start as f64), - y_bounds[1].min(range.end as f64), - ]; - (x_bounds, y_bounds) + let bounds = [bounds[0] - y_margin, bounds[1] + y_margin]; + [ + bounds[0].max(range.start as f64), + bounds[1].min(range.end as f64), + ] } diff --git a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs index 521265ec..82a72d69 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs @@ -5,33 +5,39 @@ use ratatui::layout::Rect; use ratatui::text::Span; use crate::time::format::progressively_more_specified; -use crate::tui::readings::sensor_info::ChartParts; use super::Bounds; -type Labels = Vec>; +const Y_LABEL_SPACING: u16 = 10; + +pub fn y_labels(info: &reading::Info, layout: Rect, y_bounds: Bounds) -> Vec { + // Characters are about twice as high as wide + evenly_spaced_ylabels( + layout.height / Y_LABEL_SPACING, + info.resolution as f64, + y_bounds, + ) + .map(|y| format!("{0:.1$}", y, info.precision())) + .collect() +} -pub fn labels( - chart: &ChartParts, +type Labels = Vec>; +pub fn x_labels( layout: Rect, x_bounds: Bounds, - y_bounds: Bounds, scale: &progressively_more_specified::FmtScale, -) -> (Labels, Labels) { - let y_label_spacing = 10; - let info = &chart.reading; - +) -> Labels { // Characters are about twice as high as wide - let x = evenly_spaced_labels(layout.width / y_label_spacing / 2, info, x_bounds) + let max_labels = layout.width / Y_LABEL_SPACING / 2; + let n_labels = max_labels.max(2); + let x_spacing = (x_bounds[1] - x_bounds[0]) / n_labels as f64; + + (0..=n_labels) + .map(move |i| x_bounds[0] + x_spacing * i as f64) .rev() .map(|x| fmt(x, scale)) .map(Into::into) - .collect(); - let y = evenly_spaced_labels(layout.height / y_label_spacing, info, y_bounds) - .map(|y| format!("{0:.1$}", y, info.precision()).into()) - .collect(); - - (x, y) + .collect() } fn fmt(x: f64, scale: &progressively_more_specified::FmtScale) -> String { @@ -50,12 +56,11 @@ pub fn scale(secs: f64) -> progressively_more_specified::FmtScale { progressively_more_specified::FmtScale::optimal_for(time, elapsed) } -fn evenly_spaced_labels( +fn evenly_spaced_ylabels( max_labels: u16, - reading: &reading::Info, + resolution: f64, bounds: Bounds, ) -> impl DoubleEndedIterator { - let resolution = reading.resolution as f64; let steps_in_data = (bounds[1] - bounds[0]) / resolution; let n_labels = max_labels.min(steps_in_data as u16).max(2); diff --git a/crates/sensor-tui/src/tui/readings/render/chart/split.rs b/crates/sensor-tui/src/tui/readings/render/chart/split.rs index 4ef5e77d..c848537a 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/split.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/split.rs @@ -49,7 +49,7 @@ pub(crate) fn split<'a>( .filter(move |((_, b), (_, a))| **b - **a > min_dist) .map(|((ib, _), _)| ib); - let mut data = chart.data; + let mut data = &*chart.data; splits.chain(iter::once(0)).map(move |mid| { let (left, line) = data.split_at(mid); data = left; @@ -74,7 +74,7 @@ mod test { #[test] fn test_split() { - let test_data = test_data(); + let mut test_data = test_data(); let test_chart = ChartParts { reading: protocol::reading::Info { val: 0.0, @@ -87,7 +87,7 @@ mod test { description: "test", branch_id: 1, }, - data: &test_data, + data: &mut test_data, }; assert_eq!(split(&test_chart, 500).count(), 5); assert_eq!( diff --git a/crates/sensor-tui/src/tui/readings/render/tree.rs b/crates/sensor-tui/src/tui/readings/render/tree.rs index 592c176f..6275259d 100644 --- a/crates/sensor-tui/src/tui/readings/render/tree.rs +++ b/crates/sensor-tui/src/tui/readings/render/tree.rs @@ -1,4 +1,8 @@ +use std::collections::HashSet; + use indextree::Arena; +use ratatui::style::{Style, Stylize}; +use ratatui::text::Text; use tui_tree_widget::TreeItem; use crate::tui::readings::sensor_info::{Node, Readings, SensorInfo}; @@ -14,7 +18,10 @@ impl IdGen { } } -pub(crate) fn build_ui(readings: &Readings) -> Vec> { +pub(crate) fn build_ui<'a>( + readings: &'a Readings, + comparing: &HashSet, +) -> Vec> { let mut id_gen = IdGen::default(); readings @@ -22,11 +29,11 @@ pub(crate) fn build_ui(readings: &Readings) -> Vec> { .children(&readings.arena) .map( |subroot| match readings.arena.get(subroot).expect("child exists").get() { - Node::Sensor(info) => new_leaf(info), + Node::Sensor(info) => new_leaf(info, comparing), Node::Branch(name) => TreeItem::new( id_gen.next(), name.as_str(), - recusive_call(subroot, &readings.arena, &mut id_gen), + recusive_call(subroot, &readings.arena, &mut id_gen, comparing), ) .expect("no duplicate ids"), Node::Root => unreachable!("Root is not a descendant"), @@ -39,16 +46,17 @@ fn recusive_call<'a>( root: indextree::NodeId, arena: &'a Arena, id_gen: &mut IdGen, + comparing: &HashSet, ) -> Vec> { root.children(arena) .map(|child_id| { let child_node = arena.get(child_id).expect("child exists").get(); match child_node { - Node::Sensor(info) => new_leaf(info), + Node::Sensor(info) => new_leaf(info, comparing), Node::Branch(name) => TreeItem::new( id_gen.next(), name.as_str(), - recusive_call(child_id, arena, id_gen), + recusive_call(child_id, arena, id_gen, comparing), ) .expect("no duplicate ids"), Node::Root => unreachable!("Root is not a descendant"), @@ -57,7 +65,7 @@ fn recusive_call<'a>( .collect() } -fn new_leaf(info: &SensorInfo) -> TreeItem { +fn new_leaf<'a>(info: &'a SensorInfo, comparing: &HashSet) -> TreeItem<'a, u16> { use protocol::reading::tree::{Item, Tree}; let mut node = &info.reading as &dyn Tree; @@ -65,16 +73,23 @@ fn new_leaf(info: &SensorInfo) -> TreeItem { node = inner; } - if info.is_placeholder { - TreeItem::new_leaf(info.ui_id, node.name()) + let style = if comparing.contains(&info.ui_id) { + Style::new().italic().blue() + } else { + Style::new() + }; + + let text = if info.is_placeholder { + node.name() } else { - let text = format!( + format!( "{0}: {1:.2$} {3}", node.name(), info.info.val, info.info.precision(), info.info.unit - ); - TreeItem::new_leaf(info.ui_id, text) - } + ) + }; + + TreeItem::new_leaf(info.ui_id, Text::styled(text, style)) } diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index c977ff0c..73c486ed 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -201,7 +201,7 @@ impl SensorInfo { &mut self, plot_buf: &'a mut Vec<(f64, f64)>, history_len: Duration, - ) -> Option> { + ) -> ChartParts<'a> { let reference = jiff::Timestamp::now() - history_len; let first_recent = self @@ -239,10 +239,10 @@ impl SensorInfo { \reference: {reference}" ); - Some(ChartParts { + ChartParts { reading: self.info.clone(), data: plot_buf, - }) + } } pub(crate) fn logs(&self) -> logs::List { @@ -461,5 +461,5 @@ fn get_child_by_name( pub struct ChartParts<'a> { pub reading: reading::Info, /// array of time, y - pub data: &'a [(f64, f64)], + pub data: &'a mut [(f64, f64)], } From 9032150b079bac0b43398a8349e090c9114ee960 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 12 Oct 2024 15:34:53 +0200 Subject: [PATCH 309/687] give the lines different colors --- crates/sensor-tui/src/tui/readings.rs | 1 + .../src/tui/readings/render/chart.rs | 59 ++++++++++++++++--- 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index 9d4659a9..81af67fd 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -114,6 +114,7 @@ impl Tab { .chain(ui_state.comparing.iter()) .copied() .collect(); + to_display.sort(); to_display.dedup(); fill_data(to_display, readings, plot_bufs, ui_state.history_length.dur) }; diff --git a/crates/sensor-tui/src/tui/readings/render/chart.rs b/crates/sensor-tui/src/tui/readings/render/chart.rs index df287759..2c10dbbb 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart.rs @@ -1,7 +1,7 @@ use protocol::reading; use ratatui::{ layout::{Alignment, Rect}, - style::Style, + style::{Color, Style}, symbols, widgets::{Axis, Block, Chart, Dataset, GraphType}, Frame, @@ -32,15 +32,54 @@ impl Scaling { } } +// excludes: +// - light colors: same as the normal colors on some terminals +// - gray: to light to see +// - magenta: looks the same as red +const ALL_COLORS: &[Color] = &[ + Color::Black, + Color::Red, + Color::Green, + Color::Yellow, + Color::Blue, + Color::Cyan, + Color::DarkGray, +]; + +fn plot_colors(unit: protocol::Unit) -> impl Iterator { + use protocol::Unit as U; + use Color::*; + + let preferred = match unit { + U::Pa => &[Black, Cyan, Blue] as &'static [Color], + U::C => &[Red] as &'static [Color], + U::RH => &[Blue, Cyan] as &'static [Color], + U::Lux => &[Yellow] as &'static [Color], + U::Ohm => &[DarkGray] as &'static [Color], + U::Ppm | U::MicrogramPerM3 | U::NumberPerCm3 | U::NanoMeter => { + &[Green, Cyan] as &'static [Color] + } + U::None => &[] as &'static [Color], + }; + preferred.iter().chain(ALL_COLORS.iter()).copied() +} + pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, charts: &mut [ChartParts]) { + let mut colors: Vec = Vec::new(); // same order as charts let mut merged_y_bounds: Vec<(reading::Info, [f64; 2])> = Vec::new(); - for chart in charts.iter() { + 'outer: for chart in charts.iter() { + let color = plot_colors(chart.reading.unit) + .find(|color| !colors.contains(&color)) + .clone() + .unwrap_or(Color::Black); + colors.push(color); let y_bounds = ybounds(chart, layout); + for (info, existing) in merged_y_bounds.iter_mut() { if info.unit == chart.reading.unit { existing[0] = existing[0].min(y_bounds[0]); - existing[1] = existing[1].min(y_bounds[1]); - continue; + existing[1] = existing[1].max(y_bounds[1]); + continue 'outer; } } merged_y_bounds.push((chart.reading.clone(), y_bounds)); @@ -63,9 +102,10 @@ pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, charts: &mut [ let datasets = charts .iter_mut() - .flat_map(|chart| { - let (_info, y_bounds) = merged_y_bounds - .iter() + .zip(colors.into_iter()) + .flat_map(|(chart, color)| { + let (_, y_bounds) = merged_y_bounds + .iter_mut() .find(|(info, _)| info.unit == chart.reading.unit) .expect("made bound for every chart"); let scaling = Scaling::to_normalize(*y_bounds); @@ -74,11 +114,12 @@ pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, charts: &mut [ *y = scaling.normalized(*y) } - split::split(chart, layout.width).map(|line| { + let color = color.clone(); + split::split(chart, layout.width).map(move |line| { Dataset::default() .marker(symbols::Marker::Braille) .graph_type(GraphType::Line) - .style(Style::default()) + .style(Style::default().fg(color)) .data(line) }) }) From 34093dec12d0291cd156ee884dd9a07c8a9381c9 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 12 Oct 2024 18:23:29 +0200 Subject: [PATCH 310/687] tui: adds legend in top right corner --- crates/sensor-tui/examples/chart_gaps.rs | 2 +- .../src/tui/readings/render/chart.rs | 118 +++++++++++++----- .../src/tui/readings/render/chart/split.rs | 4 +- .../src/tui/readings/sensor_info.rs | 6 +- 4 files changed, 92 insertions(+), 38 deletions(-) diff --git a/crates/sensor-tui/examples/chart_gaps.rs b/crates/sensor-tui/examples/chart_gaps.rs index c2ff8215..2f9ffa30 100644 --- a/crates/sensor-tui/examples/chart_gaps.rs +++ b/crates/sensor-tui/examples/chart_gaps.rs @@ -28,7 +28,7 @@ fn data_with_gap(buffer: &mut Vec<(f64, f64)>) -> ChartParts<'_> { }; ChartParts { - reading: info, + info, data: buffer.as_mut_slice(), } } diff --git a/crates/sensor-tui/src/tui/readings/render/chart.rs b/crates/sensor-tui/src/tui/readings/render/chart.rs index 2c10dbbb..f2ad5ffb 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart.rs @@ -3,7 +3,8 @@ use ratatui::{ layout::{Alignment, Rect}, style::{Color, Style}, symbols, - widgets::{Axis, Block, Chart, Dataset, GraphType}, + text::{Line, Text}, + widgets::{Axis, Block, Chart, Clear, Dataset, GraphType}, Frame, }; @@ -68,7 +69,7 @@ pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, charts: &mut [ let mut colors: Vec = Vec::new(); // same order as charts let mut merged_y_bounds: Vec<(reading::Info, [f64; 2])> = Vec::new(); 'outer: for chart in charts.iter() { - let color = plot_colors(chart.reading.unit) + let color = plot_colors(chart.info.unit) .find(|color| !colors.contains(&color)) .clone() .unwrap_or(Color::Black); @@ -76,20 +77,22 @@ pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, charts: &mut [ let y_bounds = ybounds(chart, layout); for (info, existing) in merged_y_bounds.iter_mut() { - if info.unit == chart.reading.unit { + if info.unit == chart.info.unit { existing[0] = existing[0].min(y_bounds[0]); existing[1] = existing[1].max(y_bounds[1]); continue 'outer; } } - merged_y_bounds.push((chart.reading.clone(), y_bounds)); + merged_y_bounds.push((chart.info.clone(), y_bounds)); } + let mut y_axis_title = String::new(); let mut labels_y = Vec::new(); - for new in merged_y_bounds - .iter() - .map(|(info, y_bounds)| y_labels(info, layout, *y_bounds)) - { + for (info, y_bounds) in merged_y_bounds.iter() { + y_axis_title.push_str(&info.unit.to_string()); + y_axis_title.push(' '); + + let new = y_labels(info, layout, *y_bounds); if labels_y.is_empty() { labels_y = new; } else { @@ -100,13 +103,34 @@ pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, charts: &mut [ } } + let x_bounds = [0f64, tab.history_length.dur.as_secs_f64()]; + let scale = labels::scale(x_bounds[1]); + + let mut labels_x = x_labels(layout, x_bounds, &scale); + let borrowed = labels_x.first_mut().expect("min labels is 2"); + let owned = std::mem::take(borrowed); + labels_x[0] = tab.history_length.style_left_x_label(owned); + + let x_axis = Axis::default() + .title(format!("Time ({scale})",)) + .style(Style::default()) + .bounds(x_bounds) + .labels(labels_x) + .labels_alignment(Alignment::Center); + + let y_axis = Axis::default() + .title(y_axis_title) + .style(Style::default()) + .bounds([0.0, 1.0]) + .labels(labels_y); + let datasets = charts .iter_mut() - .zip(colors.into_iter()) + .zip(colors.iter()) .flat_map(|(chart, color)| { let (_, y_bounds) = merged_y_bounds .iter_mut() - .find(|(info, _)| info.unit == chart.reading.unit) + .find(|(info, _)| info.unit == chart.info.unit) .expect("made bound for every chart"); let scaling = Scaling::to_normalize(*y_bounds); @@ -125,32 +149,60 @@ pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, charts: &mut [ }) .collect(); - let x_bounds = [0f64, tab.history_length.dur.as_secs_f64()]; - let scale = labels::scale(x_bounds[1]); - - let mut labels_x = x_labels(layout, x_bounds, &scale); - let borrowed = labels_x.first_mut().expect("min labels is 2"); - let owned = std::mem::take(borrowed); - labels_x[0] = tab.history_length.style_left_x_label(owned); - - let x_axis = Axis::default() - .title(format!("Time ({scale})",)) - .style(Style::default()) - .bounds(x_bounds) - .labels(labels_x) - .labels_alignment(Alignment::Center); - - let y_axis = Axis::default() - .title("selected readings") - .style(Style::default()) - .bounds([0.0, 1.0]) - .labels(labels_y); - let linechart = Chart::new(datasets) .block(Block::bordered().title("History")) .x_axis(x_axis) .y_axis(y_axis); frame.render_widget(linechart, layout); + + if charts.len() > 1 { + render_legend(layout, frame, charts, colors); + } +} + +fn render_legend(layout: Rect, frame: &mut Frame, charts: &mut [ChartParts], colors: Vec) { + let text: Text = charts + .iter() + .zip(colors) + .map(|(ChartParts { reading, .. }, color)| (reading, color)) + .map(fmt_reading) + .collect(); + + let area = legend_area(&text, layout); + frame.render_widget(Clear, area); + frame.render_widget(text, area); +} + +fn legend_area(text: &Text, chart: Rect) -> Rect { + let lines = text.iter().count() as u16; + let columns = text + .iter() + .map(|l| l.iter().map(|s| s.content.len() as u16).sum::()) + .max() + .expect("legend is never empty"); + + Rect { + x: chart.right() - columns - 2, + y: chart.top() + 1, + width: columns, + height: lines, + } +} + +fn fmt_reading((reading, color): (&protocol::Reading, Color)) -> Line { + use protocol::reading::tree::{Item, Tree}; + let mut node = reading as &dyn Tree; + let mut text = node.name(); + + loop { + match node.inner() { + Item::Node(inner) => node = inner, + Item::Leaf(_) => break, + } + text.push('/'); + text.push_str(&node.name()); + } + Line::styled(text, Style::default().fg(color).bg(Color::Gray)) } type Bounds = [f64; 2]; @@ -165,8 +217,8 @@ fn ybounds(chart: &ChartParts, layout: Rect) -> Bounds { let y_range = bounds[1] - bounds[0]; let margin = 5.0 / layout.height as f64; - let range = &chart.reading.range; - let resolution = chart.reading.resolution as f64; + let range = &chart.info.range; + let resolution = chart.info.resolution as f64; let y_margin = f64::max(y_range * margin, resolution / 2.0); let bounds = [bounds[0] - y_margin, bounds[1] + y_margin]; [ diff --git a/crates/sensor-tui/src/tui/readings/render/chart/split.rs b/crates/sensor-tui/src/tui/readings/render/chart/split.rs index c848537a..bb3c747d 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/split.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/split.rs @@ -21,7 +21,7 @@ pub(crate) fn split<'a>( chart_width: u16, ) -> impl Iterator { let min_dist = chart - .reading + .info .device .info() .max_sample_interval @@ -76,7 +76,7 @@ mod test { fn test_split() { let mut test_data = test_data(); let test_chart = ChartParts { - reading: protocol::reading::Info { + info: protocol::reading::Info { val: 0.0, device: Device::LargeBedroom(large_bedroom::Device::Bed( large_bedroom::bed::Device::Bme680, diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index 73c486ed..4384a896 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -240,7 +240,8 @@ impl SensorInfo { ); ChartParts { - reading: self.info.clone(), + info: self.info.clone(), + reading: self.reading.clone(), data: plot_buf, } } @@ -459,7 +460,8 @@ fn get_child_by_name( } pub struct ChartParts<'a> { - pub reading: reading::Info, + pub info: reading::Info, + pub reading: Reading, /// array of time, y pub data: &'a mut [(f64, f64)], } From 14b29a1bb4e3a94f46269b6d5652469cecac4c1c Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 15 Oct 2024 15:06:19 +0200 Subject: [PATCH 311/687] refactors chart render --- .../src/tui/readings/render/chart.rs | 104 +++++++++--------- .../src/tui/readings/render/chart/labels.rs | 46 ++++++-- 2 files changed, 89 insertions(+), 61 deletions(-) diff --git a/crates/sensor-tui/src/tui/readings/render/chart.rs b/crates/sensor-tui/src/tui/readings/render/chart.rs index f2ad5ffb..7afb0f59 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart.rs @@ -12,7 +12,6 @@ use crate::tui::readings::{sensor_info::ChartParts, UiState}; mod labels; mod split; -use labels::{x_labels, y_labels}; /// mul then add to get original from points between 0 and 1 #[derive(Debug)] @@ -66,64 +65,43 @@ fn plot_colors(unit: protocol::Unit) -> impl Iterator { } pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, charts: &mut [ChartParts]) { - let mut colors: Vec = Vec::new(); // same order as charts - let mut merged_y_bounds: Vec<(reading::Info, [f64; 2])> = Vec::new(); - 'outer: for chart in charts.iter() { - let color = plot_colors(chart.info.unit) - .find(|color| !colors.contains(&color)) - .clone() - .unwrap_or(Color::Black); - colors.push(color); - let y_bounds = ybounds(chart, layout); - - for (info, existing) in merged_y_bounds.iter_mut() { - if info.unit == chart.info.unit { - existing[0] = existing[0].min(y_bounds[0]); - existing[1] = existing[1].max(y_bounds[1]); - continue 'outer; - } - } - merged_y_bounds.push((chart.info.clone(), y_bounds)); - } - - let mut y_axis_title = String::new(); - let mut labels_y = Vec::new(); - for (info, y_bounds) in merged_y_bounds.iter() { - y_axis_title.push_str(&info.unit.to_string()); - y_axis_title.push(' '); - - let new = y_labels(info, layout, *y_bounds); - if labels_y.is_empty() { - labels_y = new; - } else { - for (existing, new) in labels_y.iter_mut().zip(new) { - existing.push(' '); - existing.push_str(new.as_str()); - } - } - } + let (colors, merged_y_bounds) = bounds_and_colors(charts, layout); + let (y_labels, y_title) = labels::y_and_title(&merged_y_bounds, layout); let x_bounds = [0f64, tab.history_length.dur.as_secs_f64()]; - let scale = labels::scale(x_bounds[1]); - - let mut labels_x = x_labels(layout, x_bounds, &scale); - let borrowed = labels_x.first_mut().expect("min labels is 2"); - let owned = std::mem::take(borrowed); - labels_x[0] = tab.history_length.style_left_x_label(owned); + let (x_labels, x_title) = labels::x_and_title(layout, x_bounds, &tab.history_length); let x_axis = Axis::default() - .title(format!("Time ({scale})",)) + .title(x_title) .style(Style::default()) .bounds(x_bounds) - .labels(labels_x) + .labels(x_labels) .labels_alignment(Alignment::Center); let y_axis = Axis::default() - .title(y_axis_title) + .title(y_title) .style(Style::default()) .bounds([0.0, 1.0]) - .labels(labels_y); + .labels(y_labels); + + let datasets = datasets(charts, &colors, merged_y_bounds, layout); + let linechart = Chart::new(datasets) + .block(Block::bordered().title("History")) + .x_axis(x_axis) + .y_axis(y_axis); + frame.render_widget(linechart, layout); + if charts.len() > 1 { + render_legend(layout, frame, charts, colors); + } +} + +fn datasets<'a>( + charts: &'a mut [ChartParts], + colors: &Vec, + mut merged_y_bounds: Vec<(reading::Info, [f64; 2])>, + layout: Rect, +) -> Vec> { let datasets = charts .iter_mut() .zip(colors.iter()) @@ -148,16 +126,34 @@ pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, charts: &mut [ }) }) .collect(); + datasets +} - let linechart = Chart::new(datasets) - .block(Block::bordered().title("History")) - .x_axis(x_axis) - .y_axis(y_axis); - frame.render_widget(linechart, layout); +fn bounds_and_colors( + charts: &mut [ChartParts], + layout: Rect, +) -> (Vec, Vec<(reading::Info, [f64; 2])>) { + let mut colors: Vec = Vec::new(); + // same order as charts + let mut merged_y_bounds: Vec<(reading::Info, [f64; 2])> = Vec::new(); + 'outer: for chart in charts.iter() { + let color = plot_colors(chart.info.unit) + .find(|color| !colors.contains(&color)) + .clone() + .unwrap_or(Color::Black); + colors.push(color); + let y_bounds = ybounds(chart, layout); - if charts.len() > 1 { - render_legend(layout, frame, charts, colors); + for (info, existing) in merged_y_bounds.iter_mut() { + if info.unit == chart.info.unit { + existing[0] = existing[0].min(y_bounds[0]); + existing[1] = existing[1].max(y_bounds[1]); + continue 'outer; + } + } + merged_y_bounds.push((chart.info.clone(), y_bounds)); } + (colors, merged_y_bounds) } fn render_legend(layout: Rect, frame: &mut Frame, charts: &mut [ChartParts], colors: Vec) { diff --git a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs index 82a72d69..925c2379 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs @@ -5,12 +5,36 @@ use ratatui::layout::Rect; use ratatui::text::Span; use crate::time::format::progressively_more_specified; +use crate::tui::readings::history_len::HistoryLen; use super::Bounds; const Y_LABEL_SPACING: u16 = 10; -pub fn y_labels(info: &reading::Info, layout: Rect, y_bounds: Bounds) -> Vec { +pub fn y_and_title( + merged_y_bounds: &Vec<(reading::Info, [f64; 2])>, + layout: Rect, +) -> (Vec, String) { + let mut title = String::new(); + let mut labels = Vec::new(); + for (info, y_bounds) in merged_y_bounds.iter() { + title.push_str(&info.unit.to_string()); + title.push(' '); + + let new = y_labels(info, layout, *y_bounds); + if labels.is_empty() { + labels = new; + } else { + for (existing, new) in labels.iter_mut().zip(new) { + existing.push(' '); + existing.push_str(new.as_str()); + } + } + } + (labels, title) +} + +fn y_labels(info: &reading::Info, layout: Rect, y_bounds: Bounds) -> Vec { // Characters are about twice as high as wide evenly_spaced_ylabels( layout.height / Y_LABEL_SPACING, @@ -22,22 +46,30 @@ pub fn y_labels(info: &reading::Info, layout: Rect, y_bounds: Bounds) -> Vec>; -pub fn x_labels( +pub fn x_and_title( layout: Rect, x_bounds: Bounds, - scale: &progressively_more_specified::FmtScale, -) -> Labels { + history_len: &HistoryLen, +) -> (Labels, String) { // Characters are about twice as high as wide let max_labels = layout.width / Y_LABEL_SPACING / 2; let n_labels = max_labels.max(2); let x_spacing = (x_bounds[1] - x_bounds[0]) / n_labels as f64; - (0..=n_labels) + let scale = scale(x_bounds[1]); + let mut labels: Labels = (0..=n_labels) .map(move |i| x_bounds[0] + x_spacing * i as f64) .rev() - .map(|x| fmt(x, scale)) + .map(|x| fmt(x, &scale)) .map(Into::into) - .collect() + .collect(); + + let borrowed = labels.first_mut().expect("min labels is 2"); + let owned = std::mem::take(borrowed); + labels[0] = history_len.style_left_x_label(owned); + + let title = format!("Time ({scale})"); + (labels, title) } fn fmt(x: f64, scale: &progressively_more_specified::FmtScale) -> String { From bf863f71192e8ceb658f9b759809191544b4d30c Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 15 Oct 2024 15:18:10 +0200 Subject: [PATCH 312/687] tui: add x key for show cursor --- crates/sensor-tui/src/tui/readings.rs | 8 +++-- crates/sensor-tui/src/tui/readings/render.rs | 34 ++++++++++++------- .../src/tui/readings/sensor_info.rs | 4 +++ 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index 81af67fd..a5d06c01 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -14,7 +14,7 @@ pub mod sensor_info; use history_len::HistoryLen; use crate::{fetch::Fetch, Update}; -use sensor_info::{ChartParts, Readings}; +use sensor_info::{is_leaf_id, ChartParts, Readings}; use super::Theme; @@ -30,6 +30,7 @@ pub struct UiState { show_histogram: bool, show_logs: bool, show_complete_help: bool, + show_cursor: bool, history_length: HistoryLen, input_mode: InputMode, tree_state: TreeState, @@ -107,7 +108,7 @@ impl Tab { logs, } = { let selected = ui_state.tree_state.selected().last(); - ui_state.reading_selected = selected.is_some(); + ui_state.reading_selected = selected.copied().is_some_and(is_leaf_id); let mut to_display: Vec<_> = selected .into_iter() @@ -231,6 +232,9 @@ impl UiState { KeyCode::Char('l') if self.reading_selected => { self.show_logs = !self.show_logs; } + KeyCode::Char('x') if self.reading_selected => { + self.show_cursor = !self.show_cursor; + } KeyCode::Char('c') if self.reading_selected => { let id = *self .tree_state diff --git a/crates/sensor-tui/src/tui/readings/render.rs b/crates/sensor-tui/src/tui/readings/render.rs index e7e3e135..2590b696 100644 --- a/crates/sensor-tui/src/tui/readings/render.rs +++ b/crates/sensor-tui/src/tui/readings/render.rs @@ -61,35 +61,35 @@ pub(crate) fn layout( } pub(crate) fn footer(frame: &mut Frame, layout: Rect, app: &mut UiState, theme: &Theme) { - let mut footer = Vec::new(); + let mut main = Vec::new(); if app.history_length.editing { - footer.push("ESC or q: stop bound editing"); + main.push("ESC or q: stop bound editing"); } else { - footer.push("ESC or q: quit"); + main.push("ESC or q: quit"); } if app.reading_selected { if !app.history_length.editing { - footer.push("b: edit graph start"); + main.push("b: edit graph start"); } if app.show_histogram { - footer.push("h: hide histogram"); + main.push("h: hide histogram"); } else { - footer.push("h: show histogram"); + main.push("h: show histogram"); } if app.show_logs { - footer.push("l: hide logs"); + main.push("l: hide logs"); } else { - footer.push("l: show logs"); + main.push("l: show logs"); } if app.show_complete_help { - footer.push("?: show more help"); + main.push("?: hide more help"); } else { - footer.push("?: hide more help"); + main.push("?: show more help"); } } @@ -98,7 +98,17 @@ pub(crate) fn footer(frame: &mut Frame, layout: Rect, app: &mut UiState, theme: .flex(Flex::Legacy) .areas(layout); - let footer = Text::raw("c: toggle compare") + let mut extra = Vec::new(); + if app.reading_selected { + extra.push("c: toggle compare"); + if app.show_cursor { + extra.push("x: hide cursor"); + } else { + extra.push("x: show cursor"); + } + } + let footer = extra.join(" "); + let footer = Text::raw(footer) .alignment(Alignment::Center) .style(theme.bars); frame.render_widget(footer, bottom); @@ -107,7 +117,7 @@ pub(crate) fn footer(frame: &mut Frame, layout: Rect, app: &mut UiState, theme: layout }; - let footer = footer.join(" "); + let footer = main.join(" "); let footer = Text::raw(footer) .alignment(Alignment::Center) .style(theme.bars); diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index 4384a896..6edccb02 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -277,6 +277,10 @@ impl IdGen { } } +pub fn is_leaf_id(id: u16) -> bool { + id > 10_000 +} + /// Guaranteed to be unique for a leaf, /// the path to the leaf (through branch-id's) is /// encoded with the last byte byte being the leaf's id From 95491d006d863c47ca37bf52118f9cb202ffb51f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 16 Oct 2024 16:36:04 +0200 Subject: [PATCH 313/687] adds cursor --- crates/sensor-tui/examples/chart_gaps.rs | 3 + crates/sensor-tui/src/tui.rs | 14 +- crates/sensor-tui/src/tui/readings.rs | 142 +++++++++--------- .../sensor-tui/src/tui/readings/handle_key.rs | 80 ++++++++++ crates/sensor-tui/src/tui/readings/render.rs | 6 +- .../src/tui/readings/render/chart.rs | 64 ++++++-- .../src/tui/readings/render/chart/cursor.rs | 124 +++++++++++++++ .../src/tui/readings/render/chart/labels.rs | 8 +- .../src/tui/readings/render/chart/split.rs | 11 +- 9 files changed, 348 insertions(+), 104 deletions(-) create mode 100644 crates/sensor-tui/src/tui/readings/handle_key.rs create mode 100644 crates/sensor-tui/src/tui/readings/render/chart/cursor.rs diff --git a/crates/sensor-tui/examples/chart_gaps.rs b/crates/sensor-tui/examples/chart_gaps.rs index 2f9ffa30..d8c747fa 100644 --- a/crates/sensor-tui/examples/chart_gaps.rs +++ b/crates/sensor-tui/examples/chart_gaps.rs @@ -30,6 +30,9 @@ fn data_with_gap(buffer: &mut Vec<(f64, f64)>) -> ChartParts<'_> { ChartParts { info, data: buffer.as_mut_slice(), + reading: protocol::Reading::SmallBedroom(protocol::small_bedroom::Reading::Bed( + protocol::small_bedroom::bed::Reading::Temperature(0.0), + )), } } diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index fb9233ee..60a6a584 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -114,14 +114,6 @@ impl App { tracing::trace!("key pressed: {key:?}"); if key.kind == KeyEventKind::Press { let res = match key.code { - KeyCode::Left => { - self.active_tab = self.active_tab.swap(); - None - } - KeyCode::Right => { - self.active_tab = self.active_tab.swap(); - None - } KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => { break Ok(()); } @@ -137,6 +129,12 @@ impl App { if let Some(unhandled_key) = res { match unhandled_key.code { + KeyCode::Left => { + self.active_tab = self.active_tab.swap(); + } + KeyCode::Right => { + self.active_tab = self.active_tab.swap(); + } KeyCode::Char('q') | KeyCode::Esc => return Ok(()), _ => (), } diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index a5d06c01..f37fee21 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -1,13 +1,14 @@ use std::collections::HashSet; use std::time::Instant; -use crossterm::event::{KeyCode, KeyEvent}; +use crossterm::event::KeyEvent; use log_store::api::Percentile; use ratatui::layout::Rect; use ratatui::widgets::TableState; use ratatui::Frame; use tui_tree_widget::TreeState; +mod handle_key; pub(crate) mod history_len; pub mod render; pub mod sensor_info; @@ -19,10 +20,64 @@ use sensor_info::{is_leaf_id, ChartParts, Readings}; use super::Theme; #[derive(Debug, Default, Clone, Copy)] -enum InputMode { - #[default] - Normal, - EditingBounds, +struct InputMode { + editing_bounds: bool, + chart_cursor: bool, +} + +#[derive(Debug, Clone, Copy)] +pub enum ChartCursor { + Disabled { + // steps (characters) from the left where the cursor + // will be shown again if its re-enabled + steps: i32, + }, + Enabled { + // steps (characters) from the left + steps: i32, + }, +} + +impl Default for ChartCursor { + fn default() -> Self { + Self::Disabled { steps: 0 } + } +} + +impl ChartCursor { + fn is_enabled(&self) -> bool { + matches!(self, Self::Enabled { .. }) + } + fn toggle(&mut self) { + *self = match *self { + ChartCursor::Disabled { steps } => ChartCursor::Enabled { steps }, + ChartCursor::Enabled { steps } => ChartCursor::Disabled { steps }, + } + } + fn shift(&mut self, offset: i32) { + let ChartCursor::Enabled { ref mut steps } = self else { + return; + }; + + *steps += offset; + } + + fn get(&mut self, chart_width: u16) -> Option { + let steps = match self { + ChartCursor::Disabled { .. } => return None, + ChartCursor::Enabled { steps } => steps, + }; + + *steps = if *steps >= chart_width as i32 { + 0 + } else if *steps < 0 { + chart_width as i32 - 1 + } else { + *steps + }; + + Some(*steps as u16) + } } #[derive(Default)] @@ -30,7 +85,7 @@ pub struct UiState { show_histogram: bool, show_logs: bool, show_complete_help: bool, - show_cursor: bool, + chart_cursor: ChartCursor, history_length: HistoryLen, input_mode: InputMode, tree_state: TreeState, @@ -146,11 +201,15 @@ impl Tab { } pub fn handle_key(&mut self, key: KeyEvent) -> Option { - self.ui_state.handle_key_all_modes(key)?; - match self.ui_state.input_mode { - InputMode::Normal => self.ui_state.handle_key_normal_mode(key)?, - InputMode::EditingBounds => self.ui_state.handle_key_bounds_mode(key)?, + self.ui_state.handle_key_all(key)?; + if self.ui_state.input_mode.editing_bounds { + self.ui_state.handle_key_bounds(key)?; + } else { + self.ui_state.handle_key_normal_mode(key)?; }; + if self.ui_state.input_mode.chart_cursor { + self.ui_state.handle_key_cursor(key)?; + } Some(key) } @@ -218,66 +277,3 @@ impl Tab { ); } } - -impl UiState { - fn handle_key_normal_mode(&mut self, key: KeyEvent) -> Option { - match key.code { - KeyCode::Char('b') if self.reading_selected => { - self.history_length.start_editing(); - self.input_mode = InputMode::EditingBounds; - } - KeyCode::Char('h') if self.reading_selected => { - self.show_histogram = !self.show_histogram; - } - KeyCode::Char('l') if self.reading_selected => { - self.show_logs = !self.show_logs; - } - KeyCode::Char('x') if self.reading_selected => { - self.show_cursor = !self.show_cursor; - } - KeyCode::Char('c') if self.reading_selected => { - let id = *self - .tree_state - .selected() - .last() - .expect("reading_selected is true"); - if !self.comparing.remove(&id) { - self.comparing.insert(id); - } - } - KeyCode::Char('?') => { - self.show_complete_help = !self.show_complete_help; - } - _ => return Some(key), - } - - None - } - - fn handle_key_bounds_mode(&mut self, key: KeyEvent) -> Option { - match key.code { - KeyCode::Char('q') | KeyCode::Esc => { - self.history_length.exit_editing(); - self.input_mode = InputMode::Normal; - None - } - _ => self.history_length.process(key), - } - } - - fn handle_key_all_modes(&mut self, key: KeyEvent) -> Option { - match key.code { - KeyCode::Down => { - self.tree_state.key_down(); - } - KeyCode::Up => { - self.tree_state.key_up(); - } - KeyCode::Enter => { - self.tree_state.toggle_selected(); - } - _ => return Some(key), - } - None - } -} diff --git a/crates/sensor-tui/src/tui/readings/handle_key.rs b/crates/sensor-tui/src/tui/readings/handle_key.rs new file mode 100644 index 00000000..ceac5574 --- /dev/null +++ b/crates/sensor-tui/src/tui/readings/handle_key.rs @@ -0,0 +1,80 @@ +use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; +use super::UiState; + +impl UiState { + pub(crate) fn handle_key_normal_mode(&mut self, key: KeyEvent) -> Option { + match key.code { + KeyCode::Char('b') if self.reading_selected => { + self.history_length.start_editing(); + self.input_mode.editing_bounds = true; + } + KeyCode::Char('h') if self.reading_selected => { + self.show_histogram = !self.show_histogram; + } + KeyCode::Char('l') if self.reading_selected => { + self.show_logs = !self.show_logs; + } + KeyCode::Char('x') if self.reading_selected => { + self.chart_cursor.toggle(); + self.input_mode.chart_cursor = self.chart_cursor.is_enabled(); + } + KeyCode::Char('c') if self.reading_selected => { + let id = *self + .tree_state + .selected() + .last() + .expect("reading_selected is true"); + if !self.comparing.remove(&id) { + self.comparing.insert(id); + } + } + KeyCode::Char('?') => { + self.show_complete_help = !self.show_complete_help; + } + _ => return Some(key), + } + + None + } + + pub(crate) fn handle_key_cursor(&mut self, key: KeyEvent) -> Option { + let offset = match key.code { + KeyCode::Left if key.modifiers.contains(KeyModifiers::SHIFT) => -5, + KeyCode::Right if key.modifiers.contains(KeyModifiers::SHIFT) => 5, + KeyCode::Left => -1, + KeyCode::Right => 1, + _ => return Some(key), + }; + + self.chart_cursor.shift(offset); + None + } + + pub(crate) fn handle_key_bounds(&mut self, key: KeyEvent) -> Option { + match key.code { + KeyCode::Char('q') | KeyCode::Esc => { + self.history_length.exit_editing(); + self.input_mode.editing_bounds = false; + None + } + _ => self.history_length.process(key), + } + } + + pub(crate) fn handle_key_all(&mut self, key: KeyEvent) -> Option { + match key.code { + KeyCode::Down => { + self.tree_state.key_down(); + } + KeyCode::Up => { + self.tree_state.key_up(); + } + KeyCode::Enter => { + self.tree_state.toggle_selected(); + } + _ => return Some(key), + } + None + } +} + diff --git a/crates/sensor-tui/src/tui/readings/render.rs b/crates/sensor-tui/src/tui/readings/render.rs index 2590b696..ebfcf810 100644 --- a/crates/sensor-tui/src/tui/readings/render.rs +++ b/crates/sensor-tui/src/tui/readings/render.rs @@ -101,10 +101,10 @@ pub(crate) fn footer(frame: &mut Frame, layout: Rect, app: &mut UiState, theme: let mut extra = Vec::new(); if app.reading_selected { extra.push("c: toggle compare"); - if app.show_cursor { - extra.push("x: hide cursor"); + if app.chart_cursor.is_enabled() { + extra.push("x: enable cursor"); } else { - extra.push("x: show cursor"); + extra.push("x: disable cursor"); } } let footer = extra.join(" "); diff --git a/crates/sensor-tui/src/tui/readings/render/chart.rs b/crates/sensor-tui/src/tui/readings/render/chart.rs index 7afb0f59..777fc90a 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart.rs @@ -1,3 +1,6 @@ +use std::iter; + +use cursor::{CursorData, TooInaccurate}; use protocol::reading; use ratatui::{ layout::{Alignment, Rect}, @@ -8,8 +11,12 @@ use ratatui::{ Frame, }; -use crate::tui::readings::{sensor_info::ChartParts, UiState}; +use crate::{ + time::format::progressively_more_specified::FmtScale, + tui::readings::{sensor_info::ChartParts, ChartCursor, UiState}, +}; +mod cursor; mod labels; mod split; @@ -64,12 +71,12 @@ fn plot_colors(unit: protocol::Unit) -> impl Iterator { preferred.iter().chain(ALL_COLORS.iter()).copied() } -pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, charts: &mut [ChartParts]) { +pub fn render(frame: &mut Frame, layout: Rect, ui: &mut UiState, charts: &mut [ChartParts]) { let (colors, merged_y_bounds) = bounds_and_colors(charts, layout); let (y_labels, y_title) = labels::y_and_title(&merged_y_bounds, layout); - let x_bounds = [0f64, tab.history_length.dur.as_secs_f64()]; - let (x_labels, x_title) = labels::x_and_title(layout, x_bounds, &tab.history_length); + let x_bounds = [0f64, ui.history_length.dur.as_secs_f64()]; + let (x_labels, x_title, scale) = labels::x_and_title(layout, x_bounds, &ui.history_length); let x_axis = Axis::default() .title(x_title) @@ -78,12 +85,20 @@ pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, charts: &mut [ .labels(x_labels) .labels_alignment(Alignment::Center); + let y_axis_width = y_labels.iter().map(|l| l.len()).max().unwrap_or(0) as u16; let y_axis = Axis::default() .title(y_title) .style(Style::default()) .bounds([0.0, 1.0]) .labels(y_labels); + let chart_width = layout.width - y_axis_width - 3; + let cursor = if let Some(steps) = ui.chart_cursor.get(chart_width) { + Some(CursorData::new(steps, x_bounds, charts, chart_width)) + } else { + None + }; + let datasets = datasets(charts, &colors, merged_y_bounds, layout); let linechart = Chart::new(datasets) .block(Block::bordered().title("History")) @@ -91,8 +106,11 @@ pub fn render(frame: &mut Frame, layout: Rect, tab: &mut UiState, charts: &mut [ .y_axis(y_axis); frame.render_widget(linechart, layout); - if charts.len() > 1 { - render_legend(layout, frame, charts, colors); + if charts.len() > 1 || cursor.is_some() { + render_legend(layout, frame, charts, colors, cursor, scale); + } + if let Some(steps) = ui.chart_cursor.get(chart_width) { + cursor::render(layout, frame, steps, y_axis_width); } } @@ -156,12 +174,30 @@ fn bounds_and_colors( (colors, merged_y_bounds) } -fn render_legend(layout: Rect, frame: &mut Frame, charts: &mut [ChartParts], colors: Vec) { +fn render_legend( + layout: Rect, + frame: &mut Frame, + charts: &mut [ChartParts], + colors: Vec, + cursor: Option, + scale: FmtScale, +) { + let (values, cursor_label) = if let Some(CursorData { pos, values }) = cursor { + let renderd = labels::fmt(pos, &scale); + let label = format!("cursor: {} {}", renderd, scale); + (values, Some(Line::raw(label))) + } else { + (Vec::new(), None) + }; + let values = values.into_iter().map(Some).chain(iter::repeat(None)); + let text: Text = charts .iter() + .map(|ChartParts { reading, .. }| reading) .zip(colors) - .map(|(ChartParts { reading, .. }, color)| (reading, color)) + .zip(values) .map(fmt_reading) + .chain(cursor_label) .collect(); let area = legend_area(&text, layout); @@ -185,7 +221,12 @@ fn legend_area(text: &Text, chart: Rect) -> Rect { } } -fn fmt_reading((reading, color): (&protocol::Reading, Color)) -> Line { +fn fmt_reading( + ((reading, color), cursor_value): ( + (&protocol::Reading, Color), + Option>, + ), +) -> Line { use protocol::reading::tree::{Item, Tree}; let mut node = reading as &dyn Tree; let mut text = node.name(); @@ -198,6 +239,11 @@ fn fmt_reading((reading, color): (&protocol::Reading, Color)) -> Line { text.push('/'); text.push_str(&node.name()); } + match cursor_value { + Some(Ok(v)) => text.push_str(&format!(": {0:.1$}", v, reading.leaf().precision())), + Some(Err(TooInaccurate)) => text.push_str(" x"), + None => (), + } Line::styled(text, Style::default().fg(color).bg(Color::Gray)) } diff --git a/crates/sensor-tui/src/tui/readings/render/chart/cursor.rs b/crates/sensor-tui/src/tui/readings/render/chart/cursor.rs new file mode 100644 index 00000000..11df46a3 --- /dev/null +++ b/crates/sensor-tui/src/tui/readings/render/chart/cursor.rs @@ -0,0 +1,124 @@ +use itertools::Itertools; +use ratatui::prelude::Rect; +use ratatui::text::Span; +use ratatui::widgets::Clear; + +use crate::tui::readings::sensor_info::ChartParts; + +#[derive(Debug, Clone, Copy)] +pub struct TooInaccurate; + +pub struct CursorData { + pub pos: f64, + /// None means too far from cursor pos to be accurate + pub values: Vec>, +} +impl CursorData { + pub(crate) fn new( + steps: u16, + x_bounds: [f64; 2], + charts: &mut [ChartParts], + chart_width: u16, + ) -> Self { + let pos = resolve_pos(steps, x_bounds, chart_width).clamp(0.0, f64::MAX); + + // chart data has x axis reversed correct + // for that here + let flipped_pos = x_bounds[1] - pos; + // one character + let max_deviation = (x_bounds[1] - x_bounds[0]) / chart_width as f64; + let values = find_values(flipped_pos, max_deviation, charts); + CursorData { pos, values } + } +} + +/// # panics +/// if x is not >= ax and <= db +fn interpolate(a: (f64, f64), b: (f64, f64), x: f64) -> f64 { + assert!(x >= a.0); + assert!(x <= b.0); + + let dx = b.0 - a.0; + let dy = b.1 - a.1; + let dydx = dy / dx; + let delta_x = x - a.0; + + a.1 + delta_x * dydx +} + +/// do not interpolate large gaps +fn maybe_interpolate( + a: (f64, f64), + b: (f64, f64), + x: f64, + max_deviation: f64, +) -> Result { + if b.0 - a.0 > max_deviation { + if b.0 - x < max_deviation { + Ok(b.1) + } else if x - a.0 < max_deviation { + Ok(a.1) + } else { + Err(TooInaccurate) + } + } else { + Ok(interpolate(a, b, x)) + } +} + +fn find_values( + pos: f64, + max_deviation: f64, + charts: &mut [ChartParts], +) -> Vec> { + charts + .iter() + .map(|ChartParts { data, .. }| data) + .map(|data| { + let mut left = None; + let mut right = None; + for (x, y) in data.iter() { + if *x < pos { + left = Some((*x, *y)); + } else { + right = Some((*x, *y)); + break; + } + } + (left, right) + }) + .map(|(left, right)| match (left, right) { + (None, None) => Err(TooInaccurate), + (None, Some((x, y))) | (Some((x, y)), None) => { + if (pos - x).abs() <= max_deviation { + Ok(y) + } else { + Err(TooInaccurate) + } + } + (Some(a), Some(b)) => maybe_interpolate(a, b, pos, max_deviation), + }) + .collect() +} + +pub(crate) fn resolve_pos(steps: u16, x_bounds: [f64; 2], chart_width: u16) -> f64 { + let bounds_width = x_bounds[1] - x_bounds[0]; + let dist = bounds_width / chart_width as f64; + x_bounds[1] - dist * steps as f64 +} + +pub(crate) fn render(chart: Rect, frame: &mut ratatui::Frame, steps: u16, axis_label_width: u16) { + let left = chart + .left() + .saturating_add(steps) + .saturating_add(axis_label_width) + .saturating_add(2); + let area = Rect { + x: left.clamp(chart.x, chart.x + chart.width - 2), + y: chart.bottom() - 3, + width: 1, + height: 1, + }; + frame.render_widget(Clear, area); + frame.render_widget(Span::raw("*"), area); +} diff --git a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs index 925c2379..06a0143d 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs @@ -4,7 +4,7 @@ use protocol::reading; use ratatui::layout::Rect; use ratatui::text::Span; -use crate::time::format::progressively_more_specified; +use crate::time::format::progressively_more_specified::{self, FmtScale}; use crate::tui::readings::history_len::HistoryLen; use super::Bounds; @@ -50,7 +50,7 @@ pub fn x_and_title( layout: Rect, x_bounds: Bounds, history_len: &HistoryLen, -) -> (Labels, String) { +) -> (Labels, String, FmtScale) { // Characters are about twice as high as wide let max_labels = layout.width / Y_LABEL_SPACING / 2; let n_labels = max_labels.max(2); @@ -69,10 +69,10 @@ pub fn x_and_title( labels[0] = history_len.style_left_x_label(owned); let title = format!("Time ({scale})"); - (labels, title) + (labels, title, scale) } -fn fmt(x: f64, scale: &progressively_more_specified::FmtScale) -> String { +pub fn fmt(x: f64, scale: &progressively_more_specified::FmtScale) -> String { let now = jiff::Timestamp::now(); let elapsed = Duration::from_secs_f64(x); let time = now - elapsed; diff --git a/crates/sensor-tui/src/tui/readings/render/chart/split.rs b/crates/sensor-tui/src/tui/readings/render/chart/split.rs index bb3c747d..accefb24 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/split.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/split.rs @@ -20,13 +20,7 @@ pub(crate) fn split<'a>( chart: &'a ChartParts, chart_width: u16, ) -> impl Iterator { - let min_dist = chart - .info - .device - .info() - .max_sample_interval - .as_secs_f64() - * 1.2; // 20% margin + let min_dist = chart.info.device.info().max_sample_interval.as_secs_f64() * 1.2; // 20% margin let chart_resolution = chart .data @@ -88,6 +82,9 @@ mod test { branch_id: 1, }, data: &mut test_data, + reading: protocol::Reading::LargeBedroom(large_bedroom::Reading::Bed( + large_bedroom::bed::Reading::GassResistance(0.0), + )), }; assert_eq!(split(&test_chart, 500).count(), 5); assert_eq!( From d852b33387376424c2e24dcc92ab03096430ad2b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 16 Oct 2024 17:01:59 +0200 Subject: [PATCH 314/687] tui fix compare line's range not updating --- crates/sensor-tui/src/tui/readings.rs | 36 ++++++++++--------- .../src/tui/readings/render/chart.rs | 5 +-- .../src/tui/readings/render/chart/cursor.rs | 1 - 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index f37fee21..96caabc8 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -255,25 +255,27 @@ impl Tab { } pub(crate) fn fetch_if_needed(&mut self, fetcher: &mut Fetch) { - let Some(data) = self - .ui_state - .tree_state - .selected() - .last() // Unique leaf id - .and_then(|key| self.readings.get_by_ui_id(*key)) - else { - return; // Nothing selected - }; + let selected = self.ui_state.tree_state.selected().last(); + let needed = selected + .into_iter() + .chain(self.ui_state.comparing.iter()) + .copied(); let dur = self.ui_state.history_length.dur; let history_len = &mut self.ui_state.history_length.state; - fetcher.assure_up_to_date( - dur, - || *history_len = history_len::State::Fetching(Instant::now()), - data.reading.clone(), - data.oldest_in_history(), - data.logs.covers_from(), - data.histogram_range.clone(), - ); + for data in needed { + let Some(data) = self.readings.get_by_ui_id(data) else { + continue; + }; + + fetcher.assure_up_to_date( + dur, + || *history_len = history_len::State::Fetching(Instant::now()), + data.reading.clone(), + data.oldest_in_history(), + data.logs.covers_from(), + data.histogram_range.clone(), + ); + } } } diff --git a/crates/sensor-tui/src/tui/readings/render/chart.rs b/crates/sensor-tui/src/tui/readings/render/chart.rs index 777fc90a..c22e2e0c 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart.rs @@ -13,7 +13,7 @@ use ratatui::{ use crate::{ time::format::progressively_more_specified::FmtScale, - tui::readings::{sensor_info::ChartParts, ChartCursor, UiState}, + tui::readings::{sensor_info::ChartParts, UiState}, }; mod cursor; @@ -185,7 +185,8 @@ fn render_legend( let (values, cursor_label) = if let Some(CursorData { pos, values }) = cursor { let renderd = labels::fmt(pos, &scale); let label = format!("cursor: {} {}", renderd, scale); - (values, Some(Line::raw(label))) + let label = Line::styled(label, Style::default().bg(Color::Gray)); + (values, Some(label)) } else { (Vec::new(), None) }; diff --git a/crates/sensor-tui/src/tui/readings/render/chart/cursor.rs b/crates/sensor-tui/src/tui/readings/render/chart/cursor.rs index 11df46a3..8be9c47a 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/cursor.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/cursor.rs @@ -1,4 +1,3 @@ -use itertools::Itertools; use ratatui::prelude::Rect; use ratatui::text::Span; use ratatui::widgets::Clear; From 5b372858cae15b86988728d64aa314ca7feb0b66 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 16 Oct 2024 17:19:13 +0200 Subject: [PATCH 315/687] tui: fix tabs not working --- crates/sensor-tui/src/tui/affectors.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/sensor-tui/src/tui/affectors.rs b/crates/sensor-tui/src/tui/affectors.rs index 95505780..592126f6 100644 --- a/crates/sensor-tui/src/tui/affectors.rs +++ b/crates/sensor-tui/src/tui/affectors.rs @@ -81,8 +81,9 @@ impl Tab { } _ => { if let Some(state) = data { - return handle_key::handle(key, state, control); + handle_key::handle(key, state, control)?; } + return Some(key); } } None From 6af33e72201be1869c3044b5153a91a8cd8ec70a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 16 Oct 2024 19:23:04 +0200 Subject: [PATCH 316/687] tui use abbr month name in date --- .../src/time/format/progressively_more_specified.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/sensor-tui/src/time/format/progressively_more_specified.rs b/crates/sensor-tui/src/time/format/progressively_more_specified.rs index 41c0f636..1a09f73e 100644 --- a/crates/sensor-tui/src/time/format/progressively_more_specified.rs +++ b/crates/sensor-tui/src/time/format/progressively_more_specified.rs @@ -18,8 +18,8 @@ impl Display for FmtScale { FmtScale::RelativeDuration => f.write_str("elapsed"), FmtScale::HourMinute => f.write_str(":"), FmtScale::DayHour => f.write_str(" "), - FmtScale::MonthDay => f.write_str("/"), - FmtScale::YearMonth => f.write_str("/"), + FmtScale::MonthDay => f.write_str(" "), + FmtScale::YearMonth => f.write_str(" "), } } } @@ -67,8 +67,8 @@ impl FmtScale { FmtScale::RelativeDuration => duration(elapsed.as_secs_f64()) + duration_postfix, FmtScale::HourMinute => t.strftime("%H:%M").to_string(), FmtScale::DayHour => t.strftime("%dth %Hh").to_string(), - FmtScale::MonthDay => t.strftime("%M/%d").to_string(), - FmtScale::YearMonth => t.strftime("%Y/%m").to_string(), + FmtScale::MonthDay => t.strftime("%d %b").to_string(), + FmtScale::YearMonth => t.strftime("%b %Y").to_string(), } } } From b09d0e02e7df4553617acb19f33387c3a572d16a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 17 Oct 2024 12:38:19 +0200 Subject: [PATCH 317/687] tui prep for introducing zoom --- crates/sensor-tui/src/tui/readings.rs | 83 ++++++++++--------- .../sensor-tui/src/tui/readings/handle_key.rs | 46 +++++++--- .../src/tui/readings/history_len.rs | 71 ++++++++++++++-- crates/sensor-tui/src/tui/readings/render.rs | 4 +- .../src/tui/readings/render/chart.rs | 4 +- .../src/tui/readings/render/chart/labels.rs | 4 +- .../src/tui/readings/sensor_info.rs | 9 +- 7 files changed, 155 insertions(+), 66 deletions(-) diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index 96caabc8..c747c6c1 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -12,7 +12,7 @@ mod handle_key; pub(crate) mod history_len; pub mod render; pub mod sensor_info; -use history_len::HistoryLen; +use history_len::PlotRange; use crate::{fetch::Fetch, Update}; use sensor_info::{is_leaf_id, ChartParts, Readings}; @@ -26,57 +26,66 @@ struct InputMode { } #[derive(Debug, Clone, Copy)] -pub enum ChartCursor { - Disabled { - // steps (characters) from the left where the cursor - // will be shown again if its re-enabled - steps: i32, - }, - Enabled { - // steps (characters) from the left - steps: i32, - }, +pub struct ChartCursor { + enabled: bool, + steps: i32, + chart_width: Option, } impl Default for ChartCursor { fn default() -> Self { - Self::Disabled { steps: 0 } + Self { + enabled: false, + steps: 0, + chart_width: None, + } } } impl ChartCursor { fn is_enabled(&self) -> bool { - matches!(self, Self::Enabled { .. }) + self.enabled } fn toggle(&mut self) { - *self = match *self { - ChartCursor::Disabled { steps } => ChartCursor::Enabled { steps }, - ChartCursor::Enabled { steps } => ChartCursor::Disabled { steps }, - } + self.enabled = !self.enabled; } fn shift(&mut self, offset: i32) { - let ChartCursor::Enabled { ref mut steps } = self else { - return; - }; - - *steps += offset; + self.steps += offset; } fn get(&mut self, chart_width: u16) -> Option { - let steps = match self { - ChartCursor::Disabled { .. } => return None, - ChartCursor::Enabled { steps } => steps, - }; + self.chart_width = Some(chart_width); + if !self.enabled { + return None; + } - *steps = if *steps >= chart_width as i32 { + self.steps = if self.steps >= chart_width as i32 { 0 - } else if *steps < 0 { + } else if self.steps < 0 { chart_width as i32 - 1 } else { - *steps + self.steps + }; + + Some(self.steps as u16) + } + + fn zoom_in(&self) -> [f64; 2] { + let Some(chart_width) = self.chart_width else { + return [1.0, 1.0]; + }; + + let pos = chart_width as f64 / self.steps as f64; + [pos - 0.1, pos + 0.1] + } + + fn zoom_out(&self) -> [f64; 2] { + let Some(chart_width) = self.chart_width else { + return [1.0, 1.0]; }; - Some(*steps as u16) + let pos = chart_width as f64 / self.steps as f64; + [pos - 10.0, pos + 10.0] } } @@ -86,7 +95,7 @@ pub struct UiState { show_logs: bool, show_complete_help: bool, chart_cursor: ChartCursor, - history_length: HistoryLen, + plot_range: PlotRange, input_mode: InputMode, tree_state: TreeState, logs_table_state: TableState, @@ -122,7 +131,7 @@ fn fill_data<'a>( to_display: Vec, readings: &mut Readings, plot_bufs: &'a mut Vec>, - history_len: std::time::Duration, + history_len: &history_len::Range, ) -> DataToDisplay<'a> { for buf in plot_bufs.iter_mut() { buf.clear(); @@ -143,7 +152,7 @@ fn fill_data<'a>( res.logs = Some(info.logs()); } - res.chart_parts.push(info.chart(buf, history_len)); + res.chart_parts.push(info.chart(buf, &history_len)); } res } @@ -172,7 +181,7 @@ impl Tab { .collect(); to_display.sort(); to_display.dedup(); - fill_data(to_display, readings, plot_bufs, ui_state.history_length.dur) + fill_data(to_display, readings, plot_bufs, &ui_state.plot_range.range) }; let [top, bottom, footer] = render::layout( @@ -241,7 +250,7 @@ impl Tab { .as_ref() .is_some_and(|i| i.reading.is_same_as(&reading)) { - self.ui_state.history_length.state = history_len::State::Fetched; + self.ui_state.plot_range.state = history_len::State::Fetched; } self.readings.add_fetched(reading, fetched); } @@ -261,8 +270,8 @@ impl Tab { .chain(self.ui_state.comparing.iter()) .copied(); - let dur = self.ui_state.history_length.dur; - let history_len = &mut self.ui_state.history_length.state; + let dur = self.ui_state.plot_range.range.unwrap_duration().clone(); + let history_len = &mut self.ui_state.plot_range.state; for data in needed { let Some(data) = self.readings.get_by_ui_id(data) else { continue; diff --git a/crates/sensor-tui/src/tui/readings/handle_key.rs b/crates/sensor-tui/src/tui/readings/handle_key.rs index ceac5574..b9fa80d0 100644 --- a/crates/sensor-tui/src/tui/readings/handle_key.rs +++ b/crates/sensor-tui/src/tui/readings/handle_key.rs @@ -1,24 +1,48 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; use super::UiState; +use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; impl UiState { pub(crate) fn handle_key_normal_mode(&mut self, key: KeyEvent) -> Option { match key.code { - KeyCode::Char('b') if self.reading_selected => { - self.history_length.start_editing(); + KeyCode::Char('?') => { + self.show_complete_help = !self.show_complete_help; + } + _ => { + if self.reading_selected { + self.handle_key_reading_selected(key)?; + } + return Some(key); + } + } + + None + } + + fn handle_key_reading_selected(&mut self, key: KeyEvent) -> Option { + match key.code { + KeyCode::Char('b') => { + self.plot_range.start_editing(); self.input_mode.editing_bounds = true; } - KeyCode::Char('h') if self.reading_selected => { + KeyCode::Char('h') => { self.show_histogram = !self.show_histogram; } - KeyCode::Char('l') if self.reading_selected => { + KeyCode::Char('l') => { self.show_logs = !self.show_logs; } - KeyCode::Char('x') if self.reading_selected => { + KeyCode::Char('x') => { self.chart_cursor.toggle(); self.input_mode.chart_cursor = self.chart_cursor.is_enabled(); } - KeyCode::Char('c') if self.reading_selected => { + KeyCode::Char('i') if self.chart_cursor.is_enabled() => { + let change = self.chart_cursor.zoom_in(); + self.plot_range.change(change); + } + KeyCode::Char('o') if self.chart_cursor.is_enabled() => { + let change = self.chart_cursor.zoom_out(); + self.plot_range.change(change); + } + KeyCode::Char('c') => { let id = *self .tree_state .selected() @@ -28,9 +52,6 @@ impl UiState { self.comparing.insert(id); } } - KeyCode::Char('?') => { - self.show_complete_help = !self.show_complete_help; - } _ => return Some(key), } @@ -53,11 +74,11 @@ impl UiState { pub(crate) fn handle_key_bounds(&mut self, key: KeyEvent) -> Option { match key.code { KeyCode::Char('q') | KeyCode::Esc => { - self.history_length.exit_editing(); + self.plot_range.exit_editing(); self.input_mode.editing_bounds = false; None } - _ => self.history_length.process(key), + _ => self.plot_range.process(key), } } @@ -77,4 +98,3 @@ impl UiState { None } } - diff --git a/crates/sensor-tui/src/tui/readings/history_len.rs b/crates/sensor-tui/src/tui/readings/history_len.rs index 4b8729c0..41ff3d10 100644 --- a/crates/sensor-tui/src/tui/readings/history_len.rs +++ b/crates/sensor-tui/src/tui/readings/history_len.rs @@ -1,4 +1,5 @@ use crossterm::event::{KeyCode, KeyEvent}; +use jiff::Timestamp; use ratatui::{ style::{Color, Modifier, Style}, text::Span, @@ -17,14 +18,28 @@ pub enum State { Fetched, } -pub struct HistoryLen { +#[derive(Debug)] +pub enum Range { + Elapsed(Duration), + Window([jiff::Timestamp; 2]), +} + +impl Range { + pub(crate) fn unwrap_duration(&self) -> &Duration { + let Self::Elapsed(dur) = self else { todo!() }; + + dur + } +} + +pub struct PlotRange { pub text_input: String, pub editing: bool, pub state: State, - pub dur: Duration, + pub range: Range, } -impl Default for HistoryLen { +impl Default for PlotRange { fn default() -> Self { let dur = Duration::from_secs(15 * 60); let text_input = duration(dur.as_secs_f64()); @@ -32,12 +47,12 @@ impl Default for HistoryLen { text_input, editing: false, state: State::Empty, - dur, + range: Range::Elapsed(dur), } } } -impl HistoryLen { +impl PlotRange { pub(crate) fn process(&mut self, key: KeyEvent) -> Option { match key.code { KeyCode::Char(c) => { @@ -51,7 +66,7 @@ impl HistoryLen { if let Ok(dur) = parse_duration(&self.text_input) { self.state = State::Valid; - self.dur = dur; + self.range = Range::Elapsed(dur); } else if self.text_input.is_empty() { self.state = State::Empty; } else { @@ -110,4 +125,48 @@ impl HistoryLen { self.editing = true; self.text_input.clear(); } + + pub(crate) fn x_bounds(&self) -> [f64; 2] { + match self.range { + Range::Elapsed(dur) => [0f64, dur.as_secs_f64()], + Range::Window([start, end]) => { + let now = Timestamp::now(); + [ + start + .until(now) + .expect("now should be in the future") + .round(jiff::Unit::Second) + .expect("Timestamp.until(Timestamp) < Timestamp::Max") + .get_seconds() as f64, + end.until(now) + .expect("now should be in the future") + .round(jiff::Unit::Second) + .expect("Timestamp.until(Timestamp) < Timestamp::Max") + .get_seconds() as f64, + ] + } + } + } + + pub(crate) fn change(&mut self, [mul_start, mul_end]: [f64; 2]) { + let (dur, start) = match self.range { + Range::Elapsed(dur) => { + let start = Timestamp::now() - dur; + (dur.as_secs_f64(), start) + } + Range::Window([start, end]) => { + let dur = start + .until(end) + .expect("timestamps can be subtraced") + .round(jiff::Unit::Second) + .expect("Timestamp.until(Timestamp) < Timestamp::Max") + .get_seconds() as f64; + (dur, start) + } + }; + let start = start + Duration::from_secs_f64(dur * mul_start); + let end = start + Duration::from_secs_f64(dur * mul_end); + self.range = Range::Window([start, end]); + self.state = State::Valid; + } } diff --git a/crates/sensor-tui/src/tui/readings/render.rs b/crates/sensor-tui/src/tui/readings/render.rs index ebfcf810..9e0b4c87 100644 --- a/crates/sensor-tui/src/tui/readings/render.rs +++ b/crates/sensor-tui/src/tui/readings/render.rs @@ -63,14 +63,14 @@ pub(crate) fn layout( pub(crate) fn footer(frame: &mut Frame, layout: Rect, app: &mut UiState, theme: &Theme) { let mut main = Vec::new(); - if app.history_length.editing { + if app.plot_range.editing { main.push("ESC or q: stop bound editing"); } else { main.push("ESC or q: quit"); } if app.reading_selected { - if !app.history_length.editing { + if !app.plot_range.editing { main.push("b: edit graph start"); } diff --git a/crates/sensor-tui/src/tui/readings/render/chart.rs b/crates/sensor-tui/src/tui/readings/render/chart.rs index c22e2e0c..9df56096 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart.rs @@ -75,8 +75,8 @@ pub fn render(frame: &mut Frame, layout: Rect, ui: &mut UiState, charts: &mut [C let (colors, merged_y_bounds) = bounds_and_colors(charts, layout); let (y_labels, y_title) = labels::y_and_title(&merged_y_bounds, layout); - let x_bounds = [0f64, ui.history_length.dur.as_secs_f64()]; - let (x_labels, x_title, scale) = labels::x_and_title(layout, x_bounds, &ui.history_length); + let x_bounds = ui.plot_range.x_bounds(); + let (x_labels, x_title, scale) = labels::x_and_title(layout, x_bounds, &ui.plot_range); let x_axis = Axis::default() .title(x_title) diff --git a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs index 06a0143d..1bb6ef66 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs @@ -5,7 +5,7 @@ use ratatui::layout::Rect; use ratatui::text::Span; use crate::time::format::progressively_more_specified::{self, FmtScale}; -use crate::tui::readings::history_len::HistoryLen; +use crate::tui::readings::history_len::PlotRange; use super::Bounds; @@ -49,7 +49,7 @@ type Labels = Vec>; pub fn x_and_title( layout: Rect, x_bounds: Bounds, - history_len: &HistoryLen, + history_len: &PlotRange, ) -> (Labels, String, FmtScale) { // Characters are about twice as high as wide let max_labels = layout.width / Y_LABEL_SPACING / 2; diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index 6edccb02..50b7a189 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -9,7 +9,6 @@ use protocol::Reading; use protocol::{Device, Error}; use std::ops::RangeInclusive; -use std::time::Duration; use crate::Fetchable; @@ -17,6 +16,8 @@ mod logs; pub(crate) use logs::List as LogList; pub(crate) use logs::LogSource; +use super::history_len; + #[expect( clippy::large_enum_variant, reason = "Stored on the heap through Vec, mem waste of Branches is \ @@ -200,9 +201,9 @@ impl SensorInfo { pub fn chart<'a>( &mut self, plot_buf: &'a mut Vec<(f64, f64)>, - history_len: Duration, + history_len: &history_len::Range, ) -> ChartParts<'a> { - let reference = jiff::Timestamp::now() - history_len; + let reference = jiff::Timestamp::now() - history_len.unwrap_duration().clone(); let first_recent = self .recent_history @@ -226,7 +227,7 @@ impl SensorInfo { *y as f64, ) }) - .skip_while(|(x, _)| *x > history_len.as_secs_f64()) + .skip_while(|(x, _)| *x > history_len.unwrap_duration().as_secs_f64()) { plot_buf.push(xy); } From 2e4b6bcff0bf8516df1ec59b6c7e53f2a325480e Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 18 Oct 2024 12:02:51 +0200 Subject: [PATCH 318/687] Sync kitchen lighting with adjacent small bedroom With some minor adjustments to timing and colour --- crates/brain/src/controller/rooms/kitchen.rs | 5 +++-- crates/brain/src/controller/rooms/small_bedroom.rs | 10 +++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index c2846d47..35196e58 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -5,6 +5,7 @@ use futures_util::FutureExt; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; +use crate::controller::rooms::small_bedroom; use crate::controller::{local_now, Event, RestrictedSystem}; enum State { @@ -75,12 +76,12 @@ pub async fn run( } async fn update(system: &mut RestrictedSystem) { - let (new_ct, new_bri) = optimal_ct_bri(); + let (new_ct, new_bri) = small_bedroom::optimal_ct_bri(); system.all_lamps_ct(new_ct, new_bri).await; tracing::info!("updated lamps"); } -fn optimal_ct_bri() -> (u16, u8) { +fn _optimal_ct_bri() -> (u16, u8) { let now = local_now(); match now.hour() { 0..=8 | 22.. => (500, 180), diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 3fd214e8..bd24db7e 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -79,13 +79,13 @@ async fn update(system: &mut RestrictedSystem) { system.all_lamps_ct(new_ct, new_bri).await; } -fn optimal_ct_bri() -> (u16, u8) { +pub(crate) fn optimal_ct_bri() -> (u16, u8) { let now = local_now(); match now.hour() { - 0..=8 | 21.. => (500, 100), - 9..=16 => (270, u8::MAX), - 17..=18 => (300, u8::MAX), - 19..=20 => (460, 220), + 9..17 => (270, u8::MAX), + 17..20 => (300, u8::MAX), + 20..22 => (400, 220), + 22.. | 0..9 => (500, 100), } } From 7237daa3a79d330c5e1ddeb6dca46f5d02cee032 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 18 Oct 2024 17:02:28 +0200 Subject: [PATCH 319/687] port fetch and chart to PlotRange --- crates/sensor-tui/src/fetch.rs | 221 ++++++++++++------ crates/sensor-tui/src/tui/readings.rs | 17 +- .../{history_len.rs => plot_range.rs} | 38 ++- .../src/tui/readings/render/chart/labels.rs | 2 +- .../src/tui/readings/sensor_info.rs | 85 ++++--- .../src/tui/readings/sensor_info/logs.rs | 29 ++- 6 files changed, 269 insertions(+), 123 deletions(-) rename crates/sensor-tui/src/tui/readings/{history_len.rs => plot_range.rs} (82%) diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index 65e00732..06fe9847 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -7,13 +7,15 @@ use std::time::Duration; use color_eyre::eyre::{self, Context, Report}; use color_eyre::Result; -use jiff::{Span, Timestamp, Unit}; +use jiff::Timestamp; use log_store::api::{ErrorEvent, Percentile}; use protocol::Reading; use std::sync::Mutex; use tokio::time::Instant; use tracing::{debug, instrument}; +use crate::tui::readings::plot_range; +use crate::tui::readings::sensor_info::Cover; use crate::{client_name, Fetchable, Update}; const MAX_IN_FLIGHT_REQUESTS: usize = 6; @@ -44,24 +46,12 @@ pub enum Request { } impl Request { - fn unwrap_logs(&self) -> Option<&Logs> { - match self { - Request::Logs(d) => Some(d), - _ => None, - } - } fn data(&self) -> Option<&Data> { match self { Request::Data(d) => Some(d), _ => None, } } - fn unwrap_hist(&self) -> Option<&Hist> { - match self { - Request::Hist(d) => Some(d), - _ => None, - } - } } pub struct Fetch { @@ -87,113 +77,159 @@ impl Fetch { #[instrument(skip(self, on_fetch_start))] pub fn assure_up_to_date( &mut self, - history_len: Duration, + plot_range: plot_range::Range, on_fetch_start: impl FnOnce(), reading: Reading, - oldest_in_data: Timestamp, - logs_cover_from: Timestamp, - hist_cover: Option>, + data_covers: Cover, + logs_covers: Cover, + hist_covers: Option>, ) { - let history_spans = Span::try_from(history_len).unwrap(); - let start_needed = Timestamp::now() - history_spans; - if self.history_outdated_not_updating(&reading, start_needed, oldest_in_data) { + if !self.current_or_requested_data_suffice(&reading, plot_range, data_covers) { debug!("Requesting history for {reading:?}"); self.request(Request::Data(Data { reading: reading.clone(), - range: start_needed..=Timestamp::now(), + range: plot_range.range_inclusive(), })); (on_fetch_start)(); } - if self.logs_outdated_not_updating(&reading, start_needed, logs_cover_from) { + if !self.current_or_requested_logs_suffice(&reading, plot_range, logs_covers) { debug!("Requesting logs for {reading:?}"); self.request(Request::Logs(Logs { reading: reading.clone(), - range: start_needed..=Timestamp::now(), + range: plot_range.range_inclusive(), })) } - if self.hist_outdated_not_updating(&reading, start_needed, hist_cover) { + if !self.current_or_requested_hist_suffices(&reading, plot_range, hist_covers) { debug!("Requesting percentiles for {reading:?}"); self.request(Request::Hist(Hist { reading: reading.clone(), - range: start_needed..=Timestamp::now(), + range: plot_range.range_inclusive(), })) } } #[instrument(skip(self))] - fn history_outdated_not_updating( + fn current_or_requested_data_suffice( &mut self, reading: &Reading, - oldest_needed: Timestamp, - oldest_in_history: Timestamp, + needed: plot_range::Range, + current_data: Cover, ) -> bool { - let target_span = Timestamp::now() - oldest_needed; - let target_span = target_span.total(Unit::Millisecond).expect("fits f64"); - let max_span = (target_span * 1.2) as i64; - - let oldest_allowed = Timestamp::now().as_millisecond() - max_span; - let up_to_date = |start: &i64| *start >= oldest_allowed; - - let curr_up_to_date = up_to_date(&oldest_in_history.as_millisecond()); - let curr_range_correct = oldest_in_history <= oldest_needed; - - if curr_up_to_date && curr_range_correct { - return false; // No need for update + match current_data { + Cover::Overlapping { store, local } => { + if local.start() < needed.range_inclusive().start() { + return true; + } + let start = store.start().min(local.start()).clone(); + let end = store.end().max(local.end()).clone(); + if range_is_acceptable(&needed, start..=end) && resolution_ok(needed, store, local) + { + return true; + } + } + Cover::OnlyLocal(r) | Cover::OnlyStore(r) => { + if range_is_acceptable(&needed, r) { + return true; + } + } + Cover::Distinct { store, local } => { + if local.start() < needed.range_inclusive().start() { + return true; + } + if range_is_acceptable(&needed, store) { + return true; + } + } + Cover::None => (), } - // Is there an ongoing request that will fix this? - !self - .recently_issued + self.recently_issued .iter() .filter_map(Request::data) .filter(|req| req.reading.is_same_as(reading)) - .map(|req| req.range.start().as_millisecond()) - .filter(up_to_date) - .any(|start| start <= oldest_needed.as_millisecond()) + .map(|fetch| fetch.range.clone()) + .any(|range| range_is_acceptable(&needed, range)) } - fn logs_outdated_not_updating( + fn current_or_requested_logs_suffice( &mut self, reading: &Reading, - oldest_needed: Timestamp, - logs_cover_from: Timestamp, + needed: plot_range::Range, + logs_cover: Cover, ) -> bool { - if logs_cover_from <= oldest_needed { - return false; + let needed_range = needed.range_inclusive(); + match logs_cover { + Cover::Overlapping { store, local } => { + if local.start() < needed_range.start() { + return true; + } + if store + .start() + .duration_until(*needed_range.start()) + .is_positive() + && needed_range + .end() + .duration_until(*store.end()) + .is_positive() + { + return true; + } + } + Cover::OnlyLocal(r) | Cover::OnlyStore(r) => { + if r.start() + .duration_until(*needed_range.start()) + .is_positive() + && needed_range.end().duration_until(*r.end()).is_positive() + { + return true; + } + } + Cover::Distinct { store, local } => { + if local.start() < needed_range.start() { + return true; + } + if store + .start() + .duration_until(*needed_range.start()) + .is_positive() + && needed_range + .end() + .duration_until(*store.end()) + .is_positive() + { + return true; + } + } + Cover::None => (), } !self .recently_issued .iter() - .filter_map(Request::unwrap_logs) - .filter(|req| &req.reading == reading) - .map(|req| req.range.start().as_millisecond()) - .any(|start| start <= oldest_needed.as_millisecond()) + .filter_map(Request::data) + .filter(|req| req.reading.is_same_as(reading)) + .map(|fetch| fetch.range.clone()) + .any(|range| range_is_acceptable(&needed, range)) } - fn hist_outdated_not_updating( + fn current_or_requested_hist_suffices( &mut self, reading: &Reading, - oldest_needed: Timestamp, + needed: plot_range::Range, hist_range: Option>, ) -> bool { - fn covers_recently(end: Timestamp) -> bool { - Timestamp::now().since(end).unwrap().get_seconds() < 5 - } - - if hist_range.is_some_and(|r| r.contains(&oldest_needed) && covers_recently(*r.end())) { - return false; - } + let Some(hist_range) = hist_range else { + return true; + }; !self .recently_issued .iter() - .filter_map(Request::unwrap_hist) - .filter(|req| &req.reading == reading) - .map(|req| req.range.clone()) - .filter(|range| covers_recently(*range.end())) - .map(|range| range.start().as_millisecond()) - .any(|start| start <= oldest_needed.as_millisecond()) + .filter_map(Request::data) + .filter(|req| req.reading.is_same_as(reading)) + .map(|fetch| fetch.range.clone()) + .chain(Some(hist_range)) // or does the current data satisfy? + .any(|range| range_is_acceptable(&needed, range)) } fn request(&mut self, req: Request) { @@ -208,6 +244,51 @@ impl Fetch { } } +/// store might be resampled low resolution. If we use n% of all +/// stored data for less then n% of the needed range the resolution +/// will be high enough. +fn resolution_ok( + needed: plot_range::Range, + store: RangeInclusive, + local: RangeInclusive, +) -> bool { + let part_of_needed_coverd = needed + .range_inclusive() + .start() + .duration_until(*local.start().min(needed.range_inclusive().end())) + .unsigned_abs(); + let part_coverd_by_store = part_of_needed_coverd.div_duration_f32(needed.duration()); + let stored_duration = store.start().duration_until(*store.end()).unsigned_abs(); + let part_of_store_used = part_of_needed_coverd.div_duration_f32(stored_duration); + + part_coverd_by_store < part_of_store_used +} + +fn range_is_acceptable(needed: &plot_range::Range, range: RangeInclusive) -> bool { + let needed_range = needed.range_inclusive(); + let max_deviation = needed_range + .start() + .duration_until(*needed_range.end()) + .mul_f64(0.1); + assert!( + !max_deviation.is_negative(), + "needed_range: {needed_range:?}" + ); + + let data_start_is_ok = + range.start().duration_until(*needed_range.start()).abs() < max_deviation; + let data_end_is_ok = if needed.is_relative() { + range // allow range to end early + .end() + .duration_since(*needed_range.end()) + .abs() + < max_deviation + } else { + range.end().duration_since(*needed_range.end()) < max_deviation + }; + data_start_is_ok && data_end_is_ok +} + pub(crate) async fn handle_requests( data_store: SocketAddr, log_store: SocketAddr, diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index c747c6c1..13fd30e5 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -9,10 +9,10 @@ use ratatui::Frame; use tui_tree_widget::TreeState; mod handle_key; -pub(crate) mod history_len; +pub(crate) mod plot_range; pub mod render; pub mod sensor_info; -use history_len::PlotRange; +use plot_range::PlotRange; use crate::{fetch::Fetch, Update}; use sensor_info::{is_leaf_id, ChartParts, Readings}; @@ -131,7 +131,7 @@ fn fill_data<'a>( to_display: Vec, readings: &mut Readings, plot_bufs: &'a mut Vec>, - history_len: &history_len::Range, + history_len: &plot_range::Range, ) -> DataToDisplay<'a> { for buf in plot_bufs.iter_mut() { buf.clear(); @@ -250,7 +250,7 @@ impl Tab { .as_ref() .is_some_and(|i| i.reading.is_same_as(&reading)) { - self.ui_state.plot_range.state = history_len::State::Fetched; + self.ui_state.plot_range.state = plot_range::State::Fetched; } self.readings.add_fetched(reading, fetched); } @@ -270,7 +270,6 @@ impl Tab { .chain(self.ui_state.comparing.iter()) .copied(); - let dur = self.ui_state.plot_range.range.unwrap_duration().clone(); let history_len = &mut self.ui_state.plot_range.state; for data in needed { let Some(data) = self.readings.get_by_ui_id(data) else { @@ -278,11 +277,11 @@ impl Tab { }; fetcher.assure_up_to_date( - dur, - || *history_len = history_len::State::Fetching(Instant::now()), + self.ui_state.plot_range.range, + || *history_len = plot_range::State::Fetching(Instant::now()), data.reading.clone(), - data.oldest_in_history(), - data.logs.covers_from(), + data.covers(), + data.logs.covers(), data.histogram_range.clone(), ); } diff --git a/crates/sensor-tui/src/tui/readings/history_len.rs b/crates/sensor-tui/src/tui/readings/plot_range.rs similarity index 82% rename from crates/sensor-tui/src/tui/readings/history_len.rs rename to crates/sensor-tui/src/tui/readings/plot_range.rs index 41ff3d10..12873ea2 100644 --- a/crates/sensor-tui/src/tui/readings/history_len.rs +++ b/crates/sensor-tui/src/tui/readings/plot_range.rs @@ -4,7 +4,10 @@ use ratatui::{ style::{Color, Modifier, Style}, text::Span, }; -use std::time::{Duration, Instant}; +use std::{ + ops::RangeInclusive, + time::{Duration, Instant}, +}; use crate::time::format::duration; use crate::time::parse::parse_duration; @@ -18,17 +21,32 @@ pub enum State { Fetched, } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub enum Range { - Elapsed(Duration), + Relative(Duration), Window([jiff::Timestamp; 2]), } impl Range { - pub(crate) fn unwrap_duration(&self) -> &Duration { - let Self::Elapsed(dur) = self else { todo!() }; + pub(crate) fn is_relative(&self) -> bool { + matches!(self, Range::Relative(_)) + } - dur + pub(crate) fn range_inclusive(&self) -> RangeInclusive { + match self { + Range::Relative(dur) => { + let dur = jiff::Span::try_from(dur.clone()).unwrap(); + let now = jiff::Timestamp::now(); + (now - dur)..=now + } + Range::Window([start, end]) => *start..=*end, + } + } + pub(crate) fn duration(&self) -> Duration { + match self { + Range::Relative(dur) => dur.clone(), + Range::Window([start, end]) => start.duration_until(*end).unsigned_abs(), + } } } @@ -47,7 +65,7 @@ impl Default for PlotRange { text_input, editing: false, state: State::Empty, - range: Range::Elapsed(dur), + range: Range::Relative(dur), } } } @@ -66,7 +84,7 @@ impl PlotRange { if let Ok(dur) = parse_duration(&self.text_input) { self.state = State::Valid; - self.range = Range::Elapsed(dur); + self.range = Range::Relative(dur); } else if self.text_input.is_empty() { self.state = State::Empty; } else { @@ -128,7 +146,7 @@ impl PlotRange { pub(crate) fn x_bounds(&self) -> [f64; 2] { match self.range { - Range::Elapsed(dur) => [0f64, dur.as_secs_f64()], + Range::Relative(dur) => [0f64, dur.as_secs_f64()], Range::Window([start, end]) => { let now = Timestamp::now(); [ @@ -150,7 +168,7 @@ impl PlotRange { pub(crate) fn change(&mut self, [mul_start, mul_end]: [f64; 2]) { let (dur, start) = match self.range { - Range::Elapsed(dur) => { + Range::Relative(dur) => { let start = Timestamp::now() - dur; (dur.as_secs_f64(), start) } diff --git a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs index 1bb6ef66..e4a5a15c 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs @@ -5,7 +5,7 @@ use ratatui::layout::Rect; use ratatui::text::Span; use crate::time::format::progressively_more_specified::{self, FmtScale}; -use crate::tui::readings::history_len::PlotRange; +use crate::tui::readings::plot_range::PlotRange; use super::Bounds; diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index 50b7a189..dcd20635 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -16,7 +16,22 @@ mod logs; pub(crate) use logs::List as LogList; pub(crate) use logs::LogSource; -use super::history_len; +use super::plot_range; + +#[derive(Debug)] +pub(crate) enum Cover { + Overlapping { + store: RangeInclusive, + local: RangeInclusive, + }, + OnlyLocal(RangeInclusive), + OnlyStore(RangeInclusive), + Distinct { + store: RangeInclusive, + local: RangeInclusive, + }, + None, +} #[expect( clippy::large_enum_variant, @@ -201,44 +216,48 @@ impl SensorInfo { pub fn chart<'a>( &mut self, plot_buf: &'a mut Vec<(f64, f64)>, - history_len: &history_len::Range, + range: &plot_range::Range, ) -> ChartParts<'a> { - let reference = jiff::Timestamp::now() - history_len.unwrap_duration().clone(); + let start = *range.range_inclusive().start(); + let before_start = |t: &jiff::Timestamp| t < &start; + + let first_recent = self.recent_history.first().map(|(t, _)| t).cloned(); + let not_recent = |t: &jiff::Timestamp| !first_recent.is_some_and(|recent| t > &recent); - let first_recent = self - .recent_history - .first() - .map(|(t, _)| t) - .cloned() - .unwrap_or(jiff::Timestamp::MAX); + let end = *range.range_inclusive().end(); + let after_end = |t: &jiff::Timestamp| t > &end; plot_buf.clear(); for xy in self .history_from_store .iter() - .skip_while(|(t, _)| *t < reference) - .take_while(|(t, _)| *t < first_recent) + .take_while(|(t, _)| not_recent(t)) .chain(self.recent_history.iter()) + .skip_while(|(t, _)| before_start(t)) + .skip_while(|(t, _)| after_end(t)) .map(|(x, y)| { ( - (*x - reference) + (*x - start) .total(jiff::Unit::Second) .expect("unit is not a calander unit"), *y as f64, ) }) - .skip_while(|(x, _)| *x > history_len.unwrap_duration().as_secs_f64()) { plot_buf.push(xy); } - assert!( - plot_buf.iter().all(|(x, _)| *x > 0.0), - "negative x is not allowed. Arguments: - \thistory_len: {history_len:?} - \tfirst_recent: {first_recent} - \reference: {reference}" - ); + for (i, (x, _)) in plot_buf.iter().enumerate() { + assert!( + *x >= 0.0, + "negative x is not allowed. Info: + \t x: {x}, + \t index: {i}, + \t range: {range:?} + \t first_recent: {first_recent:?} + \t start: {start}" + ); + } ChartParts { info: self.info.clone(), @@ -251,19 +270,31 @@ impl SensorInfo { self.logs.list() } - pub(crate) fn oldest_in_history(&self) -> jiff::Timestamp { - jiff::Timestamp::min( + pub(crate) fn covers(&self) -> Cover { + use jiff::Timestamp as Ts; + let are_overlapping = + |store: &RangeInclusive, local: &RangeInclusive| local.start() <= store.end(); + + match ( self.history_from_store .first() .map(|(ts, _)| ts) - .copied() - .unwrap_or(jiff::Timestamp::MAX), + .zip(self.history_from_store.last().map(|(ts, _)| ts)) + .map(|(a, b)| *a..=*b), self.recent_history .first() .map(|(ts, _)| ts) - .copied() - .unwrap_or(jiff::Timestamp::MAX), - ) + .zip(self.recent_history.last().map(|(ts, _)| ts)) + .map(|(a, b)| *a..=*b), + ) { + (None, None) => Cover::None, + (None, Some(local)) => Cover::OnlyLocal(local), + (Some(store), None) => Cover::OnlyStore(store), + (Some(store), Some(local)) if are_overlapping(&store, &local) => { + Cover::Overlapping { store, local } + } + (Some(store), Some(local)) => Cover::Distinct { store, local }, + } } } diff --git a/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs b/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs index 47965052..3ec3d08c 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs @@ -3,6 +3,8 @@ use std::ops::{Bound, RangeBounds}; use jiff::Unit; use log_store::api::{self, ErrorEvent}; +use super::Cover; + #[derive(Debug)] pub(crate) struct FromStore { pub(crate) list: Vec, @@ -131,12 +133,27 @@ impl Logs { } } - pub(crate) fn covers_from(&self) -> jiff::Timestamp { - *self - .from_store - .as_ref() - .map(|FromStore { since, .. }| since) - .unwrap_or(&self.local.since) + pub(crate) fn covers(&self) -> Cover { + let store = self.from_store.as_ref().map(|FromStore { since, list }| { + let until = list + .iter() + .rev() + .filter_map(|ErrorEvent { end, .. }| *end) + .next() + .unwrap_or(*since); + *since..=until + }); + let local = self.local.since..=jiff::Timestamp::now(); + if let Some(store) = store { + let gap = store.end().duration_until(*local.start()); + if gap.is_negative() { + Cover::Overlapping { store, local } + } else { + Cover::Distinct { store, local } + } + } else { + Cover::OnlyLocal(local) + } } } From ecad1a817309d5fb9c934a41d2cb150e6d6306fd Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 19 Oct 2024 12:13:34 +0200 Subject: [PATCH 320/687] tui: fix plot when zooming in The bounds where correct for the labels not the data. Now there are two type of bounds: - data bounds which describe what the plot window should be. These go from zero to duration of plot range. - label bounds these are relative to the current time. --- crates/sensor-tui/src/tui/readings.rs | 4 +-- .../sensor-tui/src/tui/readings/handle_key.rs | 7 ++-- .../sensor-tui/src/tui/readings/plot_range.rs | 34 ++++++++++++++----- crates/sensor-tui/src/tui/readings/render.rs | 4 +-- .../src/tui/readings/render/chart.rs | 8 ++--- .../src/tui/readings/render/chart/labels.rs | 16 ++++----- .../src/tui/readings/sensor_info.rs | 25 +++++++------- 7 files changed, 57 insertions(+), 41 deletions(-) diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index 13fd30e5..241abd71 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -75,7 +75,7 @@ impl ChartCursor { return [1.0, 1.0]; }; - let pos = chart_width as f64 / self.steps as f64; + let pos = self.steps as f64 / chart_width as f64; [pos - 0.1, pos + 0.1] } @@ -84,7 +84,7 @@ impl ChartCursor { return [1.0, 1.0]; }; - let pos = chart_width as f64 / self.steps as f64; + let pos = self.steps as f64 / chart_width as f64; [pos - 10.0, pos + 10.0] } } diff --git a/crates/sensor-tui/src/tui/readings/handle_key.rs b/crates/sensor-tui/src/tui/readings/handle_key.rs index b9fa80d0..49667568 100644 --- a/crates/sensor-tui/src/tui/readings/handle_key.rs +++ b/crates/sensor-tui/src/tui/readings/handle_key.rs @@ -59,9 +59,12 @@ impl UiState { } pub(crate) fn handle_key_cursor(&mut self, key: KeyEvent) -> Option { + let mod_on = key.modifiers.contains(KeyModifiers::SHIFT) + | key.modifiers.contains(KeyModifiers::CONTROL); + let offset = match key.code { - KeyCode::Left if key.modifiers.contains(KeyModifiers::SHIFT) => -5, - KeyCode::Right if key.modifiers.contains(KeyModifiers::SHIFT) => 5, + KeyCode::Left if mod_on => -10, + KeyCode::Right if mod_on => 10, KeyCode::Left => -1, KeyCode::Right => 1, _ => return Some(key), diff --git a/crates/sensor-tui/src/tui/readings/plot_range.rs b/crates/sensor-tui/src/tui/readings/plot_range.rs index 12873ea2..fcd0bfde 100644 --- a/crates/sensor-tui/src/tui/readings/plot_range.rs +++ b/crates/sensor-tui/src/tui/readings/plot_range.rs @@ -1,5 +1,5 @@ use crossterm::event::{KeyCode, KeyEvent}; -use jiff::Timestamp; +use jiff::{SignedDuration, Timestamp}; use ratatui::{ style::{Color, Modifier, Style}, text::Span, @@ -144,26 +144,41 @@ impl PlotRange { self.text_input.clear(); } - pub(crate) fn x_bounds(&self) -> [f64; 2] { - match self.range { + pub(crate) fn label_bounds(&self) -> [f64; 2] { + let bounds = match self.range { Range::Relative(dur) => [0f64, dur.as_secs_f64()], Range::Window([start, end]) => { let now = Timestamp::now(); [ - start - .until(now) + end.until(now) .expect("now should be in the future") .round(jiff::Unit::Second) .expect("Timestamp.until(Timestamp) < Timestamp::Max") .get_seconds() as f64, - end.until(now) + start + .until(now) .expect("now should be in the future") .round(jiff::Unit::Second) .expect("Timestamp.until(Timestamp) < Timestamp::Max") .get_seconds() as f64, ] } - } + }; + assert!(bounds[0] >= 0.0, "bounds must be >= zero: {bounds:?}"); + assert!(bounds[1] >= 0.0, "bounds must be >= zero: {bounds:?}"); + bounds + } + + pub(crate) fn data_bounds(&self) -> [f64; 2] { + let dur = match self.range { + Range::Relative(dur) => dur.as_secs_f64(), + Range::Window([start, end]) => start + .until(end) + .expect("end should be in the future") + .total(jiff::Unit::Second) + .expect("Timestamp.until(Timestamp) < Timestamp::Max"), + }; + [0f64, dur] } pub(crate) fn change(&mut self, [mul_start, mul_end]: [f64; 2]) { @@ -182,8 +197,9 @@ impl PlotRange { (dur, start) } }; - let start = start + Duration::from_secs_f64(dur * mul_start); - let end = start + Duration::from_secs_f64(dur * mul_end); + let start = start + SignedDuration::from_secs_f64(dur * mul_start); + let end = start + SignedDuration::from_secs_f64(dur * mul_end); + let end = end.min(Timestamp::now()); self.range = Range::Window([start, end]); self.state = State::Valid; } diff --git a/crates/sensor-tui/src/tui/readings/render.rs b/crates/sensor-tui/src/tui/readings/render.rs index 9e0b4c87..9cbbeb0a 100644 --- a/crates/sensor-tui/src/tui/readings/render.rs +++ b/crates/sensor-tui/src/tui/readings/render.rs @@ -102,9 +102,9 @@ pub(crate) fn footer(frame: &mut Frame, layout: Rect, app: &mut UiState, theme: if app.reading_selected { extra.push("c: toggle compare"); if app.chart_cursor.is_enabled() { - extra.push("x: enable cursor"); - } else { extra.push("x: disable cursor"); + } else { + extra.push("x: enable cursor"); } } let footer = extra.join(" "); diff --git a/crates/sensor-tui/src/tui/readings/render/chart.rs b/crates/sensor-tui/src/tui/readings/render/chart.rs index 9df56096..75a95cf6 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart.rs @@ -75,13 +75,13 @@ pub fn render(frame: &mut Frame, layout: Rect, ui: &mut UiState, charts: &mut [C let (colors, merged_y_bounds) = bounds_and_colors(charts, layout); let (y_labels, y_title) = labels::y_and_title(&merged_y_bounds, layout); - let x_bounds = ui.plot_range.x_bounds(); - let (x_labels, x_title, scale) = labels::x_and_title(layout, x_bounds, &ui.plot_range); + let (x_labels, x_title, scale) = labels::x_and_title(layout, &ui.plot_range); + let data_bounds = ui.plot_range.data_bounds(); let x_axis = Axis::default() .title(x_title) .style(Style::default()) - .bounds(x_bounds) + .bounds(data_bounds) .labels(x_labels) .labels_alignment(Alignment::Center); @@ -94,7 +94,7 @@ pub fn render(frame: &mut Frame, layout: Rect, ui: &mut UiState, charts: &mut [C let chart_width = layout.width - y_axis_width - 3; let cursor = if let Some(steps) = ui.chart_cursor.get(chart_width) { - Some(CursorData::new(steps, x_bounds, charts, chart_width)) + Some(CursorData::new(steps, data_bounds, charts, chart_width)) } else { None }; diff --git a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs index e4a5a15c..0e0c9b85 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart/labels.rs @@ -46,19 +46,17 @@ fn y_labels(info: &reading::Info, layout: Rect, y_bounds: Bounds) -> Vec } type Labels = Vec>; -pub fn x_and_title( - layout: Rect, - x_bounds: Bounds, - history_len: &PlotRange, -) -> (Labels, String, FmtScale) { +pub fn x_and_title(layout: Rect, plot_range: &PlotRange) -> (Labels, String, FmtScale) { // Characters are about twice as high as wide let max_labels = layout.width / Y_LABEL_SPACING / 2; let n_labels = max_labels.max(2); - let x_spacing = (x_bounds[1] - x_bounds[0]) / n_labels as f64; - let scale = scale(x_bounds[1]); + let bounds = plot_range.label_bounds(); + let spacing = (bounds[1] - bounds[0]) / n_labels as f64; + + let scale = scale(bounds[1]); let mut labels: Labels = (0..=n_labels) - .map(move |i| x_bounds[0] + x_spacing * i as f64) + .map(move |i| bounds[0] + spacing * i as f64) .rev() .map(|x| fmt(x, &scale)) .map(Into::into) @@ -66,7 +64,7 @@ pub fn x_and_title( let borrowed = labels.first_mut().expect("min labels is 2"); let owned = std::mem::take(borrowed); - labels[0] = history_len.style_left_x_label(owned); + labels[0] = plot_range.style_left_x_label(owned); let title = format!("Time ({scale})"); (labels, title, scale) diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index dcd20635..01b4b37d 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -225,26 +225,25 @@ impl SensorInfo { let not_recent = |t: &jiff::Timestamp| !first_recent.is_some_and(|recent| t > &recent); let end = *range.range_inclusive().end(); - let after_end = |t: &jiff::Timestamp| t > &end; + let before_end = |t: &jiff::Timestamp| t < &end; plot_buf.clear(); - for xy in self + let plot = self .history_from_store .iter() .take_while(|(t, _)| not_recent(t)) .chain(self.recent_history.iter()) .skip_while(|(t, _)| before_start(t)) - .skip_while(|(t, _)| after_end(t)) - .map(|(x, y)| { - ( - (*x - start) - .total(jiff::Unit::Second) - .expect("unit is not a calander unit"), - *y as f64, - ) - }) - { - plot_buf.push(xy); + .take_while(|(t, _)| before_end(t)) + .collect_vec(); + + for (x, y) in plot { + plot_buf.push(( + (*x - start) + .total(jiff::Unit::Second) + .expect("unit is not a calander unit"), + *y as f64, + )) } for (i, (x, _)) in plot_buf.iter().enumerate() { From 32c3cfaeb469cb22ea2c5f0cc5dc6bac62d0654f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 21 Oct 2024 02:00:07 +0200 Subject: [PATCH 321/687] data-store: do not try storing data with same ts twice This is a temp fix, this should not occur as much as it does. The tech dept is recorded in an issue here: - https://github.com/dvdsk/HomeAutomation/issues/38 --- crates/data-store/src/server/db/series.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index c26f59a6..9298e9ae 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -140,8 +140,12 @@ impl Series { let new_ts = scaled_time; if self.last_timestamp_pushed.is_some_and(|ts| ts == new_ts) { - tracing::warn!("Skipping datapoint with same timestamp"); + tracing::trace!("Skipping datapoint with same timestamp"); + return Ok(()); + } else { + self.last_timestamp_pushed = Some(new_ts); } + self.byteseries .push_line(new_ts, &self.line) .wrap_err("Could not write to timeseries on disk")?; From 3754db595c69457a4205d973550620cb97bc5cc7 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 23 Oct 2024 21:11:54 +0200 Subject: [PATCH 322/687] update to latest embassy --- sensor-nodes/bed-lb/src/main.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sensor-nodes/bed-lb/src/main.rs b/sensor-nodes/bed-lb/src/main.rs index 5661932b..693fcc72 100644 --- a/sensor-nodes/bed-lb/src/main.rs +++ b/sensor-nodes/bed-lb/src/main.rs @@ -190,13 +190,13 @@ async fn main(spawner: Spawner) { // Init network stack let mut dns_servers: Vec<_, 3> = Vec::new(); - unwrap!(dns_servers.push(Ipv4Address([192, 168, 1, 1]))); - unwrap!(dns_servers.push(Ipv4Address([192, 168, 1, 1]))); - unwrap!(dns_servers.push(Ipv4Address([192, 168, 1, 1]))); + unwrap!(dns_servers.push(Ipv4Address::new(192, 168, 1, 1))); + unwrap!(dns_servers.push(Ipv4Address::new(192, 168, 1, 1))); + unwrap!(dns_servers.push(Ipv4Address::new(192, 168, 1, 1))); static RESOURCES: StaticCell> = StaticCell::new(); let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { - address: Ipv4Cidr::new(Ipv4Address([192, 168, 1, 7]), 24), - gateway: Some(Ipv4Address([192, 168, 1, 1])), + address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 1, 7), 24), + gateway: Some(Ipv4Address::new(192, 168, 1, 1)), dns_servers, }); let (stack, runner) = From 6248e4876e6d87c7e0bd6426c381933669c10922 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 25 Oct 2024 12:05:05 +0200 Subject: [PATCH 323/687] Initial working simple mqtt light control --- Cargo.lock | 227 ++++++++++++++++++++++++++++---- crates/zigbee-bridge/Cargo.toml | 12 ++ crates/zigbee-bridge/src/lib.rs | 109 +++++++++++++++ 3 files changed, 321 insertions(+), 27 deletions(-) create mode 100644 crates/zigbee-bridge/Cargo.toml create mode 100644 crates/zigbee-bridge/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index d8bc27b5..24e089fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -299,7 +299,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -381,7 +381,7 @@ checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -631,7 +631,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -891,7 +891,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -933,7 +933,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -1023,7 +1023,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -1092,7 +1092,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -1208,6 +1208,17 @@ dependencies = [ "miniz_oxide 0.8.0", ] +[[package]] +name = "flume" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +dependencies = [ + "futures-core", + "futures-sink", + "spin", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1355,7 +1366,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -1806,7 +1817,7 @@ dependencies = [ "proc-macro2", "quote", "strum", - "syn 2.0.79", + "syn 2.0.85", "thiserror", ] @@ -1817,7 +1828,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" dependencies = [ "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -2365,6 +2376,12 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + [[package]] name = "option-ext" version = "0.2.0" @@ -2466,7 +2483,7 @@ checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -2853,6 +2870,21 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if 1.0.0", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "ron" version = "0.8.1" @@ -2881,6 +2913,24 @@ dependencies = [ "tracing", ] +[[package]] +name = "rumqttc" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1568e15fab2d546f940ed3a21f48bbbd1c494c90c99c4481339364a497f94a9" +dependencies = [ + "bytes", + "flume", + "futures-util", + "log", + "rustls-native-certs", + "rustls-pemfile", + "rustls-webpki", + "thiserror", + "tokio", + "tokio-rustls", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -2909,6 +2959,59 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -2945,12 +3048,44 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "schannel" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "1.0.23" @@ -2986,29 +3121,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.210" +version = "1.0.213" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.213" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -3240,9 +3375,15 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.79", + "syn 2.0.85", ] +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "1.0.109" @@ -3256,9 +3397,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" dependencies = [ "proc-macro2", "quote", @@ -3330,7 +3471,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -3414,7 +3555,18 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", +] + +[[package]] +name = "tokio-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", ] [[package]] @@ -3502,7 +3654,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -3673,6 +3825,12 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.2" @@ -3799,7 +3957,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", "wasm-bindgen-shared", ] @@ -3833,7 +3991,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4090,5 +4248,20 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zigbee-bridge" +version = "0.1.0" +dependencies = [ + "rumqttc", + "serde_json", + "tokio", ] diff --git a/crates/zigbee-bridge/Cargo.toml b/crates/zigbee-bridge/Cargo.toml new file mode 100644 index 00000000..a2d42987 --- /dev/null +++ b/crates/zigbee-bridge/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "zigbee-bridge" +version = "0.1.0" +rust-version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true + +[dependencies] +rumqttc = "0.24.0" +serde_json = "1.0.132" +tokio.workspace = true diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs new file mode 100644 index 00000000..03f42941 --- /dev/null +++ b/crates/zigbee-bridge/src/lib.rs @@ -0,0 +1,109 @@ +// hue_power_on_behavior: "recover" / power_on_behavior: "previous" +// state: ON/OFF +// brightness: 0-254 +// color_temp: 153-500 (mired) / 250-454 +// color_temp_startup +// color_xy +// Set to on, off after 30s +// on_time: 30, off_wait_time: 30 + +use rumqttc::{ + AsyncClient, ClientError, ConnectionError, Event, EventLoop, MqttOptions, + QoS, +}; +use serde_json::json; + +const QOS: QoS = QoS::AtLeastOnce; + +pub struct LightController { + client: AsyncClient, + eventloop: EventLoop, +} + +impl LightController { + pub fn new() -> Self { + let options = + MqttOptions::new("ha-lampcontroller", "192.168.1.43", 1883); + let (client, eventloop) = AsyncClient::new(options, 128); + + Self { client, eventloop } + } + + pub async fn poll(&mut self) -> Result { + self.eventloop.poll().await + } + + pub async fn set_on(&self, friendly_name: &str) -> Result<(), ClientError> { + self.set(friendly_name, r#"{"state": "ON"}"#).await + } + + pub async fn set_off( + &self, + friendly_name: &str, + ) -> Result<(), ClientError> { + self.set(friendly_name, r#"{"state": "OFF"}"#).await + } + + /// Brightness: 0 to 1 + /// Color temperature: 2200-4000K + pub async fn set_bri_temp( + &self, + friendly_name: &str, + brightness: f64, + color_temp: usize, + ) -> Result<(), ClientError> { + let brightness = (brightness * 254.) as usize; + let payload = json!({ + "brightness": brightness, + "color_temp": kelvin_to_mired(color_temp) + }) + .to_string(); + + self.set(friendly_name, &payload).await + } + + async fn set( + &self, + friendly_name: &str, + payload: &str, + ) -> Result<(), ClientError> { + let topic = format!("zigbee2mqtt/{friendly_name}/set"); + + self.client + .publish(topic, QOS, false, payload) + .await?; + Ok(()) + } +} + +fn mired_to_kelvin(mired: usize) -> usize { + 1_000_000 / mired +} + +fn kelvin_to_mired(kelvin: usize) -> usize { + 1_000_000 / kelvin +} + +#[cfg(test)] +mod tests { + use super::*; + + #[ignore] + #[tokio::test] + async fn set_hallway_off() { + let mut controller = LightController::new(); + controller.set_off("gangkast tafellamp").await.unwrap(); + loop { + dbg!(controller.poll().await.unwrap()); + } + } + + #[tokio::test] + async fn set_hallway_dim() { + let mut controller = LightController::new(); + controller.set_bri_temp("gangkast tafellamp", 0.1, 2200).await.unwrap(); + loop { + dbg!(controller.poll().await.unwrap()); + } + } +} From 36fbdd0fc4bf9219d0deafe8261f7bbf8489375d Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 27 Oct 2024 11:58:00 +0100 Subject: [PATCH 324/687] Make structure and loops for async light control --- Cargo.lock | 1 + crates/zigbee-bridge/Cargo.toml | 3 +- crates/zigbee-bridge/src/lib.rs | 103 +--------------- crates/zigbee-bridge/src/lights.rs | 192 +++++++++++++++++++++++++++++ 4 files changed, 201 insertions(+), 98 deletions(-) create mode 100644 crates/zigbee-bridge/src/lights.rs diff --git a/Cargo.lock b/Cargo.lock index 24e089fa..b19bf8fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4263,5 +4263,6 @@ version = "0.1.0" dependencies = [ "rumqttc", "serde_json", + "thiserror", "tokio", ] diff --git a/crates/zigbee-bridge/Cargo.toml b/crates/zigbee-bridge/Cargo.toml index a2d42987..c94fe5ed 100644 --- a/crates/zigbee-bridge/Cargo.toml +++ b/crates/zigbee-bridge/Cargo.toml @@ -9,4 +9,5 @@ authors.workspace = true [dependencies] rumqttc = "0.24.0" serde_json = "1.0.132" -tokio.workspace = true +thiserror.workspace = true +tokio = { workspace = true, features = ["sync"] } diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 03f42941..62d0c569 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -7,103 +7,12 @@ // Set to on, off after 30s // on_time: 30, off_wait_time: 30 -use rumqttc::{ - AsyncClient, ClientError, ConnectionError, Event, EventLoop, MqttOptions, - QoS, -}; -use serde_json::json; +use rumqttc::QoS; -const QOS: QoS = QoS::AtLeastOnce; - -pub struct LightController { - client: AsyncClient, - eventloop: EventLoop, -} - -impl LightController { - pub fn new() -> Self { - let options = - MqttOptions::new("ha-lampcontroller", "192.168.1.43", 1883); - let (client, eventloop) = AsyncClient::new(options, 128); - - Self { client, eventloop } - } - - pub async fn poll(&mut self) -> Result { - self.eventloop.poll().await - } - - pub async fn set_on(&self, friendly_name: &str) -> Result<(), ClientError> { - self.set(friendly_name, r#"{"state": "ON"}"#).await - } - - pub async fn set_off( - &self, - friendly_name: &str, - ) -> Result<(), ClientError> { - self.set(friendly_name, r#"{"state": "OFF"}"#).await - } - - /// Brightness: 0 to 1 - /// Color temperature: 2200-4000K - pub async fn set_bri_temp( - &self, - friendly_name: &str, - brightness: f64, - color_temp: usize, - ) -> Result<(), ClientError> { - let brightness = (brightness * 254.) as usize; - let payload = json!({ - "brightness": brightness, - "color_temp": kelvin_to_mired(color_temp) - }) - .to_string(); +pub use lights::Controller; - self.set(friendly_name, &payload).await - } +mod lights; - async fn set( - &self, - friendly_name: &str, - payload: &str, - ) -> Result<(), ClientError> { - let topic = format!("zigbee2mqtt/{friendly_name}/set"); - - self.client - .publish(topic, QOS, false, payload) - .await?; - Ok(()) - } -} - -fn mired_to_kelvin(mired: usize) -> usize { - 1_000_000 / mired -} - -fn kelvin_to_mired(kelvin: usize) -> usize { - 1_000_000 / kelvin -} - -#[cfg(test)] -mod tests { - use super::*; - - #[ignore] - #[tokio::test] - async fn set_hallway_off() { - let mut controller = LightController::new(); - controller.set_off("gangkast tafellamp").await.unwrap(); - loop { - dbg!(controller.poll().await.unwrap()); - } - } - - #[tokio::test] - async fn set_hallway_dim() { - let mut controller = LightController::new(); - controller.set_bri_temp("gangkast tafellamp", 0.1, 2200).await.unwrap(); - loop { - dbg!(controller.poll().await.unwrap()); - } - } -} +const QOS: QoS = QoS::AtLeastOnce; +const MQTT_IP: &str = "192.168.1.43"; +const MQTT_PORT: u16 = 1883; diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs new file mode 100644 index 00000000..04250606 --- /dev/null +++ b/crates/zigbee-bridge/src/lights.rs @@ -0,0 +1,192 @@ +use std::error::Error; +use std::fmt::Display; + +use rumqttc::{AsyncClient, ClientError, EventLoop, MqttOptions}; +use rumqttc::{ConnectionError, Event}; +use serde_json::json; +use thiserror::Error; +use tokio::sync::mpsc::error::SendError; +use tokio::sync::{mpsc, RwLock}; +use tokio::task; + +use super::MQTT_IP; +use super::MQTT_PORT; +use super::QOS; + +#[derive(Debug, PartialEq)] +pub(crate) struct State { + pub(crate) on: bool, + pub(crate) brightness: f64, + pub(crate) color_temp: usize, + pub(crate) color_xy: (f64, f64), +} +impl State { + fn new() -> Self { + Self { + on: todo!(), + brightness: todo!(), + color_temp: todo!(), + color_xy: todo!(), + } + } + + fn apply(&self, change: Option) -> State { + todo!() + } +} + +#[derive(Debug)] +pub(crate) struct StateChange { + pub(crate) friendly_name: String, + pub(crate) on: Option, + pub(crate) brightness: Option, + pub(crate) color_temp: Option, + pub(crate) color_xy: Option<(f64, f64)>, +} + +#[derive(Clone)] +pub struct Controller { + pub(crate) change_sender: mpsc::UnboundedSender, +} + +pub struct CachedBridge {} + +impl CachedBridge { + pub async fn set_on(&self, friendly_name: &str) -> Result<(), ClientError> { + self.set(friendly_name, r#"{"state": "ON"}"#).await + } + + pub async fn set_off( + &self, + friendly_name: &str, + ) -> Result<(), ClientError> { + self.set(friendly_name, r#"{"state": "OFF"}"#).await + } + + /// Brightness: 0 to 1 + /// Color temperature: 2200-4000K + pub async fn set_bri_temp( + &self, + friendly_name: &str, + brightness: f64, + color_temp: usize, + ) -> Result<(), ClientError> { + let brightness = (brightness * 254.) as usize; + let payload = json!({ + "brightness": brightness, + "color_temp": kelvin_to_mired(color_temp) + }) + .to_string(); + + self.set(friendly_name, &payload).await + } + + pub(crate) async fn set( + &self, + friendly_name: &str, + payload: &str, + ) -> Result<(), ClientError> { + let topic = format!("zigbee2mqtt/{friendly_name}/set"); + + self.mqtt_client.publish(topic, QOS, false, payload).await?; + Ok(()) + } + + async fn run(mut change_receiver: mpsc::UnboundedReceiver) { + let options = + MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); + // TODO: init through mqtt get + let known_state = RwLock::new(State::new()); + let needed_state = State::new(); + + loop { + let (mqtt_client, eventloop) = + AsyncClient::new(options.clone(), 128); + let poll_mqtt = poll_mqtt(eventloop, &known_state); + + // TODO: these are dropped from the task when it ends, but ownership is + // not transferred back... + let handle_changes = handle_changes( + change_receiver, + mqtt_client, + &known_state, + needed_state, + ); + + tokio::select! { + _ = handle_changes => (), + _ = poll_mqtt => (), + } + println!( + "Something went wrong with the mqtt connection, reconnecting" + ); + } + } +} + +async fn handle_changes( + mut change_receiver: mpsc::UnboundedReceiver, + mut mqtt_client: AsyncClient, + known_state: &RwLock, + mut needed_state: State, +) -> Result<(), ClientError> { + loop { + let change = change_receiver.recv().await; + needed_state = needed_state.apply(change); + let known_state = known_state.read().await; + + if needed_state != *known_state { + // Actually publish using mqtt_client + send_new_state(&mut mqtt_client, needed_state); + } + } +} + +fn send_new_state(mqtt_client: &mut AsyncClient, needed_state: State) -> _ { + todo!() +} + +impl Controller { + pub fn start_bridge() -> Self { + let (change_sender, change_receiver) = mpsc::unbounded_channel(); + + let run_bridge = CachedBridge::run(change_receiver); + tokio::task::spawn(run_bridge); + + Self { change_sender } + } +} + +#[derive(Debug, Error)] +enum MqttError { + #[error("{0}")] + Connection(#[from] ConnectionError), + #[error("{0}")] + Send(#[from] SendError), +} + +async fn poll_mqtt( + mut eventloop: EventLoop, + known_state: &RwLock, +) -> Result<(), ConnectionError> { + loop { + let message = eventloop.poll().await?; + let new_known_state = extract_state_update(message); + + let mut known_state = known_state.write().await; + *known_state = new_known_state; + } +} + +// Should return complete new state, otherwise change poll_mqtt +fn extract_state_update(message: Event) -> State { + todo!() +} + +pub(crate) fn mired_to_kelvin(mired: usize) -> usize { + 1_000_000 / mired +} + +pub(crate) fn kelvin_to_mired(kelvin: usize) -> usize { + 1_000_000 / kelvin +} From 3e6b9f0f9794d1bc750bd352081c24b5f7ed9108 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 27 Oct 2024 12:11:08 +0100 Subject: [PATCH 325/687] Fix compile errors, not yet working --- crates/zigbee-bridge/src/lights.rs | 44 ++++++++++++------------------ 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index 04250606..9872c8b3 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -1,13 +1,9 @@ -use std::error::Error; -use std::fmt::Display; - use rumqttc::{AsyncClient, ClientError, EventLoop, MqttOptions}; use rumqttc::{ConnectionError, Event}; use serde_json::json; use thiserror::Error; use tokio::sync::mpsc::error::SendError; use tokio::sync::{mpsc, RwLock}; -use tokio::task; use super::MQTT_IP; use super::MQTT_PORT; @@ -30,7 +26,7 @@ impl State { } } - fn apply(&self, change: Option) -> State { + fn apply(&mut self, change: Option) -> State { todo!() } } @@ -52,21 +48,18 @@ pub struct Controller { pub struct CachedBridge {} impl CachedBridge { - pub async fn set_on(&self, friendly_name: &str) -> Result<(), ClientError> { - self.set(friendly_name, r#"{"state": "ON"}"#).await - } - - pub async fn set_off( - &self, + pub async fn set_on( + mqtt_client: AsyncClient, friendly_name: &str, ) -> Result<(), ClientError> { - self.set(friendly_name, r#"{"state": "OFF"}"#).await + CachedBridge::set(mqtt_client, friendly_name, r#"{"state": "ON"}"#) + .await } /// Brightness: 0 to 1 /// Color temperature: 2200-4000K pub async fn set_bri_temp( - &self, + mqtt_client: AsyncClient, friendly_name: &str, brightness: f64, color_temp: usize, @@ -78,17 +71,17 @@ impl CachedBridge { }) .to_string(); - self.set(friendly_name, &payload).await + CachedBridge::set(mqtt_client, friendly_name, &payload).await } pub(crate) async fn set( - &self, + mqtt_client: AsyncClient, friendly_name: &str, payload: &str, ) -> Result<(), ClientError> { let topic = format!("zigbee2mqtt/{friendly_name}/set"); - self.mqtt_client.publish(topic, QOS, false, payload).await?; + mqtt_client.publish(topic, QOS, false, payload).await?; Ok(()) } @@ -97,20 +90,18 @@ impl CachedBridge { MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); // TODO: init through mqtt get let known_state = RwLock::new(State::new()); - let needed_state = State::new(); + let mut needed_state = State::new(); loop { let (mqtt_client, eventloop) = AsyncClient::new(options.clone(), 128); let poll_mqtt = poll_mqtt(eventloop, &known_state); - // TODO: these are dropped from the task when it ends, but ownership is - // not transferred back... let handle_changes = handle_changes( - change_receiver, + &mut change_receiver, mqtt_client, &known_state, - needed_state, + &mut needed_state, ); tokio::select! { @@ -125,24 +116,23 @@ impl CachedBridge { } async fn handle_changes( - mut change_receiver: mpsc::UnboundedReceiver, + change_receiver: &mut mpsc::UnboundedReceiver, mut mqtt_client: AsyncClient, known_state: &RwLock, - mut needed_state: State, + needed_state: &mut State, ) -> Result<(), ClientError> { loop { let change = change_receiver.recv().await; - needed_state = needed_state.apply(change); + *needed_state = needed_state.apply(change); let known_state = known_state.read().await; - if needed_state != *known_state { - // Actually publish using mqtt_client + if *needed_state != *known_state { send_new_state(&mut mqtt_client, needed_state); } } } -fn send_new_state(mqtt_client: &mut AsyncClient, needed_state: State) -> _ { +fn send_new_state(mqtt_client: &mut AsyncClient, needed_state: &State) { todo!() } From d5741476511245dc72c17072756d9326abe2188e Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 27 Oct 2024 12:26:53 +0100 Subject: [PATCH 326/687] Divide into modules --- crates/zigbee-bridge/src/lights.rs | 172 +----------------- .../zigbee-bridge/src/lights/cached_bridge.rs | 127 +++++++++++++ crates/zigbee-bridge/src/lights/state.rs | 32 ++++ 3 files changed, 164 insertions(+), 167 deletions(-) create mode 100644 crates/zigbee-bridge/src/lights/cached_bridge.rs create mode 100644 crates/zigbee-bridge/src/lights/state.rs diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index 9872c8b3..60cd8087 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -1,182 +1,20 @@ -use rumqttc::{AsyncClient, ClientError, EventLoop, MqttOptions}; -use rumqttc::{ConnectionError, Event}; -use serde_json::json; -use thiserror::Error; -use tokio::sync::mpsc::error::SendError; -use tokio::sync::{mpsc, RwLock}; +use tokio::sync::mpsc; -use super::MQTT_IP; -use super::MQTT_PORT; -use super::QOS; - -#[derive(Debug, PartialEq)] -pub(crate) struct State { - pub(crate) on: bool, - pub(crate) brightness: f64, - pub(crate) color_temp: usize, - pub(crate) color_xy: (f64, f64), -} -impl State { - fn new() -> Self { - Self { - on: todo!(), - brightness: todo!(), - color_temp: todo!(), - color_xy: todo!(), - } - } - - fn apply(&mut self, change: Option) -> State { - todo!() - } -} - -#[derive(Debug)] -pub(crate) struct StateChange { - pub(crate) friendly_name: String, - pub(crate) on: Option, - pub(crate) brightness: Option, - pub(crate) color_temp: Option, - pub(crate) color_xy: Option<(f64, f64)>, -} +mod cached_bridge; +mod state; #[derive(Clone)] pub struct Controller { - pub(crate) change_sender: mpsc::UnboundedSender, -} - -pub struct CachedBridge {} - -impl CachedBridge { - pub async fn set_on( - mqtt_client: AsyncClient, - friendly_name: &str, - ) -> Result<(), ClientError> { - CachedBridge::set(mqtt_client, friendly_name, r#"{"state": "ON"}"#) - .await - } - - /// Brightness: 0 to 1 - /// Color temperature: 2200-4000K - pub async fn set_bri_temp( - mqtt_client: AsyncClient, - friendly_name: &str, - brightness: f64, - color_temp: usize, - ) -> Result<(), ClientError> { - let brightness = (brightness * 254.) as usize; - let payload = json!({ - "brightness": brightness, - "color_temp": kelvin_to_mired(color_temp) - }) - .to_string(); - - CachedBridge::set(mqtt_client, friendly_name, &payload).await - } - - pub(crate) async fn set( - mqtt_client: AsyncClient, - friendly_name: &str, - payload: &str, - ) -> Result<(), ClientError> { - let topic = format!("zigbee2mqtt/{friendly_name}/set"); - - mqtt_client.publish(topic, QOS, false, payload).await?; - Ok(()) - } - - async fn run(mut change_receiver: mpsc::UnboundedReceiver) { - let options = - MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); - // TODO: init through mqtt get - let known_state = RwLock::new(State::new()); - let mut needed_state = State::new(); - - loop { - let (mqtt_client, eventloop) = - AsyncClient::new(options.clone(), 128); - let poll_mqtt = poll_mqtt(eventloop, &known_state); - - let handle_changes = handle_changes( - &mut change_receiver, - mqtt_client, - &known_state, - &mut needed_state, - ); - - tokio::select! { - _ = handle_changes => (), - _ = poll_mqtt => (), - } - println!( - "Something went wrong with the mqtt connection, reconnecting" - ); - } - } -} - -async fn handle_changes( - change_receiver: &mut mpsc::UnboundedReceiver, - mut mqtt_client: AsyncClient, - known_state: &RwLock, - needed_state: &mut State, -) -> Result<(), ClientError> { - loop { - let change = change_receiver.recv().await; - *needed_state = needed_state.apply(change); - let known_state = known_state.read().await; - - if *needed_state != *known_state { - send_new_state(&mut mqtt_client, needed_state); - } - } -} - -fn send_new_state(mqtt_client: &mut AsyncClient, needed_state: &State) { - todo!() + pub(crate) change_sender: mpsc::UnboundedSender, } impl Controller { pub fn start_bridge() -> Self { let (change_sender, change_receiver) = mpsc::unbounded_channel(); - let run_bridge = CachedBridge::run(change_receiver); + let run_bridge = cached_bridge::CachedBridge::run(change_receiver); tokio::task::spawn(run_bridge); Self { change_sender } } } - -#[derive(Debug, Error)] -enum MqttError { - #[error("{0}")] - Connection(#[from] ConnectionError), - #[error("{0}")] - Send(#[from] SendError), -} - -async fn poll_mqtt( - mut eventloop: EventLoop, - known_state: &RwLock, -) -> Result<(), ConnectionError> { - loop { - let message = eventloop.poll().await?; - let new_known_state = extract_state_update(message); - - let mut known_state = known_state.write().await; - *known_state = new_known_state; - } -} - -// Should return complete new state, otherwise change poll_mqtt -fn extract_state_update(message: Event) -> State { - todo!() -} - -pub(crate) fn mired_to_kelvin(mired: usize) -> usize { - 1_000_000 / mired -} - -pub(crate) fn kelvin_to_mired(kelvin: usize) -> usize { - 1_000_000 / kelvin -} diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs new file mode 100644 index 00000000..4e455f3b --- /dev/null +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -0,0 +1,127 @@ +use rumqttc::{AsyncClient, ClientError, EventLoop}; +use rumqttc::{ConnectionError, Event}; +use rumqttc::MqttOptions; +use serde_json::json; +use tokio::sync::{mpsc, RwLock}; + +use crate::{MQTT_IP, MQTT_PORT, QOS}; +use crate::lights::state::{Change, State}; + +pub struct CachedBridge {} + +impl CachedBridge { + pub async fn set_on( + mqtt_client: AsyncClient, + friendly_name: &str, + ) -> Result<(), ClientError> { + CachedBridge::set(mqtt_client, friendly_name, r#"{"state": "ON"}"#) + .await + } + + /// Brightness: 0 to 1 + /// Color temperature: 2200-4000K + pub async fn set_bri_temp( + mqtt_client: AsyncClient, + friendly_name: &str, + brightness: f64, + color_temp: usize, + ) -> Result<(), ClientError> { + let brightness = (brightness * 254.) as usize; + let payload = json!({ + "brightness": brightness, + "color_temp": kelvin_to_mired(color_temp) + }) + .to_string(); + + CachedBridge::set(mqtt_client, friendly_name, &payload).await + } + + pub(crate) async fn set( + mqtt_client: AsyncClient, + friendly_name: &str, + payload: &str, + ) -> Result<(), ClientError> { + let topic = format!("zigbee2mqtt/{friendly_name}/set"); + + mqtt_client.publish(topic, QOS, false, payload).await?; + Ok(()) + } + + pub(crate) async fn run( + mut change_receiver: mpsc::UnboundedReceiver, + ) { + let options = + MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); + // TODO: init through mqtt get + let known_state = RwLock::new(State::new()); + let mut needed_state = State::new(); + + loop { + let (mqtt_client, eventloop) = + AsyncClient::new(options.clone(), 128); + let poll_mqtt = poll_mqtt(eventloop, &known_state); + + let handle_changes = handle_changes( + &mut change_receiver, + mqtt_client, + &known_state, + &mut needed_state, + ); + + tokio::select! { + _ = handle_changes => (), + _ = poll_mqtt => (), + } + println!( + "Something went wrong with the mqtt connection, reconnecting" + ); + } + } +} + +async fn poll_mqtt( + mut eventloop: EventLoop, + known_state: &RwLock, +) -> Result<(), ConnectionError> { + loop { + let message = eventloop.poll().await?; + let new_known_state = extract_state_update(message); + + let mut known_state = known_state.write().await; + *known_state = new_known_state; + } +} + +async fn handle_changes( + change_receiver: &mut mpsc::UnboundedReceiver, + mut mqtt_client: AsyncClient, + known_state: &RwLock, + needed_state: &mut State, +) -> Result<(), ClientError> { + loop { + let change = change_receiver.recv().await; + *needed_state = needed_state.apply(change); + let known_state = known_state.read().await; + + if *needed_state != *known_state { + send_new_state(&mut mqtt_client, needed_state); + } + } +} + +fn send_new_state(mqtt_client: &mut AsyncClient, needed_state: &State) { + todo!() +} + +// Should return complete new state, otherwise change poll_mqtt +fn extract_state_update(message: Event) -> State { + todo!() +} + +pub(crate) fn mired_to_kelvin(mired: usize) -> usize { + 1_000_000 / mired +} + +pub(crate) fn kelvin_to_mired(kelvin: usize) -> usize { + 1_000_000 / kelvin +} diff --git a/crates/zigbee-bridge/src/lights/state.rs b/crates/zigbee-bridge/src/lights/state.rs new file mode 100644 index 00000000..dba50de1 --- /dev/null +++ b/crates/zigbee-bridge/src/lights/state.rs @@ -0,0 +1,32 @@ +#[derive(Debug, PartialEq)] +pub(crate) struct State { + pub(crate) brightness: f64, + pub(crate) color_temp: usize, + pub(crate) color_xy: (f64, f64), + pub(crate) on: bool, +} + +impl State { + pub(crate) fn new() -> Self { + Self { + on: todo!(), + brightness: todo!(), + color_temp: todo!(), + color_xy: todo!(), + } + } + + pub(crate) fn apply(&mut self, change: Option) -> State { + todo!() + } +} + +#[derive(Debug)] +pub(crate) struct Change { + pub(crate) friendly_name: String, + pub(crate) on: Option, + pub(crate) brightness: Option, + pub(crate) color_temp: Option, + pub(crate) color_xy: Option<(f64, f64)>, +} + From eba44a5d7169eb58a9a380be2546c42b8685c28f Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 27 Oct 2024 12:56:15 +0100 Subject: [PATCH 327/687] Attempt to put mqtt_client and eventloop into Self using Pin Going to revert this --- .../zigbee-bridge/src/lights/cached_bridge.rs | 111 ++++++++++-------- crates/zigbee-bridge/src/lights/state.rs | 1 + 2 files changed, 64 insertions(+), 48 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 4e455f3b..39be1b60 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -1,27 +1,45 @@ +#![allow(unused)] +use std::pin::{pin, Pin}; + +use rumqttc::MqttOptions; use rumqttc::{AsyncClient, ClientError, EventLoop}; use rumqttc::{ConnectionError, Event}; -use rumqttc::MqttOptions; use serde_json::json; use tokio::sync::{mpsc, RwLock}; -use crate::{MQTT_IP, MQTT_PORT, QOS}; use crate::lights::state::{Change, State}; +use crate::{MQTT_IP, MQTT_PORT, QOS}; -pub struct CachedBridge {} +pub struct CachedBridge { + mqtt_client: AsyncClient, + eventloop: EventLoop, + options: MqttOptions, +} impl CachedBridge { - pub async fn set_on( - mqtt_client: AsyncClient, - friendly_name: &str, - ) -> Result<(), ClientError> { - CachedBridge::set(mqtt_client, friendly_name, r#"{"state": "ON"}"#) - .await + fn new() -> Self { + let options = + MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); + let (mqtt_client, eventloop) = AsyncClient::new(options.clone(), 128); + Self { + mqtt_client, + options, + eventloop, + } + } + + fn send_new_state(&mut self, needed_state: &State) { + todo!() + } + + pub async fn set_on(&self, friendly_name: &str) -> Result<(), ClientError> { + self.set(friendly_name, r#"{"state": "ON"}"#).await } /// Brightness: 0 to 1 /// Color temperature: 2200-4000K pub async fn set_bri_temp( - mqtt_client: AsyncClient, + &self, friendly_name: &str, brightness: f64, color_temp: usize, @@ -33,37 +51,35 @@ impl CachedBridge { }) .to_string(); - CachedBridge::set(mqtt_client, friendly_name, &payload).await + self.set(friendly_name, &payload).await } pub(crate) async fn set( - mqtt_client: AsyncClient, + &self, friendly_name: &str, payload: &str, ) -> Result<(), ClientError> { let topic = format!("zigbee2mqtt/{friendly_name}/set"); - mqtt_client.publish(topic, QOS, false, payload).await?; + self.mqtt_client.publish(topic, QOS, false, payload).await?; Ok(()) } pub(crate) async fn run( + mut self, mut change_receiver: mpsc::UnboundedReceiver, ) { - let options = - MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); // TODO: init through mqtt get let known_state = RwLock::new(State::new()); let mut needed_state = State::new(); + let options = self.options.clone(); + let mut self_pinned = pin!(self); loop { - let (mqtt_client, eventloop) = - AsyncClient::new(options.clone(), 128); - let poll_mqtt = poll_mqtt(eventloop, &known_state); + let poll_mqtt = self_pinned.as_mut().poll_mqtt(&known_state); - let handle_changes = handle_changes( + let handle_changes = self_pinned.as_mut().handle_changes( &mut change_receiver, - mqtt_client, &known_state, &mut needed_state, ); @@ -75,44 +91,43 @@ impl CachedBridge { println!( "Something went wrong with the mqtt connection, reconnecting" ); + let (mqtt_client, eventloop) = + AsyncClient::new(options.clone(), 128); + self.mqtt_client = mqtt_client; } } -} -async fn poll_mqtt( - mut eventloop: EventLoop, - known_state: &RwLock, -) -> Result<(), ConnectionError> { - loop { - let message = eventloop.poll().await?; - let new_known_state = extract_state_update(message); + async fn handle_changes( + mut self: Pin<&mut Self>, + change_receiver: &mut mpsc::UnboundedReceiver, + known_state: &RwLock, + needed_state: &mut State, + ) -> Result<(), ClientError> { + loop { + let change = change_receiver.recv().await; + *needed_state = needed_state.apply(change); + let known_state = known_state.read().await; - let mut known_state = known_state.write().await; - *known_state = new_known_state; + if *needed_state != *known_state { + self.send_new_state(needed_state); + } + } } -} -async fn handle_changes( - change_receiver: &mut mpsc::UnboundedReceiver, - mut mqtt_client: AsyncClient, - known_state: &RwLock, - needed_state: &mut State, -) -> Result<(), ClientError> { - loop { - let change = change_receiver.recv().await; - *needed_state = needed_state.apply(change); - let known_state = known_state.read().await; - - if *needed_state != *known_state { - send_new_state(&mut mqtt_client, needed_state); + async fn poll_mqtt( + mut self: Pin<&mut Self>, + known_state: &RwLock, + ) -> Result<(), ConnectionError> { + loop { + let message = self.eventloop.poll().await?; + let new_known_state = extract_state_update(message); + + let mut known_state = known_state.write().await; + *known_state = new_known_state; } } } -fn send_new_state(mqtt_client: &mut AsyncClient, needed_state: &State) { - todo!() -} - // Should return complete new state, otherwise change poll_mqtt fn extract_state_update(message: Event) -> State { todo!() diff --git a/crates/zigbee-bridge/src/lights/state.rs b/crates/zigbee-bridge/src/lights/state.rs index dba50de1..c04eaacf 100644 --- a/crates/zigbee-bridge/src/lights/state.rs +++ b/crates/zigbee-bridge/src/lights/state.rs @@ -1,3 +1,4 @@ +#![allow(unused)] #[derive(Debug, PartialEq)] pub(crate) struct State { pub(crate) brightness: f64, From 2e0c39bf4e25b53d1996afe44e341143f1571c18 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 27 Oct 2024 12:56:46 +0100 Subject: [PATCH 328/687] Revert "Attempt to put mqtt_client and eventloop into Self using Pin" This reverts commit eba44a5d7169eb58a9a380be2546c42b8685c28f. --- .../zigbee-bridge/src/lights/cached_bridge.rs | 111 ++++++++---------- crates/zigbee-bridge/src/lights/state.rs | 1 - 2 files changed, 48 insertions(+), 64 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 39be1b60..4e455f3b 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -1,45 +1,27 @@ -#![allow(unused)] -use std::pin::{pin, Pin}; - -use rumqttc::MqttOptions; use rumqttc::{AsyncClient, ClientError, EventLoop}; use rumqttc::{ConnectionError, Event}; +use rumqttc::MqttOptions; use serde_json::json; use tokio::sync::{mpsc, RwLock}; -use crate::lights::state::{Change, State}; use crate::{MQTT_IP, MQTT_PORT, QOS}; +use crate::lights::state::{Change, State}; -pub struct CachedBridge { - mqtt_client: AsyncClient, - eventloop: EventLoop, - options: MqttOptions, -} +pub struct CachedBridge {} impl CachedBridge { - fn new() -> Self { - let options = - MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); - let (mqtt_client, eventloop) = AsyncClient::new(options.clone(), 128); - Self { - mqtt_client, - options, - eventloop, - } - } - - fn send_new_state(&mut self, needed_state: &State) { - todo!() - } - - pub async fn set_on(&self, friendly_name: &str) -> Result<(), ClientError> { - self.set(friendly_name, r#"{"state": "ON"}"#).await + pub async fn set_on( + mqtt_client: AsyncClient, + friendly_name: &str, + ) -> Result<(), ClientError> { + CachedBridge::set(mqtt_client, friendly_name, r#"{"state": "ON"}"#) + .await } /// Brightness: 0 to 1 /// Color temperature: 2200-4000K pub async fn set_bri_temp( - &self, + mqtt_client: AsyncClient, friendly_name: &str, brightness: f64, color_temp: usize, @@ -51,35 +33,37 @@ impl CachedBridge { }) .to_string(); - self.set(friendly_name, &payload).await + CachedBridge::set(mqtt_client, friendly_name, &payload).await } pub(crate) async fn set( - &self, + mqtt_client: AsyncClient, friendly_name: &str, payload: &str, ) -> Result<(), ClientError> { let topic = format!("zigbee2mqtt/{friendly_name}/set"); - self.mqtt_client.publish(topic, QOS, false, payload).await?; + mqtt_client.publish(topic, QOS, false, payload).await?; Ok(()) } pub(crate) async fn run( - mut self, mut change_receiver: mpsc::UnboundedReceiver, ) { + let options = + MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); // TODO: init through mqtt get let known_state = RwLock::new(State::new()); let mut needed_state = State::new(); - let options = self.options.clone(); - let mut self_pinned = pin!(self); loop { - let poll_mqtt = self_pinned.as_mut().poll_mqtt(&known_state); + let (mqtt_client, eventloop) = + AsyncClient::new(options.clone(), 128); + let poll_mqtt = poll_mqtt(eventloop, &known_state); - let handle_changes = self_pinned.as_mut().handle_changes( + let handle_changes = handle_changes( &mut change_receiver, + mqtt_client, &known_state, &mut needed_state, ); @@ -91,43 +75,44 @@ impl CachedBridge { println!( "Something went wrong with the mqtt connection, reconnecting" ); - let (mqtt_client, eventloop) = - AsyncClient::new(options.clone(), 128); - self.mqtt_client = mqtt_client; } } +} - async fn handle_changes( - mut self: Pin<&mut Self>, - change_receiver: &mut mpsc::UnboundedReceiver, - known_state: &RwLock, - needed_state: &mut State, - ) -> Result<(), ClientError> { - loop { - let change = change_receiver.recv().await; - *needed_state = needed_state.apply(change); - let known_state = known_state.read().await; +async fn poll_mqtt( + mut eventloop: EventLoop, + known_state: &RwLock, +) -> Result<(), ConnectionError> { + loop { + let message = eventloop.poll().await?; + let new_known_state = extract_state_update(message); - if *needed_state != *known_state { - self.send_new_state(needed_state); - } - } + let mut known_state = known_state.write().await; + *known_state = new_known_state; } +} - async fn poll_mqtt( - mut self: Pin<&mut Self>, - known_state: &RwLock, - ) -> Result<(), ConnectionError> { - loop { - let message = self.eventloop.poll().await?; - let new_known_state = extract_state_update(message); - - let mut known_state = known_state.write().await; - *known_state = new_known_state; +async fn handle_changes( + change_receiver: &mut mpsc::UnboundedReceiver, + mut mqtt_client: AsyncClient, + known_state: &RwLock, + needed_state: &mut State, +) -> Result<(), ClientError> { + loop { + let change = change_receiver.recv().await; + *needed_state = needed_state.apply(change); + let known_state = known_state.read().await; + + if *needed_state != *known_state { + send_new_state(&mut mqtt_client, needed_state); } } } +fn send_new_state(mqtt_client: &mut AsyncClient, needed_state: &State) { + todo!() +} + // Should return complete new state, otherwise change poll_mqtt fn extract_state_update(message: Event) -> State { todo!() diff --git a/crates/zigbee-bridge/src/lights/state.rs b/crates/zigbee-bridge/src/lights/state.rs index c04eaacf..dba50de1 100644 --- a/crates/zigbee-bridge/src/lights/state.rs +++ b/crates/zigbee-bridge/src/lights/state.rs @@ -1,4 +1,3 @@ -#![allow(unused)] #[derive(Debug, PartialEq)] pub(crate) struct State { pub(crate) brightness: f64, From 39b0b64f46a4444787a4ebea5c5943a854613c65 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 27 Oct 2024 12:58:50 +0100 Subject: [PATCH 329/687] Remove struct CachedBridge --- crates/zigbee-bridge/src/lights.rs | 2 +- .../zigbee-bridge/src/lights/cached_bridge.rs | 119 ++++++++---------- 2 files changed, 55 insertions(+), 66 deletions(-) diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index 60cd8087..4468f6a5 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -12,7 +12,7 @@ impl Controller { pub fn start_bridge() -> Self { let (change_sender, change_receiver) = mpsc::unbounded_channel(); - let run_bridge = cached_bridge::CachedBridge::run(change_receiver); + let run_bridge = cached_bridge::run(change_receiver); tokio::task::spawn(run_bridge); Self { change_sender } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 4e455f3b..4aa5e537 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -1,81 +1,70 @@ +use rumqttc::MqttOptions; use rumqttc::{AsyncClient, ClientError, EventLoop}; use rumqttc::{ConnectionError, Event}; -use rumqttc::MqttOptions; use serde_json::json; use tokio::sync::{mpsc, RwLock}; -use crate::{MQTT_IP, MQTT_PORT, QOS}; use crate::lights::state::{Change, State}; +use crate::{MQTT_IP, MQTT_PORT, QOS}; -pub struct CachedBridge {} +pub async fn set_on( + mqtt_client: AsyncClient, + friendly_name: &str, +) -> Result<(), ClientError> { + set(mqtt_client, friendly_name, r#"{"state": "ON"}"#).await +} -impl CachedBridge { - pub async fn set_on( - mqtt_client: AsyncClient, - friendly_name: &str, - ) -> Result<(), ClientError> { - CachedBridge::set(mqtt_client, friendly_name, r#"{"state": "ON"}"#) - .await - } +/// Brightness: 0 to 1 +/// Color temperature: 2200-4000K +pub async fn set_bri_temp( + mqtt_client: AsyncClient, + friendly_name: &str, + brightness: f64, + color_temp: usize, +) -> Result<(), ClientError> { + let brightness = (brightness * 254.) as usize; + let payload = json!({ + "brightness": brightness, + "color_temp": kelvin_to_mired(color_temp) + }) + .to_string(); + + set(mqtt_client, friendly_name, &payload).await +} - /// Brightness: 0 to 1 - /// Color temperature: 2200-4000K - pub async fn set_bri_temp( - mqtt_client: AsyncClient, - friendly_name: &str, - brightness: f64, - color_temp: usize, - ) -> Result<(), ClientError> { - let brightness = (brightness * 254.) as usize; - let payload = json!({ - "brightness": brightness, - "color_temp": kelvin_to_mired(color_temp) - }) - .to_string(); - - CachedBridge::set(mqtt_client, friendly_name, &payload).await - } +pub(crate) async fn set( + mqtt_client: AsyncClient, + friendly_name: &str, + payload: &str, +) -> Result<(), ClientError> { + let topic = format!("zigbee2mqtt/{friendly_name}/set"); - pub(crate) async fn set( - mqtt_client: AsyncClient, - friendly_name: &str, - payload: &str, - ) -> Result<(), ClientError> { - let topic = format!("zigbee2mqtt/{friendly_name}/set"); + mqtt_client.publish(topic, QOS, false, payload).await?; + Ok(()) +} - mqtt_client.publish(topic, QOS, false, payload).await?; - Ok(()) - } +pub(crate) async fn run(mut change_receiver: mpsc::UnboundedReceiver) { + let options = MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); + // TODO: init through mqtt get + let known_state = RwLock::new(State::new()); + let mut needed_state = State::new(); - pub(crate) async fn run( - mut change_receiver: mpsc::UnboundedReceiver, - ) { - let options = - MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); - // TODO: init through mqtt get - let known_state = RwLock::new(State::new()); - let mut needed_state = State::new(); - - loop { - let (mqtt_client, eventloop) = - AsyncClient::new(options.clone(), 128); - let poll_mqtt = poll_mqtt(eventloop, &known_state); - - let handle_changes = handle_changes( - &mut change_receiver, - mqtt_client, - &known_state, - &mut needed_state, - ); - - tokio::select! { - _ = handle_changes => (), - _ = poll_mqtt => (), - } - println!( - "Something went wrong with the mqtt connection, reconnecting" - ); + loop { + let (mqtt_client, eventloop) = AsyncClient::new(options.clone(), 128); + let poll_mqtt = poll_mqtt(eventloop, &known_state); + + let handle_changes = handle_changes( + &mut change_receiver, + mqtt_client, + &known_state, + &mut needed_state, + ); + + tokio::select! { + _ = handle_changes => (), + _ = poll_mqtt => (), } + println!("Something went wrong with the mqtt connection, reconnecting"); } } From 9c4aff66f8a7057810062215943cdd7f6733cc6b Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 27 Oct 2024 13:01:06 +0100 Subject: [PATCH 330/687] Reorder fns and make things less pub --- crates/zigbee-bridge/src/lights.rs | 2 +- .../zigbee-bridge/src/lights/cached_bridge.rs | 84 +++++++++---------- crates/zigbee-bridge/src/lights/state.rs | 1 - 3 files changed, 43 insertions(+), 44 deletions(-) diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index 4468f6a5..3d8da84c 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -5,7 +5,7 @@ mod state; #[derive(Clone)] pub struct Controller { - pub(crate) change_sender: mpsc::UnboundedSender, + change_sender: mpsc::UnboundedSender, } impl Controller { diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 4aa5e537..eeb4f722 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -7,42 +7,6 @@ use tokio::sync::{mpsc, RwLock}; use crate::lights::state::{Change, State}; use crate::{MQTT_IP, MQTT_PORT, QOS}; -pub async fn set_on( - mqtt_client: AsyncClient, - friendly_name: &str, -) -> Result<(), ClientError> { - set(mqtt_client, friendly_name, r#"{"state": "ON"}"#).await -} - -/// Brightness: 0 to 1 -/// Color temperature: 2200-4000K -pub async fn set_bri_temp( - mqtt_client: AsyncClient, - friendly_name: &str, - brightness: f64, - color_temp: usize, -) -> Result<(), ClientError> { - let brightness = (brightness * 254.) as usize; - let payload = json!({ - "brightness": brightness, - "color_temp": kelvin_to_mired(color_temp) - }) - .to_string(); - - set(mqtt_client, friendly_name, &payload).await -} - -pub(crate) async fn set( - mqtt_client: AsyncClient, - friendly_name: &str, - payload: &str, -) -> Result<(), ClientError> { - let topic = format!("zigbee2mqtt/{friendly_name}/set"); - - mqtt_client.publish(topic, QOS, false, payload).await?; - Ok(()) -} - pub(crate) async fn run(mut change_receiver: mpsc::UnboundedReceiver) { let options = MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); // TODO: init through mqtt get @@ -51,8 +15,8 @@ pub(crate) async fn run(mut change_receiver: mpsc::UnboundedReceiver) { loop { let (mqtt_client, eventloop) = AsyncClient::new(options.clone(), 128); - let poll_mqtt = poll_mqtt(eventloop, &known_state); + let poll_mqtt = poll_mqtt(eventloop, &known_state); let handle_changes = handle_changes( &mut change_receiver, mqtt_client, @@ -98,19 +62,55 @@ async fn handle_changes( } } -fn send_new_state(mqtt_client: &mut AsyncClient, needed_state: &State) { +// Should return complete new state, otherwise change poll_mqtt +fn extract_state_update(message: Event) -> State { todo!() } -// Should return complete new state, otherwise change poll_mqtt -fn extract_state_update(message: Event) -> State { +fn send_new_state(mqtt_client: &mut AsyncClient, needed_state: &State) { todo!() } -pub(crate) fn mired_to_kelvin(mired: usize) -> usize { +async fn set_on( + mqtt_client: AsyncClient, + friendly_name: &str, +) -> Result<(), ClientError> { + set(mqtt_client, friendly_name, r#"{"state": "ON"}"#).await +} + +/// Brightness: 0 to 1 +/// Color temperature: 2200-4000K +async fn set_bri_temp( + mqtt_client: AsyncClient, + friendly_name: &str, + brightness: f64, + color_temp: usize, +) -> Result<(), ClientError> { + let brightness = (brightness * 254.) as usize; + let payload = json!({ + "brightness": brightness, + "color_temp": kelvin_to_mired(color_temp) + }) + .to_string(); + + set(mqtt_client, friendly_name, &payload).await +} + +async fn set( + mqtt_client: AsyncClient, + friendly_name: &str, + payload: &str, +) -> Result<(), ClientError> { + let topic = format!("zigbee2mqtt/{friendly_name}/set"); + + mqtt_client.publish(topic, QOS, false, payload).await?; + Ok(()) +} + +fn mired_to_kelvin(mired: usize) -> usize { 1_000_000 / mired } -pub(crate) fn kelvin_to_mired(kelvin: usize) -> usize { +fn kelvin_to_mired(kelvin: usize) -> usize { 1_000_000 / kelvin } diff --git a/crates/zigbee-bridge/src/lights/state.rs b/crates/zigbee-bridge/src/lights/state.rs index dba50de1..5338665b 100644 --- a/crates/zigbee-bridge/src/lights/state.rs +++ b/crates/zigbee-bridge/src/lights/state.rs @@ -29,4 +29,3 @@ pub(crate) struct Change { pub(crate) color_temp: Option, pub(crate) color_xy: Option<(f64, f64)>, } - From 5d9a875e49beace3d12061c2931a427087b625b3 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 27 Oct 2024 18:02:48 +0100 Subject: [PATCH 331/687] Extract struct Mqtt for fns that use the client --- .../zigbee-bridge/src/lights/cached_bridge.rs | 92 ++++++++++--------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index eeb4f722..6ffbbccb 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -7,6 +7,49 @@ use tokio::sync::{mpsc, RwLock}; use crate::lights::state::{Change, State}; use crate::{MQTT_IP, MQTT_PORT, QOS}; +struct Mqtt { + client: AsyncClient, +} + +impl Mqtt { + fn send_new_state(&self, needed_state: &State) { + todo!() + } + + async fn set_on(&self, friendly_name: &str) -> Result<(), ClientError> { + self.set(friendly_name, r#"{"state": "ON"}"#).await + } + + /// Brightness: 0 to 1 + /// Color temperature: 2200-4000K + async fn set_bri_temp( + &self, + friendly_name: &str, + brightness: f64, + color_temp: usize, + ) -> Result<(), ClientError> { + let brightness = (brightness * 254.) as usize; + let payload = json!({ + "brightness": brightness, + "color_temp": kelvin_to_mired(color_temp) + }) + .to_string(); + + self.set(friendly_name, &payload).await + } + + async fn set( + &self, + friendly_name: &str, + payload: &str, + ) -> Result<(), ClientError> { + let topic = format!("zigbee2mqtt/{friendly_name}/set"); + + self.client.publish(topic, QOS, false, payload).await?; + Ok(()) + } +} + pub(crate) async fn run(mut change_receiver: mpsc::UnboundedReceiver) { let options = MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); // TODO: init through mqtt get @@ -14,12 +57,13 @@ pub(crate) async fn run(mut change_receiver: mpsc::UnboundedReceiver) { let mut needed_state = State::new(); loop { - let (mqtt_client, eventloop) = AsyncClient::new(options.clone(), 128); + let (client, eventloop) = AsyncClient::new(options.clone(), 128); + let mqtt = Mqtt { client }; let poll_mqtt = poll_mqtt(eventloop, &known_state); let handle_changes = handle_changes( &mut change_receiver, - mqtt_client, + &mqtt, &known_state, &mut needed_state, ); @@ -47,7 +91,7 @@ async fn poll_mqtt( async fn handle_changes( change_receiver: &mut mpsc::UnboundedReceiver, - mut mqtt_client: AsyncClient, + mqtt: &Mqtt, known_state: &RwLock, needed_state: &mut State, ) -> Result<(), ClientError> { @@ -57,7 +101,7 @@ async fn handle_changes( let known_state = known_state.read().await; if *needed_state != *known_state { - send_new_state(&mut mqtt_client, needed_state); + mqtt.send_new_state(needed_state); } } } @@ -67,46 +111,6 @@ fn extract_state_update(message: Event) -> State { todo!() } -fn send_new_state(mqtt_client: &mut AsyncClient, needed_state: &State) { - todo!() -} - -async fn set_on( - mqtt_client: AsyncClient, - friendly_name: &str, -) -> Result<(), ClientError> { - set(mqtt_client, friendly_name, r#"{"state": "ON"}"#).await -} - -/// Brightness: 0 to 1 -/// Color temperature: 2200-4000K -async fn set_bri_temp( - mqtt_client: AsyncClient, - friendly_name: &str, - brightness: f64, - color_temp: usize, -) -> Result<(), ClientError> { - let brightness = (brightness * 254.) as usize; - let payload = json!({ - "brightness": brightness, - "color_temp": kelvin_to_mired(color_temp) - }) - .to_string(); - - set(mqtt_client, friendly_name, &payload).await -} - -async fn set( - mqtt_client: AsyncClient, - friendly_name: &str, - payload: &str, -) -> Result<(), ClientError> { - let topic = format!("zigbee2mqtt/{friendly_name}/set"); - - mqtt_client.publish(topic, QOS, false, payload).await?; - Ok(()) -} - fn mired_to_kelvin(mired: usize) -> usize { 1_000_000 / mired } From 37093a130abc4a5fe258beecc610021286628c4f Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 29 Oct 2024 14:01:26 +0100 Subject: [PATCH 332/687] Add logic for states, states for multiple lights --- crates/zigbee-bridge/src/lib.rs | 2 + crates/zigbee-bridge/src/lights.rs | 4 +- .../zigbee-bridge/src/lights/cached_bridge.rs | 106 ++++++++++++------ .../src/lights/cached_bridge/conversion.rs | 12 ++ crates/zigbee-bridge/src/lights/conversion.rs | 12 ++ crates/zigbee-bridge/src/lights/state.rs | 23 ++-- 6 files changed, 118 insertions(+), 41 deletions(-) create mode 100644 crates/zigbee-bridge/src/lights/cached_bridge/conversion.rs create mode 100644 crates/zigbee-bridge/src/lights/conversion.rs diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 62d0c569..e887b661 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -16,3 +16,5 @@ mod lights; const QOS: QoS = QoS::AtLeastOnce; const MQTT_IP: &str = "192.168.1.43"; const MQTT_PORT: u16 = 1883; +// TODO: get from bridge +const LIGHTS: [&str; 2] = ["keuken tafellamp", "gangkast tafellamp"]; diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index 3d8da84c..0778e2ab 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -1,11 +1,13 @@ +#![allow(unused)] use tokio::sync::mpsc; mod cached_bridge; +mod conversion; mod state; #[derive(Clone)] pub struct Controller { - change_sender: mpsc::UnboundedSender, + change_sender: mpsc::UnboundedSender<(String, state::Change)>, } impl Controller { diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 6ffbbccb..da739533 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -1,18 +1,22 @@ +#![allow(unused)] +use std::collections::HashMap; + use rumqttc::MqttOptions; use rumqttc::{AsyncClient, ClientError, EventLoop}; use rumqttc::{ConnectionError, Event}; use serde_json::json; use tokio::sync::{mpsc, RwLock}; +use crate::lights::conversion::kelvin_to_mired; use crate::lights::state::{Change, State}; -use crate::{MQTT_IP, MQTT_PORT, QOS}; +use crate::{LIGHTS, MQTT_IP, MQTT_PORT, QOS}; struct Mqtt { client: AsyncClient, } impl Mqtt { - fn send_new_state(&self, needed_state: &State) { + fn send_new_state(&self, light_name: &str, needed_state: &State) { todo!() } @@ -45,27 +49,60 @@ impl Mqtt { ) -> Result<(), ClientError> { let topic = format!("zigbee2mqtt/{friendly_name}/set"); - self.client.publish(topic, QOS, false, payload).await?; + self.publish(&topic, payload).await?; Ok(()) } + + async fn get( + &self, + friendly_name: &str, + payload: &str, + ) -> Result<(), ClientError> { + let topic = format!("zigbee2mqtt/{friendly_name}/get"); + + self.publish(&topic, payload).await?; + Ok(()) + } + + async fn publish( + &self, + topic: &str, + payload: &str, + ) -> Result<(), ClientError> { + self.client.publish(topic, QOS, false, payload).await + } + + fn request_state(&self, name: &str) { + let payload = json!({ + "state": "", + "brightness": "", + "color_temp": "", + "color_xy": "", + }) + .to_string(); + self.get(name, &payload); + } } -pub(crate) async fn run(mut change_receiver: mpsc::UnboundedReceiver) { +pub(crate) async fn run( + mut change_receiver: mpsc::UnboundedReceiver<(String, Change)>, +) { let options = MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); // TODO: init through mqtt get - let known_state = RwLock::new(State::new()); - let mut needed_state = State::new(); + let known_states = RwLock::new(HashMap::new()); + let mut needed_states = HashMap::new(); loop { let (client, eventloop) = AsyncClient::new(options.clone(), 128); let mqtt = Mqtt { client }; + LIGHTS.into_iter().map(|name| mqtt.request_state(name)); - let poll_mqtt = poll_mqtt(eventloop, &known_state); + let poll_mqtt = poll_mqtt(eventloop, &known_states); let handle_changes = handle_changes( &mut change_receiver, &mqtt, - &known_state, - &mut needed_state, + &known_states, + &mut needed_states, ); tokio::select! { @@ -78,43 +115,48 @@ pub(crate) async fn run(mut change_receiver: mpsc::UnboundedReceiver) { async fn poll_mqtt( mut eventloop: EventLoop, - known_state: &RwLock, + known_states: &RwLock>, ) -> Result<(), ConnectionError> { loop { let message = eventloop.poll().await?; - let new_known_state = extract_state_update(message); - - let mut known_state = known_state.write().await; - *known_state = new_known_state; + if let Some((light_name, new_known_state)) = + extract_state_update(message) + { + let mut known_states = known_states.write().await; + known_states.insert(light_name, new_known_state); + } } } async fn handle_changes( - change_receiver: &mut mpsc::UnboundedReceiver, + change_receiver: &mut mpsc::UnboundedReceiver<(String, Change)>, mqtt: &Mqtt, - known_state: &RwLock, - needed_state: &mut State, + known_states: &RwLock>, + needed_states: &mut HashMap, ) -> Result<(), ClientError> { loop { - let change = change_receiver.recv().await; - *needed_state = needed_state.apply(change); - let known_state = known_state.read().await; - - if *needed_state != *known_state { - mqtt.send_new_state(needed_state); + // TODO: add timeout + let (light_name, change) = change_receiver + .recv() + .await + .expect("Channel should never close"); + let known_states = known_states.read().await; + + let previous_needed_state = match known_states.get(&light_name) { + Some(known_state) => needed_states + .entry(light_name.clone()) + .or_insert(known_state.clone()), + None => &mut State::default(), + }; + let new_needed_state = previous_needed_state.apply(change); + + if Some(&new_needed_state) != known_states.get(&light_name) { + mqtt.send_new_state(&light_name, &new_needed_state); } } } // Should return complete new state, otherwise change poll_mqtt -fn extract_state_update(message: Event) -> State { +fn extract_state_update(message: Event) -> Option<(String, State)> { todo!() } - -fn mired_to_kelvin(mired: usize) -> usize { - 1_000_000 / mired -} - -fn kelvin_to_mired(kelvin: usize) -> usize { - 1_000_000 / kelvin -} diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/conversion.rs b/crates/zigbee-bridge/src/lights/cached_bridge/conversion.rs new file mode 100644 index 00000000..46ed88df --- /dev/null +++ b/crates/zigbee-bridge/src/lights/cached_bridge/conversion.rs @@ -0,0 +1,12 @@ +pub(crate) fn mired_to_kelvin(mired: usize) -> usize { + 1_000_000 / mired +} + +pub(crate) fn kelvin_to_mired(kelvin: usize) -> usize { + 1_000_000 / kelvin +} + +pub(crate) fn temp_to_xy(color_temp: usize) -> (f64, f64) { + todo!() +} + diff --git a/crates/zigbee-bridge/src/lights/conversion.rs b/crates/zigbee-bridge/src/lights/conversion.rs new file mode 100644 index 00000000..46ed88df --- /dev/null +++ b/crates/zigbee-bridge/src/lights/conversion.rs @@ -0,0 +1,12 @@ +pub(crate) fn mired_to_kelvin(mired: usize) -> usize { + 1_000_000 / mired +} + +pub(crate) fn kelvin_to_mired(kelvin: usize) -> usize { + 1_000_000 / kelvin +} + +pub(crate) fn temp_to_xy(color_temp: usize) -> (f64, f64) { + todo!() +} + diff --git a/crates/zigbee-bridge/src/lights/state.rs b/crates/zigbee-bridge/src/lights/state.rs index 5338665b..e4e3b70b 100644 --- a/crates/zigbee-bridge/src/lights/state.rs +++ b/crates/zigbee-bridge/src/lights/state.rs @@ -1,4 +1,8 @@ -#[derive(Debug, PartialEq)] +#![allow(unused)] + +use crate::lights::conversion::temp_to_xy; + +#[derive(Debug, PartialEq, Clone)] pub(crate) struct State { pub(crate) brightness: f64, pub(crate) color_temp: usize, @@ -6,22 +10,25 @@ pub(crate) struct State { pub(crate) on: bool, } -impl State { - pub(crate) fn new() -> Self { +impl Default for State { + fn default() -> Self { Self { - on: todo!(), - brightness: todo!(), - color_temp: todo!(), - color_xy: todo!(), + brightness: 1.0, + color_temp: 2700, + color_xy: temp_to_xy(2700), + on: false, } } +} - pub(crate) fn apply(&mut self, change: Option) -> State { +impl State { + pub(crate) fn apply(&mut self, change: Change) -> State { todo!() } } #[derive(Debug)] +// TODO: make enum pub(crate) struct Change { pub(crate) friendly_name: String, pub(crate) on: Option, From bacee0d4859ec5efd8e604f5a8e8b577f56dcf8c Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 29 Oct 2024 14:12:20 +0100 Subject: [PATCH 333/687] Add unautomated integration test and debug prints --- crates/zigbee-bridge/src/lib.rs | 12 ++++++++++++ crates/zigbee-bridge/src/lights.rs | 4 ++-- crates/zigbee-bridge/src/lights/cached_bridge.rs | 3 +++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index e887b661..8b114e30 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -18,3 +18,15 @@ const MQTT_IP: &str = "192.168.1.43"; const MQTT_PORT: u16 = 1883; // TODO: get from bridge const LIGHTS: [&str; 2] = ["keuken tafellamp", "gangkast tafellamp"]; + +#[cfg(test)] +mod tests { + use super::Controller; + + #[tokio::test] + async fn start_bridge() { + let _controller = Controller::start_bridge(); + + loop {} + } +} diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index 0778e2ab..1d1a4492 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -11,11 +11,11 @@ pub struct Controller { } impl Controller { - pub fn start_bridge() -> Self { + pub async fn start_bridge() -> Self { let (change_sender, change_receiver) = mpsc::unbounded_channel(); let run_bridge = cached_bridge::run(change_receiver); - tokio::task::spawn(run_bridge); + let _task = tokio::task::spawn(run_bridge); Self { change_sender } } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index da739533..6828b80a 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -73,6 +73,7 @@ impl Mqtt { } fn request_state(&self, name: &str) { + println!("Requesting state for light {name}"); let payload = json!({ "state": "", "brightness": "", @@ -87,6 +88,7 @@ impl Mqtt { pub(crate) async fn run( mut change_receiver: mpsc::UnboundedReceiver<(String, Change)>, ) { + println!("Running bridge"); let options = MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); // TODO: init through mqtt get let known_states = RwLock::new(HashMap::new()); @@ -119,6 +121,7 @@ async fn poll_mqtt( ) -> Result<(), ConnectionError> { loop { let message = eventloop.poll().await?; + dbg!(&message); if let Some((light_name, new_known_state)) = extract_state_update(message) { From f98683eabf460b453abf23e108c6bcfb3de78920 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 31 Oct 2024 11:39:53 +0100 Subject: [PATCH 334/687] Parse state messages into known states and fix test --- crates/zigbee-bridge/src/lib.rs | 5 +- crates/zigbee-bridge/src/lights.rs | 2 +- .../zigbee-bridge/src/lights/cached_bridge.rs | 97 ++++++++++++------- crates/zigbee-bridge/src/lights/state.rs | 81 +++++++++++++++- 4 files changed, 146 insertions(+), 39 deletions(-) diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 8b114e30..e997c99a 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -25,8 +25,9 @@ mod tests { #[tokio::test] async fn start_bridge() { - let _controller = Controller::start_bridge(); + let _controller = Controller::start_bridge().await; - loop {} + let () = std::future::pending().await; + unreachable!(); } } diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index 1d1a4492..c4d9a587 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -15,7 +15,7 @@ impl Controller { let (change_sender, change_receiver) = mpsc::unbounded_channel(); let run_bridge = cached_bridge::run(change_receiver); - let _task = tokio::task::spawn(run_bridge); + tokio::task::spawn(run_bridge); Self { change_sender } } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 6828b80a..2193e0f3 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -1,9 +1,9 @@ #![allow(unused)] use std::collections::HashMap; -use rumqttc::MqttOptions; use rumqttc::{AsyncClient, ClientError, EventLoop}; use rumqttc::{ConnectionError, Event}; +use rumqttc::{Incoming, MqttOptions}; use serde_json::json; use tokio::sync::{mpsc, RwLock}; @@ -72,47 +72,59 @@ impl Mqtt { self.client.publish(topic, QOS, false, payload).await } - fn request_state(&self, name: &str) { + async fn request_state(&self, name: &str) { println!("Requesting state for light {name}"); - let payload = json!({ - "state": "", - "brightness": "", - "color_temp": "", - "color_xy": "", - }) - .to_string(); - self.get(name, &payload); + let payload = json!({"state": ""}); + + self.get(name, &payload.to_string()).await; + } + + async fn subscribe(&self, topic: &str) -> Result<(), ClientError> { + self.client.subscribe(topic, QOS).await } } pub(crate) async fn run( mut change_receiver: mpsc::UnboundedReceiver<(String, Change)>, ) { - println!("Running bridge"); - let options = MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); - // TODO: init through mqtt get + let mut options = + MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); + // Set incoming to max mqtt packet size, outgoing to rumqtt default + options.set_max_packet_size(2_usize.pow(28), 10240); + let known_states = RwLock::new(HashMap::new()); let mut needed_states = HashMap::new(); - loop { - let (client, eventloop) = AsyncClient::new(options.clone(), 128); - let mqtt = Mqtt { client }; - LIGHTS.into_iter().map(|name| mqtt.request_state(name)); - - let poll_mqtt = poll_mqtt(eventloop, &known_states); - let handle_changes = handle_changes( - &mut change_receiver, - &mqtt, - &known_states, - &mut needed_states, - ); - - tokio::select! { - _ = handle_changes => (), - _ = poll_mqtt => (), - } - println!("Something went wrong with the mqtt connection, reconnecting"); + // Reconnecting to broker is handled by Eventloop::poll + let (client, eventloop) = AsyncClient::new(options.clone(), 128); + let mqtt = Mqtt { client }; + + for light in LIGHTS { + mqtt.subscribe(&format!("zigbee2mqtt/{light}")) + .await + .unwrap(); + mqtt.request_state(light).await; } + + let poll_mqtt = poll_mqtt(eventloop, &known_states); + let handle_changes = handle_changes( + &mut change_receiver, + &mqtt, + &known_states, + &mut needed_states, + ); + + let err = tokio::select! { + err = handle_changes => Error::Changes(err.unwrap_err()), + err = poll_mqtt => Error::Poll(err.unwrap_err()), + }; + println!("Something went wrong with the mqtt connection: {err:?}"); +} + +#[derive(Debug)] +enum Error { + Changes(ClientError), + Poll(ConnectionError), } async fn poll_mqtt( @@ -121,12 +133,12 @@ async fn poll_mqtt( ) -> Result<(), ConnectionError> { loop { let message = eventloop.poll().await?; - dbg!(&message); if let Some((light_name, new_known_state)) = extract_state_update(message) { let mut known_states = known_states.write().await; known_states.insert(light_name, new_known_state); + dbg!(known_states); } } } @@ -161,5 +173,24 @@ async fn handle_changes( // Should return complete new state, otherwise change poll_mqtt fn extract_state_update(message: Event) -> Option<(String, State)> { - todo!() + match message { + Event::Incoming(incoming) => match incoming { + Incoming::ConnAck(_) + | Incoming::PubAck(_) + | Incoming::PingResp + | Incoming::SubAck(_) => None, + Incoming::Publish(message) => { + let topic: Vec<_> = message.topic.split('/').collect(); + let name = topic[1].to_string(); + let data = &(*message.payload); + + Some((name, data.try_into().unwrap())) + } + other => { + dbg!(other); + None + } + }, + _ => None, + } } diff --git a/crates/zigbee-bridge/src/lights/state.rs b/crates/zigbee-bridge/src/lights/state.rs index e4e3b70b..59064686 100644 --- a/crates/zigbee-bridge/src/lights/state.rs +++ b/crates/zigbee-bridge/src/lights/state.rs @@ -1,11 +1,15 @@ #![allow(unused)] -use crate::lights::conversion::temp_to_xy; +use std::io; + +use serde_json::Value; + +use crate::lights::conversion::{mired_to_kelvin, temp_to_xy}; #[derive(Debug, PartialEq, Clone)] pub(crate) struct State { pub(crate) brightness: f64, - pub(crate) color_temp: usize, + pub(crate) color_temp_kelvin: usize, pub(crate) color_xy: (f64, f64), pub(crate) on: bool, } @@ -14,13 +18,84 @@ impl Default for State { fn default() -> Self { Self { brightness: 1.0, - color_temp: 2700, + color_temp_kelvin: 2700, color_xy: temp_to_xy(2700), on: false, } } } +impl TryInto for &[u8] { + type Error = io::Error; + + fn try_into(self) -> Result { + fn get_key<'a>( + map: &'a serde_json::Map, + key: &str, + ) -> Result<&'a Value, io::Error> { + let key_err = io::Error::new( + io::ErrorKind::InvalidData, + "Missing key from map: {key}", + ); + map.get(key).ok_or(key_err) + } + + fn invalid_err(value_type: &str) -> io::Error { + io::Error::new( + io::ErrorKind::InvalidData, + format!("Could not parse json into {value_type}"), + ) + } + + let json: Value = serde_json::from_slice(&self)?; + let map = json.as_object().ok_or(invalid_err("Object"))?; + + let color = get_key(map, "color")? + .as_object() + .ok_or(invalid_err("Object"))?; + let color_x = get_key(color, "x")? + .as_number() + .ok_or(invalid_err("Number"))? + .as_f64() + .expect("Should return Some if not using arbitrary precision"); + let color_y = get_key(color, "y")? + .as_number() + .ok_or(invalid_err("Number"))? + .as_f64() + .expect("Should return Some if not using arbitrary precision"); + + let brightness = get_key(map, "brightness")? + .as_number() + .ok_or(invalid_err("Number"))? + .as_u64() + .ok_or(invalid_err("u64"))?; + + let color_temp_mired = get_key(map, "color_temp")? + .as_number() + .ok_or(invalid_err("Number"))? + .as_u64() + .ok_or(invalid_err("u64"))? + .try_into() + .expect("usize should be u64"); + + let state = get_key(map, "state")? + .as_str() + .ok_or(invalid_err("String"))?; + let on = match state.to_lowercase().as_str() { + "on" => true, + "off" => false, + other => return Err(invalid_err("on/off bool")), + }; + + Ok(State { + brightness: brightness as f64 / 254., + color_temp_kelvin: mired_to_kelvin(color_temp_mired), + color_xy: (color_x, color_y), + on, + }) + } +} + impl State { pub(crate) fn apply(&mut self, change: Change) -> State { todo!() From b3357697e6c8f3634cab7453ac627debc58989d6 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 31 Oct 2024 12:07:02 +0100 Subject: [PATCH 335/687] Change error handling to reflect infallibility --- .../zigbee-bridge/src/lights/cached_bridge.rs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 2193e0f3..2152bc38 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -114,17 +114,11 @@ pub(crate) async fn run( &mut needed_states, ); - let err = tokio::select! { - err = handle_changes => Error::Changes(err.unwrap_err()), - err = poll_mqtt => Error::Poll(err.unwrap_err()), + tokio::select! { + _ = handle_changes => (), + err = poll_mqtt => + println!("Something went wrong with the mqtt connection: {err:?}"), }; - println!("Something went wrong with the mqtt connection: {err:?}"); -} - -#[derive(Debug)] -enum Error { - Changes(ClientError), - Poll(ConnectionError), } async fn poll_mqtt( @@ -132,7 +126,14 @@ async fn poll_mqtt( known_states: &RwLock>, ) -> Result<(), ConnectionError> { loop { - let message = eventloop.poll().await?; + let message = match eventloop.poll().await { + Ok(message) => message, + Err(err) => { + println!("Error while polling: {err}"); + continue; + } + }; + if let Some((light_name, new_known_state)) = extract_state_update(message) { @@ -148,7 +149,7 @@ async fn handle_changes( mqtt: &Mqtt, known_states: &RwLock>, needed_states: &mut HashMap, -) -> Result<(), ClientError> { +) -> ! { loop { // TODO: add timeout let (light_name, change) = change_receiver @@ -171,7 +172,6 @@ async fn handle_changes( } } -// Should return complete new state, otherwise change poll_mqtt fn extract_state_update(message: Event) -> Option<(String, State)> { match message { Event::Incoming(incoming) => match incoming { From 3348fced334392cfc6a2c74808b042b67dc4b4a3 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 31 Oct 2024 13:19:32 +0100 Subject: [PATCH 336/687] Implement changing light state --- crates/zigbee-bridge/src/lib.rs | 4 +- crates/zigbee-bridge/src/lights.rs | 33 +++++++++++- .../zigbee-bridge/src/lights/cached_bridge.rs | 41 +++++---------- crates/zigbee-bridge/src/lights/conversion.rs | 2 +- crates/zigbee-bridge/src/lights/state.rs | 51 ++++++++++++++----- 5 files changed, 87 insertions(+), 44 deletions(-) diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index e997c99a..042e05ea 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -25,7 +25,9 @@ mod tests { #[tokio::test] async fn start_bridge() { - let _controller = Controller::start_bridge().await; + let controller = Controller::start_bridge().await; + + controller.set_brightness("gangkast tafellamp", 1.0); let () = std::future::pending().await; unreachable!(); diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index c4d9a587..2250d42a 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -1,6 +1,7 @@ -#![allow(unused)] use tokio::sync::mpsc; +use self::state::Change; + mod cached_bridge; mod conversion; mod state; @@ -19,4 +20,34 @@ impl Controller { Self { change_sender } } + + pub fn set_on(&self, friendly_name: &str) { + self.change_sender + .send((friendly_name.to_string(), Change::On(true))) + .expect("Sender should never be dropped"); + } + + pub fn set_off(&self, friendly_name: &str) { + self.change_sender + .send((friendly_name.to_string(), Change::On(false))) + .expect("Sender should never be dropped"); + } + + pub fn set_brightness(&self, friendly_name: &str, brightness: f64) { + self.change_sender + .send((friendly_name.to_string(), Change::Brightness(brightness))) + .expect("Sender should never be dropped"); + } + + pub fn set_color_temp(&self, friendly_name: &str, kelvin: usize) { + self.change_sender + .send((friendly_name.to_string(), Change::ColorTemp(kelvin))) + .expect("Sender should never be dropped"); + } + + pub fn set_color_xy(&self, friendly_name: &str, xy: (f64, f64)) { + self.change_sender + .send((friendly_name.to_string(), Change::ColorXy(xy))) + .expect("Sender should never be dropped"); + } } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 2152bc38..9b721d97 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -1,5 +1,5 @@ -#![allow(unused)] use std::collections::HashMap; +use std::time::Duration; use rumqttc::{AsyncClient, ClientError, EventLoop}; use rumqttc::{ConnectionError, Event}; @@ -7,7 +7,6 @@ use rumqttc::{Incoming, MqttOptions}; use serde_json::json; use tokio::sync::{mpsc, RwLock}; -use crate::lights::conversion::kelvin_to_mired; use crate::lights::state::{Change, State}; use crate::{LIGHTS, MQTT_IP, MQTT_PORT, QOS}; @@ -16,30 +15,15 @@ struct Mqtt { } impl Mqtt { - fn send_new_state(&self, light_name: &str, needed_state: &State) { - todo!() - } - - async fn set_on(&self, friendly_name: &str) -> Result<(), ClientError> { - self.set(friendly_name, r#"{"state": "ON"}"#).await - } - - /// Brightness: 0 to 1 - /// Color temperature: 2200-4000K - async fn set_bri_temp( + async fn send_new_state( &self, - friendly_name: &str, - brightness: f64, - color_temp: usize, + light_name: &str, + needed_state: &State, ) -> Result<(), ClientError> { - let brightness = (brightness * 254.) as usize; - let payload = json!({ - "brightness": brightness, - "color_temp": kelvin_to_mired(color_temp) - }) - .to_string(); - - self.set(friendly_name, &payload).await + for payload in needed_state.to_payloads() { + self.set(light_name, &payload).await?; + } + Ok(()) } async fn set( @@ -76,7 +60,7 @@ impl Mqtt { println!("Requesting state for light {name}"); let payload = json!({"state": ""}); - self.get(name, &payload.to_string()).await; + self.get(name, &payload.to_string()).await.unwrap(); } async fn subscribe(&self, topic: &str) -> Result<(), ClientError> { @@ -139,7 +123,6 @@ async fn poll_mqtt( { let mut known_states = known_states.write().await; known_states.insert(light_name, new_known_state); - dbg!(known_states); } } } @@ -150,6 +133,8 @@ async fn handle_changes( known_states: &RwLock>, needed_states: &mut HashMap, ) -> ! { + // Give the initial known states a chance to be fetched + tokio::time::sleep(Duration::from_millis(500)).await; loop { // TODO: add timeout let (light_name, change) = change_receiver @@ -158,6 +143,7 @@ async fn handle_changes( .expect("Channel should never close"); let known_states = known_states.read().await; + dbg!(&known_states); let previous_needed_state = match known_states.get(&light_name) { Some(known_state) => needed_states .entry(light_name.clone()) @@ -167,7 +153,8 @@ async fn handle_changes( let new_needed_state = previous_needed_state.apply(change); if Some(&new_needed_state) != known_states.get(&light_name) { - mqtt.send_new_state(&light_name, &new_needed_state); + // Ignore errors because we will retry if the state hasn't changed + let _ = mqtt.send_new_state(&light_name, &new_needed_state).await; } } } diff --git a/crates/zigbee-bridge/src/lights/conversion.rs b/crates/zigbee-bridge/src/lights/conversion.rs index 46ed88df..bdd98028 100644 --- a/crates/zigbee-bridge/src/lights/conversion.rs +++ b/crates/zigbee-bridge/src/lights/conversion.rs @@ -7,6 +7,6 @@ pub(crate) fn kelvin_to_mired(kelvin: usize) -> usize { } pub(crate) fn temp_to_xy(color_temp: usize) -> (f64, f64) { - todo!() + (1.0, 1.0) } diff --git a/crates/zigbee-bridge/src/lights/state.rs b/crates/zigbee-bridge/src/lights/state.rs index 59064686..6d016e03 100644 --- a/crates/zigbee-bridge/src/lights/state.rs +++ b/crates/zigbee-bridge/src/lights/state.rs @@ -1,10 +1,8 @@ -#![allow(unused)] - use std::io; -use serde_json::Value; +use serde_json::{json, Value}; -use crate::lights::conversion::{mired_to_kelvin, temp_to_xy}; +use crate::lights::conversion::{kelvin_to_mired, mired_to_kelvin, temp_to_xy}; #[derive(Debug, PartialEq, Clone)] pub(crate) struct State { @@ -84,7 +82,7 @@ impl TryInto for &[u8] { let on = match state.to_lowercase().as_str() { "on" => true, "off" => false, - other => return Err(invalid_err("on/off bool")), + other => return Err(invalid_err(&format!("on/off bool: {other}"))), }; Ok(State { @@ -97,17 +95,42 @@ impl TryInto for &[u8] { } impl State { - pub(crate) fn apply(&mut self, change: Change) -> State { - todo!() + pub(crate) fn apply(&self, change: Change) -> State { + let mut new_state = self.clone(); + match change { + Change::On(on) => new_state.on = on, + Change::Brightness(bri) => new_state.brightness = bri, + Change::ColorTemp(temp) => new_state.color_temp_kelvin = temp, + Change::ColorXy(xy) => new_state.color_xy = xy, + } + new_state + } + + pub(crate) fn to_payloads(&self) -> Vec { + let state = match self.on { + true => "ON", + false => "OFF", + }; + let brightness: usize = (self.brightness * 254.).round() as usize; + let color_temp_mired = kelvin_to_mired(self.color_temp_kelvin); + + [ + json!({ "state": state }), + json!({ "brightness": brightness }), + json!({ "color_temp": color_temp_mired }), + // TODO: make sure this doesn't override temp / always use this + // json!({ "color_xy": self.color_xy }), + ] + .into_iter() + .map(|x| x.to_string()) + .collect() } } #[derive(Debug)] -// TODO: make enum -pub(crate) struct Change { - pub(crate) friendly_name: String, - pub(crate) on: Option, - pub(crate) brightness: Option, - pub(crate) color_temp: Option, - pub(crate) color_xy: Option<(f64, f64)>, +pub(crate) enum Change { + On(bool), + Brightness(f64), + ColorTemp(usize), + ColorXy((f64, f64)), } From 83cd534cb420a1801f5f96493834172c9515cc9a Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 1 Nov 2024 11:42:08 +0100 Subject: [PATCH 337/687] Add timeout to change handler for retries --- .../zigbee-bridge/src/lights/cached_bridge.rs | 69 ++++++++++++++----- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 9b721d97..88ce68bf 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -10,6 +10,8 @@ use tokio::sync::{mpsc, RwLock}; use crate::lights::state::{Change, State}; use crate::{LIGHTS, MQTT_IP, MQTT_PORT, QOS}; +const CHANGE_TIMEOUT: Duration = Duration::from_secs(5); + struct Mqtt { client: AsyncClient, } @@ -136,25 +138,54 @@ async fn handle_changes( // Give the initial known states a chance to be fetched tokio::time::sleep(Duration::from_millis(500)).await; loop { - // TODO: add timeout - let (light_name, change) = change_receiver - .recv() - .await - .expect("Channel should never close"); - let known_states = known_states.read().await; - - dbg!(&known_states); - let previous_needed_state = match known_states.get(&light_name) { - Some(known_state) => needed_states - .entry(light_name.clone()) - .or_insert(known_state.clone()), - None => &mut State::default(), - }; - let new_needed_state = previous_needed_state.apply(change); - - if Some(&new_needed_state) != known_states.get(&light_name) { - // Ignore errors because we will retry if the state hasn't changed - let _ = mqtt.send_new_state(&light_name, &new_needed_state).await; + match tokio::time::timeout(CHANGE_TIMEOUT, change_receiver.recv()).await + { + Ok(change) => { + let (light_name, change) = + change.expect("Channel should never close"); + let known_states = known_states.read().await; + + let previous_needed_state = match needed_states.get(&light_name) + { + Some(needed_state) => needed_state, + None => match known_states.get(&light_name) { + Some(known_state) => needed_states + .entry(light_name.clone()) + .or_insert(known_state.clone()), + None => &mut State::default(), + }, + }; + + let new_needed_state = previous_needed_state.apply(change); + if Some(&new_needed_state) != known_states.get(&light_name) { + // Ignore errors because we will retry if the state hasn't changed + let _ = mqtt + .send_new_state(&light_name, &new_needed_state) + .await; + } + needed_states.insert(light_name, new_needed_state); + } + // Timeout + Err(_) => { + let known_states = known_states.read().await; + for light_name in LIGHTS { + match needed_states.get(light_name) { + Some(needed_state) => { + if Some(needed_state) + != known_states.get(light_name) + { + let _ = mqtt + .send_new_state( + &light_name, + &needed_state, + ) + .await; + } + }, + None => (), + } + } + } } } } From 5a1bba125cee49b3d8b9fd9ccf8e051bc6574ada Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 1 Nov 2024 11:55:53 +0100 Subject: [PATCH 338/687] Extract fns from handle_changes --- .../zigbee-bridge/src/lights/cached_bridge.rs | 85 ++++++++++--------- 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 88ce68bf..e05612a5 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -141,54 +141,55 @@ async fn handle_changes( match tokio::time::timeout(CHANGE_TIMEOUT, change_receiver.recv()).await { Ok(change) => { - let (light_name, change) = - change.expect("Channel should never close"); - let known_states = known_states.read().await; - - let previous_needed_state = match needed_states.get(&light_name) - { - Some(needed_state) => needed_state, - None => match known_states.get(&light_name) { - Some(known_state) => needed_states - .entry(light_name.clone()) - .or_insert(known_state.clone()), - None => &mut State::default(), - }, - }; - - let new_needed_state = previous_needed_state.apply(change); - if Some(&new_needed_state) != known_states.get(&light_name) { - // Ignore errors because we will retry if the state hasn't changed - let _ = mqtt - .send_new_state(&light_name, &new_needed_state) - .await; - } - needed_states.insert(light_name, new_needed_state); + apply_change(change, known_states, needed_states).await; } - // Timeout - Err(_) => { - let known_states = known_states.read().await; - for light_name in LIGHTS { - match needed_states.get(light_name) { - Some(needed_state) => { - if Some(needed_state) - != known_states.get(light_name) - { - let _ = mqtt - .send_new_state( - &light_name, - &needed_state, - ) - .await; - } - }, - None => (), - } + Err(_) => (), + } + send_all_changes(known_states, needed_states, mqtt).await; + } +} + +async fn send_all_changes( + known_states: &RwLock>, + needed_states: &mut HashMap, + mqtt: &Mqtt, +) { + let known_states = known_states.read().await; + for light_name in LIGHTS { + match needed_states.get(light_name) { + Some(needed_state) => { + if Some(needed_state) != known_states.get(light_name) { + // Ignore errors because we will retry if the state hasn't changed + let _ = + mqtt.send_new_state(&light_name, &needed_state).await; } } + None => (), } } } +async fn apply_change( + change: Option<(String, Change)>, + known_states: &RwLock>, + needed_states: &mut HashMap, +) { + let (light_name, change) = change.expect("Channel should never close"); + let known_states = known_states.read().await; + + let previous_needed_state = match needed_states.get(&light_name) { + Some(needed_state) => needed_state, + None => match known_states.get(&light_name) { + Some(known_state) => needed_states + .entry(light_name.clone()) + .or_insert(known_state.clone()), + None => &mut State::default(), + }, + }; + + let new_needed_state = previous_needed_state.apply(change); + + needed_states.insert(light_name, new_needed_state); +} fn extract_state_update(message: Event) -> Option<(String, State)> { match message { From 2100343585f097d0ff7f98d1323144c3a08503a4 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 1 Nov 2024 12:08:30 +0100 Subject: [PATCH 339/687] Fix clippy lints --- crates/zigbee-bridge/src/lib.rs | 2 +- crates/zigbee-bridge/src/lights.rs | 4 +++- .../zigbee-bridge/src/lights/cached_bridge.rs | 24 +++++++------------ crates/zigbee-bridge/src/lights/state.rs | 11 ++++----- 4 files changed, 18 insertions(+), 23 deletions(-) diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 042e05ea..4380c78e 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -25,7 +25,7 @@ mod tests { #[tokio::test] async fn start_bridge() { - let controller = Controller::start_bridge().await; + let controller = Controller::start_bridge(); controller.set_brightness("gangkast tafellamp", 1.0); diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index 2250d42a..c6742892 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -1,3 +1,4 @@ +#![allow(clippy::missing_panics_doc)] use tokio::sync::mpsc; use self::state::Change; @@ -12,7 +13,8 @@ pub struct Controller { } impl Controller { - pub async fn start_bridge() -> Self { + #[must_use] + pub fn start_bridge() -> Self { let (change_sender, change_receiver) = mpsc::unbounded_channel(); let run_bridge = cached_bridge::run(change_receiver); diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index e05612a5..fedccd37 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -101,7 +101,7 @@ pub(crate) async fn run( ); tokio::select! { - _ = handle_changes => (), + () = handle_changes => (), err = poll_mqtt => println!("Something went wrong with the mqtt connection: {err:?}"), }; @@ -138,12 +138,10 @@ async fn handle_changes( // Give the initial known states a chance to be fetched tokio::time::sleep(Duration::from_millis(500)).await; loop { - match tokio::time::timeout(CHANGE_TIMEOUT, change_receiver.recv()).await + if let Ok(change) = + tokio::time::timeout(CHANGE_TIMEOUT, change_receiver.recv()).await { - Ok(change) => { - apply_change(change, known_states, needed_states).await; - } - Err(_) => (), + apply_change(change, known_states, needed_states).await; } send_all_changes(known_states, needed_states, mqtt).await; } @@ -156,15 +154,11 @@ async fn send_all_changes( ) { let known_states = known_states.read().await; for light_name in LIGHTS { - match needed_states.get(light_name) { - Some(needed_state) => { - if Some(needed_state) != known_states.get(light_name) { - // Ignore errors because we will retry if the state hasn't changed - let _ = - mqtt.send_new_state(&light_name, &needed_state).await; - } + if let Some(needed_state) = needed_states.get(light_name) { + if Some(needed_state) != known_states.get(light_name) { + // Ignore errors because we will retry if the state hasn't changed + let _ = mqtt.send_new_state(light_name, needed_state).await; } - None => (), } } } @@ -210,6 +204,6 @@ fn extract_state_update(message: Event) -> Option<(String, State)> { None } }, - _ => None, + Event::Outgoing(_) => None, } } diff --git a/crates/zigbee-bridge/src/lights/state.rs b/crates/zigbee-bridge/src/lights/state.rs index 6d016e03..0a729f09 100644 --- a/crates/zigbee-bridge/src/lights/state.rs +++ b/crates/zigbee-bridge/src/lights/state.rs @@ -45,7 +45,7 @@ impl TryInto for &[u8] { ) } - let json: Value = serde_json::from_slice(&self)?; + let json: Value = serde_json::from_slice(self)?; let map = json.as_object().ok_or(invalid_err("Object"))?; let color = get_key(map, "color")? @@ -86,6 +86,7 @@ impl TryInto for &[u8] { }; Ok(State { + #[allow(clippy::cast_precision_loss)] brightness: brightness as f64 / 254., color_temp_kelvin: mired_to_kelvin(color_temp_mired), color_xy: (color_x, color_y), @@ -107,10 +108,8 @@ impl State { } pub(crate) fn to_payloads(&self) -> Vec { - let state = match self.on { - true => "ON", - false => "OFF", - }; + let state = if self.on { "ON" } else { "OFF" }; + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] let brightness: usize = (self.brightness * 254.).round() as usize; let color_temp_mired = kelvin_to_mired(self.color_temp_kelvin); @@ -127,7 +126,7 @@ impl State { } } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub(crate) enum Change { On(bool), Brightness(f64), From bf62ef8c0a55b23bd8d140172d946b869a646902 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 1 Nov 2024 12:14:08 +0100 Subject: [PATCH 340/687] Expand test and remove unimpl function from pub api --- crates/zigbee-bridge/src/lib.rs | 24 ++++++++++++++++++++++++ crates/zigbee-bridge/src/lights.rs | 10 +++++----- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 4380c78e..b72b0cc4 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -21,13 +21,37 @@ const LIGHTS: [&str; 2] = ["keuken tafellamp", "gangkast tafellamp"]; #[cfg(test)] mod tests { + use std::time::Duration; + use super::Controller; #[tokio::test] async fn start_bridge() { let controller = Controller::start_bridge(); + controller.set_brightness("gangkast tafellamp", 0.5); + controller.set_brightness("keuken tafellamp", 0.5); + + controller.set_color_temp("gangkast tafellamp", 2200); + controller.set_color_temp("keuken tafellamp", 2200); + + tokio::time::sleep(Duration::from_secs(2)).await; + + controller.set_off("gangkast tafellamp"); + controller.set_off("keuken tafellamp"); + + tokio::time::sleep(Duration::from_secs(2)).await; + + controller.set_on("gangkast tafellamp"); + controller.set_on("keuken tafellamp"); + + controller.set_color_temp("gangkast tafellamp", 4000); + controller.set_color_temp("keuken tafellamp", 4000); + + tokio::time::sleep(Duration::from_secs(2)).await; + controller.set_brightness("gangkast tafellamp", 1.0); + controller.set_brightness("keuken tafellamp", 1.0); let () = std::future::pending().await; unreachable!(); diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index c6742892..71da1f3f 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -47,9 +47,9 @@ impl Controller { .expect("Sender should never be dropped"); } - pub fn set_color_xy(&self, friendly_name: &str, xy: (f64, f64)) { - self.change_sender - .send((friendly_name.to_string(), Change::ColorXy(xy))) - .expect("Sender should never be dropped"); - } + // pub fn set_color_xy(&self, friendly_name: &str, xy: (f64, f64)) { + // self.change_sender + // .send((friendly_name.to_string(), Change::ColorXy(xy))) + // .expect("Sender should never be dropped"); + // } } From 67f2d223f53668bbbe84aea745e9616ce07ce998 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 1 Nov 2024 12:15:23 +0100 Subject: [PATCH 341/687] Remove unused file --- .../src/lights/cached_bridge/conversion.rs | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 crates/zigbee-bridge/src/lights/cached_bridge/conversion.rs diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/conversion.rs b/crates/zigbee-bridge/src/lights/cached_bridge/conversion.rs deleted file mode 100644 index 46ed88df..00000000 --- a/crates/zigbee-bridge/src/lights/cached_bridge/conversion.rs +++ /dev/null @@ -1,12 +0,0 @@ -pub(crate) fn mired_to_kelvin(mired: usize) -> usize { - 1_000_000 / mired -} - -pub(crate) fn kelvin_to_mired(kelvin: usize) -> usize { - 1_000_000 / kelvin -} - -pub(crate) fn temp_to_xy(color_temp: usize) -> (f64, f64) { - todo!() -} - From 238b8216b0cdc76e3470f2c646c394ebd7bf2f11 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 1 Nov 2024 12:22:05 +0100 Subject: [PATCH 342/687] Make State (Partial)Eq approximate --- crates/zigbee-bridge/src/lights/state.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/crates/zigbee-bridge/src/lights/state.rs b/crates/zigbee-bridge/src/lights/state.rs index 0a729f09..95679a81 100644 --- a/crates/zigbee-bridge/src/lights/state.rs +++ b/crates/zigbee-bridge/src/lights/state.rs @@ -4,7 +4,7 @@ use serde_json::{json, Value}; use crate::lights::conversion::{kelvin_to_mired, mired_to_kelvin, temp_to_xy}; -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, Clone)] pub(crate) struct State { pub(crate) brightness: f64, pub(crate) color_temp_kelvin: usize, @@ -23,6 +23,23 @@ impl Default for State { } } +impl PartialEq for State { + fn eq(&self, other: &Self) -> bool { + let d_bright = (self.brightness - other.brightness).abs(); + let d_color_temp = self.color_temp_kelvin - other.color_temp_kelvin; + let d_color_x = (self.color_xy.0 - other.color_xy.0).abs(); + let d_color_y = (self.color_xy.1 - other.color_xy.1).abs(); + + self.on == other.on + && d_bright < 1. / 250. + && d_color_temp < 20 + && d_color_x < 0.01 + && d_color_y < 0.01 + } +} + +impl Eq for State {} + impl TryInto for &[u8] { type Error = io::Error; From cb0e07f24c045a70ee1cebd63bc5c3e770f4fcf6 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 2 Nov 2024 11:00:34 +0100 Subject: [PATCH 343/687] Rename lights and refactor test --- crates/zigbee-bridge/src/lib.rs | 38 ++++++++++++++++----------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index b72b0cc4..8753daf0 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -9,49 +9,47 @@ use rumqttc::QoS; -pub use lights::Controller; - -mod lights; +pub mod lights; const QOS: QoS = QoS::AtLeastOnce; const MQTT_IP: &str = "192.168.1.43"; const MQTT_PORT: u16 = 1883; // TODO: get from bridge -const LIGHTS: [&str; 2] = ["keuken tafellamp", "gangkast tafellamp"]; +const LIGHTS: [&str; 2] = ["kitchen:fridge", "kitchen:hallway"]; #[cfg(test)] mod tests { + use super::*; + use crate::lights::Controller; use std::time::Duration; - use super::Controller; - #[tokio::test] async fn start_bridge() { let controller = Controller::start_bridge(); - controller.set_brightness("gangkast tafellamp", 0.5); - controller.set_brightness("keuken tafellamp", 0.5); - - controller.set_color_temp("gangkast tafellamp", 2200); - controller.set_color_temp("keuken tafellamp", 2200); + for light in LIGHTS { + controller.set_brightness(light, 0.5); + controller.set_color_temp(light, 2200); + } tokio::time::sleep(Duration::from_secs(2)).await; - controller.set_off("gangkast tafellamp"); - controller.set_off("keuken tafellamp"); + for light in LIGHTS { + controller.set_off(light); + } tokio::time::sleep(Duration::from_secs(2)).await; - controller.set_on("gangkast tafellamp"); - controller.set_on("keuken tafellamp"); - - controller.set_color_temp("gangkast tafellamp", 4000); - controller.set_color_temp("keuken tafellamp", 4000); + for light in LIGHTS { + controller.set_on(light); + controller.set_color_temp(light, 4000); + } tokio::time::sleep(Duration::from_secs(2)).await; - controller.set_brightness("gangkast tafellamp", 1.0); - controller.set_brightness("keuken tafellamp", 1.0); + for light in LIGHTS { + controller.set_brightness(light, 1.0); + } let () = std::future::pending().await; unreachable!(); From 21007d264ed541d0d66f51dd194cc6b7f6db150c Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 2 Nov 2024 11:01:08 +0100 Subject: [PATCH 344/687] Add normalize fns for bri and adjust public api --- crates/zigbee-bridge/src/lights.rs | 5 ++++- crates/zigbee-bridge/src/lights/conversion.rs | 13 ++++++++++--- crates/zigbee-bridge/src/lights/state.rs | 15 +++++++++------ 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index 71da1f3f..c74263d4 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -3,11 +3,14 @@ use tokio::sync::mpsc; use self::state::Change; +// TODO: make private once system is ported +pub use conversion::{kelvin_to_mired, mired_to_kelvin, normalize, denormalize}; + mod cached_bridge; mod conversion; mod state; -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct Controller { change_sender: mpsc::UnboundedSender<(String, state::Change)>, } diff --git a/crates/zigbee-bridge/src/lights/conversion.rs b/crates/zigbee-bridge/src/lights/conversion.rs index bdd98028..d6835c00 100644 --- a/crates/zigbee-bridge/src/lights/conversion.rs +++ b/crates/zigbee-bridge/src/lights/conversion.rs @@ -1,12 +1,19 @@ -pub(crate) fn mired_to_kelvin(mired: usize) -> usize { +pub fn mired_to_kelvin(mired: usize) -> usize { 1_000_000 / mired } -pub(crate) fn kelvin_to_mired(kelvin: usize) -> usize { +pub fn kelvin_to_mired(kelvin: usize) -> usize { 1_000_000 / kelvin } +pub fn normalize(brightness: u8) -> f64 { + brightness as f64 / 254. +} + +pub fn denormalize(brightness: f64) -> u8 { + (brightness * 254.).round() as u8 +} + pub(crate) fn temp_to_xy(color_temp: usize) -> (f64, f64) { (1.0, 1.0) } - diff --git a/crates/zigbee-bridge/src/lights/state.rs b/crates/zigbee-bridge/src/lights/state.rs index 95679a81..e6698423 100644 --- a/crates/zigbee-bridge/src/lights/state.rs +++ b/crates/zigbee-bridge/src/lights/state.rs @@ -2,7 +2,9 @@ use std::io; use serde_json::{json, Value}; -use crate::lights::conversion::{kelvin_to_mired, mired_to_kelvin, temp_to_xy}; +use crate::lights::{conversion::{ + kelvin_to_mired, mired_to_kelvin, normalize, temp_to_xy, +}, denormalize}; #[derive(Debug, Clone)] pub(crate) struct State { @@ -79,11 +81,13 @@ impl TryInto for &[u8] { .as_f64() .expect("Should return Some if not using arbitrary precision"); - let brightness = get_key(map, "brightness")? + let brightness: u8 = get_key(map, "brightness")? .as_number() .ok_or(invalid_err("Number"))? .as_u64() - .ok_or(invalid_err("u64"))?; + .ok_or(invalid_err("u64"))? + .try_into() + .map_err(|_| invalid_err("u8"))?; let color_temp_mired = get_key(map, "color_temp")? .as_number() @@ -104,7 +108,7 @@ impl TryInto for &[u8] { Ok(State { #[allow(clippy::cast_precision_loss)] - brightness: brightness as f64 / 254., + brightness: normalize(brightness), color_temp_kelvin: mired_to_kelvin(color_temp_mired), color_xy: (color_x, color_y), on, @@ -127,12 +131,11 @@ impl State { pub(crate) fn to_payloads(&self) -> Vec { let state = if self.on { "ON" } else { "OFF" }; #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - let brightness: usize = (self.brightness * 254.).round() as usize; let color_temp_mired = kelvin_to_mired(self.color_temp_kelvin); [ json!({ "state": state }), - json!({ "brightness": brightness }), + json!({ "brightness": denormalize(self.brightness) }), json!({ "color_temp": color_temp_mired }), // TODO: make sure this doesn't override temp / always use this // json!({ "color_xy": self.color_xy }), From f737264a3a3e08453bd02cb72078c3d4c7c79190 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 2 Nov 2024 11:01:36 +0100 Subject: [PATCH 345/687] Add zigbee bridge into brain for two new lights only --- Cargo.lock | 1 + Cargo.toml | 1 + crates/brain/Cargo.toml | 1 + crates/brain/src/controller/mod.rs | 28 +++++++++++++++++++++++++++- crates/brain/src/system.rs | 3 +++ 5 files changed, 33 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index b19bf8fc..3368db64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -502,6 +502,7 @@ dependencies = [ "tracing-journald", "tracing-subscriber", "tz-rs", + "zigbee-bridge", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 56b49124..73eb8648 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ data-server = { path = "crates/data-server" } data-store = { path = "crates/data-store" } log-store = { path = "crates/log-store" } protocol = { path = "crates/protocol" } +zigbee-bridge = { path = "crates/zigbee-bridge" } rpc = { path = "crates/rpc" } ratelimited-logger = { path = "crates/ratelimited-logger" } diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 71125435..0fc593fc 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -9,6 +9,7 @@ authors.workspace = true [dependencies] protocol = { workspace = true, features = ["alloc"] } data-server = { workspace = true } +zigbee-bridge = { workspace = true } futures = "0.3" tokio = { workspace = true, features = ["full"] } diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index bf21e654..1dc2f550 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize}; use time::{OffsetDateTime, UtcOffset}; use tokio::sync::broadcast; use tokio::task::JoinSet; +use zigbee_bridge::lights::{mired_to_kelvin, normalize}; // now_local works some of the time only... this replaces it with....... // horrible hard coded time stuff. Chrono does provide reliable now_local @@ -30,6 +31,7 @@ pub enum Event { struct RestrictedSystem { allowed_lights: Vec<&'static str>, + allowed_lights_new: Vec<&'static str>, system: System, } @@ -38,18 +40,35 @@ impl RestrictedSystem { for name in &self.allowed_lights { self.system.lights.set_ct(name, bri, ct).await.unwrap(); } + + for name in &self.allowed_lights_new { + self.system + .lights_new + .set_color_temp(name, mired_to_kelvin(ct.into())); + self.system + .lights_new + .set_brightness(name, normalize(bri)); + } } async fn all_lamps_off(&mut self) { for name in &self.allowed_lights { self.system.lights.single_off(name).await.unwrap(); } + + for name in &self.allowed_lights_new { + self.system.lights_new.set_off(name); + } } async fn all_lamps_on(&mut self) { for name in &self.allowed_lights { self.system.lights.single_on(name).await.unwrap(); } + + for name in &self.allowed_lights_new { + self.system.lights_new.set_on(name); + } } } @@ -71,6 +90,7 @@ pub fn start( "large_bedroom:wardrobe", "large_bedroom:bed", ], + allowed_lights_new: vec![], }; tasks.spawn(rooms::large_bedroom::run(rx1, sender.clone(), restricted)); @@ -81,12 +101,18 @@ pub fn start( "small_bedroom:bureau", "small_bedroom:piano", ], + allowed_lights_new: vec![], }; tasks.spawn(rooms::small_bedroom::run(rx2, sender.clone(), restricted)); let restricted = RestrictedSystem { system: system.clone(), - allowed_lights: vec!["kitchen:ceiling", "kitchen:hood_left", "kitchen:hood_right"], + allowed_lights: vec![ + "kitchen:ceiling", + "kitchen:hood_left", + "kitchen:hood_right", + ], + allowed_lights_new: vec!["kitchen:fridge", "kitchen:hallway"], }; tasks.spawn(rooms::kitchen::run(rx3, sender, restricted)); diff --git a/crates/brain/src/system.rs b/crates/brain/src/system.rs index 63dc964e..886cacd3 100644 --- a/crates/brain/src/system.rs +++ b/crates/brain/src/system.rs @@ -2,6 +2,7 @@ pub mod lamps; // pub mod mpd_control; pub use lamps::Lighting; +use zigbee_bridge::lights; // pub use mpd_control::Mpd; use crate::input::jobs::Jobs; @@ -11,6 +12,7 @@ pub struct System { #[allow(dead_code)] pub jobs: Jobs, pub lights: Lighting, + pub lights_new: lights::Controller, // pub mpd: Mpd, } @@ -19,6 +21,7 @@ impl System { Self { jobs, lights: Lighting::start_init(hue_bridge_ip), + lights_new: lights::Controller::start_bridge(), // mpd: Mpd, } } From f1beedf67a967990c73735d3d4dc3021dc38b450 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 2 Nov 2024 12:07:18 +0100 Subject: [PATCH 346/687] Extract mod changes --- .../zigbee-bridge/src/lights/cached_bridge.rs | 60 +---------------- .../src/lights/cached_bridge/changes.rs | 65 +++++++++++++++++++ 2 files changed, 68 insertions(+), 57 deletions(-) create mode 100644 crates/zigbee-bridge/src/lights/cached_bridge/changes.rs diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index fedccd37..c7b4270f 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -10,6 +10,8 @@ use tokio::sync::{mpsc, RwLock}; use crate::lights::state::{Change, State}; use crate::{LIGHTS, MQTT_IP, MQTT_PORT, QOS}; +mod changes; + const CHANGE_TIMEOUT: Duration = Duration::from_secs(5); struct Mqtt { @@ -93,7 +95,7 @@ pub(crate) async fn run( } let poll_mqtt = poll_mqtt(eventloop, &known_states); - let handle_changes = handle_changes( + let handle_changes = changes::handle( &mut change_receiver, &mqtt, &known_states, @@ -129,62 +131,6 @@ async fn poll_mqtt( } } -async fn handle_changes( - change_receiver: &mut mpsc::UnboundedReceiver<(String, Change)>, - mqtt: &Mqtt, - known_states: &RwLock>, - needed_states: &mut HashMap, -) -> ! { - // Give the initial known states a chance to be fetched - tokio::time::sleep(Duration::from_millis(500)).await; - loop { - if let Ok(change) = - tokio::time::timeout(CHANGE_TIMEOUT, change_receiver.recv()).await - { - apply_change(change, known_states, needed_states).await; - } - send_all_changes(known_states, needed_states, mqtt).await; - } -} - -async fn send_all_changes( - known_states: &RwLock>, - needed_states: &mut HashMap, - mqtt: &Mqtt, -) { - let known_states = known_states.read().await; - for light_name in LIGHTS { - if let Some(needed_state) = needed_states.get(light_name) { - if Some(needed_state) != known_states.get(light_name) { - // Ignore errors because we will retry if the state hasn't changed - let _ = mqtt.send_new_state(light_name, needed_state).await; - } - } - } -} -async fn apply_change( - change: Option<(String, Change)>, - known_states: &RwLock>, - needed_states: &mut HashMap, -) { - let (light_name, change) = change.expect("Channel should never close"); - let known_states = known_states.read().await; - - let previous_needed_state = match needed_states.get(&light_name) { - Some(needed_state) => needed_state, - None => match known_states.get(&light_name) { - Some(known_state) => needed_states - .entry(light_name.clone()) - .or_insert(known_state.clone()), - None => &mut State::default(), - }, - }; - - let new_needed_state = previous_needed_state.apply(change); - - needed_states.insert(light_name, new_needed_state); -} - fn extract_state_update(message: Event) -> Option<(String, State)> { match message { Event::Incoming(incoming) => match incoming { diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs new file mode 100644 index 00000000..e30c18f8 --- /dev/null +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -0,0 +1,65 @@ +use std::collections::HashMap; +use std::time::Duration; + +use tokio::sync::{mpsc, RwLock}; + +use super::{Mqtt, CHANGE_TIMEOUT}; +use crate::lights::state::{Change, State}; +use crate::LIGHTS; + +pub(super) async fn handle( + change_receiver: &mut mpsc::UnboundedReceiver<(String, Change)>, + mqtt: &Mqtt, + known_states: &RwLock>, + needed_states: &mut HashMap, +) -> ! { + // Give the initial known states a chance to be fetched + tokio::time::sleep(Duration::from_millis(500)).await; + loop { + if let Ok(change) = + tokio::time::timeout(CHANGE_TIMEOUT, change_receiver.recv()).await + { + apply_change(change, known_states, needed_states).await; + } + send_all(known_states, needed_states, mqtt).await; + } +} + +async fn send_all( + known_states: &RwLock>, + needed_states: &mut HashMap, + mqtt: &Mqtt, +) { + let known_states = known_states.read().await; + for light_name in LIGHTS { + if let Some(needed_state) = needed_states.get(light_name) { + if Some(needed_state) != known_states.get(light_name) { + // Ignore errors because we will retry if the state hasn't changed + let _ = mqtt.send_new_state(light_name, needed_state).await; + } + } + } +} + +async fn apply_change( + change: Option<(String, Change)>, + known_states: &RwLock>, + needed_states: &mut HashMap, +) { + let (light_name, change) = change.expect("Channel should never close"); + let known_states = known_states.read().await; + + let previous_needed_state = match needed_states.get(&light_name) { + Some(needed_state) => needed_state, + None => match known_states.get(&light_name) { + Some(known_state) => needed_states + .entry(light_name.clone()) + .or_insert(known_state.clone()), + None => &mut State::default(), + }, + }; + + let new_needed_state = previous_needed_state.apply(change); + + needed_states.insert(light_name, new_needed_state); +} From d797cd8dc3b2833f1d929858d141096adfec3826 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 2 Nov 2024 12:10:25 +0100 Subject: [PATCH 347/687] Extract mod poll --- .../zigbee-bridge/src/lights/cached_bridge.rs | 52 ++----------------- .../src/lights/cached_bridge/poll.rs | 51 ++++++++++++++++++ 2 files changed, 54 insertions(+), 49 deletions(-) create mode 100644 crates/zigbee-bridge/src/lights/cached_bridge/poll.rs diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index c7b4270f..6e79e800 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -1,9 +1,7 @@ use std::collections::HashMap; use std::time::Duration; -use rumqttc::{AsyncClient, ClientError, EventLoop}; -use rumqttc::{ConnectionError, Event}; -use rumqttc::{Incoming, MqttOptions}; +use rumqttc::{AsyncClient, ClientError, MqttOptions}; use serde_json::json; use tokio::sync::{mpsc, RwLock}; @@ -11,6 +9,7 @@ use crate::lights::state::{Change, State}; use crate::{LIGHTS, MQTT_IP, MQTT_PORT, QOS}; mod changes; +mod poll; const CHANGE_TIMEOUT: Duration = Duration::from_secs(5); @@ -94,7 +93,7 @@ pub(crate) async fn run( mqtt.request_state(light).await; } - let poll_mqtt = poll_mqtt(eventloop, &known_states); + let poll_mqtt = poll::poll_mqtt(eventloop, &known_states); let handle_changes = changes::handle( &mut change_receiver, &mqtt, @@ -108,48 +107,3 @@ pub(crate) async fn run( println!("Something went wrong with the mqtt connection: {err:?}"), }; } - -async fn poll_mqtt( - mut eventloop: EventLoop, - known_states: &RwLock>, -) -> Result<(), ConnectionError> { - loop { - let message = match eventloop.poll().await { - Ok(message) => message, - Err(err) => { - println!("Error while polling: {err}"); - continue; - } - }; - - if let Some((light_name, new_known_state)) = - extract_state_update(message) - { - let mut known_states = known_states.write().await; - known_states.insert(light_name, new_known_state); - } - } -} - -fn extract_state_update(message: Event) -> Option<(String, State)> { - match message { - Event::Incoming(incoming) => match incoming { - Incoming::ConnAck(_) - | Incoming::PubAck(_) - | Incoming::PingResp - | Incoming::SubAck(_) => None, - Incoming::Publish(message) => { - let topic: Vec<_> = message.topic.split('/').collect(); - let name = topic[1].to_string(); - let data = &(*message.payload); - - Some((name, data.try_into().unwrap())) - } - other => { - dbg!(other); - None - } - }, - Event::Outgoing(_) => None, - } -} diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs new file mode 100644 index 00000000..158e58f3 --- /dev/null +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -0,0 +1,51 @@ +use std::collections::HashMap; + +use rumqttc::{ConnectionError, Event, EventLoop, Incoming}; +use tokio::sync::RwLock; + +use crate::lights::state::State; + +pub(super) async fn poll_mqtt( + mut eventloop: EventLoop, + known_states: &RwLock>, +) -> Result<(), ConnectionError> { + loop { + let message = match eventloop.poll().await { + Ok(message) => message, + Err(err) => { + println!("Error while polling: {err}"); + continue; + } + }; + + if let Some((light_name, new_known_state)) = + extract_state_update(message) + { + let mut known_states = known_states.write().await; + known_states.insert(light_name, new_known_state); + } + } +} + +fn extract_state_update(message: Event) -> Option<(String, State)> { + match message { + Event::Incoming(incoming) => match incoming { + Incoming::ConnAck(_) + | Incoming::PubAck(_) + | Incoming::PingResp + | Incoming::SubAck(_) => None, + Incoming::Publish(message) => { + let topic: Vec<_> = message.topic.split('/').collect(); + let name = topic[1].to_string(); + let data = &(*message.payload); + + Some((name, data.try_into().unwrap())) + } + other => { + dbg!(other); + None + } + }, + Event::Outgoing(_) => None, + } +} From aabdc5c500810bd8d6e12aff765eac1da443695b Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 2 Nov 2024 12:15:36 +0100 Subject: [PATCH 348/687] Extract mod mqtt --- .../zigbee-bridge/src/lights/cached_bridge.rs | 69 ++---------------- .../src/lights/cached_bridge/changes.rs | 2 +- .../src/lights/cached_bridge/mqtt.rs | 70 +++++++++++++++++++ 3 files changed, 77 insertions(+), 64 deletions(-) create mode 100644 crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 6e79e800..129099ab 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -1,76 +1,19 @@ use std::collections::HashMap; use std::time::Duration; -use rumqttc::{AsyncClient, ClientError, MqttOptions}; -use serde_json::json; +use rumqttc::{AsyncClient, MqttOptions}; use tokio::sync::{mpsc, RwLock}; -use crate::lights::state::{Change, State}; -use crate::{LIGHTS, MQTT_IP, MQTT_PORT, QOS}; +use crate::lights::state::Change; +use crate::{LIGHTS, MQTT_IP, MQTT_PORT}; +use self::mqtt::Mqtt; mod changes; +mod mqtt; mod poll; const CHANGE_TIMEOUT: Duration = Duration::from_secs(5); -struct Mqtt { - client: AsyncClient, -} - -impl Mqtt { - async fn send_new_state( - &self, - light_name: &str, - needed_state: &State, - ) -> Result<(), ClientError> { - for payload in needed_state.to_payloads() { - self.set(light_name, &payload).await?; - } - Ok(()) - } - - async fn set( - &self, - friendly_name: &str, - payload: &str, - ) -> Result<(), ClientError> { - let topic = format!("zigbee2mqtt/{friendly_name}/set"); - - self.publish(&topic, payload).await?; - Ok(()) - } - - async fn get( - &self, - friendly_name: &str, - payload: &str, - ) -> Result<(), ClientError> { - let topic = format!("zigbee2mqtt/{friendly_name}/get"); - - self.publish(&topic, payload).await?; - Ok(()) - } - - async fn publish( - &self, - topic: &str, - payload: &str, - ) -> Result<(), ClientError> { - self.client.publish(topic, QOS, false, payload).await - } - - async fn request_state(&self, name: &str) { - println!("Requesting state for light {name}"); - let payload = json!({"state": ""}); - - self.get(name, &payload.to_string()).await.unwrap(); - } - - async fn subscribe(&self, topic: &str) -> Result<(), ClientError> { - self.client.subscribe(topic, QOS).await - } -} - pub(crate) async fn run( mut change_receiver: mpsc::UnboundedReceiver<(String, Change)>, ) { @@ -84,7 +27,7 @@ pub(crate) async fn run( // Reconnecting to broker is handled by Eventloop::poll let (client, eventloop) = AsyncClient::new(options.clone(), 128); - let mqtt = Mqtt { client }; + let mqtt = Mqtt::new(client); for light in LIGHTS { mqtt.subscribe(&format!("zigbee2mqtt/{light}")) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index e30c18f8..f8fb04e5 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -3,7 +3,7 @@ use std::time::Duration; use tokio::sync::{mpsc, RwLock}; -use super::{Mqtt, CHANGE_TIMEOUT}; +use super::{mqtt::Mqtt, CHANGE_TIMEOUT}; use crate::lights::state::{Change, State}; use crate::LIGHTS; diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs new file mode 100644 index 00000000..d7b1de04 --- /dev/null +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -0,0 +1,70 @@ +use rumqttc::{AsyncClient, ClientError}; +use serde_json::json; + +use crate::lights::state::State; +use crate::QOS; + +pub(super) struct Mqtt { + client: AsyncClient, +} + +impl Mqtt { + pub(super) fn new(client: AsyncClient) -> Self { + Mqtt { client } + } + + pub(super) async fn subscribe( + &self, + topic: &str, + ) -> Result<(), ClientError> { + self.client.subscribe(topic, QOS).await + } + + pub(super) async fn request_state(&self, name: &str) { + println!("Requesting state for light {name}"); + let payload = json!({"state": ""}); + + self.get(name, &payload.to_string()).await.unwrap(); + } + + pub(super) async fn send_new_state( + &self, + light_name: &str, + needed_state: &State, + ) -> Result<(), ClientError> { + for payload in needed_state.to_payloads() { + self.set(light_name, &payload).await?; + } + Ok(()) + } + + async fn set( + &self, + friendly_name: &str, + payload: &str, + ) -> Result<(), ClientError> { + let topic = format!("zigbee2mqtt/{friendly_name}/set"); + + self.publish(&topic, payload).await?; + Ok(()) + } + + async fn get( + &self, + friendly_name: &str, + payload: &str, + ) -> Result<(), ClientError> { + let topic = format!("zigbee2mqtt/{friendly_name}/get"); + + self.publish(&topic, payload).await?; + Ok(()) + } + + async fn publish( + &self, + topic: &str, + payload: &str, + ) -> Result<(), ClientError> { + self.client.publish(topic, QOS, false, payload).await + } +} From 69e4df0ba2d5c5ee0e2b68028cd4a9cd7fabc57e Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 2 Nov 2024 12:20:39 +0100 Subject: [PATCH 349/687] Small refactorings and cleanup --- crates/zigbee-bridge/src/lib.rs | 6 +----- crates/zigbee-bridge/src/lights/cached_bridge.rs | 3 ++- crates/zigbee-bridge/src/lights/cached_bridge/changes.rs | 5 ++--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 8753daf0..2285286a 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -1,7 +1,4 @@ // hue_power_on_behavior: "recover" / power_on_behavior: "previous" -// state: ON/OFF -// brightness: 0-254 -// color_temp: 153-500 (mired) / 250-454 // color_temp_startup // color_xy // Set to on, off after 30s @@ -14,7 +11,6 @@ pub mod lights; const QOS: QoS = QoS::AtLeastOnce; const MQTT_IP: &str = "192.168.1.43"; const MQTT_PORT: u16 = 1883; -// TODO: get from bridge const LIGHTS: [&str; 2] = ["kitchen:fridge", "kitchen:hallway"]; #[cfg(test)] @@ -24,7 +20,7 @@ mod tests { use std::time::Duration; #[tokio::test] - async fn start_bridge() { + async fn change_all_lights() { let controller = Controller::start_bridge(); for light in LIGHTS { diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 129099ab..c8db1df3 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -4,15 +4,16 @@ use std::time::Duration; use rumqttc::{AsyncClient, MqttOptions}; use tokio::sync::{mpsc, RwLock}; +use self::mqtt::Mqtt; use crate::lights::state::Change; use crate::{LIGHTS, MQTT_IP, MQTT_PORT}; -use self::mqtt::Mqtt; mod changes; mod mqtt; mod poll; const CHANGE_TIMEOUT: Duration = Duration::from_secs(5); +const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); pub(crate) async fn run( mut change_receiver: mpsc::UnboundedReceiver<(String, Change)>, diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index f8fb04e5..dbdb115a 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -1,9 +1,8 @@ use std::collections::HashMap; -use std::time::Duration; use tokio::sync::{mpsc, RwLock}; -use super::{mqtt::Mqtt, CHANGE_TIMEOUT}; +use super::{mqtt::Mqtt, CHANGE_TIMEOUT, WAIT_FOR_INIT_STATES}; use crate::lights::state::{Change, State}; use crate::LIGHTS; @@ -14,7 +13,7 @@ pub(super) async fn handle( needed_states: &mut HashMap, ) -> ! { // Give the initial known states a chance to be fetched - tokio::time::sleep(Duration::from_millis(500)).await; + tokio::time::sleep(WAIT_FOR_INIT_STATES).await; loop { if let Ok(change) = tokio::time::timeout(CHANGE_TIMEOUT, change_receiver.recv()).await From c403ea15b69c443a32ac990c788bf206b15daf29 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 2 Nov 2024 12:23:28 +0100 Subject: [PATCH 350/687] Fix clippy pedantic lints --- crates/zigbee-bridge/src/lights/conversion.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/zigbee-bridge/src/lights/conversion.rs b/crates/zigbee-bridge/src/lights/conversion.rs index d6835c00..80345fd6 100644 --- a/crates/zigbee-bridge/src/lights/conversion.rs +++ b/crates/zigbee-bridge/src/lights/conversion.rs @@ -1,15 +1,20 @@ +#[must_use] pub fn mired_to_kelvin(mired: usize) -> usize { 1_000_000 / mired } +#[must_use] pub fn kelvin_to_mired(kelvin: usize) -> usize { 1_000_000 / kelvin } +#[must_use] pub fn normalize(brightness: u8) -> f64 { - brightness as f64 / 254. + f64::from(brightness) / 254. } +#[must_use] +#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] pub fn denormalize(brightness: f64) -> u8 { (brightness * 254.).round() as u8 } From f58b882c5cf0077411528bc8bc010ef11cbbacf1 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 2 Nov 2024 13:54:21 +0100 Subject: [PATCH 351/687] zigbee-bridge: rename State->Lamp, never type for some returns --- .../zigbee-bridge/src/lights/cached_bridge.rs | 14 +++--- .../src/lights/cached_bridge/changes.rs | 43 ++++++++++--------- .../src/lights/cached_bridge/mqtt.rs | 4 +- .../src/lights/cached_bridge/poll.rs | 14 +++--- crates/zigbee-bridge/src/lights/state.rs | 18 ++++---- 5 files changed, 44 insertions(+), 49 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index c8db1df3..211a1a38 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -15,11 +15,8 @@ mod poll; const CHANGE_TIMEOUT: Duration = Duration::from_secs(5); const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); -pub(crate) async fn run( - mut change_receiver: mpsc::UnboundedReceiver<(String, Change)>, -) { - let mut options = - MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); +pub(crate) async fn run(mut change_receiver: mpsc::UnboundedReceiver<(String, Change)>) -> ! { + let mut options = MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); // Set incoming to max mqtt packet size, outgoing to rumqtt default options.set_max_packet_size(2_usize.pow(28), 10240); @@ -46,8 +43,7 @@ pub(crate) async fn run( ); tokio::select! { - () = handle_changes => (), - err = poll_mqtt => - println!("Something went wrong with the mqtt connection: {err:?}"), - }; + () = handle_changes => unreachable!("should not panic"), + () = poll_mqtt => unreachable!("should not panic") + } } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index dbdb115a..cb5d5ae9 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -1,23 +1,22 @@ use std::collections::HashMap; use tokio::sync::{mpsc, RwLock}; +use tokio::time::{sleep, timeout}; use super::{mqtt::Mqtt, CHANGE_TIMEOUT, WAIT_FOR_INIT_STATES}; -use crate::lights::state::{Change, State}; +use crate::lights::state::{Change, Lamp}; use crate::LIGHTS; pub(super) async fn handle( change_receiver: &mut mpsc::UnboundedReceiver<(String, Change)>, mqtt: &Mqtt, - known_states: &RwLock>, - needed_states: &mut HashMap, + known_states: &RwLock>, + needed_states: &mut HashMap, ) -> ! { // Give the initial known states a chance to be fetched - tokio::time::sleep(WAIT_FOR_INIT_STATES).await; + sleep(WAIT_FOR_INIT_STATES).await; loop { - if let Ok(change) = - tokio::time::timeout(CHANGE_TIMEOUT, change_receiver.recv()).await - { + if let Ok(change) = timeout(CHANGE_TIMEOUT, change_receiver.recv()).await { apply_change(change, known_states, needed_states).await; } send_all(known_states, needed_states, mqtt).await; @@ -25,40 +24,42 @@ pub(super) async fn handle( } async fn send_all( - known_states: &RwLock>, - needed_states: &mut HashMap, + known_states: &RwLock>, + needed_states: &mut HashMap, mqtt: &Mqtt, ) { let known_states = known_states.read().await; for light_name in LIGHTS { - if let Some(needed_state) = needed_states.get(light_name) { - if Some(needed_state) != known_states.get(light_name) { - // Ignore errors because we will retry if the state hasn't changed - let _ = mqtt.send_new_state(light_name, needed_state).await; - } + let Some(needed) = needed_states.get(light_name) else { + continue; + }; + + let known = known_states.get(light_name); + if Some(needed) != known { + // Ignore errors because we will retry if the state hasn't changed + let _ = mqtt.send_new_state(light_name, needed).await; } } } async fn apply_change( change: Option<(String, Change)>, - known_states: &RwLock>, - needed_states: &mut HashMap, + known_states: &RwLock>, + needed_states: &mut HashMap, ) { let (light_name, change) = change.expect("Channel should never close"); let known_states = known_states.read().await; - let previous_needed_state = match needed_states.get(&light_name) { + let needed = match needed_states.get(&light_name) { Some(needed_state) => needed_state, None => match known_states.get(&light_name) { Some(known_state) => needed_states .entry(light_name.clone()) .or_insert(known_state.clone()), - None => &mut State::default(), + None => &mut Lamp::default(), }, }; - let new_needed_state = previous_needed_state.apply(change); - - needed_states.insert(light_name, new_needed_state); + let with_change_applied = needed.apply(change); + needed_states.insert(light_name, with_change_applied); } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index d7b1de04..81e72a85 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -1,7 +1,7 @@ use rumqttc::{AsyncClient, ClientError}; use serde_json::json; -use crate::lights::state::State; +use crate::lights::state::Lamp; use crate::QOS; pub(super) struct Mqtt { @@ -30,7 +30,7 @@ impl Mqtt { pub(super) async fn send_new_state( &self, light_name: &str, - needed_state: &State, + needed_state: &Lamp, ) -> Result<(), ClientError> { for payload in needed_state.to_payloads() { self.set(light_name, &payload).await?; diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 158e58f3..743201c0 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -1,14 +1,14 @@ use std::collections::HashMap; -use rumqttc::{ConnectionError, Event, EventLoop, Incoming}; +use rumqttc::{Event, EventLoop, Incoming}; use tokio::sync::RwLock; -use crate::lights::state::State; +use crate::lights::state::Lamp; pub(super) async fn poll_mqtt( mut eventloop: EventLoop, - known_states: &RwLock>, -) -> Result<(), ConnectionError> { + known_states: &RwLock>, +) -> ! { loop { let message = match eventloop.poll().await { Ok(message) => message, @@ -18,16 +18,14 @@ pub(super) async fn poll_mqtt( } }; - if let Some((light_name, new_known_state)) = - extract_state_update(message) - { + if let Some((light_name, new_known_state)) = extract_state_update(message) { let mut known_states = known_states.write().await; known_states.insert(light_name, new_known_state); } } } -fn extract_state_update(message: Event) -> Option<(String, State)> { +fn extract_state_update(message: Event) -> Option<(String, Lamp)> { match message { Event::Incoming(incoming) => match incoming { Incoming::ConnAck(_) diff --git a/crates/zigbee-bridge/src/lights/state.rs b/crates/zigbee-bridge/src/lights/state.rs index e6698423..c6acf7b2 100644 --- a/crates/zigbee-bridge/src/lights/state.rs +++ b/crates/zigbee-bridge/src/lights/state.rs @@ -7,14 +7,14 @@ use crate::lights::{conversion::{ }, denormalize}; #[derive(Debug, Clone)] -pub(crate) struct State { +pub(crate) struct Lamp { pub(crate) brightness: f64, pub(crate) color_temp_kelvin: usize, pub(crate) color_xy: (f64, f64), pub(crate) on: bool, } -impl Default for State { +impl Default for Lamp { fn default() -> Self { Self { brightness: 1.0, @@ -25,7 +25,7 @@ impl Default for State { } } -impl PartialEq for State { +impl PartialEq for Lamp { fn eq(&self, other: &Self) -> bool { let d_bright = (self.brightness - other.brightness).abs(); let d_color_temp = self.color_temp_kelvin - other.color_temp_kelvin; @@ -40,12 +40,12 @@ impl PartialEq for State { } } -impl Eq for State {} +impl Eq for Lamp {} -impl TryInto for &[u8] { +impl TryInto for &[u8] { type Error = io::Error; - fn try_into(self) -> Result { + fn try_into(self) -> Result { fn get_key<'a>( map: &'a serde_json::Map, key: &str, @@ -106,7 +106,7 @@ impl TryInto for &[u8] { other => return Err(invalid_err(&format!("on/off bool: {other}"))), }; - Ok(State { + Ok(Lamp { #[allow(clippy::cast_precision_loss)] brightness: normalize(brightness), color_temp_kelvin: mired_to_kelvin(color_temp_mired), @@ -116,8 +116,8 @@ impl TryInto for &[u8] { } } -impl State { - pub(crate) fn apply(&self, change: Change) -> State { +impl Lamp { + pub(crate) fn apply(&self, change: Change) -> Lamp { let mut new_state = self.clone(); match change { Change::On(on) => new_state.on = on, From 37f3c7df9ba01e2396ec31c39e492650b444baf4 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 2 Nov 2024 13:56:47 +0100 Subject: [PATCH 352/687] zigbee-bridge: removes transient C dep --- Cargo.lock | 474 ++++++++++++-------------------- crates/zigbee-bridge/Cargo.toml | 4 +- 2 files changed, 184 insertions(+), 294 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3368db64..9a7a0aae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,9 +55,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" dependencies = [ "anstyle", "anstyle-parse", @@ -70,36 +70,36 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -150,7 +150,7 @@ dependencies = [ "async-task", "concurrent-queue", "fastrand 2.1.1", - "futures-lite 2.3.0", + "futures-lite 2.4.0", "slab", ] @@ -165,7 +165,7 @@ dependencies = [ "async-io", "async-lock", "blocking", - "futures-lite 2.3.0", + "futures-lite 2.4.0", "once_cell", ] @@ -179,7 +179,7 @@ dependencies = [ "cfg-if 1.0.0", "concurrent-queue", "futures-io", - "futures-lite 2.3.0", + "futures-lite 2.4.0", "parking", "polling", "rustix", @@ -213,7 +213,7 @@ dependencies = [ "blocking", "cfg-if 1.0.0", "event-listener 5.3.1", - "futures-lite 2.3.0", + "futures-lite 2.4.0", "rustix", "tracing", ] @@ -252,7 +252,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-io", - "futures-lite 2.3.0", + "futures-lite 2.4.0", "gloo-timers", "kv-log-macro", "log", @@ -299,7 +299,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.86", ] [[package]] @@ -381,7 +381,7 @@ checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.86", ] [[package]] @@ -435,18 +435,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - [[package]] name = "blocking" version = "1.6.1" @@ -456,7 +444,7 @@ dependencies = [ "async-channel 2.3.1", "async-task", "futures-io", - "futures-lite 2.3.0", + "futures-lite 2.4.0", "piper", ] @@ -525,9 +513,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "byteseries" @@ -567,9 +555,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.28" +version = "1.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +checksum = "e3788d6ac30243803df38a3e9991cf37e41210232916d41a8222ae378f912624" dependencies = [ "shlex", ] @@ -632,7 +620,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.86", ] [[package]] @@ -687,9 +675,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "compact_str" @@ -726,6 +714,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "cordyceps" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec10f0a762d93c4498d2e97a333805cb6250d60bead623f71d8034f9a4152ba3" +dependencies = [ + "loom", + "tracing", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -736,6 +734,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -753,9 +761,9 @@ dependencies = [ [[package]] name = "critical-section" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "crossbeam-channel" @@ -892,7 +900,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.86", ] [[package]] @@ -934,7 +942,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.85", + "syn 2.0.86", ] [[package]] @@ -1024,7 +1032,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.86", ] [[package]] @@ -1093,7 +1101,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.86", ] [[package]] @@ -1199,6 +1207,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "flate2" version = "1.0.34" @@ -1251,12 +1265,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - [[package]] name = "futures" version = "0.3.31" @@ -1274,10 +1282,11 @@ dependencies = [ [[package]] name = "futures-buffered" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fa130f3777d0d4b0993653c20bc433026d3290627693c4ed1b18dd237357ab" +checksum = "34acda8ae8b63fbe0b2195c998b180cff89a8212fb2622a78b572a9f1c6f7684" dependencies = [ + "cordyceps", "diatomic-waker", "futures-core", "pin-project-lite", @@ -1295,11 +1304,11 @@ dependencies = [ [[package]] name = "futures-concurrency" -version = "7.6.1" +version = "7.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b14ac911e85d57c5ea6eef76d7b4d4a3177ecd15f4bea2e61927e9e3823e19f" +checksum = "d9b724496da7c26fcce66458526ce68fc2ecf4aaaa994281cf322ded5755520c" dependencies = [ - "bitvec", + "fixedbitset", "futures-buffered", "futures-core", "futures-lite 1.13.0", @@ -1348,9 +1357,9 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +checksum = "3f1fa2f9765705486b33fd2acf1577f8ec449c2ba1f318ae5447697b7c08d210" dependencies = [ "fastrand 2.1.1", "futures-core", @@ -1367,7 +1376,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.86", ] [[package]] @@ -1415,6 +1424,19 @@ dependencies = [ "byteorder", ] +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows", +] + [[package]] name = "gethostname" version = "0.5.0" @@ -1700,9 +1722,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", @@ -1720,9 +1742,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", @@ -1800,25 +1822,25 @@ dependencies = [ [[package]] name = "indextree" -version = "4.7.2" +version = "4.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6f1b8dbc8f1e5a0f45e05b9293c42cbab79086baeb3e914d3936f8149edc4f" +checksum = "91f3e68a01402c3404bfb739079f38858325bc7ad775b07922278a8a415b1a3f" dependencies = [ "indextree-macros", ] [[package]] name = "indextree-macros" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357230c23ee6024223892ce0de19888a04139ca5bb94f5becb04d38b75a4bccf" +checksum = "477e2e7ec7379407656293ff74902caea786a1dda427ca1f84b923c4fdeb7659" dependencies = [ "either", "itertools", "proc-macro2", "quote", "strum", - "syn 2.0.85", + "syn 2.0.86", "thiserror", ] @@ -1829,7 +1851,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" dependencies = [ "quote", - "syn 2.0.85", + "syn 2.0.86", ] [[package]] @@ -1886,9 +1908,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jiff" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a45489186a6123c128fdf6016183fcfab7113e1820eb813127e036e287233fb" +checksum = "b9d9d414fc817d3e3d62b2598616733f76c4cc74fbac96069674739b881295c8" dependencies = [ "jiff-tzdb-platform", "serde", @@ -1912,9 +1934,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -1936,9 +1958,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.159" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libredox" @@ -2023,6 +2045,19 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if 1.0.0", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + [[package]] name = "lru" version = "0.12.5" @@ -2352,7 +2387,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d8beeee5c0ad012e1eaca540f5610d09a3af58ec435537d511b67e0be36ea66" dependencies = [ "atomic-waker", - "core-foundation", + "core-foundation 0.9.4", "core-foundation-sys", "io-kit-sys", "log", @@ -2377,12 +2412,6 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - [[package]] name = "option-ext" version = "0.2.0" @@ -2469,29 +2498,29 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.86", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -2598,9 +2627,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.87" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -2667,12 +2696,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - [[package]] name = "radix_trie" version = "0.2.1" @@ -2784,9 +2807,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -2828,9 +2851,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.8" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ "base64 0.22.1", "bytes", @@ -2871,21 +2894,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "ring" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" -dependencies = [ - "cc", - "cfg-if 1.0.0", - "getrandom", - "libc", - "spin", - "untrusted", - "windows-sys 0.52.0", -] - [[package]] name = "ron" version = "0.8.1" @@ -2924,12 +2932,8 @@ dependencies = [ "flume", "futures-util", "log", - "rustls-native-certs", - "rustls-pemfile", - "rustls-webpki", "thiserror", "tokio", - "tokio-rustls", ] [[package]] @@ -2949,9 +2953,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" dependencies = [ "bitflags 2.6.0", "errno", @@ -2960,64 +2964,11 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rustls" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" -dependencies = [ - "log", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-native-certs" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" -dependencies = [ - "openssl-probe", - "rustls-pemfile", - "rustls-pki-types", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" - -[[package]] -name = "rustls-webpki" -version = "0.102.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "rustyline" @@ -3050,13 +3001,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] -name = "schannel" -version = "0.1.26" +name = "scoped-tls" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" -dependencies = [ - "windows-sys 0.59.0", -] +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" @@ -3064,29 +3012,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.6.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "1.0.23" @@ -3122,22 +3047,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.213" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.213" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.86", ] [[package]] @@ -3179,12 +3104,13 @@ dependencies = [ [[package]] name = "serialport" -version = "4.5.1" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ba776acc8c373b9175829206229366273225436845c04f9c20aab8099960e2e" +checksum = "7331eefcaafaa382c0df95bcd84068f0b3e3c215c300750dde2316e9b8806ed5" dependencies = [ "bitflags 2.6.0", "cfg-if 1.0.0", + "core-foundation 0.10.0", "core-foundation-sys", "io-kit-sys", "mach2", @@ -3376,15 +3302,9 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.85", + "syn 2.0.86", ] -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - [[package]] name = "syn" version = "1.0.109" @@ -3398,9 +3318,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.85" +version = "2.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +checksum = "e89275301d38033efb81a6e60e3497e734dfcc62571f2854bf4b16690398824c" dependencies = [ "proc-macro2", "quote", @@ -3443,12 +3363,6 @@ dependencies = [ "nix 0.23.2", ] -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - [[package]] name = "temp-dir" version = "0.1.14" @@ -3457,22 +3371,22 @@ checksum = "bc1ee6eef34f12f765cb94725905c6312b6610ab2b0940889cfe58dae7bc3c72" [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.86", ] [[package]] @@ -3532,9 +3446,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" dependencies = [ "backtrace", "bytes", @@ -3556,18 +3470,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", -] - -[[package]] -name = "tokio-rustls" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" -dependencies = [ - "rustls", - "rustls-pki-types", - "tokio", + "syn 2.0.86", ] [[package]] @@ -3655,7 +3558,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.86", ] [[package]] @@ -3763,12 +3666,9 @@ dependencies = [ [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-bidi" @@ -3826,12 +3726,6 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - [[package]] name = "url" version = "2.5.2" @@ -3885,9 +3779,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" +checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" [[package]] name = "version_check" @@ -3938,9 +3832,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if 1.0.0", "once_cell", @@ -3949,24 +3843,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.86", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -3976,9 +3870,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3986,28 +3880,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.86", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -4035,6 +3929,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -4222,15 +4125,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - [[package]] name = "zerocopy" version = "0.7.35" @@ -4249,15 +4143,9 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.86", ] -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" - [[package]] name = "zigbee-bridge" version = "0.1.0" diff --git a/crates/zigbee-bridge/Cargo.toml b/crates/zigbee-bridge/Cargo.toml index c94fe5ed..29507621 100644 --- a/crates/zigbee-bridge/Cargo.toml +++ b/crates/zigbee-bridge/Cargo.toml @@ -7,7 +7,9 @@ license.workspace = true authors.workspace = true [dependencies] -rumqttc = "0.24.0" +# default-features enable rustls which we do not need and drags in +# C dependencies making deployment a chore +rumqttc = { version = "0.24.0", default-features = false } serde_json = "1.0.132" thiserror.workspace = true tokio = { workspace = true, features = ["sync"] } From 2d7b44e7266d3d3fe69e8811d139a60cc3442aa9 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 3 Nov 2024 16:32:08 +0100 Subject: [PATCH 353/687] Revert "add reset on error i2c" This reverts commit c499a6b2f730c4be4ea157a9b1074b14ee2cd77f. --- Cargo.lock | 307 +++++++++--------- sensor-nodes/Cargo.lock | 21 +- sensor-nodes/Cargo.toml | 39 +-- sensor-nodes/bed-sb/src/main.rs | 9 +- sensor-nodes/bed-sb/src/reset_on_error_i2c.rs | 74 ----- sensor-nodes/bed-sb/src/sensors.rs | 11 +- sensor-nodes/bed-sb/src/sensors/retry.rs | 11 +- sensor-nodes/rust-toolchain.toml | 6 - 8 files changed, 201 insertions(+), 277 deletions(-) delete mode 100644 sensor-nodes/bed-sb/src/reset_on_error_i2c.rs delete mode 100644 sensor-nodes/rust-toolchain.toml diff --git a/Cargo.lock b/Cargo.lock index d8bc27b5..42d25d3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,18 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if 1.0.0", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -293,13 +305,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.83" +version = "0.1.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.77", ] [[package]] @@ -319,15 +331,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" -version = "0.7.7" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" +checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", "axum-core", @@ -355,9 +367,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.5" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" dependencies = [ "async-trait", "bytes", @@ -368,20 +380,21 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.1", + "sync_wrapper 0.1.2", "tower-layer", "tower-service", ] [[package]] name = "axum-macros" -version = "0.4.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" +checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" dependencies = [ + "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.77", ] [[package]] @@ -531,7 +544,7 @@ checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "byteseries" version = "0.7.1" -source = "git+https://github.com/dvdsk/byteseries#eb057c6363548fa1fc2fbe5a89395b81238152f5" +source = "git+https://github.com/dvdsk/byteseries#edc1c89c580c35b411de68feab4f665303d4c5cc" dependencies = [ "arraydeque", "itertools", @@ -566,9 +579,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.28" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" dependencies = [ "shlex", ] @@ -602,9 +615,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" dependencies = [ "clap_builder", "clap_derive", @@ -612,9 +625,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" dependencies = [ "anstream", "anstyle", @@ -624,14 +637,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.77", ] [[package]] @@ -812,7 +825,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if 1.0.0", - "hashbrown 0.14.5", + "hashbrown", "lock_api", "once_cell", "parking_lot_core 0.9.10", @@ -891,7 +904,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.77", ] [[package]] @@ -933,7 +946,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.79", + "syn 2.0.77", ] [[package]] @@ -1023,7 +1036,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.77", ] [[package]] @@ -1092,7 +1105,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.77", ] [[package]] @@ -1200,9 +1213,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", "miniz_oxide 0.8.0", @@ -1214,12 +1227,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foldhash" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -1247,9 +1254,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -1273,9 +1280,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1298,15 +1305,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -1315,9 +1322,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-lite" @@ -1349,26 +1356,26 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.77", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-timer" @@ -1378,9 +1385,9 @@ checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -1475,9 +1482,9 @@ dependencies = [ [[package]] name = "gpiocdev" -version = "0.7.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea1a9715542f84bc7b67cbb01c02ed3a72a919750b7d8611cc5bd684449386e" +checksum = "f5119c89eccee09c4f6e9ca2b112aea1cd80bac31cd29169f171a48ae5552d1c" dependencies = [ "futures", "gpiocdev-uapi", @@ -1500,9 +1507,9 @@ dependencies = [ [[package]] name = "gpiocdev-uapi" -version = "0.6.3" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d5c09e8bbed8a03e31b0fabf273da9486940091820a088215cd9fc24a1523d1" +checksum = "a02357253f833a6ce4e93f17e8dd3e169c941ea71b83d442ed9c55f784045204" dependencies = [ "bitflags 2.6.0", "ioctl-sys", @@ -1554,16 +1561,9 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - -[[package]] -name = "hashbrown" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" dependencies = [ + "ahash", "allocator-api2", - "equivalent", - "foldhash", ] [[package]] @@ -1606,6 +1606,12 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "heck" version = "0.5.0" @@ -1624,6 +1630,24 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +[[package]] +name = "host" +version = "0.1.0" +dependencies = [ + "clap", + "color-eyre", + "data-server", + "heapless 0.8.0", + "nusb", + "protocol", + "ratelimited-logger", + "tokio", + "tracing", + "tracing-error", + "tracing-subscriber", + "users", +] + [[package]] name = "http" version = "1.1.0" @@ -1660,9 +1684,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.5" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -1708,9 +1732,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.9" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" dependencies = [ "bytes", "futures-channel", @@ -1721,6 +1745,7 @@ dependencies = [ "pin-project-lite", "socket2", "tokio", + "tower", "tower-service", "tracing", ] @@ -1778,12 +1803,12 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "2.6.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown", ] [[package]] @@ -1817,7 +1842,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" dependencies = [ "quote", - "syn 2.0.79", + "syn 2.0.77", ] [[package]] @@ -1847,9 +1872,9 @@ checksum = "8bd11f3a29434026f5ff98c730b668ba74b1033637b8817940b54d040696133c" [[package]] name = "ipnet" -version = "2.10.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" [[package]] name = "is_terminal_polyfill" @@ -1924,9 +1949,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.159" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libredox" @@ -2013,11 +2038,11 @@ dependencies = [ [[package]] name = "lru" -version = "0.12.5" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" dependencies = [ - "hashbrown 0.15.0", + "hashbrown", ] [[package]] @@ -2361,9 +2386,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.2" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "option-ext" @@ -2432,7 +2457,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.5.7", + "redox_syscall 0.5.4", "smallvec 1.13.2", "windows-targets 0.52.6", ] @@ -2451,22 +2476,22 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.6" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.6" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.77", ] [[package]] @@ -2509,9 +2534,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.9.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" +checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce" [[package]] name = "postcard" @@ -2580,9 +2605,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.87" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -2728,9 +2753,9 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "11.2.0" +version = "11.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0" +checksum = "cb9ee317cfe3fbd54b36a511efc1edd42e216903c9cd575e686dd68a2ba90d8d" dependencies = [ "bitflags 2.6.0", ] @@ -2746,9 +2771,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" dependencies = [ "bitflags 2.6.0", ] @@ -2766,14 +2791,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.0" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.8", - "regex-syntax 0.8.5", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] @@ -2787,13 +2812,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.5", + "regex-syntax 0.8.4", ] [[package]] @@ -2804,15 +2829,15 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "reqwest" -version = "0.12.8" +version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" dependencies = [ "base64 0.22.1", "bytes", @@ -3001,7 +3026,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.77", ] [[package]] @@ -3236,11 +3261,11 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", "rustversion", - "syn 2.0.79", + "syn 2.0.77", ] [[package]] @@ -3256,9 +3281,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -3309,28 +3334,28 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "temp-dir" -version = "0.1.14" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc1ee6eef34f12f765cb94725905c6312b6610ab2b0940889cfe58dae7bc3c72" +checksum = "1f227968ec00f0e5322f9b8173c7a0cbcff6181a0a5b28e9892491c286277231" [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.77", ] [[package]] @@ -3414,7 +3439,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.77", ] [[package]] @@ -3458,14 +3483,14 @@ dependencies = [ [[package]] name = "tower" -version = "0.5.1" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", + "pin-project", "pin-project-lite", - "sync_wrapper 0.1.2", "tokio", "tower-layer", "tower-service", @@ -3502,7 +3527,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.77", ] [[package]] @@ -3619,9 +3644,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.17" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -3684,24 +3709,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "usb-bridge" -version = "0.1.0" -dependencies = [ - "clap", - "color-eyre", - "data-server", - "heapless 0.8.0", - "nusb", - "protocol", - "ratelimited-logger", - "tokio", - "tracing", - "tracing-error", - "tracing-subscriber", - "users", -] - [[package]] name = "users" version = "0.11.0" @@ -3799,7 +3806,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.77", "wasm-bindgen-shared", ] @@ -3833,7 +3840,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.77", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4090,5 +4097,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.77", ] diff --git a/sensor-nodes/Cargo.lock b/sensor-nodes/Cargo.lock index e60edb92..f5f04cb2 100644 --- a/sensor-nodes/Cargo.lock +++ b/sensor-nodes/Cargo.lock @@ -266,6 +266,7 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "defmt", "embassy-futures", @@ -282,6 +283,7 @@ dependencies = [ [[package]] name = "embassy-executor" version = "0.6.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "cortex-m", "critical-section", @@ -295,6 +297,7 @@ dependencies = [ [[package]] name = "embassy-executor-macros" version = "0.5.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "darling", "proc-macro2", @@ -305,10 +308,12 @@ dependencies = [ [[package]] name = "embassy-futures" version = "0.1.1" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" [[package]] name = "embassy-hal-internal" version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "cortex-m", "critical-section", @@ -319,6 +324,7 @@ dependencies = [ [[package]] name = "embassy-net" version = "0.4.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "defmt", "document-features", @@ -335,6 +341,7 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "defmt", ] @@ -342,6 +349,7 @@ dependencies = [ [[package]] name = "embassy-net-driver-channel" version = "0.3.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "embassy-futures", "embassy-net-driver", @@ -351,6 +359,7 @@ dependencies = [ [[package]] name = "embassy-net-wiznet" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "defmt", "embassy-futures", @@ -363,6 +372,7 @@ dependencies = [ [[package]] name = "embassy-stm32" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "aligned", "bit_field", @@ -408,6 +418,7 @@ dependencies = [ [[package]] name = "embassy-sync" version = "0.6.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "cfg-if", "critical-section", @@ -420,6 +431,7 @@ dependencies = [ [[package]] name = "embassy-time" version = "0.3.2" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "cfg-if", "critical-section", @@ -437,6 +449,7 @@ dependencies = [ [[package]] name = "embassy-time-driver" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "document-features", ] @@ -444,10 +457,12 @@ dependencies = [ [[package]] name = "embassy-time-queue-driver" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" [[package]] name = "embassy-usb" version = "0.3.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "defmt", "embassy-futures", @@ -462,6 +477,7 @@ dependencies = [ [[package]] name = "embassy-usb-driver" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "defmt", ] @@ -469,6 +485,7 @@ dependencies = [ [[package]] name = "embassy-usb-synopsys-otg" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" dependencies = [ "critical-section", "embassy-sync", @@ -1048,10 +1065,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -[[package]] -name = "sensors" -version = "0.1.0" - [[package]] name = "serde" version = "1.0.210" diff --git a/sensor-nodes/Cargo.toml b/sensor-nodes/Cargo.toml index 1d793955..935e2f00 100644 --- a/sensor-nodes/Cargo.toml +++ b/sensor-nodes/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "2" -members = ["bed-sb", "bed-lb", "sensors"] +members = ["bed-sb", "bed-lb"] [workspace.dependencies] protocol = { path = "../crates/protocol" } @@ -17,31 +17,18 @@ embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime-ms", "tick-hz-32_768"] } embassy-futures = { version = "0.1.0"} -# [patch.crates-io] -# embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -# embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -# embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -# embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -# embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -# embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -# embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -# embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -# embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -# embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -# embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } - [patch.crates-io] -embassy-stm32 = {path = "/home/david/Documents/embassy/embassy-stm32" } -embassy-net = {path = "/home/david/Documents/embassy/embassy-net" } -embassy-net-wiznet = {path = "/home/david/Documents/embassy/embassy-net-wiznet" } -embassy-sync = {path = "/home/david/Documents/embassy/embassy-sync" } -embassy-executor = {path = "/home/david/Documents/embassy/embassy-executor" } -embassy-embedded-hal = {path = "/home/david/Documents/embassy/embassy-embedded-hal" } -embassy-futures = {path = "/home/david/Documents/embassy/embassy-futures" } -embassy-time = {path = "/home/david/Documents/embassy/embassy-time" } -embassy-time-driver = {path = "/home/david/Documents/embassy/embassy-time-driver" } -embassy-time-queue-driver = {path = "/home/david/Documents/embassy/embassy-time-queue-driver" } -embassy-usb = {path = "/home/david/Documents/embassy/embassy-usb" } +embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } [workspace.package] rust-version = "1.78" @@ -57,5 +44,5 @@ lto = "fat" opt-level = "s" incremental = false codegen-units = 1 -# note: debug = true is okay - debug-info isn't flashed to the device! +# note: debug = true is okay - debuginfo isn't flashed to the device! debug = true diff --git a/sensor-nodes/bed-sb/src/main.rs b/sensor-nodes/bed-sb/src/main.rs index b8dab86f..801f9afb 100644 --- a/sensor-nodes/bed-sb/src/main.rs +++ b/sensor-nodes/bed-sb/src/main.rs @@ -24,7 +24,6 @@ use {defmt_rtt as _, panic_probe as _}; mod channel; mod comms; mod error_cache; -mod reset_on_error_i2c; mod sensors; mod usb_wrapper; use crate::channel::Queues; @@ -42,11 +41,11 @@ embassy_stm32::bind_interrupts!(struct Irqs { // 84 Mhz clock stm32f401 // 48 Mhz clock for usb fn config() -> Config { - use embassy_stm32::rcc::mux; use embassy_stm32::rcc::{ - AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllPreDiv, PllQDiv, - PllSource, Sysclk, + AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllQDiv, PllPreDiv, PllSource, + Sysclk, }; + use embassy_stm32::rcc::mux; let mut config = Config::default(); config.rcc.hse = Some(Hse { @@ -112,7 +111,6 @@ async fn main(_spawner: Spawner) { Hertz(150_000), i2c::Config::default(), ); - let i2c_1 = reset_on_error_i2c::I2c::new(i2c_1, Hertz(150_000), i2c::Config::default()); let i2c_1: Mutex = Mutex::new(i2c_1); let i2c_3 = I2c::new( @@ -126,7 +124,6 @@ async fn main(_spawner: Spawner) { Hertz(150_000), i2c::Config::default(), ); - let i2c_3 = reset_on_error_i2c::I2c::new(i2c_3, Hertz(150_000), i2c::Config::default()); let i2c_3: Mutex = Mutex::new(i2c_3); let buttons = ButtonInputs { diff --git a/sensor-nodes/bed-sb/src/reset_on_error_i2c.rs b/sensor-nodes/bed-sb/src/reset_on_error_i2c.rs deleted file mode 100644 index a6b1df54..00000000 --- a/sensor-nodes/bed-sb/src/reset_on_error_i2c.rs +++ /dev/null @@ -1,74 +0,0 @@ -use embassy_stm32::i2c::{Config, Error}; -use embassy_stm32::mode::Async; -use embassy_stm32::time::Hertz; -use embedded_hal::i2c::ErrorType; - -pub struct I2c<'d> { - inner: embassy_stm32::i2c::I2c<'d, Async>, - freq: Hertz, - config: Config, -} - -// impl<'d> From> for I2c<'d> { -// fn from(value: embassy_stm32::i2c::I2c<'d, Async>) -> Self { -// Self { inner: value } -// } -// } - -impl<'d> I2c<'d> { - pub fn new(i2c: embassy_stm32::i2c::I2c<'d, Async>, freq: Hertz, config: Config) -> Self { - Self { - inner: i2c, - freq, - config, - } - } -} - -impl ErrorType for I2c<'_> { - type Error = Error; -} - -impl embedded_hal_async::i2c::I2c for I2c<'_> { - async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { - let res = self.inner.read(address, read).await; - if let Err(Error::Arbitration) = res { - self.inner.clear_error(); - self.inner.reset(self.freq, self.config) - } - return res; - } - - async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { - let res = self.inner.write(address, write).await; - if let Err(Error::Arbitration) = res { - self.inner.clear_error(); - } - return res; - } - - async fn write_read( - &mut self, - address: u8, - write: &[u8], - read: &mut [u8], - ) -> Result<(), Self::Error> { - let res = self.inner.write_read(address, write, read).await; - if let Err(Error::Arbitration) = res { - self.inner.clear_error(); - } - return res; - } - - async fn transaction( - &mut self, - address: u8, - operations: &mut [embedded_hal::i2c::Operation<'_>], - ) -> Result<(), Self::Error> { - let res = self.inner.transaction(address, operations).await; - if let Err(Error::Arbitration) = res { - self.inner.clear_error(); - } - return res; - } -} diff --git a/sensor-nodes/bed-sb/src/sensors.rs b/sensor-nodes/bed-sb/src/sensors.rs index 38e14523..9840ae71 100644 --- a/sensor-nodes/bed-sb/src/sensors.rs +++ b/sensor-nodes/bed-sb/src/sensors.rs @@ -1,6 +1,7 @@ use defmt::info; use embassy_embedded_hal::shared_bus::I2cDeviceError; use embassy_futures::join; +use embassy_stm32::i2c::I2c; use embassy_stm32::mode::Async; use embassy_stm32::usart::Uart; use embassy_sync::blocking_mutex::raw::NoopRawMutex; @@ -13,7 +14,6 @@ use sps30_async::Sps30; use crate::channel::Queues; use crate::error_cache::{Error, SensorError}; -use crate::reset_on_error_i2c::I2c; pub mod fast; pub mod retry; pub mod slow; @@ -25,14 +25,13 @@ pub type UartError = embassy_stm32::usart::Error; pub mod concrete_types { use embassy_embedded_hal::shared_bus; + use embassy_stm32::i2c::I2c; use embassy_stm32::mode::Async; use embassy_stm32::usart::{RingBufferedUartRx, UartTx}; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use shared_bus::asynch::i2c::I2cDevice; - use crate::reset_on_error_i2c::I2c; - - pub type ConcreteSharedI2c<'a> = I2cDevice<'a, NoopRawMutex, I2c<'static>>; + pub type ConcreteSharedI2c<'a> = I2cDevice<'a, NoopRawMutex, I2c<'static, Async>>; pub type ConcreteTx<'a> = UartTx<'a, Async>; pub type ConcreteRx<'a> = RingBufferedUartRx<'a>; } @@ -43,8 +42,8 @@ const SPS30_DRIVER_BUF_SIZE: usize = 2 * SPS30_UART_BUF_SIZE; pub async fn init_then_measure( publish: &Queues, orderers: &slow::DriverOrderers, - i2c_1: Mutex>, - i2c_3: Mutex>, + i2c_1: Mutex>, + i2c_3: Mutex>, usart_mhz: Uart<'static, Async>, usart_sps: Uart<'static, Async>, buttons: ButtonInputs, diff --git a/sensor-nodes/bed-sb/src/sensors/retry.rs b/sensor-nodes/bed-sb/src/sensors/retry.rs index 52d1aa38..f25e1046 100644 --- a/sensor-nodes/bed-sb/src/sensors/retry.rs +++ b/sensor-nodes/bed-sb/src/sensors/retry.rs @@ -1,5 +1,7 @@ use bosch_bme680::Bme680; use embassy_embedded_hal::shared_bus; +use embassy_stm32::i2c::I2c; +use embassy_stm32::mode::Async; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; use embassy_time::{Delay, Timer}; @@ -10,7 +12,6 @@ use sht31::SHT31; use super::concrete_types::ConcreteSharedI2c; use crate::error_cache::SensorError; -use crate::reset_on_error_i2c::I2c; mod reinit_on_error; pub use reinit_on_error::{ @@ -21,7 +22,7 @@ mod retry_init; pub use retry_init::Sps30Driver; impl<'a> ReInitableDriver for SHT31> { - type Parts = &'a Mutex>; + type Parts = &'a Mutex>; type Measurement = sht31::Reading; async fn init(parts: Self::Parts) -> Result { @@ -45,7 +46,7 @@ impl<'a> ReInitableDriver for SHT31> { } impl<'a> ReInitableDriver for Bme680, Delay> { - type Parts = &'a Mutex>; + type Parts = &'a Mutex>; type Measurement = bosch_bme680::MeasurementData; async fn init(parts: Self::Parts) -> Result { @@ -67,7 +68,7 @@ impl<'a> ReInitableDriver for Bme680, Delay> { } impl<'a> ReInitableDriver for Max44009> { - type Parts = &'a Mutex>; + type Parts = &'a Mutex>; type Measurement = f32; async fn init(parts: Self::Parts) -> Result { @@ -87,7 +88,7 @@ impl<'a> ReInitableDriver for Max44009> { } impl<'a> ReInitableDriver for Nau7802, Delay> { - type Parts = &'a Mutex>; + type Parts = &'a Mutex>; type Measurement = u32; async fn init(parts: Self::Parts) -> Result { diff --git a/sensor-nodes/rust-toolchain.toml b/sensor-nodes/rust-toolchain.toml deleted file mode 100644 index c17f644e..00000000 --- a/sensor-nodes/rust-toolchain.toml +++ /dev/null @@ -1,6 +0,0 @@ -[toolchain] -channel = "stable" -components = [ "rust-src", "rustfmt", "llvm-tools" ] -targets = [ - "thumbv7em-none-eabihf", -] From 5731a3f8c1e06658d91ab98104f59ebbadfedd34 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 3 Nov 2024 17:31:52 +0100 Subject: [PATCH 354/687] reset node if comms fail twice in a row within a given period --- sensor-nodes/bed-sb/src/channel.rs | 2 +- sensor-nodes/bed-sb/src/comms.rs | 19 ++++++++++++++++-- sensor-nodes/bed-sb/src/main.rs | 31 ++++++++++++++++++++---------- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/sensor-nodes/bed-sb/src/channel.rs b/sensor-nodes/bed-sb/src/channel.rs index 6ad87faf..fb7448f3 100644 --- a/sensor-nodes/bed-sb/src/channel.rs +++ b/sensor-nodes/bed-sb/src/channel.rs @@ -100,7 +100,7 @@ impl Queues { } } -/// Higher prio will be send earlier +/// Higher priority will be send earlier pub struct PriorityValue { priority: u8, pub value: protocol::Reading, diff --git a/sensor-nodes/bed-sb/src/comms.rs b/sensor-nodes/bed-sb/src/comms.rs index 601a1003..2bd52f23 100644 --- a/sensor-nodes/bed-sb/src/comms.rs +++ b/sensor-nodes/bed-sb/src/comms.rs @@ -59,9 +59,14 @@ async fn get_messages<'a>(publish: &Queues, buf: &'a mut [u8]) -> &'a [u8] { } } +pub async fn handle( + usb: UsbHandle<'_>, + publish: &Queues, + driver_orderers: &slow::DriverOrderers, +) -> ! { + const MIN_BETWEEN_COMM_ERRS: Duration = Duration::from_secs(30); + let mut last_error_at = None; - -pub async fn handle(usb: UsbHandle<'_>, publish: &Queues, driver_orderers: &slow::DriverOrderers) { loop { publish.clear().await; @@ -75,6 +80,16 @@ pub async fn handle(usb: UsbHandle<'_>, publish: &Queues, driver_orderers: &slow select::Either::First(e) => warn!("Error while sending messages: {}", e), select::Either::Second(e) => warn!("Error receiving orders: {}", e), }; + + if last_error_at.is_some_and(|at| at.elapsed() < MIN_BETWEEN_COMM_ERRS) { + error!( + "Something is terribly wrong with the connection, \ + resetting entire node" + ); + cortex_m::peripheral::SCB::sys_reset(); + } else { + last_error_at = Some(Instant::now()); + } } } diff --git a/sensor-nodes/bed-sb/src/main.rs b/sensor-nodes/bed-sb/src/main.rs index 801f9afb..1e84c2f5 100644 --- a/sensor-nodes/bed-sb/src/main.rs +++ b/sensor-nodes/bed-sb/src/main.rs @@ -1,8 +1,10 @@ #![no_std] #![no_main] +use core::time::Duration; + use embassy_executor::Spawner; -use embassy_futures::select::{self, Either3}; +use embassy_futures::select::{self, Either4}; use embassy_stm32::exti::ExtiInput; use embassy_stm32::gpio::Pull; use embassy_stm32::i2c::{self, I2c}; @@ -41,11 +43,11 @@ embassy_stm32::bind_interrupts!(struct Irqs { // 84 Mhz clock stm32f401 // 48 Mhz clock for usb fn config() -> Config { + use embassy_stm32::rcc::mux; use embassy_stm32::rcc::{ - AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllQDiv, PllPreDiv, PllSource, - Sysclk, + AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllPreDiv, PllQDiv, + PllSource, Sysclk, }; - use embassy_stm32::rcc::mux; let mut config = Config::default(); config.rcc.hse = Some(Hse { @@ -71,6 +73,7 @@ fn config() -> Config { #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(config()); + let dog = IndependentWatchdog::new(p.IWDG, Duration::from_secs(5).as_micros() as u32); let mut usart_config = usart::Config::default(); usart_config.baudrate = 9600; @@ -169,10 +172,19 @@ async fn main(_spawner: Spawner) { buttons, ); - let res = select::select3(&mut handle_network, init_then_measure, usb_bus.run()).await; + let res = select::select4( + &mut handle_network, + init_then_measure, + usb_bus.run(), + keep_dog_happy(dog), + ) + .await; + let unrecoverable_err = match res { - Either3::First(()) | Either3::Third(()) | Either3::Second(Ok(())) => defmt::unreachable!(), - Either3::Second(Err(err)) => err, + Either4::First(_) | Either4::Second(Ok(())) | Either4::Third(()) | Either4::Fourth(_) => { + defmt::unreachable!() + } + Either4::Second(Err(err)) => err, }; // at this point no other errors have occurred @@ -198,10 +210,9 @@ pub fn usb_config() -> embassy_usb::Config<'static> { config } -async fn keep_dog_happy(mut dog: IndependentWatchdog<'_, IWDG>) { +async fn keep_dog_happy(mut dog: IndependentWatchdog<'_, IWDG>) -> ! { loop { - dog.unleash(); - Timer::after_secs(8).await; + Timer::after_secs(1).await; trace!("petting dog"); dog.pet(); } From 5cd52b435ea20ffba08efeee4e66dbc1539616fb Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 3 Nov 2024 18:40:42 +0100 Subject: [PATCH 355/687] node: reset if comms fail fast consecutivly --- Cargo.lock | 38 +++++++-------- crates/protocol/src/small_bedroom/bed.rs | 6 +++ sensor-nodes/Cargo.lock | 31 ++++++++----- sensor-nodes/bed-sb/Cargo.toml | 2 +- sensor-nodes/bed-sb/src/comms.rs | 59 ++++++++++++++++++------ 5 files changed, 91 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 42d25d3e..13245be4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1630,24 +1630,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" -[[package]] -name = "host" -version = "0.1.0" -dependencies = [ - "clap", - "color-eyre", - "data-server", - "heapless 0.8.0", - "nusb", - "protocol", - "ratelimited-logger", - "tokio", - "tracing", - "tracing-error", - "tracing-subscriber", - "users", -] - [[package]] name = "http" version = "1.1.0" @@ -1831,7 +1813,7 @@ dependencies = [ "proc-macro2", "quote", "strum", - "syn 2.0.79", + "syn 2.0.77", "thiserror", ] @@ -3709,6 +3691,24 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "usb-bridge" +version = "0.1.0" +dependencies = [ + "clap", + "color-eyre", + "data-server", + "heapless 0.8.0", + "nusb", + "protocol", + "ratelimited-logger", + "tokio", + "tracing", + "tracing-error", + "tracing-subscriber", + "users", +] + [[package]] name = "users" version = "0.11.0" diff --git a/crates/protocol/src/small_bedroom/bed.rs b/crates/protocol/src/small_bedroom/bed.rs index 1748d4fb..62139576 100644 --- a/crates/protocol/src/small_bedroom/bed.rs +++ b/crates/protocol/src/small_bedroom/bed.rs @@ -480,6 +480,7 @@ pub enum Affector { Sps30FanClean, MhzZeroPointCalib, Nau7802Calib, + ResetNode, } impl Affector { @@ -509,6 +510,10 @@ impl Affector { name: "things with ac power noise or something", value: ControlValue::Trigger, }], + Affector::ResetNode => vec![Control { + name: "reset the node", + value: ControlValue::Trigger, + }], } } } @@ -520,6 +525,7 @@ impl affector::tree::Tree for Affector { Affector::Sps30FanClean => "Accelerate the fan to maximum speed for 10 seconds in order to blow out the dust accumulated in the fan", Affector::MhzZeroPointCalib => "Set the current co2 value as 400ppm", Affector::Nau7802Calib => "Detect and correct power supply and temperature variations to ADC", + Affector::ResetNode => "Reset the node, this might fix errors such as I2c getting stuck after Arbitration Error", }; affector::tree::Item::Leaf(affector::Info { description }) diff --git a/sensor-nodes/Cargo.lock b/sensor-nodes/Cargo.lock index f5f04cb2..dcb647aa 100644 --- a/sensor-nodes/Cargo.lock +++ b/sensor-nodes/Cargo.lock @@ -333,7 +333,7 @@ dependencies = [ "embassy-time", "embedded-io-async", "embedded-nal-async", - "heapless 0.8.0", + "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "managed", "smoltcp", ] @@ -425,7 +425,7 @@ dependencies = [ "defmt", "embedded-io-async", "futures-util", - "heapless 0.8.0", + "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -443,7 +443,7 @@ dependencies = [ "embedded-hal 1.0.0", "embedded-hal-async", "futures-util", - "heapless 0.8.0", + "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -469,7 +469,7 @@ dependencies = [ "embassy-net-driver-channel", "embassy-sync", "embassy-usb-driver", - "heapless 0.8.0", + "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "ssmarshal", "usbd-hid", ] @@ -746,6 +746,15 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "heapless" +version = "0.8.0" +source = "git+https://github.com/rust-embedded/heapless?rev=0ebca23#0ebca2320970b8a1aa3e58ceba924f8c65385946" +dependencies = [ + "hash32 0.3.1", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.5.0" @@ -780,7 +789,7 @@ dependencies = [ "embedded-hal-bus", "embedded-io-async", "futures", - "heapless 0.8.0", + "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "max44009", "mhzx", "nau7802-async", @@ -836,7 +845,7 @@ version = "0.3.0" dependencies = [ "defmt", "embedded-io-async", - "heapless 0.8.0", + "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "postcard", "serde", ] @@ -978,7 +987,7 @@ name = "protocol" version = "0.1.0" dependencies = [ "defmt", - "heapless 0.8.0", + "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "postcard", "serde", "strum", @@ -1117,7 +1126,7 @@ dependencies = [ "embedded-hal-bus", "embedded-io-async", "futures", - "heapless 0.8.0", + "heapless 0.8.0 (git+https://github.com/rust-embedded/heapless?rev=0ebca23)", "max44009", "mhzx", "nau7802-async", @@ -1139,7 +1148,7 @@ dependencies = [ "byteorder", "cfg-if", "defmt", - "heapless 0.8.0", + "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "managed", ] @@ -1160,7 +1169,7 @@ dependencies = [ "embedded-hal-async", "embedded-io-async", "futures", - "heapless 0.8.0", + "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "postcard", "serde", ] @@ -1296,7 +1305,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98816b1accafbb09085168b90f27e93d790b4bfa19d883466b5e53315b5f06a6" dependencies = [ - "heapless 0.8.0", + "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "portable-atomic", ] diff --git a/sensor-nodes/bed-sb/Cargo.toml b/sensor-nodes/bed-sb/Cargo.toml index ef49f92f..701b3ce6 100644 --- a/sensor-nodes/bed-sb/Cargo.toml +++ b/sensor-nodes/bed-sb/Cargo.toml @@ -29,7 +29,7 @@ embedded-hal-bus = { version = "0.2", features = ["async", "defmt-03"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } -heapless = { version = "0.8", default-features = false } +heapless = { git = "https://github.com/rust-embedded/heapless", version = "0.8", rev = "0ebca23", default-features = false } nb = "1.0.0" rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } static_cell = "2.0.0" diff --git a/sensor-nodes/bed-sb/src/comms.rs b/sensor-nodes/bed-sb/src/comms.rs index 2bd52f23..af22c8ec 100644 --- a/sensor-nodes/bed-sb/src/comms.rs +++ b/sensor-nodes/bed-sb/src/comms.rs @@ -1,6 +1,7 @@ use defmt::{unwrap, warn}; use embassy_futures::select::{self, select}; use embassy_time::{with_timeout, Duration, Instant}; +use heapless::HistoryBuffer; use protocol::small_bedroom::{self, bed}; use protocol::{affector, Affector, ErrorReport, SensorMessage}; @@ -65,7 +66,7 @@ pub async fn handle( driver_orderers: &slow::DriverOrderers, ) -> ! { const MIN_BETWEEN_COMM_ERRS: Duration = Duration::from_secs(30); - let mut last_error_at = None; + let mut last_errors_at: HistoryBuffer<_, 5> = HistoryBuffer::new(); loop { publish.clear().await; @@ -81,29 +82,55 @@ pub async fn handle( select::Either::Second(e) => warn!("Error receiving orders: {}", e), }; - if last_error_at.is_some_and(|at| at.elapsed() < MIN_BETWEEN_COMM_ERRS) { - error!( + let mut error_after = Instant::now(); + if last_errors_at + .oldest_ordered() + .rev() + .copied() + .all(|error: Instant| { + let is_recent = error_after.duration_since(error) < MIN_BETWEEN_COMM_ERRS; + error_after = error; + is_recent + }) + { + defmt::error!( "Something is terribly wrong with the connection, \ - resetting entire node" + 5 errors occured each within 30 seconds of the previous. \ + Resetting entire node" ); cortex_m::peripheral::SCB::sys_reset(); } else { - last_error_at = Some(Instant::now()); + last_errors_at.write(Instant::now()); } } } fn affector_list() -> affector::ListMessage<5> { let mut list = affector::ListMessage::<5>::empty(); - unwrap!(list.values.push(Affector::SmallBedroom( - protocol::small_bedroom::Affector::Bed(bed::Affector::Sps30FanClean), - ))); - unwrap!(list.values.push(Affector::SmallBedroom( - protocol::small_bedroom::Affector::Bed(bed::Affector::MhzZeroPointCalib), - ))); - unwrap!(list.values.push(Affector::SmallBedroom( - protocol::small_bedroom::Affector::Bed(bed::Affector::Nau7802Calib), - ))); + unwrap!( + list.values.push(Affector::SmallBedroom( + protocol::small_bedroom::Affector::Bed(bed::Affector::Sps30FanClean), + )), + "list is long enough" + ); + unwrap!( + list.values.push(Affector::SmallBedroom( + protocol::small_bedroom::Affector::Bed(bed::Affector::MhzZeroPointCalib), + )), + "list is long enough" + ); + unwrap!( + list.values.push(Affector::SmallBedroom( + protocol::small_bedroom::Affector::Bed(bed::Affector::Nau7802Calib), + )), + "list is long enough" + ); + unwrap!( + list.values.push(Affector::SmallBedroom( + protocol::small_bedroom::Affector::Bed(bed::Affector::ResetNode), + )), + "list is long enough" + ); list } @@ -148,6 +175,10 @@ async fn receive_orders(usb: UsbReceiver<'_>, driver_orderers: &slow::DriverOrde bed::Affector::Sps30FanClean => { driver_orderers.sps.send(()).await; } + bed::Affector::ResetNode => { + defmt::info!("resetting node as orderd via affector"); + cortex_m::peripheral::SCB::sys_reset(); + } } } } From 905f640b0e7c52714cebeb812c24150289ed126b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 4 Nov 2024 14:43:37 +0100 Subject: [PATCH 356/687] adds watchdog to data-server that resets node's with sustained errors --- crates/data-server/src/main.rs | 3 +- crates/data-server/src/server.rs | 2 + crates/data-server/src/server/watch.rs | 101 +++++++++++++++++++++++ crates/protocol/src/large_bedroom/bed.rs | 9 +- 4 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 crates/data-server/src/server/watch.rs diff --git a/crates/data-server/src/main.rs b/crates/data-server/src/main.rs index 98da55a1..e298acf1 100644 --- a/crates/data-server/src/main.rs +++ b/crates/data-server/src/main.rs @@ -40,8 +40,9 @@ async fn main() -> Result<()> { let (tx, rx) = mpsc::channel(2000); select! { e = server::client::handle(subscribe_addr, tx.clone(), affectors.clone()) => e, - e = server::handle_nodes(update_addr, &tx, affectors) => e, + e = server::handle_nodes(update_addr, &tx, affectors.clone()) => e, e = server::spread_updates(rx) => e, + _ = server::node_watchdog(affectors, &tx) => Ok(()), } } diff --git a/crates/data-server/src/server.rs b/crates/data-server/src/server.rs index 0a2f9677..53e84fbd 100644 --- a/crates/data-server/src/server.rs +++ b/crates/data-server/src/server.rs @@ -9,10 +9,12 @@ mod affector; pub mod client; mod data_source; mod subscribe; +mod watch; pub use affector::Registar as AffectorRegistar; pub use data_source::handle_nodes; pub use subscribe::spread_updates; +pub use watch::node_watchdog; use crate::api::subscriber::{self, SubMessage}; diff --git a/crates/data-server/src/server/watch.rs b/crates/data-server/src/server/watch.rs new file mode 100644 index 00000000..7cc1df56 --- /dev/null +++ b/crates/data-server/src/server/watch.rs @@ -0,0 +1,101 @@ +use crate::api::subscriber::SubMessage; +use std::time::Duration; + +use super::{AffectorRegistar, Event}; +use protocol::reading::tree::Tree; +use protocol::{large_bedroom, small_bedroom, Affector, Reading}; +use tokio::sync::mpsc; +use tokio::time::{timeout_at, Instant}; + +const CHECK_INTERVAL: Duration = Duration::from_secs(5); +const MIN_RESET_INTERVAL: Duration = Duration::from_secs(600); + +#[derive(Default)] +struct LastSeen { + map: Vec<(Reading, Instant)>, + last_reset: Vec<(Affector, Instant)>, +} + +impl LastSeen { + fn update(&mut self, reading: Reading) { + if let Some((_, time)) = self.map.iter_mut().find(|(r, _)| r.is_same_as(&reading)) { + *time = Instant::now(); + } else { + self.map.push((reading, Instant::now())); + } + } + + fn mark_reset(&mut self, affector: Affector) { + if let Some((_, last)) = self + .last_reset + .iter_mut() + .find(|(a, _)| a.is_same_as(&affector)) + { + *last = Instant::now(); + } else { + self.last_reset.push((affector, Instant::now())); + } + } + + fn check_and_bite(&mut self, registar: &AffectorRegistar) { + let to_reset = self.map.iter().filter(|(reading, last_seen)| { + let max_interval = reading.leaf().device.info().max_sample_interval; + last_seen.elapsed() > max_interval * 10 + }); + + let mut reset_commands: Vec<_> = to_reset + .filter_map(|(reading, _)| match reading { + Reading::LargeBedroom(large_bedroom::Reading::Bed(_)) => { + Some(Affector::LargeBedroom(large_bedroom::Affector::Bed( + large_bedroom::bed::Affector::ResetNode, + ))) + } + Reading::LargeBedroom(large_bedroom::Reading::Desk(_)) => None, + Reading::SmallBedroom(small_bedroom::Reading::Bed(_)) => { + Some(Affector::SmallBedroom(small_bedroom::Affector::Bed( + small_bedroom::bed::Affector::ResetNode, + ))) + } + Reading::SmallBedroom(small_bedroom::Reading::Desk(_)) => None, + Reading::SmallBedroom(small_bedroom::Reading::ButtonPanel(_)) => None, + }) + .filter(|affector| { + let last_reset = self + .last_reset + .iter() + .find(|(a, _)| a == affector) + .map(|(_, at)| at) + .copied(); + !last_reset.is_some_and(|last_reset| last_reset.elapsed() < MIN_RESET_INTERVAL) + }) + .collect(); + reset_commands.dedup_by(|a, b| a.is_same_as(b)); + for cmd in reset_commands { + if registar.activate(cmd).is_ok() { + self.mark_reset(cmd); + } + } + } +} + +pub async fn node_watchdog(registar: AffectorRegistar, sub_tx: &mpsc::Sender) -> ! { + let (tx, mut rx) = mpsc::channel(128); + sub_tx + .send(Event::NewSub { tx }) + .await + .expect("handle_sub_should_still_run"); + + let mut next_check = tokio::time::Instant::now() + CHECK_INTERVAL; + let mut last_seen = LastSeen::default(); + loop { + match timeout_at(next_check, rx.recv()).await { + Ok(None) => unreachable!("subscribers should never be dropped"), + Ok(Some(SubMessage::Reading(r))) => last_seen.update(r), + Ok(Some(_)) => (), + Err(_timeout) => { + last_seen.check_and_bite(®istar); + next_check = Instant::now() + CHECK_INTERVAL; + } + } + } +} diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 26537fc8..e7b1b66d 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -517,6 +517,7 @@ pub enum Affector { Nau7802LeftCalib, Nau7802RightCalib, RgbLed { red: u8, green: u8, blue: u8 }, + ResetNode, } impl Affector { @@ -529,6 +530,7 @@ impl Affector { (Affector::Nau7802LeftCalib, Affector::Nau7802LeftCalib) => true, (Affector::Nau7802RightCalib, Affector::Nau7802RightCalib) => true, (Affector::RgbLed { .. }, Affector::RgbLed { .. }) => true, + (Affector::ResetNode, Affector::ResetNode) => true, _ => false, } } @@ -578,6 +580,10 @@ impl Affector { }, }, ], + Affector::ResetNode => vec![Control { + name: "reset the node", + value: ControlValue::Trigger, + }], } } } @@ -590,7 +596,8 @@ impl affector::tree::Tree for Affector { Affector::MhzZeroPointCalib => "Set the current co2 value as 400ppm", Affector::Nau7802LeftCalib | Affector::Nau7802RightCalib => "Detect and correct power supply and temperature variations to ADC", - Affector::RgbLed {..} => "Set color & power of the RGB led at the top of the bed post" + Affector::RgbLed {..} => "Set color & power of the RGB led at the top of the bed post", + Affector::ResetNode => "Reset the node, this might fix errors such as I2c getting stuck after Arbitration Error", }; affector::tree::Item::Leaf(affector::Info { description }) From 681578ae5a4b995bc1974a7e870146458e0dcc20 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 4 Nov 2024 21:10:29 +0100 Subject: [PATCH 357/687] add warning --- crates/data-server/src/server/watch.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/data-server/src/server/watch.rs b/crates/data-server/src/server/watch.rs index 7cc1df56..8c7e3a56 100644 --- a/crates/data-server/src/server/watch.rs +++ b/crates/data-server/src/server/watch.rs @@ -6,6 +6,7 @@ use protocol::reading::tree::Tree; use protocol::{large_bedroom, small_bedroom, Affector, Reading}; use tokio::sync::mpsc; use tokio::time::{timeout_at, Instant}; +use tracing::warn; const CHECK_INTERVAL: Duration = Duration::from_secs(5); const MIN_RESET_INTERVAL: Duration = Duration::from_secs(600); @@ -71,6 +72,7 @@ impl LastSeen { .collect(); reset_commands.dedup_by(|a, b| a.is_same_as(b)); for cmd in reset_commands { + warn!("resetting node with problematic reading, using: {cmd:?}"); if registar.activate(cmd).is_ok() { self.mark_reset(cmd); } From 2fcdaa77dda0d613c1fb5c61728ef90fb4f7e5ae Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 3 Nov 2024 12:58:16 +0100 Subject: [PATCH 358/687] Add temp_to_xy fn using colorimetry crate --- Cargo.lock | 134 ++++++++++++++++++ crates/zigbee-bridge/Cargo.toml | 1 + crates/zigbee-bridge/src/lib.rs | 1 + crates/zigbee-bridge/src/lights/conversion.rs | 32 ++++- 4 files changed, 166 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9a7a0aae..3521a66a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -102,6 +102,15 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + [[package]] name = "arraydeque" version = "0.5.1" @@ -505,6 +514,12 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "bytemuck" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" + [[package]] name = "byteorder" version = "1.5.0" @@ -679,6 +694,37 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "colored" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" +dependencies = [ + "lazy_static", + "windows-sys 0.48.0", +] + +[[package]] +name = "colorimetry" +version = "0.0.2" +source = "git+https://github.com/harbik/colorimetry#f55b1953653a8a264c54648ef3b6a3d5cfce9f14" +dependencies = [ + "approx", + "colored", + "js-sys", + "libm", + "nalgebra", + "num-traits", + "once_cell", + "paste", + "strum", + "strum_macros", + "thiserror", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", +] + [[package]] name = "compact_str" version = "0.8.0" @@ -1962,6 +2008,12 @@ version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + [[package]] name = "libredox" version = "0.1.3" @@ -2091,6 +2143,16 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +[[package]] +name = "matrixmultiply" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" +dependencies = [ + "autocfg", + "rawpointer", +] + [[package]] name = "maybe-async-cfg" version = "0.2.4" @@ -2196,6 +2258,33 @@ dependencies = [ "bufstream", ] +[[package]] +name = "nalgebra" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b" +dependencies = [ + "approx", + "matrixmultiply", + "nalgebra-macros", + "num-complex", + "num-rational", + "num-traits", + "simba", + "typenum", +] + +[[package]] +name = "nalgebra-macros" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.86", +] + [[package]] name = "nb" version = "1.1.0" @@ -2776,6 +2865,12 @@ dependencies = [ "bitflags 2.6.0", ] +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + [[package]] name = "redox_syscall" version = "0.2.16" @@ -3000,6 +3095,15 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "safe_arch" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3460605018fdc9612bce72735cba0d27efbcd9904780d44c7e3a9948f96148a" +dependencies = [ + "bytemuck", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -3165,6 +3269,19 @@ dependencies = [ "libc", ] +[[package]] +name = "simba" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa" +dependencies = [ + "approx", + "num-complex", + "num-traits", + "paste", + "wide", +] + [[package]] name = "slab" version = "0.4.9" @@ -3646,6 +3763,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "tz-rs" version = "0.6.14" @@ -3907,6 +4030,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "wide" +version = "0.7.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b828f995bf1e9622031f8009f8481a85406ce1f4d4588ff746d872043e855690" +dependencies = [ + "bytemuck", + "safe_arch", +] + [[package]] name = "winapi" version = "0.3.9" @@ -4150,6 +4283,7 @@ dependencies = [ name = "zigbee-bridge" version = "0.1.0" dependencies = [ + "colorimetry", "rumqttc", "serde_json", "thiserror", diff --git a/crates/zigbee-bridge/Cargo.toml b/crates/zigbee-bridge/Cargo.toml index 29507621..d23baa8e 100644 --- a/crates/zigbee-bridge/Cargo.toml +++ b/crates/zigbee-bridge/Cargo.toml @@ -7,6 +7,7 @@ license.workspace = true authors.workspace = true [dependencies] +colorimetry = { git = "https://github.com/harbik/colorimetry", features = ["cct"] } # default-features enable rustls which we do not need and drags in # C dependencies making deployment a chore rumqttc = { version = "0.24.0", default-features = false } diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 2285286a..accfd5a7 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -19,6 +19,7 @@ mod tests { use crate::lights::Controller; use std::time::Duration; + #[ignore] #[tokio::test] async fn change_all_lights() { let controller = Controller::start_bridge(); diff --git a/crates/zigbee-bridge/src/lights/conversion.rs b/crates/zigbee-bridge/src/lights/conversion.rs index 80345fd6..f57fed36 100644 --- a/crates/zigbee-bridge/src/lights/conversion.rs +++ b/crates/zigbee-bridge/src/lights/conversion.rs @@ -1,3 +1,8 @@ +use colorimetry::{cct::CCT, xyz::XYZ}; + +// Deviation from black body, must be between -0.05 and 0.05 +const DUV_IKEA: f64 = -0.002; + #[must_use] pub fn mired_to_kelvin(mired: usize) -> usize { 1_000_000 / mired @@ -19,6 +24,29 @@ pub fn denormalize(brightness: f64) -> u8 { (brightness * 254.).round() as u8 } -pub(crate) fn temp_to_xy(color_temp: usize) -> (f64, f64) { - (1.0, 1.0) +/// 1000K < color_temp < 1_000_000K +pub fn temp_to_xy(color_temp: usize) -> (f64, f64) { + // TODO: use table from black body deviation measurements + let cct = CCT::try_new(color_temp as f64, DUV_IKEA).unwrap(); + let xyz: XYZ = cct.try_into().unwrap(); + + xyz_to_xy(xyz) +} + +fn xyz_to_xy(xyz: XYZ) -> (f64, f64) { + let [x, y, z] = xyz.values(); + (x / (x + y + z), y / (x + y + z)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn temp_to_xy_works() { + dbg!(temp_to_xy(2200)); + dbg!(temp_to_xy(2500)); + dbg!(temp_to_xy(3000)); + dbg!(temp_to_xy(4000)); + } } From ad87b67c6be4b60518c7efb6a3e0682dc739f7fb Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 5 Nov 2024 15:50:33 +0100 Subject: [PATCH 359/687] Add new lights in kitchen --- crates/brain/src/controller/mod.rs | 10 +++++----- crates/zigbee-bridge/src/lib.rs | 8 +++++++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 1dc2f550..171311e1 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -45,9 +45,7 @@ impl RestrictedSystem { self.system .lights_new .set_color_temp(name, mired_to_kelvin(ct.into())); - self.system - .lights_new - .set_brightness(name, normalize(bri)); + self.system.lights_new.set_brightness(name, normalize(bri)); } } @@ -107,12 +105,14 @@ pub fn start( let restricted = RestrictedSystem { system: system.clone(), - allowed_lights: vec![ + allowed_lights: vec![], + allowed_lights_new: vec![ "kitchen:ceiling", "kitchen:hood_left", "kitchen:hood_right", + "kitchen:fridge", + "kitchen:hallway", ], - allowed_lights_new: vec!["kitchen:fridge", "kitchen:hallway"], }; tasks.spawn(rooms::kitchen::run(rx3, sender, restricted)); diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index accfd5a7..7c8d8add 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -11,7 +11,13 @@ pub mod lights; const QOS: QoS = QoS::AtLeastOnce; const MQTT_IP: &str = "192.168.1.43"; const MQTT_PORT: u16 = 1883; -const LIGHTS: [&str; 2] = ["kitchen:fridge", "kitchen:hallway"]; +const LIGHTS: [&str; 5] = [ + "kitchen:fridge", + "kitchen:hallway", + "kitchen:hood_left", + "kitchen:hood_right", + "kitchen:ceiling", +]; #[cfg(test)] mod tests { From 3624eff40eccb28c2d3eaaee630fbdd1ead24121 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 6 Nov 2024 01:36:59 +0100 Subject: [PATCH 360/687] data-server log reading that trigger reset long with reset --- crates/data-server/src/server/watch.rs | 41 +++++++++++++++----------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/crates/data-server/src/server/watch.rs b/crates/data-server/src/server/watch.rs index 8c7e3a56..7c56ce61 100644 --- a/crates/data-server/src/server/watch.rs +++ b/crates/data-server/src/server/watch.rs @@ -45,34 +45,39 @@ impl LastSeen { }); let mut reset_commands: Vec<_> = to_reset - .filter_map(|(reading, _)| match reading { - Reading::LargeBedroom(large_bedroom::Reading::Bed(_)) => { - Some(Affector::LargeBedroom(large_bedroom::Affector::Bed( - large_bedroom::bed::Affector::ResetNode, - ))) + .filter_map(|(reading, _)| { + match reading { + Reading::LargeBedroom(large_bedroom::Reading::Bed(_)) => { + Some(Affector::LargeBedroom(large_bedroom::Affector::Bed( + large_bedroom::bed::Affector::ResetNode, + ))) + } + Reading::LargeBedroom(large_bedroom::Reading::Desk(_)) => None, + Reading::SmallBedroom(small_bedroom::Reading::Bed(_)) => { + Some(Affector::SmallBedroom(small_bedroom::Affector::Bed( + small_bedroom::bed::Affector::ResetNode, + ))) + } + Reading::SmallBedroom(small_bedroom::Reading::Desk(_)) => None, + Reading::SmallBedroom(small_bedroom::Reading::ButtonPanel(_)) => None, } - Reading::LargeBedroom(large_bedroom::Reading::Desk(_)) => None, - Reading::SmallBedroom(small_bedroom::Reading::Bed(_)) => { - Some(Affector::SmallBedroom(small_bedroom::Affector::Bed( - small_bedroom::bed::Affector::ResetNode, - ))) - } - Reading::SmallBedroom(small_bedroom::Reading::Desk(_)) => None, - Reading::SmallBedroom(small_bedroom::Reading::ButtonPanel(_)) => None, + .map(|reset_cmd| (reading, reset_cmd)) }) - .filter(|affector| { + .filter(|(_, reset_cmd)| { let last_reset = self .last_reset .iter() - .find(|(a, _)| a == affector) + .find(|(a, _)| a == reset_cmd) .map(|(_, at)| at) .copied(); !last_reset.is_some_and(|last_reset| last_reset.elapsed() < MIN_RESET_INTERVAL) }) + .map(|(reading, reset_cmd)| (reading.clone(), reset_cmd)) .collect(); - reset_commands.dedup_by(|a, b| a.is_same_as(b)); - for cmd in reset_commands { - warn!("resetting node with problematic reading, using: {cmd:?}"); + reset_commands.dedup_by(|(_, a), (_, b)| a.is_same_as(b)); + + for (reading, cmd) in reset_commands { + warn!("resetting node with problematic reading: {reading:?}, using: {cmd:?}"); if registar.activate(cmd).is_ok() { self.mark_reset(cmd); } From 53335aa4e3dfc00203cd98181a195fd0aa5cc26b Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Wed, 6 Nov 2024 11:02:15 +0100 Subject: [PATCH 361/687] Tweak light values --- crates/brain/src/controller/rooms/small_bedroom.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index bd24db7e..a21cb814 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -82,8 +82,8 @@ async fn update(system: &mut RestrictedSystem) { pub(crate) fn optimal_ct_bri() -> (u16, u8) { let now = local_now(); match now.hour() { - 9..17 => (270, u8::MAX), - 17..20 => (300, u8::MAX), + 9..17 => (280, u8::MAX), + 17..20 => (330, u8::MAX), 20..22 => (400, 220), 22.. | 0..9 => (500, 100), } From 0c643d097a149f476afc33c37de43253031c1615 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Wed, 6 Nov 2024 11:09:12 +0100 Subject: [PATCH 362/687] Switch light colors over to XY when setting temp Fixes crash when state from bridge doesn't contain XY --- crates/brain/src/controller/mod.rs | 10 +-- crates/zigbee-bridge/src/lights/state.rs | 90 ++++++++++++------------ 2 files changed, 49 insertions(+), 51 deletions(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 1dc2f550..5959468c 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -45,9 +45,7 @@ impl RestrictedSystem { self.system .lights_new .set_color_temp(name, mired_to_kelvin(ct.into())); - self.system - .lights_new - .set_brightness(name, normalize(bri)); + self.system.lights_new.set_brightness(name, normalize(bri)); } } @@ -107,12 +105,14 @@ pub fn start( let restricted = RestrictedSystem { system: system.clone(), - allowed_lights: vec![ + allowed_lights: vec![], + allowed_lights_new: vec![ + "kitchen:fridge", + "kitchen:hallway", "kitchen:ceiling", "kitchen:hood_left", "kitchen:hood_right", ], - allowed_lights_new: vec!["kitchen:fridge", "kitchen:hallway"], }; tasks.spawn(rooms::kitchen::run(rx3, sender, restricted)); diff --git a/crates/zigbee-bridge/src/lights/state.rs b/crates/zigbee-bridge/src/lights/state.rs index c6acf7b2..db0a67cb 100644 --- a/crates/zigbee-bridge/src/lights/state.rs +++ b/crates/zigbee-bridge/src/lights/state.rs @@ -2,15 +2,15 @@ use std::io; use serde_json::{json, Value}; -use crate::lights::{conversion::{ - kelvin_to_mired, mired_to_kelvin, normalize, temp_to_xy, -}, denormalize}; +use crate::lights::{ + conversion::{normalize, temp_to_xy}, + denormalize, +}; #[derive(Debug, Clone)] pub(crate) struct Lamp { pub(crate) brightness: f64, - pub(crate) color_temp_kelvin: usize, - pub(crate) color_xy: (f64, f64), + pub(crate) color_xy: Option<(f64, f64)>, pub(crate) on: bool, } @@ -18,8 +18,7 @@ impl Default for Lamp { fn default() -> Self { Self { brightness: 1.0, - color_temp_kelvin: 2700, - color_xy: temp_to_xy(2700), + color_xy: Some(temp_to_xy(2700)), on: false, } } @@ -28,13 +27,17 @@ impl Default for Lamp { impl PartialEq for Lamp { fn eq(&self, other: &Self) -> bool { let d_bright = (self.brightness - other.brightness).abs(); - let d_color_temp = self.color_temp_kelvin - other.color_temp_kelvin; - let d_color_x = (self.color_xy.0 - other.color_xy.0).abs(); - let d_color_y = (self.color_xy.1 - other.color_xy.1).abs(); + let (d_color_x, d_color_y) = match (self.color_xy, other.color_xy) { + (Some(self_xy), Some(other_xy)) => ( + (self_xy.0 - other_xy.0).abs(), + (self_xy.1 - other_xy.1).abs(), + ), + // If either Lamp has no xy set, they are different + _ => return false, + }; self.on == other.on && d_bright < 1. / 250. - && d_color_temp < 20 && d_color_x < 0.01 && d_color_y < 0.01 } @@ -67,19 +70,23 @@ impl TryInto for &[u8] { let json: Value = serde_json::from_slice(self)?; let map = json.as_object().ok_or(invalid_err("Object"))?; - let color = get_key(map, "color")? - .as_object() - .ok_or(invalid_err("Object"))?; - let color_x = get_key(color, "x")? - .as_number() - .ok_or(invalid_err("Number"))? - .as_f64() - .expect("Should return Some if not using arbitrary precision"); - let color_y = get_key(color, "y")? - .as_number() - .ok_or(invalid_err("Number"))? - .as_f64() - .expect("Should return Some if not using arbitrary precision"); + let color_xy = match get_key(map, "color") { + Ok(color) => { + let color = color.as_object().ok_or(invalid_err("Object"))?; + let color_x = get_key(color, "x")? + .as_number() + .ok_or(invalid_err("Number"))? + .as_f64() + .expect("Should be Some if not using arbitrary precision"); + let color_y = get_key(color, "y")? + .as_number() + .ok_or(invalid_err("Number"))? + .as_f64() + .expect("Should be Some if not using arbitrary precision"); + Some((color_x, color_y)) + } + Err(_) => None, + }; let brightness: u8 = get_key(map, "brightness")? .as_number() @@ -89,14 +96,6 @@ impl TryInto for &[u8] { .try_into() .map_err(|_| invalid_err("u8"))?; - let color_temp_mired = get_key(map, "color_temp")? - .as_number() - .ok_or(invalid_err("Number"))? - .as_u64() - .ok_or(invalid_err("u64"))? - .try_into() - .expect("usize should be u64"); - let state = get_key(map, "state")? .as_str() .ok_or(invalid_err("String"))?; @@ -109,8 +108,7 @@ impl TryInto for &[u8] { Ok(Lamp { #[allow(clippy::cast_precision_loss)] brightness: normalize(brightness), - color_temp_kelvin: mired_to_kelvin(color_temp_mired), - color_xy: (color_x, color_y), + color_xy, on, }) } @@ -122,8 +120,10 @@ impl Lamp { match change { Change::On(on) => new_state.on = on, Change::Brightness(bri) => new_state.brightness = bri, - Change::ColorTemp(temp) => new_state.color_temp_kelvin = temp, - Change::ColorXy(xy) => new_state.color_xy = xy, + Change::ColorTemp(temp) => { + new_state.color_xy = Some(temp_to_xy(temp)); + } + Change::ColorXy(xy) => new_state.color_xy = Some(xy), } new_state } @@ -131,18 +131,16 @@ impl Lamp { pub(crate) fn to_payloads(&self) -> Vec { let state = if self.on { "ON" } else { "OFF" }; #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - let color_temp_mired = kelvin_to_mired(self.color_temp_kelvin); - - [ + let mut payloads = vec![ json!({ "state": state }), json!({ "brightness": denormalize(self.brightness) }), - json!({ "color_temp": color_temp_mired }), - // TODO: make sure this doesn't override temp / always use this - // json!({ "color_xy": self.color_xy }), - ] - .into_iter() - .map(|x| x.to_string()) - .collect() + ]; + + if let Some(color_xy) = self.color_xy { + payloads.push(json!({ "color_xy": color_xy })); + } + + payloads.into_iter().map(|x| x.to_string()).collect() } } From 70ffadde7cd7fd3f5798cf1f6ee3fd868760e419 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Wed, 6 Nov 2024 12:24:00 +0100 Subject: [PATCH 363/687] Get devices and models from bridge --- .../zigbee-bridge/src/lights/cached_bridge.rs | 4 +- .../src/lights/cached_bridge/poll.rs | 93 +++++++++++++++++-- 2 files changed, 86 insertions(+), 11 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 211a1a38..82b73514 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -21,12 +21,14 @@ pub(crate) async fn run(mut change_receiver: mpsc::UnboundedReceiver<(String, Ch options.set_max_packet_size(2_usize.pow(28), 10240); let known_states = RwLock::new(HashMap::new()); + let devices = RwLock::new(HashMap::new()); let mut needed_states = HashMap::new(); // Reconnecting to broker is handled by Eventloop::poll let (client, eventloop) = AsyncClient::new(options.clone(), 128); let mqtt = Mqtt::new(client); + mqtt.subscribe("zigbee2mqtt/bridge/devices").await.unwrap(); for light in LIGHTS { mqtt.subscribe(&format!("zigbee2mqtt/{light}")) .await @@ -34,7 +36,7 @@ pub(crate) async fn run(mut change_receiver: mpsc::UnboundedReceiver<(String, Ch mqtt.request_state(light).await; } - let poll_mqtt = poll::poll_mqtt(eventloop, &known_states); + let poll_mqtt = poll::poll_mqtt(eventloop, &known_states, &devices); let handle_changes = changes::handle( &mut change_receiver, &mqtt, diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 743201c0..4e191ecf 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -1,49 +1,122 @@ -use std::collections::HashMap; +use std::{collections::HashMap, time::Duration}; use rumqttc::{Event, EventLoop, Incoming}; -use tokio::sync::RwLock; +use serde_json::Value; +use tokio::{sync::RwLock, time::sleep}; use crate::lights::state::Lamp; pub(super) async fn poll_mqtt( mut eventloop: EventLoop, known_states: &RwLock>, + devices: &RwLock>, ) -> ! { loop { let message = match eventloop.poll().await { Ok(message) => message, Err(err) => { println!("Error while polling: {err}"); + sleep(Duration::from_millis(100)).await; continue; } }; - if let Some((light_name, new_known_state)) = extract_state_update(message) { - let mut known_states = known_states.write().await; - known_states.insert(light_name, new_known_state); + match parse_message(message) { + Message::StateUpdate((light_name, new_known_state)) => { + let mut known_states = known_states.write().await; + known_states.insert(light_name, new_known_state); + } + Message::Devices(new_devices) => { + let mut devices = devices.write().await; + if *devices != new_devices { + dbg!(&new_devices); + } + *devices = new_devices + } + Message::Other => (), } } } -fn extract_state_update(message: Event) -> Option<(String, Lamp)> { +fn parse_message(message: Event) -> Message { match message { Event::Incoming(incoming) => match incoming { Incoming::ConnAck(_) | Incoming::PubAck(_) | Incoming::PingResp - | Incoming::SubAck(_) => None, + | Incoming::SubAck(_) => Message::Other, + Incoming::Publish(message) + if message.topic == "zigbee2mqtt/bridge/devices" => + { + let json: Value = + serde_json::from_slice(&message.payload).unwrap(); + let list = json.as_array().unwrap(); + let devices: HashMap = list + .into_iter() + .map(parse_device) + .filter(|d| d.0 != "Coordinator") + .collect(); + + Message::Devices(devices) + } Incoming::Publish(message) => { let topic: Vec<_> = message.topic.split('/').collect(); let name = topic[1].to_string(); let data = &(*message.payload); - Some((name, data.try_into().unwrap())) + Message::StateUpdate((name, data.try_into().unwrap())) } other => { dbg!(other); - None + Message::Other } }, - Event::Outgoing(_) => None, + Event::Outgoing(_) => Message::Other, } } + +#[derive(Debug)] +enum Message { + StateUpdate((String, Lamp)), + Devices(HashMap), + Other, +} + +#[derive(Debug, PartialEq, Eq)] +pub(super) enum Model { + TradfriCandle, + TradfriE27, + TradfriE14, + HueGen4, + TradfriOther(String), + Other(String), +} + +fn parse_device(device: &Value) -> (String, Model) { + let properties = device.as_object().unwrap(); + + let friendly_name = properties + .get("friendly_name") + .unwrap() + .as_str() + .unwrap() + .to_owned(); + let model_id = properties + .get("model_id") + .map(Value::as_str) + .map(Option::unwrap); + + let model = match model_id { + Some("TRADFRI bulb E14 WS candle 470lm") => Model::TradfriCandle, + Some("TRADFRI bulb E27 CWS globe 806lm") => Model::TradfriE27, + Some("TRADFRI bulb E14 CWS globe 806lm") => Model::TradfriE14, + Some("LCT001") => Model::HueGen4, + Some(id) if id.to_lowercase().contains("tradfri") => { + Model::TradfriOther(id.to_owned()) + } + Some(id) => Model::Other(id.to_owned()), + None => Model::Other("".to_owned()), + }; + + (friendly_name, model) +} From 44afb25af9fabe17ebccdcfae69b1519a6d2b63b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 7 Nov 2024 18:41:37 +0100 Subject: [PATCH 364/687] update data-server byteseries dep --- Cargo.lock | 865 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 575 insertions(+), 290 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 13245be4..17716b7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,18 +23,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if 1.0.0", - "once_cell", - "version_check", - "zerocopy", -] - [[package]] name = "aho-corasick" version = "1.1.3" @@ -67,9 +55,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -82,36 +70,36 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -162,7 +150,7 @@ dependencies = [ "async-task", "concurrent-queue", "fastrand 2.1.1", - "futures-lite 2.3.0", + "futures-lite 2.4.0", "slab", ] @@ -177,7 +165,7 @@ dependencies = [ "async-io", "async-lock", "blocking", - "futures-lite 2.3.0", + "futures-lite 2.4.0", "once_cell", ] @@ -191,7 +179,7 @@ dependencies = [ "cfg-if 1.0.0", "concurrent-queue", "futures-io", - "futures-lite 2.3.0", + "futures-lite 2.4.0", "parking", "polling", "rustix", @@ -225,7 +213,7 @@ dependencies = [ "blocking", "cfg-if 1.0.0", "event-listener 5.3.1", - "futures-lite 2.3.0", + "futures-lite 2.4.0", "rustix", "tracing", ] @@ -264,7 +252,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-io", - "futures-lite 2.3.0", + "futures-lite 2.4.0", "gloo-timers", "kv-log-macro", "log", @@ -305,13 +293,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.82" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -331,15 +319,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.7.5" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ "async-trait", "axum-core", @@ -367,9 +355,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", @@ -380,21 +368,20 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", ] [[package]] name = "axum-macros" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" +checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ - "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -448,18 +435,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - [[package]] name = "blocking" version = "1.6.1" @@ -469,7 +444,7 @@ dependencies = [ "async-channel 2.3.1", "async-task", "futures-io", - "futures-lite 2.3.0", + "futures-lite 2.4.0", "piper", ] @@ -537,14 +512,14 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "byteseries" version = "0.7.1" -source = "git+https://github.com/dvdsk/byteseries#edc1c89c580c35b411de68feab4f665303d4c5cc" +source = "git+https://github.com/dvdsk/byteseries#eb057c6363548fa1fc2fbe5a89395b81238152f5" dependencies = [ "arraydeque", "itertools", @@ -579,9 +554,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.21" +version = "1.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70" dependencies = [ "shlex", ] @@ -615,9 +590,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.17" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -625,9 +600,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.17" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -637,14 +612,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -699,9 +674,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "compact_str" @@ -738,6 +713,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "cordyceps" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec10f0a762d93c4498d2e97a333805cb6250d60bead623f71d8034f9a4152ba3" +dependencies = [ + "loom", + "tracing", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -748,6 +733,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -765,9 +760,9 @@ dependencies = [ [[package]] name = "critical-section" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "crossbeam-channel" @@ -825,7 +820,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if 1.0.0", - "hashbrown", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core 0.9.10", @@ -904,7 +899,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -946,7 +941,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -1017,6 +1012,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "dns-parser" version = "0.8.0" @@ -1036,7 +1042,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -1105,7 +1111,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -1125,7 +1131,7 @@ dependencies = [ "quote", "rustversion", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -1211,11 +1217,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "flate2" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide 0.8.0", @@ -1227,6 +1239,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -1246,17 +1264,11 @@ dependencies = [ "winapi", ] -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1269,10 +1281,11 @@ dependencies = [ [[package]] name = "futures-buffered" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fa130f3777d0d4b0993653c20bc433026d3290627693c4ed1b18dd237357ab" +checksum = "34acda8ae8b63fbe0b2195c998b180cff89a8212fb2622a78b572a9f1c6f7684" dependencies = [ + "cordyceps", "diatomic-waker", "futures-core", "pin-project-lite", @@ -1280,9 +1293,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1290,11 +1303,11 @@ dependencies = [ [[package]] name = "futures-concurrency" -version = "7.6.1" +version = "7.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b14ac911e85d57c5ea6eef76d7b4d4a3177ecd15f4bea2e61927e9e3823e19f" +checksum = "d9b724496da7c26fcce66458526ce68fc2ecf4aaaa994281cf322ded5755520c" dependencies = [ - "bitvec", + "fixedbitset", "futures-buffered", "futures-core", "futures-lite 1.13.0", @@ -1305,15 +1318,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1322,9 +1335,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" @@ -1343,9 +1356,9 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +checksum = "3f1fa2f9765705486b33fd2acf1577f8ec449c2ba1f318ae5447697b7c08d210" dependencies = [ "fastrand 2.1.1", "futures-core", @@ -1356,26 +1369,26 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-timer" @@ -1385,9 +1398,9 @@ checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1410,6 +1423,19 @@ dependencies = [ "byteorder", ] +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows", +] + [[package]] name = "gethostname" version = "0.5.0" @@ -1482,9 +1508,9 @@ dependencies = [ [[package]] name = "gpiocdev" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5119c89eccee09c4f6e9ca2b112aea1cd80bac31cd29169f171a48ae5552d1c" +checksum = "4ea1a9715542f84bc7b67cbb01c02ed3a72a919750b7d8611cc5bd684449386e" dependencies = [ "futures", "gpiocdev-uapi", @@ -1507,9 +1533,9 @@ dependencies = [ [[package]] name = "gpiocdev-uapi" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a02357253f833a6ce4e93f17e8dd3e169c941ea71b83d442ed9c55f784045204" +checksum = "1d5c09e8bbed8a03e31b0fabf273da9486940091820a088215cd9fc24a1523d1" dependencies = [ "bitflags 2.6.0", "ioctl-sys", @@ -1561,9 +1587,16 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" dependencies = [ - "ahash", "allocator-api2", + "equivalent", + "foldhash", ] [[package]] @@ -1606,12 +1639,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" @@ -1666,9 +1693,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1694,9 +1721,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", @@ -1714,9 +1741,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", @@ -1727,7 +1754,6 @@ dependencies = [ "pin-project-lite", "socket2", "tokio", - "tower", "tower-service", "tracing", ] @@ -1767,14 +1793,143 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec 1.13.2", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec 1.13.2", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", ] [[package]] @@ -1785,35 +1940,35 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.1", ] [[package]] name = "indextree" -version = "4.7.2" +version = "4.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6f1b8dbc8f1e5a0f45e05b9293c42cbab79086baeb3e914d3936f8149edc4f" +checksum = "91f3e68a01402c3404bfb739079f38858325bc7ad775b07922278a8a415b1a3f" dependencies = [ "indextree-macros", ] [[package]] name = "indextree-macros" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357230c23ee6024223892ce0de19888a04139ca5bb94f5becb04d38b75a4bccf" +checksum = "477e2e7ec7379407656293ff74902caea786a1dda427ca1f84b923c4fdeb7659" dependencies = [ "either", "itertools", "proc-macro2", "quote", "strum", - "syn 2.0.77", + "syn 2.0.87", "thiserror", ] @@ -1824,7 +1979,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" dependencies = [ "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -1854,9 +2009,9 @@ checksum = "8bd11f3a29434026f5ff98c730b668ba74b1033637b8817940b54d040696133c" [[package]] name = "ipnet" -version = "2.10.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is_terminal_polyfill" @@ -1881,9 +2036,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jiff" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a45489186a6123c128fdf6016183fcfab7113e1820eb813127e036e287233fb" +checksum = "b9d9d414fc817d3e3d62b2598616733f76c4cc74fbac96069674739b881295c8" dependencies = [ "jiff-tzdb-platform", "serde", @@ -1907,9 +2062,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -1931,9 +2086,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" [[package]] name = "libredox" @@ -1969,6 +2124,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "lock_api" version = "0.4.12" @@ -2018,13 +2179,26 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if 1.0.0", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + [[package]] name = "lru" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown", + "hashbrown 0.15.1", ] [[package]] @@ -2036,6 +2210,30 @@ dependencies = [ "libc", ] +[[package]] +name = "manyhow" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b33efb3ca6d3b07393750d4030418d594ab1139cee518f0dc88db70fec873587" +dependencies = [ + "manyhow-macros", + "proc-macro2", + "quote", + "syn 1.0.109", + "syn 2.0.87", +] + +[[package]] +name = "manyhow-macros" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495" +dependencies = [ + "proc-macro-utils", + "proc-macro2", + "quote", +] + [[package]] name = "matchers" version = "0.1.0" @@ -2053,11 +2251,11 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "maybe-async-cfg" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e083394889336bc66a4eaf1011ffbfa74893e910f902a9f271fa624c61e1b2" +checksum = "8dbfaa67a76e2623580df07d6bb5e7956c0a4bae4b418314083a9c619bd66627" dependencies = [ - "proc-macro-error", + "manyhow", "proc-macro2", "pulldown-cmark", "quote", @@ -2342,14 +2540,16 @@ dependencies = [ [[package]] name = "nusb" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d8beeee5c0ad012e1eaca540f5610d09a3af58ec435537d511b67e0be36ea66" +checksum = "b58c5baaf1902712d1c7ef734165376bf1e05f0ebfd00755fd4c4762c06b0c1a" dependencies = [ "atomic-waker", - "core-foundation", + "core-foundation 0.9.4", "core-foundation-sys", + "futures-core", "io-kit-sys", + "libc", "log", "once_cell", "rustix", @@ -2368,9 +2568,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "option-ext" @@ -2439,7 +2639,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.5.4", + "redox_syscall 0.5.7", "smallvec 1.13.2", "windows-targets 0.52.6", ] @@ -2458,29 +2658,29 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -2501,9 +2701,9 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.3" +version = "3.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ "cfg-if 1.0.0", "concurrent-queue", @@ -2516,9 +2716,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" [[package]] name = "postcard" @@ -2585,11 +2785,22 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-utils" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071" +dependencies = [ + "proc-macro2", + "quote", + "smallvec 1.13.2", +] + [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -2656,12 +2867,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - [[package]] name = "radix_trie" version = "0.2.1" @@ -2735,9 +2940,9 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "11.1.0" +version = "11.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb9ee317cfe3fbd54b36a511efc1edd42e216903c9cd575e686dd68a2ba90d8d" +checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0" dependencies = [ "bitflags 2.6.0", ] @@ -2753,9 +2958,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.4" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] @@ -2773,14 +2978,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -2794,13 +2999,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -2811,15 +3016,15 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.7" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ "base64 0.22.1", "bytes", @@ -2905,9 +3110,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" dependencies = [ "bitflags 2.6.0", "errno", @@ -2918,9 +3123,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "rustyline" @@ -2952,6 +3157,12 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -2993,29 +3204,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -3050,12 +3261,13 @@ dependencies = [ [[package]] name = "serialport" -version = "4.5.1" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ba776acc8c373b9175829206229366273225436845c04f9c20aab8099960e2e" +checksum = "7331eefcaafaa382c0df95bcd84068f0b3e3c215c300750dde2316e9b8806ed5" dependencies = [ "bitflags 2.6.0", "cfg-if 1.0.0", + "core-foundation 0.10.0", "core-foundation-sys", "io-kit-sys", "mach2", @@ -3243,11 +3455,11 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "rustversion", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -3263,9 +3475,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -3299,6 +3511,17 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "sysfs_gpio" version = "0.6.2" @@ -3308,36 +3531,30 @@ dependencies = [ "nix 0.23.2", ] -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - [[package]] name = "temp-dir" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f227968ec00f0e5322f9b8173c7a0cbcff6181a0a5b28e9892491c286277231" +checksum = "bc1ee6eef34f12f765cb94725905c6312b6610ab2b0940889cfe58dae7bc3c72" [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -3381,25 +3598,20 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.8.0" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", @@ -3421,7 +3633,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -3465,14 +3677,14 @@ dependencies = [ [[package]] name = "tower" -version = "0.4.13" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" dependencies = [ "futures-core", "futures-util", - "pin-project", "pin-project-lite", + "sync_wrapper 0.1.2", "tokio", "tower-layer", "tower-service", @@ -3509,7 +3721,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -3617,18 +3829,9 @@ dependencies = [ [[package]] name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-ident" @@ -3636,15 +3839,6 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-segmentation" version = "1.12.0" @@ -3682,9 +3876,9 @@ checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "url" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" dependencies = [ "form_urlencoded", "idna", @@ -3719,6 +3913,18 @@ dependencies = [ "log", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -3733,9 +3939,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" +checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" [[package]] name = "version_check" @@ -3786,9 +3992,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if 1.0.0", "once_cell", @@ -3797,24 +4003,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -3824,9 +4030,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3834,28 +4040,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -3883,6 +4089,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -4071,12 +4286,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "wyz" -version = "0.5.1" +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ - "tap", + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure 0.13.1", ] [[package]] @@ -4097,5 +4339,48 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure 0.13.1", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", ] From 73a90abe66290d263dbbe88aa5faa2ed88636707 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 8 Nov 2024 12:56:50 +0100 Subject: [PATCH 365/687] Add tracing to zigbee, demote info spam to trace, autofmt --- Cargo.lock | 1 + crates/brain/src/controller/rooms/kitchen.rs | 2 +- crates/brain/src/controller/rooms/small_bedroom.rs | 10 ++++++++-- crates/zigbee-bridge/Cargo.toml | 1 + crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs | 1 + 5 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3521a66a..24951906 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4288,4 +4288,5 @@ dependencies = [ "serde_json", "thiserror", "tokio", + "tracing", ] diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index 35196e58..1b47b365 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -78,7 +78,7 @@ pub async fn run( async fn update(system: &mut RestrictedSystem) { let (new_ct, new_bri) = small_bedroom::optimal_ct_bri(); system.all_lamps_ct(new_ct, new_bri).await; - tracing::info!("updated lamps"); + tracing::trace!("updated lamps"); } fn _optimal_ct_bri() -> (u16, u8) { diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index a21cb814..e2849ee2 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -17,11 +17,17 @@ enum State { const INTERVAL: Duration = Duration::from_secs(5); trait RecvFiltered { - async fn recv_filter_mapped(&mut self, filter_map: impl Fn(Event) -> Option) -> T; + async fn recv_filter_mapped( + &mut self, + filter_map: impl Fn(Event) -> Option, + ) -> T; } impl RecvFiltered for broadcast::Receiver { - async fn recv_filter_mapped(&mut self, filter_map: impl Fn(Event) -> Option) -> T { + async fn recv_filter_mapped( + &mut self, + filter_map: impl Fn(Event) -> Option, + ) -> T { loop { let event = self.recv().await.unwrap(); if let Some(relevant) = filter_map(event) { diff --git a/crates/zigbee-bridge/Cargo.toml b/crates/zigbee-bridge/Cargo.toml index d23baa8e..f9b68fba 100644 --- a/crates/zigbee-bridge/Cargo.toml +++ b/crates/zigbee-bridge/Cargo.toml @@ -14,3 +14,4 @@ rumqttc = { version = "0.24.0", default-features = false } serde_json = "1.0.132" thiserror.workspace = true tokio = { workspace = true, features = ["sync"] } +tracing = { workspace = true } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index 81e72a85..0486e912 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -45,6 +45,7 @@ impl Mqtt { ) -> Result<(), ClientError> { let topic = format!("zigbee2mqtt/{friendly_name}/set"); + tracing::trace!("Sending payload {payload} to lamp {friendly_name}"); self.publish(&topic, payload).await?; Ok(()) } From 67c6620c5a4d04a67cdbfbe138207542d43681cb Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 8 Nov 2024 12:57:25 +0100 Subject: [PATCH 366/687] Use Kelvin and float in small bedroom light settings --- crates/brain/src/controller/rooms/small_bedroom.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index e2849ee2..07befa09 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -4,6 +4,7 @@ use futures_concurrency::future::Race; use futures_util::FutureExt; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; +use zigbee_bridge::lights::{denormalize, kelvin_to_mired}; use crate::controller::{local_now, Event, RestrictedSystem}; @@ -87,12 +88,13 @@ async fn update(system: &mut RestrictedSystem) { pub(crate) fn optimal_ct_bri() -> (u16, u8) { let now = local_now(); - match now.hour() { - 9..17 => (280, u8::MAX), - 17..20 => (330, u8::MAX), - 20..22 => (400, 220), - 22.. | 0..9 => (500, 100), - } + let (temp, bri) = match now.hour() { + 9..17 => (3500, 1.0), + 17..20 => (3000, 1.0), + 20..22 => (2500, 0.85), + 22.. | 0..9 => (2000, 0.4), + }; + (kelvin_to_mired(temp).try_into().unwrap(), denormalize(bri)) } // fn handle_event(e: RelevantEvent) { From abd29749ef62be91e6d410d2858fe88ab50cdad9 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 8 Nov 2024 12:58:10 +0100 Subject: [PATCH 367/687] Fix kitchen lights flashing Taking into account color bulb yes/no, sending actually correct json for color_xy, using Option instead of Default for Lamp --- crates/zigbee-bridge/src/lib.rs | 2 +- .../zigbee-bridge/src/lights/cached_bridge.rs | 1 + .../src/lights/cached_bridge/changes.rs | 10 +- .../src/lights/cached_bridge/mqtt.rs | 5 +- .../src/lights/cached_bridge/poll.rs | 12 +- crates/zigbee-bridge/src/lights/state.rs | 164 +++++++++++++----- 6 files changed, 129 insertions(+), 65 deletions(-) diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 7c8d8add..0fc7c898 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -8,7 +8,7 @@ use rumqttc::QoS; pub mod lights; -const QOS: QoS = QoS::AtLeastOnce; +const QOS: QoS = QoS::AtMostOnce; const MQTT_IP: &str = "192.168.1.43"; const MQTT_PORT: u16 = 1883; const LIGHTS: [&str; 5] = [ diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 82b73514..29c7e3e8 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -42,6 +42,7 @@ pub(crate) async fn run(mut change_receiver: mpsc::UnboundedReceiver<(String, Ch &mqtt, &known_states, &mut needed_states, + &devices, ); tokio::select! { diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index cb5d5ae9..496cc85b 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -4,7 +4,7 @@ use tokio::sync::{mpsc, RwLock}; use tokio::time::{sleep, timeout}; use super::{mqtt::Mqtt, CHANGE_TIMEOUT, WAIT_FOR_INIT_STATES}; -use crate::lights::state::{Change, Lamp}; +use crate::lights::state::{Change, Lamp, Model}; use crate::LIGHTS; pub(super) async fn handle( @@ -12,6 +12,7 @@ pub(super) async fn handle( mqtt: &Mqtt, known_states: &RwLock>, needed_states: &mut HashMap, + devices: &RwLock>, ) -> ! { // Give the initial known states a chance to be fetched sleep(WAIT_FOR_INIT_STATES).await; @@ -19,13 +20,14 @@ pub(super) async fn handle( if let Ok(change) = timeout(CHANGE_TIMEOUT, change_receiver.recv()).await { apply_change(change, known_states, needed_states).await; } - send_all(known_states, needed_states, mqtt).await; + send_all(known_states, needed_states, devices, mqtt).await; } } async fn send_all( known_states: &RwLock>, needed_states: &mut HashMap, + devices: &RwLock>, mqtt: &Mqtt, ) { let known_states = known_states.read().await; @@ -36,8 +38,10 @@ async fn send_all( let known = known_states.get(light_name); if Some(needed) != known { + let devices = devices.read().await; + let model = devices.get(light_name).expect("Should be registered"); // Ignore errors because we will retry if the state hasn't changed - let _ = mqtt.send_new_state(light_name, needed).await; + let _ = mqtt.send_new_state(light_name, needed, model).await; } } } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index 0486e912..ccd7996d 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -1,7 +1,7 @@ use rumqttc::{AsyncClient, ClientError}; use serde_json::json; -use crate::lights::state::Lamp; +use crate::lights::state::{Lamp, Model}; use crate::QOS; pub(super) struct Mqtt { @@ -31,8 +31,9 @@ impl Mqtt { &self, light_name: &str, needed_state: &Lamp, + model: &Model, ) -> Result<(), ClientError> { - for payload in needed_state.to_payloads() { + for payload in needed_state.to_payloads(model) { self.set(light_name, &payload).await?; } Ok(()) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 4e191ecf..b0ffa7dc 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -4,7 +4,7 @@ use rumqttc::{Event, EventLoop, Incoming}; use serde_json::Value; use tokio::{sync::RwLock, time::sleep}; -use crate::lights::state::Lamp; +use crate::lights::state::{Lamp, Model}; pub(super) async fn poll_mqtt( mut eventloop: EventLoop, @@ -82,16 +82,6 @@ enum Message { Other, } -#[derive(Debug, PartialEq, Eq)] -pub(super) enum Model { - TradfriCandle, - TradfriE27, - TradfriE14, - HueGen4, - TradfriOther(String), - Other(String), -} - fn parse_device(device: &Value) -> (String, Model) { let properties = device.as_object().unwrap(); diff --git a/crates/zigbee-bridge/src/lights/state.rs b/crates/zigbee-bridge/src/lights/state.rs index db0a67cb..68f2d772 100644 --- a/crates/zigbee-bridge/src/lights/state.rs +++ b/crates/zigbee-bridge/src/lights/state.rs @@ -4,42 +4,42 @@ use serde_json::{json, Value}; use crate::lights::{ conversion::{normalize, temp_to_xy}, - denormalize, + denormalize, kelvin_to_mired, mired_to_kelvin, }; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] pub(crate) struct Lamp { - pub(crate) brightness: f64, + pub(crate) brightness: Option, + pub(crate) color_temp_k: Option, pub(crate) color_xy: Option<(f64, f64)>, - pub(crate) on: bool, -} - -impl Default for Lamp { - fn default() -> Self { - Self { - brightness: 1.0, - color_xy: Some(temp_to_xy(2700)), - on: false, - } - } + pub(crate) on: Option, } impl PartialEq for Lamp { fn eq(&self, other: &Self) -> bool { - let d_bright = (self.brightness - other.brightness).abs(); + let d_bright = match (self.brightness, other.brightness) { + (Some(self_bri), Some(other_bri)) => (self_bri - other_bri).abs(), + _ => 1.0, + }; let (d_color_x, d_color_y) = match (self.color_xy, other.color_xy) { (Some(self_xy), Some(other_xy)) => ( (self_xy.0 - other_xy.0).abs(), (self_xy.1 - other_xy.1).abs(), ), - // If either Lamp has no xy set, they are different - _ => return false, + // If either Lamp has no xy set, xy is "different" (so we use temp) + // so this needs to be over threshold + _ => (1.0, 1.0), + }; + let d_color_temp = match (self.color_temp_k, other.color_temp_k) { + (Some(self_temp), Some(other_temp)) => { + self_temp.abs_diff(other_temp) + } + _ => 5000, }; - self.on == other.on - && d_bright < 1. / 250. - && d_color_x < 0.01 - && d_color_y < 0.01 + let color_equal = + (d_color_x < 0.01 && d_color_y < 0.01) || d_color_temp < 50; + self.on == other.on && d_bright < 1. / 250. && color_equal } } @@ -70,6 +70,20 @@ impl TryInto for &[u8] { let json: Value = serde_json::from_slice(self)?; let map = json.as_object().ok_or(invalid_err("Object"))?; + let color_temp_mired = match get_key(map, "color_temp") { + Ok(temp) => { + let color_temp: usize = temp + .as_number() + .ok_or(invalid_err("Number"))? + .as_u64() + .ok_or(invalid_err("u64"))? + .try_into() + .expect("usize should be u64"); + Some(color_temp) + } + Err(_) => None, + }; + let color_xy = match get_key(map, "color") { Ok(color) => { let color = color.as_object().ok_or(invalid_err("Object"))?; @@ -88,26 +102,41 @@ impl TryInto for &[u8] { Err(_) => None, }; - let brightness: u8 = get_key(map, "brightness")? - .as_number() - .ok_or(invalid_err("Number"))? - .as_u64() - .ok_or(invalid_err("u64"))? - .try_into() - .map_err(|_| invalid_err("u8"))?; - - let state = get_key(map, "state")? - .as_str() - .ok_or(invalid_err("String"))?; - let on = match state.to_lowercase().as_str() { - "on" => true, - "off" => false, - other => return Err(invalid_err(&format!("on/off bool: {other}"))), + let brightness = match get_key(map, "brightness") { + Ok(bri) => { + let bri: u8 = bri + .as_number() + .ok_or(invalid_err("Number"))? + .as_u64() + .ok_or(invalid_err("u64"))? + .try_into() + .map_err(|_| invalid_err("u8"))?; + Some(bri) + } + Err(_) => None, + }; + + let on = match get_key(map, "state") { + Ok(on) => { + let state = on.as_str().ok_or(invalid_err("String"))?; + let on = match state.to_lowercase().as_str() { + "on" => true, + "off" => false, + other => { + return Err(invalid_err(&format!( + "on/off bool: {other}" + ))) + } + }; + Some(on) + } + Err(_) => None, }; Ok(Lamp { #[allow(clippy::cast_precision_loss)] - brightness: normalize(brightness), + brightness: brightness.map(normalize), + color_temp_k: color_temp_mired.map(mired_to_kelvin), color_xy, on, }) @@ -118,9 +147,10 @@ impl Lamp { pub(crate) fn apply(&self, change: Change) -> Lamp { let mut new_state = self.clone(); match change { - Change::On(on) => new_state.on = on, - Change::Brightness(bri) => new_state.brightness = bri, + Change::On(on) => new_state.on = Some(on), + Change::Brightness(bri) => new_state.brightness = Some(bri), Change::ColorTemp(temp) => { + new_state.color_temp_k = Some(temp); new_state.color_xy = Some(temp_to_xy(temp)); } Change::ColorXy(xy) => new_state.color_xy = Some(xy), @@ -128,16 +158,32 @@ impl Lamp { new_state } - pub(crate) fn to_payloads(&self) -> Vec { - let state = if self.on { "ON" } else { "OFF" }; - #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - let mut payloads = vec![ - json!({ "state": state }), - json!({ "brightness": denormalize(self.brightness) }), - ]; + pub(crate) fn to_payloads(&self, model: &Model) -> Vec { + let mut payloads = vec![]; + match self.on { + Some(true) => payloads.push(json!({ "state": "ON" })), + Some(false) => payloads.push(json!({ "state": "OFF" })), + None => (), + }; + + match self.brightness { + Some(bri) => { + payloads.push(json!({ "brightness": denormalize(bri) })) + } + None => (), + } - if let Some(color_xy) = self.color_xy { - payloads.push(json!({ "color_xy": color_xy })); + if model.is_color_lamp() { + if let Some(color_xy) = self.color_xy { + payloads.push( + json!({ "color": {"x": color_xy.0, "y": color_xy.1} }), + ); + } + } else { + if let Some(color_temp) = self.color_temp_k { + payloads + .push(json!({ "color_temp": kelvin_to_mired(color_temp) })); + } } payloads.into_iter().map(|x| x.to_string()).collect() @@ -151,3 +197,25 @@ pub(crate) enum Change { ColorTemp(usize), ColorXy((f64, f64)), } + +#[derive(Debug, PartialEq, Eq)] +pub(crate) enum Model { + TradfriCandle, + TradfriE27, + TradfriE14, + HueGen4, + TradfriOther(String), + Other(String), +} + +impl Model { + pub(crate) fn is_color_lamp(&self) -> bool { + use Model as M; + match self { + M::TradfriE27 | M::TradfriE14 | M::HueGen4 => true, + M::TradfriCandle => false, + // We assume no so that things at least don't break + M::TradfriOther(_) | M::Other(_) => false, + } + } +} From 1a3469b44991c92dc5ff2e47a7712ef74fb6d3af Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 8 Nov 2024 13:07:28 +0100 Subject: [PATCH 368/687] Rename Lamp to LampState and mod state to lamp --- crates/zigbee-bridge/src/lights.rs | 6 +++--- crates/zigbee-bridge/src/lights/cached_bridge.rs | 2 +- .../src/lights/cached_bridge/changes.rs | 16 ++++++++-------- .../src/lights/cached_bridge/mqtt.rs | 4 ++-- .../src/lights/cached_bridge/poll.rs | 6 +++--- .../src/lights/{state.rs => lamp.rs} | 16 ++++++++-------- 6 files changed, 25 insertions(+), 25 deletions(-) rename crates/zigbee-bridge/src/lights/{state.rs => lamp.rs} (95%) diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index c74263d4..54359147 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -1,18 +1,18 @@ #![allow(clippy::missing_panics_doc)] use tokio::sync::mpsc; -use self::state::Change; +use self::lamp::Change; // TODO: make private once system is ported pub use conversion::{kelvin_to_mired, mired_to_kelvin, normalize, denormalize}; mod cached_bridge; mod conversion; -mod state; +mod lamp; #[derive(Debug, Clone)] pub struct Controller { - change_sender: mpsc::UnboundedSender<(String, state::Change)>, + change_sender: mpsc::UnboundedSender<(String, lamp::Change)>, } impl Controller { diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 29c7e3e8..6d94206d 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -5,7 +5,7 @@ use rumqttc::{AsyncClient, MqttOptions}; use tokio::sync::{mpsc, RwLock}; use self::mqtt::Mqtt; -use crate::lights::state::Change; +use crate::lights::lamp::Change; use crate::{LIGHTS, MQTT_IP, MQTT_PORT}; mod changes; diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index 496cc85b..5b1904df 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -4,14 +4,14 @@ use tokio::sync::{mpsc, RwLock}; use tokio::time::{sleep, timeout}; use super::{mqtt::Mqtt, CHANGE_TIMEOUT, WAIT_FOR_INIT_STATES}; -use crate::lights::state::{Change, Lamp, Model}; +use crate::lights::lamp::{Change, LampState, Model}; use crate::LIGHTS; pub(super) async fn handle( change_receiver: &mut mpsc::UnboundedReceiver<(String, Change)>, mqtt: &Mqtt, - known_states: &RwLock>, - needed_states: &mut HashMap, + known_states: &RwLock>, + needed_states: &mut HashMap, devices: &RwLock>, ) -> ! { // Give the initial known states a chance to be fetched @@ -25,8 +25,8 @@ pub(super) async fn handle( } async fn send_all( - known_states: &RwLock>, - needed_states: &mut HashMap, + known_states: &RwLock>, + needed_states: &mut HashMap, devices: &RwLock>, mqtt: &Mqtt, ) { @@ -48,8 +48,8 @@ async fn send_all( async fn apply_change( change: Option<(String, Change)>, - known_states: &RwLock>, - needed_states: &mut HashMap, + known_states: &RwLock>, + needed_states: &mut HashMap, ) { let (light_name, change) = change.expect("Channel should never close"); let known_states = known_states.read().await; @@ -60,7 +60,7 @@ async fn apply_change( Some(known_state) => needed_states .entry(light_name.clone()) .or_insert(known_state.clone()), - None => &mut Lamp::default(), + None => &mut LampState::default(), }, }; diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index ccd7996d..bab92759 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -1,7 +1,7 @@ use rumqttc::{AsyncClient, ClientError}; use serde_json::json; -use crate::lights::state::{Lamp, Model}; +use crate::lights::lamp::{LampState, Model}; use crate::QOS; pub(super) struct Mqtt { @@ -30,7 +30,7 @@ impl Mqtt { pub(super) async fn send_new_state( &self, light_name: &str, - needed_state: &Lamp, + needed_state: &LampState, model: &Model, ) -> Result<(), ClientError> { for payload in needed_state.to_payloads(model) { diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index b0ffa7dc..a13d9df2 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -4,11 +4,11 @@ use rumqttc::{Event, EventLoop, Incoming}; use serde_json::Value; use tokio::{sync::RwLock, time::sleep}; -use crate::lights::state::{Lamp, Model}; +use crate::lights::lamp::{LampState, Model}; pub(super) async fn poll_mqtt( mut eventloop: EventLoop, - known_states: &RwLock>, + known_states: &RwLock>, devices: &RwLock>, ) -> ! { loop { @@ -77,7 +77,7 @@ fn parse_message(message: Event) -> Message { #[derive(Debug)] enum Message { - StateUpdate((String, Lamp)), + StateUpdate((String, LampState)), Devices(HashMap), Other, } diff --git a/crates/zigbee-bridge/src/lights/state.rs b/crates/zigbee-bridge/src/lights/lamp.rs similarity index 95% rename from crates/zigbee-bridge/src/lights/state.rs rename to crates/zigbee-bridge/src/lights/lamp.rs index 68f2d772..f9db11b0 100644 --- a/crates/zigbee-bridge/src/lights/state.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -8,14 +8,14 @@ use crate::lights::{ }; #[derive(Debug, Clone, Default)] -pub(crate) struct Lamp { +pub(crate) struct LampState { pub(crate) brightness: Option, pub(crate) color_temp_k: Option, pub(crate) color_xy: Option<(f64, f64)>, pub(crate) on: Option, } -impl PartialEq for Lamp { +impl PartialEq for LampState { fn eq(&self, other: &Self) -> bool { let d_bright = match (self.brightness, other.brightness) { (Some(self_bri), Some(other_bri)) => (self_bri - other_bri).abs(), @@ -43,12 +43,12 @@ impl PartialEq for Lamp { } } -impl Eq for Lamp {} +impl Eq for LampState {} -impl TryInto for &[u8] { +impl TryInto for &[u8] { type Error = io::Error; - fn try_into(self) -> Result { + fn try_into(self) -> Result { fn get_key<'a>( map: &'a serde_json::Map, key: &str, @@ -133,7 +133,7 @@ impl TryInto for &[u8] { Err(_) => None, }; - Ok(Lamp { + Ok(LampState { #[allow(clippy::cast_precision_loss)] brightness: brightness.map(normalize), color_temp_k: color_temp_mired.map(mired_to_kelvin), @@ -143,8 +143,8 @@ impl TryInto for &[u8] { } } -impl Lamp { - pub(crate) fn apply(&self, change: Change) -> Lamp { +impl LampState { + pub(crate) fn apply(&self, change: Change) -> LampState { let mut new_state = self.clone(); match change { Change::On(on) => new_state.on = Some(on), From c3d4a18c3f5bc10bd068cd6fdfd936a36b89258a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 8 Nov 2024 13:58:55 +0100 Subject: [PATCH 369/687] crash if affectorlist does not fit + wait for queue space for high prio items --- sensor-nodes/bed-sb/src/comms.rs | 41 ++++++++++++++------- sensor-nodes/bed-sb/src/usb_wrapper.rs | 50 +++++++++++++++++++++----- 2 files changed, 70 insertions(+), 21 deletions(-) diff --git a/sensor-nodes/bed-sb/src/comms.rs b/sensor-nodes/bed-sb/src/comms.rs index af22c8ec..d9332679 100644 --- a/sensor-nodes/bed-sb/src/comms.rs +++ b/sensor-nodes/bed-sb/src/comms.rs @@ -7,15 +7,21 @@ use protocol::{affector, Affector, ErrorReport, SensorMessage}; use crate::channel::{PriorityValue, QueueItem, Queues}; use crate::sensors::slow; -use crate::usb_wrapper::{UsbHandle, UsbReceiver, UsbSender}; +use crate::usb_wrapper::{NoSpaceInQueue, UsbHandle, UsbReceiver, UsbSender}; pub(crate) type SensMsg = SensorMessage<10>; -async fn collect_pending(publish: &Queues, reading: PriorityValue) -> SensorMessage<10> { +type IsLowPrio = bool; + +/// send as soon as we find a high priority message +async fn collect_pending( + publish: &Queues, + reading: PriorityValue, +) -> (IsLowPrio, SensorMessage<10>) { let mut msg = SensMsg::default(); - let low_priority = reading.low_priority(); + let mut is_low_priority = reading.low_priority(); unwrap!(msg.values.push(reading.value)); - if low_priority { + if is_low_priority { let deadline = Instant::now() + Duration::from_millis(200); while msg.space_left() { let until = deadline.saturating_duration_since(Instant::now()); @@ -24,6 +30,7 @@ async fn collect_pending(publish: &Queues, reading: PriorityValue) -> SensorMess unwrap!(msg.values.push(new.value)); } Ok(new) => { + is_low_priority = false; unwrap!(msg.values.push(new.value)); break; } @@ -38,24 +45,24 @@ async fn collect_pending(publish: &Queues, reading: PriorityValue) -> SensorMess unwrap!(msg.values.push(next.value)); } } - msg + (is_low_priority, msg) } -async fn get_messages<'a>(publish: &Queues, buf: &'a mut [u8]) -> &'a [u8] { +async fn get_messages<'a>(publish: &Queues, buf: &'a mut [u8]) -> (IsLowPrio, &'a [u8]) { let next = publish.receive().await; match next { QueueItem::Reading(reading) => { - let msg = collect_pending(publish, reading).await; + let (is_low_prio, msg) = collect_pending(publish, reading).await; let encoded_len = msg.encode_slice(&mut buf[1..]).len(); buf[0] = protocol::Msg::<0>::READINGS; - &buf[..=encoded_len] + (is_low_prio, &buf[..=encoded_len]) } QueueItem::Error(error) => { let error = protocol::small_bedroom::Error::Bed(error.into()); let error = protocol::Error::SmallBedroom(error); let encoded_len = ErrorReport::new(error).encode_slice(&mut buf[1..]).len(); buf[0] = protocol::Msg::<0>::ERROR_REPORT; - &buf[..=encoded_len] + (true, &buf[..=encoded_len]) } } } @@ -140,11 +147,21 @@ async fn send_messages(usb: UsbSender<'_>, publish: &Queues) { let encoded_len = affector_list().encode_slice(&mut buf[1..]).len(); buf[0] = protocol::Msg::<5>::AFFECTOR_LIST; let to_send = &buf[..=encoded_len]; - usb.send(to_send).await; + defmt::unwrap!( + usb.send(to_send).await, + "first message, queue should still be empty & large enough" + ); loop { - let to_send = get_messages(publish, &mut buf).await; - usb.send(to_send).await; + let (is_low_prio, to_send) = get_messages(publish, &mut buf).await; + while let Err(NoSpaceInQueue) = usb.send(to_send).await { + if is_low_prio { + defmt::trace!("dropping low priority package because queue is full"); + break; + } else { + usb.wait_till_queue_free().await; + } + } } } diff --git a/sensor-nodes/bed-sb/src/usb_wrapper.rs b/sensor-nodes/bed-sb/src/usb_wrapper.rs index 2d6c3027..865fe20f 100644 --- a/sensor-nodes/bed-sb/src/usb_wrapper.rs +++ b/sensor-nodes/bed-sb/src/usb_wrapper.rs @@ -1,6 +1,7 @@ use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::channel::Channel; use embassy_sync::mutex::Mutex; +use embassy_sync::signal::Signal; use embassy_usb::control::{InResponse, OutResponse, Recipient, RequestType}; use embassy_usb::types::InterfaceNumber; use embassy_usb::UsbDevice; @@ -15,6 +16,7 @@ pub(crate) type RecvItem = heapless::Vec; pub struct UsbControlHandler<'a> { pub if_num: Option, send_queue: &'a Mutex>, + ready_to_send: &'a Signal, receive_queue: &'a Channel, } @@ -94,13 +96,25 @@ impl embassy_usb::Handler for UsbControlHandler<'_> { *byte = 0; // end of encoded data } } + self.ready_to_send.signal(()); Some(InResponse::Accepted(buf)) } } +// struct SendQueue{ +// free: Channel, +// bytes: heapless::Deque +// } +// +// impl SendQueue { +// fn send(&self, to_send) { +// } +// } + pub struct UsbHandle<'a> { send_queue: &'a Mutex>, + ready_to_send: &'a Signal, receive_queue: &'a Channel, 2>, } @@ -109,6 +123,7 @@ impl<'a> UsbHandle<'a> { ( UsbSender { send_queue: self.send_queue, + ready_to_send: self.ready_to_send, }, UsbReceiver { receive_queue: self.receive_queue, @@ -119,27 +134,40 @@ impl<'a> UsbHandle<'a> { pub struct UsbSender<'a> { send_queue: &'a Mutex>, + ready_to_send: &'a Signal, } +pub struct NoSpaceInQueue; + impl UsbSender<'_> { - pub(crate) async fn send(&self, to_send: &[u8]) { + pub(crate) async fn send(&self, to_send: &[u8]) -> Result<(), NoSpaceInQueue> { let mut queue = self.send_queue.lock().await; let free = queue.capacity() - queue.len(); if free < 1 + to_send.len() { - defmt::trace!("dropping package because queue is full"); - return; // drop the package + return Err(NoSpaceInQueue); } - defmt::unwrap!(queue.push_back( - to_send - .len() - .try_into() - .expect("send only supports buffers up to and including u8::MAX long"), - )); + defmt::unwrap!( + queue.push_back(defmt::unwrap!( + to_send.len().try_into(), + "send only supports buffers up to and including u8::MAX long" + ),), + "just checked that queue has capacity" + ); for byte in to_send { defmt::unwrap!(queue.push_back(*byte)) } + Ok(()) + } + + pub(crate) async fn wait_till_queue_free(&self) { + let wait_for_ready = self.ready_to_send.wait(); + if !self.send_queue.lock().await.is_full() { + return; + } + + wait_for_ready.await } } @@ -170,6 +198,7 @@ pub fn config() -> embassy_usb::Config<'static> { pub struct StackA { send_queue: Mutex>, + ready_to_send: Signal, receive_queue: Channel, 2>, } @@ -178,6 +207,7 @@ impl StackA { Self { send_queue: Mutex::new(heapless::Deque::new()), receive_queue: Channel::new(), + ready_to_send: Signal::new(), } } } @@ -202,6 +232,7 @@ impl<'a> StackB<'a> { if_num: None, send_queue: &stack_a.send_queue, receive_queue: &stack_a.receive_queue, + ready_to_send: &stack_a.ready_to_send, }, } } @@ -270,6 +301,7 @@ pub(crate) fn new<'a, D: embassy_usb::driver::Driver<'a>>( UsbHandle { send_queue: &stack_a.send_queue, receive_queue: &stack_a.receive_queue, + ready_to_send: &stack_a.ready_to_send, }, ) } From 885f195e4c361854b813db8708c52af8c66c4184 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 8 Nov 2024 14:10:46 +0100 Subject: [PATCH 370/687] always reserve space for high prio packages --- sensor-nodes/bed-sb/src/comms.rs | 4 ++-- sensor-nodes/bed-sb/src/usb_wrapper.rs | 13 ++++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/sensor-nodes/bed-sb/src/comms.rs b/sensor-nodes/bed-sb/src/comms.rs index d9332679..8fe27f3d 100644 --- a/sensor-nodes/bed-sb/src/comms.rs +++ b/sensor-nodes/bed-sb/src/comms.rs @@ -148,13 +148,13 @@ async fn send_messages(usb: UsbSender<'_>, publish: &Queues) { buf[0] = protocol::Msg::<5>::AFFECTOR_LIST; let to_send = &buf[..=encoded_len]; defmt::unwrap!( - usb.send(to_send).await, + usb.send(to_send, false).await, "first message, queue should still be empty & large enough" ); loop { let (is_low_prio, to_send) = get_messages(publish, &mut buf).await; - while let Err(NoSpaceInQueue) = usb.send(to_send).await { + while let Err(NoSpaceInQueue) = usb.send(to_send, is_low_prio).await { if is_low_prio { defmt::trace!("dropping low priority package because queue is full"); break; diff --git a/sensor-nodes/bed-sb/src/usb_wrapper.rs b/sensor-nodes/bed-sb/src/usb_wrapper.rs index 865fe20f..363d693e 100644 --- a/sensor-nodes/bed-sb/src/usb_wrapper.rs +++ b/sensor-nodes/bed-sb/src/usb_wrapper.rs @@ -140,13 +140,24 @@ pub struct UsbSender<'a> { pub struct NoSpaceInQueue; impl UsbSender<'_> { - pub(crate) async fn send(&self, to_send: &[u8]) -> Result<(), NoSpaceInQueue> { + pub(crate) async fn send( + &self, + to_send: &[u8], + is_low_prio: bool, + ) -> Result<(), NoSpaceInQueue> { + const RESERVED_FOR_HIGH_PRIO: usize = 32; + let mut queue = self.send_queue.lock().await; let free = queue.capacity() - queue.len(); if free < 1 + to_send.len() { return Err(NoSpaceInQueue); } + let left_over = free - 1 - to_send.len(); + if left_over < RESERVED_FOR_HIGH_PRIO && is_low_prio { + return Err(NoSpaceInQueue); + } + defmt::unwrap!( queue.push_back(defmt::unwrap!( to_send.len().try_into(), From ec260d7bfdd3c3e68d69f84310bb47498d87f963 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 8 Nov 2024 14:20:26 +0100 Subject: [PATCH 371/687] Merge devices into known_states wrapping State with Lamp --- .../zigbee-bridge/src/lights/cached_bridge.rs | 4 +- .../src/lights/cached_bridge/changes.rs | 24 ++++---- .../src/lights/cached_bridge/mqtt.rs | 7 +-- .../src/lights/cached_bridge/poll.rs | 24 +++++--- crates/zigbee-bridge/src/lights/lamp.rs | 60 +++++++++++++++---- 5 files changed, 77 insertions(+), 42 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 6d94206d..4469370b 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -21,7 +21,6 @@ pub(crate) async fn run(mut change_receiver: mpsc::UnboundedReceiver<(String, Ch options.set_max_packet_size(2_usize.pow(28), 10240); let known_states = RwLock::new(HashMap::new()); - let devices = RwLock::new(HashMap::new()); let mut needed_states = HashMap::new(); // Reconnecting to broker is handled by Eventloop::poll @@ -36,13 +35,12 @@ pub(crate) async fn run(mut change_receiver: mpsc::UnboundedReceiver<(String, Ch mqtt.request_state(light).await; } - let poll_mqtt = poll::poll_mqtt(eventloop, &known_states, &devices); + let poll_mqtt = poll::poll_mqtt(eventloop, &known_states); let handle_changes = changes::handle( &mut change_receiver, &mqtt, &known_states, &mut needed_states, - &devices, ); tokio::select! { diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index 5b1904df..e698db01 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -4,15 +4,14 @@ use tokio::sync::{mpsc, RwLock}; use tokio::time::{sleep, timeout}; use super::{mqtt::Mqtt, CHANGE_TIMEOUT, WAIT_FOR_INIT_STATES}; -use crate::lights::lamp::{Change, LampState, Model}; +use crate::lights::lamp::{Change, Lamp}; use crate::LIGHTS; pub(super) async fn handle( change_receiver: &mut mpsc::UnboundedReceiver<(String, Change)>, mqtt: &Mqtt, - known_states: &RwLock>, - needed_states: &mut HashMap, - devices: &RwLock>, + known_states: &RwLock>, + needed_states: &mut HashMap, ) -> ! { // Give the initial known states a chance to be fetched sleep(WAIT_FOR_INIT_STATES).await; @@ -20,14 +19,13 @@ pub(super) async fn handle( if let Ok(change) = timeout(CHANGE_TIMEOUT, change_receiver.recv()).await { apply_change(change, known_states, needed_states).await; } - send_all(known_states, needed_states, devices, mqtt).await; + send_all(known_states, needed_states, mqtt).await; } } async fn send_all( - known_states: &RwLock>, - needed_states: &mut HashMap, - devices: &RwLock>, + known_states: &RwLock>, + needed_states: &mut HashMap, mqtt: &Mqtt, ) { let known_states = known_states.read().await; @@ -38,18 +36,16 @@ async fn send_all( let known = known_states.get(light_name); if Some(needed) != known { - let devices = devices.read().await; - let model = devices.get(light_name).expect("Should be registered"); // Ignore errors because we will retry if the state hasn't changed - let _ = mqtt.send_new_state(light_name, needed, model).await; + let _ = mqtt.send_new_state(light_name, needed).await; } } } async fn apply_change( change: Option<(String, Change)>, - known_states: &RwLock>, - needed_states: &mut HashMap, + known_states: &RwLock>, + needed_states: &mut HashMap, ) { let (light_name, change) = change.expect("Channel should never close"); let known_states = known_states.read().await; @@ -60,7 +56,7 @@ async fn apply_change( Some(known_state) => needed_states .entry(light_name.clone()) .or_insert(known_state.clone()), - None => &mut LampState::default(), + None => &mut Lamp::default(), }, }; diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index bab92759..99e2c10b 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -1,7 +1,7 @@ use rumqttc::{AsyncClient, ClientError}; use serde_json::json; -use crate::lights::lamp::{LampState, Model}; +use crate::lights::lamp::Lamp; use crate::QOS; pub(super) struct Mqtt { @@ -30,10 +30,9 @@ impl Mqtt { pub(super) async fn send_new_state( &self, light_name: &str, - needed_state: &LampState, - model: &Model, + needed: &Lamp, ) -> Result<(), ClientError> { - for payload in needed_state.to_payloads(model) { + for payload in needed.to_payloads() { self.set(light_name, &payload).await?; } Ok(()) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index a13d9df2..c59c41e6 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -4,12 +4,11 @@ use rumqttc::{Event, EventLoop, Incoming}; use serde_json::Value; use tokio::{sync::RwLock, time::sleep}; -use crate::lights::lamp::{LampState, Model}; +use crate::lights::lamp::{Lamp, LampState, Model}; pub(super) async fn poll_mqtt( mut eventloop: EventLoop, - known_states: &RwLock>, - devices: &RwLock>, + known_states: &RwLock>, ) -> ! { loop { let message = match eventloop.poll().await { @@ -21,17 +20,24 @@ pub(super) async fn poll_mqtt( } }; + let mut known_states = known_states.write().await; + match parse_message(message) { - Message::StateUpdate((light_name, new_known_state)) => { - let mut known_states = known_states.write().await; + Message::StateUpdate((light_name, updated_state)) => { + let new_known_state = match known_states.get(&light_name) { + Some(lamp) => lamp.store_state(updated_state), + None => Lamp::default().store_state(updated_state), + }; known_states.insert(light_name, new_known_state); } Message::Devices(new_devices) => { - let mut devices = devices.write().await; - if *devices != new_devices { - dbg!(&new_devices); + for (light_name, model) in new_devices { + let new_known_state = match known_states.get(&light_name) { + Some(lamp) => lamp.store_model(model), + None => Lamp::default().store_model(model), + }; + known_states.insert(light_name, new_known_state); } - *devices = new_devices } Message::Other => (), } diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index f9db11b0..67a5f3c8 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -7,6 +7,39 @@ use crate::lights::{ denormalize, kelvin_to_mired, mired_to_kelvin, }; +#[derive(PartialEq, Eq, Default, Clone)] +pub(crate) struct Lamp { + pub(crate) model: Option, + pub(crate) state: LampState, +} + +impl Lamp { + pub(crate) fn store_model(&self, model: Model) -> Self { + Self { + model: Some(model), + state: self.state.clone(), + } + } + + pub(crate) fn store_state(&self, state: LampState) -> Self { + Self { + model: self.model.clone(), + state, + } + } + + pub(crate) fn apply(&self, change: Change) -> Self { + Self { + model: self.model.clone(), + state: self.state.apply(change), + } + } + + pub(crate) fn to_payloads(&self) -> Vec { + self.state.to_payloads(&self.model) + } +} + #[derive(Debug, Clone, Default)] pub(crate) struct LampState { pub(crate) brightness: Option, @@ -158,7 +191,7 @@ impl LampState { new_state } - pub(crate) fn to_payloads(&self, model: &Model) -> Vec { + pub(crate) fn to_payloads(&self, model: &Option) -> Vec { let mut payloads = vec![]; match self.on { Some(true) => payloads.push(json!({ "state": "ON" })), @@ -173,16 +206,19 @@ impl LampState { None => (), } - if model.is_color_lamp() { - if let Some(color_xy) = self.color_xy { - payloads.push( - json!({ "color": {"x": color_xy.0, "y": color_xy.1} }), - ); - } - } else { - if let Some(color_temp) = self.color_temp_k { - payloads - .push(json!({ "color_temp": kelvin_to_mired(color_temp) })); + if let Some(model) = model { + if model.is_color_lamp() { + if let Some(color_xy) = self.color_xy { + payloads.push( + json!({ "color": {"x": color_xy.0, "y": color_xy.1} }), + ); + } + } else { + if let Some(color_temp) = self.color_temp_k { + payloads.push( + json!({ "color_temp": kelvin_to_mired(color_temp) }), + ); + } } } @@ -198,7 +234,7 @@ pub(crate) enum Change { ColorXy((f64, f64)), } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub(crate) enum Model { TradfriCandle, TradfriE27, From 8dd8c65a60a3de0307cbca801782a29665af089d Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 8 Nov 2024 14:36:23 +0100 Subject: [PATCH 372/687] Move state bytes parsing to new mod --- crates/zigbee-bridge/src/lights.rs | 5 +- crates/zigbee-bridge/src/lights/lamp.rs | 107 +----------------- .../zigbee-bridge/src/lights/parse_state.rs | 103 +++++++++++++++++ 3 files changed, 109 insertions(+), 106 deletions(-) create mode 100644 crates/zigbee-bridge/src/lights/parse_state.rs diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index 54359147..992c4633 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -4,11 +4,14 @@ use tokio::sync::mpsc; use self::lamp::Change; // TODO: make private once system is ported -pub use conversion::{kelvin_to_mired, mired_to_kelvin, normalize, denormalize}; +pub use conversion::{ + denormalize, kelvin_to_mired, mired_to_kelvin, normalize, +}; mod cached_bridge; mod conversion; mod lamp; +mod parse_state; #[derive(Debug, Clone)] pub struct Controller { diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 67a5f3c8..10e4b963 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -1,11 +1,6 @@ -use std::io; +use serde_json::json; -use serde_json::{json, Value}; - -use crate::lights::{ - conversion::{normalize, temp_to_xy}, - denormalize, kelvin_to_mired, mired_to_kelvin, -}; +use crate::lights::{conversion::temp_to_xy, denormalize, kelvin_to_mired}; #[derive(PartialEq, Eq, Default, Clone)] pub(crate) struct Lamp { @@ -78,104 +73,6 @@ impl PartialEq for LampState { impl Eq for LampState {} -impl TryInto for &[u8] { - type Error = io::Error; - - fn try_into(self) -> Result { - fn get_key<'a>( - map: &'a serde_json::Map, - key: &str, - ) -> Result<&'a Value, io::Error> { - let key_err = io::Error::new( - io::ErrorKind::InvalidData, - "Missing key from map: {key}", - ); - map.get(key).ok_or(key_err) - } - - fn invalid_err(value_type: &str) -> io::Error { - io::Error::new( - io::ErrorKind::InvalidData, - format!("Could not parse json into {value_type}"), - ) - } - - let json: Value = serde_json::from_slice(self)?; - let map = json.as_object().ok_or(invalid_err("Object"))?; - - let color_temp_mired = match get_key(map, "color_temp") { - Ok(temp) => { - let color_temp: usize = temp - .as_number() - .ok_or(invalid_err("Number"))? - .as_u64() - .ok_or(invalid_err("u64"))? - .try_into() - .expect("usize should be u64"); - Some(color_temp) - } - Err(_) => None, - }; - - let color_xy = match get_key(map, "color") { - Ok(color) => { - let color = color.as_object().ok_or(invalid_err("Object"))?; - let color_x = get_key(color, "x")? - .as_number() - .ok_or(invalid_err("Number"))? - .as_f64() - .expect("Should be Some if not using arbitrary precision"); - let color_y = get_key(color, "y")? - .as_number() - .ok_or(invalid_err("Number"))? - .as_f64() - .expect("Should be Some if not using arbitrary precision"); - Some((color_x, color_y)) - } - Err(_) => None, - }; - - let brightness = match get_key(map, "brightness") { - Ok(bri) => { - let bri: u8 = bri - .as_number() - .ok_or(invalid_err("Number"))? - .as_u64() - .ok_or(invalid_err("u64"))? - .try_into() - .map_err(|_| invalid_err("u8"))?; - Some(bri) - } - Err(_) => None, - }; - - let on = match get_key(map, "state") { - Ok(on) => { - let state = on.as_str().ok_or(invalid_err("String"))?; - let on = match state.to_lowercase().as_str() { - "on" => true, - "off" => false, - other => { - return Err(invalid_err(&format!( - "on/off bool: {other}" - ))) - } - }; - Some(on) - } - Err(_) => None, - }; - - Ok(LampState { - #[allow(clippy::cast_precision_loss)] - brightness: brightness.map(normalize), - color_temp_k: color_temp_mired.map(mired_to_kelvin), - color_xy, - on, - }) - } -} - impl LampState { pub(crate) fn apply(&self, change: Change) -> LampState { let mut new_state = self.clone(); diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs new file mode 100644 index 00000000..0509a820 --- /dev/null +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -0,0 +1,103 @@ +use std::io; + +use serde_json::Value; + +use crate::lights::{lamp::LampState, mired_to_kelvin, normalize}; + +impl TryInto for &[u8] { + type Error = io::Error; + + fn try_into(self) -> Result { + let json: Value = serde_json::from_slice(self)?; + let map = json.as_object().ok_or(invalid_err("Object"))?; + + let color_temp_mired = match get_key(map, "color_temp") { + Ok(temp) => { + let color_temp: usize = temp + .as_number() + .ok_or(invalid_err("Number"))? + .as_u64() + .ok_or(invalid_err("u64"))? + .try_into() + .expect("usize should be u64"); + Some(color_temp) + } + Err(_) => None, + }; + + let color_xy = match get_key(map, "color") { + Ok(color) => { + let color = color.as_object().ok_or(invalid_err("Object"))?; + let color_x = get_key(color, "x")? + .as_number() + .ok_or(invalid_err("Number"))? + .as_f64() + .expect("Should be Some if not using arbitrary precision"); + let color_y = get_key(color, "y")? + .as_number() + .ok_or(invalid_err("Number"))? + .as_f64() + .expect("Should be Some if not using arbitrary precision"); + Some((color_x, color_y)) + } + Err(_) => None, + }; + + let brightness = match get_key(map, "brightness") { + Ok(bri) => { + let bri: u8 = bri + .as_number() + .ok_or(invalid_err("Number"))? + .as_u64() + .ok_or(invalid_err("u64"))? + .try_into() + .map_err(|_| invalid_err("u8"))?; + Some(bri) + } + Err(_) => None, + }; + + let on = match get_key(map, "state") { + Ok(on) => { + let state = on.as_str().ok_or(invalid_err("String"))?; + let on = match state.to_lowercase().as_str() { + "on" => true, + "off" => false, + other => { + return Err(invalid_err(&format!( + "on/off bool: {other}" + ))) + } + }; + Some(on) + } + Err(_) => None, + }; + + Ok(LampState { + #[allow(clippy::cast_precision_loss)] + brightness: brightness.map(normalize), + color_temp_k: color_temp_mired.map(mired_to_kelvin), + color_xy, + on, + }) + } +} + +fn get_key<'a>( + map: &'a serde_json::Map, + key: &str, +) -> Result<&'a Value, io::Error> { + let key_err = io::Error::new( + io::ErrorKind::InvalidData, + "Missing key from map: {key}", + ); + map.get(key).ok_or(key_err) +} + +fn invalid_err(value_type: &str) -> io::Error { + io::Error::new( + io::ErrorKind::InvalidData, + format!("Could not parse json into {value_type}"), + ) +} From efe54203533a33954080b9acffe9e6794a345605 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 8 Nov 2024 14:43:06 +0100 Subject: [PATCH 373/687] Extract fns for json parsing --- .../zigbee-bridge/src/lights/parse_state.rs | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs index 0509a820..bbab107f 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -13,13 +13,8 @@ impl TryInto for &[u8] { let color_temp_mired = match get_key(map, "color_temp") { Ok(temp) => { - let color_temp: usize = temp - .as_number() - .ok_or(invalid_err("Number"))? - .as_u64() - .ok_or(invalid_err("u64"))? - .try_into() - .expect("usize should be u64"); + let color_temp: usize = + json_to_u64(temp)?.try_into().expect("usize should be u64"); Some(color_temp) } Err(_) => None, @@ -28,16 +23,8 @@ impl TryInto for &[u8] { let color_xy = match get_key(map, "color") { Ok(color) => { let color = color.as_object().ok_or(invalid_err("Object"))?; - let color_x = get_key(color, "x")? - .as_number() - .ok_or(invalid_err("Number"))? - .as_f64() - .expect("Should be Some if not using arbitrary precision"); - let color_y = get_key(color, "y")? - .as_number() - .ok_or(invalid_err("Number"))? - .as_f64() - .expect("Should be Some if not using arbitrary precision"); + let color_x = json_to_f64(get_key(color, "x")?)?; + let color_y = json_to_f64(get_key(color, "y")?)?; Some((color_x, color_y)) } Err(_) => None, @@ -45,11 +32,7 @@ impl TryInto for &[u8] { let brightness = match get_key(map, "brightness") { Ok(bri) => { - let bri: u8 = bri - .as_number() - .ok_or(invalid_err("Number"))? - .as_u64() - .ok_or(invalid_err("u64"))? + let bri: u8 = json_to_u64(bri)? .try_into() .map_err(|_| invalid_err("u8"))?; Some(bri) @@ -84,6 +67,22 @@ impl TryInto for &[u8] { } } +fn json_to_u64(json: &Value) -> Result { + Ok(json + .as_number() + .ok_or(invalid_err("Number"))? + .as_u64() + .ok_or(invalid_err("u64"))?) +} + +fn json_to_f64(json: &Value) -> Result { + Ok(json + .as_number() + .ok_or(invalid_err("Number"))? + .as_f64() + .expect("Should be Some if not using arbitrary precision")) +} + fn get_key<'a>( map: &'a serde_json::Map, key: &str, From 5f0d8aaa9f03562c64e2c5265a84bba58f2d5cdb Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 8 Nov 2024 14:45:04 +0100 Subject: [PATCH 374/687] fix usb bridge not sending affectors on reconnect --- .../src/api/data_source/reconnecting.rs | 5 ++--- crates/usb-bridge/src/main.rs | 22 +++++++++++++++++-- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/crates/data-server/src/api/data_source/reconnecting.rs b/crates/data-server/src/api/data_source/reconnecting.rs index 7a7f38e1..35399193 100644 --- a/crates/data-server/src/api/data_source/reconnecting.rs +++ b/crates/data-server/src/api/data_source/reconnecting.rs @@ -31,8 +31,7 @@ impl Client { let mut conn = if let Some(conn) = self.connection.take() { conn } else { - get_connection_or_reconnect(self.addr, &self.affectors, &mut self.retry_period) - .await + get_conn_or_reconnect(self.addr, &self.affectors, &mut self.retry_period).await }; match conn.send_bytes(bytes).await { @@ -83,7 +82,7 @@ impl Client { } } -async fn get_connection_or_reconnect( +async fn get_conn_or_reconnect( addr: SocketAddr, affectors: &[protocol::Affector], retry_period: &mut Duration, diff --git a/crates/usb-bridge/src/main.rs b/crates/usb-bridge/src/main.rs index c452e9a2..dd157ea9 100644 --- a/crates/usb-bridge/src/main.rs +++ b/crates/usb-bridge/src/main.rs @@ -5,8 +5,9 @@ use clap::Parser; use color_eyre::eyre::{bail, eyre, Context}; use color_eyre::Section; -use data_server::api::data_source; +use data_server::api::data_source::reconnecting; use nusb::transfer; +use protocol::Affector; use tokio::time::{sleep, sleep_until, Instant}; use ratelimited_logger as rl; @@ -57,6 +58,22 @@ impl ReconnectingUsbSub { } } + async fn wait_for_affectors(&mut self) -> color_eyre::Result> { + let msg = self.recv().await; + let msg = protocol::Msg::<50>::decode(msg.to_vec()).wrap_err( + "Could not decode protocol::Msg, maybe the protocol library \ + has changed since this was compiled", + )?; + let protocol::Msg::AffectorList(list) = msg else { + bail!( + "Every usb node should send an affector list on connect,\ + this node did not" + ); + }; + + Ok(list.values.to_vec()) + } + async fn recv(&mut self) -> Vec { let mut retry_period = Duration::from_millis(100); loop { @@ -140,7 +157,8 @@ async fn main() -> Result<(), color_eyre::Report> { let args = Cli::parse(); let mut usb = ReconnectingUsbSub::new(args.serial_number); - let mut server_client = data_source::reconnecting::Client::new(args.data_server, Vec::new()); + let affectors = usb.wait_for_affectors().await?; + let mut server_client = reconnecting::Client::new(args.data_server, affectors); loop { let encoded_msg = usb.recv().await; From 62fc9224a2d3711a1913ee22f915fee37d262d92 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 8 Nov 2024 14:54:07 +0100 Subject: [PATCH 375/687] Fix clippy lints --- crates/zigbee-bridge/src/lights.rs | 10 +++++----- .../src/lights/cached_bridge/poll.rs | 4 ++-- crates/zigbee-bridge/src/lights/conversion.rs | 4 +++- crates/zigbee-bridge/src/lights/lamp.rs | 17 ++++++----------- crates/zigbee-bridge/src/lights/parse_state.rs | 4 ++-- 5 files changed, 18 insertions(+), 21 deletions(-) diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index 992c4633..36324371 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -53,9 +53,9 @@ impl Controller { .expect("Sender should never be dropped"); } - // pub fn set_color_xy(&self, friendly_name: &str, xy: (f64, f64)) { - // self.change_sender - // .send((friendly_name.to_string(), Change::ColorXy(xy))) - // .expect("Sender should never be dropped"); - // } + pub fn set_color_xy(&self, friendly_name: &str, xy: (f64, f64)) { + self.change_sender + .send((friendly_name.to_string(), Change::ColorXy(xy))) + .expect("Sender should never be dropped"); + } } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index c59c41e6..92f2a21d 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -58,7 +58,7 @@ fn parse_message(message: Event) -> Message { serde_json::from_slice(&message.payload).unwrap(); let list = json.as_array().unwrap(); let devices: HashMap = list - .into_iter() + .iter() .map(parse_device) .filter(|d| d.0 != "Coordinator") .collect(); @@ -111,7 +111,7 @@ fn parse_device(device: &Value) -> (String, Model) { Model::TradfriOther(id.to_owned()) } Some(id) => Model::Other(id.to_owned()), - None => Model::Other("".to_owned()), + None => Model::Other(String::new()), }; (friendly_name, model) diff --git a/crates/zigbee-bridge/src/lights/conversion.rs b/crates/zigbee-bridge/src/lights/conversion.rs index f57fed36..e804ebaa 100644 --- a/crates/zigbee-bridge/src/lights/conversion.rs +++ b/crates/zigbee-bridge/src/lights/conversion.rs @@ -24,9 +24,11 @@ pub fn denormalize(brightness: f64) -> u8 { (brightness * 254.).round() as u8 } -/// 1000K < color_temp < 1_000_000K +#[allow(clippy::doc_markdown)] +/// 1000K < `color_temp` < 1_000_000K pub fn temp_to_xy(color_temp: usize) -> (f64, f64) { // TODO: use table from black body deviation measurements + #[allow(clippy::cast_precision_loss)] let cct = CCT::try_new(color_temp as f64, DUV_IKEA).unwrap(); let xyz: XYZ = cct.try_into().unwrap(); diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 10e4b963..c853c711 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -96,11 +96,8 @@ impl LampState { None => (), }; - match self.brightness { - Some(bri) => { - payloads.push(json!({ "brightness": denormalize(bri) })) - } - None => (), + if let Some(bri) = self.brightness { + payloads.push(json!({ "brightness": denormalize(bri) })); } if let Some(model) = model { @@ -110,12 +107,9 @@ impl LampState { json!({ "color": {"x": color_xy.0, "y": color_xy.1} }), ); } - } else { - if let Some(color_temp) = self.color_temp_k { - payloads.push( - json!({ "color_temp": kelvin_to_mired(color_temp) }), - ); - } + } else if let Some(color_temp) = self.color_temp_k { + payloads + .push(json!({ "color_temp": kelvin_to_mired(color_temp) })); } } @@ -144,6 +138,7 @@ pub(crate) enum Model { impl Model { pub(crate) fn is_color_lamp(&self) -> bool { use Model as M; + #[allow(clippy::match_same_arms)] // clearer comment match self { M::TradfriE27 | M::TradfriE14 | M::HueGen4 => true, M::TradfriCandle => false, diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs index bbab107f..d47b4c37 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -68,11 +68,11 @@ impl TryInto for &[u8] { } fn json_to_u64(json: &Value) -> Result { - Ok(json + json .as_number() .ok_or(invalid_err("Number"))? .as_u64() - .ok_or(invalid_err("u64"))?) + .ok_or(invalid_err("u64")) } fn json_to_f64(json: &Value) -> Result { From ba368703ddb696fbd8779c7fd91f263fc8d61905 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 8 Nov 2024 14:57:24 +0100 Subject: [PATCH 376/687] Reorder lamp structs and impls --- crates/zigbee-bridge/src/lights/lamp.rs | 76 ++++++++++++------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index c853c711..8497df3a 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -8,6 +8,14 @@ pub(crate) struct Lamp { pub(crate) state: LampState, } +#[derive(Debug, Clone, Default)] +pub(crate) struct LampState { + pub(crate) brightness: Option, + pub(crate) color_temp_k: Option, + pub(crate) color_xy: Option<(f64, f64)>, + pub(crate) on: Option, +} + impl Lamp { pub(crate) fn store_model(&self, model: Model) -> Self { Self { @@ -35,44 +43,6 @@ impl Lamp { } } -#[derive(Debug, Clone, Default)] -pub(crate) struct LampState { - pub(crate) brightness: Option, - pub(crate) color_temp_k: Option, - pub(crate) color_xy: Option<(f64, f64)>, - pub(crate) on: Option, -} - -impl PartialEq for LampState { - fn eq(&self, other: &Self) -> bool { - let d_bright = match (self.brightness, other.brightness) { - (Some(self_bri), Some(other_bri)) => (self_bri - other_bri).abs(), - _ => 1.0, - }; - let (d_color_x, d_color_y) = match (self.color_xy, other.color_xy) { - (Some(self_xy), Some(other_xy)) => ( - (self_xy.0 - other_xy.0).abs(), - (self_xy.1 - other_xy.1).abs(), - ), - // If either Lamp has no xy set, xy is "different" (so we use temp) - // so this needs to be over threshold - _ => (1.0, 1.0), - }; - let d_color_temp = match (self.color_temp_k, other.color_temp_k) { - (Some(self_temp), Some(other_temp)) => { - self_temp.abs_diff(other_temp) - } - _ => 5000, - }; - - let color_equal = - (d_color_x < 0.01 && d_color_y < 0.01) || d_color_temp < 50; - self.on == other.on && d_bright < 1. / 250. && color_equal - } -} - -impl Eq for LampState {} - impl LampState { pub(crate) fn apply(&self, change: Change) -> LampState { let mut new_state = self.clone(); @@ -117,6 +87,36 @@ impl LampState { } } +impl PartialEq for LampState { + fn eq(&self, other: &Self) -> bool { + let d_bright = match (self.brightness, other.brightness) { + (Some(self_bri), Some(other_bri)) => (self_bri - other_bri).abs(), + _ => 1.0, + }; + let (d_color_x, d_color_y) = match (self.color_xy, other.color_xy) { + (Some(self_xy), Some(other_xy)) => ( + (self_xy.0 - other_xy.0).abs(), + (self_xy.1 - other_xy.1).abs(), + ), + // If either State has no xy set, xy is "different" (so we use temp) + // so this needs to be over threshold + _ => (1.0, 1.0), + }; + let d_color_temp = match (self.color_temp_k, other.color_temp_k) { + (Some(self_temp), Some(other_temp)) => { + self_temp.abs_diff(other_temp) + } + _ => 5000, + }; + + let color_equal = + (d_color_x < 0.01 && d_color_y < 0.01) || d_color_temp < 50; + self.on == other.on && d_bright < 1. / 250. && color_equal + } +} + +impl Eq for LampState {} + #[derive(Debug, Clone, Copy)] pub(crate) enum Change { On(bool), From 985b1ddfb44f4aa6bf16ddc0896bfad526e15aed Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 8 Nov 2024 17:33:51 +0100 Subject: [PATCH 377/687] fixes affector list on usb nodes --- crates/protocol/src/lib.rs | 1 + crates/protocol/src/usb.rs | 7 ++ crates/usb-bridge/src/main.rs | 130 +++++++++++++++---------- sensor-nodes/bed-sb/src/comms.rs | 17 ++-- sensor-nodes/bed-sb/src/main.rs | 3 +- sensor-nodes/bed-sb/src/usb_wrapper.rs | 64 +++++++----- 6 files changed, 134 insertions(+), 88 deletions(-) create mode 100644 crates/protocol/src/usb.rs diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 42026c18..2c8f886f 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -13,6 +13,7 @@ pub mod affector; mod device; mod error; pub mod reading; +pub mod usb; mod msg; pub use affector::Affector; diff --git a/crates/protocol/src/usb.rs b/crates/protocol/src/usb.rs new file mode 100644 index 00000000..cc0e625f --- /dev/null +++ b/crates/protocol/src/usb.rs @@ -0,0 +1,7 @@ + +pub const GET_QUEUED_MESSAGES: u8 = 101; +pub const AFFECTOR_ORDER: u8 = 100; +pub const GET_AFFECTOR_LIST: u8 = 102; + +// USB full speed devices have a max data packet size of 1023 +pub const SEND_BUFFER_SIZE: usize = 208; diff --git a/crates/usb-bridge/src/main.rs b/crates/usb-bridge/src/main.rs index dd157ea9..f7f670c6 100644 --- a/crates/usb-bridge/src/main.rs +++ b/crates/usb-bridge/src/main.rs @@ -3,19 +3,19 @@ use std::{net::SocketAddr, time::Duration}; use clap::Parser; -use color_eyre::eyre::{bail, eyre, Context}; +use color_eyre::eyre::{eyre, Context}; use color_eyre::Section; use data_server::api::data_source::reconnecting; use nusb::transfer; -use protocol::Affector; +use protocol::{usb, Affector}; use tokio::time::{sleep, sleep_until, Instant}; use ratelimited_logger as rl; #[derive(Parser)] -#[command(name = "local sensors")] +#[command(name = "usb-bridge")] #[command(version = "1.0")] -#[command(about = "reads sensors attached to rpi gpio pins and i2c perhipheral")] +#[command(about = "forwards sensor info from and affector orders to nodes attached to usb")] struct Cli { /// Where to send the data on the local system #[arg(short, long("data-server"), default_value = "192.168.1.43:1234")] @@ -35,15 +35,14 @@ struct ReconnectingUsbSub { logger: ratelimited_logger::RateLimitedLogger, } -fn request_msg() -> transfer::ControlIn { +fn usb_request(request: u8) -> transfer::ControlIn { transfer::ControlIn { control_type: transfer::ControlType::Vendor, recipient: transfer::Recipient::Interface, - request: 42, + request, value: 0, index: 0, - // must match SEND_BUFFER_SIZE in usb nodes - length: 208, + length: usb::SEND_BUFFER_SIZE.try_into().expect("fits"), } } @@ -58,23 +57,28 @@ impl ReconnectingUsbSub { } } - async fn wait_for_affectors(&mut self) -> color_eyre::Result> { - let msg = self.recv().await; + async fn get_affectors(&mut self) -> color_eyre::Result> { + let msg = loop { + if let Some(msg) = self + .try_request_data(usb_request(usb::GET_AFFECTOR_LIST)) + .await? + { + break msg; + } + sleep(Duration::from_secs(5)).await; + }; let msg = protocol::Msg::<50>::decode(msg.to_vec()).wrap_err( "Could not decode protocol::Msg, maybe the protocol library \ has changed since this was compiled", )?; let protocol::Msg::AffectorList(list) = msg else { - bail!( - "Every usb node should send an affector list on connect,\ - this node did not" - ); + unreachable!("affector list request is only anwserd by affector list msg"); }; Ok(list.values.to_vec()) } - async fn recv(&mut self) -> Vec { + async fn recv_msgs(&mut self) -> Vec { let mut retry_period = Duration::from_millis(100); loop { if let Some(len) = self.bytes.next() { @@ -86,7 +90,10 @@ impl ReconnectingUsbSub { } self.bytes = loop { - match self.try_recv_step().await { + match self + .try_request_data(usb_request(usb::GET_QUEUED_MESSAGES)) + .await + { Ok(Some(bytes)) => break bytes.into_iter(), Ok(None) => continue, Err(e) => { @@ -101,12 +108,15 @@ impl ReconnectingUsbSub { } } - async fn try_recv_step(&mut self) -> color_eyre::Result>> { + async fn try_request_data( + &mut self, + request: transfer::ControlIn, + ) -> color_eyre::Result>> { if let Some(device) = self.conn.take() { sleep_until(self.next_poll).await; self.next_poll = Instant::now() + Duration::from_millis(100); let msg = device - .control_in(request_msg()) + .control_in(request) .await .into_result() .wrap_err("Something went wrong with control_in request")?; @@ -115,41 +125,58 @@ impl ReconnectingUsbSub { return Ok(Some(msg)); } - let list: Vec<_> = nusb::list_devices() - .wrap_err("Could not list usb devices")? - .filter(|d| { - d.serial_number() - .is_some_and(|d| d.eq_ignore_ascii_case(&self.serial_number)) - }) - .collect(); - - self.conn = match list.as_slice() { - [dev] => dev, - [] => bail!("No usb device found with the correct serial"), - more => { - return Err(eyre!("Multiple usb devices have the same serial number") - .with_note(|| format!("they are: {more:?}"))) - } - } - .open() - .map(Option::Some) - .wrap_err("Could not open the usb device") - .suggestion("Try running as sudo") - .with_suggestion(|| { - format!( - "Add a .rules file in /etc/udev/rules.d with line: \ - ATTRS{{serial}}==\"{}\", MODE=\"660\", GROUP=\"{}\", TAG+=\"uaccess\"", - self.serial_number, - users::get_current_groupname() - .expect("process should always run as a group") - .to_string_lossy() - ) - })?; + let list = list_usb_devices(&self.serial_number)?; + self.conn = Some(get_usb_device(list, &self.serial_number)?); Ok(None) // no errors but not done yet, call us again } } +fn list_usb_devices(serial_number: &str) -> Result, color_eyre::eyre::Error> { + let list: Vec<_> = nusb::list_devices() + .wrap_err("Could not list usb devices")? + .filter(|d| { + d.serial_number() + .is_some_and(|d| d.eq_ignore_ascii_case(serial_number)) + }) + .collect(); + Ok(list) +} + +fn get_usb_device( + list: Vec, + serial_number: &str, +) -> Result { + match list.as_slice() { + [dev] => dev, + [] => { + return Err(eyre!("No usb device found with the correct serial")) + .with_note(|| format!("looking for device with serial: {serial_number}")) + .suggestion( + "Is the device working (sometimes programming fails) \ + & connected?", + ); + } + more => { + return Err(eyre!("Multiple usb devices have the same serial number") + .with_note(|| format!("they are: {more:?}"))); + } + } + .open() + .wrap_err("Could not open the usb device") + .suggestion("Try running as sudo") + .with_suggestion(|| { + format!( + "Add a .rules file in /etc/udev/rules.d with line: \ + ATTRS{{serial}}==\"{}\", MODE=\"660\", GROUP=\"{}\", TAG+=\"uaccess\"", + serial_number, + users::get_current_groupname() + .expect("process should always run as a group") + .to_string_lossy() + ) + }) +} + #[tokio::main(flavor = "current_thread")] async fn main() -> Result<(), color_eyre::Report> { color_eyre::install().unwrap(); @@ -157,11 +184,14 @@ async fn main() -> Result<(), color_eyre::Report> { let args = Cli::parse(); let mut usb = ReconnectingUsbSub::new(args.serial_number); - let affectors = usb.wait_for_affectors().await?; + let affectors = usb + .get_affectors() + .await + .wrap_err("Could not get affector list")?; let mut server_client = reconnecting::Client::new(args.data_server, affectors); loop { - let encoded_msg = usb.recv().await; + let encoded_msg = usb.recv_msgs().await; server_client .check_send_encoded(&encoded_msg) .await diff --git a/sensor-nodes/bed-sb/src/comms.rs b/sensor-nodes/bed-sb/src/comms.rs index 8fe27f3d..3306460a 100644 --- a/sensor-nodes/bed-sb/src/comms.rs +++ b/sensor-nodes/bed-sb/src/comms.rs @@ -112,7 +112,8 @@ pub async fn handle( } } -fn affector_list() -> affector::ListMessage<5> { +const AFFECTOR_LIST_MAX_SIZE: usize = protocol::Msg::<5>::max_size(); +pub fn affector_list() -> heapless::Vec { let mut list = affector::ListMessage::<5>::empty(); unwrap!( list.values.push(Affector::SmallBedroom( @@ -139,19 +140,15 @@ fn affector_list() -> affector::ListMessage<5> { "list is long enough" ); - list + let mut buf = heapless::Vec::new(); + defmt::unwrap!(buf.resize_default(AFFECTOR_LIST_MAX_SIZE)); + let encoded_len = list.encode_slice(&mut buf).len(); + buf.truncate(encoded_len); + buf } async fn send_messages(usb: UsbSender<'_>, publish: &Queues) { let mut buf = [0; protocol::Msg::<5>::max_size()]; - let encoded_len = affector_list().encode_slice(&mut buf[1..]).len(); - buf[0] = protocol::Msg::<5>::AFFECTOR_LIST; - let to_send = &buf[..=encoded_len]; - defmt::unwrap!( - usb.send(to_send, false).await, - "first message, queue should still be empty & large enough" - ); - loop { let (is_low_prio, to_send) = get_messages(publish, &mut buf).await; while let Err(NoSpaceInQueue) = usb.send(to_send, is_low_prio).await { diff --git a/sensor-nodes/bed-sb/src/main.rs b/sensor-nodes/bed-sb/src/main.rs index 1e84c2f5..fb6d0af9 100644 --- a/sensor-nodes/bed-sb/src/main.rs +++ b/sensor-nodes/bed-sb/src/main.rs @@ -153,8 +153,9 @@ async fn main(_spawner: Spawner) { usb_driver_config, ); + let affector_list = comms::affector_list(); let stack_a = usb_wrapper::StackA::new(); - let mut stack_b = usb_wrapper::StackB::new(&stack_a); + let mut stack_b = usb_wrapper::StackB::new(&stack_a, &affector_list); let (mut usb_bus, usb_handle) = usb_wrapper::new(&stack_a, &mut stack_b, usb_driver); let driver_orderers = slow::DriverOrderers::new(); diff --git a/sensor-nodes/bed-sb/src/usb_wrapper.rs b/sensor-nodes/bed-sb/src/usb_wrapper.rs index 363d693e..d621d9cb 100644 --- a/sensor-nodes/bed-sb/src/usb_wrapper.rs +++ b/sensor-nodes/bed-sb/src/usb_wrapper.rs @@ -5,17 +5,17 @@ use embassy_sync::signal::Signal; use embassy_usb::control::{InResponse, OutResponse, Recipient, RequestType}; use embassy_usb::types::InterfaceNumber; use embassy_usb::UsbDevice; -use protocol::affector; +use protocol::{affector, usb}; -/// USB full speed devices such as this one have a max data packet size of 1023 -const SEND_BUFFER_SIZE: usize = 208; const MAX_RECV_ITEM_SIZE: usize = 1 + affector::Affector::ENCODED_SIZE; pub(crate) type RecvItem = heapless::Vec; +type SendQueue = Mutex>; pub struct UsbControlHandler<'a> { pub if_num: Option, - send_queue: &'a Mutex>, + affector_list: &'a [u8], + send_queue: &'a SendQueue, ready_to_send: &'a Signal, receive_queue: &'a Channel, } @@ -43,8 +43,8 @@ impl embassy_usb::Handler for UsbControlHandler<'_> { return None; } - // Accept request 100, value 200, reject others. - if req.request == 100 && req.value == 200 && data.len() <= MAX_RECV_ITEM_SIZE { + // Accept affector orders only. + if req.request == usb::AFFECTOR_ORDER && data.len() <= MAX_RECV_ITEM_SIZE { let data = heapless::Vec::from_slice(data).expect("checked length above"); if self.receive_queue.try_send(data).is_err() { Some(OutResponse::Rejected) @@ -75,16 +75,36 @@ impl embassy_usb::Handler for UsbControlHandler<'_> { return None; } - if buf.len() != SEND_BUFFER_SIZE { + if buf.len() != usb::SEND_BUFFER_SIZE { defmt::warn!( "Send buffer is incorrect size ({}), should be: {}. \ - Please adjuct host driver (usb-bridge) os the usb stack here", + recompile either usb-bridge or this", buf.len(), - SEND_BUFFER_SIZE + usb::SEND_BUFFER_SIZE ); return Some(InResponse::Rejected); } + if req.request == usb::GET_AFFECTOR_LIST { + self.send_affector_list(buf); + Some(InResponse::Accepted(buf)) + } else if req.request == usb::GET_QUEUED_MESSAGES { + self.send_queued(buf)?; + Some(InResponse::Accepted(buf)) + } else { + Some(InResponse::Rejected) + } + } +} + +impl UsbControlHandler<'_> { + fn send_affector_list(&mut self, buf: &mut [u8]) { + buf[0] = protocol::Msg::<5>::AFFECTOR_LIST; + buf[1..1 + self.affector_list.len()].copy_from_slice(self.affector_list); + buf[1 + self.affector_list.len()..].fill(0); + } + + fn send_queued(&mut self, buf: &mut [u8]) -> Option<()> { let Ok(mut send_queue) = self.send_queue.try_lock() else { return None; }; @@ -97,23 +117,12 @@ impl embassy_usb::Handler for UsbControlHandler<'_> { } } self.ready_to_send.signal(()); - - Some(InResponse::Accepted(buf)) + Some(()) } } -// struct SendQueue{ -// free: Channel, -// bytes: heapless::Deque -// } -// -// impl SendQueue { -// fn send(&self, to_send) { -// } -// } - pub struct UsbHandle<'a> { - send_queue: &'a Mutex>, + send_queue: &'a SendQueue, ready_to_send: &'a Signal, receive_queue: &'a Channel, 2>, } @@ -133,7 +142,7 @@ impl<'a> UsbHandle<'a> { } pub struct UsbSender<'a> { - send_queue: &'a Mutex>, + send_queue: &'a SendQueue, ready_to_send: &'a Signal, } @@ -208,7 +217,7 @@ pub fn config() -> embassy_usb::Config<'static> { } pub struct StackA { - send_queue: Mutex>, + send_queue: SendQueue, ready_to_send: Signal, receive_queue: Channel, 2>, } @@ -227,23 +236,24 @@ pub struct StackB<'a> { config_descriptor: [u8; 256], bos_descriptor: [u8; 256], msos_descriptor: [u8; 256], - control_buf: [u8; SEND_BUFFER_SIZE], + control_buf: [u8; usb::SEND_BUFFER_SIZE], handler: UsbControlHandler<'a>, } impl<'a> StackB<'a> { - pub(crate) fn new(stack_a: &'a StackA) -> Self { + pub(crate) fn new(stack_a: &'a StackA, affector_list: &'a [u8]) -> Self { Self { config_descriptor: [0u8; 256], bos_descriptor: [0u8; 256], msos_descriptor: [0u8; 256], - control_buf: [0u8; SEND_BUFFER_SIZE], + control_buf: [0u8; usb::SEND_BUFFER_SIZE], handler: UsbControlHandler { if_num: None, send_queue: &stack_a.send_queue, receive_queue: &stack_a.receive_queue, ready_to_send: &stack_a.ready_to_send, + affector_list, }, } } From 7ff91eab5d6b05b617a0f6e5a8bd9f8ede4804ee Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 9 Nov 2024 11:19:00 +0100 Subject: [PATCH 378/687] Decrease pub where possible --- .../zigbee-bridge/src/lights/cached_bridge.rs | 7 ++-- crates/zigbee-bridge/src/lights/conversion.rs | 2 +- crates/zigbee-bridge/src/lights/lamp.rs | 34 +++++++++---------- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 4469370b..c16de805 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -15,8 +15,11 @@ mod poll; const CHANGE_TIMEOUT: Duration = Duration::from_secs(5); const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); -pub(crate) async fn run(mut change_receiver: mpsc::UnboundedReceiver<(String, Change)>) -> ! { - let mut options = MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); +pub(super) async fn run( + mut change_receiver: mpsc::UnboundedReceiver<(String, Change)>, +) -> ! { + let mut options = + MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); // Set incoming to max mqtt packet size, outgoing to rumqtt default options.set_max_packet_size(2_usize.pow(28), 10240); diff --git a/crates/zigbee-bridge/src/lights/conversion.rs b/crates/zigbee-bridge/src/lights/conversion.rs index e804ebaa..e75f3415 100644 --- a/crates/zigbee-bridge/src/lights/conversion.rs +++ b/crates/zigbee-bridge/src/lights/conversion.rs @@ -26,7 +26,7 @@ pub fn denormalize(brightness: f64) -> u8 { #[allow(clippy::doc_markdown)] /// 1000K < `color_temp` < 1_000_000K -pub fn temp_to_xy(color_temp: usize) -> (f64, f64) { +pub(super) fn temp_to_xy(color_temp: usize) -> (f64, f64) { // TODO: use table from black body deviation measurements #[allow(clippy::cast_precision_loss)] let cct = CCT::try_new(color_temp as f64, DUV_IKEA).unwrap(); diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 8497df3a..f0712e21 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -3,48 +3,48 @@ use serde_json::json; use crate::lights::{conversion::temp_to_xy, denormalize, kelvin_to_mired}; #[derive(PartialEq, Eq, Default, Clone)] -pub(crate) struct Lamp { - pub(crate) model: Option, - pub(crate) state: LampState, +pub(super) struct Lamp { + pub(super) model: Option, + pub(super) state: LampState, } #[derive(Debug, Clone, Default)] -pub(crate) struct LampState { - pub(crate) brightness: Option, - pub(crate) color_temp_k: Option, - pub(crate) color_xy: Option<(f64, f64)>, - pub(crate) on: Option, +pub(super) struct LampState { + pub(super) brightness: Option, + pub(super) color_temp_k: Option, + pub(super) color_xy: Option<(f64, f64)>, + pub(super) on: Option, } impl Lamp { - pub(crate) fn store_model(&self, model: Model) -> Self { + pub(super) fn store_model(&self, model: Model) -> Self { Self { model: Some(model), state: self.state.clone(), } } - pub(crate) fn store_state(&self, state: LampState) -> Self { + pub(super) fn store_state(&self, state: LampState) -> Self { Self { model: self.model.clone(), state, } } - pub(crate) fn apply(&self, change: Change) -> Self { + pub(super) fn apply(&self, change: Change) -> Self { Self { model: self.model.clone(), state: self.state.apply(change), } } - pub(crate) fn to_payloads(&self) -> Vec { + pub(super) fn to_payloads(&self) -> Vec { self.state.to_payloads(&self.model) } } impl LampState { - pub(crate) fn apply(&self, change: Change) -> LampState { + fn apply(&self, change: Change) -> LampState { let mut new_state = self.clone(); match change { Change::On(on) => new_state.on = Some(on), @@ -58,7 +58,7 @@ impl LampState { new_state } - pub(crate) fn to_payloads(&self, model: &Option) -> Vec { + fn to_payloads(&self, model: &Option) -> Vec { let mut payloads = vec![]; match self.on { Some(true) => payloads.push(json!({ "state": "ON" })), @@ -118,7 +118,7 @@ impl PartialEq for LampState { impl Eq for LampState {} #[derive(Debug, Clone, Copy)] -pub(crate) enum Change { +pub(super) enum Change { On(bool), Brightness(f64), ColorTemp(usize), @@ -126,7 +126,7 @@ pub(crate) enum Change { } #[derive(Debug, Clone, PartialEq, Eq)] -pub(crate) enum Model { +pub(super) enum Model { TradfriCandle, TradfriE27, TradfriE14, @@ -136,7 +136,7 @@ pub(crate) enum Model { } impl Model { - pub(crate) fn is_color_lamp(&self) -> bool { + fn is_color_lamp(&self) -> bool { use Model as M; #[allow(clippy::match_same_arms)] // clearer comment match self { From 16228e67e1366ba13288f23d0c3daa28e60c0b54 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 9 Nov 2024 11:39:41 +0100 Subject: [PATCH 379/687] Add settings to state --- crates/zigbee-bridge/src/lights/lamp.rs | 22 ++++++++++++++++++- .../zigbee-bridge/src/lights/parse_state.rs | 4 ++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index f0712e21..8bad0dea 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -8,12 +8,29 @@ pub(super) struct Lamp { pub(super) state: LampState, } -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone)] pub(super) struct LampState { pub(super) brightness: Option, pub(super) color_temp_k: Option, pub(super) color_xy: Option<(f64, f64)>, pub(super) on: Option, + pub(super) color_temp_startup: String, + pub(super) color_sync: bool, +} + +impl Default for LampState { + fn default() -> Self { + Self { + brightness: None, + color_temp_k: None, + color_xy: None, + on: None, + // Settings, will not be updated from MQTT state message + // and will never trigger a publish + color_temp_startup: String::from("previous"), + color_sync: true, + } + } } impl Lamp { @@ -83,6 +100,9 @@ impl LampState { } } + payloads.push(json!({ "color_temp_startup": self.color_temp_startup })); + payloads.push(json!({ "color_sync": self.color_sync })); + payloads.into_iter().map(|x| x.to_string()).collect() } } diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs index d47b4c37..ff1666c7 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -63,13 +63,13 @@ impl TryInto for &[u8] { color_temp_k: color_temp_mired.map(mired_to_kelvin), color_xy, on, + ..Default::default() }) } } fn json_to_u64(json: &Value) -> Result { - json - .as_number() + json.as_number() .ok_or(invalid_err("Number"))? .as_u64() .ok_or(invalid_err("u64")) From 1a2845db40a2444662ed52249d7f709c3a22eeb2 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 9 Nov 2024 13:23:06 +0100 Subject: [PATCH 380/687] Add color deviation data --- crates/zigbee-bridge/src/lights/lamp.rs | 100 +++++++++++++++++++++++- 1 file changed, 96 insertions(+), 4 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 8bad0dea..f05b9095 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use serde_json::json; use crate::lights::{conversion::temp_to_xy, denormalize, kelvin_to_mired}; @@ -152,18 +154,108 @@ pub(super) enum Model { TradfriE14, HueGen4, TradfriOther(String), + HueOther(String), Other(String), } impl Model { fn is_color_lamp(&self) -> bool { - use Model as M; #[allow(clippy::match_same_arms)] // clearer comment match self { - M::TradfriE27 | M::TradfriE14 | M::HueGen4 => true, - M::TradfriCandle => false, + Model::TradfriE27 | Model::TradfriE14 | Model::HueGen4 => true, + Model::TradfriCandle => false, // We assume no so that things at least don't break - M::TradfriOther(_) | M::Other(_) => false, + Model::TradfriOther(_) | Model::HueOther(_) | Model::Other(_) => { + false + } + } + } + + fn color_deviation(&self, color_temp: usize) -> (usize, f64) { + match self { + Model::TradfriCandle => todo!(), + Model::TradfriE27 => todo!(), + Model::TradfriE14 => todo!(), + Model::HueGen4 => todo!(), + Model::TradfriOther(_) => todo!(), + Model::HueOther(_) => todo!(), + Model::Other(_) => todo!(), + } + } + + // Value for actual color temp (after temp correction) + fn blackbody_table(&self) -> HashMap { + match self { + // 105.455.00 data + Model::TradfriCandle => vec![ + (2170, 0.0028), + (2391, 0.0018), + (2683, 0.0006), + (2990, 0.0006), + (3193, 0.0012), + (3590, 0.003), + (3791, 0.0036), + (3951, 0.0046), + ], + // 604.391.68 data + Model::TradfriE27 => vec![ + (1964, -0.003), + (2090, 0.0014), + (2668, 0.0015), + (3046, 0.001), + (3499, 0.0015), + (3605, -0.0011), + (4098, -0.0017), + (4110, -0.0009), + (4250, 0.0007), + ], + // 204.391.94 data + Model::TradfriE14 => vec![ + (1841, -0.0032), + (2055, -0.0034), + (2120, 0.0012), + (2738, -0.0005), + (3070, 0.0004), + (3467, 0.0045), + (3555, 0.00), + (3981, 0.0009), + (4113, 0.0037), + ], + // A19 Color 9.5W data + Model::HueGen4 | Model::HueOther(_) => vec![ + (1998, 0.0005), + (2197, 0.00000), + (2519, -0.0004), + (2695, -0.0007), + (2849, -0.0011), + (3358, -0.0012), + (3864, -0.012), + (4010, -0.0009), + (5455, -0.0005), + (6495, 0.0014), + ], + Model::TradfriOther(_) => todo!(), + Model::Other(_) => todo!(), + } + .into_iter() + .collect() + } + + // Value to add to requested color temp + fn temp_table(&self) -> HashMap { + match self { + Model::TradfriCandle => { + vec![(2200, 30), (2700, 20), (4000, 50)] + } + Model::TradfriE27 => vec![(2200, 110), (2700, 30), (4000, -110)], + Model::TradfriE14 => vec![(2200, 70), (2700, -40), (4000, 20)], + Model::HueGen4 | Model::HueOther(_) => { + vec![(2200, 2), (2700, 5), (4000, -10), (5500, 45), (6500, 5)] + } + Model::TradfriOther(_) => todo!(), + Model::Other(_) => todo!(), } + .into_iter() + .collect() } } From 34f696f9e1e8aa7b9deff3384f7cbda4b0ab7cf5 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 9 Nov 2024 17:54:49 +0100 Subject: [PATCH 381/687] fix data-server crashing when subscriber is queue is full --- crates/data-server/src/server/subscribe.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/data-server/src/server/subscribe.rs b/crates/data-server/src/server/subscribe.rs index 4d90c4dd..d450f46b 100644 --- a/crates/data-server/src/server/subscribe.rs +++ b/crates/data-server/src/server/subscribe.rs @@ -1,5 +1,6 @@ use std::mem; use tokio::sync::mpsc; +use tokio::sync::mpsc::error::TrySendError; use tracing::trace; use color_eyre::Result; @@ -17,7 +18,7 @@ pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { .expect("queue is kept open by register_subs"); trace!("event: {event:?}"); - let msg = match event { + let to_forward = match event { Event::NewSub { tx } => { subscribers.push(tx); continue; @@ -35,8 +36,9 @@ pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { let subs = mem::take(&mut subscribers); for sub in subs { - if sub.try_send(msg.clone()).is_ok() { - subscribers.push(sub); + let res = sub.try_send(to_forward.clone()); + if let Ok(()) | Err(TrySendError::Full(_)) = res { + subscribers.push(sub) } } } From 9dd8f164a3d963602781d64df2ec4395ef1d6a4e Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 9 Nov 2024 17:56:14 +0100 Subject: [PATCH 382/687] adds ratelimiting to affector orders --- crates/data-server/src/server/affector.rs | 22 +++++++++++++++++++--- crates/data-server/src/server/client.rs | 4 ++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/crates/data-server/src/server/affector.rs b/crates/data-server/src/server/affector.rs index 050cfa1a..178ad6fc 100644 --- a/crates/data-server/src/server/affector.rs +++ b/crates/data-server/src/server/affector.rs @@ -1,6 +1,8 @@ +use std::num::NonZeroU32; use std::sync::{Arc, Mutex}; use color_eyre::Result; +use governor::Quota; use protocol::Affector; use slotmap::{DefaultKey, SlotMap}; use tokio::io::AsyncWriteExt; @@ -13,6 +15,7 @@ use tracing::{instrument, warn}; pub(crate) struct Registration { tx: tokio::sync::mpsc::Sender, controls: Vec, + rate_limiter: governor::DefaultDirectRateLimiter, } impl Registration { @@ -53,6 +56,10 @@ impl Registar { this.insert(Registration { tx, controls: affectors, + rate_limiter: governor::DefaultDirectRateLimiter::direct( + Quota::per_second(NonZeroU32::new(1).expect("not zero")) + .allow_burst(NonZeroU32::new(5).expect("not zero")), + ), }) } @@ -61,7 +68,7 @@ impl Registar { let _ = this.remove(key); // Could have been removed by register } - pub(crate) fn activate(&self, order: Affector) -> Result<(), Offline> { + pub(crate) fn activate(&self, order: Affector) -> Result<(), AffectorError> { tracing::info!("client is trying to activate: {order:?}"); let mut this = self.0.lock().expect("nothing should panic"); for possible_controller in this.iter_mut().map(|(_, reg)| reg).filter(|reg| { @@ -69,13 +76,16 @@ impl Registar { .iter() .any(|control| control.is_same_as(&order)) }) { + if possible_controller.rate_limiter.check().is_err() { + return Err(AffectorError::RateLimited); + } if possible_controller.tx.try_send(order).is_ok() { possible_controller.update(order); return Ok(()); } } - Err(Offline) + Err(AffectorError::Offline) } pub(crate) fn list(&self) -> Vec { @@ -87,7 +97,13 @@ impl Registar { } } -pub struct Offline; +#[derive(Debug, thiserror::Error, Clone, Serialize, Deserialize)] +pub enum AffectorError { + #[error("Sensor node to which the affector belongs is offline")] + Offline, + #[error("Too many requests, ratelimited")] + RateLimited, +} #[instrument(skip_all)] pub(super) async fn control_affectors(mut writer: OwnedWriteHalf, mut rx: Receiver) { diff --git a/crates/data-server/src/server/client.rs b/crates/data-server/src/server/client.rs index be679823..b7dbdcbb 100644 --- a/crates/data-server/src/server/client.rs +++ b/crates/data-server/src/server/client.rs @@ -6,7 +6,7 @@ use color_eyre::Result; use crate::api::subscriber; -use super::{affector::Offline, affector::Registar, Event}; +use super::{affector::Registar, Event}; #[derive(Debug, Clone)] struct SubHandler { @@ -96,7 +96,7 @@ async fn perform_request_inner( .map_err(|_| subscriber::ServerError::FailedToSpread)?; subscriber::Response::Actuate(Ok(())) } - Err(Offline) => subscriber::Response::Actuate(Err(subscriber::AffectorError::Offline)), + Err(err) => subscriber::Response::Actuate(Err(err)), }, subscriber::Request::ListAffectors => subscriber::Response::ListAffectors(affectors.list()), }) From 0be7d6260d39b450e61d1c5bb1c1571f21f2b81e Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 9 Nov 2024 17:56:52 +0100 Subject: [PATCH 383/687] reconnecting data-source can forwards affector orders + usb bridge forwards affector orders --- .../src/api/data_source/reconnecting.rs | 59 ++++++-- crates/data-server/src/api/subscriber.rs | 11 +- crates/data-server/src/server.rs | 2 +- crates/data-server/src/server/affector.rs | 1 + crates/data-server/src/server/data_source.rs | 3 + crates/data-server/src/server/watch.rs | 4 +- crates/desk-sensors/src/main.rs | 2 +- crates/usb-bridge/src/main.rs | 131 ++++++++++++++---- 8 files changed, 163 insertions(+), 50 deletions(-) diff --git a/crates/data-server/src/api/data_source/reconnecting.rs b/crates/data-server/src/api/data_source/reconnecting.rs index 35399193..afaf5074 100644 --- a/crates/data-server/src/api/data_source/reconnecting.rs +++ b/crates/data-server/src/api/data_source/reconnecting.rs @@ -1,5 +1,8 @@ +use protocol::Affector; use std::net::SocketAddr; use std::time::Duration; +use tokio::sync::mpsc; +use tokio::task::JoinHandle; use tokio::time::{sleep, timeout}; use tracing::{info, warn}; @@ -7,9 +10,17 @@ use super::SendPreEncodedError; pub struct Client { retry_period: Duration, - connection: Option, + conn: Option<(super::Sender, Option)>, addr: SocketAddr, affectors: Vec, + affector_tx: Option>, +} + +struct AbortOnDrop(JoinHandle<()>); +impl Drop for AbortOnDrop { + fn drop(&mut self) { + self.0.abort(); + } } impl Client { @@ -17,29 +28,43 @@ impl Client { /// node as an argument. If your node provides not controllable affectors /// pass in an empty Vec. #[must_use] - pub fn new(addr: SocketAddr, affectors: Vec) -> Self { + pub fn new( + addr: SocketAddr, + affectors: Vec, + affector_tx: Option>, + ) -> Self { Self { retry_period: Duration::from_millis(200), - connection: None, + conn: None, addr, affectors, + affector_tx, } } async fn send_bytes(&mut self, bytes: &[u8]) { loop { - let mut conn = if let Some(conn) = self.connection.take() { - conn + let (mut sender, handle) = if let Some((sender, handle)) = self.conn.take() { + dbg!(); + (sender, handle) } else { - get_conn_or_reconnect(self.addr, &self.affectors, &mut self.retry_period).await + dbg!(); + let conn = reconnect(self.addr, &self.affectors, &mut self.retry_period).await; + let (sender, receiver) = conn.split(); + let handle = self.affector_tx.clone().map(|tx| { + let task = forward_received(receiver, tx); + let handle = tokio::spawn(task); + AbortOnDrop(handle) + }); + (sender, handle) }; - match conn.send_bytes(bytes).await { - Ok(msg) => { + dbg!(); + match sender.send_bytes(bytes).await { + Ok(_) => { self.retry_period /= 2; self.retry_period = self.retry_period.max(Duration::from_millis(200)); - self.connection = Some(conn); - return msg; + self.conn = Some((sender, handle)); } Err(issue) => { warn!("Conn issue while sending new reading: {issue}, reconnecting"); @@ -82,7 +107,19 @@ impl Client { } } -async fn get_conn_or_reconnect( +async fn forward_received(mut receiver: super::Receiver, tx: mpsc::Sender) { + loop { + let Ok(order) = receiver.receive().await else { + return; + }; + + let Ok(_) = tx.send(order).await else { + return; + }; + } +} + +async fn reconnect( addr: SocketAddr, affectors: &[protocol::Affector], retry_period: &mut Duration, diff --git a/crates/data-server/src/api/subscriber.rs b/crates/data-server/src/api/subscriber.rs index 9283b847..edc0e511 100644 --- a/crates/data-server/src/api/subscriber.rs +++ b/crates/data-server/src/api/subscriber.rs @@ -1,8 +1,10 @@ -use serde::{Deserialize, Serialize}; pub use client::reconnecting::Client as ReconnectingClient; pub use client::reconnecting::SubscribedClient as ReconnectingSubscribedClient; pub use client::Client; pub use client::Subscribed as SubscribedClient; +use serde::{Deserialize, Serialize}; + +pub use crate::server::affector::AffectorError; pub mod client; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -33,12 +35,6 @@ pub enum SubMessage { ErrorReport(Box), } -#[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)] -pub enum AffectorError { - #[error("We do not have a connection to the actuator's node")] - Offline, -} - #[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)] #[error("placeholder")] pub struct SubscribeError; @@ -48,4 +44,3 @@ pub enum ServerError { #[error("Could not activate affector")] FailedToSpread, } - diff --git a/crates/data-server/src/server.rs b/crates/data-server/src/server.rs index 53e84fbd..819d9a3d 100644 --- a/crates/data-server/src/server.rs +++ b/crates/data-server/src/server.rs @@ -5,7 +5,7 @@ use tokio::sync::mpsc; use tokio_serde::formats::Bincode; use tokio_util::codec::{Framed, LengthDelimitedCodec}; -mod affector; +pub mod affector; pub mod client; mod data_source; mod subscribe; diff --git a/crates/data-server/src/server/affector.rs b/crates/data-server/src/server/affector.rs index 178ad6fc..9c91c088 100644 --- a/crates/data-server/src/server/affector.rs +++ b/crates/data-server/src/server/affector.rs @@ -4,6 +4,7 @@ use std::sync::{Arc, Mutex}; use color_eyre::Result; use governor::Quota; use protocol::Affector; +use serde::{Deserialize, Serialize}; use slotmap::{DefaultKey, SlotMap}; use tokio::io::AsyncWriteExt; use tokio::net::tcp::OwnedWriteHalf; diff --git a/crates/data-server/src/server/data_source.rs b/crates/data-server/src/server/data_source.rs index e3ffda35..5765e4cd 100644 --- a/crates/data-server/src/server/data_source.rs +++ b/crates/data-server/src/server/data_source.rs @@ -20,6 +20,9 @@ use tracing::{error, info, instrument, warn}; use super::affector::{control_affectors, Registar}; +/// spawns tasks for all nodes that connect. Those tasks push the readings +/// their nodes report into share and send relevant affector orders to the +/// node if they get them via the registar. pub async fn handle_nodes( addr: SocketAddr, share: &Sender, diff --git a/crates/data-server/src/server/watch.rs b/crates/data-server/src/server/watch.rs index 7c56ce61..56aa66d1 100644 --- a/crates/data-server/src/server/watch.rs +++ b/crates/data-server/src/server/watch.rs @@ -1,4 +1,4 @@ -use crate::api::subscriber::SubMessage; +use crate::api::subscriber::{AffectorError, SubMessage}; use std::time::Duration; use super::{AffectorRegistar, Event}; @@ -67,7 +67,7 @@ impl LastSeen { let last_reset = self .last_reset .iter() - .find(|(a, _)| a == reset_cmd) + .find(|(a, _)| a.is_same_as(reset_cmd)) .map(|(_, at)| at) .copied(); !last_reset.is_some_and(|last_reset| last_reset.elapsed() < MIN_RESET_INTERVAL) diff --git a/crates/desk-sensors/src/main.rs b/crates/desk-sensors/src/main.rs index 7b04eacf..465ec181 100644 --- a/crates/desk-sensors/src/main.rs +++ b/crates/desk-sensors/src/main.rs @@ -34,7 +34,7 @@ async fn main() { sensors::start_monitoring(tx.clone(), cli.bedroom); info!("connecting to dataserver on: {}", cli.data_server); - let mut client = data_source::reconnecting::Client::new(cli.data_server, Vec::new()); + let mut client = data_source::reconnecting::Client::new(cli.data_server, Vec::new(), None); loop { match rx.recv().await.expect("sensor monitoring never stops") { diff --git a/crates/usb-bridge/src/main.rs b/crates/usb-bridge/src/main.rs index f7f670c6..9c3bbdb6 100644 --- a/crates/usb-bridge/src/main.rs +++ b/crates/usb-bridge/src/main.rs @@ -8,6 +8,7 @@ use color_eyre::Section; use data_server::api::data_source::reconnecting; use nusb::transfer; use protocol::{usb, Affector}; +use tokio::sync::mpsc; use tokio::time::{sleep, sleep_until, Instant}; use ratelimited_logger as rl; @@ -25,7 +26,7 @@ struct Cli { serial_number: String, } -struct ReconnectingUsbSub { +struct ReconnectingUsb { serial_number: String, /// when we are allowed to poll the usb /// device for more data again @@ -33,9 +34,10 @@ struct ReconnectingUsbSub { conn: Option, bytes: vec::IntoIter, logger: ratelimited_logger::RateLimitedLogger, + to_send: mpsc::Receiver, } -fn usb_request(request: u8) -> transfer::ControlIn { +fn usb_get(request: u8) -> transfer::ControlIn { transfer::ControlIn { control_type: transfer::ControlType::Vendor, recipient: transfer::Recipient::Interface, @@ -46,21 +48,39 @@ fn usb_request(request: u8) -> transfer::ControlIn { } } -impl ReconnectingUsbSub { - fn new(serial_number: String) -> Self { - ReconnectingUsbSub { +fn usb_send(request: u8, data: &[u8]) -> transfer::ControlOut { + transfer::ControlOut { + control_type: transfer::ControlType::Vendor, + recipient: transfer::Recipient::Interface, + request, + value: 0, + index: 0, + data, + } +} + +enum Status { + Done, + CallAgain, +} + +impl ReconnectingUsb { + fn new(serial_number: String, to_send: mpsc::Receiver) -> Self { + ReconnectingUsb { serial_number, next_poll: Instant::now(), conn: None, bytes: Vec::new().into_iter(), logger: ratelimited_logger::RateLimitedLogger::default(), + to_send, } } async fn get_affectors(&mut self) -> color_eyre::Result> { let msg = loop { + dbg!(); if let Some(msg) = self - .try_request_data(usb_request(usb::GET_AFFECTOR_LIST)) + .try_request_data(usb_get(usb::GET_AFFECTOR_LIST)) .await? { break msg; @@ -78,9 +98,10 @@ impl ReconnectingUsbSub { Ok(list.values.to_vec()) } - async fn recv_msgs(&mut self) -> Vec { + async fn handle_usb(&mut self) -> Vec { let mut retry_period = Duration::from_millis(100); loop { + dbg!(); if let Some(len) = self.bytes.next() { if len == 0 { self.bytes = Vec::new().into_iter(); @@ -89,22 +110,57 @@ impl ReconnectingUsbSub { return self.bytes.by_ref().take(len as usize).collect(); } - self.bytes = loop { - match self - .try_request_data(usb_request(usb::GET_QUEUED_MESSAGES)) - .await - { - Ok(Some(bytes)) => break bytes.into_iter(), - Ok(None) => continue, - Err(e) => { - let logger = &mut self.logger; - rl::warn!(logger; "{e:?}"); - retry_period *= 2; - let retry_period = retry_period.min(Duration::from_secs(30)); - sleep(retry_period).await; - } - }; + if let Ok(order) = self.to_send.try_recv() { + dbg!(&order); + self.send_order(&mut retry_period, order).await; + } + tokio::time::sleep(retry_period).await; + + dbg!(); + self.receive_bytes(&mut retry_period).await; + } + } + + async fn receive_bytes(&mut self, retry_period: &mut Duration) { + self.bytes = loop { + dbg!(); + sleep_until(self.next_poll).await; + self.next_poll = Instant::now() + Duration::from_millis(100); + + match self + .try_request_data(usb_get(usb::GET_QUEUED_MESSAGES)) + .await + { + Ok(Some(bytes)) => break bytes.into_iter(), + Ok(None) => continue, + Err(e) => { + let logger = &mut self.logger; + rl::warn!(logger; "could not receive sensor message: {e:?}"); + *retry_period *= 2; + *retry_period = (*retry_period).min(Duration::from_secs(30)); + sleep(*retry_period).await; + } }; + }; + } + + async fn send_order(&mut self, retry_period: &mut Duration, order: Affector) { + let data = order.encode(); + for _ in 0..2 { + match self + .try_send_data(usb_send(usb::AFFECTOR_ORDER, &data)) + .await + { + Ok(Status::Done) => break, + Ok(Status::CallAgain) => continue, + Err(e) => { + let logger = &mut self.logger; + rl::warn!(logger; "could not send affector order: {e:?}"); + *retry_period *= 2; + *retry_period = (*retry_period).min(Duration::from_secs(30)); + sleep(*retry_period).await; + } + } } } @@ -113,8 +169,6 @@ impl ReconnectingUsbSub { request: transfer::ControlIn, ) -> color_eyre::Result>> { if let Some(device) = self.conn.take() { - sleep_until(self.next_poll).await; - self.next_poll = Instant::now() + Duration::from_millis(100); let msg = device .control_in(request) .await @@ -130,6 +184,27 @@ impl ReconnectingUsbSub { Ok(None) // no errors but not done yet, call us again } + + async fn try_send_data( + &mut self, + request: transfer::ControlOut<'_>, + ) -> color_eyre::Result { + if let Some(device) = self.conn.take() { + device + .control_out(request) + .await + .into_result() + .wrap_err("Something went wrong with control_out request")?; + + self.conn = Some(device); + return Ok(Status::Done); + } + + let list = list_usb_devices(&self.serial_number)?; + self.conn = Some(get_usb_device(list, &self.serial_number)?); + + Ok(Status::CallAgain) // no errors but not done yet, call us again + } } fn list_usb_devices(serial_number: &str) -> Result, color_eyre::eyre::Error> { @@ -183,15 +258,17 @@ async fn main() -> Result<(), color_eyre::Report> { setup_tracing(); let args = Cli::parse(); - let mut usb = ReconnectingUsbSub::new(args.serial_number); + let (order_tx, order_rx) = tokio::sync::mpsc::channel(10); + let mut usb = ReconnectingUsb::new(args.serial_number, order_rx); let affectors = usb .get_affectors() .await .wrap_err("Could not get affector list")?; - let mut server_client = reconnecting::Client::new(args.data_server, affectors); + let mut server_client = reconnecting::Client::new(args.data_server, affectors, Some(order_tx)); loop { - let encoded_msg = usb.recv_msgs().await; + dbg!(); + let encoded_msg = usb.handle_usb().await; server_client .check_send_encoded(&encoded_msg) .await From 07f870acf421df81a58cf748d7d150ec7ee8ffdc Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 10 Nov 2024 18:14:54 +0100 Subject: [PATCH 384/687] Fix lamps never changing by fixing Eq impl Also remove color_sync from state because it is a conf file thing --- crates/zigbee-bridge/src/lights.rs | 2 + .../zigbee-bridge/src/lights/cached_bridge.rs | 2 + .../src/lights/cached_bridge/changes.rs | 7 +- .../src/lights/cached_bridge/mqtt.rs | 5 +- .../src/lights/cached_bridge/poll.rs | 3 +- crates/zigbee-bridge/src/lights/lamp.rs | 66 ++++++++++++------- 6 files changed, 56 insertions(+), 29 deletions(-) diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index 36324371..e522313f 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -1,5 +1,6 @@ #![allow(clippy::missing_panics_doc)] use tokio::sync::mpsc; +use tracing::trace; use self::lamp::Change; @@ -24,6 +25,7 @@ impl Controller { let (change_sender, change_receiver) = mpsc::unbounded_channel(); let run_bridge = cached_bridge::run(change_receiver); + trace!("Spawning zigbee bridge task"); tokio::task::spawn(run_bridge); Self { change_sender } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index c16de805..86f8fe01 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -3,6 +3,7 @@ use std::time::Duration; use rumqttc::{AsyncClient, MqttOptions}; use tokio::sync::{mpsc, RwLock}; +use tracing::trace; use self::mqtt::Mqtt; use crate::lights::lamp::Change; @@ -38,6 +39,7 @@ pub(super) async fn run( mqtt.request_state(light).await; } + trace!("Starting main zigbee management loops"); let poll_mqtt = poll::poll_mqtt(eventloop, &known_states); let handle_changes = changes::handle( &mut change_receiver, diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index e698db01..67719e08 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use tokio::sync::{mpsc, RwLock}; use tokio::time::{sleep, timeout}; +use tracing::trace; use super::{mqtt::Mqtt, CHANGE_TIMEOUT, WAIT_FOR_INIT_STATES}; use crate::lights::lamp::{Change, Lamp}; @@ -16,7 +17,10 @@ pub(super) async fn handle( // Give the initial known states a chance to be fetched sleep(WAIT_FOR_INIT_STATES).await; loop { - if let Ok(change) = timeout(CHANGE_TIMEOUT, change_receiver.recv()).await { + if let Ok(change) = + timeout(CHANGE_TIMEOUT, change_receiver.recv()).await + { + trace!("Received change: {change:?}"); apply_change(change, known_states, needed_states).await; } send_all(known_states, needed_states, mqtt).await; @@ -36,6 +40,7 @@ async fn send_all( let known = known_states.get(light_name); if Some(needed) != known { + trace!("Sending needed state {needed:?} to replace known {known:?}"); // Ignore errors because we will retry if the state hasn't changed let _ = mqtt.send_new_state(light_name, needed).await; } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index 99e2c10b..28cb4417 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -1,5 +1,6 @@ use rumqttc::{AsyncClient, ClientError}; use serde_json::json; +use tracing::trace; use crate::lights::lamp::Lamp; use crate::QOS; @@ -21,7 +22,7 @@ impl Mqtt { } pub(super) async fn request_state(&self, name: &str) { - println!("Requesting state for light {name}"); + trace!("Requesting state for light {name}"); let payload = json!({"state": ""}); self.get(name, &payload.to_string()).await.unwrap(); @@ -45,7 +46,7 @@ impl Mqtt { ) -> Result<(), ClientError> { let topic = format!("zigbee2mqtt/{friendly_name}/set"); - tracing::trace!("Sending payload {payload} to lamp {friendly_name}"); + trace!("Sending payload {payload} to lamp {friendly_name}"); self.publish(&topic, payload).await?; Ok(()) } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 92f2a21d..2b0bb0b1 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -3,6 +3,7 @@ use std::{collections::HashMap, time::Duration}; use rumqttc::{Event, EventLoop, Incoming}; use serde_json::Value; use tokio::{sync::RwLock, time::sleep}; +use tracing::trace; use crate::lights::lamp::{Lamp, LampState, Model}; @@ -14,7 +15,7 @@ pub(super) async fn poll_mqtt( let message = match eventloop.poll().await { Ok(message) => message, Err(err) => { - println!("Error while polling: {err}"); + trace!("Error while polling: {err}"); sleep(Duration::from_millis(100)).await; continue; } diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index f05b9095..0dda0a66 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -4,7 +4,7 @@ use serde_json::json; use crate::lights::{conversion::temp_to_xy, denormalize, kelvin_to_mired}; -#[derive(PartialEq, Eq, Default, Clone)] +#[derive(Default, Clone, Debug)] pub(super) struct Lamp { pub(super) model: Option, pub(super) state: LampState, @@ -17,7 +17,6 @@ pub(super) struct LampState { pub(super) color_xy: Option<(f64, f64)>, pub(super) on: Option, pub(super) color_temp_startup: String, - pub(super) color_sync: bool, } impl Default for LampState { @@ -30,7 +29,6 @@ impl Default for LampState { // Settings, will not be updated from MQTT state message // and will never trigger a publish color_temp_startup: String::from("previous"), - color_sync: true, } } } @@ -103,41 +101,59 @@ impl LampState { } payloads.push(json!({ "color_temp_startup": self.color_temp_startup })); - payloads.push(json!({ "color_sync": self.color_sync })); payloads.into_iter().map(|x| x.to_string()).collect() } } -impl PartialEq for LampState { +impl PartialEq for Lamp { fn eq(&self, other: &Self) -> bool { - let d_bright = match (self.brightness, other.brightness) { - (Some(self_bri), Some(other_bri)) => (self_bri - other_bri).abs(), - _ => 1.0, - }; - let (d_color_x, d_color_y) = match (self.color_xy, other.color_xy) { - (Some(self_xy), Some(other_xy)) => ( - (self_xy.0 - other_xy.0).abs(), - (self_xy.1 - other_xy.1).abs(), - ), - // If either State has no xy set, xy is "different" (so we use temp) - // so this needs to be over threshold - _ => (1.0, 1.0), + let color_is_equal = if let (Some(self_model), Some(other_model)) = + (self.model.clone(), other.model.clone()) + { + // We should only compare states for the same lamp + assert_eq!(self_model, other_model); + + // We only ever set xy for color lamps, + // so color temp doesn't say anything + if self_model.is_color_lamp() { + match (self.state.color_xy, other.state.color_xy) { + (Some(self_xy), Some(other_xy)) => { + let d_color_x = (self_xy.0 - other_xy.0).abs(); + let d_color_y = (self_xy.1 - other_xy.1).abs(); + d_color_x < 0.01 && d_color_y < 0.01 + } + // If either State has no xy set, xy is unset -> different + _ => false, + } + // We only ever set temp, and xy doesn't exist + } else { + match (self.state.color_temp_k, other.state.color_temp_k) { + (Some(self_temp), Some(other_temp)) => { + self_temp.abs_diff(other_temp) < 50 + } + _ => false, + } + } + } else { + // We don't know what model this is, thus we don't know how to compare + // colors, so we assume unequal and hope that we know a model soon + false }; - let d_color_temp = match (self.color_temp_k, other.color_temp_k) { - (Some(self_temp), Some(other_temp)) => { - self_temp.abs_diff(other_temp) + + let bri_is_equal = match (self.state.brightness, other.state.brightness) + { + (Some(self_bri), Some(other_bri)) => { + (self_bri - other_bri).abs() < 1. / 250. } - _ => 5000, + _ => false, }; - let color_equal = - (d_color_x < 0.01 && d_color_y < 0.01) || d_color_temp < 50; - self.on == other.on && d_bright < 1. / 250. && color_equal + self.state.on == other.state.on && bri_is_equal && color_is_equal } } -impl Eq for LampState {} +impl Eq for Lamp {} #[derive(Debug, Clone, Copy)] pub(super) enum Change { From e727bc0399d507b04f747a3804782a98871fa4a4 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 11 Nov 2024 00:47:14 +0100 Subject: [PATCH 385/687] partial refactor of data-server data-source api client --- .../src/api/data_source/reconnecting.rs | 135 ++++++---- crates/usb-bridge/src/main.rs | 240 +----------------- sensor-nodes/bed-sb/src/usb_wrapper.rs | 1 + 3 files changed, 87 insertions(+), 289 deletions(-) diff --git a/crates/data-server/src/api/data_source/reconnecting.rs b/crates/data-server/src/api/data_source/reconnecting.rs index afaf5074..d2d62c88 100644 --- a/crates/data-server/src/api/data_source/reconnecting.rs +++ b/crates/data-server/src/api/data_source/reconnecting.rs @@ -1,19 +1,17 @@ +use futures_concurrency::future::Race; use protocol::Affector; use std::net::SocketAddr; use std::time::Duration; -use tokio::sync::mpsc; +use tokio::sync::{mpsc, oneshot}; use tokio::task::JoinHandle; use tokio::time::{sleep, timeout}; use tracing::{info, warn}; -use super::SendPreEncodedError; +use super::{ReceiveError, SendPreEncodedError}; pub struct Client { - retry_period: Duration, - conn: Option<(super::Sender, Option)>, - addr: SocketAddr, - affectors: Vec, - affector_tx: Option>, + conn_handler: AbortOnDrop, + to_send_tx: mpsc::Sender<(Vec, SendFeedback)>, } struct AbortOnDrop(JoinHandle<()>); @@ -23,6 +21,74 @@ impl Drop for AbortOnDrop { } } +type SendFeedback = oneshot::Sender>; +async fn handle_conn( + addr: SocketAddr, + affectors: Vec, + mut msgs_to_send: mpsc::Receiver<(Vec, SendFeedback)>, + msgs_recieved: Option>, +) { + loop { + let mut retry_period = Duration::from_millis(200); + let conn = reconnect(addr, &affectors, &mut retry_period).await; + let (sender, receiver) = conn.split(); + + if let Some(ref msgs_recieved) = msgs_recieved { + let res = ( + handle_sending(sender, &mut msgs_to_send), + handle_recieving(receiver, msgs_recieved), + ) + .race() + .await; + match res { + SendOrRecvError::Sending(e) => todo!(), + SendOrRecvError::Recieving(e) => todo!(), + } + } else { + handle_sending(sender, &mut msgs_to_send).await; + } + } +} + +enum SendOrRecvError { + Sending(std::io::Error), + Recieving(ReceiveError), +} + +async fn handle_sending( + mut sender: super::Sender, + msgs_to_send: &mut mpsc::Receiver<(Vec, SendFeedback)>, +) -> SendOrRecvError { + loop { + let (msg, feedback_channel) = msgs_to_send + .recv() + .await + .expect("this is canceled before the corrosponding sender is dropped"); + let res = sender.send_bytes(&msg).await; + let _ignore_err = feedback_channel.send(res.as_ref().map_err(|e| e.to_string()).copied()); + if let Err(e) = res { + return SendOrRecvError::Sending(e); + } + } +} + +async fn handle_recieving( + mut receiver: super::Receiver, + msgs_recieved: &mpsc::Sender, +) -> SendOrRecvError { + loop { + let msg = match receiver.receive().await { + Ok(msg) => msg, + Err(err) => return SendOrRecvError::Recieving(err), + }; + + msgs_recieved + .send(msg) + .await + .expect("Reciever in the 'Client' is never dropped") + } +} + impl Client { /// Needs a list of the affectors that can be controlled through this /// node as an argument. If your node provides not controllable affectors @@ -33,44 +99,19 @@ impl Client { affectors: Vec, affector_tx: Option>, ) -> Self { + let (to_send_tx, to_send_rx) = mpsc::channel(100); + let task = handle_conn(addr, affectors, to_send_rx, affector_tx); + let handle = tokio::spawn(task); Self { - retry_period: Duration::from_millis(200), - conn: None, - addr, - affectors, - affector_tx, + conn_handler: AbortOnDrop(handle), + to_send_tx, } } - async fn send_bytes(&mut self, bytes: &[u8]) { - loop { - let (mut sender, handle) = if let Some((sender, handle)) = self.conn.take() { - dbg!(); - (sender, handle) - } else { - dbg!(); - let conn = reconnect(self.addr, &self.affectors, &mut self.retry_period).await; - let (sender, receiver) = conn.split(); - let handle = self.affector_tx.clone().map(|tx| { - let task = forward_received(receiver, tx); - let handle = tokio::spawn(task); - AbortOnDrop(handle) - }); - (sender, handle) - }; - - dbg!(); - match sender.send_bytes(bytes).await { - Ok(_) => { - self.retry_period /= 2; - self.retry_period = self.retry_period.max(Duration::from_millis(200)); - self.conn = Some((sender, handle)); - } - Err(issue) => { - warn!("Conn issue while sending new reading: {issue}, reconnecting"); - } - }; - } + async fn send_bytes(&mut self, bytes: Vec) -> Result<(), ()> { + let (tx, rx) = oneshot::channel(); + self.to_send_tx.send((bytes, tx)).await; + rx.await } /// # Cancel safety @@ -107,18 +148,6 @@ impl Client { } } -async fn forward_received(mut receiver: super::Receiver, tx: mpsc::Sender) { - loop { - let Ok(order) = receiver.receive().await else { - return; - }; - - let Ok(_) = tx.send(order).await else { - return; - }; - } -} - async fn reconnect( addr: SocketAddr, affectors: &[protocol::Affector], diff --git a/crates/usb-bridge/src/main.rs b/crates/usb-bridge/src/main.rs index 9c3bbdb6..71e62edd 100644 --- a/crates/usb-bridge/src/main.rs +++ b/crates/usb-bridge/src/main.rs @@ -1,17 +1,12 @@ -use std::vec; -use std::{net::SocketAddr, time::Duration}; +use std::net::SocketAddr; use clap::Parser; -use color_eyre::eyre::{eyre, Context}; +use color_eyre::eyre::Context; use color_eyre::Section; use data_server::api::data_source::reconnecting; -use nusb::transfer; -use protocol::{usb, Affector}; -use tokio::sync::mpsc; -use tokio::time::{sleep, sleep_until, Instant}; -use ratelimited_logger as rl; +mod usb; #[derive(Parser)] #[command(name = "usb-bridge")] @@ -26,232 +21,6 @@ struct Cli { serial_number: String, } -struct ReconnectingUsb { - serial_number: String, - /// when we are allowed to poll the usb - /// device for more data again - next_poll: Instant, - conn: Option, - bytes: vec::IntoIter, - logger: ratelimited_logger::RateLimitedLogger, - to_send: mpsc::Receiver, -} - -fn usb_get(request: u8) -> transfer::ControlIn { - transfer::ControlIn { - control_type: transfer::ControlType::Vendor, - recipient: transfer::Recipient::Interface, - request, - value: 0, - index: 0, - length: usb::SEND_BUFFER_SIZE.try_into().expect("fits"), - } -} - -fn usb_send(request: u8, data: &[u8]) -> transfer::ControlOut { - transfer::ControlOut { - control_type: transfer::ControlType::Vendor, - recipient: transfer::Recipient::Interface, - request, - value: 0, - index: 0, - data, - } -} - -enum Status { - Done, - CallAgain, -} - -impl ReconnectingUsb { - fn new(serial_number: String, to_send: mpsc::Receiver) -> Self { - ReconnectingUsb { - serial_number, - next_poll: Instant::now(), - conn: None, - bytes: Vec::new().into_iter(), - logger: ratelimited_logger::RateLimitedLogger::default(), - to_send, - } - } - - async fn get_affectors(&mut self) -> color_eyre::Result> { - let msg = loop { - dbg!(); - if let Some(msg) = self - .try_request_data(usb_get(usb::GET_AFFECTOR_LIST)) - .await? - { - break msg; - } - sleep(Duration::from_secs(5)).await; - }; - let msg = protocol::Msg::<50>::decode(msg.to_vec()).wrap_err( - "Could not decode protocol::Msg, maybe the protocol library \ - has changed since this was compiled", - )?; - let protocol::Msg::AffectorList(list) = msg else { - unreachable!("affector list request is only anwserd by affector list msg"); - }; - - Ok(list.values.to_vec()) - } - - async fn handle_usb(&mut self) -> Vec { - let mut retry_period = Duration::from_millis(100); - loop { - dbg!(); - if let Some(len) = self.bytes.next() { - if len == 0 { - self.bytes = Vec::new().into_iter(); - continue; - } - return self.bytes.by_ref().take(len as usize).collect(); - } - - if let Ok(order) = self.to_send.try_recv() { - dbg!(&order); - self.send_order(&mut retry_period, order).await; - } - tokio::time::sleep(retry_period).await; - - dbg!(); - self.receive_bytes(&mut retry_period).await; - } - } - - async fn receive_bytes(&mut self, retry_period: &mut Duration) { - self.bytes = loop { - dbg!(); - sleep_until(self.next_poll).await; - self.next_poll = Instant::now() + Duration::from_millis(100); - - match self - .try_request_data(usb_get(usb::GET_QUEUED_MESSAGES)) - .await - { - Ok(Some(bytes)) => break bytes.into_iter(), - Ok(None) => continue, - Err(e) => { - let logger = &mut self.logger; - rl::warn!(logger; "could not receive sensor message: {e:?}"); - *retry_period *= 2; - *retry_period = (*retry_period).min(Duration::from_secs(30)); - sleep(*retry_period).await; - } - }; - }; - } - - async fn send_order(&mut self, retry_period: &mut Duration, order: Affector) { - let data = order.encode(); - for _ in 0..2 { - match self - .try_send_data(usb_send(usb::AFFECTOR_ORDER, &data)) - .await - { - Ok(Status::Done) => break, - Ok(Status::CallAgain) => continue, - Err(e) => { - let logger = &mut self.logger; - rl::warn!(logger; "could not send affector order: {e:?}"); - *retry_period *= 2; - *retry_period = (*retry_period).min(Duration::from_secs(30)); - sleep(*retry_period).await; - } - } - } - } - - async fn try_request_data( - &mut self, - request: transfer::ControlIn, - ) -> color_eyre::Result>> { - if let Some(device) = self.conn.take() { - let msg = device - .control_in(request) - .await - .into_result() - .wrap_err("Something went wrong with control_in request")?; - - self.conn = Some(device); - return Ok(Some(msg)); - } - - let list = list_usb_devices(&self.serial_number)?; - self.conn = Some(get_usb_device(list, &self.serial_number)?); - - Ok(None) // no errors but not done yet, call us again - } - - async fn try_send_data( - &mut self, - request: transfer::ControlOut<'_>, - ) -> color_eyre::Result { - if let Some(device) = self.conn.take() { - device - .control_out(request) - .await - .into_result() - .wrap_err("Something went wrong with control_out request")?; - - self.conn = Some(device); - return Ok(Status::Done); - } - - let list = list_usb_devices(&self.serial_number)?; - self.conn = Some(get_usb_device(list, &self.serial_number)?); - - Ok(Status::CallAgain) // no errors but not done yet, call us again - } -} - -fn list_usb_devices(serial_number: &str) -> Result, color_eyre::eyre::Error> { - let list: Vec<_> = nusb::list_devices() - .wrap_err("Could not list usb devices")? - .filter(|d| { - d.serial_number() - .is_some_and(|d| d.eq_ignore_ascii_case(serial_number)) - }) - .collect(); - Ok(list) -} - -fn get_usb_device( - list: Vec, - serial_number: &str, -) -> Result { - match list.as_slice() { - [dev] => dev, - [] => { - return Err(eyre!("No usb device found with the correct serial")) - .with_note(|| format!("looking for device with serial: {serial_number}")) - .suggestion( - "Is the device working (sometimes programming fails) \ - & connected?", - ); - } - more => { - return Err(eyre!("Multiple usb devices have the same serial number") - .with_note(|| format!("they are: {more:?}"))); - } - } - .open() - .wrap_err("Could not open the usb device") - .suggestion("Try running as sudo") - .with_suggestion(|| { - format!( - "Add a .rules file in /etc/udev/rules.d with line: \ - ATTRS{{serial}}==\"{}\", MODE=\"660\", GROUP=\"{}\", TAG+=\"uaccess\"", - serial_number, - users::get_current_groupname() - .expect("process should always run as a group") - .to_string_lossy() - ) - }) -} - #[tokio::main(flavor = "current_thread")] async fn main() -> Result<(), color_eyre::Report> { color_eyre::install().unwrap(); @@ -259,7 +28,7 @@ async fn main() -> Result<(), color_eyre::Report> { let args = Cli::parse(); let (order_tx, order_rx) = tokio::sync::mpsc::channel(10); - let mut usb = ReconnectingUsb::new(args.serial_number, order_rx); + let mut usb = usb::ReconnectingUsb::new(args.serial_number, order_rx); let affectors = usb .get_affectors() .await @@ -267,7 +36,6 @@ async fn main() -> Result<(), color_eyre::Report> { let mut server_client = reconnecting::Client::new(args.data_server, affectors, Some(order_tx)); loop { - dbg!(); let encoded_msg = usb.handle_usb().await; server_client .check_send_encoded(&encoded_msg) diff --git a/sensor-nodes/bed-sb/src/usb_wrapper.rs b/sensor-nodes/bed-sb/src/usb_wrapper.rs index d621d9cb..56fa601f 100644 --- a/sensor-nodes/bed-sb/src/usb_wrapper.rs +++ b/sensor-nodes/bed-sb/src/usb_wrapper.rs @@ -85,6 +85,7 @@ impl embassy_usb::Handler for UsbControlHandler<'_> { return Some(InResponse::Rejected); } + defmt::info!("usb request: {:?}", req); if req.request == usb::GET_AFFECTOR_LIST { self.send_affector_list(buf); Some(InResponse::Accepted(buf)) From 1c64a993e610fc10fb8712c0b23f36a7c2176f51 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 11 Nov 2024 01:56:10 +0100 Subject: [PATCH 386/687] code review, see TODO and FIX comments. --- crates/zigbee-bridge/src/lib.rs | 9 ++++++ crates/zigbee-bridge/src/lights.rs | 4 ++- .../zigbee-bridge/src/lights/cached_bridge.rs | 5 +-- .../src/lights/cached_bridge/mqtt.rs | 4 +++ crates/zigbee-bridge/src/lights/state.rs | 32 ++++++++++++++----- 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 2285286a..28d93cff 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -8,6 +8,15 @@ use rumqttc::QoS; pub mod lights; +// TODO: could arrive multiple times, causing strange behavior. Maybe try +// ExactlyOnce. +// +// strackoverflow: +// QoS 1 allows for message duplicates - it is possible a duplicate will arrive +// after the first instance of the next message that was published. +// https://stackoverflow.com/questions/30955110/is-message-order-preserved-in-mqtt-messages +// +// <11-11-24, dvdsk noreply@davidsk.dev> const QOS: QoS = QoS::AtLeastOnce; const MQTT_IP: &str = "192.168.1.43"; const MQTT_PORT: u16 = 1883; diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index c74263d4..a47a6e4b 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -4,7 +4,7 @@ use tokio::sync::mpsc; use self::state::Change; // TODO: make private once system is ported -pub use conversion::{kelvin_to_mired, mired_to_kelvin, normalize, denormalize}; +pub use conversion::{denormalize, kelvin_to_mired, mired_to_kelvin, normalize}; mod cached_bridge; mod conversion; @@ -38,6 +38,8 @@ impl Controller { .expect("Sender should never be dropped"); } + // TODO: document, is this lumen? Maybe use newtype pattern with a new lumen + // struct pub fn set_brightness(&self, friendly_name: &str, brightness: f64) { self.change_sender .send((friendly_name.to_string(), Change::Brightness(brightness))) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 211a1a38..ebf1d5f9 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -18,13 +18,14 @@ const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); pub(crate) async fn run(mut change_receiver: mpsc::UnboundedReceiver<(String, Change)>) -> ! { let mut options = MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); // Set incoming to max mqtt packet size, outgoing to rumqtt default - options.set_max_packet_size(2_usize.pow(28), 10240); + options.set_max_packet_size(2_usize.pow(28), 10240); // incoming: ~ 268 MB let known_states = RwLock::new(HashMap::new()); let mut needed_states = HashMap::new(); // Reconnecting to broker is handled by Eventloop::poll - let (client, eventloop) = AsyncClient::new(options.clone(), 128); + let channel_capacity = 128; + let (client, eventloop) = AsyncClient::new(options.clone(), channel_capacity); let mqtt = Mqtt::new(client); for light in LIGHTS { diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index 81e72a85..3777a649 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -32,6 +32,10 @@ impl Mqtt { light_name: &str, needed_state: &Lamp, ) -> Result<(), ClientError> { + // TODO: Can we not send all the json for each lamp in one go? I + // remember you told me something about this but I forgot what it was. + // Might be useful to have a line documenting that here. <11-11-24, + // dvdsk> for payload in needed_state.to_payloads() { self.set(light_name, &payload).await?; } diff --git a/crates/zigbee-bridge/src/lights/state.rs b/crates/zigbee-bridge/src/lights/state.rs index c6acf7b2..83bf8469 100644 --- a/crates/zigbee-bridge/src/lights/state.rs +++ b/crates/zigbee-bridge/src/lights/state.rs @@ -2,9 +2,10 @@ use std::io; use serde_json::{json, Value}; -use crate::lights::{conversion::{ - kelvin_to_mired, mired_to_kelvin, normalize, temp_to_xy, -}, denormalize}; +use crate::lights::{ + conversion::{kelvin_to_mired, mired_to_kelvin, normalize, temp_to_xy}, + denormalize, +}; #[derive(Debug, Clone)] pub(crate) struct Lamp { @@ -43,17 +44,26 @@ impl PartialEq for Lamp { impl Eq for Lamp {} impl TryInto for &[u8] { - type Error = io::Error; + type Error = io::Error; // TODO: could be a parse error enum, saves having + // to go through the whole ErrorKind stuff. + // + // But this is fine too, kinda like the str for + // invalid_err() stuff + // + // but get_key(map, "color") could be + // map.get("color").ok_or(ParseError("Missing key + // from map: {key}")). Just an idea, do what you + // prefer. + // <11-11-24, dvdsk> fn try_into(self) -> Result { fn get_key<'a>( map: &'a serde_json::Map, key: &str, ) -> Result<&'a Value, io::Error> { - let key_err = io::Error::new( - io::ErrorKind::InvalidData, - "Missing key from map: {key}", - ); + // FIX: this is the literal string {key} (missing a format! call + // probably?) <11-11-24, dvdsk> + let key_err = io::Error::new(io::ErrorKind::InvalidData, "Missing key from map: {key}"); map.get(key).ok_or(key_err) } @@ -100,6 +110,9 @@ impl TryInto for &[u8] { let state = get_key(map, "state")? .as_str() .ok_or(invalid_err("String"))?; + // TODO: why not compare to uppercase ON and OFF? Now this is confusing + // because we set the state using uppercase ON and OFF in `to_payloads` + // <11-11-24, dvdsk> let on = match state.to_lowercase().as_str() { "on" => true, "off" => false, @@ -117,6 +130,9 @@ impl TryInto for &[u8] { } impl Lamp { + // TODO: How do you feel about letting this take ownership of self. Then the + // clone would move to the caller and the first parameter would take be &self + // but self <11-11-24, dvdsk> pub(crate) fn apply(&self, change: Change) -> Lamp { let mut new_state = self.clone(); match change { From 7fc5f54c8b917ac1e4f5814c0fc46a6896d6732a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 11 Nov 2024 02:15:56 +0100 Subject: [PATCH 387/687] more code review, now I really have to sleep though --- crates/zigbee-bridge/src/lights/lamp.rs | 30 +++++++++---------- .../zigbee-bridge/src/lights/parse_state.rs | 2 ++ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index a5e82e52..a6b3160f 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -93,18 +93,23 @@ impl LampState { if let Some(model) = model { if model.is_color_lamp() { if let Some(color_xy) = self.color_xy { - payloads.push( - json!({ "color": {"x": color_xy.0, "y": color_xy.1} }), - ); + payloads.push(json!({ "color": {"x": color_xy.0, "y": color_xy.1} })); } } else if let Some(color_temp) = self.color_temp_k { - payloads - .push(json!({ "color_temp": kelvin_to_mired(color_temp) })); + payloads.push(json!({ "color_temp": kelvin_to_mired(color_temp) })); } } payloads.push(json!({ "color_temp_startup": self.color_temp_startup })); + // TODO: I might have said this somewhere already however I am too lazy + // to look up where: + // + // I am not sure if this creates json. As far as I know every string of + // json starts with { and ends with }. So this will not be one json + // string but text consisting of multiple concatenated bits of json. + // + // payloads.into_iter().map(|x| x.to_string()).collect() } } @@ -132,9 +137,7 @@ impl PartialEq for Lamp { // We only ever set temp, and xy doesn't exist } else { match (self.state.color_temp_k, other.state.color_temp_k) { - (Some(self_temp), Some(other_temp)) => { - self_temp.abs_diff(other_temp) < 50 - } + (Some(self_temp), Some(other_temp)) => self_temp.abs_diff(other_temp) < 50, _ => false, } } @@ -144,11 +147,8 @@ impl PartialEq for Lamp { false }; - let bri_is_equal = match (self.state.brightness, other.state.brightness) - { - (Some(self_bri), Some(other_bri)) => { - (self_bri - other_bri).abs() < 1. / 250. - } + let bri_is_equal = match (self.state.brightness, other.state.brightness) { + (Some(self_bri), Some(other_bri)) => (self_bri - other_bri).abs() < 1. / 250., _ => false, }; @@ -184,9 +184,7 @@ impl Model { Model::TradfriE27 | Model::TradfriE14 | Model::HueGen4 => true, Model::TradfriCandle => false, // We assume no so that things at least don't break - Model::TradfriOther(_) | Model::HueOther(_) | Model::Other(_) => { - false - } + Model::TradfriOther(_) | Model::HueOther(_) | Model::Other(_) => false, } } diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs index ada7abb5..ee010458 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -21,6 +21,8 @@ impl TryInto for &[u8] { let json: Value = serde_json::from_slice(self)?; let map = json.as_object().ok_or(invalid_err("Object"))?; + // TODO: disappointed in clippy, match Ok -> Some, Err -> None is + // Result::ok() let color_temp_mired = match get_key(map, "color_temp") { Ok(temp) => { let color_temp: usize = json_to_u64(temp)?.try_into().expect("usize should be u64"); From eb8ed453d701217293e5082180d25521d18e7759 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 12 Nov 2024 11:08:34 +0100 Subject: [PATCH 388/687] Add rustfmt.toml with smaller width to stop autofmts --- rustfmt.toml | 1 + 1 file changed, 1 insertion(+) create mode 100644 rustfmt.toml diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..df99c691 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +max_width = 80 From 276d9f67c0b98f82cd32afe090805646b561d913 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 12 Nov 2024 11:12:21 +0100 Subject: [PATCH 389/687] Autofmt with new unified settings --- .../zigbee-bridge/src/lights/cached_bridge.rs | 3 ++- .../src/lights/cached_bridge/changes.rs | 4 +++- .../src/lights/cached_bridge/mqtt.rs | 2 +- crates/zigbee-bridge/src/lights/lamp.rs | 24 +++++++++++++------ .../zigbee-bridge/src/lights/parse_state.rs | 19 +++++++++++---- 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 4a87dc22..c97b456f 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -29,7 +29,8 @@ pub(super) async fn run( // Reconnecting to broker is handled by Eventloop::poll let channel_capacity = 128; - let (client, eventloop) = AsyncClient::new(options.clone(), channel_capacity); + let (client, eventloop) = + AsyncClient::new(options.clone(), channel_capacity); let mqtt = Mqtt::new(client); mqtt.subscribe("zigbee2mqtt/bridge/devices").await.unwrap(); diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index 67719e08..244df32b 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -40,7 +40,9 @@ async fn send_all( let known = known_states.get(light_name); if Some(needed) != known { - trace!("Sending needed state {needed:?} to replace known {known:?}"); + trace!( + "Sending needed state {needed:?} to replace known {known:?}" + ); // Ignore errors because we will retry if the state hasn't changed let _ = mqtt.send_new_state(light_name, needed).await; } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index 8be2c9a0..a0f7cc41 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -36,7 +36,7 @@ impl Mqtt { // TODO: Can we not send all the json for each lamp in one go? I // remember you told me something about this but I forgot what it was. // Might be useful to have a line documenting that here. <11-11-24, - // dvdsk> + // dvdsk> for payload in needed.to_payloads() { self.set(light_name, &payload).await?; } diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index a6b3160f..dac22a87 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -93,10 +93,13 @@ impl LampState { if let Some(model) = model { if model.is_color_lamp() { if let Some(color_xy) = self.color_xy { - payloads.push(json!({ "color": {"x": color_xy.0, "y": color_xy.1} })); + payloads.push( + json!({ "color": {"x": color_xy.0, "y": color_xy.1} }), + ); } } else if let Some(color_temp) = self.color_temp_k { - payloads.push(json!({ "color_temp": kelvin_to_mired(color_temp) })); + payloads + .push(json!({ "color_temp": kelvin_to_mired(color_temp) })); } } @@ -108,7 +111,7 @@ impl LampState { // I am not sure if this creates json. As far as I know every string of // json starts with { and ends with }. So this will not be one json // string but text consisting of multiple concatenated bits of json. - // + // // payloads.into_iter().map(|x| x.to_string()).collect() } @@ -137,7 +140,9 @@ impl PartialEq for Lamp { // We only ever set temp, and xy doesn't exist } else { match (self.state.color_temp_k, other.state.color_temp_k) { - (Some(self_temp), Some(other_temp)) => self_temp.abs_diff(other_temp) < 50, + (Some(self_temp), Some(other_temp)) => { + self_temp.abs_diff(other_temp) < 50 + } _ => false, } } @@ -147,8 +152,11 @@ impl PartialEq for Lamp { false }; - let bri_is_equal = match (self.state.brightness, other.state.brightness) { - (Some(self_bri), Some(other_bri)) => (self_bri - other_bri).abs() < 1. / 250., + let bri_is_equal = match (self.state.brightness, other.state.brightness) + { + (Some(self_bri), Some(other_bri)) => { + (self_bri - other_bri).abs() < 1. / 250. + } _ => false, }; @@ -184,7 +192,9 @@ impl Model { Model::TradfriE27 | Model::TradfriE14 | Model::HueGen4 => true, Model::TradfriCandle => false, // We assume no so that things at least don't break - Model::TradfriOther(_) | Model::HueOther(_) | Model::Other(_) => false, + Model::TradfriOther(_) | Model::HueOther(_) | Model::Other(_) => { + false + } } } diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs index ee010458..ebb15c80 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -25,7 +25,8 @@ impl TryInto for &[u8] { // Result::ok() let color_temp_mired = match get_key(map, "color_temp") { Ok(temp) => { - let color_temp: usize = json_to_u64(temp)?.try_into().expect("usize should be u64"); + let color_temp: usize = + json_to_u64(temp)?.try_into().expect("usize should be u64"); Some(color_temp) } Err(_) => None, @@ -60,7 +61,11 @@ impl TryInto for &[u8] { let on = match state.to_lowercase().as_str() { "on" => true, "off" => false, - other => return Err(invalid_err(&format!("on/off bool: {other}"))), + other => { + return Err(invalid_err(&format!( + "on/off bool: {other}" + ))) + } }; Some(on) } @@ -93,8 +98,14 @@ fn json_to_f64(json: &Value) -> Result { .expect("Should be Some if not using arbitrary precision")) } -fn get_key<'a>(map: &'a serde_json::Map, key: &str) -> Result<&'a Value, io::Error> { - let key_err = io::Error::new(io::ErrorKind::InvalidData, "Missing key from map: {key}"); +fn get_key<'a>( + map: &'a serde_json::Map, + key: &str, +) -> Result<&'a Value, io::Error> { + let key_err = io::Error::new( + io::ErrorKind::InvalidData, + "Missing key from map: {key}", + ); map.get(key).ok_or(key_err) } From 8c0ec87f57000b3404b9ab20020317b5b73072a9 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 12 Nov 2024 11:58:09 +0100 Subject: [PATCH 390/687] Clarify test and add warn for hallway on/off payload --- crates/zigbee-bridge/src/lib.rs | 13 +++++++++---- .../zigbee-bridge/src/lights/cached_bridge/mqtt.rs | 5 ++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 0fc7c898..6032b842 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -28,28 +28,33 @@ mod tests { #[ignore] #[tokio::test] async fn change_all_lights() { + std::env::set_var("RUST_LOG", "brain=trace,zigbee_bridge=trace,info"); let controller = Controller::start_bridge(); + println!("Setting to on, 2200"); for light in LIGHTS { - controller.set_brightness(light, 0.5); + controller.set_on(light); controller.set_color_temp(light, 2200); } - tokio::time::sleep(Duration::from_secs(2)).await; + tokio::time::sleep(Duration::from_secs(1)).await; + println!("Turning off"); for light in LIGHTS { controller.set_off(light); } - tokio::time::sleep(Duration::from_secs(2)).await; + tokio::time::sleep(Duration::from_secs(1)).await; + println!("Turning on to 4000"); for light in LIGHTS { controller.set_on(light); controller.set_color_temp(light, 4000); } - tokio::time::sleep(Duration::from_secs(2)).await; + tokio::time::sleep(Duration::from_secs(1)).await; + println!("Setting bri to 1.0"); for light in LIGHTS { controller.set_brightness(light, 1.0); } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index a0f7cc41..5a5f0ba4 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -1,6 +1,6 @@ use rumqttc::{AsyncClient, ClientError}; use serde_json::json; -use tracing::trace; +use tracing::{trace, warn}; use crate::lights::lamp::Lamp; use crate::QOS; @@ -51,6 +51,9 @@ impl Mqtt { let topic = format!("zigbee2mqtt/{friendly_name}/set"); trace!("Sending payload {payload} to lamp {friendly_name}"); + if friendly_name == "kitchen:hallway" && payload.contains("state") { + warn!("Sending payload {payload} to {friendly_name}"); + } self.publish(&topic, payload).await?; Ok(()) } From 534dd709f5f561c5c6db926579f608cd17d01b9f Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 12 Nov 2024 12:30:31 +0100 Subject: [PATCH 391/687] Apply feedback (mostly) --- crates/zigbee-bridge/src/lights.rs | 3 +- .../src/lights/cached_bridge/changes.rs | 2 +- .../src/lights/cached_bridge/mqtt.rs | 6 +-- crates/zigbee-bridge/src/lights/lamp.rs | 19 ++------ .../zigbee-bridge/src/lights/parse_state.rs | 48 +++++++++++-------- 5 files changed, 37 insertions(+), 41 deletions(-) diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index 91caee88..7ae5a954 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -43,8 +43,7 @@ impl Controller { .expect("Sender should never be dropped"); } - // TODO: document, is this lumen? Maybe use newtype pattern with a new lumen - // struct + /// Brightness from 0 to 1 pub fn set_brightness(&self, friendly_name: &str, brightness: f64) { self.change_sender .send((friendly_name.to_string(), Change::Brightness(brightness))) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index 244df32b..c96a8b34 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -67,6 +67,6 @@ async fn apply_change( }, }; - let with_change_applied = needed.apply(change); + let with_change_applied = needed.clone().apply(change); needed_states.insert(light_name, with_change_applied); } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index 5a5f0ba4..774a2de3 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -33,10 +33,8 @@ impl Mqtt { light_name: &str, needed: &Lamp, ) -> Result<(), ClientError> { - // TODO: Can we not send all the json for each lamp in one go? I - // remember you told me something about this but I forgot what it was. - // Might be useful to have a line documenting that here. <11-11-24, - // dvdsk> + // The IKEA lamps can only accept one state change command at a time, + // so we need to send each parameter in a separate json payload for payload in needed.to_payloads() { self.set(light_name, &payload).await?; } diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index dac22a87..42210c0e 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -48,9 +48,9 @@ impl Lamp { } } - pub(super) fn apply(&self, change: Change) -> Self { + pub(super) fn apply(self, change: Change) -> Self { Self { - model: self.model.clone(), + model: self.model, state: self.state.apply(change), } } @@ -61,10 +61,7 @@ impl Lamp { } impl LampState { - // TODO: How do you feel about letting this take ownership of self. Then the - // clone would move to the caller and the first parameter would take be &self - // but self <11-11-24, dvdsk> - fn apply(&self, change: Change) -> LampState { + fn apply(self, change: Change) -> LampState { let mut new_state = self.clone(); match change { Change::On(on) => new_state.on = Some(on), @@ -105,14 +102,8 @@ impl LampState { payloads.push(json!({ "color_temp_startup": self.color_temp_startup })); - // TODO: I might have said this somewhere already however I am too lazy - // to look up where: - // - // I am not sure if this creates json. As far as I know every string of - // json starts with { and ends with }. So this will not be one json - // string but text consisting of multiple concatenated bits of json. - // - // + // The IKEA lamps can only accept one state change command at a time, + // so we need to send each parameter in a separate json payload payloads.into_iter().map(|x| x.to_string()).collect() } } diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs index ebb15c80..0c6ab83d 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -1,28 +1,39 @@ use std::io; use serde_json::Value; +use thiserror::Error; use crate::lights::{lamp::LampState, mired_to_kelvin, normalize}; +#[derive(Error, Debug)] +pub(super) enum ParseError { + #[error("json error: {0}")] + Json(#[from] serde_json::Error), + #[error("io error: {0}")] + Io(#[from] io::Error), + #[error("invalid value: {0}")] + InvalidValue(String), +} + impl TryInto for &[u8] { - type Error = io::Error; // TODO: could be a parse error enum, saves having - // to go through the whole ErrorKind stuff. - // - // But this is fine too, kinda like the str for - // invalid_err() stuff - // - // but get_key(map, "color") could be - // map.get("color").ok_or(ParseError("Missing key - // from map: {key}")). Just an idea, do what you - // prefer. - // <11-11-24, dvdsk> + type Error = ParseError; // TODO: could be a parse error enum, saves having + // to go through the whole ErrorKind stuff. + // + // But this is fine too, kinda like the str for + // invalid_err() stuff + // + // but get_key(map, "color") could be + // map.get("color").ok_or(ParseError("Missing key + // from map: {key}")). Just an idea, do what you + // prefer. + // <11-11-24, dvdsk> fn try_into(self) -> Result { let json: Value = serde_json::from_slice(self)?; let map = json.as_object().ok_or(invalid_err("Object"))?; - // TODO: disappointed in clippy, match Ok -> Some, Err -> None is - // Result::ok() + // Could be done using .map(|temp| {...}).ok(), except that the question + // mark gets in the way let color_temp_mired = match get_key(map, "color_temp") { Ok(temp) => { let color_temp: usize = @@ -55,14 +66,11 @@ impl TryInto for &[u8] { let on = match get_key(map, "state") { Ok(on) => { let state = on.as_str().ok_or(invalid_err("String"))?; - // TODO: why not compare to uppercase ON and OFF? Now this is - // confusing because we set the state using uppercase ON and OFF - // in `to_payloads` <11-11-24, dvdsk> - let on = match state.to_lowercase().as_str() { - "on" => true, - "off" => false, + let on = match state { + "ON" => true, + "OFF" => false, other => { - return Err(invalid_err(&format!( + return Err(ParseError::InvalidValue(format!( "on/off bool: {other}" ))) } From 1dc23a819920788e14a372d69e26c4bdba46d635 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 12 Nov 2024 14:07:13 +0100 Subject: [PATCH 392/687] usb-bridge adds forgotten files --- crates/usb-bridge/src/usb.rs | 172 ++++++++++++++++++++++++++++ crates/usb-bridge/src/usb/device.rs | 72 ++++++++++++ 2 files changed, 244 insertions(+) create mode 100644 crates/usb-bridge/src/usb.rs create mode 100644 crates/usb-bridge/src/usb/device.rs diff --git a/crates/usb-bridge/src/usb.rs b/crates/usb-bridge/src/usb.rs new file mode 100644 index 00000000..b1198dfd --- /dev/null +++ b/crates/usb-bridge/src/usb.rs @@ -0,0 +1,172 @@ +use nusb::transfer; +use tokio::sync::mpsc; + +use ratelimited_logger as rl; +use tokio::time::{sleep, sleep_until, timeout}; + +use protocol::Affector; +use std::time::Duration; +use std::vec; + +use color_eyre::eyre::{bail, Context}; + +use tokio::time::Instant; + +mod device; + +pub(crate) struct ReconnectingUsb { + pub(crate) serial_number: String, + /// when we are allowed to poll the usb + /// device for more data again + pub(crate) next_poll: Instant, + pub(crate) conn: Option, + pub(crate) bytes: vec::IntoIter, + pub(crate) logger: ratelimited_logger::RateLimitedLogger, + pub(crate) to_send: mpsc::Receiver, +} + +pub(crate) enum Status { + Done, + CallAgain, +} + +impl ReconnectingUsb { + pub(crate) fn new(serial_number: String, to_send: mpsc::Receiver) -> Self { + ReconnectingUsb { + serial_number, + next_poll: Instant::now(), + conn: None, + bytes: Vec::new().into_iter(), + logger: ratelimited_logger::RateLimitedLogger::default(), + to_send, + } + } + + pub(crate) async fn get_affectors(&mut self) -> color_eyre::Result> { + let msg = loop { + if let Some(msg) = self + .try_request_data(device::get(protocol::usb::GET_AFFECTOR_LIST)) + .await? + { + break msg; + } + sleep(Duration::from_secs(5)).await; + }; + let msg = protocol::Msg::<50>::decode(msg.to_vec()).wrap_err( + "Could not decode protocol::Msg, maybe the protocol library \ + has changed since this was compiled", + )?; + let protocol::Msg::AffectorList(list) = msg else { + unreachable!("affector list request is only anwserd by affector list msg"); + }; + + Ok(list.values.to_vec()) + } + + pub(crate) async fn handle_usb(&mut self) -> Vec { + let mut retry_period = Duration::from_millis(100); + loop { + if let Some(len) = self.bytes.next() { + if len == 0 { + self.bytes = Vec::new().into_iter(); + continue; + } + return self.bytes.by_ref().take(len as usize).collect(); + } + + if let Ok(order) = self.to_send.try_recv() { + self.send_order(&mut retry_period, order).await; + } + + self.receive_bytes(&mut retry_period).await; + } + } + + pub(crate) async fn receive_bytes(&mut self, retry_period: &mut Duration) { + self.bytes = loop { + sleep_until(self.next_poll).await; + self.next_poll = Instant::now() + Duration::from_millis(100); + + match self + .try_request_data(device::get(protocol::usb::GET_QUEUED_MESSAGES)) + .await + { + Ok(Some(bytes)) => break bytes.into_iter(), + Ok(None) => continue, + Err(e) => { + let logger = &mut self.logger; + rl::warn!(logger; "could not receive sensor message: {e:?}"); + *retry_period *= 2; + *retry_period = (*retry_period).min(Duration::from_secs(30)); + sleep(*retry_period).await; + } + }; + }; + } + + pub(crate) async fn send_order(&mut self, retry_period: &mut Duration, order: Affector) { + let data = order.encode(); + for _ in 0..2 { + match self + .try_send_data(device::send(protocol::usb::AFFECTOR_ORDER, &data)) + .await + { + Ok(Status::Done) => break, + Ok(Status::CallAgain) => continue, + Err(e) => { + let logger = &mut self.logger; + rl::warn!(logger; "could not send affector order: {e:?}"); + *retry_period *= 2; + *retry_period = (*retry_period).min(Duration::from_secs(30)); + sleep(*retry_period).await; + } + } + } + } + + pub(crate) async fn try_request_data( + &mut self, + request: transfer::ControlIn, + ) -> color_eyre::Result>> { + if let Some(device) = self.conn.take() { + let do_request = device.control_in(request); + let msg = match timeout(Duration::from_secs(1), do_request) + .await + .map(|res| res.into_result()) + { + Ok(Ok(msg)) => msg, + Ok(e @ Err(_)) => e.wrap_err("Something went wrong with control_in request")?, + Err(_timeout) => bail!("Usb control_in request timed out"), + }; + + self.conn = Some(device); + return Ok(Some(msg)); + } + + let list = device::list_usb_devices(&self.serial_number)?; + self.conn = Some(device::get_usb_device(list, &self.serial_number)?); + + Ok(None) // no errors but not done yet, call us again + } + + pub(crate) async fn try_send_data( + &mut self, + request: transfer::ControlOut<'_>, + ) -> color_eyre::Result { + if let Some(device) = self.conn.take() { + device + .control_out(request) + .await + .into_result() + .wrap_err("Something went wrong with control_out request")?; + + self.conn = Some(device); + return Ok(Status::Done); + } + + let list = device::list_usb_devices(&self.serial_number)?; + self.conn = Some(device::get_usb_device(list, &self.serial_number)?); + + Ok(Status::CallAgain) // no errors but not done yet, call us again + } +} diff --git a/crates/usb-bridge/src/usb/device.rs b/crates/usb-bridge/src/usb/device.rs new file mode 100644 index 00000000..f2d9af00 --- /dev/null +++ b/crates/usb-bridge/src/usb/device.rs @@ -0,0 +1,72 @@ +use color_eyre::eyre::{eyre, Context}; +use color_eyre::Section; +use nusb::transfer; + +pub(crate) fn get(request: u8) -> transfer::ControlIn { + transfer::ControlIn { + control_type: transfer::ControlType::Vendor, + recipient: transfer::Recipient::Interface, + request, + value: 0, + index: 0, + length: protocol::usb::SEND_BUFFER_SIZE.try_into().expect("fits"), + } +} + +pub(crate) fn send(request: u8, data: &[u8]) -> transfer::ControlOut { + transfer::ControlOut { + control_type: transfer::ControlType::Vendor, + recipient: transfer::Recipient::Interface, + request, + value: 0, + index: 0, + data, + } +} + +pub(crate) fn list_usb_devices( + serial_number: &str, +) -> Result, color_eyre::eyre::Error> { + let list: Vec<_> = nusb::list_devices() + .wrap_err("Could not list usb devices")? + .filter(|d| { + d.serial_number() + .is_some_and(|d| d.eq_ignore_ascii_case(serial_number)) + }) + .collect(); + Ok(list) +} + +pub(crate) fn get_usb_device( + list: Vec, + serial_number: &str, +) -> Result { + match list.as_slice() { + [dev] => dev, + [] => { + return Err(eyre!("No usb device found with the correct serial")) + .with_note(|| format!("looking for device with serial: {serial_number}")) + .suggestion( + "Is the device working (sometimes programming fails) \ + & connected?", + ); + } + more => { + return Err(eyre!("Multiple usb devices have the same serial number") + .with_note(|| format!("they are: {more:?}"))); + } + } + .open() + .wrap_err("Could not open the usb device") + .suggestion("Try running as sudo") + .with_suggestion(|| { + format!( + "Add a .rules file in /etc/udev/rules.d with line: \ + ATTRS{{serial}}==\"{}\", MODE=\"660\", GROUP=\"{}\", TAG+=\"uaccess\"", + serial_number, + users::get_current_groupname() + .expect("process should always run as a group") + .to_string_lossy() + ) + }) +} From f5b0af73d70cead266b4a29bfc21b06b55dd7061 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 13 Nov 2024 14:55:42 +0100 Subject: [PATCH 393/687] usb-bridge/data-source client remove non reconnecting client, fix error reporting in recon client --- crates/data-server/src/api/data_source.rs | 35 ++--------- .../src/api/data_source/reconnecting.rs | 62 +++++++++++++------ crates/data-server/src/server/watch.rs | 2 +- crates/usb-bridge/src/main.rs | 14 +++-- crates/usb-bridge/src/usb.rs | 1 + 5 files changed, 59 insertions(+), 55 deletions(-) diff --git a/crates/data-server/src/api/data_source.rs b/crates/data-server/src/api/data_source.rs index bbf34034..6845a980 100644 --- a/crates/data-server/src/api/data_source.rs +++ b/crates/data-server/src/api/data_source.rs @@ -1,4 +1,5 @@ use protocol::{affector, DecodeMsgError}; +use reconnecting::SendError; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf}; use tokio::net::{TcpStream, ToSocketAddrs}; @@ -16,8 +17,8 @@ pub enum Error { } pub struct Client { - sender: Sender, - receiver: Receiver, + pub sender: Sender, + pub receiver: Receiver, } impl Client { @@ -58,32 +59,6 @@ impl Client { sender: Sender(writer), }) } - - /// # Cancel safety - /// This is cancel safe, if it is canceled the reading has not been send yet - pub async fn send_reading(&mut self, reading: protocol::Reading) -> Result<(), std::io::Error> { - self.sender.send_reading(reading).await - } - - /// # Cancel safety - /// This is cancel safe, if it is canceled the report has not been send yet - pub async fn send_error(&mut self, report: protocol::Error) -> Result<(), std::io::Error> { - self.sender.send_error(report).await - } - - /// Checks if the encoded message can be decoded then sends it. - pub async fn check_send_encoded(&mut self, msg: &[u8]) -> Result<(), SendPreEncodedError> { - protocol::Msg::<50>::decode(msg.to_vec()).map_err(SendPreEncodedError::EncodingCheck)?; - self.send_bytes(msg).await.map_err(SendPreEncodedError::Io) - } - - pub(crate) async fn send_bytes(&mut self, bytes: &[u8]) -> Result<(), std::io::Error> { - self.sender.send_bytes(bytes).await - } - - pub fn split(self) -> (Sender, Receiver) { - (self.sender, self.receiver) - } } pub struct Sender(OwnedWriteHalf); @@ -95,10 +70,10 @@ pub struct Receiver { #[derive(Debug, thiserror::Error)] pub enum SendPreEncodedError { - #[error("Ran into io error while sending pre-encoded msg: {0}")] - Io(std::io::Error), #[error("Pre-encoded message, could not be decoded it might be from a previous version: {0}")] EncodingCheck(DecodeMsgError), + #[error("Error while sending pre-encoded msg: {0}")] + Sending(SendError), } impl Sender { diff --git a/crates/data-server/src/api/data_source/reconnecting.rs b/crates/data-server/src/api/data_source/reconnecting.rs index d2d62c88..d8949804 100644 --- a/crates/data-server/src/api/data_source/reconnecting.rs +++ b/crates/data-server/src/api/data_source/reconnecting.rs @@ -10,7 +10,7 @@ use tracing::{info, warn}; use super::{ReceiveError, SendPreEncodedError}; pub struct Client { - conn_handler: AbortOnDrop, + _conn_handler_task: AbortOnDrop, to_send_tx: mpsc::Sender<(Vec, SendFeedback)>, } @@ -31,21 +31,22 @@ async fn handle_conn( loop { let mut retry_period = Duration::from_millis(200); let conn = reconnect(addr, &affectors, &mut retry_period).await; - let (sender, receiver) = conn.split(); if let Some(ref msgs_recieved) = msgs_recieved { let res = ( - handle_sending(sender, &mut msgs_to_send), - handle_recieving(receiver, msgs_recieved), + handle_sending(conn.sender, &mut msgs_to_send), + handle_recieving(conn.receiver, msgs_recieved), ) .race() .await; match res { - SendOrRecvError::Sending(e) => todo!(), - SendOrRecvError::Recieving(e) => todo!(), + SendOrRecvError::Sending(e) => tracing::error!("Error sending to data-server: {e}"), + SendOrRecvError::Recieving(e) => { + tracing::error!("Error receiving order from data-server: {e}") + } } } else { - handle_sending(sender, &mut msgs_to_send).await; + handle_sending(conn.sender, &mut msgs_to_send).await; } } } @@ -72,6 +73,20 @@ async fn handle_sending( } } +#[derive(Debug, thiserror::Error)] +pub enum SendError { + #[error("Error while sending data to data-server: {0}")] + Sending(String), + #[error( + "Sending the data was aborted, probably due to \ + reconnect due to failed recieve" + )] + Aborted, + /// returns the encoded message that you tried to send + #[error("Sender queue is full, it has probably been disconnected for a while")] + Overloaded { bytes: Vec }, +} + async fn handle_recieving( mut receiver: super::Receiver, msgs_recieved: &mpsc::Sender, @@ -103,22 +118,32 @@ impl Client { let task = handle_conn(addr, affectors, to_send_rx, affector_tx); let handle = tokio::spawn(task); Self { - conn_handler: AbortOnDrop(handle), + _conn_handler_task: AbortOnDrop(handle), to_send_tx, } } - async fn send_bytes(&mut self, bytes: Vec) -> Result<(), ()> { + async fn send_bytes(&mut self, bytes: Vec) -> Result<(), SendError> { let (tx, rx) = oneshot::channel(); - self.to_send_tx.send((bytes, tx)).await; - rx.await + match self.to_send_tx.try_send((bytes, tx)) { + Ok(()) => (), + Err(mpsc::error::TrySendError::Full((bytes, _))) => { + return Err(SendError::Overloaded { bytes }) + } + Err(mpsc::error::TrySendError::Closed(_)) => panic!("re-connect loop should never end"), + } + match rx.await { + Ok(Ok(())) => Ok(()), + Ok(Err(send)) => Err(SendError::Sending(send)), + Err(_) => Err(SendError::Aborted), + } } /// # Cancel safety /// This is cancel safe however the connection will need to be re-established /// the next time its called. This will retry forever, you should call this /// in a timeout future if that is a problem. - pub async fn send_reading(&mut self, reading: protocol::Reading) { + pub async fn send_reading(&mut self, reading: protocol::Reading) -> Result<(), SendError> { let mut readings = protocol::SensorMessage::<1>::default(); readings .values @@ -127,24 +152,25 @@ impl Client { let msg = protocol::Msg::Readings(readings); let bytes = msg.encode(); - self.send_bytes(&bytes).await + self.send_bytes(bytes).await } /// # Cancel safety /// This is cancel safe however the connection will need to be re-established /// the next time its called. This will retry forever, you should call this /// in a timeout future if that is a problem. - pub async fn send_error(&mut self, report: protocol::Error) { + pub async fn send_error(&mut self, report: protocol::Error) -> Result<(), SendError> { let msg = protocol::Msg::<1>::ErrorReport(protocol::ErrorReport::new(report)); let bytes = msg.encode(); - self.send_bytes(&bytes).await + self.send_bytes(bytes).await } - pub async fn check_send_encoded(&mut self, msg: &[u8]) -> Result<(), SendPreEncodedError> { + pub async fn check_send_encoded(&mut self, msg: Vec) -> Result<(), SendPreEncodedError> { protocol::Msg::<50>::decode(msg.to_vec()).map_err(SendPreEncodedError::EncodingCheck)?; - self.send_bytes(msg).await; - Ok(()) + self.send_bytes(msg) + .await + .map_err(SendPreEncodedError::Sending) } } diff --git a/crates/data-server/src/server/watch.rs b/crates/data-server/src/server/watch.rs index 56aa66d1..d4b1f18a 100644 --- a/crates/data-server/src/server/watch.rs +++ b/crates/data-server/src/server/watch.rs @@ -1,4 +1,4 @@ -use crate::api::subscriber::{AffectorError, SubMessage}; +use crate::api::subscriber::SubMessage; use std::time::Duration; use super::{AffectorRegistar, Event}; diff --git a/crates/usb-bridge/src/main.rs b/crates/usb-bridge/src/main.rs index 71e62edd..5feb02bb 100644 --- a/crates/usb-bridge/src/main.rs +++ b/crates/usb-bridge/src/main.rs @@ -33,15 +33,17 @@ async fn main() -> Result<(), color_eyre::Report> { .get_affectors() .await .wrap_err("Could not get affector list")?; - let mut server_client = reconnecting::Client::new(args.data_server, affectors, Some(order_tx)); + // let mut server_client = reconnecting::Client::new(args.data_server, affectors, Some(order_tx)); + dbg!(affectors); loop { let encoded_msg = usb.handle_usb().await; - server_client - .check_send_encoded(&encoded_msg) - .await - .wrap_err("Should be correctly encoded") - .suggestion("Check if this needs to be updated")?; + dbg!("msg: {}", encoded_msg.len()); + // server_client + // .check_send_encoded(encoded_msg) + // .await + // .wrap_err("Should be correctly encoded") + // .suggestion("Check if this needs to be updated")?; } } diff --git a/crates/usb-bridge/src/usb.rs b/crates/usb-bridge/src/usb.rs index b1198dfd..443a7a09 100644 --- a/crates/usb-bridge/src/usb.rs +++ b/crates/usb-bridge/src/usb.rs @@ -66,6 +66,7 @@ impl ReconnectingUsb { pub(crate) async fn handle_usb(&mut self) -> Vec { let mut retry_period = Duration::from_millis(100); loop { + tracing::info!("polling usb"); if let Some(len) = self.bytes.next() { if len == 0 { self.bytes = Vec::new().into_iter(); From 510a484e976178784aa43fe15c889024e04b0277 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 13 Nov 2024 15:24:48 +0100 Subject: [PATCH 394/687] adds instrumentation + refactor send_all --- crates/brain/test.sh | 11 ++------ .../zigbee-bridge/src/lights/cached_bridge.rs | 10 +++---- .../src/lights/cached_bridge/changes.rs | 27 ++++++++++++------- .../src/lights/cached_bridge/poll.rs | 4 ++- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/crates/brain/test.sh b/crates/brain/test.sh index 9ed58c4b..8b5243fa 100755 --- a/crates/brain/test.sh +++ b/crates/brain/test.sh @@ -1,14 +1,7 @@ #!/usr/bin/env bash -SERVER="sgc" # ssh config name or full address -cmds="sudo systemctl stop brain" -ssh -t $SERVER "$cmds" - -RUST_LOG=reqwest::connect=info,hyper_util=info,sled=info,trace RUST_BACKTRACE=1 cargo r -- \ +RUST_LOG=reqwest::connect=info,hyper_util=info,sled=info,rumqttc::state=info,zigbee_bridge::lights::cached_bridge::mqtt=debug,trace RUST_BACKTRACE=1 cargo r -- \ --data-server 192.168.1.43:1235 \ - --mpd-ip 127.0.0.1 \ + --mpd-ip 192.168.1.43 \ --port 34326 \ --hue-bridge-ip 192.168.1.11 - -cmds="sudo systemctl start brain" -ssh -t $SERVER "$cmds" diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index c97b456f..7d45a606 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -16,11 +16,8 @@ mod poll; const CHANGE_TIMEOUT: Duration = Duration::from_secs(5); const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); -pub(super) async fn run( - mut change_receiver: mpsc::UnboundedReceiver<(String, Change)>, -) -> ! { - let mut options = - MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); +pub(super) async fn run(mut change_receiver: mpsc::UnboundedReceiver<(String, Change)>) -> ! { + let mut options = MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); // Set incoming to max mqtt packet size, outgoing to rumqtt default options.set_max_packet_size(2_usize.pow(28), 10240); // incoming: ~ 268 MB @@ -29,8 +26,7 @@ pub(super) async fn run( // Reconnecting to broker is handled by Eventloop::poll let channel_capacity = 128; - let (client, eventloop) = - AsyncClient::new(options.clone(), channel_capacity); + let (client, eventloop) = AsyncClient::new(options.clone(), channel_capacity); let mqtt = Mqtt::new(client); mqtt.subscribe("zigbee2mqtt/bridge/devices").await.unwrap(); diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index c96a8b34..d3a1d93f 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use tokio::sync::{mpsc, RwLock}; use tokio::time::{sleep, timeout}; -use tracing::trace; +use tracing::{instrument, trace}; use super::{mqtt::Mqtt, CHANGE_TIMEOUT, WAIT_FOR_INIT_STATES}; use crate::lights::lamp::{Change, Lamp}; @@ -17,9 +17,7 @@ pub(super) async fn handle( // Give the initial known states a chance to be fetched sleep(WAIT_FOR_INIT_STATES).await; loop { - if let Ok(change) = - timeout(CHANGE_TIMEOUT, change_receiver.recv()).await - { + if let Ok(change) = timeout(CHANGE_TIMEOUT, change_receiver.recv()).await { trace!("Received change: {change:?}"); apply_change(change, known_states, needed_states).await; } @@ -27,6 +25,7 @@ pub(super) async fn handle( } } +#[instrument(skip_all)] async fn send_all( known_states: &RwLock>, needed_states: &mut HashMap, @@ -38,17 +37,27 @@ async fn send_all( continue; }; - let known = known_states.get(light_name); - if Some(needed) != known { - trace!( - "Sending needed state {needed:?} to replace known {known:?}" - ); + let Some(known) = known_states.get(light_name) else { + // Ignore errors because we will retry if the state hasn't changed + let _ = mqtt.send_new_state(light_name, needed).await; + continue; + }; + + if needed != known { + if light_name == "kitchen:ceiling" { + trace!( + "Lamp {light_name} + sending needed {needed:?} + to replace known {known:?}" + ); + } // Ignore errors because we will retry if the state hasn't changed let _ = mqtt.send_new_state(light_name, needed).await; } } } +#[instrument(skip_all)] async fn apply_change( change: Option<(String, Change)>, known_states: &RwLock>, diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 2b0bb0b1..26ff0825 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, time::Duration}; use rumqttc::{Event, EventLoop, Incoming}; use serde_json::Value; use tokio::{sync::RwLock, time::sleep}; -use tracing::trace; +use tracing::{instrument, trace}; use crate::lights::lamp::{Lamp, LampState, Model}; @@ -45,6 +45,7 @@ pub(super) async fn poll_mqtt( } } +#[instrument(skip_all)] fn parse_message(message: Event) -> Message { match message { Event::Incoming(incoming) => match incoming { @@ -89,6 +90,7 @@ enum Message { Other, } +#[instrument(skip_all)] fn parse_device(device: &Value) -> (String, Model) { let properties = device.as_object().unwrap(); From da99589205a3bc516525e2e710a762e6df5c6d99 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 13 Nov 2024 21:55:09 +0100 Subject: [PATCH 395/687] changes::handle now only sends needed changes & waits a second for changes to apply before resending --- Cargo.lock | 3 + Cargo.toml | 3 +- crates/brain/Cargo.toml | 2 +- crates/data-server/Cargo.toml | 2 +- crates/data-store/Cargo.toml | 4 +- crates/log-store/Cargo.toml | 4 +- crates/zigbee-bridge/Cargo.toml | 3 + .../zigbee-bridge/src/lights/cached_bridge.rs | 15 +- .../src/lights/cached_bridge/changes.rs | 65 +++++--- .../src/lights/cached_bridge/mqtt.rs | 105 +++++++----- crates/zigbee-bridge/src/lights/lamp.rs | 156 ++++++++++++------ 11 files changed, 230 insertions(+), 132 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 24951906..6e078421 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4284,8 +4284,11 @@ name = "zigbee-bridge" version = "0.1.0" dependencies = [ "colorimetry", + "futures", + "futures-concurrency", "rumqttc", "serde_json", + "strum", "thiserror", "tokio", "tracing", diff --git a/Cargo.toml b/Cargo.toml index 73eb8648..95c506f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,13 +19,14 @@ color-eyre = "0.6.3" tracing = "0.1.40" tracing-error = "0.2.0" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +futures-concurrency = "7.6.2" time = "0.3.36" jiff = "0.1" clap = { version = "4", features = ["derive"]} thiserror = "1" [workspace.package] -rust-version = "1.78" +rust-version = "1.82" edition = "2021" license = "GPLv3" authors = ["David Kleingeld & Eva van Houten"] diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 0fc593fc..7e3e2c76 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -41,5 +41,5 @@ tracing = {workspace = true} tracing-subscriber = { workspace = true, features = ["env-filter"] } tracing-journald = "0.3.0" clap = { workspace = true } -futures-concurrency = "7.5.0" +futures-concurrency = { workspace = true } strum = { version = "0.26.2", default-features = false, features = ["derive"] } diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index 2b745c68..30e4a616 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -25,7 +25,7 @@ futures = "0.3.30" tokio-serde = { version = "0.9.0", features = ["bincode"] } tokio-util = { version = "0.7.11", features = ["codec"] } serde = { version = "1.0.208", features = ["derive"] } -futures-concurrency = "7.6.1" +futures-concurrency = { workspace = true } slotmap = "1.0.7" tracing-futures = "0.2.5" socket2 = "0.5.7" diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index f20ce859..55386560 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -25,7 +25,7 @@ data-server = { workspace = true } byteseries = { workspace = true } tokio = { workspace = true, features = ["fs", "net", "rt-multi-thread", "sync"] } -futures-concurrency = "7.6.1" +futures-concurrency = { workspace = true } serde = { version = "1.0.203", features = ["derive"] } thiserror = { workspace = true } futures = "0.3.30" @@ -34,7 +34,7 @@ num = "0.4.3" hdrhistogram = "7.5.4" [dev-dependencies] -futures-concurrency = "7.6.1" +futures-concurrency = { workspace = true } nucleo-matcher = "0.3.1" reserve-port = "2.0.1" temp-dir = "0.1.13" diff --git a/crates/log-store/Cargo.toml b/crates/log-store/Cargo.toml index 1adc8aab..a589c539 100644 --- a/crates/log-store/Cargo.toml +++ b/crates/log-store/Cargo.toml @@ -25,7 +25,7 @@ byteseries = { workspace = true } rpc = { workspace = true } tokio = { workspace = true, features = ["fs", "net", "rt-multi-thread", "sync"] } -futures-concurrency = "7.6.1" +futures-concurrency = { workspace = true } serde = { version = "1.0.203", features = ["derive"] } bincode = "1.3.3" thiserror = { workspace = true } @@ -36,7 +36,7 @@ hdrhistogram = "7.5.4" derivative = "2.2.0" [dev-dependencies] -futures-concurrency = "7.6.1" +futures-concurrency = { workspace = true } heapless = "0.8.0" nucleo-matcher = "0.3.1" reserve-port = "2.0.1" diff --git a/crates/zigbee-bridge/Cargo.toml b/crates/zigbee-bridge/Cargo.toml index f9b68fba..362ca918 100644 --- a/crates/zigbee-bridge/Cargo.toml +++ b/crates/zigbee-bridge/Cargo.toml @@ -13,5 +13,8 @@ colorimetry = { git = "https://github.com/harbik/colorimetry", features = ["cct" rumqttc = { version = "0.24.0", default-features = false } serde_json = "1.0.132" thiserror.workspace = true +futures-concurrency = { workspace = true } tokio = { workspace = true, features = ["sync"] } tracing = { workspace = true } +futures = "0.3.31" +strum = { version = "0.26.3", features = ["derive"] } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 7d45a606..17e36785 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -1,5 +1,4 @@ use std::collections::HashMap; -use std::time::Duration; use rumqttc::{AsyncClient, MqttOptions}; use tokio::sync::{mpsc, RwLock}; @@ -13,21 +12,18 @@ mod changes; mod mqtt; mod poll; -const CHANGE_TIMEOUT: Duration = Duration::from_secs(5); -const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); -pub(super) async fn run(mut change_receiver: mpsc::UnboundedReceiver<(String, Change)>) -> ! { +pub(super) async fn run(change_receiver: mpsc::UnboundedReceiver<(String, Change)>) -> ! { let mut options = MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); // Set incoming to max mqtt packet size, outgoing to rumqtt default options.set_max_packet_size(2_usize.pow(28), 10240); // incoming: ~ 268 MB let known_states = RwLock::new(HashMap::new()); - let mut needed_states = HashMap::new(); // Reconnecting to broker is handled by Eventloop::poll let channel_capacity = 128; let (client, eventloop) = AsyncClient::new(options.clone(), channel_capacity); - let mqtt = Mqtt::new(client); + let mut mqtt = Mqtt::new(client); mqtt.subscribe("zigbee2mqtt/bridge/devices").await.unwrap(); for light in LIGHTS { @@ -39,12 +35,7 @@ pub(super) async fn run(mut change_receiver: mpsc::UnboundedReceiver<(String, Ch trace!("Starting main zigbee management loops"); let poll_mqtt = poll::poll_mqtt(eventloop, &known_states); - let handle_changes = changes::handle( - &mut change_receiver, - &mqtt, - &known_states, - &mut needed_states, - ); + let handle_changes = changes::handle(change_receiver, &mut mqtt, &known_states); tokio::select! { () = handle_changes => unreachable!("should not panic"), diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index d3a1d93f..459aef8d 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -1,37 +1,56 @@ use std::collections::HashMap; +use std::time::Duration; use tokio::sync::{mpsc, RwLock}; use tokio::time::{sleep, timeout}; use tracing::{instrument, trace}; -use super::{mqtt::Mqtt, CHANGE_TIMEOUT, WAIT_FOR_INIT_STATES}; +use super::mqtt::Mqtt; use crate::lights::lamp::{Change, Lamp}; use crate::LIGHTS; pub(super) async fn handle( - change_receiver: &mut mpsc::UnboundedReceiver<(String, Change)>, - mqtt: &Mqtt, + mut change_receiver: mpsc::UnboundedReceiver<(String, Change)>, + mqtt: &mut Mqtt, known_states: &RwLock>, - needed_states: &mut HashMap, ) -> ! { + const MQTT_MIGHT_BE_DOWN_TIMEOUT: Duration = Duration::from_secs(5); + const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); + // Give the initial known states a chance to be fetched sleep(WAIT_FOR_INIT_STATES).await; + let mut needed_states = HashMap::new(); + let mut call_again_in = MQTT_MIGHT_BE_DOWN_TIMEOUT; + loop { - if let Ok(change) = timeout(CHANGE_TIMEOUT, change_receiver.recv()).await { + if let Ok(res) = timeout(call_again_in, change_receiver.recv()).await { + let res = res.expect("Channel should never close"); + let (light_name, change) = res; + trace!("Received change: {change:?}"); - apply_change(change, known_states, needed_states).await; - } - send_all(known_states, needed_states, mqtt).await; + apply_change(light_name, change, known_states, &mut needed_states).await; + }; + + call_again_in = send_and_queue(known_states, &mut needed_states, mqtt) + .await + .min(MQTT_MIGHT_BE_DOWN_TIMEOUT); } } +/// Might not be done in case a light property in needed does not match known +/// however has recently been set/send. Needs a recheck in the near future to +/// make sure the set/send takes effect. We do not send it again now as that +/// would be a little spammy. Returns when we need to recheck. If we do not need +/// to do so we return Duration::MAX. #[instrument(skip_all)] -async fn send_all( +async fn send_and_queue( known_states: &RwLock>, needed_states: &mut HashMap, - mqtt: &Mqtt, -) { + mqtt: &mut Mqtt, +) -> Duration { + let mut call_again_in = Duration::MAX; let known_states = known_states.read().await; + for light_name in LIGHTS { let Some(needed) = needed_states.get(light_name) else { continue; @@ -39,31 +58,33 @@ async fn send_all( let Some(known) = known_states.get(light_name) else { // Ignore errors because we will retry if the state hasn't changed - let _ = mqtt.send_new_state(light_name, needed).await; + if let Ok(dur) = mqtt + .try_send_state_diff(light_name, needed.property_list()) + .await + { + call_again_in = call_again_in.min(dur); + } continue; }; if needed != known { - if light_name == "kitchen:ceiling" { - trace!( - "Lamp {light_name} - sending needed {needed:?} - to replace known {known:?}" - ); - } + let diff = needed.changes_relative_to(known); // Ignore errors because we will retry if the state hasn't changed - let _ = mqtt.send_new_state(light_name, needed).await; + if let Ok(dur) = mqtt.try_send_state_diff(light_name, diff).await { + call_again_in = call_again_in.min(dur); + } } } + call_again_in } #[instrument(skip_all)] async fn apply_change( - change: Option<(String, Change)>, + light_name: String, + change: Change, known_states: &RwLock>, needed_states: &mut HashMap, ) { - let (light_name, change) = change.expect("Channel should never close"); let known_states = known_states.read().await; let needed = match needed_states.get(&light_name) { diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index 774a2de3..cbacd099 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -1,23 +1,27 @@ +use std::collections::HashMap; +use std::time::{Duration, Instant}; + use rumqttc::{AsyncClient, ClientError}; use serde_json::json; use tracing::{trace, warn}; -use crate::lights::lamp::Lamp; +use crate::lights::lamp::{LampProperty, LampPropertyDiscriminants}; use crate::QOS; pub(super) struct Mqtt { client: AsyncClient, + property_last_set: HashMap>, } impl Mqtt { pub(super) fn new(client: AsyncClient) -> Self { - Mqtt { client } + Mqtt { + client, + property_last_set: HashMap::new(), + } } - pub(super) async fn subscribe( - &self, - topic: &str, - ) -> Result<(), ClientError> { + pub(super) async fn subscribe(&self, topic: &str) -> Result<(), ClientError> { self.client.subscribe(topic, QOS).await } @@ -25,53 +29,66 @@ impl Mqtt { trace!("Requesting state for light {name}"); let payload = json!({"state": ""}); - self.get(name, &payload.to_string()).await.unwrap(); + get(&self.client, name, &payload.to_string()).await.unwrap(); } - pub(super) async fn send_new_state( - &self, + pub(super) async fn try_send_state_diff( + &mut self, light_name: &str, - needed: &Lamp, - ) -> Result<(), ClientError> { - // The IKEA lamps can only accept one state change command at a time, - // so we need to send each parameter in a separate json payload - for payload in needed.to_payloads() { - self.set(light_name, &payload).await?; + diff: Vec, + ) -> Result { + const TIME_IT_TAKES_TO_APPLY_CHANGE: Duration = Duration::from_secs(1); + let mut new_call_needed_in: Duration = Duration::MAX; + + if let Some(last_set) = self.property_last_set.get_mut(light_name) { + for change in diff { + let change_key = change.clone().into(); + match last_set.get(&change_key) { + None => { + set(&self.client, light_name, &change.clone().into_payload()).await?; + last_set.insert(change_key, Instant::now()); + } + Some(at) if at.elapsed() > TIME_IT_TAKES_TO_APPLY_CHANGE => { + set(&self.client, light_name, &change.clone().into_payload()).await?; + last_set.insert(change_key, Instant::now()); + } + Some(at) => { + let until = at.saturating_duration_since(Instant::now()); + new_call_needed_in = new_call_needed_in.min(until); + } + } + } + } else { + let mut last_set = HashMap::new(); + for change in diff { + let change_key: LampPropertyDiscriminants = change.clone().into(); + set(&self.client, light_name, &change.clone().into_payload()).await?; + last_set.insert(change_key, Instant::now()); + } } - Ok(()) + + Ok(new_call_needed_in) } +} - async fn set( - &self, - friendly_name: &str, - payload: &str, - ) -> Result<(), ClientError> { - let topic = format!("zigbee2mqtt/{friendly_name}/set"); +async fn set(client: &AsyncClient, friendly_name: &str, payload: &str) -> Result<(), ClientError> { + let topic = format!("zigbee2mqtt/{friendly_name}/set"); - trace!("Sending payload {payload} to lamp {friendly_name}"); - if friendly_name == "kitchen:hallway" && payload.contains("state") { - warn!("Sending payload {payload} to {friendly_name}"); - } - self.publish(&topic, payload).await?; - Ok(()) + trace!("Sending payload {payload} to lamp {friendly_name}"); + if friendly_name == "kitchen:hallway" && payload.contains("state") { + warn!("Sending payload {payload} to {friendly_name}"); } + publish(client, &topic, payload).await?; + Ok(()) +} - async fn get( - &self, - friendly_name: &str, - payload: &str, - ) -> Result<(), ClientError> { - let topic = format!("zigbee2mqtt/{friendly_name}/get"); +async fn get(client: &AsyncClient, friendly_name: &str, payload: &str) -> Result<(), ClientError> { + let topic = format!("zigbee2mqtt/{friendly_name}/get"); - self.publish(&topic, payload).await?; - Ok(()) - } + publish(client, &topic, payload).await?; + Ok(()) +} - async fn publish( - &self, - topic: &str, - payload: &str, - ) -> Result<(), ClientError> { - self.client.publish(topic, QOS, false, payload).await - } +async fn publish(client: &AsyncClient, topic: &str, payload: &str) -> Result<(), ClientError> { + client.publish(topic, QOS, false, payload).await } diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 42210c0e..dd08f3b3 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -1,15 +1,10 @@ use std::collections::HashMap; use serde_json::json; +use strum::EnumDiscriminants; use crate::lights::{conversion::temp_to_xy, denormalize, kelvin_to_mired}; -#[derive(Default, Clone, Debug)] -pub(super) struct Lamp { - pub(super) model: Option, - pub(super) state: LampState, -} - #[derive(Debug, Clone)] pub(super) struct LampState { pub(super) brightness: Option, @@ -33,7 +28,41 @@ impl Default for LampState { } } +#[derive(Default, Clone, Debug)] +pub(super) struct Lamp { + pub(super) model: Option, + pub(super) state: LampState, +} + +#[derive(Debug, EnumDiscriminants, Clone)] +#[strum_discriminants(derive(Hash))] +pub(super) enum LampProperty { + Brightness(f64), + ColorTempK(usize), + ColorXY((f64, f64)), + On(bool), + ColorTempStartup(String), +} + +impl LampProperty { + pub(crate) fn into_payload(self) -> String { + match self { + LampProperty::Brightness(bri) => json!({ "brightness": denormalize(bri) }), + LampProperty::ColorTempK(k) => json!({ "color_temp": kelvin_to_mired(k) }), + LampProperty::ColorXY((x, y)) => json!({ "color": {"x": x, "y": y} }), + LampProperty::On(lamp_on) if lamp_on => json!({"state": "ON"}), + LampProperty::On(_) => json!({"state": "OFF"}), + LampProperty::ColorTempStartup(s) => json!({"color_temp_startup": s}), + } + .to_string() + } +} + impl Lamp { + pub(super) fn changes_relative_to(&self, other: &Self) -> Vec { + self.state.changes_relative_to(&other.state) + } + pub(super) fn store_model(&self, model: Model) -> Self { Self { model: Some(model), @@ -55,12 +84,64 @@ impl Lamp { } } - pub(super) fn to_payloads(&self) -> Vec { - self.state.to_payloads(&self.model) + pub(crate) fn property_list(&self) -> Vec { + self.state.property_list() } } +fn bri_close(a: f64, b: f64) -> bool { + (a - b).abs() < 1. / 250. +} + +fn temp_close(a: usize, b: usize) -> bool { + a.abs_diff(b) < 50 +} + +fn xy_close(a: (f64, f64), b: (f64, f64)) -> bool { + let d_color_x = (a.0 - b.0).abs(); + let d_color_y = (a.1 - b.1).abs(); + d_color_x < 0.01 && d_color_y < 0.01 +} + impl LampState { + pub(super) fn changes_relative_to(&self, other: &Self) -> Vec { + let mut res = Vec::new(); + if let Some(brightness) = self.brightness { + if other + .brightness + .is_none_or(|bri| !bri_close(bri, brightness)) + { + res.push(LampProperty::Brightness(brightness)); + } + } + + if let Some(temp) = self.color_temp_k { + if other.color_temp_k.is_none_or(|t| !temp_close(t, temp)) { + res.push(LampProperty::ColorTempK(temp)); + } + } + + if let Some(xy) = self.color_xy { + if other.color_xy.is_none_or(|xy_b| !xy_close(xy_b, xy)) { + res.push(LampProperty::ColorXY(xy)); + } + } + + if let Some(on) = self.on { + if other.on.is_none_or(|on_b| on_b != on) { + res.push(LampProperty::On(on)); + } + } + + if self.color_temp_startup != other.color_temp_startup { + res.push(LampProperty::ColorTempStartup( + self.color_temp_startup.clone(), + )); + } + + res + } + fn apply(self, change: Change) -> LampState { let mut new_state = self.clone(); match change { @@ -75,36 +156,24 @@ impl LampState { new_state } - fn to_payloads(&self, model: &Option) -> Vec { - let mut payloads = vec![]; - match self.on { - Some(true) => payloads.push(json!({ "state": "ON" })), - Some(false) => payloads.push(json!({ "state": "OFF" })), - None => (), - }; - - if let Some(bri) = self.brightness { - payloads.push(json!({ "brightness": denormalize(bri) })); + fn property_list(&self) -> Vec { + let mut list = Vec::new(); + if let Some(val) = self.brightness { + list.push(LampProperty::Brightness(val)); } - - if let Some(model) = model { - if model.is_color_lamp() { - if let Some(color_xy) = self.color_xy { - payloads.push( - json!({ "color": {"x": color_xy.0, "y": color_xy.1} }), - ); - } - } else if let Some(color_temp) = self.color_temp_k { - payloads - .push(json!({ "color_temp": kelvin_to_mired(color_temp) })); - } + if let Some(val) = self.color_temp_k { + list.push(LampProperty::ColorTempK(val)); } - - payloads.push(json!({ "color_temp_startup": self.color_temp_startup })); - - // The IKEA lamps can only accept one state change command at a time, - // so we need to send each parameter in a separate json payload - payloads.into_iter().map(|x| x.to_string()).collect() + if let Some(val) = self.color_xy { + list.push(LampProperty::ColorXY(val)); + } + if let Some(val) = self.on { + list.push(LampProperty::On(val)); + } + list.push(LampProperty::ColorTempStartup( + self.color_temp_startup.clone(), + )); + list } } @@ -131,9 +200,7 @@ impl PartialEq for Lamp { // We only ever set temp, and xy doesn't exist } else { match (self.state.color_temp_k, other.state.color_temp_k) { - (Some(self_temp), Some(other_temp)) => { - self_temp.abs_diff(other_temp) < 50 - } + (Some(self_temp), Some(other_temp)) => self_temp.abs_diff(other_temp) < 50, _ => false, } } @@ -143,11 +210,8 @@ impl PartialEq for Lamp { false }; - let bri_is_equal = match (self.state.brightness, other.state.brightness) - { - (Some(self_bri), Some(other_bri)) => { - (self_bri - other_bri).abs() < 1. / 250. - } + let bri_is_equal = match (self.state.brightness, other.state.brightness) { + (Some(self_bri), Some(other_bri)) => (self_bri - other_bri).abs() < 1. / 250., _ => false, }; @@ -183,9 +247,7 @@ impl Model { Model::TradfriE27 | Model::TradfriE14 | Model::HueGen4 => true, Model::TradfriCandle => false, // We assume no so that things at least don't break - Model::TradfriOther(_) | Model::HueOther(_) | Model::Other(_) => { - false - } + Model::TradfriOther(_) | Model::HueOther(_) | Model::Other(_) => false, } } From 02ba84788b38bc0d1be3bf31dfce39d35d074280 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 13 Nov 2024 22:17:09 +0100 Subject: [PATCH 396/687] remove String with ColorTempStartup enum --- .../src/lights/cached_bridge/mqtt.rs | 27 +++++++----- crates/zigbee-bridge/src/lights/lamp.rs | 44 +++++++++++++------ 2 files changed, 46 insertions(+), 25 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index cbacd099..91e5882f 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -3,14 +3,14 @@ use std::time::{Duration, Instant}; use rumqttc::{AsyncClient, ClientError}; use serde_json::json; -use tracing::{trace, warn}; +use tracing::{instrument, trace, warn}; use crate::lights::lamp::{LampProperty, LampPropertyDiscriminants}; use crate::QOS; pub(super) struct Mqtt { client: AsyncClient, - property_last_set: HashMap>, + property_last_set: HashMap>, } impl Mqtt { @@ -32,6 +32,7 @@ impl Mqtt { get(&self.client, name, &payload.to_string()).await.unwrap(); } + #[instrument(skip(self))] pub(super) async fn try_send_state_diff( &mut self, light_name: &str, @@ -42,17 +43,19 @@ impl Mqtt { if let Some(last_set) = self.property_last_set.get_mut(light_name) { for change in diff { - let change_key = change.clone().into(); - match last_set.get(&change_key) { + match last_set.get(&change.into()) { None => { - set(&self.client, light_name, &change.clone().into_payload()).await?; - last_set.insert(change_key, Instant::now()); + set(&self.client, light_name, &change.payload()).await?; + last_set.insert(change.into(), (Instant::now(), change)); } - Some(at) if at.elapsed() > TIME_IT_TAKES_TO_APPLY_CHANGE => { - set(&self.client, light_name, &change.clone().into_payload()).await?; - last_set.insert(change_key, Instant::now()); + Some((at, prev_change)) + if *prev_change == change + && at.elapsed() > TIME_IT_TAKES_TO_APPLY_CHANGE => + { + set(&self.client, light_name, &change.payload()).await?; + last_set.insert(change.into(), (Instant::now(), change)); } - Some(at) => { + Some((at, _)) => { let until = at.saturating_duration_since(Instant::now()); new_call_needed_in = new_call_needed_in.min(until); } @@ -61,8 +64,8 @@ impl Mqtt { } else { let mut last_set = HashMap::new(); for change in diff { - let change_key: LampPropertyDiscriminants = change.clone().into(); - set(&self.client, light_name, &change.clone().into_payload()).await?; + let change_key: LampPropertyDiscriminants = change.into(); + set(&self.client, light_name, &change.payload()).await?; last_set.insert(change_key, Instant::now()); } } diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index dd08f3b3..1c8e22b5 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -11,7 +11,7 @@ pub(super) struct LampState { pub(super) color_temp_k: Option, pub(super) color_xy: Option<(f64, f64)>, pub(super) on: Option, - pub(super) color_temp_startup: String, + pub(super) color_temp_startup: ColorTempStartup, } impl Default for LampState { @@ -23,7 +23,7 @@ impl Default for LampState { on: None, // Settings, will not be updated from MQTT state message // and will never trigger a publish - color_temp_startup: String::from("previous"), + color_temp_startup: ColorTempStartup::Previous, } } } @@ -34,25 +34,47 @@ pub(super) struct Lamp { pub(super) state: LampState, } -#[derive(Debug, EnumDiscriminants, Clone)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(super) enum ColorTempStartup { + Previous, +} + +#[derive(Debug, EnumDiscriminants, Clone, Copy)] #[strum_discriminants(derive(Hash))] pub(super) enum LampProperty { Brightness(f64), ColorTempK(usize), ColorXY((f64, f64)), On(bool), - ColorTempStartup(String), + ColorTempStartup(ColorTempStartup), +} + +impl PartialEq for LampProperty { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (LampProperty::Brightness(a), LampProperty::Brightness(b)) => bri_close(*a, *b), + (LampProperty::ColorTempK(a), LampProperty::ColorTempK(b)) => temp_close(*a, *b), + (LampProperty::ColorXY(a), LampProperty::ColorXY(b)) => xy_close(*a, *b), + (LampProperty::On(a), LampProperty::On(b)) => a == b, + (LampProperty::ColorTempStartup(a), LampProperty::ColorTempStartup(b)) => a == b, + (_, _) => false, + } + } } +impl Eq for LampProperty {} + impl LampProperty { - pub(crate) fn into_payload(self) -> String { - match self { + pub(crate) fn payload(&self) -> String { + match *self { LampProperty::Brightness(bri) => json!({ "brightness": denormalize(bri) }), LampProperty::ColorTempK(k) => json!({ "color_temp": kelvin_to_mired(k) }), LampProperty::ColorXY((x, y)) => json!({ "color": {"x": x, "y": y} }), LampProperty::On(lamp_on) if lamp_on => json!({"state": "ON"}), LampProperty::On(_) => json!({"state": "OFF"}), - LampProperty::ColorTempStartup(s) => json!({"color_temp_startup": s}), + LampProperty::ColorTempStartup(ColorTempStartup::Previous) => { + json!({"color_temp_startup": "previous"}) + } } .to_string() } @@ -134,9 +156,7 @@ impl LampState { } if self.color_temp_startup != other.color_temp_startup { - res.push(LampProperty::ColorTempStartup( - self.color_temp_startup.clone(), - )); + res.push(LampProperty::ColorTempStartup(self.color_temp_startup)); } res @@ -170,9 +190,7 @@ impl LampState { if let Some(val) = self.on { list.push(LampProperty::On(val)); } - list.push(LampProperty::ColorTempStartup( - self.color_temp_startup.clone(), - )); + list.push(LampProperty::ColorTempStartup(self.color_temp_startup)); list } } From 82091fb7d2539c51d4356c165d7c42f36e9ba18b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 13 Nov 2024 22:29:00 +0100 Subject: [PATCH 397/687] switch to mqtt v5 --- crates/brain/test.sh | 2 +- crates/zigbee-bridge/src/lib.rs | 2 +- .../zigbee-bridge/src/lights/cached_bridge.rs | 7 +++---- .../src/lights/cached_bridge/mqtt.rs | 16 ++++++++-------- .../src/lights/cached_bridge/poll.rs | 18 +++++++----------- 5 files changed, 20 insertions(+), 25 deletions(-) diff --git a/crates/brain/test.sh b/crates/brain/test.sh index 8b5243fa..ab6cff14 100755 --- a/crates/brain/test.sh +++ b/crates/brain/test.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -RUST_LOG=reqwest::connect=info,hyper_util=info,sled=info,rumqttc::state=info,zigbee_bridge::lights::cached_bridge::mqtt=debug,trace RUST_BACKTRACE=1 cargo r -- \ +RUST_LOG=reqwest::connect=info,hyper_util=info,sled=info,rumqttc::v5::state=info,zigbee_bridge::lights::cached_bridge::mqtt=debug,trace RUST_BACKTRACE=1 cargo r -- \ --data-server 192.168.1.43:1235 \ --mpd-ip 192.168.1.43 \ --port 34326 \ diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 6032b842..a5946e15 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -4,7 +4,7 @@ // Set to on, off after 30s // on_time: 30, off_wait_time: 30 -use rumqttc::QoS; +use rumqttc::v5::mqttbytes::QoS; pub mod lights; diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 17e36785..b5c238df 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use rumqttc::{AsyncClient, MqttOptions}; +use rumqttc::v5::{AsyncClient, MqttOptions}; use tokio::sync::{mpsc, RwLock}; use tracing::trace; @@ -12,11 +12,10 @@ mod changes; mod mqtt; mod poll; - pub(super) async fn run(change_receiver: mpsc::UnboundedReceiver<(String, Change)>) -> ! { let mut options = MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); - // Set incoming to max mqtt packet size, outgoing to rumqtt default - options.set_max_packet_size(2_usize.pow(28), 10240); // incoming: ~ 268 MB + // Set max mqtt packet size to 4kB + options.set_max_packet_size(Some(4096)); let known_states = RwLock::new(HashMap::new()); diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index 91e5882f..142d15f5 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use std::time::{Duration, Instant}; -use rumqttc::{AsyncClient, ClientError}; +use rumqttc::v5::{AsyncClient, ClientError}; use serde_json::json; use tracing::{instrument, trace, warn}; @@ -29,7 +29,7 @@ impl Mqtt { trace!("Requesting state for light {name}"); let payload = json!({"state": ""}); - get(&self.client, name, &payload.to_string()).await.unwrap(); + get(&self.client, name, payload.to_string()).await.unwrap(); } #[instrument(skip(self))] @@ -45,14 +45,14 @@ impl Mqtt { for change in diff { match last_set.get(&change.into()) { None => { - set(&self.client, light_name, &change.payload()).await?; + set(&self.client, light_name, change.payload()).await?; last_set.insert(change.into(), (Instant::now(), change)); } Some((at, prev_change)) if *prev_change == change && at.elapsed() > TIME_IT_TAKES_TO_APPLY_CHANGE => { - set(&self.client, light_name, &change.payload()).await?; + set(&self.client, light_name, change.payload()).await?; last_set.insert(change.into(), (Instant::now(), change)); } Some((at, _)) => { @@ -65,7 +65,7 @@ impl Mqtt { let mut last_set = HashMap::new(); for change in diff { let change_key: LampPropertyDiscriminants = change.into(); - set(&self.client, light_name, &change.payload()).await?; + set(&self.client, light_name, change.payload()).await?; last_set.insert(change_key, Instant::now()); } } @@ -74,7 +74,7 @@ impl Mqtt { } } -async fn set(client: &AsyncClient, friendly_name: &str, payload: &str) -> Result<(), ClientError> { +async fn set(client: &AsyncClient, friendly_name: &str, payload: String) -> Result<(), ClientError> { let topic = format!("zigbee2mqtt/{friendly_name}/set"); trace!("Sending payload {payload} to lamp {friendly_name}"); @@ -85,13 +85,13 @@ async fn set(client: &AsyncClient, friendly_name: &str, payload: &str) -> Result Ok(()) } -async fn get(client: &AsyncClient, friendly_name: &str, payload: &str) -> Result<(), ClientError> { +async fn get(client: &AsyncClient, friendly_name: &str, payload: String) -> Result<(), ClientError> { let topic = format!("zigbee2mqtt/{friendly_name}/get"); publish(client, &topic, payload).await?; Ok(()) } -async fn publish(client: &AsyncClient, topic: &str, payload: &str) -> Result<(), ClientError> { +async fn publish(client: &AsyncClient, topic: &str, payload: String) -> Result<(), ClientError> { client.publish(topic, QOS, false, payload).await } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 26ff0825..b95a848c 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -1,6 +1,6 @@ use std::{collections::HashMap, time::Duration}; -use rumqttc::{Event, EventLoop, Incoming}; +use rumqttc::v5::{Event, EventLoop, Incoming}; use serde_json::Value; use tokio::{sync::RwLock, time::sleep}; use tracing::{instrument, trace}; @@ -51,13 +51,10 @@ fn parse_message(message: Event) -> Message { Event::Incoming(incoming) => match incoming { Incoming::ConnAck(_) | Incoming::PubAck(_) - | Incoming::PingResp + | Incoming::PingResp(_) | Incoming::SubAck(_) => Message::Other, - Incoming::Publish(message) - if message.topic == "zigbee2mqtt/bridge/devices" => - { - let json: Value = - serde_json::from_slice(&message.payload).unwrap(); + Incoming::Publish(message) if message.topic == "zigbee2mqtt/bridge/devices" => { + let json: Value = serde_json::from_slice(&message.payload).unwrap(); let list = json.as_array().unwrap(); let devices: HashMap = list .iter() @@ -68,7 +65,8 @@ fn parse_message(message: Event) -> Message { Message::Devices(devices) } Incoming::Publish(message) => { - let topic: Vec<_> = message.topic.split('/').collect(); + let topic = String::from_utf8_lossy(&message.topic); + let topic: Vec<_> = topic.split('/').collect(); let name = topic[1].to_string(); let data = &(*message.payload); @@ -110,9 +108,7 @@ fn parse_device(device: &Value) -> (String, Model) { Some("TRADFRI bulb E27 CWS globe 806lm") => Model::TradfriE27, Some("TRADFRI bulb E14 CWS globe 806lm") => Model::TradfriE14, Some("LCT001") => Model::HueGen4, - Some(id) if id.to_lowercase().contains("tradfri") => { - Model::TradfriOther(id.to_owned()) - } + Some(id) if id.to_lowercase().contains("tradfri") => Model::TradfriOther(id.to_owned()), Some(id) => Model::Other(id.to_owned()), None => Model::Other(String::new()), }; From 1c4ed06988f2540b27d1cb11d0628c61cee9efcb Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 13 Nov 2024 22:40:31 +0100 Subject: [PATCH 398/687] add message expiry interval & adjust subscribe QOS --- crates/zigbee-bridge/src/lib.rs | 3 --- .../src/lights/cached_bridge/mqtt.rs | 26 +++++++++++++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index a5946e15..5c7a53a7 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -4,11 +4,8 @@ // Set to on, off after 30s // on_time: 30, off_wait_time: 30 -use rumqttc::v5::mqttbytes::QoS; - pub mod lights; -const QOS: QoS = QoS::AtMostOnce; const MQTT_IP: &str = "192.168.1.43"; const MQTT_PORT: u16 = 1883; const LIGHTS: [&str; 5] = [ diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index 142d15f5..e7347e91 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -1,12 +1,12 @@ use std::collections::HashMap; use std::time::{Duration, Instant}; +use rumqttc::v5::mqttbytes::QoS; use rumqttc::v5::{AsyncClient, ClientError}; use serde_json::json; use tracing::{instrument, trace, warn}; use crate::lights::lamp::{LampProperty, LampPropertyDiscriminants}; -use crate::QOS; pub(super) struct Mqtt { client: AsyncClient, @@ -22,7 +22,10 @@ impl Mqtt { } pub(super) async fn subscribe(&self, topic: &str) -> Result<(), ClientError> { - self.client.subscribe(topic, QOS).await + // Its okay for messages to arrive twice or more. MQTT guarantees + // ordering and we only do something if the cached bridge indicates we + // need to so light states arriving twice is not an issue. + self.client.subscribe(topic, QoS::AtLeastOnce).await } pub(super) async fn request_state(&self, name: &str) { @@ -74,7 +77,11 @@ impl Mqtt { } } -async fn set(client: &AsyncClient, friendly_name: &str, payload: String) -> Result<(), ClientError> { +async fn set( + client: &AsyncClient, + friendly_name: &str, + payload: String, +) -> Result<(), ClientError> { let topic = format!("zigbee2mqtt/{friendly_name}/set"); trace!("Sending payload {payload} to lamp {friendly_name}"); @@ -85,7 +92,11 @@ async fn set(client: &AsyncClient, friendly_name: &str, payload: String) -> Resu Ok(()) } -async fn get(client: &AsyncClient, friendly_name: &str, payload: String) -> Result<(), ClientError> { +async fn get( + client: &AsyncClient, + friendly_name: &str, + payload: String, +) -> Result<(), ClientError> { let topic = format!("zigbee2mqtt/{friendly_name}/get"); publish(client, &topic, payload).await?; @@ -93,5 +104,10 @@ async fn get(client: &AsyncClient, friendly_name: &str, payload: String) -> Resu } async fn publish(client: &AsyncClient, topic: &str, payload: String) -> Result<(), ClientError> { - client.publish(topic, QOS, false, payload).await + let mut properties = rumqttc::v5::mqttbytes::v5::PublishProperties::default(); + properties.message_expiry_interval = Some(5); // seconds + + client + .publish_with_properties(topic, QoS::AtLeastOnce, false, payload, properties) + .await } From 1354b19d786d2d2222b98a6ab60a8583846b84de Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 14 Nov 2024 17:40:43 +0100 Subject: [PATCH 399/687] refactor cached_bridge and parse_state --- crates/zigbee-bridge/src/lib.rs | 10 +- .../src/lights/cached_bridge/changes.rs | 15 +- .../src/lights/cached_bridge/mqtt.rs | 51 +++--- .../src/lights/cached_bridge/poll.rs | 54 +++---- crates/zigbee-bridge/src/lights/lamp.rs | 2 + .../zigbee-bridge/src/lights/parse_state.rs | 149 ++++++++---------- 6 files changed, 130 insertions(+), 151 deletions(-) diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 5c7a53a7..fbbf26e4 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -8,12 +8,12 @@ pub mod lights; const MQTT_IP: &str = "192.168.1.43"; const MQTT_PORT: u16 = 1883; -const LIGHTS: [&str; 5] = [ - "kitchen:fridge", +const LIGHTS: [&str; 1] = [ + // "kitchen:fridge", "kitchen:hallway", - "kitchen:hood_left", - "kitchen:hood_right", - "kitchen:ceiling", + // "kitchen:hood_left", + // "kitchen:hood_right", + // "kitchen:ceiling", ]; #[cfg(test)] diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index 459aef8d..54a09d38 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -14,7 +14,8 @@ pub(super) async fn handle( mqtt: &mut Mqtt, known_states: &RwLock>, ) -> ! { - const MQTT_MIGHT_BE_DOWN_TIMEOUT: Duration = Duration::from_secs(5); + // const MQTT_MIGHT_BE_DOWN_TIMEOUT: Duration = Duration::from_secs(5); + const MQTT_MIGHT_BE_DOWN_TIMEOUT: Duration = Duration::from_secs(500); const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); // Give the initial known states a chance to be fetched @@ -42,7 +43,7 @@ pub(super) async fn handle( /// make sure the set/send takes effect. We do not send it again now as that /// would be a little spammy. Returns when we need to recheck. If we do not need /// to do so we return Duration::MAX. -#[instrument(skip_all)] +#[instrument(skip_all, fields(light_name))] async fn send_and_queue( known_states: &RwLock>, needed_states: &mut HashMap, @@ -52,6 +53,8 @@ async fn send_and_queue( let known_states = known_states.read().await; for light_name in LIGHTS { + tracing::Span::current().record("light_name", light_name); + let Some(needed) = needed_states.get(light_name) else { continue; }; @@ -59,7 +62,7 @@ async fn send_and_queue( let Some(known) = known_states.get(light_name) else { // Ignore errors because we will retry if the state hasn't changed if let Ok(dur) = mqtt - .try_send_state_diff(light_name, needed.property_list()) + .try_send_state_diff(light_name.to_string(), needed.property_list()) .await { call_again_in = call_again_in.min(dur); @@ -67,10 +70,10 @@ async fn send_and_queue( continue; }; - if needed != known { - let diff = needed.changes_relative_to(known); + let diff = needed.changes_relative_to(known); + if !diff.is_empty() && known.model.is_some() { // Ignore errors because we will retry if the state hasn't changed - if let Ok(dur) = mqtt.try_send_state_diff(light_name, diff).await { + if let Ok(dur) = mqtt.try_send_state_diff(light_name.to_string(), diff).await { call_again_in = call_again_in.min(dur); } } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index e7347e91..654e91df 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -38,39 +38,38 @@ impl Mqtt { #[instrument(skip(self))] pub(super) async fn try_send_state_diff( &mut self, - light_name: &str, + light_name: String, diff: Vec, ) -> Result { const TIME_IT_TAKES_TO_APPLY_CHANGE: Duration = Duration::from_secs(1); let mut new_call_needed_in: Duration = Duration::MAX; - if let Some(last_set) = self.property_last_set.get_mut(light_name) { - for change in diff { - match last_set.get(&change.into()) { - None => { - set(&self.client, light_name, change.payload()).await?; - last_set.insert(change.into(), (Instant::now(), change)); - } - Some((at, prev_change)) - if *prev_change == change - && at.elapsed() > TIME_IT_TAKES_TO_APPLY_CHANGE => - { - set(&self.client, light_name, change.payload()).await?; - last_set.insert(change.into(), (Instant::now(), change)); - } - Some((at, _)) => { - let until = at.saturating_duration_since(Instant::now()); - new_call_needed_in = new_call_needed_in.min(until); - } - } + let last_set = self + .property_last_set + .entry(light_name.clone()) + .or_default(); + + for change in diff { + let Some((at, prev_change)) = last_set.get(&change.into()) else { + set(&self.client, &light_name, change.payload()).await?; + last_set.insert(change.into(), (Instant::now(), change)); + continue; + }; + + if *prev_change != change { + set(&self.client, &light_name, change.payload()).await?; + last_set.insert(change.into(), (Instant::now(), change)); + continue; } - } else { - let mut last_set = HashMap::new(); - for change in diff { - let change_key: LampPropertyDiscriminants = change.into(); - set(&self.client, light_name, change.payload()).await?; - last_set.insert(change_key, Instant::now()); + + if at.elapsed() > TIME_IT_TAKES_TO_APPLY_CHANGE { + set(&self.client, &light_name, change.payload()).await?; + last_set.insert(change.into(), (Instant::now(), change)); + continue; } + + let until = at.saturating_duration_since(Instant::now()); + new_call_needed_in = new_call_needed_in.min(until); } Ok(new_call_needed_in) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index b95a848c..cbd09962 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -46,38 +46,32 @@ pub(super) async fn poll_mqtt( } #[instrument(skip_all)] -fn parse_message(message: Event) -> Message { - match message { - Event::Incoming(incoming) => match incoming { - Incoming::ConnAck(_) - | Incoming::PubAck(_) - | Incoming::PingResp(_) - | Incoming::SubAck(_) => Message::Other, - Incoming::Publish(message) if message.topic == "zigbee2mqtt/bridge/devices" => { - let json: Value = serde_json::from_slice(&message.payload).unwrap(); - let list = json.as_array().unwrap(); - let devices: HashMap = list - .iter() - .map(parse_device) - .filter(|d| d.0 != "Coordinator") - .collect(); +fn parse_message(event: Event) -> Message { + let Event::Incoming(incoming) = event else { + return Message::Other; + }; - Message::Devices(devices) - } - Incoming::Publish(message) => { - let topic = String::from_utf8_lossy(&message.topic); - let topic: Vec<_> = topic.split('/').collect(); - let name = topic[1].to_string(); - let data = &(*message.payload); + let Incoming::Publish(message) = incoming else { + return Message::Other; + }; - Message::StateUpdate((name, data.try_into().unwrap())) - } - other => { - dbg!(other); - Message::Other - } - }, - Event::Outgoing(_) => Message::Other, + let topic = String::from_utf8_lossy(&message.topic); + + if topic == "zigbee2mqtt/bridge/devices" { + let json: Value = serde_json::from_slice(&message.payload).unwrap(); + let list = json.as_array().unwrap(); + let devices: HashMap = list + .iter() + .map(parse_device) + .filter(|d| d.0 != "Coordinator") + .collect(); + Message::Devices(devices) + } else { + let topic = String::from_utf8_lossy(&message.topic); + let topic: Vec<_> = topic.split('/').collect(); + let name = topic[1].to_string(); + let data = &(*message.payload); + Message::StateUpdate((name, data.try_into().unwrap())) } } diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 1c8e22b5..0b9bd096 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use serde_json::json; use strum::EnumDiscriminants; +use tracing::instrument; use crate::lights::{conversion::temp_to_xy, denormalize, kelvin_to_mired}; @@ -126,6 +127,7 @@ fn xy_close(a: (f64, f64), b: (f64, f64)) -> bool { } impl LampState { + #[instrument(ret)] pub(super) fn changes_relative_to(&self, other: &Self) -> Vec { let mut res = Vec::new(); if let Some(brightness) = self.brightness { diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs index 0c6ab83d..7f22a590 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -1,84 +1,71 @@ -use std::io; - use serde_json::Value; use thiserror::Error; use crate::lights::{lamp::LampState, mired_to_kelvin, normalize}; #[derive(Error, Debug)] -pub(super) enum ParseError { - #[error("json error: {0}")] - Json(#[from] serde_json::Error), - #[error("io error: {0}")] - Io(#[from] io::Error), - #[error("invalid value: {0}")] - InvalidValue(String), +pub(super) enum Error { + #[error("Could not deserialize to json: {0}")] + NotJson(#[from] serde_json::Error), + #[error("Needed key {0}, is missing")] + MissingKey(&'static str), + #[error("Needed a number however got: {0}")] + NotNumber(String), + #[error("Needed an integer number however got: {0}")] + NotInteger(String), + #[error("Needed a 8 bit integer number however got: {0}")] + NumberNotU8(String), + #[error("Needed an usize bit integer number however got: {0}")] + NumberNotUsize(String), + #[error("Needed an uf8 string got: {0}")] + NotString(String), + #[error("Needed json object got: {0}")] + NotObject(String), + #[error("Invalid light state, expected ON or EFF got: {0}")] + InvalidState(String), } impl TryInto for &[u8] { - type Error = ParseError; // TODO: could be a parse error enum, saves having - // to go through the whole ErrorKind stuff. - // - // But this is fine too, kinda like the str for - // invalid_err() stuff - // - // but get_key(map, "color") could be - // map.get("color").ok_or(ParseError("Missing key - // from map: {key}")). Just an idea, do what you - // prefer. - // <11-11-24, dvdsk> + type Error = Error; fn try_into(self) -> Result { let json: Value = serde_json::from_slice(self)?; - let map = json.as_object().ok_or(invalid_err("Object"))?; + let map = json.as_object().ok_or(Error::NotObject(json.to_string()))?; - // Could be done using .map(|temp| {...}).ok(), except that the question - // mark gets in the way - let color_temp_mired = match get_key(map, "color_temp") { - Ok(temp) => { - let color_temp: usize = - json_to_u64(temp)?.try_into().expect("usize should be u64"); - Some(color_temp) - } - Err(_) => None, - }; + let color_temp_mired: Option = map + .get("color_temp") + .map(|temp| json_to_usize(temp)) + .transpose()?; - let color_xy = match get_key(map, "color") { - Ok(color) => { - let color = color.as_object().ok_or(invalid_err("Object"))?; - let color_x = json_to_f64(get_key(color, "x")?)?; - let color_y = json_to_f64(get_key(color, "y")?)?; - Some((color_x, color_y)) - } - Err(_) => None, - }; + let color_xy = map + .get("color") + .map(|color| { + let color = color + .as_object() + .ok_or(Error::NotObject(color.to_string()))?; + let color_x = json_to_f64(color.get("x").ok_or(Error::MissingKey("x"))?)?; + let color_y = json_to_f64(color.get("y").ok_or(Error::MissingKey("y"))?)?; + Ok::<_, Error>((color_x, color_y)) + }) + .transpose()?; - let brightness = match get_key(map, "brightness") { - Ok(bri) => { - let bri: u8 = json_to_u64(bri)? - .try_into() - .map_err(|_| invalid_err("u8"))?; - Some(bri) - } - Err(_) => None, - }; + let brightness: Option = map + .get("brightness") + .map(|bri| json_to_u8(bri)) + .transpose()?; - let on = match get_key(map, "state") { - Ok(on) => { - let state = on.as_str().ok_or(invalid_err("String"))?; + let on = map + .get("state") + .map(|on| { + let state = on.as_str().ok_or(Error::NotString(on.to_string()))?; let on = match state { "ON" => true, "OFF" => false, - other => { - return Err(ParseError::InvalidValue(format!( - "on/off bool: {other}" - ))) - } + other => return Err(Error::InvalidState(other.to_string())), }; - Some(on) - } - Err(_) => None, - }; + Ok(on) + }) + .transpose()?; Ok(LampState { #[allow(clippy::cast_precision_loss)] @@ -91,35 +78,29 @@ impl TryInto for &[u8] { } } -fn json_to_u64(json: &Value) -> Result { +fn json_to_usize(json: &Value) -> Result { + json_to_u64(json)? + .try_into() + .map_err(|_| Error::NumberNotUsize(json.to_string())) +} + +fn json_to_u8(json: &Value) -> Result { + json_to_u64(json)? + .try_into() + .map_err(|_| Error::NumberNotU8(json.to_string())) +} + +fn json_to_u64(json: &Value) -> Result { json.as_number() - .ok_or(invalid_err("Number"))? + .ok_or(Error::NotNumber(json.to_string()))? .as_u64() - .ok_or(invalid_err("u64")) + .ok_or(Error::NotInteger(json.to_string())) } -fn json_to_f64(json: &Value) -> Result { +fn json_to_f64(json: &Value) -> Result { Ok(json .as_number() - .ok_or(invalid_err("Number"))? + .ok_or(Error::NotNumber(json.to_string()))? .as_f64() .expect("Should be Some if not using arbitrary precision")) } - -fn get_key<'a>( - map: &'a serde_json::Map, - key: &str, -) -> Result<&'a Value, io::Error> { - let key_err = io::Error::new( - io::ErrorKind::InvalidData, - "Missing key from map: {key}", - ); - map.get(key).ok_or(key_err) -} - -fn invalid_err(value_type: &str) -> io::Error { - io::Error::new( - io::ErrorKind::InvalidData, - format!("Could not parse json into {value_type}"), - ) -} From d6d3ed8e9a858fda5f5530fa80a55e69ef4ca942 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 14 Nov 2024 21:50:52 +0100 Subject: [PATCH 400/687] fixes next_call_allowed time being 0ns --- Cargo.lock | 3 + crates/brain/test.sh | 2 +- crates/zigbee-bridge/Cargo.toml | 3 + .../src/lights/cached_bridge/changes.rs | 17 ++-- .../src/lights/cached_bridge/mqtt.rs | 10 ++- .../src/lights/cached_bridge/poll.rs | 72 +++++++++++---- crates/zigbee-bridge/src/lights/lamp.rs | 9 +- .../zigbee-bridge/src/lights/parse_state.rs | 88 +++++++++---------- 8 files changed, 118 insertions(+), 86 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e078421..c328bcc8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4283,9 +4283,12 @@ dependencies = [ name = "zigbee-bridge" version = "0.1.0" dependencies = [ + "color-eyre", "colorimetry", "futures", "futures-concurrency", + "itertools", + "ratelimited-logger", "rumqttc", "serde_json", "strum", diff --git a/crates/brain/test.sh b/crates/brain/test.sh index ab6cff14..fe9d7b0c 100755 --- a/crates/brain/test.sh +++ b/crates/brain/test.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -RUST_LOG=reqwest::connect=info,hyper_util=info,sled=info,rumqttc::v5::state=info,zigbee_bridge::lights::cached_bridge::mqtt=debug,trace RUST_BACKTRACE=1 cargo r -- \ +RUST_LOG=reqwest::connect=info,hyper_util=info,sled=info,rumqttc::v5::state=info,trace RUST_BACKTRACE=1 cargo r -- \ --data-server 192.168.1.43:1235 \ --mpd-ip 192.168.1.43 \ --port 34326 \ diff --git a/crates/zigbee-bridge/Cargo.toml b/crates/zigbee-bridge/Cargo.toml index 362ca918..8bfd8810 100644 --- a/crates/zigbee-bridge/Cargo.toml +++ b/crates/zigbee-bridge/Cargo.toml @@ -18,3 +18,6 @@ tokio = { workspace = true, features = ["sync"] } tracing = { workspace = true } futures = "0.3.31" strum = { version = "0.26.3", features = ["derive"] } +ratelimited-logger = { workspace = true } +color-eyre.workspace = true +itertools = "0.13.0" diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index 54a09d38..49dd1ef9 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -28,7 +28,7 @@ pub(super) async fn handle( let res = res.expect("Channel should never close"); let (light_name, change) = res; - trace!("Received change: {change:?}"); + trace!("Received change order: {change:?}"); apply_change(light_name, change, known_states, &mut needed_states).await; }; @@ -59,19 +59,12 @@ async fn send_and_queue( continue; }; - let Some(known) = known_states.get(light_name) else { - // Ignore errors because we will retry if the state hasn't changed - if let Ok(dur) = mqtt - .try_send_state_diff(light_name.to_string(), needed.property_list()) - .await - { - call_again_in = call_again_in.min(dur); - } - continue; + let diff = match known_states.get(light_name) { + Some(known) => needed.changes_relative_to(known), + None => needed.property_list(), }; - let diff = needed.changes_relative_to(known); - if !diff.is_empty() && known.model.is_some() { + if !diff.is_empty() { // Ignore errors because we will retry if the state hasn't changed if let Ok(dur) = mqtt.try_send_state_diff(light_name.to_string(), diff).await { call_again_in = call_again_in.min(dur); diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index 654e91df..601486d4 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -68,7 +68,12 @@ impl Mqtt { continue; } - let until = at.saturating_duration_since(Instant::now()); + trace!( + "not setting property {change:?} for {light_name} as it has \ + recently been set" + ); + let next_call_allowed = *at + TIME_IT_TAKES_TO_APPLY_CHANGE; + let until = next_call_allowed.saturating_duration_since(Instant::now()); new_call_needed_in = new_call_needed_in.min(until); } @@ -84,9 +89,6 @@ async fn set( let topic = format!("zigbee2mqtt/{friendly_name}/set"); trace!("Sending payload {payload} to lamp {friendly_name}"); - if friendly_name == "kitchen:hallway" && payload.contains("state") { - warn!("Sending payload {payload} to {friendly_name}"); - } publish(client, &topic, payload).await?; Ok(()) } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index cbd09962..eda845d4 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -1,16 +1,23 @@ use std::{collections::HashMap, time::Duration}; +use color_eyre::eyre::{Context, ContextCompat, OptionExt}; +use color_eyre::Section; +use itertools::Itertools; +use ratelimited_logger::RateLimitedLogger; use rumqttc::v5::{Event, EventLoop, Incoming}; use serde_json::Value; use tokio::{sync::RwLock, time::sleep}; use tracing::{instrument, trace}; use crate::lights::lamp::{Lamp, LampState, Model}; +use crate::lights::parse_state::parse_lamp_state; pub(super) async fn poll_mqtt( mut eventloop: EventLoop, known_states: &RwLock>, ) -> ! { + let mut logger = RateLimitedLogger::default(); + loop { let message = match eventloop.poll().await { Ok(message) => message, @@ -21,14 +28,22 @@ pub(super) async fn poll_mqtt( } }; - let mut known_states = known_states.write().await; + let message = match parse_message(message) { + Ok(message) => message, + Err(err) => { + ratelimited_logger::warn!(logger; "Error parsing mqtt message: {err}"); + continue; + } + }; - match parse_message(message) { + let mut known_states = known_states.write().await; + match message { Message::StateUpdate((light_name, updated_state)) => { let new_known_state = match known_states.get(&light_name) { Some(lamp) => lamp.store_state(updated_state), None => Lamp::default().store_state(updated_state), }; + trace!("updating known state: {new_known_state:?}"); known_states.insert(light_name, new_known_state); } Message::Devices(new_devices) => { @@ -37,6 +52,7 @@ pub(super) async fn poll_mqtt( Some(lamp) => lamp.store_model(model), None => Lamp::default().store_model(model), }; + trace!("updating known state: {new_known_state:?}"); known_states.insert(light_name, new_known_state); } } @@ -45,33 +61,48 @@ pub(super) async fn poll_mqtt( } } +// async fn update_state(known_states: &RwLock>) { +// let mut known_states = known_states.write().await; +// known_states.entry() +// } + #[instrument(skip_all)] -fn parse_message(event: Event) -> Message { +fn parse_message(event: Event) -> color_eyre::Result { let Event::Incoming(incoming) = event else { - return Message::Other; + return Ok(Message::Other); }; let Incoming::Publish(message) = incoming else { - return Message::Other; + return Ok(Message::Other); }; let topic = String::from_utf8_lossy(&message.topic); if topic == "zigbee2mqtt/bridge/devices" { - let json: Value = serde_json::from_slice(&message.payload).unwrap(); - let list = json.as_array().unwrap(); + let json: Value = serde_json::from_slice(&message.payload) + .wrap_err("could not parse message payload as json")?; + let list = json + .as_array() + .ok_or_eyre("devices list should be array its not") + .with_note(|| format!("json was: {json:?}"))?; let devices: HashMap = list .iter() - .map(parse_device) - .filter(|d| d.0 != "Coordinator") - .collect(); - Message::Devices(devices) + .map(|dev| { + parse_device(dev) + .wrap_err("could not parse device") + .with_note(|| format!("device: {dev:?}")) + }) + .filter_ok(|d| d.0 != "Coordinator") + .collect::>()?; + Ok(Message::Devices(devices)) } else { let topic = String::from_utf8_lossy(&message.topic); let topic: Vec<_> = topic.split('/').collect(); let name = topic[1].to_string(); - let data = &(*message.payload); - Message::StateUpdate((name, data.try_into().unwrap())) + let state = parse_lamp_state(&message.payload) + .wrap_err("failed to parse lamp state") + .with_note(|| format!("topic: {topic:?}"))?; + Ok(Message::StateUpdate((name, state))) } } @@ -83,19 +114,22 @@ enum Message { } #[instrument(skip_all)] -fn parse_device(device: &Value) -> (String, Model) { - let properties = device.as_object().unwrap(); +fn parse_device(device: &Value) -> color_eyre::Result<(String, Model)> { + let properties = device + .as_object() + .wrap_err("device should be json object")?; let friendly_name = properties .get("friendly_name") - .unwrap() + .wrap_err("device misses key `friendly_name`")? .as_str() - .unwrap() + .wrap_err("value of `friendly_name` is not a string")? .to_owned(); let model_id = properties .get("model_id") .map(Value::as_str) - .map(Option::unwrap); + .map(|res| res.ok_or_eyre("value of `model_id` is not a string")) + .transpose()?; let model = match model_id { Some("TRADFRI bulb E14 WS candle 470lm") => Model::TradfriCandle, @@ -107,5 +141,5 @@ fn parse_device(device: &Value) -> (String, Model) { None => Model::Other(String::new()), }; - (friendly_name, model) + Ok((friendly_name, model)) } diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 0b9bd096..12ae48b9 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -127,7 +127,7 @@ fn xy_close(a: (f64, f64), b: (f64, f64)) -> bool { } impl LampState { - #[instrument(ret)] + #[instrument] pub(super) fn changes_relative_to(&self, other: &Self) -> Vec { let mut res = Vec::new(); if let Some(brightness) = self.brightness { @@ -179,6 +179,10 @@ impl LampState { } fn property_list(&self) -> Vec { + // we do not send color xy as the lamp might not support it + // if it does then property_list is never called but an exact + // diff between the current and need state is send + let mut list = Vec::new(); if let Some(val) = self.brightness { list.push(LampProperty::Brightness(val)); @@ -186,9 +190,6 @@ impl LampState { if let Some(val) = self.color_temp_k { list.push(LampProperty::ColorTempK(val)); } - if let Some(val) = self.color_xy { - list.push(LampProperty::ColorXY(val)); - } if let Some(val) = self.on { list.push(LampProperty::On(val)); } diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs index 7f22a590..3ea8208c 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -25,57 +25,53 @@ pub(super) enum Error { InvalidState(String), } -impl TryInto for &[u8] { - type Error = Error; +pub(super) fn parse_lamp_state(bytes: &[u8]) -> Result { + let json: Value = serde_json::from_slice(bytes)?; + let map = json.as_object().ok_or(Error::NotObject(json.to_string()))?; - fn try_into(self) -> Result { - let json: Value = serde_json::from_slice(self)?; - let map = json.as_object().ok_or(Error::NotObject(json.to_string()))?; + let color_temp_mired: Option = map + .get("color_temp") + .map(|temp| json_to_usize(temp)) + .transpose()?; - let color_temp_mired: Option = map - .get("color_temp") - .map(|temp| json_to_usize(temp)) - .transpose()?; - - let color_xy = map - .get("color") - .map(|color| { - let color = color - .as_object() - .ok_or(Error::NotObject(color.to_string()))?; - let color_x = json_to_f64(color.get("x").ok_or(Error::MissingKey("x"))?)?; - let color_y = json_to_f64(color.get("y").ok_or(Error::MissingKey("y"))?)?; - Ok::<_, Error>((color_x, color_y)) - }) - .transpose()?; - - let brightness: Option = map - .get("brightness") - .map(|bri| json_to_u8(bri)) - .transpose()?; + let color_xy = map + .get("color") + .map(|color| { + let color = color + .as_object() + .ok_or(Error::NotObject(color.to_string()))?; + let color_x = json_to_f64(color.get("x").ok_or(Error::MissingKey("x"))?)?; + let color_y = json_to_f64(color.get("y").ok_or(Error::MissingKey("y"))?)?; + Ok::<_, Error>((color_x, color_y)) + }) + .transpose()?; - let on = map - .get("state") - .map(|on| { - let state = on.as_str().ok_or(Error::NotString(on.to_string()))?; - let on = match state { - "ON" => true, - "OFF" => false, - other => return Err(Error::InvalidState(other.to_string())), - }; - Ok(on) - }) - .transpose()?; + let brightness: Option = map + .get("brightness") + .map(|bri| json_to_u8(bri)) + .transpose()?; - Ok(LampState { - #[allow(clippy::cast_precision_loss)] - brightness: brightness.map(normalize), - color_temp_k: color_temp_mired.map(mired_to_kelvin), - color_xy, - on, - ..Default::default() + let on = map + .get("state") + .map(|on| { + let state = on.as_str().ok_or(Error::NotString(on.to_string()))?; + let on = match state { + "ON" => true, + "OFF" => false, + other => return Err(Error::InvalidState(other.to_string())), + }; + Ok(on) }) - } + .transpose()?; + + Ok(LampState { + #[allow(clippy::cast_precision_loss)] + brightness: brightness.map(normalize), + color_temp_k: color_temp_mired.map(mired_to_kelvin), + color_xy, + on, + ..Default::default() + }) } fn json_to_usize(json: &Value) -> Result { From aca95d3ca6683664cabb4febafa592f7e8a5fe5b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 14 Nov 2024 22:04:58 +0100 Subject: [PATCH 401/687] parse state sends list of changed properties --- .../src/lights/cached_bridge/poll.rs | 62 ++++++++++++------- .../zigbee-bridge/src/lights/parse_state.rs | 49 +++++++++------ 2 files changed, 71 insertions(+), 40 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index eda845d4..74eb65b3 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -9,8 +9,8 @@ use serde_json::Value; use tokio::{sync::RwLock, time::sleep}; use tracing::{instrument, trace}; -use crate::lights::lamp::{Lamp, LampState, Model}; -use crate::lights::parse_state::parse_lamp_state; +use crate::lights::lamp::{Lamp, LampProperty, Model}; +use crate::lights::parse_state::parse_lamp_properties; pub(super) async fn poll_mqtt( mut eventloop: EventLoop, @@ -36,24 +36,13 @@ pub(super) async fn poll_mqtt( } }; - let mut known_states = known_states.write().await; match message { - Message::StateUpdate((light_name, updated_state)) => { - let new_known_state = match known_states.get(&light_name) { - Some(lamp) => lamp.store_state(updated_state), - None => Lamp::default().store_state(updated_state), - }; - trace!("updating known state: {new_known_state:?}"); - known_states.insert(light_name, new_known_state); + Message::StateUpdate((light_name, changed_properties)) => { + update_state(known_states, light_name, changed_properties).await; } Message::Devices(new_devices) => { for (light_name, model) in new_devices { - let new_known_state = match known_states.get(&light_name) { - Some(lamp) => lamp.store_model(model), - None => Lamp::default().store_model(model), - }; - trace!("updating known state: {new_known_state:?}"); - known_states.insert(light_name, new_known_state); + update_model(known_states, light_name, model).await; } } Message::Other => (), @@ -61,10 +50,39 @@ pub(super) async fn poll_mqtt( } } -// async fn update_state(known_states: &RwLock>) { -// let mut known_states = known_states.write().await; -// known_states.entry() -// } +async fn update_model( + known_states: &RwLock>, + light_name: String, + model: Model, +) { + let mut known_states = known_states.write().await; + let curr_model = &mut known_states + .entry(light_name.to_string()) + .or_default() + .model; + *curr_model = Some(model); +} + +async fn update_state( + known_states: &RwLock>, + light_name: String, + new: Vec, +) { + let mut known_states = known_states.write().await; + let curr = &mut known_states + .entry(light_name.to_string()) + .or_default() + .state; + for property in new { + match property { + LampProperty::Brightness(bri) => curr.brightness = Some(bri), + LampProperty::ColorTempK(temp) => curr.color_temp_k = Some(temp), + LampProperty::ColorXY(xy) => curr.color_xy = Some(xy), + LampProperty::On(is_on) => curr.on = Some(is_on), + LampProperty::ColorTempStartup(behavior) => curr.color_temp_startup = behavior, + } + } +} #[instrument(skip_all)] fn parse_message(event: Event) -> color_eyre::Result { @@ -99,7 +117,7 @@ fn parse_message(event: Event) -> color_eyre::Result { let topic = String::from_utf8_lossy(&message.topic); let topic: Vec<_> = topic.split('/').collect(); let name = topic[1].to_string(); - let state = parse_lamp_state(&message.payload) + let state = parse_lamp_properties(&message.payload) .wrap_err("failed to parse lamp state") .with_note(|| format!("topic: {topic:?}"))?; Ok(Message::StateUpdate((name, state))) @@ -108,7 +126,7 @@ fn parse_message(event: Event) -> color_eyre::Result { #[derive(Debug)] enum Message { - StateUpdate((String, LampState)), + StateUpdate((String, Vec)), Devices(HashMap), Other, } diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs index 3ea8208c..61436856 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -3,6 +3,8 @@ use thiserror::Error; use crate::lights::{lamp::LampState, mired_to_kelvin, normalize}; +use super::lamp::LampProperty; + #[derive(Error, Debug)] pub(super) enum Error { #[error("Could not deserialize to json: {0}")] @@ -25,16 +27,22 @@ pub(super) enum Error { InvalidState(String), } -pub(super) fn parse_lamp_state(bytes: &[u8]) -> Result { +pub(super) fn parse_lamp_properties(bytes: &[u8]) -> Result, Error> { + let mut list = Vec::new(); + let json: Value = serde_json::from_slice(bytes)?; let map = json.as_object().ok_or(Error::NotObject(json.to_string()))?; - let color_temp_mired: Option = map + if let Some(kelvin) = map .get("color_temp") - .map(|temp| json_to_usize(temp)) - .transpose()?; + .map(|mired| json_to_usize(mired)) + .transpose()? + .map(mired_to_kelvin) + { + list.push(LampProperty::ColorTempK(kelvin)); + } - let color_xy = map + if let Some(xy) = map .get("color") .map(|color| { let color = color @@ -44,14 +52,21 @@ pub(super) fn parse_lamp_state(bytes: &[u8]) -> Result { let color_y = json_to_f64(color.get("y").ok_or(Error::MissingKey("y"))?)?; Ok::<_, Error>((color_x, color_y)) }) - .transpose()?; + .transpose()? + { + list.push(LampProperty::ColorXY(xy)); + } - let brightness: Option = map + if let Some(brightness) = map .get("brightness") .map(|bri| json_to_u8(bri)) - .transpose()?; + .transpose()? + .map(normalize) + { + list.push(LampProperty::Brightness(brightness)); + } - let on = map + if let Some(on) = map .get("state") .map(|on| { let state = on.as_str().ok_or(Error::NotString(on.to_string()))?; @@ -62,16 +77,14 @@ pub(super) fn parse_lamp_state(bytes: &[u8]) -> Result { }; Ok(on) }) - .transpose()?; + .transpose()? + { + list.push(LampProperty::On(on)) + } - Ok(LampState { - #[allow(clippy::cast_precision_loss)] - brightness: brightness.map(normalize), - color_temp_k: color_temp_mired.map(mired_to_kelvin), - color_xy, - on, - ..Default::default() - }) + // TODO: startup behavior? <14-11-24, dvdsk> + // + Ok(list) } fn json_to_usize(json: &Value) -> Result { From 0494c8b3bbd515eee833ce2d19cfac8e4ae91c6c Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 14 Nov 2024 22:20:19 +0100 Subject: [PATCH 402/687] remove error enum in favor of color_eyre --- .../zigbee-bridge/src/lights/parse_state.rs | 72 ++++++++----------- 1 file changed, 29 insertions(+), 43 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs index 61436856..e97b7ce8 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -1,37 +1,18 @@ +use color_eyre::eyre::{bail, Context, OptionExt, Report}; +use color_eyre::Section; use serde_json::Value; -use thiserror::Error; -use crate::lights::{lamp::LampState, mired_to_kelvin, normalize}; +use crate::lights::{mired_to_kelvin, normalize}; use super::lamp::LampProperty; -#[derive(Error, Debug)] -pub(super) enum Error { - #[error("Could not deserialize to json: {0}")] - NotJson(#[from] serde_json::Error), - #[error("Needed key {0}, is missing")] - MissingKey(&'static str), - #[error("Needed a number however got: {0}")] - NotNumber(String), - #[error("Needed an integer number however got: {0}")] - NotInteger(String), - #[error("Needed a 8 bit integer number however got: {0}")] - NumberNotU8(String), - #[error("Needed an usize bit integer number however got: {0}")] - NumberNotUsize(String), - #[error("Needed an uf8 string got: {0}")] - NotString(String), - #[error("Needed json object got: {0}")] - NotObject(String), - #[error("Invalid light state, expected ON or EFF got: {0}")] - InvalidState(String), -} - -pub(super) fn parse_lamp_properties(bytes: &[u8]) -> Result, Error> { +pub(super) fn parse_lamp_properties(bytes: &[u8]) -> color_eyre::Result> { let mut list = Vec::new(); - let json: Value = serde_json::from_slice(bytes)?; - let map = json.as_object().ok_or(Error::NotObject(json.to_string()))?; + let json: Value = serde_json::from_slice(bytes).wrap_err("Could not deserialize")?; + let map = json + .as_object() + .ok_or_eyre("Top level json must be object")?; if let Some(kelvin) = map .get("color_temp") @@ -47,10 +28,10 @@ pub(super) fn parse_lamp_properties(bytes: &[u8]) -> Result, E .map(|color| { let color = color .as_object() - .ok_or(Error::NotObject(color.to_string()))?; - let color_x = json_to_f64(color.get("x").ok_or(Error::MissingKey("x"))?)?; - let color_y = json_to_f64(color.get("y").ok_or(Error::MissingKey("y"))?)?; - Ok::<_, Error>((color_x, color_y)) + .ok_or_eyre("Color json should be an object")?; + let color_x = json_to_f64(color.get("x").ok_or_eyre("Need a key 'x'")?)?; + let color_y = json_to_f64(color.get("y").ok_or_eyre("Need a key 'y'")?)?; + Ok::<_, Report>((color_x, color_y)) }) .transpose()? { @@ -69,11 +50,11 @@ pub(super) fn parse_lamp_properties(bytes: &[u8]) -> Result, E if let Some(on) = map .get("state") .map(|on| { - let state = on.as_str().ok_or(Error::NotString(on.to_string()))?; + let state = on.as_str().ok_or_eyre("state should be a string")?; let on = match state { "ON" => true, "OFF" => false, - other => return Err(Error::InvalidState(other.to_string())), + _ => bail!("state string should be ON or OFF"), }; Ok(on) }) @@ -82,34 +63,39 @@ pub(super) fn parse_lamp_properties(bytes: &[u8]) -> Result, E list.push(LampProperty::On(on)) } - // TODO: startup behavior? <14-11-24, dvdsk> + // TODO: startup behavior? <14-11-24, dvdsk> // Ok(list) } -fn json_to_usize(json: &Value) -> Result { +fn json_to_usize(json: &Value) -> color_eyre::Result { json_to_u64(json)? .try_into() - .map_err(|_| Error::NumberNotUsize(json.to_string())) + .wrap_err("Should be a usize integer") + .with_note(|| format!("got: {json:?}")) } -fn json_to_u8(json: &Value) -> Result { +fn json_to_u8(json: &Value) -> color_eyre::Result { json_to_u64(json)? .try_into() - .map_err(|_| Error::NumberNotU8(json.to_string())) + .wrap_err("Should be a 8 bit integer") + .with_note(|| format!("got: {json:?}")) } -fn json_to_u64(json: &Value) -> Result { +fn json_to_u64(json: &Value) -> color_eyre::Result { json.as_number() - .ok_or(Error::NotNumber(json.to_string()))? + .ok_or_eyre("Must be a number") + .with_note(|| format!("got: {json:?}"))? .as_u64() - .ok_or(Error::NotInteger(json.to_string())) + .ok_or_eyre("Must be a positive integer") + .with_note(|| format!("got: {json:?}")) } -fn json_to_f64(json: &Value) -> Result { +fn json_to_f64(json: &Value) -> color_eyre::Result { Ok(json .as_number() - .ok_or(Error::NotNumber(json.to_string()))? + .ok_or_eyre("Must be a number") + .with_note(|| format!("got: {json:?}"))? .as_f64() .expect("Should be Some if not using arbitrary precision")) } From f0141f16ff87c55f0fdc14650651733be9b9283b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 14 Nov 2024 22:23:19 +0100 Subject: [PATCH 403/687] clippy + enable all kitchen lights --- crates/zigbee-bridge/src/lib.rs | 10 +++++----- .../zigbee-bridge/src/lights/cached_bridge/mqtt.rs | 8 +++++--- crates/zigbee-bridge/src/lights/lamp.rs | 14 -------------- crates/zigbee-bridge/src/lights/parse_state.rs | 4 ++-- 4 files changed, 12 insertions(+), 24 deletions(-) diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index fbbf26e4..5c7a53a7 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -8,12 +8,12 @@ pub mod lights; const MQTT_IP: &str = "192.168.1.43"; const MQTT_PORT: u16 = 1883; -const LIGHTS: [&str; 1] = [ - // "kitchen:fridge", +const LIGHTS: [&str; 5] = [ + "kitchen:fridge", "kitchen:hallway", - // "kitchen:hood_left", - // "kitchen:hood_right", - // "kitchen:ceiling", + "kitchen:hood_left", + "kitchen:hood_right", + "kitchen:ceiling", ]; #[cfg(test)] diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index 601486d4..01995632 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -4,7 +4,7 @@ use std::time::{Duration, Instant}; use rumqttc::v5::mqttbytes::QoS; use rumqttc::v5::{AsyncClient, ClientError}; use serde_json::json; -use tracing::{instrument, trace, warn}; +use tracing::{instrument, trace}; use crate::lights::lamp::{LampProperty, LampPropertyDiscriminants}; @@ -105,8 +105,10 @@ async fn get( } async fn publish(client: &AsyncClient, topic: &str, payload: String) -> Result<(), ClientError> { - let mut properties = rumqttc::v5::mqttbytes::v5::PublishProperties::default(); - properties.message_expiry_interval = Some(5); // seconds + let properties = rumqttc::v5::mqttbytes::v5::PublishProperties { + message_expiry_interval: Some(5), // seconds + ..Default::default() + }; client .publish_with_properties(topic, QoS::AtLeastOnce, false, payload, properties) diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 12ae48b9..d64b61ed 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -86,20 +86,6 @@ impl Lamp { self.state.changes_relative_to(&other.state) } - pub(super) fn store_model(&self, model: Model) -> Self { - Self { - model: Some(model), - state: self.state.clone(), - } - } - - pub(super) fn store_state(&self, state: LampState) -> Self { - Self { - model: self.model.clone(), - state, - } - } - pub(super) fn apply(self, change: Change) -> Self { Self { model: self.model, diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs index e97b7ce8..b4aa8b5d 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -16,7 +16,7 @@ pub(super) fn parse_lamp_properties(bytes: &[u8]) -> color_eyre::Result color_eyre::Result Date: Fri, 15 Nov 2024 14:51:25 +0100 Subject: [PATCH 404/687] logging changes --- crates/brain/test.sh | 2 +- crates/zigbee-bridge/src/lights/cached_bridge/changes.rs | 7 ++++--- crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs | 8 ++++---- crates/zigbee-bridge/src/lights/cached_bridge/poll.rs | 1 + 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/crates/brain/test.sh b/crates/brain/test.sh index fe9d7b0c..4d9f82b9 100755 --- a/crates/brain/test.sh +++ b/crates/brain/test.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -RUST_LOG=reqwest::connect=info,hyper_util=info,sled=info,rumqttc::v5::state=info,trace RUST_BACKTRACE=1 cargo r -- \ +RUST_LOG=reqwest::connect=info,hyper_util=info,sled=info,rumqttc::v5::state=info,zigbee_bridge::lights::cached_bridge::poll=trace,debug RUST_BACKTRACE=1 cargo r -- \ --data-server 192.168.1.43:1235 \ --mpd-ip 192.168.1.43 \ --port 34326 \ diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index 49dd1ef9..04c6fddd 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -3,7 +3,7 @@ use std::time::Duration; use tokio::sync::{mpsc, RwLock}; use tokio::time::{sleep, timeout}; -use tracing::{instrument, trace}; +use tracing::{debug, instrument, trace}; use super::mqtt::Mqtt; use crate::lights::lamp::{Change, Lamp}; @@ -24,11 +24,12 @@ pub(super) async fn handle( let mut call_again_in = MQTT_MIGHT_BE_DOWN_TIMEOUT; loop { + debug!("timeout: {call_again_in:?}"); if let Ok(res) = timeout(call_again_in, change_receiver.recv()).await { let res = res.expect("Channel should never close"); let (light_name, change) = res; - trace!("Received change order: {change:?}"); + trace!("Received change: {change:?} for lamp {light_name}"); apply_change(light_name, change, known_states, &mut needed_states).await; }; @@ -43,7 +44,7 @@ pub(super) async fn handle( /// make sure the set/send takes effect. We do not send it again now as that /// would be a little spammy. Returns when we need to recheck. If we do not need /// to do so we return Duration::MAX. -#[instrument(skip_all, fields(light_name))] +#[instrument(skip_all)] async fn send_and_queue( known_states: &RwLock>, needed_states: &mut HashMap, diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index 01995632..1907b56d 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -68,10 +68,10 @@ impl Mqtt { continue; } - trace!( - "not setting property {change:?} for {light_name} as it has \ - recently been set" - ); + // trace!( + // "not setting property {change:?} for {light_name} as it has \ + // recently been set" + // ); let next_call_allowed = *at + TIME_IT_TAKES_TO_APPLY_CHANGE; let until = next_call_allowed.saturating_duration_since(Instant::now()); new_call_needed_in = new_call_needed_in.min(until); diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 74eb65b3..d1e22937 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -94,6 +94,7 @@ fn parse_message(event: Event) -> color_eyre::Result { return Ok(Message::Other); }; + trace!("message: {message:?}"); let topic = String::from_utf8_lossy(&message.topic); if topic == "zigbee2mqtt/bridge/devices" { From b28f9bf5258e6587fce1e5a43517dc8083dd0fbe Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 15 Nov 2024 15:27:21 +0100 Subject: [PATCH 405/687] fix: do not send xy to lamps that do not support it --- crates/zigbee-bridge/src/lights/lamp.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index d64b61ed..2f26ee05 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -83,7 +83,8 @@ impl LampProperty { impl Lamp { pub(super) fn changes_relative_to(&self, other: &Self) -> Vec { - self.state.changes_relative_to(&other.state) + self.state + .changes_relative_to(&other.state, self.model.as_ref()) } pub(super) fn apply(self, change: Change) -> Self { @@ -114,7 +115,11 @@ fn xy_close(a: (f64, f64), b: (f64, f64)) -> bool { impl LampState { #[instrument] - pub(super) fn changes_relative_to(&self, other: &Self) -> Vec { + pub(super) fn changes_relative_to( + &self, + other: &Self, + model: Option<&Model>, + ) -> Vec { let mut res = Vec::new(); if let Some(brightness) = self.brightness { if other @@ -131,9 +136,11 @@ impl LampState { } } - if let Some(xy) = self.color_xy { - if other.color_xy.is_none_or(|xy_b| !xy_close(xy_b, xy)) { - res.push(LampProperty::ColorXY(xy)); + if model.is_some_and(Model::is_color_lamp) { + if let Some(xy) = self.color_xy { + if other.color_xy.is_none_or(|xy_b| !xy_close(xy_b, xy)) { + res.push(LampProperty::ColorXY(xy)); + } } } From 5dca7fe6286a1d61108132e70faf913e2448bd79 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 16 Nov 2024 12:11:49 +0100 Subject: [PATCH 406/687] Add rustfmt and autofmt --- crates/brain/src/controller/rooms/kitchen.rs | 10 +++- crates/zigbee-bridge/src/lib.rs | 2 +- .../zigbee-bridge/src/lights/cached_bridge.rs | 13 +++-- .../src/lights/cached_bridge/changes.rs | 7 ++- .../src/lights/cached_bridge/mqtt.rs | 27 ++++++++-- .../src/lights/cached_bridge/poll.rs | 11 +++-- crates/zigbee-bridge/src/lights/lamp.rs | 49 ++++++++++++++----- .../zigbee-bridge/src/lights/parse_state.rs | 13 +++-- rustfmt.toml | 1 + 9 files changed, 100 insertions(+), 33 deletions(-) create mode 100644 rustfmt.toml diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index 1b47b365..b0e744e7 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -18,11 +18,17 @@ enum State { const INTERVAL: Duration = Duration::from_secs(5); trait RecvFiltered { - async fn recv_filter_mapped(&mut self, filter_map: impl Fn(Event) -> Option) -> T; + async fn recv_filter_mapped( + &mut self, + filter_map: impl Fn(Event) -> Option, + ) -> T; } impl RecvFiltered for broadcast::Receiver { - async fn recv_filter_mapped(&mut self, filter_map: impl Fn(Event) -> Option) -> T { + async fn recv_filter_mapped( + &mut self, + filter_map: impl Fn(Event) -> Option, + ) -> T { loop { let event = self.recv().await.unwrap(); if let Some(relevant) = filter_map(event) { diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 5c7a53a7..32ed4a9f 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -25,7 +25,7 @@ mod tests { #[ignore] #[tokio::test] async fn change_all_lights() { - std::env::set_var("RUST_LOG", "brain=trace,zigbee_bridge=trace,info"); + std::env::set_var("RUST_LOG", "brain=trace,zigbee_bridge=trace,info"); let controller = Controller::start_bridge(); println!("Setting to on, 2200"); diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index b5c238df..b72f93b2 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -12,8 +12,11 @@ mod changes; mod mqtt; mod poll; -pub(super) async fn run(change_receiver: mpsc::UnboundedReceiver<(String, Change)>) -> ! { - let mut options = MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); +pub(super) async fn run( + change_receiver: mpsc::UnboundedReceiver<(String, Change)>, +) -> ! { + let mut options = + MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); // Set max mqtt packet size to 4kB options.set_max_packet_size(Some(4096)); @@ -21,7 +24,8 @@ pub(super) async fn run(change_receiver: mpsc::UnboundedReceiver<(String, Change // Reconnecting to broker is handled by Eventloop::poll let channel_capacity = 128; - let (client, eventloop) = AsyncClient::new(options.clone(), channel_capacity); + let (client, eventloop) = + AsyncClient::new(options.clone(), channel_capacity); let mut mqtt = Mqtt::new(client); mqtt.subscribe("zigbee2mqtt/bridge/devices").await.unwrap(); @@ -34,7 +38,8 @@ pub(super) async fn run(change_receiver: mpsc::UnboundedReceiver<(String, Change trace!("Starting main zigbee management loops"); let poll_mqtt = poll::poll_mqtt(eventloop, &known_states); - let handle_changes = changes::handle(change_receiver, &mut mqtt, &known_states); + let handle_changes = + changes::handle(change_receiver, &mut mqtt, &known_states); tokio::select! { () = handle_changes => unreachable!("should not panic"), diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index 04c6fddd..25bc298c 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -30,7 +30,8 @@ pub(super) async fn handle( let (light_name, change) = res; trace!("Received change: {change:?} for lamp {light_name}"); - apply_change(light_name, change, known_states, &mut needed_states).await; + apply_change(light_name, change, known_states, &mut needed_states) + .await; }; call_again_in = send_and_queue(known_states, &mut needed_states, mqtt) @@ -67,7 +68,9 @@ async fn send_and_queue( if !diff.is_empty() { // Ignore errors because we will retry if the state hasn't changed - if let Ok(dur) = mqtt.try_send_state_diff(light_name.to_string(), diff).await { + if let Ok(dur) = + mqtt.try_send_state_diff(light_name.to_string(), diff).await + { call_again_in = call_again_in.min(dur); } } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index 1907b56d..e0d1bb3e 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -10,7 +10,10 @@ use crate::lights::lamp::{LampProperty, LampPropertyDiscriminants}; pub(super) struct Mqtt { client: AsyncClient, - property_last_set: HashMap>, + property_last_set: HashMap< + String, + HashMap, + >, } impl Mqtt { @@ -21,7 +24,10 @@ impl Mqtt { } } - pub(super) async fn subscribe(&self, topic: &str) -> Result<(), ClientError> { + pub(super) async fn subscribe( + &self, + topic: &str, + ) -> Result<(), ClientError> { // Its okay for messages to arrive twice or more. MQTT guarantees // ordering and we only do something if the cached bridge indicates we // need to so light states arriving twice is not an issue. @@ -73,7 +79,8 @@ impl Mqtt { // recently been set" // ); let next_call_allowed = *at + TIME_IT_TAKES_TO_APPLY_CHANGE; - let until = next_call_allowed.saturating_duration_since(Instant::now()); + let until = + next_call_allowed.saturating_duration_since(Instant::now()); new_call_needed_in = new_call_needed_in.min(until); } @@ -104,13 +111,23 @@ async fn get( Ok(()) } -async fn publish(client: &AsyncClient, topic: &str, payload: String) -> Result<(), ClientError> { +async fn publish( + client: &AsyncClient, + topic: &str, + payload: String, +) -> Result<(), ClientError> { let properties = rumqttc::v5::mqttbytes::v5::PublishProperties { message_expiry_interval: Some(5), // seconds ..Default::default() }; client - .publish_with_properties(topic, QoS::AtLeastOnce, false, payload, properties) + .publish_with_properties( + topic, + QoS::AtLeastOnce, + false, + payload, + properties, + ) .await } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index d1e22937..cd1a9fd5 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -38,7 +38,8 @@ pub(super) async fn poll_mqtt( match message { Message::StateUpdate((light_name, changed_properties)) => { - update_state(known_states, light_name, changed_properties).await; + update_state(known_states, light_name, changed_properties) + .await; } Message::Devices(new_devices) => { for (light_name, model) in new_devices { @@ -79,7 +80,9 @@ async fn update_state( LampProperty::ColorTempK(temp) => curr.color_temp_k = Some(temp), LampProperty::ColorXY(xy) => curr.color_xy = Some(xy), LampProperty::On(is_on) => curr.on = Some(is_on), - LampProperty::ColorTempStartup(behavior) => curr.color_temp_startup = behavior, + LampProperty::ColorTempStartup(behavior) => { + curr.color_temp_startup = behavior + } } } } @@ -155,7 +158,9 @@ fn parse_device(device: &Value) -> color_eyre::Result<(String, Model)> { Some("TRADFRI bulb E27 CWS globe 806lm") => Model::TradfriE27, Some("TRADFRI bulb E14 CWS globe 806lm") => Model::TradfriE14, Some("LCT001") => Model::HueGen4, - Some(id) if id.to_lowercase().contains("tradfri") => Model::TradfriOther(id.to_owned()), + Some(id) if id.to_lowercase().contains("tradfri") => { + Model::TradfriOther(id.to_owned()) + } Some(id) => Model::Other(id.to_owned()), None => Model::Other(String::new()), }; diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 2f26ee05..76fc279c 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -53,11 +53,20 @@ pub(super) enum LampProperty { impl PartialEq for LampProperty { fn eq(&self, other: &Self) -> bool { match (self, other) { - (LampProperty::Brightness(a), LampProperty::Brightness(b)) => bri_close(*a, *b), - (LampProperty::ColorTempK(a), LampProperty::ColorTempK(b)) => temp_close(*a, *b), - (LampProperty::ColorXY(a), LampProperty::ColorXY(b)) => xy_close(*a, *b), + (LampProperty::Brightness(a), LampProperty::Brightness(b)) => { + bri_close(*a, *b) + } + (LampProperty::ColorTempK(a), LampProperty::ColorTempK(b)) => { + temp_close(*a, *b) + } + (LampProperty::ColorXY(a), LampProperty::ColorXY(b)) => { + xy_close(*a, *b) + } (LampProperty::On(a), LampProperty::On(b)) => a == b, - (LampProperty::ColorTempStartup(a), LampProperty::ColorTempStartup(b)) => a == b, + ( + LampProperty::ColorTempStartup(a), + LampProperty::ColorTempStartup(b), + ) => a == b, (_, _) => false, } } @@ -68,9 +77,15 @@ impl Eq for LampProperty {} impl LampProperty { pub(crate) fn payload(&self) -> String { match *self { - LampProperty::Brightness(bri) => json!({ "brightness": denormalize(bri) }), - LampProperty::ColorTempK(k) => json!({ "color_temp": kelvin_to_mired(k) }), - LampProperty::ColorXY((x, y)) => json!({ "color": {"x": x, "y": y} }), + LampProperty::Brightness(bri) => { + json!({ "brightness": denormalize(bri) }) + } + LampProperty::ColorTempK(k) => { + json!({ "color_temp": kelvin_to_mired(k) }) + } + LampProperty::ColorXY((x, y)) => { + json!({ "color": {"x": x, "y": y} }) + } LampProperty::On(lamp_on) if lamp_on => json!({"state": "ON"}), LampProperty::On(_) => json!({"state": "OFF"}), LampProperty::ColorTempStartup(ColorTempStartup::Previous) => { @@ -82,7 +97,10 @@ impl LampProperty { } impl Lamp { - pub(super) fn changes_relative_to(&self, other: &Self) -> Vec { + pub(super) fn changes_relative_to( + &self, + other: &Self, + ) -> Vec { self.state .changes_relative_to(&other.state, self.model.as_ref()) } @@ -214,7 +232,9 @@ impl PartialEq for Lamp { // We only ever set temp, and xy doesn't exist } else { match (self.state.color_temp_k, other.state.color_temp_k) { - (Some(self_temp), Some(other_temp)) => self_temp.abs_diff(other_temp) < 50, + (Some(self_temp), Some(other_temp)) => { + self_temp.abs_diff(other_temp) < 50 + } _ => false, } } @@ -224,8 +244,11 @@ impl PartialEq for Lamp { false }; - let bri_is_equal = match (self.state.brightness, other.state.brightness) { - (Some(self_bri), Some(other_bri)) => (self_bri - other_bri).abs() < 1. / 250., + let bri_is_equal = match (self.state.brightness, other.state.brightness) + { + (Some(self_bri), Some(other_bri)) => { + (self_bri - other_bri).abs() < 1. / 250. + } _ => false, }; @@ -261,7 +284,9 @@ impl Model { Model::TradfriE27 | Model::TradfriE14 | Model::HueGen4 => true, Model::TradfriCandle => false, // We assume no so that things at least don't break - Model::TradfriOther(_) | Model::HueOther(_) | Model::Other(_) => false, + Model::TradfriOther(_) | Model::HueOther(_) | Model::Other(_) => { + false + } } } diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs index b4aa8b5d..600245b1 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -6,10 +6,13 @@ use crate::lights::{mired_to_kelvin, normalize}; use super::lamp::LampProperty; -pub(super) fn parse_lamp_properties(bytes: &[u8]) -> color_eyre::Result> { +pub(super) fn parse_lamp_properties( + bytes: &[u8], +) -> color_eyre::Result> { let mut list = Vec::new(); - let json: Value = serde_json::from_slice(bytes).wrap_err("Could not deserialize")?; + let json: Value = + serde_json::from_slice(bytes).wrap_err("Could not deserialize")?; let map = json .as_object() .ok_or_eyre("Top level json must be object")?; @@ -29,8 +32,10 @@ pub(super) fn parse_lamp_properties(bytes: &[u8]) -> color_eyre::Result((color_x, color_y)) }) .transpose()? diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..df99c691 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +max_width = 80 From 147db49787bc24a4eba5d2e4f1bdc70ee42aaf7a Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 16 Nov 2024 13:07:15 +0100 Subject: [PATCH 407/687] Set kitchen to debug mode: change drastically every hour --- crates/brain/src/controller/rooms/kitchen.rs | 20 +++++++++++-------- .../src/lights/cached_bridge/mqtt.rs | 3 ++- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index b0e744e7..f05aafeb 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -4,6 +4,7 @@ use futures_concurrency::future::Race; use futures_util::FutureExt; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; +use tracing::warn; use crate::controller::rooms::small_bedroom; use crate::controller::{local_now, Event, RestrictedSystem}; @@ -75,26 +76,29 @@ pub async fn run( Res::Event(_) => (), // handle_event(e), Res::ShouldUpdate => { update(&mut system).await; - next_update = Instant::now() + Duration::from_secs(60); + next_update = Instant::now() + INTERVAL; } } } } async fn update(system: &mut RestrictedSystem) { - let (new_ct, new_bri) = small_bedroom::optimal_ct_bri(); + let (new_ct, new_bri) = optimal_ct_bri(); system.all_lamps_ct(new_ct, new_bri).await; tracing::trace!("updated lamps"); } -fn _optimal_ct_bri() -> (u16, u8) { +fn optimal_ct_bri() -> (u16, u8) { let now = local_now(); - match now.hour() { - 0..=8 | 22.. => (500, 180), - 9..=16 => (270, u8::MAX), - 17..=19 => (300, u8::MAX), - 20..=21 => (400, 210), + let optimal = match now.hour() { + min if min % 2 == 0 => (400, u8::MAX), // Even hour: orange + min if min % 2 == 1 => (250, u8::MAX), // Odd hour: blue + _ => (400, u8::MAX), + }; + if now.second() <= 9 { + warn!("Correct color temp is now {}", optimal.0); } + optimal } // fn handle_event(e: RelevantEvent) { diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index e0d1bb3e..ef955e82 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -4,7 +4,7 @@ use std::time::{Duration, Instant}; use rumqttc::v5::mqttbytes::QoS; use rumqttc::v5::{AsyncClient, ClientError}; use serde_json::json; -use tracing::{instrument, trace}; +use tracing::{instrument, trace, warn}; use crate::lights::lamp::{LampProperty, LampPropertyDiscriminants}; @@ -121,6 +121,7 @@ async fn publish( ..Default::default() }; + warn!("To MQTT: {topic}, {payload}"); client .publish_with_properties( topic, From 4e7f45b7e34928736bb8c475f08079b323df6175 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 17 Nov 2024 21:09:05 +0100 Subject: [PATCH 408/687] fixes affector order decoder + add data_source tests --- Cargo.lock | 1 + crates/data-server/src/api/data_source.rs | 39 ++-- .../src/api/data_source/reconnecting.rs | 24 ++- crates/data-server/src/main.rs | 24 ++- crates/data-server/src/server/affector.rs | 1 + crates/data-server/tests/source_api.rs | 204 ++++++++++++++++++ crates/desk-sensors/Cargo.toml | 1 + crates/desk-sensors/src/main.rs | 25 ++- crates/protocol/Cargo.toml | 2 +- crates/protocol/src/affector.rs | 19 +- crates/usb-bridge/Cargo.toml | 1 - crates/usb-bridge/src/main.rs | 23 +- 12 files changed, 320 insertions(+), 44 deletions(-) create mode 100644 crates/data-server/tests/source_api.rs diff --git a/Cargo.lock b/Cargo.lock index 17716b7a..e965cc62 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -958,6 +958,7 @@ dependencies = [ "heapless 0.8.0", "linux-embedded-hal", "protocol", + "ratelimited-logger", "tokio", "tracing", "tracing-error", diff --git a/crates/data-server/src/api/data_source.rs b/crates/data-server/src/api/data_source.rs index 6845a980..3b0b298a 100644 --- a/crates/data-server/src/api/data_source.rs +++ b/crates/data-server/src/api/data_source.rs @@ -51,23 +51,12 @@ impl Client { let (reader, writer) = stream.into_split(); Ok(Self { - receiver: Receiver { - reader, - decoder: affector::Decoder::default(), - buffer: vec![0u8; 100], - }, + receiver: Receiver::from_reader(reader), sender: Sender(writer), }) } } -pub struct Sender(OwnedWriteHalf); -pub struct Receiver { - reader: OwnedReadHalf, - decoder: affector::Decoder, - buffer: Vec, -} - #[derive(Debug, thiserror::Error)] pub enum SendPreEncodedError { #[error("Pre-encoded message, could not be decoded it might be from a previous version: {0}")] @@ -107,13 +96,37 @@ pub enum ReceiveError { Io(std::io::Error), #[error("The connection was closed by the data-server")] ConnClosed, + #[error("Could not deserialize")] + Deserialize(affector::DeserializeError), +} + +pub struct Sender(OwnedWriteHalf); +pub struct Receiver { + reader: OwnedReadHalf, + decoder: affector::Decoder, + buffer: Vec, } impl Receiver { + fn from_reader(reader: OwnedReadHalf) -> Self { + Self { + reader, + decoder: affector::Decoder::default(), + buffer: Vec::new(), + } + } + pub async fn receive(&mut self) -> Result { loop { if !self.buffer.is_empty() { - if let Some((item, remaining)) = self.decoder.feed(&self.buffer) { + if let Some((item, remaining)) = self + .decoder + // this should shrink the buffer on deserialize error, it does + // not however. For now its okay (no more errors) however if + // something goes wrong in the future this is where to look first + .feed(&self.buffer) + .map_err(ReceiveError::Deserialize)? + { let new_buffer = remaining.to_vec(); self.buffer = new_buffer; return Ok(item); diff --git a/crates/data-server/src/api/data_source/reconnecting.rs b/crates/data-server/src/api/data_source/reconnecting.rs index d8949804..647ab1b4 100644 --- a/crates/data-server/src/api/data_source/reconnecting.rs +++ b/crates/data-server/src/api/data_source/reconnecting.rs @@ -46,6 +46,7 @@ async fn handle_conn( } } } else { + dbg!(); handle_sending(conn.sender, &mut msgs_to_send).await; } } @@ -70,6 +71,7 @@ async fn handle_sending( if let Err(e) = res { return SendOrRecvError::Sending(e); } + tracing::debug!("send bytes: {}", msg.len()); } } @@ -97,6 +99,7 @@ async fn handle_recieving( Err(err) => return SendOrRecvError::Recieving(err), }; + tracing::debug!("recv item: {msg:?}"); msgs_recieved .send(msg) .await @@ -104,23 +107,34 @@ async fn handle_recieving( } } +#[derive(Debug, thiserror::Error)] +#[error("Invalid address: {0}")] +pub struct InvalidAddress(String); + impl Client { /// Needs a list of the affectors that can be controlled through this /// node as an argument. If your node provides not controllable affectors /// pass in an empty Vec. #[must_use] - pub fn new( - addr: SocketAddr, + pub async fn new( + addr: A, affectors: Vec, affector_tx: Option>, - ) -> Self { + ) -> Result { + let addr: SocketAddr = tokio::net::lookup_host(addr) + .await + .map_err(|e| e.to_string()) + .map_err(InvalidAddress)? + .next() + .ok_or_else(|| InvalidAddress("No address passed in".to_string()))?; + let (to_send_tx, to_send_rx) = mpsc::channel(100); let task = handle_conn(addr, affectors, to_send_rx, affector_tx); let handle = tokio::spawn(task); - Self { + Ok(Self { _conn_handler_task: AbortOnDrop(handle), to_send_tx, - } + }) } async fn send_bytes(&mut self, bytes: Vec) -> Result<(), SendError> { diff --git a/crates/data-server/src/main.rs b/crates/data-server/src/main.rs index e298acf1..24fee887 100644 --- a/crates/data-server/src/main.rs +++ b/crates/data-server/src/main.rs @@ -21,6 +21,10 @@ struct Cli { /// Addr to which data-source can supply messages #[arg(short, long)] update_addr: SocketAddr, + + /// Reset data-sources that have missing or slow sensors + #[arg(short, long)] + enable_reset: bool, } #[tokio::main(flavor = "current_thread")] @@ -30,6 +34,7 @@ async fn main() -> Result<()> { let Cli { subscribe_addr, update_addr, + enable_reset, } = Cli::parse(); assert_ne!(subscribe_addr, update_addr); @@ -38,11 +43,20 @@ async fn main() -> Result<()> { let affectors = server::AffectorRegistar::default(); let (tx, rx) = mpsc::channel(2000); - select! { - e = server::client::handle(subscribe_addr, tx.clone(), affectors.clone()) => e, - e = server::handle_nodes(update_addr, &tx, affectors.clone()) => e, - e = server::spread_updates(rx) => e, - _ = server::node_watchdog(affectors, &tx) => Ok(()), + + if enable_reset { + select! { + e = server::client::handle(subscribe_addr, tx.clone(), affectors.clone()) => e, + e = server::handle_nodes(update_addr, &tx, affectors.clone()) => e, + e = server::spread_updates(rx) => e, + _ = server::node_watchdog(affectors, &tx) => Ok(()), + } + } else { + select! { + e = server::client::handle(subscribe_addr, tx.clone(), affectors.clone()) => e, + e = server::handle_nodes(update_addr, &tx, affectors.clone()) => e, + e = server::spread_updates(rx) => e, + } } } diff --git a/crates/data-server/src/server/affector.rs b/crates/data-server/src/server/affector.rs index 9c91c088..7a13be49 100644 --- a/crates/data-server/src/server/affector.rs +++ b/crates/data-server/src/server/affector.rs @@ -110,6 +110,7 @@ pub enum AffectorError { pub(super) async fn control_affectors(mut writer: OwnedWriteHalf, mut rx: Receiver) { while let Some(new_order) = rx.recv().await { let buf = new_order.encode(); + dbg!(&buf); if let Err(e) = writer.write_all(&buf).await { warn!("Could not send affector order: {e}"); break; diff --git a/crates/data-server/tests/source_api.rs b/crates/data-server/tests/source_api.rs new file mode 100644 index 00000000..b180e43e --- /dev/null +++ b/crates/data-server/tests/source_api.rs @@ -0,0 +1,204 @@ +use std::future::pending; +use std::net::{Ipv4Addr, SocketAddr}; +use std::time::Duration; + +use color_eyre::Result; +use data_server::api::data_source; +use data_server::api::subscriber::{Client, SubMessage}; +use data_server::server::{self, AffectorRegistar}; +use protocol::large_bedroom::bed; +use protocol::Reading; +use protocol::{large_bedroom, Affector}; +use tokio::io::AsyncWriteExt; +use tokio::net::TcpStream; +use tokio::select; +use tokio::sync::mpsc; +use tokio::time::sleep; + +#[derive(Debug, PartialEq)] +enum Done { + RunServer, + SendValue, + Test, +} + +const TEST_READING: Reading = + Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::NumberPm2_5(0.0))); +const TEST_AFFECTOR: Affector = + Affector::LargeBedroom(large_bedroom::Affector::Bed(bed::Affector::ResetNode)); + +async fn run_server( + client_addr: impl Into, + data_port: impl Into, +) -> Result { + let (tx, rx) = mpsc::channel(2000); + let affectors = AffectorRegistar::default(); + select! { + e = server::client::handle(client_addr.into(), tx.clone(), affectors.clone()) => e.unwrap(), + e = server::handle_nodes(data_port.into(), &tx, affectors) => e.unwrap(), + e = server::spread_updates(rx) => e?, + }; + + Ok(Done::RunServer) +} + +async fn send_sensor_value(data_port: u16) -> Result { + tokio::time::sleep(Duration::from_millis(500)).await; + + let mut list = protocol::affector::ListMessage::<50>::empty(); + list.values + .push(protocol::Affector::LargeBedroom( + large_bedroom::Affector::Bed(bed::Affector::Sps30FanClean), + )) + .unwrap(); + let handshake = protocol::Msg::AffectorList(list).encode(); + + let mut conn = TcpStream::connect(("127.0.0.1", data_port)).await.unwrap(); + conn.write_all(&handshake).await.unwrap(); + + let mut sensor_msg = protocol::SensorMessage::<50>::default(); + sensor_msg.values.push(TEST_READING).unwrap(); + let sensor_msg = protocol::Msg::Readings(sensor_msg).encode(); + conn.write_all(&sensor_msg).await.unwrap(); + + sleep(Duration::from_secs(999)).await; + Ok(Done::SendValue) +} + +async fn subscribe_and_receive_inner(sub_port: u16) -> Result { + tokio::time::sleep(Duration::from_millis(100)).await; + let mut sub = Client::connect( + (Ipv4Addr::LOCALHOST, sub_port), + "api_integration_tests".to_owned(), + ) + .await + .unwrap() + .subscribe() + .await + .unwrap(); + + let received = sub.next().await.unwrap(); + assert!(matches!(received, SubMessage::Reading(TEST_READING))); + + Ok(Done::Test) +} + +async fn list_affectors_inner(sub_port: u16) -> Result { + tokio::time::sleep(Duration::from_millis(500)).await; + let list = Client::connect( + (Ipv4Addr::LOCALHOST, sub_port), + "api_integration_tests".to_owned(), + ) + .await + .unwrap() + .list_affectors() + .await + .unwrap(); + + assert_eq!( + list, + [protocol::Affector::LargeBedroom( + large_bedroom::Affector::Bed(bed::Affector::Sps30FanClean) + )] + ); + + Ok(Done::Test) +} + +#[tokio::test] +async fn subscribe_and_receive() { + setup_tracing(); + + let sub_port = reserve_port::ReservedPort::random().unwrap(); + let data_port = reserve_port::ReservedPort::random().unwrap(); + let res = select! { + e = run_server(([127,0,0,1], sub_port.port()), ([127,0,0,1], data_port.port())) => e, + e = send_sensor_value(data_port.port()) => e, + e = subscribe_and_receive_inner(sub_port.port()) => e, + }; + assert_eq!(res.unwrap(), Done::Test); +} + +#[tokio::test] +async fn list_affectors() { + setup_tracing(); + + let sub_port = reserve_port::ReservedPort::random().unwrap(); + let data_port = reserve_port::ReservedPort::random().unwrap(); + let res = select! { + e = run_server(([127,0,0,1], sub_port.port()), ([127,0,0,1], data_port.port())) => e, + e = send_sensor_value(data_port.port()) => e, + e = list_affectors_inner(sub_port.port()) => e, + }; + assert_eq!(res.unwrap(), Done::Test); +} + +async fn trigger_affector(sub_port: u16) -> Result { + tokio::time::sleep(Duration::from_millis(100)).await; + let mut client = Client::connect( + (Ipv4Addr::LOCALHOST, sub_port), + "api_integration_tests".to_owned(), + ) + .await + .unwrap(); + + client.actuate_affector(TEST_AFFECTOR).await.unwrap(); + Ok(pending::().await) +} + +async fn recv_affector_order(data_port: u16) -> Result { + let (tx, mut rx) = mpsc::channel(2); + let _client = data_source::reconnecting::Client::new( + (Ipv4Addr::LOCALHOST, data_port), + vec![TEST_AFFECTOR], + Some(tx), + ) + .await + .unwrap(); + + let affector_order = tokio::time::timeout(Duration::from_secs(1), rx.recv()) + .await + .unwrap() + .unwrap(); + + assert_eq!(affector_order, TEST_AFFECTOR); + + Ok(Done::Test) +} + +#[tokio::test] +async fn recv_affector() { + setup_tracing(); + + let sub_port = reserve_port::ReservedPort::random().unwrap(); + let data_port = reserve_port::ReservedPort::random().unwrap(); + let res = select! { + e = run_server(([127,0,0,1], sub_port.port()), ([127,0,0,1], data_port.port())) => e, + e = recv_affector_order(data_port.port()) => e, + e = trigger_affector(sub_port.port()) => e, + }; + assert_eq!(res.unwrap(), Done::Test); +} + +fn setup_tracing() { + // use std::sync::Once; + // use tracing_error::ErrorLayer; + // use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt, Layer}; + // + // static INIT: Once = Once::new(); + // + // INIT.call_once(|| { + // color_eyre::install().unwrap(); + // + // let file_subscriber = tracing_subscriber::fmt::layer() + // .with_file(true) + // .with_line_number(true) + // .with_target(false) + // .with_ansi(false) + // .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()); + // tracing_subscriber::registry() + // .with(file_subscriber) + // .with(ErrorLayer::default()) + // .init(); + // }) +} diff --git a/crates/desk-sensors/Cargo.toml b/crates/desk-sensors/Cargo.toml index 6914c9bc..a3c59ce9 100644 --- a/crates/desk-sensors/Cargo.toml +++ b/crates/desk-sensors/Cargo.toml @@ -18,6 +18,7 @@ color-eyre = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace =true, features = ["env-filter"] } tracing-error = { workspace = true } +ratelimited-logger = { workspace = true } tokio = { workspace = true, features = ["rt", "time", "macros"] } embedded-hal-async = "1.0.0" diff --git a/crates/desk-sensors/src/main.rs b/crates/desk-sensors/src/main.rs index 465ec181..666aedef 100644 --- a/crates/desk-sensors/src/main.rs +++ b/crates/desk-sensors/src/main.rs @@ -1,6 +1,8 @@ use clap::Parser; +use color_eyre::eyre::Context; use color_eyre::Result; -use data_server::api::data_source; +use data_server::api::data_source::reconnecting::Client; +use ratelimited_logger::RateLimitedLogger; use std::net::SocketAddr; use tokio::sync::mpsc; @@ -29,17 +31,30 @@ async fn main() { let cli = Cli::parse(); setup_tracing().unwrap(); + let mut logger = RateLimitedLogger::default(); let (tx, mut rx) = mpsc::channel(100); sensors::start_monitoring(tx.clone(), cli.bedroom); info!("connecting to dataserver on: {}", cli.data_server); - let mut client = data_source::reconnecting::Client::new(cli.data_server, Vec::new(), None); + let mut client = Client::new(cli.data_server, Vec::new(), None) + .await + .unwrap(); loop { - match rx.recv().await.expect("sensor monitoring never stops") { - Ok(reading) => client.send_reading(reading).await, - Err(report) => client.send_error(report).await, + let res = match rx.recv().await.expect("sensor monitoring never stops") { + Ok(reading) => client + .send_reading(reading) + .await + .wrap_err("Sending reading"), + Err(report) => client + .send_error(report) + .await + .wrap_err("Sending error report"), + }; + + if let Err(e) = res { + ratelimited_logger::warn!(logger; "{e}"); } } } diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index aa740c14..76620158 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -10,7 +10,7 @@ authors.workspace = true [dependencies] serde = { version = "1.0", features = ["derive"], default-features = false } -postcard = { version = "1.0", features = ["experimental-derive", "use-defmt"] } +postcard = { version = "1.0.10", features = ["experimental-derive", "use-defmt"] } heapless = { version = "0.8.0", features = ["serde", "defmt-03"] } strum = { version = "0.26.2", default-features = false, features = ["derive"] } thiserror = { workspace = true, optional = true } diff --git a/crates/protocol/src/affector.rs b/crates/protocol/src/affector.rs index 8c5c5513..c8f64b03 100644 --- a/crates/protocol/src/affector.rs +++ b/crates/protocol/src/affector.rs @@ -94,18 +94,25 @@ impl Default for Decoder { } } +#[derive(Debug)] +pub struct DeserializeError; + impl Decoder { /// If this returns Some(_, remaining) move the remaining into it again - pub fn feed<'a>(&mut self, read_bytes: &'a [u8]) -> Option<(Affector, &'a [u8])> { + pub fn feed<'a>( + &mut self, + read_bytes: &'a [u8], + ) -> Result, DeserializeError> { let mut window = read_bytes; while !window.is_empty() { window = match self.cobs_buf.feed::(read_bytes) { FeedResult::Consumed => break, - FeedResult::OverFull(new_window) | FeedResult::DeserError(new_window) => new_window, - FeedResult::Success { data, remaining } => return Some((data, remaining)), + FeedResult::OverFull(new_window) => new_window, + FeedResult::DeserError(_) => return Err(DeserializeError), + FeedResult::Success { data, remaining } => return Ok(Some((data, remaining))), } } - None + Ok(None) } } @@ -170,8 +177,8 @@ mod test { let mut decoder = Decoder::default(); - decoder.feed(&encoded); - let res = decoder.feed(&encoded); + decoder.feed(&encoded).unwrap(); + let res = decoder.feed(&encoded).unwrap(); let empty_slice = [].as_slice(); assert_eq!(res, Some((test_affector, empty_slice))); diff --git a/crates/usb-bridge/Cargo.toml b/crates/usb-bridge/Cargo.toml index dea717f8..e9658f22 100644 --- a/crates/usb-bridge/Cargo.toml +++ b/crates/usb-bridge/Cargo.toml @@ -21,4 +21,3 @@ tracing = { workspace = true } nusb = "0.1.10" color-eyre.workspace = true users = "0.11.0" - diff --git a/crates/usb-bridge/src/main.rs b/crates/usb-bridge/src/main.rs index 5feb02bb..b9ec53b8 100644 --- a/crates/usb-bridge/src/main.rs +++ b/crates/usb-bridge/src/main.rs @@ -5,6 +5,7 @@ use clap::Parser; use color_eyre::eyre::Context; use color_eyre::Section; use data_server::api::data_source::reconnecting; +use tracing::debug; mod usb; @@ -25,7 +26,9 @@ struct Cli { async fn main() -> Result<(), color_eyre::Report> { color_eyre::install().unwrap(); setup_tracing(); + let args = Cli::parse(); + debug!("Started usb-bridge"); let (order_tx, order_rx) = tokio::sync::mpsc::channel(10); let mut usb = usb::ReconnectingUsb::new(args.serial_number, order_rx); @@ -33,17 +36,20 @@ async fn main() -> Result<(), color_eyre::Report> { .get_affectors() .await .wrap_err("Could not get affector list")?; - // let mut server_client = reconnecting::Client::new(args.data_server, affectors, Some(order_tx)); - dbg!(affectors); + dbg!(&affectors); + let mut server_client = reconnecting::Client::new( + args.data_server, + affectors, + Some(order_tx), + ).await?; loop { let encoded_msg = usb.handle_usb().await; - dbg!("msg: {}", encoded_msg.len()); - // server_client - // .check_send_encoded(encoded_msg) - // .await - // .wrap_err("Should be correctly encoded") - // .suggestion("Check if this needs to be updated")?; + server_client + .check_send_encoded(encoded_msg) + .await + .wrap_err("Should be correctly encoded") + .suggestion("Check if this needs to be updated")?; } } @@ -55,6 +61,7 @@ fn setup_tracing() { .with_file(true) .with_line_number(true) .with_target(false) + .without_time() .with_ansi(false) .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()); tracing_subscriber::registry() From 5ab51fd792e8ded9b3ece8d530c6cc3cb6172e2f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 17 Nov 2024 23:16:58 +0100 Subject: [PATCH 409/687] ratelimited logging now per msg +globla limit --- crates/ratelimited-logger/src/lib.rs | 88 ++++++++++++++-------------- crates/usb-bridge/src/usb.rs | 16 +++-- 2 files changed, 55 insertions(+), 49 deletions(-) diff --git a/crates/ratelimited-logger/src/lib.rs b/crates/ratelimited-logger/src/lib.rs index 03998f6d..aca52b45 100644 --- a/crates/ratelimited-logger/src/lib.rs +++ b/crates/ratelimited-logger/src/lib.rs @@ -1,5 +1,6 @@ use governor::clock::DefaultClock; use governor::middleware::NoOpMiddleware; +use governor::state::keyed::DefaultKeyedStateStore; use governor::state::InMemoryState; use governor::state::NotKeyed; use governor::Quota; @@ -8,22 +9,29 @@ use std::num::NonZeroU32; use std::time::Duration; pub struct RateLimitedLogger { - pub rate_limiter: RateLimiter, + pub msg_rate_limiter: + RateLimiter, DefaultClock, NoOpMiddleware>, + pub global_rate_limiter: RateLimiter, pub withheld: usize, } #[macro_export] macro_rules! warn { ($limiter:ident; $($arg:tt)*) => { - if $limiter.rate_limiter.check().is_err() { - $limiter.withheld += 1; - } else { - if $limiter.withheld > 0 { - tracing::warn!("Logs are being spammed, withheld {} logs", $limiter.withheld); - $limiter.withheld = 0; - } + { // scope so msg cannot interfere with locals with same name + let msg = format!($($arg)*); + if $limiter.global_rate_limiter.check().is_err() { + $limiter.withheld += 1; + } else if $limiter.msg_rate_limiter.check_key(&msg).is_err() { + $limiter.withheld += 1; + } else { + if $limiter.withheld > 0 { + tracing::warn!("Logs are being spammed, withheld {} copies of this msg", $limiter.withheld); + $limiter.withheld = 0; + } - tracing::warn!($($arg)*); + tracing::warn!("{msg}"); + } } }; } @@ -31,57 +39,49 @@ macro_rules! warn { #[macro_export] macro_rules! info { ($limiter:ident; $($arg:tt)*) => { - if $limiter.rate_limiter.check().is_err() { - $limiter.withheld += 1; - } else { - if $limiter.withheld > 0 { - tracing::info!("Logs are being spammed, withheld {} logs", $limiter.withheld); - $limiter.withheld = 0; - } + { // scope so msg cannot interfere with locals with same name + let msg = format!($($arg)*); + if $limiter.global_rate_limiter.check().is_err() { + $limiter.withheld += 1; + } else if $limiter.msg_rate_limiter.check_key(&msg).is_err() { + $limiter.withheld += 1; + } else { + if $limiter.withheld > 0 { + tracing::info!("Logs are being spammed, withheld {} copies of this msgs", $limiter.withheld); + $limiter.withheld = 0; + } - tracing::info!($($arg)*); + tracing::info!("{msg}"); + } } }; } impl Default for RateLimitedLogger { fn default() -> Self { - let quota = Quota::with_period(Duration::from_secs(1)) + let per_msg_quota = Quota::with_period(Duration::from_secs(5)) .unwrap() .allow_burst(NonZeroU32::new(5).unwrap()); + let global_quota = Quota::with_period(Duration::from_secs(1)) + .unwrap() + .allow_burst(NonZeroU32::new(25).unwrap()); Self { - rate_limiter: RateLimiter::direct(quota), + msg_rate_limiter: RateLimiter::keyed(per_msg_quota), + global_rate_limiter: RateLimiter::direct(global_quota), withheld: 0, } } } impl RateLimitedLogger { - pub fn warn(&mut self, txt: &str) { - if self.rate_limiter.check().is_err() { - self.withheld += 1; - return; - } - - if self.withheld > 0 { - tracing::warn!("Logs are being spammed, withheld {} logs", self.withheld); - self.withheld = 0; - } - - tracing::warn!(txt); - } - - pub fn info(&mut self, txt: &str) { - if self.rate_limiter.check().is_err() { - self.withheld += 1; - return; - } - - if self.withheld > 0 { - tracing::info!("Logs are being spammed, withheld {} logs", self.withheld); - self.withheld = 0; + pub fn with_per_msg_period(self, one_msg_per: Duration) -> Self { + let quota = Quota::with_period(one_msg_per) + .unwrap() + .allow_burst(NonZeroU32::new(5).unwrap()); + Self { + msg_rate_limiter: RateLimiter::keyed(quota), + global_rate_limiter: self.global_rate_limiter, + withheld: self.withheld, } - - tracing::info!(txt); } } diff --git a/crates/usb-bridge/src/usb.rs b/crates/usb-bridge/src/usb.rs index 443a7a09..719b9eb0 100644 --- a/crates/usb-bridge/src/usb.rs +++ b/crates/usb-bridge/src/usb.rs @@ -37,20 +37,26 @@ impl ReconnectingUsb { next_poll: Instant::now(), conn: None, bytes: Vec::new().into_iter(), - logger: ratelimited_logger::RateLimitedLogger::default(), + logger: ratelimited_logger::RateLimitedLogger::default() + .with_per_msg_period(Duration::from_secs(60)), to_send, } } pub(crate) async fn get_affectors(&mut self) -> color_eyre::Result> { let msg = loop { - if let Some(msg) = self + match self .try_request_data(device::get(protocol::usb::GET_AFFECTOR_LIST)) - .await? + .await { - break msg; + Ok(Some(msg)) => break msg, + Ok(None) => continue, // needs another call to decode more + Err(e) => { + let logger = &mut self.logger; + rl::warn!(logger; "Error trying get affector list: {e}"); + sleep(Duration::from_secs(5)).await; + } } - sleep(Duration::from_secs(5)).await; }; let msg = protocol::Msg::<50>::decode(msg.to_vec()).wrap_err( "Could not decode protocol::Msg, maybe the protocol library \ From 41b2c7436ec28d5ef138441c37af5850657e112b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 18 Nov 2024 16:32:44 +0100 Subject: [PATCH 410/687] removed leftover spammy info call --- crates/usb-bridge/src/usb.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/usb-bridge/src/usb.rs b/crates/usb-bridge/src/usb.rs index 719b9eb0..a47ce1ba 100644 --- a/crates/usb-bridge/src/usb.rs +++ b/crates/usb-bridge/src/usb.rs @@ -72,7 +72,6 @@ impl ReconnectingUsb { pub(crate) async fn handle_usb(&mut self) -> Vec { let mut retry_period = Duration::from_millis(100); loop { - tracing::info!("polling usb"); if let Some(len) = self.bytes.next() { if len == 0 { self.bytes = Vec::new().into_iter(); From 9af3fad27e4a29191cdff639ec51ba2905f07c0d Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 17 Nov 2024 13:20:29 +0100 Subject: [PATCH 411/687] Add extensive but efficient trace logging (as warn) --- crates/brain/src/controller/mod.rs | 8 ++++++++ crates/brain/src/controller/rooms/kitchen.rs | 8 ++++---- .../src/lights/cached_bridge/mqtt.rs | 4 +++- .../src/lights/cached_bridge/poll.rs | 15 ++++++++++++--- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 171311e1..8ca91e87 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize}; use time::{OffsetDateTime, UtcOffset}; use tokio::sync::broadcast; use tokio::task::JoinSet; +use tracing::warn; use zigbee_bridge::lights::{mired_to_kelvin, normalize}; // now_local works some of the time only... this replaces it with....... @@ -41,6 +42,13 @@ impl RestrictedSystem { self.system.lights.set_ct(name, bri, ct).await.unwrap(); } + let now = local_now(); + if !&self.allowed_lights_new.is_empty() + && now.minute() == 0 + && now.second() <= 9 + { + warn!("B sending changes to ZB (every 5s from now): ct = {ct}"); + } for name in &self.allowed_lights_new { self.system .lights_new diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index f05aafeb..1622d165 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -83,20 +83,20 @@ pub async fn run( } async fn update(system: &mut RestrictedSystem) { - let (new_ct, new_bri) = optimal_ct_bri(); + let (new_ct, new_bri) = small_bedroom::optimal_ct_bri(); system.all_lamps_ct(new_ct, new_bri).await; tracing::trace!("updated lamps"); } -fn optimal_ct_bri() -> (u16, u8) { +fn _testing_ct_bri() -> (u16, u8) { let now = local_now(); let optimal = match now.hour() { min if min % 2 == 0 => (400, u8::MAX), // Even hour: orange min if min % 2 == 1 => (250, u8::MAX), // Odd hour: blue _ => (400, u8::MAX), }; - if now.second() <= 9 { - warn!("Correct color temp is now {}", optimal.0); + if now.minute() == 0 && now.second() <= 9 { + warn!("B: correct color temp is now {}", optimal.0); } optimal } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index ef955e82..e17c885b 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -121,7 +121,9 @@ async fn publish( ..Default::default() }; - warn!("To MQTT: {topic}, {payload}"); + if topic.contains("kitchen:fridge") { + warn!("ZB to MQTT (fridge): {payload}"); + } client .publish_with_properties( topic, diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index cd1a9fd5..e8a00ee9 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -7,8 +7,9 @@ use ratelimited_logger::RateLimitedLogger; use rumqttc::v5::{Event, EventLoop, Incoming}; use serde_json::Value; use tokio::{sync::RwLock, time::sleep}; -use tracing::{instrument, trace}; +use tracing::{instrument, trace, warn}; +use crate::lights::kelvin_to_mired; use crate::lights::lamp::{Lamp, LampProperty, Model}; use crate::lights::parse_state::parse_lamp_properties; @@ -31,7 +32,7 @@ pub(super) async fn poll_mqtt( let message = match parse_message(message) { Ok(message) => message, Err(err) => { - ratelimited_logger::warn!(logger; "Error parsing mqtt message: {err}"); + ratelimited_logger::warn!(logger; "ZB error parsing mqtt message: {err}"); continue; } }; @@ -77,7 +78,15 @@ async fn update_state( for property in new { match property { LampProperty::Brightness(bri) => curr.brightness = Some(bri), - LampProperty::ColorTempK(temp) => curr.color_temp_k = Some(temp), + LampProperty::ColorTempK(temp) => { + if light_name == "kitchen:fridge" { + warn!( + "ZB received fridge color temp change: {}", + kelvin_to_mired(temp) + ); + } + curr.color_temp_k = Some(temp) + } LampProperty::ColorXY(xy) => curr.color_xy = Some(xy), LampProperty::On(is_on) => curr.on = Some(is_on), LampProperty::ColorTempStartup(behavior) => { From 7e75b2d17d25b5467f45112ec400dd987f8a8928 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 22 Nov 2024 18:20:29 +0100 Subject: [PATCH 412/687] Fix lights not responding after ~1h (tested) --- crates/zigbee-bridge/src/lights/cached_bridge.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index b72f93b2..be54c42e 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -19,6 +19,8 @@ pub(super) async fn run( MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); // Set max mqtt packet size to 4kB options.set_max_packet_size(Some(4096)); + // Keep subscriptions when reconnecting!!!! + options.set_clean_start(false); let known_states = RwLock::new(HashMap::new()); From 11b313ce60755943269f03811f169aecf92d40d3 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 17 Nov 2024 13:27:36 +0100 Subject: [PATCH 413/687] Rename vars for clarity --- crates/zigbee-bridge/src/lights/lamp.rs | 42 ++++++++++++++----------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 76fc279c..0e1c6ae1 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -54,13 +54,13 @@ impl PartialEq for LampProperty { fn eq(&self, other: &Self) -> bool { match (self, other) { (LampProperty::Brightness(a), LampProperty::Brightness(b)) => { - bri_close(*a, *b) + bri_is_close(*a, *b) } (LampProperty::ColorTempK(a), LampProperty::ColorTempK(b)) => { - temp_close(*a, *b) + temp_is_close(*a, *b) } (LampProperty::ColorXY(a), LampProperty::ColorXY(b)) => { - xy_close(*a, *b) + xy_is_close(*a, *b) } (LampProperty::On(a), LampProperty::On(b)) => a == b, ( @@ -117,15 +117,15 @@ impl Lamp { } } -fn bri_close(a: f64, b: f64) -> bool { +fn bri_is_close(a: f64, b: f64) -> bool { (a - b).abs() < 1. / 250. } -fn temp_close(a: usize, b: usize) -> bool { +fn temp_is_close(a: usize, b: usize) -> bool { a.abs_diff(b) < 50 } -fn xy_close(a: (f64, f64), b: (f64, f64)) -> bool { +fn xy_is_close(a: (f64, f64), b: (f64, f64)) -> bool { let d_color_x = (a.0 - b.0).abs(); let d_color_y = (a.1 - b.1).abs(); d_color_x < 0.01 && d_color_y < 0.01 @@ -139,32 +139,38 @@ impl LampState { model: Option<&Model>, ) -> Vec { let mut res = Vec::new(); - if let Some(brightness) = self.brightness { + if let Some(bri_self) = self.brightness { if other .brightness - .is_none_or(|bri| !bri_close(bri, brightness)) + .is_none_or(|bri_other| !bri_is_close(bri_other, bri_self)) { - res.push(LampProperty::Brightness(brightness)); + res.push(LampProperty::Brightness(bri_self)); } } - if let Some(temp) = self.color_temp_k { - if other.color_temp_k.is_none_or(|t| !temp_close(t, temp)) { - res.push(LampProperty::ColorTempK(temp)); + if let Some(temp_self) = self.color_temp_k { + if other + .color_temp_k + .is_none_or(|temp_other| !temp_is_close(temp_other, temp_self)) + { + res.push(LampProperty::ColorTempK(temp_self)); } } if model.is_some_and(Model::is_color_lamp) { - if let Some(xy) = self.color_xy { - if other.color_xy.is_none_or(|xy_b| !xy_close(xy_b, xy)) { - res.push(LampProperty::ColorXY(xy)); + if let Some(xy_self) = self.color_xy { + if other + .color_xy + .is_none_or(|xy_other| !xy_is_close(xy_other, xy_self)) + { + res.push(LampProperty::ColorXY(xy_self)); } } } - if let Some(on) = self.on { - if other.on.is_none_or(|on_b| on_b != on) { - res.push(LampProperty::On(on)); + if let Some(on_self) = self.on { + if other.on.is_none_or(|on_other| on_other != on_self) { + res.push(LampProperty::On(on_self)); } } From e292c3d3010ba572ea87c9db9bc829376c7986b3 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 17 Nov 2024 13:50:26 +0100 Subject: [PATCH 414/687] Move lamp items to their own submods --- crates/zigbee-bridge/src/lights/lamp.rs | 202 +----------------- crates/zigbee-bridge/src/lights/lamp/model.rs | 114 ++++++++++ .../zigbee-bridge/src/lights/lamp/property.rs | 79 +++++++ 3 files changed, 202 insertions(+), 193 deletions(-) create mode 100644 crates/zigbee-bridge/src/lights/lamp/model.rs create mode 100644 crates/zigbee-bridge/src/lights/lamp/property.rs diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 0e1c6ae1..40da8819 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -1,10 +1,14 @@ -use std::collections::HashMap; - -use serde_json::json; -use strum::EnumDiscriminants; use tracing::instrument; -use crate::lights::{conversion::temp_to_xy, denormalize, kelvin_to_mired}; +use crate::lights::conversion::temp_to_xy; + +pub(super) use model::Model; +pub(super) use property::{LampProperty, LampPropertyDiscriminants}; + +use property::{bri_is_close, temp_is_close, xy_is_close, ColorTempStartup}; + +mod model; +mod property; #[derive(Debug, Clone)] pub(super) struct LampState { @@ -35,67 +39,6 @@ pub(super) struct Lamp { pub(super) state: LampState, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub(super) enum ColorTempStartup { - Previous, -} - -#[derive(Debug, EnumDiscriminants, Clone, Copy)] -#[strum_discriminants(derive(Hash))] -pub(super) enum LampProperty { - Brightness(f64), - ColorTempK(usize), - ColorXY((f64, f64)), - On(bool), - ColorTempStartup(ColorTempStartup), -} - -impl PartialEq for LampProperty { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (LampProperty::Brightness(a), LampProperty::Brightness(b)) => { - bri_is_close(*a, *b) - } - (LampProperty::ColorTempK(a), LampProperty::ColorTempK(b)) => { - temp_is_close(*a, *b) - } - (LampProperty::ColorXY(a), LampProperty::ColorXY(b)) => { - xy_is_close(*a, *b) - } - (LampProperty::On(a), LampProperty::On(b)) => a == b, - ( - LampProperty::ColorTempStartup(a), - LampProperty::ColorTempStartup(b), - ) => a == b, - (_, _) => false, - } - } -} - -impl Eq for LampProperty {} - -impl LampProperty { - pub(crate) fn payload(&self) -> String { - match *self { - LampProperty::Brightness(bri) => { - json!({ "brightness": denormalize(bri) }) - } - LampProperty::ColorTempK(k) => { - json!({ "color_temp": kelvin_to_mired(k) }) - } - LampProperty::ColorXY((x, y)) => { - json!({ "color": {"x": x, "y": y} }) - } - LampProperty::On(lamp_on) if lamp_on => json!({"state": "ON"}), - LampProperty::On(_) => json!({"state": "OFF"}), - LampProperty::ColorTempStartup(ColorTempStartup::Previous) => { - json!({"color_temp_startup": "previous"}) - } - } - .to_string() - } -} - impl Lamp { pub(super) fn changes_relative_to( &self, @@ -117,20 +60,6 @@ impl Lamp { } } -fn bri_is_close(a: f64, b: f64) -> bool { - (a - b).abs() < 1. / 250. -} - -fn temp_is_close(a: usize, b: usize) -> bool { - a.abs_diff(b) < 50 -} - -fn xy_is_close(a: (f64, f64), b: (f64, f64)) -> bool { - let d_color_x = (a.0 - b.0).abs(); - let d_color_y = (a.1 - b.1).abs(); - d_color_x < 0.01 && d_color_y < 0.01 -} - impl LampState { #[instrument] pub(super) fn changes_relative_to( @@ -271,116 +200,3 @@ pub(super) enum Change { ColorTemp(usize), ColorXy((f64, f64)), } - -#[derive(Debug, Clone, PartialEq, Eq)] -pub(super) enum Model { - TradfriCandle, - TradfriE27, - TradfriE14, - HueGen4, - TradfriOther(String), - HueOther(String), - Other(String), -} - -impl Model { - fn is_color_lamp(&self) -> bool { - #[allow(clippy::match_same_arms)] // clearer comment - match self { - Model::TradfriE27 | Model::TradfriE14 | Model::HueGen4 => true, - Model::TradfriCandle => false, - // We assume no so that things at least don't break - Model::TradfriOther(_) | Model::HueOther(_) | Model::Other(_) => { - false - } - } - } - - fn color_deviation(&self, color_temp: usize) -> (usize, f64) { - match self { - Model::TradfriCandle => todo!(), - Model::TradfriE27 => todo!(), - Model::TradfriE14 => todo!(), - Model::HueGen4 => todo!(), - Model::TradfriOther(_) => todo!(), - Model::HueOther(_) => todo!(), - Model::Other(_) => todo!(), - } - } - - // Value for actual color temp (after temp correction) - fn blackbody_table(&self) -> HashMap { - match self { - // 105.455.00 data - Model::TradfriCandle => vec![ - (2170, 0.0028), - (2391, 0.0018), - (2683, 0.0006), - (2990, 0.0006), - (3193, 0.0012), - (3590, 0.003), - (3791, 0.0036), - (3951, 0.0046), - ], - // 604.391.68 data - Model::TradfriE27 => vec![ - (1964, -0.003), - (2090, 0.0014), - (2668, 0.0015), - (3046, 0.001), - (3499, 0.0015), - (3605, -0.0011), - (4098, -0.0017), - (4110, -0.0009), - (4250, 0.0007), - ], - // 204.391.94 data - Model::TradfriE14 => vec![ - (1841, -0.0032), - (2055, -0.0034), - (2120, 0.0012), - (2738, -0.0005), - (3070, 0.0004), - (3467, 0.0045), - (3555, 0.00), - (3981, 0.0009), - (4113, 0.0037), - ], - // A19 Color 9.5W data - Model::HueGen4 | Model::HueOther(_) => vec![ - (1998, 0.0005), - (2197, 0.00000), - (2519, -0.0004), - (2695, -0.0007), - (2849, -0.0011), - (3358, -0.0012), - (3864, -0.012), - (4010, -0.0009), - (5455, -0.0005), - (6495, 0.0014), - ], - Model::TradfriOther(_) => todo!(), - Model::Other(_) => todo!(), - } - .into_iter() - .collect() - } - - // Value to add to requested color temp - fn temp_table(&self) -> HashMap { - match self { - Model::TradfriCandle => { - vec![(2200, 30), (2700, 20), (4000, 50)] - } - Model::TradfriE27 => vec![(2200, 110), (2700, 30), (4000, -110)], - Model::TradfriE14 => vec![(2200, 70), (2700, -40), (4000, 20)], - Model::HueGen4 | Model::HueOther(_) => { - vec![(2200, 2), (2700, 5), (4000, -10), (5500, 45), (6500, 5)] - } - Model::TradfriOther(_) => todo!(), - Model::Other(_) => todo!(), - } - .into_iter() - .collect() - } -} diff --git a/crates/zigbee-bridge/src/lights/lamp/model.rs b/crates/zigbee-bridge/src/lights/lamp/model.rs new file mode 100644 index 00000000..38ccf1ed --- /dev/null +++ b/crates/zigbee-bridge/src/lights/lamp/model.rs @@ -0,0 +1,114 @@ +use std::collections::HashMap; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) enum Model { + TradfriCandle, + TradfriE27, + TradfriE14, + HueGen4, + TradfriOther(String), + HueOther(String), + Other(String), +} + +impl Model { + pub(crate) fn is_color_lamp(&self) -> bool { + #[allow(clippy::match_same_arms)] // clearer comment + match self { + Model::TradfriE27 | Model::TradfriE14 | Model::HueGen4 => true, + Model::TradfriCandle => false, + // We assume no so that things at least don't break + Model::TradfriOther(_) | Model::HueOther(_) | Model::Other(_) => { + false + } + } + } + + pub(crate) fn color_deviation(&self, color_temp: usize) -> (usize, f64) { + match self { + Model::TradfriCandle => todo!(), + Model::TradfriE27 => todo!(), + Model::TradfriE14 => todo!(), + Model::HueGen4 => todo!(), + Model::TradfriOther(_) => todo!(), + Model::HueOther(_) => todo!(), + Model::Other(_) => todo!(), + } + } + + // Value for actual color temp (after temp correction) + pub(crate) fn blackbody_table(&self) -> HashMap { + match self { + // 105.455.00 data + Model::TradfriCandle => vec![ + (2170, 0.0028), + (2391, 0.0018), + (2683, 0.0006), + (2990, 0.0006), + (3193, 0.0012), + (3590, 0.003), + (3791, 0.0036), + (3951, 0.0046), + ], + // 604.391.68 data + Model::TradfriE27 => vec![ + (1964, -0.003), + (2090, 0.0014), + (2668, 0.0015), + (3046, 0.001), + (3499, 0.0015), + (3605, -0.0011), + (4098, -0.0017), + (4110, -0.0009), + (4250, 0.0007), + ], + // 204.391.94 data + Model::TradfriE14 => vec![ + (1841, -0.0032), + (2055, -0.0034), + (2120, 0.0012), + (2738, -0.0005), + (3070, 0.0004), + (3467, 0.0045), + (3555, 0.00), + (3981, 0.0009), + (4113, 0.0037), + ], + // A19 Color 9.5W data + Model::HueGen4 | Model::HueOther(_) => vec![ + (1998, 0.0005), + (2197, 0.00000), + (2519, -0.0004), + (2695, -0.0007), + (2849, -0.0011), + (3358, -0.0012), + (3864, -0.012), + (4010, -0.0009), + (5455, -0.0005), + (6495, 0.0014), + ], + Model::TradfriOther(_) => todo!(), + Model::Other(_) => todo!(), + } + .into_iter() + .collect() + } + + // Value to add to requested color temp + pub(crate) fn temp_table(&self) -> HashMap { + match self { + Model::TradfriCandle => { + vec![(2200, 30), (2700, 20), (4000, 50)] + } + Model::TradfriE27 => vec![(2200, 110), (2700, 30), (4000, -110)], + Model::TradfriE14 => vec![(2200, 70), (2700, -40), (4000, 20)], + Model::HueGen4 | Model::HueOther(_) => { + vec![(2200, 2), (2700, 5), (4000, -10), (5500, 45), (6500, 5)] + } + Model::TradfriOther(_) => todo!(), + Model::Other(_) => todo!(), + } + .into_iter() + .collect() + } +} diff --git a/crates/zigbee-bridge/src/lights/lamp/property.rs b/crates/zigbee-bridge/src/lights/lamp/property.rs new file mode 100644 index 00000000..1e8f25c2 --- /dev/null +++ b/crates/zigbee-bridge/src/lights/lamp/property.rs @@ -0,0 +1,79 @@ +use serde_json::json; +use strum::EnumDiscriminants; + +use crate::lights::{denormalize, kelvin_to_mired}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(crate) enum ColorTempStartup { + Previous, +} + +#[derive(Debug, EnumDiscriminants, Clone, Copy)] +#[strum_discriminants(derive(Hash))] +pub(crate) enum LampProperty { + Brightness(f64), + ColorTempK(usize), + ColorXY((f64, f64)), + On(bool), + ColorTempStartup(ColorTempStartup), +} + +impl PartialEq for LampProperty { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (LampProperty::Brightness(a), LampProperty::Brightness(b)) => { + bri_is_close(*a, *b) + } + (LampProperty::ColorTempK(a), LampProperty::ColorTempK(b)) => { + temp_is_close(*a, *b) + } + (LampProperty::ColorXY(a), LampProperty::ColorXY(b)) => { + xy_is_close(*a, *b) + } + (LampProperty::On(a), LampProperty::On(b)) => a == b, + ( + LampProperty::ColorTempStartup(a), + LampProperty::ColorTempStartup(b), + ) => a == b, + (_, _) => false, + } + } +} + +impl Eq for LampProperty {} + +impl LampProperty { + pub(crate) fn payload(&self) -> String { + match *self { + LampProperty::Brightness(bri) => { + json!({ "brightness": denormalize(bri) }) + } + LampProperty::ColorTempK(k) => { + json!({ "color_temp": kelvin_to_mired(k) }) + } + LampProperty::ColorXY((x, y)) => { + json!({ "color": {"x": x, "y": y} }) + } + LampProperty::On(lamp_on) if lamp_on => json!({"state": "ON"}), + LampProperty::On(_) => json!({"state": "OFF"}), + LampProperty::ColorTempStartup(ColorTempStartup::Previous) => { + json!({"color_temp_startup": "previous"}) + } + } + .to_string() + } +} + +pub(super) fn bri_is_close(a: f64, b: f64) -> bool { + (a - b).abs() < 1. / 250. +} + +pub(super) fn temp_is_close(a: usize, b: usize) -> bool { + a.abs_diff(b) < 50 +} + +pub(super) fn xy_is_close(a: (f64, f64), b: (f64, f64)) -> bool { + let d_color_x = (a.0 - b.0).abs(); + let d_color_y = (a.1 - b.1).abs(); + d_color_x < 0.01 && d_color_y < 0.01 +} From d259fe257a13a5c3c904040a1f23cdff7e9326a8 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 17 Nov 2024 14:00:14 +0100 Subject: [PATCH 415/687] Move LampState to its own mod Not sure about this --- crates/zigbee-bridge/src/lights/lamp.rs | 128 ++---------------- crates/zigbee-bridge/src/lights/lamp/state.rs | 115 ++++++++++++++++ 2 files changed, 123 insertions(+), 120 deletions(-) create mode 100644 crates/zigbee-bridge/src/lights/lamp/state.rs diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 40da8819..8c3f4d64 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -1,42 +1,22 @@ -use tracing::instrument; - -use crate::lights::conversion::temp_to_xy; - pub(super) use model::Model; pub(super) use property::{LampProperty, LampPropertyDiscriminants}; -use property::{bri_is_close, temp_is_close, xy_is_close, ColorTempStartup}; - mod model; mod property; +mod state; -#[derive(Debug, Clone)] -pub(super) struct LampState { - pub(super) brightness: Option, - pub(super) color_temp_k: Option, - pub(super) color_xy: Option<(f64, f64)>, - pub(super) on: Option, - pub(super) color_temp_startup: ColorTempStartup, -} - -impl Default for LampState { - fn default() -> Self { - Self { - brightness: None, - color_temp_k: None, - color_xy: None, - on: None, - // Settings, will not be updated from MQTT state message - // and will never trigger a publish - color_temp_startup: ColorTempStartup::Previous, - } - } +#[derive(Debug, Clone, Copy)] +pub(super) enum Change { + On(bool), + Brightness(f64), + ColorTemp(usize), + ColorXy((f64, f64)), } #[derive(Default, Clone, Debug)] pub(super) struct Lamp { pub(super) model: Option, - pub(super) state: LampState, + pub(super) state: state::LampState, } impl Lamp { @@ -60,90 +40,6 @@ impl Lamp { } } -impl LampState { - #[instrument] - pub(super) fn changes_relative_to( - &self, - other: &Self, - model: Option<&Model>, - ) -> Vec { - let mut res = Vec::new(); - if let Some(bri_self) = self.brightness { - if other - .brightness - .is_none_or(|bri_other| !bri_is_close(bri_other, bri_self)) - { - res.push(LampProperty::Brightness(bri_self)); - } - } - - if let Some(temp_self) = self.color_temp_k { - if other - .color_temp_k - .is_none_or(|temp_other| !temp_is_close(temp_other, temp_self)) - { - res.push(LampProperty::ColorTempK(temp_self)); - } - } - - if model.is_some_and(Model::is_color_lamp) { - if let Some(xy_self) = self.color_xy { - if other - .color_xy - .is_none_or(|xy_other| !xy_is_close(xy_other, xy_self)) - { - res.push(LampProperty::ColorXY(xy_self)); - } - } - } - - if let Some(on_self) = self.on { - if other.on.is_none_or(|on_other| on_other != on_self) { - res.push(LampProperty::On(on_self)); - } - } - - if self.color_temp_startup != other.color_temp_startup { - res.push(LampProperty::ColorTempStartup(self.color_temp_startup)); - } - - res - } - - fn apply(self, change: Change) -> LampState { - let mut new_state = self.clone(); - match change { - Change::On(on) => new_state.on = Some(on), - Change::Brightness(bri) => new_state.brightness = Some(bri), - Change::ColorTemp(temp) => { - new_state.color_temp_k = Some(temp); - new_state.color_xy = Some(temp_to_xy(temp)); - } - Change::ColorXy(xy) => new_state.color_xy = Some(xy), - } - new_state - } - - fn property_list(&self) -> Vec { - // we do not send color xy as the lamp might not support it - // if it does then property_list is never called but an exact - // diff between the current and need state is send - - let mut list = Vec::new(); - if let Some(val) = self.brightness { - list.push(LampProperty::Brightness(val)); - } - if let Some(val) = self.color_temp_k { - list.push(LampProperty::ColorTempK(val)); - } - if let Some(val) = self.on { - list.push(LampProperty::On(val)); - } - list.push(LampProperty::ColorTempStartup(self.color_temp_startup)); - list - } -} - impl PartialEq for Lamp { fn eq(&self, other: &Self) -> bool { let color_is_equal = if let (Some(self_model), Some(other_model)) = @@ -192,11 +88,3 @@ impl PartialEq for Lamp { } impl Eq for Lamp {} - -#[derive(Debug, Clone, Copy)] -pub(super) enum Change { - On(bool), - Brightness(f64), - ColorTemp(usize), - ColorXy((f64, f64)), -} diff --git a/crates/zigbee-bridge/src/lights/lamp/state.rs b/crates/zigbee-bridge/src/lights/lamp/state.rs new file mode 100644 index 00000000..8d4cdb20 --- /dev/null +++ b/crates/zigbee-bridge/src/lights/lamp/state.rs @@ -0,0 +1,115 @@ +use tracing::instrument; + +use super::property::{ + bri_is_close, temp_is_close, xy_is_close, ColorTempStartup, LampProperty, +}; +use super::Change; +use super::Model; +use crate::lights::conversion::temp_to_xy; + +#[derive(Debug, Clone)] +pub(crate) struct LampState { + pub(crate) brightness: Option, + pub(crate) color_temp_k: Option, + pub(crate) color_xy: Option<(f64, f64)>, + pub(crate) on: Option, + pub(crate) color_temp_startup: ColorTempStartup, +} + +impl Default for LampState { + fn default() -> Self { + Self { + brightness: None, + color_temp_k: None, + color_xy: None, + on: None, + // Settings, will not be updated from MQTT state message + // and will never trigger a publish + color_temp_startup: ColorTempStartup::Previous, + } + } +} + +impl LampState { + #[instrument] + pub(super) fn changes_relative_to( + &self, + other: &Self, + model: Option<&Model>, + ) -> Vec { + let mut res = Vec::new(); + if let Some(bri_self) = self.brightness { + if other + .brightness + .is_none_or(|bri_other| !bri_is_close(bri_other, bri_self)) + { + res.push(LampProperty::Brightness(bri_self)); + } + } + + if let Some(temp_self) = self.color_temp_k { + if other + .color_temp_k + .is_none_or(|temp_other| !temp_is_close(temp_other, temp_self)) + { + res.push(LampProperty::ColorTempK(temp_self)); + } + } + + if model.is_some_and(Model::is_color_lamp) { + if let Some(xy_self) = self.color_xy { + if other + .color_xy + .is_none_or(|xy_other| !xy_is_close(xy_other, xy_self)) + { + res.push(LampProperty::ColorXY(xy_self)); + } + } + } + + if let Some(on_self) = self.on { + if other.on.is_none_or(|on_other| on_other != on_self) { + res.push(LampProperty::On(on_self)); + } + } + + if self.color_temp_startup != other.color_temp_startup { + res.push(LampProperty::ColorTempStartup(self.color_temp_startup)); + } + + res + } + + pub(crate) fn apply(self, change: Change) -> LampState { + let mut new_state = self.clone(); + match change { + Change::On(on) => new_state.on = Some(on), + Change::Brightness(bri) => new_state.brightness = Some(bri), + Change::ColorTemp(temp) => { + new_state.color_temp_k = Some(temp); + new_state.color_xy = Some(temp_to_xy(temp)); + } + Change::ColorXy(xy) => new_state.color_xy = Some(xy), + } + new_state + } + + pub(crate) fn property_list(&self) -> Vec { + // we do not send color xy as the lamp might not support it + // if it does then property_list is never called but an exact + // diff between the current and need state is send + + let mut list = Vec::new(); + if let Some(val) = self.brightness { + list.push(LampProperty::Brightness(val)); + } + if let Some(val) = self.color_temp_k { + list.push(LampProperty::ColorTempK(val)); + } + if let Some(val) = self.on { + list.push(LampProperty::On(val)); + } + list.push(LampProperty::ColorTempStartup(self.color_temp_startup)); + list + } +} From 3e02a09c2326c0385d7a65bec1a3ea5aedc70690 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 17 Nov 2024 14:09:11 +0100 Subject: [PATCH 416/687] Restrict LampState to lamp mod --- .../src/lights/cached_bridge/poll.rs | 28 ++++++------------- crates/zigbee-bridge/src/lights/lamp.rs | 17 ++++++++++- crates/zigbee-bridge/src/lights/lamp/state.rs | 12 ++++---- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index e8a00ee9..7f9e1c1f 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -71,28 +71,18 @@ async fn update_state( new: Vec, ) { let mut known_states = known_states.write().await; - let curr = &mut known_states - .entry(light_name.to_string()) - .or_default() - .state; + let current_lamp = + &mut known_states.entry(light_name.to_string()).or_default(); for property in new { - match property { - LampProperty::Brightness(bri) => curr.brightness = Some(bri), - LampProperty::ColorTempK(temp) => { - if light_name == "kitchen:fridge" { - warn!( - "ZB received fridge color temp change: {}", - kelvin_to_mired(temp) - ); - } - curr.color_temp_k = Some(temp) - } - LampProperty::ColorXY(xy) => curr.color_xy = Some(xy), - LampProperty::On(is_on) => curr.on = Some(is_on), - LampProperty::ColorTempStartup(behavior) => { - curr.color_temp_startup = behavior + if let LampProperty::ColorTempK(temp) = property { + if light_name == "kitchen:fridge" { + warn!( + "ZB received fridge color temp change: {}", + kelvin_to_mired(temp) + ); } } + current_lamp.change_state(property); } } diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 8c3f4d64..3df0b1a6 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -1,6 +1,8 @@ pub(super) use model::Model; pub(super) use property::{LampProperty, LampPropertyDiscriminants}; +use state::LampState; + mod model; mod property; mod state; @@ -16,7 +18,7 @@ pub(super) enum Change { #[derive(Default, Clone, Debug)] pub(super) struct Lamp { pub(super) model: Option, - pub(super) state: state::LampState, + state: LampState, } impl Lamp { @@ -38,6 +40,19 @@ impl Lamp { pub(crate) fn property_list(&self) -> Vec { self.state.property_list() } + + pub(crate) fn change_state(&mut self, property: LampProperty) { + let state = &mut self.state; + match property { + LampProperty::Brightness(bri) => state.brightness = Some(bri), + LampProperty::ColorTempK(temp) => state.color_temp_k = Some(temp), + LampProperty::ColorXY(xy) => state.color_xy = Some(xy), + LampProperty::On(is_on) => state.on = Some(is_on), + LampProperty::ColorTempStartup(behavior) => { + state.color_temp_startup = behavior + } + } + } } impl PartialEq for Lamp { diff --git a/crates/zigbee-bridge/src/lights/lamp/state.rs b/crates/zigbee-bridge/src/lights/lamp/state.rs index 8d4cdb20..f1de9708 100644 --- a/crates/zigbee-bridge/src/lights/lamp/state.rs +++ b/crates/zigbee-bridge/src/lights/lamp/state.rs @@ -8,12 +8,12 @@ use super::Model; use crate::lights::conversion::temp_to_xy; #[derive(Debug, Clone)] -pub(crate) struct LampState { - pub(crate) brightness: Option, - pub(crate) color_temp_k: Option, - pub(crate) color_xy: Option<(f64, f64)>, - pub(crate) on: Option, - pub(crate) color_temp_startup: ColorTempStartup, +pub(super) struct LampState { + pub(super) brightness: Option, + pub(super) color_temp_k: Option, + pub(super) color_xy: Option<(f64, f64)>, + pub(super) on: Option, + pub(super) color_temp_startup: ColorTempStartup, } impl Default for LampState { From ebff315ec6841fa94adf305a629bec1269537c78 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 17 Nov 2024 14:16:33 +0100 Subject: [PATCH 417/687] Add setter for lamp model for consistency --- crates/zigbee-bridge/src/lights/cached_bridge/poll.rs | 9 ++++----- crates/zigbee-bridge/src/lights/lamp.rs | 6 +++++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 7f9e1c1f..40e3edf2 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -58,11 +58,10 @@ async fn update_model( model: Model, ) { let mut known_states = known_states.write().await; - let curr_model = &mut known_states + let current_lamp = &mut known_states .entry(light_name.to_string()) - .or_default() - .model; - *curr_model = Some(model); + .or_default(); + current_lamp.set_model(model); } async fn update_state( @@ -72,7 +71,7 @@ async fn update_state( ) { let mut known_states = known_states.write().await; let current_lamp = - &mut known_states.entry(light_name.to_string()).or_default(); + known_states.entry(light_name.to_string()).or_default(); for property in new { if let LampProperty::ColorTempK(temp) = property { if light_name == "kitchen:fridge" { diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 3df0b1a6..29dab38f 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -17,7 +17,7 @@ pub(super) enum Change { #[derive(Default, Clone, Debug)] pub(super) struct Lamp { - pub(super) model: Option, + model: Option, state: LampState, } @@ -53,6 +53,10 @@ impl Lamp { } } } + + pub(crate) fn set_model(&mut self, model: Model) { + self.model = Some(model); + } } impl PartialEq for Lamp { From 4ecf06816d75fd7760fc9b6d7dc7ca52701d3946 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 17 Nov 2024 14:18:55 +0100 Subject: [PATCH 418/687] Make model fns least pub and remove unused warnings --- crates/zigbee-bridge/src/lights/lamp/model.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/lamp/model.rs b/crates/zigbee-bridge/src/lights/lamp/model.rs index 38ccf1ed..4d8c7458 100644 --- a/crates/zigbee-bridge/src/lights/lamp/model.rs +++ b/crates/zigbee-bridge/src/lights/lamp/model.rs @@ -7,12 +7,13 @@ pub(crate) enum Model { TradfriE14, HueGen4, TradfriOther(String), + #[allow(unused)] HueOther(String), Other(String), } impl Model { - pub(crate) fn is_color_lamp(&self) -> bool { + pub(super) fn is_color_lamp(&self) -> bool { #[allow(clippy::match_same_arms)] // clearer comment match self { Model::TradfriE27 | Model::TradfriE14 | Model::HueGen4 => true, @@ -24,7 +25,8 @@ impl Model { } } - pub(crate) fn color_deviation(&self, color_temp: usize) -> (usize, f64) { + #[allow(unused)] + pub(super) fn color_deviation(&self, color_temp: usize) -> (usize, f64) { match self { Model::TradfriCandle => todo!(), Model::TradfriE27 => todo!(), @@ -36,8 +38,9 @@ impl Model { } } + #[allow(unused)] // Value for actual color temp (after temp correction) - pub(crate) fn blackbody_table(&self) -> HashMap { + fn blackbody_table(&self) -> HashMap { match self { // 105.455.00 data Model::TradfriCandle => vec![ @@ -94,8 +97,9 @@ impl Model { .collect() } + #[allow(unused)] // Value to add to requested color temp - pub(crate) fn temp_table(&self) -> HashMap { + fn temp_table(&self) -> HashMap { match self { Model::TradfriCandle => { vec![(2200, 30), (2700, 20), (4000, 50)] From bbebc353ad61f45bd3d0c33588c1e1e180eb42bf Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 17 Nov 2024 14:25:27 +0100 Subject: [PATCH 419/687] Fix clippy pedantic lints --- crates/zigbee-bridge/src/lights/cached_bridge/poll.rs | 7 ++----- crates/zigbee-bridge/src/lights/lamp.rs | 2 +- crates/zigbee-bridge/src/lights/parse_state.rs | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 40e3edf2..c6bf97fc 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -58,9 +58,7 @@ async fn update_model( model: Model, ) { let mut known_states = known_states.write().await; - let current_lamp = &mut known_states - .entry(light_name.to_string()) - .or_default(); + let current_lamp = known_states.entry(light_name.to_string()).or_default(); current_lamp.set_model(model); } @@ -70,8 +68,7 @@ async fn update_state( new: Vec, ) { let mut known_states = known_states.write().await; - let current_lamp = - known_states.entry(light_name.to_string()).or_default(); + let current_lamp = known_states.entry(light_name.to_string()).or_default(); for property in new { if let LampProperty::ColorTempK(temp) = property { if light_name == "kitchen:fridge" { diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 29dab38f..8add546b 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -49,7 +49,7 @@ impl Lamp { LampProperty::ColorXY(xy) => state.color_xy = Some(xy), LampProperty::On(is_on) => state.on = Some(is_on), LampProperty::ColorTempStartup(behavior) => { - state.color_temp_startup = behavior + state.color_temp_startup = behavior; } } } diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs index 600245b1..0d8aedec 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -65,7 +65,7 @@ pub(super) fn parse_lamp_properties( }) .transpose()? { - list.push(LampProperty::On(on)) + list.push(LampProperty::On(on)); } // TODO: startup behavior? <14-11-24, dvdsk> From 1aeadaca2d463d5b0a8e07d35ea45d5cdd8c63cd Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 17 Nov 2024 14:32:07 +0100 Subject: [PATCH 420/687] Prefix all lamp items with mod name for consistency --- crates/zigbee-bridge/src/lights.rs | 12 +++---- .../zigbee-bridge/src/lights/cached_bridge.rs | 6 ++-- .../src/lights/cached_bridge/changes.rs | 6 ++-- .../src/lights/cached_bridge/mqtt.rs | 6 ++-- .../src/lights/cached_bridge/poll.rs | 30 ++++++++--------- crates/zigbee-bridge/src/lights/lamp.rs | 18 +++++------ .../zigbee-bridge/src/lights/lamp/property.rs | 32 +++++++++---------- crates/zigbee-bridge/src/lights/lamp/state.rs | 24 +++++++------- .../zigbee-bridge/src/lights/parse_state.rs | 12 +++---- 9 files changed, 72 insertions(+), 74 deletions(-) diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index 7ae5a954..455b3022 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -2,8 +2,6 @@ use tokio::sync::mpsc; use tracing::trace; -use self::lamp::Change; - // TODO: make private once system is ported pub use conversion::{ denormalize, kelvin_to_mired, mired_to_kelvin, normalize, @@ -33,32 +31,32 @@ impl Controller { pub fn set_on(&self, friendly_name: &str) { self.change_sender - .send((friendly_name.to_string(), Change::On(true))) + .send((friendly_name.to_string(), lamp::Change::On(true))) .expect("Sender should never be dropped"); } pub fn set_off(&self, friendly_name: &str) { self.change_sender - .send((friendly_name.to_string(), Change::On(false))) + .send((friendly_name.to_string(), lamp::Change::On(false))) .expect("Sender should never be dropped"); } /// Brightness from 0 to 1 pub fn set_brightness(&self, friendly_name: &str, brightness: f64) { self.change_sender - .send((friendly_name.to_string(), Change::Brightness(brightness))) + .send((friendly_name.to_string(), lamp::Change::Brightness(brightness))) .expect("Sender should never be dropped"); } pub fn set_color_temp(&self, friendly_name: &str, kelvin: usize) { self.change_sender - .send((friendly_name.to_string(), Change::ColorTemp(kelvin))) + .send((friendly_name.to_string(), lamp::Change::ColorTemp(kelvin))) .expect("Sender should never be dropped"); } pub fn set_color_xy(&self, friendly_name: &str, xy: (f64, f64)) { self.change_sender - .send((friendly_name.to_string(), Change::ColorXy(xy))) + .send((friendly_name.to_string(), lamp::Change::ColorXy(xy))) .expect("Sender should never be dropped"); } } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index be54c42e..ce42fc37 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -5,15 +5,15 @@ use tokio::sync::{mpsc, RwLock}; use tracing::trace; use self::mqtt::Mqtt; -use crate::lights::lamp::Change; -use crate::{LIGHTS, MQTT_IP, MQTT_PORT}; +use crate::{lights::lamp, LIGHTS, MQTT_IP, MQTT_PORT}; + mod changes; mod mqtt; mod poll; pub(super) async fn run( - change_receiver: mpsc::UnboundedReceiver<(String, Change)>, + change_receiver: mpsc::UnboundedReceiver<(String, lamp::Change)>, ) -> ! { let mut options = MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index 25bc298c..4dd8cbc5 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -6,11 +6,11 @@ use tokio::time::{sleep, timeout}; use tracing::{debug, instrument, trace}; use super::mqtt::Mqtt; -use crate::lights::lamp::{Change, Lamp}; +use crate::lights::lamp::{self, Lamp}; use crate::LIGHTS; pub(super) async fn handle( - mut change_receiver: mpsc::UnboundedReceiver<(String, Change)>, + mut change_receiver: mpsc::UnboundedReceiver<(String, lamp::Change)>, mqtt: &mut Mqtt, known_states: &RwLock>, ) -> ! { @@ -81,7 +81,7 @@ async fn send_and_queue( #[instrument(skip_all)] async fn apply_change( light_name: String, - change: Change, + change: lamp::Change, known_states: &RwLock>, needed_states: &mut HashMap, ) { diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index e17c885b..43327138 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -6,13 +6,13 @@ use rumqttc::v5::{AsyncClient, ClientError}; use serde_json::json; use tracing::{instrument, trace, warn}; -use crate::lights::lamp::{LampProperty, LampPropertyDiscriminants}; +use crate::lights::lamp; pub(super) struct Mqtt { client: AsyncClient, property_last_set: HashMap< String, - HashMap, + HashMap, >, } @@ -45,7 +45,7 @@ impl Mqtt { pub(super) async fn try_send_state_diff( &mut self, light_name: String, - diff: Vec, + diff: Vec, ) -> Result { const TIME_IT_TAKES_TO_APPLY_CHANGE: Duration = Duration::from_secs(1); let mut new_call_needed_in: Duration = Duration::MAX; diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index c6bf97fc..4af1990a 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -10,7 +10,7 @@ use tokio::{sync::RwLock, time::sleep}; use tracing::{instrument, trace, warn}; use crate::lights::kelvin_to_mired; -use crate::lights::lamp::{Lamp, LampProperty, Model}; +use crate::lights::lamp::{self, Lamp}; use crate::lights::parse_state::parse_lamp_properties; pub(super) async fn poll_mqtt( @@ -55,7 +55,7 @@ pub(super) async fn poll_mqtt( async fn update_model( known_states: &RwLock>, light_name: String, - model: Model, + model: lamp::Model, ) { let mut known_states = known_states.write().await; let current_lamp = known_states.entry(light_name.to_string()).or_default(); @@ -65,12 +65,12 @@ async fn update_model( async fn update_state( known_states: &RwLock>, light_name: String, - new: Vec, + new: Vec, ) { let mut known_states = known_states.write().await; let current_lamp = known_states.entry(light_name.to_string()).or_default(); for property in new { - if let LampProperty::ColorTempK(temp) = property { + if let lamp::Property::ColorTempK(temp) = property { if light_name == "kitchen:fridge" { warn!( "ZB received fridge color temp change: {}", @@ -102,7 +102,7 @@ fn parse_message(event: Event) -> color_eyre::Result { .as_array() .ok_or_eyre("devices list should be array its not") .with_note(|| format!("json was: {json:?}"))?; - let devices: HashMap = list + let devices: HashMap = list .iter() .map(|dev| { parse_device(dev) @@ -125,13 +125,13 @@ fn parse_message(event: Event) -> color_eyre::Result { #[derive(Debug)] enum Message { - StateUpdate((String, Vec)), - Devices(HashMap), + StateUpdate((String, Vec)), + Devices(HashMap), Other, } #[instrument(skip_all)] -fn parse_device(device: &Value) -> color_eyre::Result<(String, Model)> { +fn parse_device(device: &Value) -> color_eyre::Result<(String, lamp::Model)> { let properties = device .as_object() .wrap_err("device should be json object")?; @@ -149,15 +149,15 @@ fn parse_device(device: &Value) -> color_eyre::Result<(String, Model)> { .transpose()?; let model = match model_id { - Some("TRADFRI bulb E14 WS candle 470lm") => Model::TradfriCandle, - Some("TRADFRI bulb E27 CWS globe 806lm") => Model::TradfriE27, - Some("TRADFRI bulb E14 CWS globe 806lm") => Model::TradfriE14, - Some("LCT001") => Model::HueGen4, + Some("TRADFRI bulb E14 WS candle 470lm") => lamp::Model::TradfriCandle, + Some("TRADFRI bulb E27 CWS globe 806lm") => lamp::Model::TradfriE27, + Some("TRADFRI bulb E14 CWS globe 806lm") => lamp::Model::TradfriE14, + Some("LCT001") => lamp::Model::HueGen4, Some(id) if id.to_lowercase().contains("tradfri") => { - Model::TradfriOther(id.to_owned()) + lamp::Model::TradfriOther(id.to_owned()) } - Some(id) => Model::Other(id.to_owned()), - None => Model::Other(String::new()), + Some(id) => lamp::Model::Other(id.to_owned()), + None => lamp::Model::Other(String::new()), }; Ok((friendly_name, model)) diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 8add546b..af2aeaf3 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -1,5 +1,5 @@ pub(super) use model::Model; -pub(super) use property::{LampProperty, LampPropertyDiscriminants}; +pub(super) use property::{Property, PropertyDiscriminants}; use state::LampState; @@ -25,7 +25,7 @@ impl Lamp { pub(super) fn changes_relative_to( &self, other: &Self, - ) -> Vec { + ) -> Vec { self.state .changes_relative_to(&other.state, self.model.as_ref()) } @@ -37,18 +37,18 @@ impl Lamp { } } - pub(crate) fn property_list(&self) -> Vec { + pub(crate) fn property_list(&self) -> Vec { self.state.property_list() } - pub(crate) fn change_state(&mut self, property: LampProperty) { + pub(crate) fn change_state(&mut self, property: Property) { let state = &mut self.state; match property { - LampProperty::Brightness(bri) => state.brightness = Some(bri), - LampProperty::ColorTempK(temp) => state.color_temp_k = Some(temp), - LampProperty::ColorXY(xy) => state.color_xy = Some(xy), - LampProperty::On(is_on) => state.on = Some(is_on), - LampProperty::ColorTempStartup(behavior) => { + Property::Brightness(bri) => state.brightness = Some(bri), + Property::ColorTempK(temp) => state.color_temp_k = Some(temp), + Property::ColorXY(xy) => state.color_xy = Some(xy), + Property::On(is_on) => state.on = Some(is_on), + Property::ColorTempStartup(behavior) => { state.color_temp_startup = behavior; } } diff --git a/crates/zigbee-bridge/src/lights/lamp/property.rs b/crates/zigbee-bridge/src/lights/lamp/property.rs index 1e8f25c2..01acbc6c 100644 --- a/crates/zigbee-bridge/src/lights/lamp/property.rs +++ b/crates/zigbee-bridge/src/lights/lamp/property.rs @@ -10,7 +10,7 @@ pub(crate) enum ColorTempStartup { #[derive(Debug, EnumDiscriminants, Clone, Copy)] #[strum_discriminants(derive(Hash))] -pub(crate) enum LampProperty { +pub(crate) enum Property { Brightness(f64), ColorTempK(usize), ColorXY((f64, f64)), @@ -18,45 +18,45 @@ pub(crate) enum LampProperty { ColorTempStartup(ColorTempStartup), } -impl PartialEq for LampProperty { +impl PartialEq for Property { fn eq(&self, other: &Self) -> bool { match (self, other) { - (LampProperty::Brightness(a), LampProperty::Brightness(b)) => { + (Property::Brightness(a), Property::Brightness(b)) => { bri_is_close(*a, *b) } - (LampProperty::ColorTempK(a), LampProperty::ColorTempK(b)) => { + (Property::ColorTempK(a), Property::ColorTempK(b)) => { temp_is_close(*a, *b) } - (LampProperty::ColorXY(a), LampProperty::ColorXY(b)) => { + (Property::ColorXY(a), Property::ColorXY(b)) => { xy_is_close(*a, *b) } - (LampProperty::On(a), LampProperty::On(b)) => a == b, + (Property::On(a), Property::On(b)) => a == b, ( - LampProperty::ColorTempStartup(a), - LampProperty::ColorTempStartup(b), + Property::ColorTempStartup(a), + Property::ColorTempStartup(b), ) => a == b, (_, _) => false, } } } -impl Eq for LampProperty {} +impl Eq for Property {} -impl LampProperty { +impl Property { pub(crate) fn payload(&self) -> String { match *self { - LampProperty::Brightness(bri) => { + Property::Brightness(bri) => { json!({ "brightness": denormalize(bri) }) } - LampProperty::ColorTempK(k) => { + Property::ColorTempK(k) => { json!({ "color_temp": kelvin_to_mired(k) }) } - LampProperty::ColorXY((x, y)) => { + Property::ColorXY((x, y)) => { json!({ "color": {"x": x, "y": y} }) } - LampProperty::On(lamp_on) if lamp_on => json!({"state": "ON"}), - LampProperty::On(_) => json!({"state": "OFF"}), - LampProperty::ColorTempStartup(ColorTempStartup::Previous) => { + Property::On(lamp_on) if lamp_on => json!({"state": "ON"}), + Property::On(_) => json!({"state": "OFF"}), + Property::ColorTempStartup(ColorTempStartup::Previous) => { json!({"color_temp_startup": "previous"}) } } diff --git a/crates/zigbee-bridge/src/lights/lamp/state.rs b/crates/zigbee-bridge/src/lights/lamp/state.rs index f1de9708..60e64a54 100644 --- a/crates/zigbee-bridge/src/lights/lamp/state.rs +++ b/crates/zigbee-bridge/src/lights/lamp/state.rs @@ -1,7 +1,7 @@ use tracing::instrument; use super::property::{ - bri_is_close, temp_is_close, xy_is_close, ColorTempStartup, LampProperty, + bri_is_close, temp_is_close, xy_is_close, ColorTempStartup, Property, }; use super::Change; use super::Model; @@ -36,14 +36,14 @@ impl LampState { &self, other: &Self, model: Option<&Model>, - ) -> Vec { + ) -> Vec { let mut res = Vec::new(); if let Some(bri_self) = self.brightness { if other .brightness .is_none_or(|bri_other| !bri_is_close(bri_other, bri_self)) { - res.push(LampProperty::Brightness(bri_self)); + res.push(Property::Brightness(bri_self)); } } @@ -52,7 +52,7 @@ impl LampState { .color_temp_k .is_none_or(|temp_other| !temp_is_close(temp_other, temp_self)) { - res.push(LampProperty::ColorTempK(temp_self)); + res.push(Property::ColorTempK(temp_self)); } } @@ -62,19 +62,19 @@ impl LampState { .color_xy .is_none_or(|xy_other| !xy_is_close(xy_other, xy_self)) { - res.push(LampProperty::ColorXY(xy_self)); + res.push(Property::ColorXY(xy_self)); } } } if let Some(on_self) = self.on { if other.on.is_none_or(|on_other| on_other != on_self) { - res.push(LampProperty::On(on_self)); + res.push(Property::On(on_self)); } } if self.color_temp_startup != other.color_temp_startup { - res.push(LampProperty::ColorTempStartup(self.color_temp_startup)); + res.push(Property::ColorTempStartup(self.color_temp_startup)); } res @@ -94,22 +94,22 @@ impl LampState { new_state } - pub(crate) fn property_list(&self) -> Vec { + pub(crate) fn property_list(&self) -> Vec { // we do not send color xy as the lamp might not support it // if it does then property_list is never called but an exact // diff between the current and need state is send let mut list = Vec::new(); if let Some(val) = self.brightness { - list.push(LampProperty::Brightness(val)); + list.push(Property::Brightness(val)); } if let Some(val) = self.color_temp_k { - list.push(LampProperty::ColorTempK(val)); + list.push(Property::ColorTempK(val)); } if let Some(val) = self.on { - list.push(LampProperty::On(val)); + list.push(Property::On(val)); } - list.push(LampProperty::ColorTempStartup(self.color_temp_startup)); + list.push(Property::ColorTempStartup(self.color_temp_startup)); list } } diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs index 0d8aedec..02d49472 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -4,11 +4,11 @@ use serde_json::Value; use crate::lights::{mired_to_kelvin, normalize}; -use super::lamp::LampProperty; +use super::lamp; pub(super) fn parse_lamp_properties( bytes: &[u8], -) -> color_eyre::Result> { +) -> color_eyre::Result> { let mut list = Vec::new(); let json: Value = @@ -23,7 +23,7 @@ pub(super) fn parse_lamp_properties( .transpose()? .map(mired_to_kelvin) { - list.push(LampProperty::ColorTempK(kelvin)); + list.push(lamp::Property::ColorTempK(kelvin)); } if let Some(xy) = map @@ -40,7 +40,7 @@ pub(super) fn parse_lamp_properties( }) .transpose()? { - list.push(LampProperty::ColorXY(xy)); + list.push(lamp::Property::ColorXY(xy)); } if let Some(brightness) = map @@ -49,7 +49,7 @@ pub(super) fn parse_lamp_properties( .transpose()? .map(normalize) { - list.push(LampProperty::Brightness(brightness)); + list.push(lamp::Property::Brightness(brightness)); } if let Some(on) = map @@ -65,7 +65,7 @@ pub(super) fn parse_lamp_properties( }) .transpose()? { - list.push(LampProperty::On(on)); + list.push(lamp::Property::On(on)); } // TODO: startup behavior? <14-11-24, dvdsk> From fe74f013e7f0129d7237090b9940af7bc07817b4 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 19 Nov 2024 13:53:37 +0100 Subject: [PATCH 421/687] Inline LampState struct in Lamp struct --- crates/zigbee-bridge/src/lights/lamp.rs | 111 +++++++++++++---- .../zigbee-bridge/src/lights/lamp/property.rs | 3 +- crates/zigbee-bridge/src/lights/lamp/state.rs | 115 ------------------ 3 files changed, 89 insertions(+), 140 deletions(-) delete mode 100644 crates/zigbee-bridge/src/lights/lamp/state.rs diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index af2aeaf3..47bf13d6 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -1,11 +1,13 @@ pub(super) use model::Model; pub(super) use property::{Property, PropertyDiscriminants}; -use state::LampState; +use self::property::{bri_is_close, temp_is_close, xy_is_close}; +use tracing::instrument; + +use super::conversion::temp_to_xy; mod model; mod property; -mod state; #[derive(Debug, Clone, Copy)] pub(super) enum Change { @@ -18,38 +20,100 @@ pub(super) enum Change { #[derive(Default, Clone, Debug)] pub(super) struct Lamp { model: Option, - state: LampState, + brightness: Option, + color_temp_k: Option, + color_xy: Option<(f64, f64)>, + on: Option, + color_temp_startup: property::ColorTempStartup, } impl Lamp { - pub(super) fn changes_relative_to( - &self, - other: &Self, - ) -> Vec { - self.state - .changes_relative_to(&other.state, self.model.as_ref()) + #[instrument] + pub(super) fn changes_relative_to(&self, other: &Self) -> Vec { + let mut res = Vec::new(); + if let Some(bri_self) = self.brightness { + if other + .brightness + .is_none_or(|bri_other| !bri_is_close(bri_other, bri_self)) + { + res.push(Property::Brightness(bri_self)); + } + } + + if let Some(temp_self) = self.color_temp_k { + if other + .color_temp_k + .is_none_or(|temp_other| !temp_is_close(temp_other, temp_self)) + { + res.push(Property::ColorTempK(temp_self)); + } + } + + if self.model.as_ref().is_some_and(Model::is_color_lamp) { + if let Some(xy_self) = self.color_xy { + if other + .color_xy + .is_none_or(|xy_other| !xy_is_close(xy_other, xy_self)) + { + res.push(Property::ColorXY(xy_self)); + } + } + } + + if let Some(on_self) = self.on { + if other.on.is_none_or(|on_other| on_other != on_self) { + res.push(Property::On(on_self)); + } + } + + if self.color_temp_startup != other.color_temp_startup { + res.push(Property::ColorTempStartup(self.color_temp_startup)); + } + + res } pub(super) fn apply(self, change: Change) -> Self { - Self { - model: self.model, - state: self.state.apply(change), + let mut new_state = self.clone(); + match change { + Change::On(on) => new_state.on = Some(on), + Change::Brightness(bri) => new_state.brightness = Some(bri), + Change::ColorTemp(temp) => { + new_state.color_temp_k = Some(temp); + new_state.color_xy = Some(temp_to_xy(temp)); + } + Change::ColorXy(xy) => new_state.color_xy = Some(xy), } + new_state } pub(crate) fn property_list(&self) -> Vec { - self.state.property_list() + // we do not send color xy as the lamp might not support it + // if it does then property_list is never called but an exact + // diff between the current and need state is send + + let mut list = Vec::new(); + if let Some(val) = (&self).brightness { + list.push(Property::Brightness(val)); + } + if let Some(val) = (&self).color_temp_k { + list.push(Property::ColorTempK(val)); + } + if let Some(val) = (&self).on { + list.push(Property::On(val)); + } + list.push(Property::ColorTempStartup((&self).color_temp_startup)); + list } pub(crate) fn change_state(&mut self, property: Property) { - let state = &mut self.state; match property { - Property::Brightness(bri) => state.brightness = Some(bri), - Property::ColorTempK(temp) => state.color_temp_k = Some(temp), - Property::ColorXY(xy) => state.color_xy = Some(xy), - Property::On(is_on) => state.on = Some(is_on), + Property::Brightness(bri) => self.brightness = Some(bri), + Property::ColorTempK(temp) => self.color_temp_k = Some(temp), + Property::ColorXY(xy) => self.color_xy = Some(xy), + Property::On(is_on) => self.on = Some(is_on), Property::ColorTempStartup(behavior) => { - state.color_temp_startup = behavior; + self.color_temp_startup = behavior; } } } @@ -70,7 +134,7 @@ impl PartialEq for Lamp { // We only ever set xy for color lamps, // so color temp doesn't say anything if self_model.is_color_lamp() { - match (self.state.color_xy, other.state.color_xy) { + match (self.color_xy, other.color_xy) { (Some(self_xy), Some(other_xy)) => { let d_color_x = (self_xy.0 - other_xy.0).abs(); let d_color_y = (self_xy.1 - other_xy.1).abs(); @@ -81,7 +145,7 @@ impl PartialEq for Lamp { } // We only ever set temp, and xy doesn't exist } else { - match (self.state.color_temp_k, other.state.color_temp_k) { + match (self.color_temp_k, other.color_temp_k) { (Some(self_temp), Some(other_temp)) => { self_temp.abs_diff(other_temp) < 50 } @@ -94,15 +158,14 @@ impl PartialEq for Lamp { false }; - let bri_is_equal = match (self.state.brightness, other.state.brightness) - { + let bri_is_equal = match (self.brightness, other.brightness) { (Some(self_bri), Some(other_bri)) => { (self_bri - other_bri).abs() < 1. / 250. } _ => false, }; - self.state.on == other.state.on && bri_is_equal && color_is_equal + self.on == other.on && bri_is_equal && color_is_equal } } diff --git a/crates/zigbee-bridge/src/lights/lamp/property.rs b/crates/zigbee-bridge/src/lights/lamp/property.rs index 01acbc6c..be762aaf 100644 --- a/crates/zigbee-bridge/src/lights/lamp/property.rs +++ b/crates/zigbee-bridge/src/lights/lamp/property.rs @@ -3,8 +3,9 @@ use strum::EnumDiscriminants; use crate::lights::{denormalize, kelvin_to_mired}; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] pub(crate) enum ColorTempStartup { + #[default] Previous, } diff --git a/crates/zigbee-bridge/src/lights/lamp/state.rs b/crates/zigbee-bridge/src/lights/lamp/state.rs deleted file mode 100644 index 60e64a54..00000000 --- a/crates/zigbee-bridge/src/lights/lamp/state.rs +++ /dev/null @@ -1,115 +0,0 @@ -use tracing::instrument; - -use super::property::{ - bri_is_close, temp_is_close, xy_is_close, ColorTempStartup, Property, -}; -use super::Change; -use super::Model; -use crate::lights::conversion::temp_to_xy; - -#[derive(Debug, Clone)] -pub(super) struct LampState { - pub(super) brightness: Option, - pub(super) color_temp_k: Option, - pub(super) color_xy: Option<(f64, f64)>, - pub(super) on: Option, - pub(super) color_temp_startup: ColorTempStartup, -} - -impl Default for LampState { - fn default() -> Self { - Self { - brightness: None, - color_temp_k: None, - color_xy: None, - on: None, - // Settings, will not be updated from MQTT state message - // and will never trigger a publish - color_temp_startup: ColorTempStartup::Previous, - } - } -} - -impl LampState { - #[instrument] - pub(super) fn changes_relative_to( - &self, - other: &Self, - model: Option<&Model>, - ) -> Vec { - let mut res = Vec::new(); - if let Some(bri_self) = self.brightness { - if other - .brightness - .is_none_or(|bri_other| !bri_is_close(bri_other, bri_self)) - { - res.push(Property::Brightness(bri_self)); - } - } - - if let Some(temp_self) = self.color_temp_k { - if other - .color_temp_k - .is_none_or(|temp_other| !temp_is_close(temp_other, temp_self)) - { - res.push(Property::ColorTempK(temp_self)); - } - } - - if model.is_some_and(Model::is_color_lamp) { - if let Some(xy_self) = self.color_xy { - if other - .color_xy - .is_none_or(|xy_other| !xy_is_close(xy_other, xy_self)) - { - res.push(Property::ColorXY(xy_self)); - } - } - } - - if let Some(on_self) = self.on { - if other.on.is_none_or(|on_other| on_other != on_self) { - res.push(Property::On(on_self)); - } - } - - if self.color_temp_startup != other.color_temp_startup { - res.push(Property::ColorTempStartup(self.color_temp_startup)); - } - - res - } - - pub(crate) fn apply(self, change: Change) -> LampState { - let mut new_state = self.clone(); - match change { - Change::On(on) => new_state.on = Some(on), - Change::Brightness(bri) => new_state.brightness = Some(bri), - Change::ColorTemp(temp) => { - new_state.color_temp_k = Some(temp); - new_state.color_xy = Some(temp_to_xy(temp)); - } - Change::ColorXy(xy) => new_state.color_xy = Some(xy), - } - new_state - } - - pub(crate) fn property_list(&self) -> Vec { - // we do not send color xy as the lamp might not support it - // if it does then property_list is never called but an exact - // diff between the current and need state is send - - let mut list = Vec::new(); - if let Some(val) = self.brightness { - list.push(Property::Brightness(val)); - } - if let Some(val) = self.color_temp_k { - list.push(Property::ColorTempK(val)); - } - if let Some(val) = self.on { - list.push(Property::On(val)); - } - list.push(Property::ColorTempStartup(self.color_temp_startup)); - list - } -} From 4f1105d9e4fe628a673283a69b2da0544ada4d2c Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 19 Nov 2024 14:53:36 +0100 Subject: [PATCH 422/687] Replace Change with Property --- crates/zigbee-bridge/src/lights.rs | 18 ++++++++++------ .../zigbee-bridge/src/lights/cached_bridge.rs | 2 +- .../src/lights/cached_bridge/changes.rs | 4 ++-- crates/zigbee-bridge/src/lights/lamp.rs | 21 +++++++------------ 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index 455b3022..d1eb07e4 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -14,7 +14,7 @@ mod parse_state; #[derive(Debug, Clone)] pub struct Controller { - change_sender: mpsc::UnboundedSender<(String, lamp::Change)>, + change_sender: mpsc::UnboundedSender<(String, lamp::Property)>, } impl Controller { @@ -31,32 +31,38 @@ impl Controller { pub fn set_on(&self, friendly_name: &str) { self.change_sender - .send((friendly_name.to_string(), lamp::Change::On(true))) + .send((friendly_name.to_string(), lamp::Property::On(true))) .expect("Sender should never be dropped"); } pub fn set_off(&self, friendly_name: &str) { self.change_sender - .send((friendly_name.to_string(), lamp::Change::On(false))) + .send((friendly_name.to_string(), lamp::Property::On(false))) .expect("Sender should never be dropped"); } /// Brightness from 0 to 1 pub fn set_brightness(&self, friendly_name: &str, brightness: f64) { self.change_sender - .send((friendly_name.to_string(), lamp::Change::Brightness(brightness))) + .send(( + friendly_name.to_string(), + lamp::Property::Brightness(brightness), + )) .expect("Sender should never be dropped"); } pub fn set_color_temp(&self, friendly_name: &str, kelvin: usize) { self.change_sender - .send((friendly_name.to_string(), lamp::Change::ColorTemp(kelvin))) + .send(( + friendly_name.to_string(), + lamp::Property::ColorTempK(kelvin), + )) .expect("Sender should never be dropped"); } pub fn set_color_xy(&self, friendly_name: &str, xy: (f64, f64)) { self.change_sender - .send((friendly_name.to_string(), lamp::Change::ColorXy(xy))) + .send((friendly_name.to_string(), lamp::Property::ColorXY(xy))) .expect("Sender should never be dropped"); } } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index ce42fc37..db6b0fea 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -13,7 +13,7 @@ mod mqtt; mod poll; pub(super) async fn run( - change_receiver: mpsc::UnboundedReceiver<(String, lamp::Change)>, + change_receiver: mpsc::UnboundedReceiver<(String, lamp::Property)>, ) -> ! { let mut options = MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index 4dd8cbc5..967fbf98 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -10,7 +10,7 @@ use crate::lights::lamp::{self, Lamp}; use crate::LIGHTS; pub(super) async fn handle( - mut change_receiver: mpsc::UnboundedReceiver<(String, lamp::Change)>, + mut change_receiver: mpsc::UnboundedReceiver<(String, lamp::Property)>, mqtt: &mut Mqtt, known_states: &RwLock>, ) -> ! { @@ -81,7 +81,7 @@ async fn send_and_queue( #[instrument(skip_all)] async fn apply_change( light_name: String, - change: lamp::Change, + change: lamp::Property, known_states: &RwLock>, needed_states: &mut HashMap, ) { diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 47bf13d6..b392fe6a 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -9,14 +9,6 @@ use super::conversion::temp_to_xy; mod model; mod property; -#[derive(Debug, Clone, Copy)] -pub(super) enum Change { - On(bool), - Brightness(f64), - ColorTemp(usize), - ColorXy((f64, f64)), -} - #[derive(Default, Clone, Debug)] pub(super) struct Lamp { model: Option, @@ -73,16 +65,19 @@ impl Lamp { res } - pub(super) fn apply(self, change: Change) -> Self { + pub(super) fn apply(self, change: Property) -> Self { let mut new_state = self.clone(); match change { - Change::On(on) => new_state.on = Some(on), - Change::Brightness(bri) => new_state.brightness = Some(bri), - Change::ColorTemp(temp) => { + Property::On(on) => new_state.on = Some(on), + Property::Brightness(bri) => new_state.brightness = Some(bri), + Property::ColorTempK(temp) => { new_state.color_temp_k = Some(temp); new_state.color_xy = Some(temp_to_xy(temp)); } - Change::ColorXy(xy) => new_state.color_xy = Some(xy), + Property::ColorXY(xy) => new_state.color_xy = Some(xy), + Property::ColorTempStartup(ct_startup) => { + new_state.color_temp_startup = ct_startup + } } new_state } From b9adaed0d230f8d11a5a4ab52926b37d94008687 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 19 Nov 2024 15:11:52 +0100 Subject: [PATCH 423/687] Remove obsolete PartialEq for Lamp --- crates/zigbee-bridge/src/lights/lamp.rs | 48 ------------------------- 1 file changed, 48 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index b392fe6a..98a09140 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -117,51 +117,3 @@ impl Lamp { self.model = Some(model); } } - -impl PartialEq for Lamp { - fn eq(&self, other: &Self) -> bool { - let color_is_equal = if let (Some(self_model), Some(other_model)) = - (self.model.clone(), other.model.clone()) - { - // We should only compare states for the same lamp - assert_eq!(self_model, other_model); - - // We only ever set xy for color lamps, - // so color temp doesn't say anything - if self_model.is_color_lamp() { - match (self.color_xy, other.color_xy) { - (Some(self_xy), Some(other_xy)) => { - let d_color_x = (self_xy.0 - other_xy.0).abs(); - let d_color_y = (self_xy.1 - other_xy.1).abs(); - d_color_x < 0.01 && d_color_y < 0.01 - } - // If either State has no xy set, xy is unset -> different - _ => false, - } - // We only ever set temp, and xy doesn't exist - } else { - match (self.color_temp_k, other.color_temp_k) { - (Some(self_temp), Some(other_temp)) => { - self_temp.abs_diff(other_temp) < 50 - } - _ => false, - } - } - } else { - // We don't know what model this is, thus we don't know how to compare - // colors, so we assume unequal and hope that we know a model soon - false - }; - - let bri_is_equal = match (self.brightness, other.brightness) { - (Some(self_bri), Some(other_bri)) => { - (self_bri - other_bri).abs() < 1. / 250. - } - _ => false, - }; - - self.on == other.on && bri_is_equal && color_is_equal - } -} - -impl Eq for Lamp {} From dc6b71e67443c8e208a6e89f656f8cd9acff2f25 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Wed, 20 Nov 2024 15:21:01 +0100 Subject: [PATCH 424/687] Refactor send timeout fns, untested --- .../src/lights/cached_bridge/changes.rs | 51 ++--- .../src/lights/cached_bridge/mqtt.rs | 177 ++++++++++-------- crates/zigbee-bridge/src/lights/lamp.rs | 2 +- 3 files changed, 124 insertions(+), 106 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index 967fbf98..e14e3bbe 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -1,8 +1,8 @@ use std::collections::HashMap; -use std::time::Duration; +use std::time::{Duration, Instant}; use tokio::sync::{mpsc, RwLock}; -use tokio::time::{sleep, timeout}; +use tokio::time::sleep; use tracing::{debug, instrument, trace}; use super::mqtt::Mqtt; @@ -14,27 +14,34 @@ pub(super) async fn handle( mqtt: &mut Mqtt, known_states: &RwLock>, ) -> ! { - // const MQTT_MIGHT_BE_DOWN_TIMEOUT: Duration = Duration::from_secs(5); const MQTT_MIGHT_BE_DOWN_TIMEOUT: Duration = Duration::from_secs(500); const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); // Give the initial known states a chance to be fetched sleep(WAIT_FOR_INIT_STATES).await; + let mut needed_states = HashMap::new(); - let mut call_again_in = MQTT_MIGHT_BE_DOWN_TIMEOUT; + let mut timeout = MQTT_MIGHT_BE_DOWN_TIMEOUT; loop { - debug!("timeout: {call_again_in:?}"); - if let Ok(res) = timeout(call_again_in, change_receiver.recv()).await { - let res = res.expect("Channel should never close"); - let (light_name, change) = res; + debug!("timeout: {timeout:?}"); + if let Ok(update) = + tokio::time::timeout(timeout, change_receiver.recv()).await + { + let (light_name, change) = + update.expect("Channel should never close"); trace!("Received change: {change:?} for lamp {light_name}"); - apply_change(light_name, change, known_states, &mut needed_states) - .await; + apply_change_to_needed( + light_name, + change, + known_states, + &mut needed_states, + ) + .await; }; - call_again_in = send_and_queue(known_states, &mut needed_states, mqtt) + timeout = on_change_or_timeout(known_states, &mut needed_states, mqtt) .await .min(MQTT_MIGHT_BE_DOWN_TIMEOUT); } @@ -46,12 +53,12 @@ pub(super) async fn handle( /// would be a little spammy. Returns when we need to recheck. If we do not need /// to do so we return Duration::MAX. #[instrument(skip_all)] -async fn send_and_queue( +async fn on_change_or_timeout( known_states: &RwLock>, needed_states: &mut HashMap, mqtt: &mut Mqtt, ) -> Duration { - let mut call_again_in = Duration::MAX; + let mut new_timeout = Duration::MAX; let known_states = known_states.read().await; for light_name in LIGHTS { @@ -63,23 +70,23 @@ async fn send_and_queue( let diff = match known_states.get(light_name) { Some(known) => needed.changes_relative_to(known), - None => needed.property_list(), + None => needed.all_as_changes(), }; if !diff.is_empty() { - // Ignore errors because we will retry if the state hasn't changed - if let Ok(dur) = - mqtt.try_send_state_diff(light_name.to_string(), diff).await - { - call_again_in = call_again_in.min(dur); - } + let _ = mqtt.send_diff(light_name, &diff).await; + + let this_light_due = mqtt.earliest_change_due(light_name, &diff); + let this_light_timeout = + this_light_due.saturating_duration_since(Instant::now()); + new_timeout = new_timeout.min(this_light_timeout); } } - call_again_in + new_timeout } #[instrument(skip_all)] -async fn apply_change( +async fn apply_change_to_needed( light_name: String, change: lamp::Property, known_states: &RwLock>, diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index 43327138..d20a1048 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -10,7 +10,7 @@ use crate::lights::lamp; pub(super) struct Mqtt { client: AsyncClient, - property_last_set: HashMap< + last_sent: HashMap< String, HashMap, >, @@ -20,7 +20,7 @@ impl Mqtt { pub(super) fn new(client: AsyncClient) -> Self { Mqtt { client, - property_last_set: HashMap::new(), + last_sent: HashMap::new(), } } @@ -38,99 +38,110 @@ impl Mqtt { trace!("Requesting state for light {name}"); let payload = json!({"state": ""}); - get(&self.client, name, payload.to_string()).await.unwrap(); + self.get(name, payload.to_string()).await.unwrap(); } - #[instrument(skip(self))] - pub(super) async fn try_send_state_diff( - &mut self, - light_name: String, - diff: Vec, - ) -> Result { - const TIME_IT_TAKES_TO_APPLY_CHANGE: Duration = Duration::from_secs(1); - let mut new_call_needed_in: Duration = Duration::MAX; + /// Pre-condition: diff non-empty + pub(super) fn earliest_change_due( + &self, + light_name: &str, + diff: &[lamp::Property], + ) -> Instant { + diff.into_iter() + .map(|change| self.change_next_due(light_name, &change)) + .min() + .expect("Diff should be non-empty") + } - let last_set = self - .property_last_set - .entry(light_name.clone()) - .or_default(); + fn change_next_due( + &self, + light_name: &str, + change: &lamp::Property, + ) -> Instant { + const CHANGE_APPLY_DELAY: Duration = Duration::from_secs(1); + + let Some(light_send_record) = self.last_sent.get(light_name) else { + // lamp has never been sent before + return Instant::now(); + }; + + let Some(prop_send_record) = light_send_record.get(&change.into()) + else { + // property has never been sent before + return Instant::now(); + }; + + let (sent_at, prev_change) = prop_send_record; + + if prev_change != change || sent_at.elapsed() > CHANGE_APPLY_DELAY { + // we are overdue + Instant::now() + } else { + *sent_at + CHANGE_APPLY_DELAY + } + } + #[instrument(skip(self))] + pub(super) async fn send_diff( + &mut self, + light_name: &str, + diff: &[lamp::Property], + ) -> Result<(), ClientError> { for change in diff { - let Some((at, prev_change)) = last_set.get(&change.into()) else { - set(&self.client, &light_name, change.payload()).await?; - last_set.insert(change.into(), (Instant::now(), change)); - continue; - }; - - if *prev_change != change { - set(&self.client, &light_name, change.payload()).await?; - last_set.insert(change.into(), (Instant::now(), change)); - continue; - } - - if at.elapsed() > TIME_IT_TAKES_TO_APPLY_CHANGE { - set(&self.client, &light_name, change.payload()).await?; - last_set.insert(change.into(), (Instant::now(), change)); - continue; - } - - // trace!( - // "not setting property {change:?} for {light_name} as it has \ - // recently been set" - // ); - let next_call_allowed = *at + TIME_IT_TAKES_TO_APPLY_CHANGE; - let until = - next_call_allowed.saturating_duration_since(Instant::now()); - new_call_needed_in = new_call_needed_in.min(until); + self.set(&light_name, change.payload()).await?; + + let light_send_record = + self.last_sent.entry(light_name.to_owned()).or_default(); + light_send_record.insert(change.into(), (Instant::now(), *change)); } - Ok(new_call_needed_in) + Ok(()) } -} -async fn set( - client: &AsyncClient, - friendly_name: &str, - payload: String, -) -> Result<(), ClientError> { - let topic = format!("zigbee2mqtt/{friendly_name}/set"); + async fn set( + &self, + friendly_name: &str, + payload: String, + ) -> Result<(), ClientError> { + let topic = format!("zigbee2mqtt/{friendly_name}/set"); - trace!("Sending payload {payload} to lamp {friendly_name}"); - publish(client, &topic, payload).await?; - Ok(()) -} + trace!("Sending payload {payload} to lamp {friendly_name}"); + self.publish(&topic, payload).await?; + Ok(()) + } -async fn get( - client: &AsyncClient, - friendly_name: &str, - payload: String, -) -> Result<(), ClientError> { - let topic = format!("zigbee2mqtt/{friendly_name}/get"); + async fn get( + &self, + friendly_name: &str, + payload: String, + ) -> Result<(), ClientError> { + let topic = format!("zigbee2mqtt/{friendly_name}/get"); - publish(client, &topic, payload).await?; - Ok(()) -} + self.publish(&topic, payload).await?; + Ok(()) + } + + async fn publish( + &self, + topic: &str, + payload: String, + ) -> Result<(), ClientError> { + let properties = rumqttc::v5::mqttbytes::v5::PublishProperties { + message_expiry_interval: Some(5), // seconds + ..Default::default() + }; -async fn publish( - client: &AsyncClient, - topic: &str, - payload: String, -) -> Result<(), ClientError> { - let properties = rumqttc::v5::mqttbytes::v5::PublishProperties { - message_expiry_interval: Some(5), // seconds - ..Default::default() - }; - - if topic.contains("kitchen:fridge") { - warn!("ZB to MQTT (fridge): {payload}"); + if topic.contains("kitchen:fridge") { + warn!("ZB to MQTT (fridge): {payload}"); + } + self.client + .publish_with_properties( + topic, + QoS::AtLeastOnce, + false, + payload, + properties, + ) + .await } - client - .publish_with_properties( - topic, - QoS::AtLeastOnce, - false, - payload, - properties, - ) - .await } diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 98a09140..f2693333 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -82,7 +82,7 @@ impl Lamp { new_state } - pub(crate) fn property_list(&self) -> Vec { + pub(crate) fn all_as_changes(&self) -> Vec { // we do not send color xy as the lamp might not support it // if it does then property_list is never called but an exact // diff between the current and need state is send From 8b5dccccf22869ad9b67395ca3756cdaf21d3fb9 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 21 Nov 2024 13:59:53 +0100 Subject: [PATCH 425/687] Fix rewrite of sent tracking, only sending due changes --- .../zigbee-bridge/src/lights/cached_bridge.rs | 7 +++- .../src/lights/cached_bridge/changes.rs | 41 ++++++++++--------- .../src/lights/cached_bridge/mqtt.rs | 33 +++++++++------ 3 files changed, 46 insertions(+), 35 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index db6b0fea..f0d79840 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{collections::HashMap, time::Duration}; use rumqttc::v5::{AsyncClient, MqttOptions}; use tokio::sync::{mpsc, RwLock}; @@ -7,11 +7,14 @@ use tracing::trace; use self::mqtt::Mqtt; use crate::{lights::lamp, LIGHTS, MQTT_IP, MQTT_PORT}; - mod changes; mod mqtt; mod poll; +const MQTT_MIGHT_BE_DOWN_TIMEOUT: Duration = Duration::from_secs(500); +const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); +const CHANGE_APPLY_DELAY: Duration = Duration::from_secs(1); + pub(super) async fn run( change_receiver: mpsc::UnboundedReceiver<(String, lamp::Property)>, ) -> ! { diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index e14e3bbe..91c7e43f 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -2,10 +2,11 @@ use std::collections::HashMap; use std::time::{Duration, Instant}; use tokio::sync::{mpsc, RwLock}; -use tokio::time::sleep; +use tokio::time::{sleep, timeout}; use tracing::{debug, instrument, trace}; use super::mqtt::Mqtt; +use super::{MQTT_MIGHT_BE_DOWN_TIMEOUT, WAIT_FOR_INIT_STATES}; use crate::lights::lamp::{self, Lamp}; use crate::LIGHTS; @@ -14,19 +15,16 @@ pub(super) async fn handle( mqtt: &mut Mqtt, known_states: &RwLock>, ) -> ! { - const MQTT_MIGHT_BE_DOWN_TIMEOUT: Duration = Duration::from_secs(500); - const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); - // Give the initial known states a chance to be fetched sleep(WAIT_FOR_INIT_STATES).await; let mut needed_states = HashMap::new(); - let mut timeout = MQTT_MIGHT_BE_DOWN_TIMEOUT; + let mut call_at_least_in = MQTT_MIGHT_BE_DOWN_TIMEOUT; loop { - debug!("timeout: {timeout:?}"); + debug!("timeout: {call_at_least_in:?}"); if let Ok(update) = - tokio::time::timeout(timeout, change_receiver.recv()).await + timeout(call_at_least_in, change_receiver.recv()).await { let (light_name, change) = update.expect("Channel should never close"); @@ -41,9 +39,10 @@ pub(super) async fn handle( .await; }; - timeout = on_change_or_timeout(known_states, &mut needed_states, mqtt) - .await - .min(MQTT_MIGHT_BE_DOWN_TIMEOUT); + call_at_least_in = + send_diff_get_timeout(known_states, &mut needed_states, mqtt) + .await + .min(MQTT_MIGHT_BE_DOWN_TIMEOUT); } } @@ -53,17 +52,18 @@ pub(super) async fn handle( /// would be a little spammy. Returns when we need to recheck. If we do not need /// to do so we return Duration::MAX. #[instrument(skip_all)] -async fn on_change_or_timeout( +async fn send_diff_get_timeout( known_states: &RwLock>, needed_states: &mut HashMap, mqtt: &mut Mqtt, ) -> Duration { - let mut new_timeout = Duration::MAX; let known_states = known_states.read().await; + let mut light_deadlines = Vec::new(); for light_name in LIGHTS { tracing::Span::current().record("light_name", light_name); + // if there is no needed state, we ignore this light let Some(needed) = needed_states.get(light_name) else { continue; }; @@ -73,16 +73,17 @@ async fn on_change_or_timeout( None => needed.all_as_changes(), }; - if !diff.is_empty() { - let _ = mqtt.send_diff(light_name, &diff).await; - - let this_light_due = mqtt.earliest_change_due(light_name, &diff); - let this_light_timeout = - this_light_due.saturating_duration_since(Instant::now()); - new_timeout = new_timeout.min(this_light_timeout); + let _ = mqtt.send_diff_where_due(light_name, &diff).await; + if let Some(deadline) = mqtt.next_deadline(light_name, &diff) { + light_deadlines.push(deadline); } } - new_timeout + + light_deadlines + .into_iter() + .min() + .map(|deadline| deadline.saturating_duration_since(Instant::now())) + .unwrap_or(Duration::MAX) } #[instrument(skip_all)] diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index d20a1048..e7ed539b 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -1,5 +1,5 @@ use std::collections::HashMap; -use std::time::{Duration, Instant}; +use std::time::Instant; use rumqttc::v5::mqttbytes::QoS; use rumqttc::v5::{AsyncClient, ClientError}; @@ -8,8 +8,11 @@ use tracing::{instrument, trace, warn}; use crate::lights::lamp; +use super::CHANGE_APPLY_DELAY; + pub(super) struct Mqtt { client: AsyncClient, + // TODO: extract into SendTracker struct? last_sent: HashMap< String, HashMap, @@ -41,16 +44,14 @@ impl Mqtt { self.get(name, payload.to_string()).await.unwrap(); } - /// Pre-condition: diff non-empty - pub(super) fn earliest_change_due( + pub(super) fn next_deadline( &self, light_name: &str, diff: &[lamp::Property], - ) -> Instant { + ) -> Option { diff.into_iter() .map(|change| self.change_next_due(light_name, &change)) .min() - .expect("Diff should be non-empty") } fn change_next_due( @@ -58,8 +59,6 @@ impl Mqtt { light_name: &str, change: &lamp::Property, ) -> Instant { - const CHANGE_APPLY_DELAY: Duration = Duration::from_secs(1); - let Some(light_send_record) = self.last_sent.get(light_name) else { // lamp has never been sent before return Instant::now(); @@ -81,18 +80,26 @@ impl Mqtt { } } + fn is_due(&self, light_name: &str, change: &lamp::Property) -> bool { + let deadline = self.change_next_due(light_name, change); + deadline < Instant::now() + } + #[instrument(skip(self))] - pub(super) async fn send_diff( + pub(super) async fn send_diff_where_due( &mut self, light_name: &str, diff: &[lamp::Property], ) -> Result<(), ClientError> { for change in diff { - self.set(&light_name, change.payload()).await?; - - let light_send_record = - self.last_sent.entry(light_name.to_owned()).or_default(); - light_send_record.insert(change.into(), (Instant::now(), *change)); + if self.is_due(&light_name, change) { + self.set(&light_name, change.payload()).await?; + + let light_send_record = + self.last_sent.entry(light_name.to_owned()).or_default(); + light_send_record + .insert(change.into(), (Instant::now(), *change)); + } } Ok(()) From 1e91e3b4619c7ef41e2e91332ea10e491a70772b Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 21 Nov 2024 14:31:53 +0100 Subject: [PATCH 426/687] Add model to needed when it is changed from known --- .../src/lights/cached_bridge/changes.rs | 14 ++++++-------- crates/zigbee-bridge/src/lights/lamp.rs | 7 +++++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index 91c7e43f..532cc253 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -95,16 +95,14 @@ async fn apply_change_to_needed( ) { let known_states = known_states.read().await; + let default = Lamp::default(); + let known = known_states.get(&light_name).unwrap_or(&default); let needed = match needed_states.get(&light_name) { - Some(needed_state) => needed_state, - None => match known_states.get(&light_name) { - Some(known_state) => needed_states - .entry(light_name.clone()) - .or_insert(known_state.clone()), - None => &mut Lamp::default(), - }, + // make sure needed has the model if known has it + Some(needed) => needed.clone().add_model_from(&known), + None => known.clone(), }; - let with_change_applied = needed.clone().apply(change); + let with_change_applied = needed.apply(change); needed_states.insert(light_name, with_change_applied); } diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index f2693333..63b63076 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -113,6 +113,13 @@ impl Lamp { } } + pub(crate) fn add_model_from(mut self, other: &Lamp) -> Self { + if let Some(model) = &other.model { + self.model = Some(model.clone()); + } + self + } + pub(crate) fn set_model(&mut self, model: Model) { self.model = Some(model); } From 10b521829b6f18990aeca725f04bf91ce7bc084a Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 22 Nov 2024 11:14:36 +0100 Subject: [PATCH 427/687] Make lamp have either temp or xy, not both --- .../src/lights/cached_bridge/changes.rs | 6 +- .../src/lights/cached_bridge/poll.rs | 2 +- crates/zigbee-bridge/src/lights/lamp.rs | 109 ++++++++++-------- crates/zigbee-bridge/src/lights/lamp/model.rs | 2 +- .../zigbee-bridge/src/lights/lamp/property.rs | 25 ++-- 5 files changed, 83 insertions(+), 61 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index 532cc253..e6275501 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -97,12 +97,12 @@ async fn apply_change_to_needed( let default = Lamp::default(); let known = known_states.get(&light_name).unwrap_or(&default); - let needed = match needed_states.get(&light_name) { + let mut needed = match needed_states.get(&light_name) { // make sure needed has the model if known has it Some(needed) => needed.clone().add_model_from(&known), None => known.clone(), }; - let with_change_applied = needed.apply(change); - needed_states.insert(light_name, with_change_applied); + needed.apply(change); + needed_states.insert(light_name, needed); } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 4af1990a..f7693cfc 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -78,7 +78,7 @@ async fn update_state( ); } } - current_lamp.change_state(property); + current_lamp.apply(property); } } diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 63b63076..2fcacedc 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -1,7 +1,7 @@ pub(super) use model::Model; pub(super) use property::{Property, PropertyDiscriminants}; -use self::property::{bri_is_close, temp_is_close, xy_is_close}; +use self::property::{bri_is_close, color_is_close}; use tracing::instrument; use super::conversion::temp_to_xy; @@ -9,13 +9,24 @@ use super::conversion::temp_to_xy; mod model; mod property; +#[derive(Clone, Copy, Debug)] +enum Color { + TempK(usize), + XY((f64, f64)), +} + +impl Color { + fn xy_from_temp(temp: usize) -> Color { + Color::XY(temp_to_xy(temp)) + } +} + #[derive(Default, Clone, Debug)] pub(super) struct Lamp { model: Option, brightness: Option, - color_temp_k: Option, - color_xy: Option<(f64, f64)>, - on: Option, + color: Option, + is_on: Option, color_temp_startup: property::ColorTempStartup, } @@ -32,28 +43,30 @@ impl Lamp { } } - if let Some(temp_self) = self.color_temp_k { - if other - .color_temp_k - .is_none_or(|temp_other| !temp_is_close(temp_other, temp_self)) - { - res.push(Property::ColorTempK(temp_self)); - } - } - - if self.model.as_ref().is_some_and(Model::is_color_lamp) { - if let Some(xy_self) = self.color_xy { - if other - .color_xy - .is_none_or(|xy_other| !xy_is_close(xy_other, xy_self)) - { - res.push(Property::ColorXY(xy_self)); + if let Some(color_self) = self.color { + let log_err = |err| { + tracing::error!("Comparing incompatible lamp states, defaulting to same\nSelf: {self:?}\nOther: {other:?}\nErr: {err}"); + }; + + let color_is_close = match other.color { + None => false, + Some(color_other) => color_is_close(color_other, color_self) + .unwrap_or_else(|err| { + log_err(err); + true + }), + }; + + if !color_is_close { + match color_self { + Color::XY(xy) => res.push(Property::ColorXY(xy)), + Color::TempK(temp) => res.push(Property::ColorTempK(temp)), } } } - if let Some(on_self) = self.on { - if other.on.is_none_or(|on_other| on_other != on_self) { + if let Some(on_self) = self.is_on { + if other.is_on.is_none_or(|on_other| on_other != on_self) { res.push(Property::On(on_self)); } } @@ -65,21 +78,32 @@ impl Lamp { res } - pub(super) fn apply(self, change: Property) -> Self { - let mut new_state = self.clone(); + pub(super) fn apply(&mut self, change: Property) { match change { - Property::On(on) => new_state.on = Some(on), - Property::Brightness(bri) => new_state.brightness = Some(bri), + Property::On(is_on) => self.is_on = Some(is_on), + Property::Brightness(bri) => self.brightness = Some(bri), Property::ColorTempK(temp) => { - new_state.color_temp_k = Some(temp); - new_state.color_xy = Some(temp_to_xy(temp)); + // if we know the model, we know how to apply temp + if let Some(model) = &self.model { + if model.supports_xy() { + self.color = Some(Color::xy_from_temp(temp)); + } else { + self.color = Some(Color::TempK(temp)) + } + } } - Property::ColorXY(xy) => new_state.color_xy = Some(xy), - Property::ColorTempStartup(ct_startup) => { - new_state.color_temp_startup = ct_startup + Property::ColorXY(xy) => { + // don't apply xy to unknown or non-color lamp + if let Some(model) = &self.model { + if model.supports_xy() { + self.color = Some(Color::XY(xy)) + } + } + } + Property::ColorTempStartup(behaviour) => { + self.color_temp_startup = behaviour } } - new_state } pub(crate) fn all_as_changes(&self) -> Vec { @@ -91,28 +115,19 @@ impl Lamp { if let Some(val) = (&self).brightness { list.push(Property::Brightness(val)); } - if let Some(val) = (&self).color_temp_k { - list.push(Property::ColorTempK(val)); + if let Some(val) = &self.color { + match val { + Color::XY(xy) => list.push(Property::ColorXY(*xy)), + Color::TempK(temp) => list.push(Property::ColorTempK(*temp)), + } } - if let Some(val) = (&self).on { + if let Some(val) = (&self).is_on { list.push(Property::On(val)); } list.push(Property::ColorTempStartup((&self).color_temp_startup)); list } - pub(crate) fn change_state(&mut self, property: Property) { - match property { - Property::Brightness(bri) => self.brightness = Some(bri), - Property::ColorTempK(temp) => self.color_temp_k = Some(temp), - Property::ColorXY(xy) => self.color_xy = Some(xy), - Property::On(is_on) => self.on = Some(is_on), - Property::ColorTempStartup(behavior) => { - self.color_temp_startup = behavior; - } - } - } - pub(crate) fn add_model_from(mut self, other: &Lamp) -> Self { if let Some(model) = &other.model { self.model = Some(model.clone()); diff --git a/crates/zigbee-bridge/src/lights/lamp/model.rs b/crates/zigbee-bridge/src/lights/lamp/model.rs index 4d8c7458..616bedf1 100644 --- a/crates/zigbee-bridge/src/lights/lamp/model.rs +++ b/crates/zigbee-bridge/src/lights/lamp/model.rs @@ -13,7 +13,7 @@ pub(crate) enum Model { } impl Model { - pub(super) fn is_color_lamp(&self) -> bool { + pub(super) fn supports_xy(&self) -> bool { #[allow(clippy::match_same_arms)] // clearer comment match self { Model::TradfriE27 | Model::TradfriE14 | Model::HueGen4 => true, diff --git a/crates/zigbee-bridge/src/lights/lamp/property.rs b/crates/zigbee-bridge/src/lights/lamp/property.rs index be762aaf..caba5a37 100644 --- a/crates/zigbee-bridge/src/lights/lamp/property.rs +++ b/crates/zigbee-bridge/src/lights/lamp/property.rs @@ -3,6 +3,8 @@ use strum::EnumDiscriminants; use crate::lights::{denormalize, kelvin_to_mired}; +use super::Color; + #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] pub(crate) enum ColorTempStartup { #[default] @@ -28,14 +30,11 @@ impl PartialEq for Property { (Property::ColorTempK(a), Property::ColorTempK(b)) => { temp_is_close(*a, *b) } - (Property::ColorXY(a), Property::ColorXY(b)) => { - xy_is_close(*a, *b) - } + (Property::ColorXY(a), Property::ColorXY(b)) => xy_is_close(*a, *b), (Property::On(a), Property::On(b)) => a == b, - ( - Property::ColorTempStartup(a), - Property::ColorTempStartup(b), - ) => a == b, + (Property::ColorTempStartup(a), Property::ColorTempStartup(b)) => { + a == b + } (_, _) => false, } } @@ -69,11 +68,19 @@ pub(super) fn bri_is_close(a: f64, b: f64) -> bool { (a - b).abs() < 1. / 250. } -pub(super) fn temp_is_close(a: usize, b: usize) -> bool { +pub(super) fn color_is_close(a: Color, b: Color) -> Result { + match (a, b) { + (Color::XY(a), Color::XY(b)) => Ok(xy_is_close(a, b)), + (Color::TempK(a), Color::TempK(b)) => Ok(temp_is_close(a, b)), + (_, _) => Err("Comparing XY and Temp".to_owned()), + } +} + +fn temp_is_close(a: usize, b: usize) -> bool { a.abs_diff(b) < 50 } -pub(super) fn xy_is_close(a: (f64, f64), b: (f64, f64)) -> bool { +fn xy_is_close(a: (f64, f64), b: (f64, f64)) -> bool { let d_color_x = (a.0 - b.0).abs(); let d_color_y = (a.1 - b.1).abs(); d_color_x < 0.01 && d_color_y < 0.01 From bbfb0a10acaac6ff369f4ce43e805013d5beb9d9 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 22 Nov 2024 11:30:24 +0100 Subject: [PATCH 428/687] Clamp color temp to possible values for model --- crates/zigbee-bridge/src/lights/conversion.rs | 4 +++- crates/zigbee-bridge/src/lights/lamp.rs | 2 ++ crates/zigbee-bridge/src/lights/lamp/model.rs | 13 ++++++++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/conversion.rs b/crates/zigbee-bridge/src/lights/conversion.rs index e75f3415..2492bf4c 100644 --- a/crates/zigbee-bridge/src/lights/conversion.rs +++ b/crates/zigbee-bridge/src/lights/conversion.rs @@ -32,7 +32,9 @@ pub(super) fn temp_to_xy(color_temp: usize) -> (f64, f64) { let cct = CCT::try_new(color_temp as f64, DUV_IKEA).unwrap(); let xyz: XYZ = cct.try_into().unwrap(); - xyz_to_xy(xyz) + let (x, y) = xyz_to_xy(xyz); + (x.clamp(0.0, 1.0), y.clamp(0.0, 1.0)) + } fn xyz_to_xy(xyz: XYZ) -> (f64, f64) { diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 2fcacedc..6aec1a7f 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -88,6 +88,8 @@ impl Lamp { if model.supports_xy() { self.color = Some(Color::xy_from_temp(temp)); } else { + let range = model.temp_k_range(); + let temp = temp.clamp(range.start, range.end); self.color = Some(Color::TempK(temp)) } } diff --git a/crates/zigbee-bridge/src/lights/lamp/model.rs b/crates/zigbee-bridge/src/lights/lamp/model.rs index 616bedf1..fad0d92f 100644 --- a/crates/zigbee-bridge/src/lights/lamp/model.rs +++ b/crates/zigbee-bridge/src/lights/lamp/model.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{collections::HashMap, ops::Range}; #[derive(Debug, Clone, PartialEq, Eq)] pub(crate) enum Model { @@ -25,6 +25,17 @@ impl Model { } } + pub(super) fn temp_k_range(&self) -> Range { + match self { + Model::TradfriCandle => 2200..4000, + Model::TradfriE27 | Model::TradfriE14 => 1780..4000, + Model::HueGen4 => 2000..6500, + Model::TradfriOther(_) => 2200..4000, + Model::HueOther(_) => 2200..6500, + Model::Other(_) => 2200..4000, + } + } + #[allow(unused)] pub(super) fn color_deviation(&self, color_temp: usize) -> (usize, f64) { match self { From 2b8c4d785c297e81d0b9a1925ed40f2a22b7246f Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 22 Nov 2024 13:24:31 +0100 Subject: [PATCH 429/687] Apply feedback --- .../zigbee-bridge/src/lights/cached_bridge.rs | 2 +- .../src/lights/cached_bridge/mqtt.rs | 20 +++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index f0d79840..c7cbe7a5 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -13,7 +13,7 @@ mod poll; const MQTT_MIGHT_BE_DOWN_TIMEOUT: Duration = Duration::from_secs(500); const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); -const CHANGE_APPLY_DELAY: Duration = Duration::from_secs(1); +const TIME_IT_TAKES_TO_APPLY_CHANGE: Duration = Duration::from_secs(1); pub(super) async fn run( change_receiver: mpsc::UnboundedReceiver<(String, lamp::Property)>, diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index e7ed539b..f34667de 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -8,7 +8,7 @@ use tracing::{instrument, trace, warn}; use crate::lights::lamp; -use super::CHANGE_APPLY_DELAY; +use super::TIME_IT_TAKES_TO_APPLY_CHANGE; pub(super) struct Mqtt { client: AsyncClient, @@ -64,20 +64,24 @@ impl Mqtt { return Instant::now(); }; - let Some(prop_send_record) = light_send_record.get(&change.into()) + let Some((sent_at, prev_change)) = + light_send_record.get(&change.into()) else { // property has never been sent before return Instant::now(); }; - let (sent_at, prev_change) = prop_send_record; + // there is a new change + if prev_change != change { + return Instant::now(); + } - if prev_change != change || sent_at.elapsed() > CHANGE_APPLY_DELAY { - // we are overdue - Instant::now() - } else { - *sent_at + CHANGE_APPLY_DELAY + // we are overdue + if sent_at.elapsed() > TIME_IT_TAKES_TO_APPLY_CHANGE { + return Instant::now(); } + + *sent_at + TIME_IT_TAKES_TO_APPLY_CHANGE } fn is_due(&self, light_name: &str, change: &lamp::Property) -> bool { From a19e3aba71a1cbd109a1c469dbe5f62606389593 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 22 Nov 2024 13:48:48 +0100 Subject: [PATCH 430/687] Add Online property and logging sub (unused) --- .../zigbee-bridge/src/lights/cached_bridge.rs | 1 + .../src/lights/cached_bridge/poll.rs | 76 ++++++++++++------- crates/zigbee-bridge/src/lights/lamp.rs | 17 +++-- .../zigbee-bridge/src/lights/lamp/property.rs | 9 +++ 4 files changed, 71 insertions(+), 32 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index c7cbe7a5..08da6e22 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -34,6 +34,7 @@ pub(super) async fn run( let mut mqtt = Mqtt::new(client); mqtt.subscribe("zigbee2mqtt/bridge/devices").await.unwrap(); + mqtt.subscribe("zigbee2mqtt/bridge/logging").await.unwrap(); for light in LIGHTS { mqtt.subscribe(&format!("zigbee2mqtt/{light}")) .await diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index f7693cfc..ae7f6f67 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -93,33 +93,57 @@ fn parse_message(event: Event) -> color_eyre::Result { }; trace!("message: {message:?}"); - let topic = String::from_utf8_lossy(&message.topic); - - if topic == "zigbee2mqtt/bridge/devices" { - let json: Value = serde_json::from_slice(&message.payload) - .wrap_err("could not parse message payload as json")?; - let list = json - .as_array() - .ok_or_eyre("devices list should be array its not") - .with_note(|| format!("json was: {json:?}"))?; - let devices: HashMap = list - .iter() - .map(|dev| { - parse_device(dev) - .wrap_err("could not parse device") - .with_note(|| format!("device: {dev:?}")) - }) - .filter_ok(|d| d.0 != "Coordinator") - .collect::>()?; - Ok(Message::Devices(devices)) + let topic: &str = &String::from_utf8_lossy(&message.topic); + + match topic { + "zigbee2mqtt/bridge/devices" => { + let json: Value = serde_json::from_slice(&message.payload) + .wrap_err("could not parse message payload as json")?; + let list = json + .as_array() + .ok_or_eyre("devices list should be array its not") + .with_note(|| format!("json was: {json:?}"))?; + let devices: HashMap = list + .iter() + .map(|dev| { + parse_device(dev) + .wrap_err("could not parse device") + .with_note(|| format!("device: {dev:?}")) + }) + .filter_ok(|d| d.0 != "Coordinator") + .collect::>()?; + Ok(Message::Devices(devices)) + } + "zigbee2mqtt/bridge/logging" => { + let json: Value = serde_json::from_slice(&message.payload) + .wrap_err("could not parse message payload as json")?; + let log = json + .as_object() + .ok_or_eyre("log should be map it is not") + .with_note(|| format!("json was: {json:?}"))?; + // parse_log_message(log) + Ok(Message::Other) + } + topic => { + let topic: Vec<_> = topic.split('/').collect(); + let name = topic[1].to_string(); + let state = parse_lamp_properties(&message.payload) + .wrap_err("failed to parse lamp state") + .with_note(|| format!("topic: {topic:?}"))?; + Ok(Message::StateUpdate((name, state))) + } + } +} + +fn parse_log_message( + log: &serde_json::Map, +) -> color_eyre::Result { + let level = log.get("level").ok_or_eyre("no level in log message")?; + let message = log.get("message").ok_or_eyre("no message in log message")?; + if level == "error" { + todo!() } else { - let topic = String::from_utf8_lossy(&message.topic); - let topic: Vec<_> = topic.split('/').collect(); - let name = topic[1].to_string(); - let state = parse_lamp_properties(&message.payload) - .wrap_err("failed to parse lamp state") - .with_note(|| format!("topic: {topic:?}"))?; - Ok(Message::StateUpdate((name, state))) + Ok(Message::Other) } } diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 6aec1a7f..48cb53bd 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -2,7 +2,7 @@ pub(super) use model::Model; pub(super) use property::{Property, PropertyDiscriminants}; use self::property::{bri_is_close, color_is_close}; -use tracing::instrument; +use tracing::{error, instrument}; use super::conversion::temp_to_xy; @@ -21,9 +21,11 @@ impl Color { } } +// TODO: some way to enforce read-only (thus known-updatable-only) fields? #[derive(Default, Clone, Debug)] pub(super) struct Lamp { model: Option, + is_online: Option, brightness: Option, color: Option, is_on: Option, @@ -34,6 +36,9 @@ impl Lamp { #[instrument] pub(super) fn changes_relative_to(&self, other: &Self) -> Vec { let mut res = Vec::new(); + + // Ignore model and is_online, because they are read-only + if let Some(bri_self) = self.brightness { if other .brightness @@ -45,7 +50,7 @@ impl Lamp { if let Some(color_self) = self.color { let log_err = |err| { - tracing::error!("Comparing incompatible lamp states, defaulting to same\nSelf: {self:?}\nOther: {other:?}\nErr: {err}"); + error!("Comparing incompatible lamp states, defaulting to same\nSelf: {self:?}\nOther: {other:?}\nErr: {err}"); }; let color_is_close = match other.color { @@ -105,15 +110,15 @@ impl Lamp { Property::ColorTempStartup(behaviour) => { self.color_temp_startup = behaviour } + Property::Online(is_online) => self.is_online = Some(is_online), } } pub(crate) fn all_as_changes(&self) -> Vec { - // we do not send color xy as the lamp might not support it - // if it does then property_list is never called but an exact - // diff between the current and need state is send - let mut list = Vec::new(); + + // Ignore model and is_online, because they are read-only + if let Some(val) = (&self).brightness { list.push(Property::Brightness(val)); } diff --git a/crates/zigbee-bridge/src/lights/lamp/property.rs b/crates/zigbee-bridge/src/lights/lamp/property.rs index caba5a37..fedaf324 100644 --- a/crates/zigbee-bridge/src/lights/lamp/property.rs +++ b/crates/zigbee-bridge/src/lights/lamp/property.rs @@ -1,5 +1,6 @@ use serde_json::json; use strum::EnumDiscriminants; +use tracing::error; use crate::lights::{denormalize, kelvin_to_mired}; @@ -14,6 +15,7 @@ pub(crate) enum ColorTempStartup { #[derive(Debug, EnumDiscriminants, Clone, Copy)] #[strum_discriminants(derive(Hash))] pub(crate) enum Property { + Online(bool), Brightness(f64), ColorTempK(usize), ColorXY((f64, f64)), @@ -35,6 +37,8 @@ impl PartialEq for Property { (Property::ColorTempStartup(a), Property::ColorTempStartup(b)) => { a == b } + // we never need to update this, thus we always consider it the same + (Property::Online(_), Property::Online(_)) => true, (_, _) => false, } } @@ -59,6 +63,11 @@ impl Property { Property::ColorTempStartup(ColorTempStartup::Previous) => { json!({"color_temp_startup": "previous"}) } + // read-only, shouldn't be called, safe default + Property::Online(_) => { + error!("Tried to convert Online to payload"); + json!({"state": ""}) + } } .to_string() } From a447382a416eab19f4e81f6bf35633d440261f06 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 23 Nov 2024 14:54:45 +0100 Subject: [PATCH 431/687] Set to testing settings and add tracing --- crates/brain/src/controller/rooms/kitchen.rs | 9 ++++++--- crates/zigbee-bridge/src/lights/cached_bridge/changes.rs | 5 ++++- crates/zigbee-bridge/src/lights/cached_bridge/poll.rs | 9 +++++++++ crates/zigbee-bridge/src/lights/lamp.rs | 3 ++- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index 1622d165..bac97ae8 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -83,19 +83,22 @@ pub async fn run( } async fn update(system: &mut RestrictedSystem) { - let (new_ct, new_bri) = small_bedroom::optimal_ct_bri(); + // let (new_ct, new_bri) = small_bedroom::optimal_ct_bri(); + let (new_ct, new_bri) = _testing_ct_bri(); system.all_lamps_ct(new_ct, new_bri).await; tracing::trace!("updated lamps"); } fn _testing_ct_bri() -> (u16, u8) { let now = local_now(); - let optimal = match now.hour() { + // let optimal = match now.hour() { + let optimal = match now.minute() { min if min % 2 == 0 => (400, u8::MAX), // Even hour: orange min if min % 2 == 1 => (250, u8::MAX), // Odd hour: blue _ => (400, u8::MAX), }; - if now.minute() == 0 && now.second() <= 9 { + // if now.minute() == 0 && now.second() <= 9 { + if now.second() <= 9 { warn!("B: correct color temp is now {}", optimal.0); } optimal diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index e6275501..c6fca67b 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -3,7 +3,7 @@ use std::time::{Duration, Instant}; use tokio::sync::{mpsc, RwLock}; use tokio::time::{sleep, timeout}; -use tracing::{debug, instrument, trace}; +use tracing::{debug, instrument, trace, warn}; use super::mqtt::Mqtt; use super::{MQTT_MIGHT_BE_DOWN_TIMEOUT, WAIT_FOR_INIT_STATES}; @@ -104,5 +104,8 @@ async fn apply_change_to_needed( }; needed.apply(change); + // if light_name == "kitchen:fridge" { + // warn!("New (fridge) needed state model: {:?}", needed.model); + // } needed_states.insert(light_name, needed); } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index ae7f6f67..2e58252e 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -43,6 +43,7 @@ pub(super) async fn poll_mqtt( .await; } Message::Devices(new_devices) => { + warn!("Received devices list"); for (light_name, model) in new_devices { update_model(known_states, light_name, model).await; } @@ -59,6 +60,12 @@ async fn update_model( ) { let mut known_states = known_states.write().await; let current_lamp = known_states.entry(light_name.to_string()).or_default(); + if light_name == "kitchen:fridge" { + warn!( + "Received model update for fridge lamp,\nold: {:?},\nnew: {model:?}", + current_lamp.model + ); + } current_lamp.set_model(model); } @@ -97,8 +104,10 @@ fn parse_message(event: Event) -> color_eyre::Result { match topic { "zigbee2mqtt/bridge/devices" => { + warn!("ZB received devices message"); let json: Value = serde_json::from_slice(&message.payload) .wrap_err("could not parse message payload as json")?; + warn!("contents: {json:#?}"); let list = json .as_array() .ok_or_eyre("devices list should be array its not") diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 48cb53bd..6115606b 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -24,7 +24,8 @@ impl Color { // TODO: some way to enforce read-only (thus known-updatable-only) fields? #[derive(Default, Clone, Debug)] pub(super) struct Lamp { - model: Option, + // TODO: remove after debugging + pub(super) model: Option, is_online: Option, brightness: Option, color: Option, From 99c5ee3c92c477993ce388a4f033ab330efb8c25 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 23 Nov 2024 14:56:06 +0100 Subject: [PATCH 432/687] Switch to clean session and resubscribe when reconnecting To be reversed, but useful to have in history --- .../zigbee-bridge/src/lights/cached_bridge.rs | 26 +++++++------------ .../src/lights/cached_bridge/changes.rs | 7 ++--- .../src/lights/cached_bridge/mqtt.rs | 20 ++++++++++---- .../src/lights/cached_bridge/poll.rs | 16 ++++++++++-- 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 08da6e22..556b122b 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -5,7 +5,7 @@ use tokio::sync::{mpsc, RwLock}; use tracing::trace; use self::mqtt::Mqtt; -use crate::{lights::lamp, LIGHTS, MQTT_IP, MQTT_PORT}; +use crate::{lights::lamp, MQTT_IP, MQTT_PORT}; mod changes; mod mqtt; @@ -15,6 +15,9 @@ const MQTT_MIGHT_BE_DOWN_TIMEOUT: Duration = Duration::from_secs(500); const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); const TIME_IT_TAKES_TO_APPLY_CHANGE: Duration = Duration::from_secs(1); +const TO_SUBSCRIBE: [&str; 2] = + ["zigbee2mqtt/bridge/devices", "zigbee2mqtt/bridge/logging"]; + pub(super) async fn run( change_receiver: mpsc::UnboundedReceiver<(String, lamp::Property)>, ) -> ! { @@ -22,8 +25,9 @@ pub(super) async fn run( MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); // Set max mqtt packet size to 4kB options.set_max_packet_size(Some(4096)); - // Keep subscriptions when reconnecting!!!! - options.set_clean_start(false); + // We need a clean session to receive the device list... + // Now we need to resubscribe when we reconnect... + options.set_clean_start(true); let known_states = RwLock::new(HashMap::new()); @@ -31,21 +35,11 @@ pub(super) async fn run( let channel_capacity = 128; let (client, eventloop) = AsyncClient::new(options.clone(), channel_capacity); - let mut mqtt = Mqtt::new(client); - - mqtt.subscribe("zigbee2mqtt/bridge/devices").await.unwrap(); - mqtt.subscribe("zigbee2mqtt/bridge/logging").await.unwrap(); - for light in LIGHTS { - mqtt.subscribe(&format!("zigbee2mqtt/{light}")) - .await - .unwrap(); - mqtt.request_state(light).await; - } + let mqtt = RwLock::new(Mqtt::new(client)); trace!("Starting main zigbee management loops"); - let poll_mqtt = poll::poll_mqtt(eventloop, &known_states); - let handle_changes = - changes::handle(change_receiver, &mut mqtt, &known_states); + let poll_mqtt = poll::poll_mqtt(eventloop, &mqtt, &known_states); + let handle_changes = changes::handle(change_receiver, &mqtt, &known_states); tokio::select! { () = handle_changes => unreachable!("should not panic"), diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index c6fca67b..f2e981ce 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use std::time::{Duration, Instant}; -use tokio::sync::{mpsc, RwLock}; +use tokio::sync::{mpsc, Mutex, RwLock}; use tokio::time::{sleep, timeout}; use tracing::{debug, instrument, trace, warn}; @@ -12,7 +12,7 @@ use crate::LIGHTS; pub(super) async fn handle( mut change_receiver: mpsc::UnboundedReceiver<(String, lamp::Property)>, - mqtt: &mut Mqtt, + mqtt: &RwLock, known_states: &RwLock>, ) -> ! { // Give the initial known states a chance to be fetched @@ -39,8 +39,9 @@ pub(super) async fn handle( .await; }; + let mut mqtt = mqtt.write().await; call_at_least_in = - send_diff_get_timeout(known_states, &mut needed_states, mqtt) + send_diff_get_timeout(known_states, &mut needed_states, &mut mqtt) .await .min(MQTT_MIGHT_BE_DOWN_TIMEOUT); } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index f34667de..35c246c1 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -7,8 +7,9 @@ use serde_json::json; use tracing::{instrument, trace, warn}; use crate::lights::lamp; +use crate::LIGHTS; -use super::TIME_IT_TAKES_TO_APPLY_CHANGE; +use super::{TIME_IT_TAKES_TO_APPLY_CHANGE, TO_SUBSCRIBE}; pub(super) struct Mqtt { client: AsyncClient, @@ -27,10 +28,19 @@ impl Mqtt { } } - pub(super) async fn subscribe( - &self, - topic: &str, - ) -> Result<(), ClientError> { + pub(super) async fn subscribe_to_all(&self) { + for topic in TO_SUBSCRIBE { + self.subscribe(topic).await.unwrap(); + } + for light in LIGHTS { + self.subscribe(&format!("zigbee2mqtt/{light}")) + .await + .unwrap(); + self.request_state(light).await; + } + } + + async fn subscribe(&self, topic: &str) -> Result<(), ClientError> { // Its okay for messages to arrive twice or more. MQTT guarantees // ordering and we only do something if the cached bridge indicates we // need to so light states arriving twice is not an issue. diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 2e58252e..71edd2be 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -6,6 +6,7 @@ use itertools::Itertools; use ratelimited_logger::RateLimitedLogger; use rumqttc::v5::{Event, EventLoop, Incoming}; use serde_json::Value; +use tokio::sync::Mutex; use tokio::{sync::RwLock, time::sleep}; use tracing::{instrument, trace, warn}; @@ -13,8 +14,11 @@ use crate::lights::kelvin_to_mired; use crate::lights::lamp::{self, Lamp}; use crate::lights::parse_state::parse_lamp_properties; +use super::mqtt::Mqtt; + pub(super) async fn poll_mqtt( mut eventloop: EventLoop, + mqtt: &RwLock, known_states: &RwLock>, ) -> ! { let mut logger = RateLimitedLogger::default(); @@ -48,6 +52,11 @@ pub(super) async fn poll_mqtt( update_model(known_states, light_name, model).await; } } + Message::ConnAck => { + warn!("Received ConnAck, resubscribing"); + let mqtt = mqtt.read().await; + mqtt.subscribe_to_all().await; + } Message::Other => (), } } @@ -95,8 +104,10 @@ fn parse_message(event: Event) -> color_eyre::Result { return Ok(Message::Other); }; - let Incoming::Publish(message) = incoming else { - return Ok(Message::Other); + let message = match incoming { + Incoming::Publish(message) => message, + Incoming::ConnAck(_) => return Ok(Message::ConnAck), + _ => return Ok(Message::Other), }; trace!("message: {message:?}"); @@ -160,6 +171,7 @@ fn parse_log_message( enum Message { StateUpdate((String, Vec)), Devices(HashMap), + ConnAck, Other, } From 808e2d6d834c6234f63444d9d6363007b5c7194a Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 23 Nov 2024 14:56:46 +0100 Subject: [PATCH 433/687] Revert "Switch to clean session and resubscribe when reconnecting" This reverts commit 99c5ee3c92c477993ce388a4f033ab330efb8c25. --- .../zigbee-bridge/src/lights/cached_bridge.rs | 26 ++++++++++++------- .../src/lights/cached_bridge/changes.rs | 7 +++-- .../src/lights/cached_bridge/mqtt.rs | 20 ++++---------- .../src/lights/cached_bridge/poll.rs | 16 ++---------- 4 files changed, 26 insertions(+), 43 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 556b122b..08da6e22 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -5,7 +5,7 @@ use tokio::sync::{mpsc, RwLock}; use tracing::trace; use self::mqtt::Mqtt; -use crate::{lights::lamp, MQTT_IP, MQTT_PORT}; +use crate::{lights::lamp, LIGHTS, MQTT_IP, MQTT_PORT}; mod changes; mod mqtt; @@ -15,9 +15,6 @@ const MQTT_MIGHT_BE_DOWN_TIMEOUT: Duration = Duration::from_secs(500); const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); const TIME_IT_TAKES_TO_APPLY_CHANGE: Duration = Duration::from_secs(1); -const TO_SUBSCRIBE: [&str; 2] = - ["zigbee2mqtt/bridge/devices", "zigbee2mqtt/bridge/logging"]; - pub(super) async fn run( change_receiver: mpsc::UnboundedReceiver<(String, lamp::Property)>, ) -> ! { @@ -25,9 +22,8 @@ pub(super) async fn run( MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); // Set max mqtt packet size to 4kB options.set_max_packet_size(Some(4096)); - // We need a clean session to receive the device list... - // Now we need to resubscribe when we reconnect... - options.set_clean_start(true); + // Keep subscriptions when reconnecting!!!! + options.set_clean_start(false); let known_states = RwLock::new(HashMap::new()); @@ -35,11 +31,21 @@ pub(super) async fn run( let channel_capacity = 128; let (client, eventloop) = AsyncClient::new(options.clone(), channel_capacity); - let mqtt = RwLock::new(Mqtt::new(client)); + let mut mqtt = Mqtt::new(client); + + mqtt.subscribe("zigbee2mqtt/bridge/devices").await.unwrap(); + mqtt.subscribe("zigbee2mqtt/bridge/logging").await.unwrap(); + for light in LIGHTS { + mqtt.subscribe(&format!("zigbee2mqtt/{light}")) + .await + .unwrap(); + mqtt.request_state(light).await; + } trace!("Starting main zigbee management loops"); - let poll_mqtt = poll::poll_mqtt(eventloop, &mqtt, &known_states); - let handle_changes = changes::handle(change_receiver, &mqtt, &known_states); + let poll_mqtt = poll::poll_mqtt(eventloop, &known_states); + let handle_changes = + changes::handle(change_receiver, &mut mqtt, &known_states); tokio::select! { () = handle_changes => unreachable!("should not panic"), diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index f2e981ce..c6fca67b 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use std::time::{Duration, Instant}; -use tokio::sync::{mpsc, Mutex, RwLock}; +use tokio::sync::{mpsc, RwLock}; use tokio::time::{sleep, timeout}; use tracing::{debug, instrument, trace, warn}; @@ -12,7 +12,7 @@ use crate::LIGHTS; pub(super) async fn handle( mut change_receiver: mpsc::UnboundedReceiver<(String, lamp::Property)>, - mqtt: &RwLock, + mqtt: &mut Mqtt, known_states: &RwLock>, ) -> ! { // Give the initial known states a chance to be fetched @@ -39,9 +39,8 @@ pub(super) async fn handle( .await; }; - let mut mqtt = mqtt.write().await; call_at_least_in = - send_diff_get_timeout(known_states, &mut needed_states, &mut mqtt) + send_diff_get_timeout(known_states, &mut needed_states, mqtt) .await .min(MQTT_MIGHT_BE_DOWN_TIMEOUT); } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index 35c246c1..f34667de 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -7,9 +7,8 @@ use serde_json::json; use tracing::{instrument, trace, warn}; use crate::lights::lamp; -use crate::LIGHTS; -use super::{TIME_IT_TAKES_TO_APPLY_CHANGE, TO_SUBSCRIBE}; +use super::TIME_IT_TAKES_TO_APPLY_CHANGE; pub(super) struct Mqtt { client: AsyncClient, @@ -28,19 +27,10 @@ impl Mqtt { } } - pub(super) async fn subscribe_to_all(&self) { - for topic in TO_SUBSCRIBE { - self.subscribe(topic).await.unwrap(); - } - for light in LIGHTS { - self.subscribe(&format!("zigbee2mqtt/{light}")) - .await - .unwrap(); - self.request_state(light).await; - } - } - - async fn subscribe(&self, topic: &str) -> Result<(), ClientError> { + pub(super) async fn subscribe( + &self, + topic: &str, + ) -> Result<(), ClientError> { // Its okay for messages to arrive twice or more. MQTT guarantees // ordering and we only do something if the cached bridge indicates we // need to so light states arriving twice is not an issue. diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 71edd2be..2e58252e 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -6,7 +6,6 @@ use itertools::Itertools; use ratelimited_logger::RateLimitedLogger; use rumqttc::v5::{Event, EventLoop, Incoming}; use serde_json::Value; -use tokio::sync::Mutex; use tokio::{sync::RwLock, time::sleep}; use tracing::{instrument, trace, warn}; @@ -14,11 +13,8 @@ use crate::lights::kelvin_to_mired; use crate::lights::lamp::{self, Lamp}; use crate::lights::parse_state::parse_lamp_properties; -use super::mqtt::Mqtt; - pub(super) async fn poll_mqtt( mut eventloop: EventLoop, - mqtt: &RwLock, known_states: &RwLock>, ) -> ! { let mut logger = RateLimitedLogger::default(); @@ -52,11 +48,6 @@ pub(super) async fn poll_mqtt( update_model(known_states, light_name, model).await; } } - Message::ConnAck => { - warn!("Received ConnAck, resubscribing"); - let mqtt = mqtt.read().await; - mqtt.subscribe_to_all().await; - } Message::Other => (), } } @@ -104,10 +95,8 @@ fn parse_message(event: Event) -> color_eyre::Result { return Ok(Message::Other); }; - let message = match incoming { - Incoming::Publish(message) => message, - Incoming::ConnAck(_) => return Ok(Message::ConnAck), - _ => return Ok(Message::Other), + let Incoming::Publish(message) = incoming else { + return Ok(Message::Other); }; trace!("message: {message:?}"); @@ -171,7 +160,6 @@ fn parse_log_message( enum Message { StateUpdate((String, Vec)), Devices(HashMap), - ConnAck, Other, } From 7b7ac8a7b26c57d3da30151a56298335ad6f95c1 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 24 Nov 2024 11:57:17 +0100 Subject: [PATCH 434/687] Hardcode model Working with the retained devices list was just too painful --- crates/zigbee-bridge/src/lib.rs | 22 ++--- crates/zigbee-bridge/src/lights.rs | 1 + .../zigbee-bridge/src/lights/cached_bridge.rs | 3 +- .../src/lights/cached_bridge/changes.rs | 16 ++-- .../src/lights/cached_bridge/poll.rs | 87 ++----------------- crates/zigbee-bridge/src/lights/lamp.rs | 51 +++++------ crates/zigbee-bridge/src/lights/lamp/model.rs | 15 ++++ 7 files changed, 66 insertions(+), 129 deletions(-) diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 32ed4a9f..b5d78d9e 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -4,16 +4,18 @@ // Set to on, off after 30s // on_time: 30, off_wait_time: 30 +use lights::Model; + pub mod lights; const MQTT_IP: &str = "192.168.1.43"; const MQTT_PORT: u16 = 1883; -const LIGHTS: [&str; 5] = [ - "kitchen:fridge", - "kitchen:hallway", - "kitchen:hood_left", - "kitchen:hood_right", - "kitchen:ceiling", +const LIGHTS: [(&str, Model); 5] = [ + ("kitchen:fridge", Model::TradfriE14), + ("kitchen:hallway", Model::TradfriE27), + ("kitchen:hood_left", Model::TradfriCandle), + ("kitchen:hood_right", Model::TradfriCandle), + ("kitchen:ceiling", Model::HueGen4), ]; #[cfg(test)] @@ -29,7 +31,7 @@ mod tests { let controller = Controller::start_bridge(); println!("Setting to on, 2200"); - for light in LIGHTS { + for (light, _) in LIGHTS { controller.set_on(light); controller.set_color_temp(light, 2200); } @@ -37,14 +39,14 @@ mod tests { tokio::time::sleep(Duration::from_secs(1)).await; println!("Turning off"); - for light in LIGHTS { + for (light, _) in LIGHTS { controller.set_off(light); } tokio::time::sleep(Duration::from_secs(1)).await; println!("Turning on to 4000"); - for light in LIGHTS { + for (light, _) in LIGHTS { controller.set_on(light); controller.set_color_temp(light, 4000); } @@ -52,7 +54,7 @@ mod tests { tokio::time::sleep(Duration::from_secs(1)).await; println!("Setting bri to 1.0"); - for light in LIGHTS { + for (light, _) in LIGHTS { controller.set_brightness(light, 1.0); } diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index d1eb07e4..e842eac3 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -6,6 +6,7 @@ use tracing::trace; pub use conversion::{ denormalize, kelvin_to_mired, mired_to_kelvin, normalize, }; +pub(crate) use lamp::Model; mod cached_bridge; mod conversion; diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 08da6e22..0b484f55 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -33,9 +33,8 @@ pub(super) async fn run( AsyncClient::new(options.clone(), channel_capacity); let mut mqtt = Mqtt::new(client); - mqtt.subscribe("zigbee2mqtt/bridge/devices").await.unwrap(); mqtt.subscribe("zigbee2mqtt/bridge/logging").await.unwrap(); - for light in LIGHTS { + for (light, _) in LIGHTS { mqtt.subscribe(&format!("zigbee2mqtt/{light}")) .await .unwrap(); diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index c6fca67b..fd915f14 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -60,7 +60,7 @@ async fn send_diff_get_timeout( let known_states = known_states.read().await; let mut light_deadlines = Vec::new(); - for light_name in LIGHTS { + for (light_name, _) in LIGHTS { tracing::Span::current().record("light_name", light_name); // if there is no needed state, we ignore this light @@ -95,17 +95,15 @@ async fn apply_change_to_needed( ) { let known_states = known_states.read().await; - let default = Lamp::default(); - let known = known_states.get(&light_name).unwrap_or(&default); + let known = known_states + .get(&light_name) + .map(|l| l.to_owned()) + .unwrap_or_else(|| Lamp::new(&light_name)); let mut needed = match needed_states.get(&light_name) { - // make sure needed has the model if known has it - Some(needed) => needed.clone().add_model_from(&known), - None => known.clone(), + Some(needed) => needed.clone(), + None => known, }; needed.apply(change); - // if light_name == "kitchen:fridge" { - // warn!("New (fridge) needed state model: {:?}", needed.model); - // } needed_states.insert(light_name, needed); } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 2e58252e..2ce84fec 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -1,8 +1,7 @@ use std::{collections::HashMap, time::Duration}; -use color_eyre::eyre::{Context, ContextCompat, OptionExt}; +use color_eyre::eyre::{Context, OptionExt}; use color_eyre::Section; -use itertools::Itertools; use ratelimited_logger::RateLimitedLogger; use rumqttc::v5::{Event, EventLoop, Incoming}; use serde_json::Value; @@ -39,43 +38,23 @@ pub(super) async fn poll_mqtt( match message { Message::StateUpdate((light_name, changed_properties)) => { - update_state(known_states, light_name, changed_properties) + update_state(known_states, &light_name, changed_properties) .await; } - Message::Devices(new_devices) => { - warn!("Received devices list"); - for (light_name, model) in new_devices { - update_model(known_states, light_name, model).await; - } - } Message::Other => (), } } } -async fn update_model( - known_states: &RwLock>, - light_name: String, - model: lamp::Model, -) { - let mut known_states = known_states.write().await; - let current_lamp = known_states.entry(light_name.to_string()).or_default(); - if light_name == "kitchen:fridge" { - warn!( - "Received model update for fridge lamp,\nold: {:?},\nnew: {model:?}", - current_lamp.model - ); - } - current_lamp.set_model(model); -} - async fn update_state( known_states: &RwLock>, - light_name: String, + light_name: &str, new: Vec, ) { let mut known_states = known_states.write().await; - let current_lamp = known_states.entry(light_name.to_string()).or_default(); + let current_lamp = known_states + .entry(light_name.to_owned()) + .or_insert_with(|| Lamp::new(light_name)); for property in new { if let lamp::Property::ColorTempK(temp) = property { if light_name == "kitchen:fridge" { @@ -103,26 +82,6 @@ fn parse_message(event: Event) -> color_eyre::Result { let topic: &str = &String::from_utf8_lossy(&message.topic); match topic { - "zigbee2mqtt/bridge/devices" => { - warn!("ZB received devices message"); - let json: Value = serde_json::from_slice(&message.payload) - .wrap_err("could not parse message payload as json")?; - warn!("contents: {json:#?}"); - let list = json - .as_array() - .ok_or_eyre("devices list should be array its not") - .with_note(|| format!("json was: {json:?}"))?; - let devices: HashMap = list - .iter() - .map(|dev| { - parse_device(dev) - .wrap_err("could not parse device") - .with_note(|| format!("device: {dev:?}")) - }) - .filter_ok(|d| d.0 != "Coordinator") - .collect::>()?; - Ok(Message::Devices(devices)) - } "zigbee2mqtt/bridge/logging" => { let json: Value = serde_json::from_slice(&message.payload) .wrap_err("could not parse message payload as json")?; @@ -159,39 +118,5 @@ fn parse_log_message( #[derive(Debug)] enum Message { StateUpdate((String, Vec)), - Devices(HashMap), Other, } - -#[instrument(skip_all)] -fn parse_device(device: &Value) -> color_eyre::Result<(String, lamp::Model)> { - let properties = device - .as_object() - .wrap_err("device should be json object")?; - - let friendly_name = properties - .get("friendly_name") - .wrap_err("device misses key `friendly_name`")? - .as_str() - .wrap_err("value of `friendly_name` is not a string")? - .to_owned(); - let model_id = properties - .get("model_id") - .map(Value::as_str) - .map(|res| res.ok_or_eyre("value of `model_id` is not a string")) - .transpose()?; - - let model = match model_id { - Some("TRADFRI bulb E14 WS candle 470lm") => lamp::Model::TradfriCandle, - Some("TRADFRI bulb E27 CWS globe 806lm") => lamp::Model::TradfriE27, - Some("TRADFRI bulb E14 CWS globe 806lm") => lamp::Model::TradfriE14, - Some("LCT001") => lamp::Model::HueGen4, - Some(id) if id.to_lowercase().contains("tradfri") => { - lamp::Model::TradfriOther(id.to_owned()) - } - Some(id) => lamp::Model::Other(id.to_owned()), - None => lamp::Model::Other(String::new()), - }; - - Ok((friendly_name, model)) -} diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index 6115606b..c4008c45 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -1,4 +1,4 @@ -pub(super) use model::Model; +pub(crate) use model::Model; pub(super) use property::{Property, PropertyDiscriminants}; use self::property::{bri_is_close, color_is_close}; @@ -22,10 +22,10 @@ impl Color { } // TODO: some way to enforce read-only (thus known-updatable-only) fields? -#[derive(Default, Clone, Debug)] +#[derive(Clone, Debug)] pub(super) struct Lamp { - // TODO: remove after debugging - pub(super) model: Option, + name: String, + model: Model, is_online: Option, brightness: Option, color: Option, @@ -34,6 +34,18 @@ pub(super) struct Lamp { } impl Lamp { + pub(super) fn new(name: &str) -> Self { + Self { + name: name.to_owned(), + model: Model::from_light(name), + is_online: None, + brightness: None, + color: None, + is_on: None, + color_temp_startup: property::ColorTempStartup::default(), + } + } + #[instrument] pub(super) fn changes_relative_to(&self, other: &Self) -> Vec { let mut res = Vec::new(); @@ -90,22 +102,18 @@ impl Lamp { Property::Brightness(bri) => self.brightness = Some(bri), Property::ColorTempK(temp) => { // if we know the model, we know how to apply temp - if let Some(model) = &self.model { - if model.supports_xy() { - self.color = Some(Color::xy_from_temp(temp)); - } else { - let range = model.temp_k_range(); - let temp = temp.clamp(range.start, range.end); - self.color = Some(Color::TempK(temp)) - } + if self.model.supports_xy() { + self.color = Some(Color::xy_from_temp(temp)); + } else { + let range = self.model.temp_k_range(); + let temp = temp.clamp(range.start, range.end); + self.color = Some(Color::TempK(temp)) } } Property::ColorXY(xy) => { // don't apply xy to unknown or non-color lamp - if let Some(model) = &self.model { - if model.supports_xy() { - self.color = Some(Color::XY(xy)) - } + if self.model.supports_xy() { + self.color = Some(Color::XY(xy)) } } Property::ColorTempStartup(behaviour) => { @@ -135,15 +143,4 @@ impl Lamp { list.push(Property::ColorTempStartup((&self).color_temp_startup)); list } - - pub(crate) fn add_model_from(mut self, other: &Lamp) -> Self { - if let Some(model) = &other.model { - self.model = Some(model.clone()); - } - self - } - - pub(crate) fn set_model(&mut self, model: Model) { - self.model = Some(model); - } } diff --git a/crates/zigbee-bridge/src/lights/lamp/model.rs b/crates/zigbee-bridge/src/lights/lamp/model.rs index fad0d92f..4d168e24 100644 --- a/crates/zigbee-bridge/src/lights/lamp/model.rs +++ b/crates/zigbee-bridge/src/lights/lamp/model.rs @@ -1,5 +1,9 @@ use std::{collections::HashMap, ops::Range}; +use tracing::warn; + +use crate::LIGHTS; + #[derive(Debug, Clone, PartialEq, Eq)] pub(crate) enum Model { TradfriCandle, @@ -13,6 +17,17 @@ pub(crate) enum Model { } impl Model { + pub(super) fn from_light(name: &str) -> Self { + let map = HashMap::from(LIGHTS); + match map.get(name) { + Some(model) => model.clone(), + None => { + warn!("No model known for light {name}"); + Model::Other(String::from("Unknown")) + } + } + } + pub(super) fn supports_xy(&self) -> bool { #[allow(clippy::match_same_arms)] // clearer comment match self { From ee8e2aa8073022a889002d5cfe0b3eed924f8572 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 24 Nov 2024 12:08:34 +0100 Subject: [PATCH 435/687] Reduce iterating over hardcoded light names, cleanup --- crates/zigbee-bridge/src/lib.rs | 26 +++++++------------ .../zigbee-bridge/src/lights/cached_bridge.rs | 4 +-- .../src/lights/cached_bridge/changes.rs | 8 +----- crates/zigbee-bridge/src/lights/lamp.rs | 2 -- crates/zigbee-bridge/src/lights/lamp/model.rs | 5 ++-- 5 files changed, 15 insertions(+), 30 deletions(-) diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index b5d78d9e..992c38b9 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -10,7 +10,7 @@ pub mod lights; const MQTT_IP: &str = "192.168.1.43"; const MQTT_PORT: u16 = 1883; -const LIGHTS: [(&str, Model); 5] = [ +const LIGHT_MODELS: [(&str, Model); 5] = [ ("kitchen:fridge", Model::TradfriE14), ("kitchen:hallway", Model::TradfriE27), ("kitchen:hood_left", Model::TradfriCandle), @@ -20,43 +20,35 @@ const LIGHTS: [(&str, Model); 5] = [ #[cfg(test)] mod tests { - use super::*; use crate::lights::Controller; use std::time::Duration; #[ignore] #[tokio::test] - async fn change_all_lights() { + async fn change_fridge_light() { std::env::set_var("RUST_LOG", "brain=trace,zigbee_bridge=trace,info"); let controller = Controller::start_bridge(); + let light = "kitchen:fridge"; println!("Setting to on, 2200"); - for (light, _) in LIGHTS { - controller.set_on(light); - controller.set_color_temp(light, 2200); - } + controller.set_on(light); + controller.set_color_temp(light, 2200); tokio::time::sleep(Duration::from_secs(1)).await; println!("Turning off"); - for (light, _) in LIGHTS { - controller.set_off(light); - } + controller.set_off(light); tokio::time::sleep(Duration::from_secs(1)).await; println!("Turning on to 4000"); - for (light, _) in LIGHTS { - controller.set_on(light); - controller.set_color_temp(light, 4000); - } + controller.set_on(light); + controller.set_color_temp(light, 4000); tokio::time::sleep(Duration::from_secs(1)).await; println!("Setting bri to 1.0"); - for (light, _) in LIGHTS { - controller.set_brightness(light, 1.0); - } + controller.set_brightness(light, 1.0); let () = std::future::pending().await; unreachable!(); diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 0b484f55..a549db00 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -5,7 +5,7 @@ use tokio::sync::{mpsc, RwLock}; use tracing::trace; use self::mqtt::Mqtt; -use crate::{lights::lamp, LIGHTS, MQTT_IP, MQTT_PORT}; +use crate::{lights::lamp, LIGHT_MODELS, MQTT_IP, MQTT_PORT}; mod changes; mod mqtt; @@ -34,7 +34,7 @@ pub(super) async fn run( let mut mqtt = Mqtt::new(client); mqtt.subscribe("zigbee2mqtt/bridge/logging").await.unwrap(); - for (light, _) in LIGHTS { + for (light, _) in LIGHT_MODELS { mqtt.subscribe(&format!("zigbee2mqtt/{light}")) .await .unwrap(); diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index fd915f14..98435219 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -8,7 +8,6 @@ use tracing::{debug, instrument, trace, warn}; use super::mqtt::Mqtt; use super::{MQTT_MIGHT_BE_DOWN_TIMEOUT, WAIT_FOR_INIT_STATES}; use crate::lights::lamp::{self, Lamp}; -use crate::LIGHTS; pub(super) async fn handle( mut change_receiver: mpsc::UnboundedReceiver<(String, lamp::Property)>, @@ -60,14 +59,9 @@ async fn send_diff_get_timeout( let known_states = known_states.read().await; let mut light_deadlines = Vec::new(); - for (light_name, _) in LIGHTS { + for (light_name, needed) in needed_states { tracing::Span::current().record("light_name", light_name); - // if there is no needed state, we ignore this light - let Some(needed) = needed_states.get(light_name) else { - continue; - }; - let diff = match known_states.get(light_name) { Some(known) => needed.changes_relative_to(known), None => needed.all_as_changes(), diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index c4008c45..c10ff66c 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -24,7 +24,6 @@ impl Color { // TODO: some way to enforce read-only (thus known-updatable-only) fields? #[derive(Clone, Debug)] pub(super) struct Lamp { - name: String, model: Model, is_online: Option, brightness: Option, @@ -36,7 +35,6 @@ pub(super) struct Lamp { impl Lamp { pub(super) fn new(name: &str) -> Self { Self { - name: name.to_owned(), model: Model::from_light(name), is_online: None, brightness: None, diff --git a/crates/zigbee-bridge/src/lights/lamp/model.rs b/crates/zigbee-bridge/src/lights/lamp/model.rs index 4d168e24..711bfbfb 100644 --- a/crates/zigbee-bridge/src/lights/lamp/model.rs +++ b/crates/zigbee-bridge/src/lights/lamp/model.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, ops::Range}; use tracing::warn; -use crate::LIGHTS; +use crate::LIGHT_MODELS; #[derive(Debug, Clone, PartialEq, Eq)] pub(crate) enum Model { @@ -10,6 +10,7 @@ pub(crate) enum Model { TradfriE27, TradfriE14, HueGen4, + #[allow(unused)] TradfriOther(String), #[allow(unused)] HueOther(String), @@ -18,7 +19,7 @@ pub(crate) enum Model { impl Model { pub(super) fn from_light(name: &str) -> Self { - let map = HashMap::from(LIGHTS); + let map = HashMap::from(LIGHT_MODELS); match map.get(name) { Some(model) => model.clone(), None => { From 4a33fb936a13a89d8074596e1c01cd25d95e106b Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 24 Nov 2024 12:36:05 +0100 Subject: [PATCH 436/687] Parse z2m publish error to Online state update --- Cargo.lock | 1 + crates/zigbee-bridge/Cargo.toml | 1 + .../src/lights/cached_bridge/poll.rs | 30 +++++++++++++++---- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c328bcc8..94efd00b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4289,6 +4289,7 @@ dependencies = [ "futures-concurrency", "itertools", "ratelimited-logger", + "regex", "rumqttc", "serde_json", "strum", diff --git a/crates/zigbee-bridge/Cargo.toml b/crates/zigbee-bridge/Cargo.toml index 8bfd8810..eb87f1eb 100644 --- a/crates/zigbee-bridge/Cargo.toml +++ b/crates/zigbee-bridge/Cargo.toml @@ -21,3 +21,4 @@ strum = { version = "0.26.3", features = ["derive"] } ratelimited-logger = { workspace = true } color-eyre.workspace = true itertools = "0.13.0" +regex = "1.11.1" diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 2ce84fec..c94c5931 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -3,6 +3,7 @@ use std::{collections::HashMap, time::Duration}; use color_eyre::eyre::{Context, OptionExt}; use color_eyre::Section; use ratelimited_logger::RateLimitedLogger; +use regex::Regex; use rumqttc::v5::{Event, EventLoop, Incoming}; use serde_json::Value; use tokio::{sync::RwLock, time::sleep}; @@ -89,8 +90,7 @@ fn parse_message(event: Event) -> color_eyre::Result { .as_object() .ok_or_eyre("log should be map it is not") .with_note(|| format!("json was: {json:?}"))?; - // parse_log_message(log) - Ok(Message::Other) + parse_log_message(log) } topic => { let topic: Vec<_> = topic.split('/').collect(); @@ -107,12 +107,30 @@ fn parse_log_message( log: &serde_json::Map, ) -> color_eyre::Result { let level = log.get("level").ok_or_eyre("no level in log message")?; - let message = log.get("message").ok_or_eyre("no message in log message")?; + let message = log + .get("message") + .ok_or_eyre("no message in log message")? + .as_str() + .ok_or_eyre("log message is not a string")?; + + if level != "error" { + return Ok(Message::Other); + } + + let regex = + Regex::new(r"Publish.*? to '(.*?)' failed.*?MAC no ack").unwrap(); + if level == "error" { - todo!() - } else { - Ok(Message::Other) + if let Some(caps) = regex.captures(message) { + let light_name = caps[1].to_string(); + return Ok(Message::StateUpdate(( + light_name, + vec![lamp::Property::Online(false)], + ))); + } } + + Ok(Message::Other) } #[derive(Debug)] From a1fe16eac507e6cce545e4c998518183f0969b82 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 24 Nov 2024 13:01:54 +0100 Subject: [PATCH 437/687] Parse bridge events to Online state updates --- .../zigbee-bridge/src/lights/cached_bridge.rs | 1 + .../src/lights/cached_bridge/poll.rs | 47 +++++++++++++++++-- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index a549db00..9930679c 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -34,6 +34,7 @@ pub(super) async fn run( let mut mqtt = Mqtt::new(client); mqtt.subscribe("zigbee2mqtt/bridge/logging").await.unwrap(); + mqtt.subscribe("zigbee2mqtt/bridge/event").await.unwrap(); for (light, _) in LIGHT_MODELS { mqtt.subscribe(&format!("zigbee2mqtt/{light}")) .await diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index c94c5931..767bea7a 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -83,6 +83,15 @@ fn parse_message(event: Event) -> color_eyre::Result { let topic: &str = &String::from_utf8_lossy(&message.topic); match topic { + "zigbee2mqtt/bridge/event" => { + let json: Value = serde_json::from_slice(&message.payload) + .wrap_err("could not parse message payload as json")?; + let bridge_event = json + .as_object() + .ok_or_eyre("log should be map it is not") + .with_note(|| format!("json was: {json:?}"))?; + dbg!(parse_bridge_event(bridge_event)) + } "zigbee2mqtt/bridge/logging" => { let json: Value = serde_json::from_slice(&message.payload) .wrap_err("could not parse message payload as json")?; @@ -90,7 +99,7 @@ fn parse_message(event: Event) -> color_eyre::Result { .as_object() .ok_or_eyre("log should be map it is not") .with_note(|| format!("json was: {json:?}"))?; - parse_log_message(log) + dbg!(parse_log_message(log)) } topic => { let topic: Vec<_> = topic.split('/').collect(); @@ -103,6 +112,36 @@ fn parse_message(event: Event) -> color_eyre::Result { } } +fn parse_bridge_event( + payload: &serde_json::Map, +) -> color_eyre::Result { + let event = payload + .get("type") + .ok_or_eyre("no type in bridge event")? + .as_str() + .ok_or_eyre("bridge event type is not a string")?; + let data = payload + .get("data") + .ok_or_eyre("no data in bridge event")? + .as_object() + .ok_or_eyre("bridge event data is not a map")?; + let light_name = data + .get("friendly_name") + .ok_or_eyre("no name in bridge event data")? + .as_str() + .ok_or_eyre("bridge event friendly name is not a string")? + .to_owned(); + + let is_online = match event { + "device_joined" | "device_announce" => true, + "device_leave" => false, + _ => return Ok(Message::Other), + }; + + let update = (light_name, vec![lamp::Property::Online(is_online)]); + Ok(Message::StateUpdate(update)) +} + fn parse_log_message( log: &serde_json::Map, ) -> color_eyre::Result { @@ -123,10 +162,8 @@ fn parse_log_message( if level == "error" { if let Some(caps) = regex.captures(message) { let light_name = caps[1].to_string(); - return Ok(Message::StateUpdate(( - light_name, - vec![lamp::Property::Online(false)], - ))); + let update = (light_name, vec![lamp::Property::Online(false)]); + return Ok(Message::StateUpdate(update)); } } From b751a428c8f358f1018b16328ce98cc70c280d20 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 24 Nov 2024 13:13:10 +0100 Subject: [PATCH 438/687] Only send diff when lamp is online --- .../zigbee-bridge/src/lights/cached_bridge/changes.rs | 11 ++++++++++- crates/zigbee-bridge/src/lights/lamp.rs | 7 ++++--- crates/zigbee-bridge/src/lights/parse_state.rs | 5 +++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index 98435219..cd5f7646 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -67,7 +67,16 @@ async fn send_diff_get_timeout( None => needed.all_as_changes(), }; - let _ = mqtt.send_diff_where_due(light_name, &diff).await; + let is_online = match known_states.get(light_name) { + Some(known) => known.is_online, + // we assume the lamp is online so that init messages get sent + None => true, + }; + + if is_online { + let _ = mqtt.send_diff_where_due(light_name, &diff).await; + } + if let Some(deadline) = mqtt.next_deadline(light_name, &diff) { light_deadlines.push(deadline); } diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index c10ff66c..a4120001 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -25,7 +25,7 @@ impl Color { #[derive(Clone, Debug)] pub(super) struct Lamp { model: Model, - is_online: Option, + pub(super) is_online: bool, brightness: Option, color: Option, is_on: Option, @@ -36,7 +36,8 @@ impl Lamp { pub(super) fn new(name: &str) -> Self { Self { model: Model::from_light(name), - is_online: None, + // we assume the lamp is online so that init messages get sent + is_online: true, brightness: None, color: None, is_on: None, @@ -117,7 +118,7 @@ impl Lamp { Property::ColorTempStartup(behaviour) => { self.color_temp_startup = behaviour } - Property::Online(is_online) => self.is_online = Some(is_online), + Property::Online(is_online) => self.is_online = is_online, } } diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs index 02d49472..22312a42 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -68,8 +68,9 @@ pub(super) fn parse_lamp_properties( list.push(lamp::Property::On(on)); } - // TODO: startup behavior? <14-11-24, dvdsk> - // + // we have just received a state message, so the lamp must be online + list.push(lamp::Property::Online(true)); + Ok(list) } From 1468dfce0298e19da561b51a99943c7c0d5aa250 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 24 Nov 2024 13:39:31 +0100 Subject: [PATCH 439/687] Add logging for Online state --- .../zigbee-bridge/src/lights/cached_bridge/poll.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 767bea7a..d39774d2 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -90,7 +90,7 @@ fn parse_message(event: Event) -> color_eyre::Result { .as_object() .ok_or_eyre("log should be map it is not") .with_note(|| format!("json was: {json:?}"))?; - dbg!(parse_bridge_event(bridge_event)) + parse_bridge_event(bridge_event) } "zigbee2mqtt/bridge/logging" => { let json: Value = serde_json::from_slice(&message.payload) @@ -99,7 +99,7 @@ fn parse_message(event: Event) -> color_eyre::Result { .as_object() .ok_or_eyre("log should be map it is not") .with_note(|| format!("json was: {json:?}"))?; - dbg!(parse_log_message(log)) + parse_log_message(log) } topic => { let topic: Vec<_> = topic.split('/').collect(); @@ -137,6 +137,9 @@ fn parse_bridge_event( "device_leave" => false, _ => return Ok(Message::Other), }; + if light_name == "kitchen:fridge" { + warn!("Fridge online: {is_online}"); + } let update = (light_name, vec![lamp::Property::Online(is_online)]); Ok(Message::StateUpdate(update)) @@ -157,11 +160,14 @@ fn parse_log_message( } let regex = - Regex::new(r"Publish.*? to '(.*?)' failed.*?MAC no ack").unwrap(); + Regex::new(r"Publish.*? to '(.*?)' failed").unwrap(); if level == "error" { if let Some(caps) = regex.captures(message) { let light_name = caps[1].to_string(); + if light_name == "kitchen:fridge" { + warn!("Fridge is Offline"); + } let update = (light_name, vec![lamp::Property::Online(false)]); return Ok(Message::StateUpdate(update)); } From 8a5013b423498cbf2436ce36e29b8d52717dd65d Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 26 Nov 2024 13:13:54 +0100 Subject: [PATCH 440/687] Fix resend timeout and set kitchen to normal settings --- crates/brain/src/controller/rooms/kitchen.rs | 4 ++-- crates/zigbee-bridge/src/lights/cached_bridge.rs | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index bac97ae8..eba54e54 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -83,8 +83,8 @@ pub async fn run( } async fn update(system: &mut RestrictedSystem) { - // let (new_ct, new_bri) = small_bedroom::optimal_ct_bri(); - let (new_ct, new_bri) = _testing_ct_bri(); + let (new_ct, new_bri) = small_bedroom::optimal_ct_bri(); + // let (new_ct, new_bri) = _testing_ct_bri(); system.all_lamps_ct(new_ct, new_bri).await; tracing::trace!("updated lamps"); } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 9930679c..f38c86d3 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -13,7 +13,9 @@ mod poll; const MQTT_MIGHT_BE_DOWN_TIMEOUT: Duration = Duration::from_secs(500); const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); -const TIME_IT_TAKES_TO_APPLY_CHANGE: Duration = Duration::from_secs(1); +// unfortunately we have to use the zigbee-herdsman timeout to prevent +// the z2m queue from getting filled up +const TIME_IT_TAKES_TO_APPLY_CHANGE: Duration = Duration::from_secs(10); pub(super) async fn run( change_receiver: mpsc::UnboundedReceiver<(String, lamp::Property)>, From 2925367c5723b59546af4038ab3bc7c268e41bd3 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 26 Nov 2024 13:26:38 +0100 Subject: [PATCH 441/687] Clean up ZB logs --- crates/brain/src/controller/mod.rs | 7 ----- .../src/lights/cached_bridge/poll.rs | 29 ++++++++++--------- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 8ca91e87..7f4faf92 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -42,13 +42,6 @@ impl RestrictedSystem { self.system.lights.set_ct(name, bri, ct).await.unwrap(); } - let now = local_now(); - if !&self.allowed_lights_new.is_empty() - && now.minute() == 0 - && now.second() <= 9 - { - warn!("B sending changes to ZB (every 5s from now): ct = {ct}"); - } for name in &self.allowed_lights_new { self.system .lights_new diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index d39774d2..3033c5e3 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -57,13 +57,21 @@ async fn update_state( .entry(light_name.to_owned()) .or_insert_with(|| Lamp::new(light_name)); for property in new { - if let lamp::Property::ColorTempK(temp) = property { - if light_name == "kitchen:fridge" { - warn!( - "ZB received fridge color temp change: {}", - kelvin_to_mired(temp) - ); + match property { + lamp::Property::ColorTempK(temp) => { + if light_name == "kitchen:fridge" { + warn!( + "ZB received fridge color temp change: {}", + kelvin_to_mired(temp) + ); + } } + lamp::Property::Online(new_online) => { + if new_online != current_lamp.is_online { + warn!("ZB received fridge online change: {new_online}"); + } + } + _ => (), } current_lamp.apply(property); } @@ -137,9 +145,6 @@ fn parse_bridge_event( "device_leave" => false, _ => return Ok(Message::Other), }; - if light_name == "kitchen:fridge" { - warn!("Fridge online: {is_online}"); - } let update = (light_name, vec![lamp::Property::Online(is_online)]); Ok(Message::StateUpdate(update)) @@ -159,15 +164,11 @@ fn parse_log_message( return Ok(Message::Other); } - let regex = - Regex::new(r"Publish.*? to '(.*?)' failed").unwrap(); + let regex = Regex::new(r"Publish.*? to '(.*?)' failed").unwrap(); if level == "error" { if let Some(caps) = regex.captures(message) { let light_name = caps[1].to_string(); - if light_name == "kitchen:fridge" { - warn!("Fridge is Offline"); - } let update = (light_name, vec![lamp::Property::Online(false)]); return Ok(Message::StateUpdate(update)); } From 64d5e9c637072309aeb606324e1512d7871f42ae Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 26 Nov 2024 14:10:41 +0100 Subject: [PATCH 442/687] Change time match SB to work with minutes --- .../src/controller/rooms/small_bedroom.rs | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 07befa09..7cef01ef 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -86,23 +86,28 @@ async fn update(system: &mut RestrictedSystem) { system.all_lamps_ct(new_ct, new_bri).await; } +const fn time(hour: u8, minute: u8) -> f64 { + hour as f64 + minute as f64 / 60. +} + pub(crate) fn optimal_ct_bri() -> (u16, u8) { let now = local_now(); - let (temp, bri) = match now.hour() { - 9..17 => (3500, 1.0), - 17..20 => (3000, 1.0), - 20..22 => (2500, 0.85), - 22.. | 0..9 => (2000, 0.4), + const T0_00: f64 = time(0, 0); + const T8_00: f64 = time(8, 0); + const T9_00: f64 = time(9, 0); + const T17_00: f64 = time(17, 0); + const T20_30: f64 = time(20, 30); + const T21_30: f64 = time(21, 30); + const T22_00: f64 = time(22, 0); + + let (temp, bri) = match time(now.hour(), now.minute()) { + T8_00..T9_00 => (1500, 0.5), + T9_00..T17_00 => (3500, 1.0), + T17_00..T20_30 => (2500, 1.0), + T20_30..T21_30 => (2000, 0.8), + T21_30..T22_00 => (1500, 0.5), + T22_00.. | T0_00..T8_00 => (1000, 0.1), + _ => (2500, 1.0), }; (kelvin_to_mired(temp).try_into().unwrap(), denormalize(bri)) } - -// fn handle_event(e: RelevantEvent) { -// use protocol::large_bedroom::DeskButton as D; -// use RelevantEvent as R; -// -// match e { -// R::DeskButton(D::OneOfFour(p)) if p.is_long() => todo!(), -// unhandled => warn!("Unhandled button: {unhandled:?}"), -// } -// } From e4183b68bde3445b04bc94ede013ffb87193ff81 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 26 Nov 2024 14:10:56 +0100 Subject: [PATCH 443/687] Add basic logic to SB for light button processing --- .../src/controller/rooms/small_bedroom.rs | 59 ++++++++++++------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 7cef01ef..285e0fee 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -2,6 +2,8 @@ use std::time::Duration; use futures_concurrency::future::Race; use futures_util::FutureExt; +use protocol::small_bedroom::ButtonPanel; +use protocol::{small_bedroom, Reading}; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; use zigbee_bridge::lights::{denormalize, kelvin_to_mired}; @@ -40,17 +42,22 @@ impl RecvFiltered for broadcast::Receiver { #[derive(Debug)] enum RelevantEvent { - // DeskButton(protocol::large_bedroom::DeskButton), + Button(ButtonPanel), } -fn filter(_event: Event) -> Option { - // match event { - // // Event::Sensor(SensorValue::ButtonPress(Button::LargeBedroomDesk(desk))) => { - // // Some(RelevantEvent::DeskButton(desk)) - // // } - // _ => None, - // } - None +fn event_filter(event: Event) -> Option { + match event { + Event::Sensor(Reading::SmallBedroom( + small_bedroom::Reading::ButtonPanel(button), + )) => Some(RelevantEvent::Button(button)), + _ => None, + } +} + +#[derive(Debug)] +enum Trigger { + Event(RelevantEvent), + ShouldUpdate, } pub async fn run( @@ -59,21 +66,20 @@ pub async fn run( _event_tx: broadcast::Sender, mut system: RestrictedSystem, ) { - enum Res { - Event(RelevantEvent), - ShouldUpdate, - } - let _state = State::Normal; let mut next_update = Instant::now() + INTERVAL; loop { - let get_event = event_rx.recv_filter_mapped(filter).map(Res::Event); - let tick = sleep_until(next_update).map(|_| Res::ShouldUpdate); + let get_event = event_rx + .recv_filter_mapped(event_filter) + .map(Trigger::Event); + let tick = sleep_until(next_update).map(|_| Trigger::ShouldUpdate); - let res = (get_event, tick).race().await; - match res { - Res::Event(_) => (), //handle_event(e), - Res::ShouldUpdate => { + let trigger = (get_event, tick).race().await; + match trigger { + Trigger::Event(RelevantEvent::Button(button)) => { + handle_buttonpress(&mut system, button).await; + } + Trigger::ShouldUpdate => { update(&mut system).await; next_update = Instant::now() + INTERVAL; } @@ -81,6 +87,19 @@ pub async fn run( } } +async fn handle_buttonpress( + system: &mut RestrictedSystem, + button: ButtonPanel, +) { + dbg!(&button); + match button { + ButtonPanel::BottomLeft(_) => system.all_lamps_off().await, + ButtonPanel::BottomMiddle(_) => system.all_lamps_on().await, + ButtonPanel::BOttomRight(_) => system.all_lamps_ct(2000, 254).await, + _ => (), + } +} + async fn update(system: &mut RestrictedSystem) { let (new_ct, new_bri) = optimal_ct_bri(); system.all_lamps_ct(new_ct, new_bri).await; From 36f7083421e32c4d5e9e6ffbcadef4b1c6181f94 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Wed, 27 Nov 2024 12:23:55 +0100 Subject: [PATCH 444/687] Make color less extreme and switch log to ceiling --- crates/brain/src/controller/rooms/small_bedroom.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 285e0fee..c3915cbb 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -120,13 +120,13 @@ pub(crate) fn optimal_ct_bri() -> (u16, u8) { const T22_00: f64 = time(22, 0); let (temp, bri) = match time(now.hour(), now.minute()) { - T8_00..T9_00 => (1500, 0.5), + T8_00..T9_00 => (2000, 0.5), T9_00..T17_00 => (3500, 1.0), - T17_00..T20_30 => (2500, 1.0), - T20_30..T21_30 => (2000, 0.8), - T21_30..T22_00 => (1500, 0.5), - T22_00.. | T0_00..T8_00 => (1000, 0.1), - _ => (2500, 1.0), + T17_00..T20_30 => (2300, 1.0), + T20_30..T21_30 => (2000, 0.7), + T21_30..T22_00 => (1900, 0.4), + T22_00.. | T0_00..T8_00 => (1800, 0.1), + _ => (2300, 1.0), }; (kelvin_to_mired(temp).try_into().unwrap(), denormalize(bri)) } From e3ed86caf7987729fe06525d9b1784a4b2175b6d Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 27 Nov 2024 14:35:39 +0100 Subject: [PATCH 445/687] overhauls logger, not done just changing method at this moment and need the state saved --- crates/logger/Cargo.toml | 16 +++ crates/logger/examples/log.rs | 43 ++++++ crates/logger/src/lib.rs | 2 + crates/logger/src/ratelimited.rs | 223 +++++++++++++++++++++++++++++++ crates/logger/src/tracing.rs | 87 ++++++++++++ 5 files changed, 371 insertions(+) create mode 100644 crates/logger/Cargo.toml create mode 100644 crates/logger/examples/log.rs create mode 100644 crates/logger/src/lib.rs create mode 100644 crates/logger/src/ratelimited.rs create mode 100644 crates/logger/src/tracing.rs diff --git a/crates/logger/Cargo.toml b/crates/logger/Cargo.toml new file mode 100644 index 00000000..2ff605db --- /dev/null +++ b/crates/logger/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "logger" +version = "0.1.0" +rust-version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true + +[dependencies] +tracing = { workspace = true } +tracing-error = { workspace = true } +tracing-subscriber = { workspace = true, features = ["env-filter"] } +tracing-journald = "0.3" +libsystemd = "0.7" +governor = "0.6.3" +tracing-core = "0.1.32" diff --git a/crates/logger/examples/log.rs b/crates/logger/examples/log.rs new file mode 100644 index 00000000..201e4eb7 --- /dev/null +++ b/crates/logger/examples/log.rs @@ -0,0 +1,43 @@ +use std::thread; +use std::time::Duration; + +use tracing::field::FieldSet; +use tracing::{Level, Metadata}; +use tracing_core::callsite::DefaultCallsite; + +// use logger::{ratelimited::Logger, warn}; +// +// fn main() { +// logger::tracing::setup(); +// +// let mut logger = Logger::default().with_per_msg_period(Duration::from_millis(800)); +// +// for i in 0..10 { +// warn!(logger; "constant message always the same"); +// warn!(logger; "oh no the number is: {}", i); +// thread::sleep(Duration::from_millis(100)); +// } +// } + +fn main() { + logger::tracing::setup(); + + tracing::info!("works"); + let callsite = DefaultCallsite + let fields = FieldSet::new(names, callsite) + let meta = Metadata::new("test", "test", Level::INFO, None, None, None, FieldSet::new + tracing::Event::dispatch(DefaultCallsite::new, kind)) + + + static META: $crate::Metadata<'static> = { + $crate::metadata! { + name: $name, + target: $target, + level: $lvl, + fields: $crate::fieldset!( $($fields)* ), + callsite: &__CALLSITE, + kind: $kind, + } + }; + $crate::callsite::DefaultCallsite::new(&META) +} diff --git a/crates/logger/src/lib.rs b/crates/logger/src/lib.rs new file mode 100644 index 00000000..8846840a --- /dev/null +++ b/crates/logger/src/lib.rs @@ -0,0 +1,2 @@ +pub mod ratelimited; +pub mod tracing; diff --git a/crates/logger/src/ratelimited.rs b/crates/logger/src/ratelimited.rs new file mode 100644 index 00000000..729697fd --- /dev/null +++ b/crates/logger/src/ratelimited.rs @@ -0,0 +1,223 @@ +use governor::clock::DefaultClock; +use governor::middleware::NoOpMiddleware; +use governor::state::InMemoryState; +use governor::state::NotKeyed; +use governor::Quota; +use governor::RateLimiter; +use std::collections::HashMap; +use std::collections::HashSet; +use std::num::NonZero; +use std::num::NonZeroU32; +use std::sync::Mutex; +use std::time::Duration; +use tracing::field::Visit; +use tracing::Metadata; +use tracing::Subscriber; +use tracing_core::callsite; +use tracing_core::span; +use tracing_core::Interest; +use tracing_subscriber::layer::Context; + +struct Message { + limiter: RateLimiter, + supressed: usize, +} + +struct LogMsgHash(u64); +struct CallSite { + limiter: RateLimiter, + supressed: usize, + msg_limited: HashMap, +} + +#[derive(Debug, Hash, PartialEq, Eq)] +struct Key { + callsite: callsite::Identifier, +} + +impl Key { + fn from_meta(meta: &Metadata<'_>) -> Key { + Key { + callsite: meta.callsite(), + } + } +} + +struct Inner { + pub callsite: HashMap, + pub callsite_by_span_id: HashMap, + pub global: CallSite, +} + +fn span_quota() -> Quota { + Quota::per_second(NonZero::new(1).unwrap()).allow_burst(NonZero::new(10).unwrap()) +} + +fn message_quota() -> Quota { + Quota::per_second(NonZero::new(1).unwrap()).allow_burst(NonZero::new(10).unwrap()) +} + +fn global_quota() -> Quota { + Quota::per_second(NonZero::new(1).unwrap()).allow_burst(NonZero::new(10).unwrap()) +} + +impl Inner { + /// Should this be filtered? Determined by the work of on_record + fn enabled(&mut self, meta: &Metadata<'_>) -> bool { + } + + fn on_record(&mut self, span_id: &span::Id, values: &span::Record<'_>) { + let callsite_id = self + .callsite_by_span_id + .get(span_id) + .expect("on_new_span handler should run before on_record"); + let callsite = self + .callsite + .entry(callsite_id.clone()) + .or_insert(CallSite { + limiter: RateLimiter::direct(span_quota()), + withheld: 0, + msg_limited: HashMap::new(), + }); + + if callsite.limiter.check().is_err() { + callsite.supressed += 1; + return + } + + let mut visitor = Visitor { + hash: LogMsgHash(0), // placeholder + }; + values.record(&mut visitor); + } + + pub fn on_new_span(&mut self, attrs: &span::Attributes<'_>, span_id: &span::Id) { + self.callsite_by_span_id + .insert(span_id.clone(), attrs.metadata().callsite()); + } +} + +pub struct Limiter { + inner: Mutex, + // pub msg_rate_limiter: + // RateLimiter, DefaultClock, NoOpMiddleware>, + // pub global_rate_limiter: + // pub was_withheld: HashSet, + // pub withheld: usize, +} + +impl tracing_subscriber::layer::Filter for Limiter { + /// Returns `true` if this layer is interested in a span or event with the + /// given [`Metadata`] in the current [`Context`], similarly to + /// [`Subscriber::enabled`]. + /// + /// If this returns `false`, the span or event will be disabled _for the + /// wrapped [`Layer`]_. Unlike [`Layer::enabled`], the span or event will + /// still be recorded if any _other_ layers choose to enable it. However, + /// the layer [filtered] by this filter will skip recording that span or + /// event. + /// + /// If all layers indicate that they do not wish to see this span or event, + /// it will be disabled. + /// + /// [`metadata`]: tracing_core::Metadata + /// [`Subscriber::enabled`]: tracing_core::Subscriber::enabled + /// [filtered]: crate::filter::Filtered + fn enabled(&self, meta: &Metadata<'_>, _: &Context<'_, S>) -> bool { + self.inner.lock().unwrap().enabled(meta) + } + + /// uses visitor pattern (sorry, tracing uses it so we must ...) + /// derived from tracing-subscriber EnvFilter::on_record + /// -> span.record_update + /// -> record.record + /// -> m.visitor() + /// -> impl<'a> Visit for MatchVisitor + fn on_record(&self, id: &span::Id, values: &span::Record<'_>, _: Context<'_, S>) { + self.inner.lock().unwrap().on_record(id, values) + } + + fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, _: Context<'_, S>) { + self.inner.lock().unwrap().on_new_span(attrs, id); + } + + fn callsite_enabled(&self, _: &'static Metadata<'static>) -> Interest { + Interest::sometimes() + } +} + +struct Visitor { + hash: LogMsgHash, +} + +impl Visit for Visitor { + fn record_debug(&mut self, _field: &tracing_core::Field, value: &dyn std::fmt::Debug) { + self.hash = debug_hash(&value) + } +} + +// adapted from tracing-subscriber/src/filter/env.field.rs +// by Tokio Contributors +fn debug_hash(debug: &impl std::fmt::Debug) -> LogMsgHash { + // Naively, we would probably hash a value's `fmt::Debug` output by + // formatting it to a string, and then calculating the stings hash This + // would however require allocating every time we want to hash a field + // value + // + // Instead, we implement `fmt::Write` for a type that, rather than + // actually _writing_ the strings to something, hashes them. + use std::fmt; + use std::fmt::Write; + use std::hash::DefaultHasher; + use std::hash::Hasher; + + struct FmtHasher { + hash_state: DefaultHasher, + } + + impl fmt::Write for FmtHasher { + fn write_str(&mut self, s: &str) -> fmt::Result { + for byte in s.bytes() { + self.hash_state.write_u8(byte); + } + Ok(()) + } + } + let mut hasher = FmtHasher { hash_state: DefaultHasher::new() }; + + // Try to "write" the value's `fmt::Debug` output to a `Matcher`. This + // returns an error if the `fmt::Debug` implementation wrote any + // characters that did not match the expected pattern. + write!(hasher, "{:?}", debug).is_ok(); + LogMsgHash(hasher.hash_state.finish()) +} + +impl Default for Limiter { + fn default() -> Self { + let per_msg_quota = Quota::with_period(Duration::from_secs(5)) + .unwrap() + .allow_burst(NonZeroU32::new(5).unwrap()); + let global_quota = Quota::with_period(Duration::from_secs(1)) + .unwrap() + .allow_burst(NonZeroU32::new(25).unwrap()); + Self { + msg_rate_limiter: RateLimiter::keyed(per_msg_quota), + global_rate_limiter: RateLimiter::direct(global_quota), + was_withheld: HashSet::, + } + } +} + +impl Limiter { + pub fn with_per_msg_period(self, one_msg_per: Duration) -> Self { + let quota = Quota::with_period(one_msg_per) + .unwrap() + .allow_burst(NonZeroU32::new(5).unwrap()); + Self { + msg_rate_limiter: RateLimiter::keyed(quota), + global_rate_limiter: self.global_rate_limiter, + withheld: self.withheld, + was_withheld: self.was_withheld, + } + } +} diff --git a/crates/logger/src/tracing.rs b/crates/logger/src/tracing.rs new file mode 100644 index 00000000..39613ce2 --- /dev/null +++ b/crates/logger/src/tracing.rs @@ -0,0 +1,87 @@ +use tracing::level_filters::LevelFilter; +use tracing_subscriber::registry::LookupSpan; + +/// # WARNING +/// part of the filter syntax is broken (sad) +/// see: https://github.com/tokio-rs/tracing/issues/1181 +/// +/// ## what does work +/// Filter directives like: `crate::module::submodule=trace,crate::module=info,error` +/// which logs everything in `submodule`, in `module` things are logged at level +/// info, warn or error and for the rest of the crate and all dependencies only +/// errors are logged +/// +/// ## what should work but only does so sporadically +/// Filter directives allowing you to match field values (values recorded by for +/// example `#[instrument]`), +/// +/// their syntax: +/// RUST_LOG=target[span{field=value}]=level +/// +/// field value will be interpreted as regular expressions if it cannot be interpreted as +/// bool, i64, u64, or f64 literal. Regex syntax follows the regex crate. +/// +/// ### Example: +/// run something like this with: RUST_LOG='[shave{yak=2}]' and it should only +/// print the trace message once +/// ```rust +/// #[tracing::instrument] +/// pub fn shave(yak: usize) { +/// tracing::trace!("I am going to shave a yak :)") +/// } +/// +/// fn main() { +/// shave(1); +/// shave(2); +/// shave(3); +/// } +/// ``` +/// +/// for full docs see: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html +pub fn setup() { + use tracing_error::ErrorLayer; + use tracing_subscriber::filter; + use tracing_subscriber::fmt; + use tracing_subscriber::util::SubscriberInitExt; + use tracing_subscriber::{self, layer::SubscriberExt}; + + let filter = filter::EnvFilter::builder() + .with_regex(true) + .try_from_env() + .unwrap_or_else(|_| { + filter::EnvFilter::builder() + .with_default_directive(LevelFilter::INFO.into()) + .parse_lossy("") + }); + + let fmt = fmt::layer() + .pretty() + .with_writer(std::io::stderr) // to stderr as to not disrupt TUI's + .with_file(true) + .with_line_number(true) + .with_target(false) + .with_ansi(true); + + let registry = tracing_subscriber::registry() + .register_filter() + .with(filter) + .with(ErrorLayer::default()); + if libsystemd::logging::connected_to_journal() { + match tracing_journald::layer() { + Ok(journal) => { + registry.with(journal).init(); + tracing::info!("Started logging & tracing to journald"); + } + Err(err) => { + registry.with(fmt).init(); + tracing::error!( + "Could not log to journald directly. Logging to stderr \ + as fallback. Error connecting to journald:: {err}" + ); + } + }; + } else { + registry.with(fmt).init(); + tracing::info!("Started logging & tracing to stderr"); + } +} From 3d1246138c3c422acee72e550f35abfd7a4b0b47 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 27 Nov 2024 18:11:45 +0100 Subject: [PATCH 446/687] tracing ratelimiter implemented in Filter::event_enabled --- Cargo.lock | 131 ++++++++++++++++++ crates/logger/examples/log.rs | 55 ++++---- crates/logger/src/ratelimited.rs | 228 ++++++++++++++++++------------- crates/logger/src/tracing.rs | 24 ++-- 4 files changed, 312 insertions(+), 126 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e965cc62..e4e9d9ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -435,6 +435,15 @@ dependencies = [ "serde", ] +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "blocking" version = "1.6.1" @@ -749,6 +758,15 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "cpufeatures" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.4.2" @@ -813,6 +831,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "dashmap" version = "5.5.3" @@ -971,6 +999,17 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab03c107fafeb3ee9f5925686dbb7a73bc76e3932abb0d2b365cb64b169cf04c" +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + [[package]] name = "dirs" version = "5.0.1" @@ -1437,6 +1476,16 @@ dependencies = [ "windows", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "gethostname" version = "0.5.0" @@ -1658,6 +1707,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "http" version = "1.1.0" @@ -2101,6 +2159,24 @@ dependencies = [ "libc", ] +[[package]] +name = "libsystemd" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c592dc396b464005f78a5853555b9f240bc5378bf5221acc4e129910b2678869" +dependencies = [ + "hmac", + "libc", + "log", + "nix 0.27.1", + "nom", + "once_cell", + "serde", + "sha2", + "thiserror", + "uuid", +] + [[package]] name = "linux-embedded-hal" version = "0.4.0" @@ -2180,6 +2256,19 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "logger" +version = "0.1.0" +dependencies = [ + "governor", + "libsystemd", + "tracing", + "tracing-core", + "tracing-error", + "tracing-journald", + "tracing-subscriber", +] + [[package]] name = "loom" version = "0.5.6" @@ -2303,6 +2392,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.17" @@ -2416,6 +2514,7 @@ dependencies = [ "bitflags 2.6.0", "cfg-if 1.0.0", "libc", + "memoffset 0.9.1", ] [[package]] @@ -3278,6 +3377,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -3463,6 +3573,12 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "1.0.109" @@ -3810,6 +3926,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "tz-rs" version = "0.6.14" @@ -3932,6 +4054,15 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +dependencies = [ + "serde", +] + [[package]] name = "valuable" version = "0.1.0" diff --git a/crates/logger/examples/log.rs b/crates/logger/examples/log.rs index 201e4eb7..79f5a43f 100644 --- a/crates/logger/examples/log.rs +++ b/crates/logger/examples/log.rs @@ -1,10 +1,3 @@ -use std::thread; -use std::time::Duration; - -use tracing::field::FieldSet; -use tracing::{Level, Metadata}; -use tracing_core::callsite::DefaultCallsite; - // use logger::{ratelimited::Logger, warn}; // // fn main() { @@ -19,25 +12,37 @@ use tracing_core::callsite::DefaultCallsite; // } // } +use std::time::Duration; + +fn log_a() { + tracing::info!("a"); +} + +fn log_b() { + tracing::info!("b"); +} + +fn log_c() { + tracing::info!("c"); +} + + fn main() { logger::tracing::setup(); - tracing::info!("works"); - let callsite = DefaultCallsite - let fields = FieldSet::new(names, callsite) - let meta = Metadata::new("test", "test", Level::INFO, None, None, None, FieldSet::new - tracing::Event::dispatch(DefaultCallsite::new, kind)) - - - static META: $crate::Metadata<'static> = { - $crate::metadata! { - name: $name, - target: $target, - level: $lvl, - fields: $crate::fieldset!( $($fields)* ), - callsite: &__CALLSITE, - kind: $kind, - } - }; - $crate::callsite::DefaultCallsite::new(&META) + // functions otherwise the callsite will be different + log_a(); + log_a(); + log_a(); + log_b(); + log_a(); + log_b(); + log_a(); + log_c(); + log_a(); + + std::thread::sleep(Duration::from_secs(2)); + log_a(); + log_b(); + log_c(); } diff --git a/crates/logger/src/ratelimited.rs b/crates/logger/src/ratelimited.rs index 729697fd..dd96a913 100644 --- a/crates/logger/src/ratelimited.rs +++ b/crates/logger/src/ratelimited.rs @@ -5,105 +5,127 @@ use governor::state::NotKeyed; use governor::Quota; use governor::RateLimiter; use std::collections::HashMap; -use std::collections::HashSet; use std::num::NonZero; -use std::num::NonZeroU32; use std::sync::Mutex; use std::time::Duration; use tracing::field::Visit; +use tracing::Event; use tracing::Metadata; use tracing::Subscriber; use tracing_core::callsite; -use tracing_core::span; use tracing_core::Interest; use tracing_subscriber::layer::Context; -struct Message { +struct LimitState { limiter: RateLimiter, supressed: usize, } +impl LimitState { + fn new(quota: Quota) -> Self { + Self { + limiter: RateLimiter::direct(quota), + supressed: 0, + } + } +} +#[derive(Debug, PartialEq, Eq, Hash)] struct LogMsgHash(u64); struct CallSite { - limiter: RateLimiter, - supressed: usize, - msg_limited: HashMap, -} - -#[derive(Debug, Hash, PartialEq, Eq)] -struct Key { - callsite: callsite::Identifier, -} - -impl Key { - fn from_meta(meta: &Metadata<'_>) -> Key { - Key { - callsite: meta.callsite(), - } - } + state: LimitState, + msg: HashMap, } struct Inner { pub callsite: HashMap, - pub callsite_by_span_id: HashMap, - pub global: CallSite, -} - -fn span_quota() -> Quota { - Quota::per_second(NonZero::new(1).unwrap()).allow_burst(NonZero::new(10).unwrap()) -} - -fn message_quota() -> Quota { - Quota::per_second(NonZero::new(1).unwrap()).allow_burst(NonZero::new(10).unwrap()) -} - -fn global_quota() -> Quota { - Quota::per_second(NonZero::new(1).unwrap()).allow_burst(NonZero::new(10).unwrap()) + pub global: LimitState, } impl Inner { - /// Should this be filtered? Determined by the work of on_record - fn enabled(&mut self, meta: &Metadata<'_>) -> bool { - } + fn event_enabled(&mut self, event: &Event<'_>, quoti: &Quoti) -> bool { + if self.global.limiter.check().is_err() { + self.global.supressed += 1; + } else if self.global.supressed > 0 { + eprintln!( + "Logs are being ratelimitted, supressed {} messages", + self.global.supressed + ); + self.global.supressed = 0; + } - fn on_record(&mut self, span_id: &span::Id, values: &span::Record<'_>) { - let callsite_id = self - .callsite_by_span_id - .get(span_id) - .expect("on_new_span handler should run before on_record"); let callsite = self .callsite - .entry(callsite_id.clone()) + .entry(event.metadata().callsite().clone()) .or_insert(CallSite { - limiter: RateLimiter::direct(span_quota()), - withheld: 0, - msg_limited: HashMap::new(), + state: LimitState { + limiter: RateLimiter::direct(quoti.callsite), + supressed: 0, + }, + msg: HashMap::new(), }); - if callsite.limiter.check().is_err() { - callsite.supressed += 1; - return + if callsite.state.limiter.check().is_err() { + callsite.state.supressed += 1; + return false; + } else if callsite.state.supressed > 0 { + eprintln!( + "Logs from this callsite are ratelimitted, \ + supressed {} messages", + callsite.state.supressed + ); + callsite.state.supressed = 0; } let mut visitor = Visitor { hash: LogMsgHash(0), // placeholder }; - values.record(&mut visitor); + event.record(&mut visitor); + let msg = callsite + .msg + .entry(visitor.hash) + .or_insert_with(|| LimitState { + limiter: RateLimiter::direct(quoti.msg), + supressed: 0, + }); + + if msg.limiter.check().is_err() { + msg.supressed += 1; + false + } else if msg.supressed > 0 { + eprintln!( + "Logs with this exact message are ratelimitted, \ + supressed {} messages", + msg.supressed + ); + msg.supressed = 0; + true + } else { + true + } } +} + +struct Quoti { + global: Quota, + callsite: Quota, + msg: Quota, +} - pub fn on_new_span(&mut self, attrs: &span::Attributes<'_>, span_id: &span::Id) { - self.callsite_by_span_id - .insert(span_id.clone(), attrs.metadata().callsite()); +impl Default for Quoti { + fn default() -> Self { + Self { + global: Quota::per_second(NonZero::new(9).unwrap()) + .allow_burst(NonZero::new(9).unwrap()), + callsite: Quota::per_second(NonZero::new(6).unwrap()) + .allow_burst(NonZero::new(6).unwrap()), + msg: Quota::per_second(NonZero::new(1).unwrap()).allow_burst(NonZero::new(1).unwrap()), + } } } pub struct Limiter { inner: Mutex, - // pub msg_rate_limiter: - // RateLimiter, DefaultClock, NoOpMiddleware>, - // pub global_rate_limiter: - // pub was_withheld: HashSet, - // pub withheld: usize, + quoti: Quoti, } impl tracing_subscriber::layer::Filter for Limiter { @@ -123,22 +145,13 @@ impl tracing_subscriber::layer::Filter for Limiter { /// [`metadata`]: tracing_core::Metadata /// [`Subscriber::enabled`]: tracing_core::Subscriber::enabled /// [filtered]: crate::filter::Filtered - fn enabled(&self, meta: &Metadata<'_>, _: &Context<'_, S>) -> bool { - self.inner.lock().unwrap().enabled(meta) - } - - /// uses visitor pattern (sorry, tracing uses it so we must ...) - /// derived from tracing-subscriber EnvFilter::on_record - /// -> span.record_update - /// -> record.record - /// -> m.visitor() - /// -> impl<'a> Visit for MatchVisitor - fn on_record(&self, id: &span::Id, values: &span::Record<'_>, _: Context<'_, S>) { - self.inner.lock().unwrap().on_record(id, values) + fn enabled(&self, _: &Metadata<'_>, _: &Context<'_, S>) -> bool { + // all filtering is done based on event_enabled + true } - fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, _: Context<'_, S>) { - self.inner.lock().unwrap().on_new_span(attrs, id); + fn event_enabled(&self, event: &Event<'_>, _: &Context<'_, S>) -> bool { + self.inner.lock().unwrap().event_enabled(event, &self.quoti) } fn callsite_enabled(&self, _: &'static Metadata<'static>) -> Interest { @@ -183,41 +196,72 @@ fn debug_hash(debug: &impl std::fmt::Debug) -> LogMsgHash { Ok(()) } } - let mut hasher = FmtHasher { hash_state: DefaultHasher::new() }; + let mut hasher = FmtHasher { + hash_state: DefaultHasher::new(), + }; // Try to "write" the value's `fmt::Debug` output to a `Matcher`. This // returns an error if the `fmt::Debug` implementation wrote any // characters that did not match the expected pattern. - write!(hasher, "{:?}", debug).is_ok(); + write!(hasher, "{:?}", debug).expect("hashing can not go wrong"); LogMsgHash(hasher.hash_state.finish()) } impl Default for Limiter { fn default() -> Self { - let per_msg_quota = Quota::with_period(Duration::from_secs(5)) - .unwrap() - .allow_burst(NonZeroU32::new(5).unwrap()); - let global_quota = Quota::with_period(Duration::from_secs(1)) - .unwrap() - .allow_burst(NonZeroU32::new(25).unwrap()); Self { - msg_rate_limiter: RateLimiter::keyed(per_msg_quota), - global_rate_limiter: RateLimiter::direct(global_quota), - was_withheld: HashSet::, + inner: Mutex::new(Inner { + callsite: HashMap::new(), + global: LimitState::new(Quoti::default().global), + }), + quoti: Quoti::default(), } } } impl Limiter { - pub fn with_per_msg_period(self, one_msg_per: Duration) -> Self { - let quota = Quota::with_period(one_msg_per) - .unwrap() - .allow_burst(NonZeroU32::new(5).unwrap()); - Self { - msg_rate_limiter: RateLimiter::keyed(quota), - global_rate_limiter: self.global_rate_limiter, - withheld: self.withheld, - was_withheld: self.was_withheld, + pub fn with_global_period(mut self, one_log_per: Duration) -> Self { + self.quoti.global = Quota::with_period(one_log_per) + .expect("duration may not be zero") + .allow_burst(self.quoti.global.burst_size()); + + { + let mut inner = self.inner.lock().unwrap(); + inner.global.limiter = RateLimiter::direct(self.quoti.global) } + + self + } + pub fn with_callsite_period(mut self, one_callsite_log_per: Duration) -> Self { + self.quoti.callsite = Quota::with_period(one_callsite_log_per) + .expect("duration may not be zero") + .allow_burst(self.quoti.callsite.burst_size()); + + { + let mut inner = self.inner.lock().unwrap(); + for CallSite { state, .. } in inner.callsite.values_mut() { + state.limiter = RateLimiter::direct(self.quoti.callsite) + } + } + + self + } + pub fn with_msg_period(mut self, one_msg_per: Duration) -> Self { + self.quoti.msg = Quota::with_period(one_msg_per) + .expect("duration may not be zero") + .allow_burst(self.quoti.msg.burst_size()); + + { + let mut inner = self.inner.lock().unwrap(); + for msg_state in inner + .callsite + .values_mut() + .flat_map(|CallSite { msg, .. }| msg.values_mut()) + { + msg_state.limiter = RateLimiter::direct(self.quoti.msg) + } + } + + self } } diff --git a/crates/logger/src/tracing.rs b/crates/logger/src/tracing.rs index 39613ce2..0f6946ab 100644 --- a/crates/logger/src/tracing.rs +++ b/crates/logger/src/tracing.rs @@ -1,5 +1,6 @@ use tracing::level_filters::LevelFilter; -use tracing_subscriber::registry::LookupSpan; + +use crate::ratelimited; /// # WARNING /// part of the filter syntax is broken (sad) @@ -45,7 +46,7 @@ pub fn setup() { use tracing_subscriber::util::SubscriberInitExt; use tracing_subscriber::{self, layer::SubscriberExt}; - let filter = filter::EnvFilter::builder() + let env_filter = filter::EnvFilter::builder() .with_regex(true) .try_from_env() .unwrap_or_else(|_| { @@ -54,6 +55,8 @@ pub fn setup() { .parse_lossy("") }); + let ratelimiter = ratelimited::Limiter::default(); + let fmt = fmt::layer() .pretty() .with_writer(std::io::stderr) // to stderr as to not disrupt TUI's @@ -62,18 +65,21 @@ pub fn setup() { .with_target(false) .with_ansi(true); - let registry = tracing_subscriber::registry() - .register_filter() - .with(filter) - .with(ErrorLayer::default()); + let registry = tracing_subscriber::Registry::default().with(ErrorLayer::default()); + use tracing_subscriber::Layer; + if libsystemd::logging::connected_to_journal() { match tracing_journald::layer() { Ok(journal) => { - registry.with(journal).init(); + registry + .with(journal.with_filter(ratelimiter).with_filter(env_filter)) + .init(); tracing::info!("Started logging & tracing to journald"); } Err(err) => { - registry.with(fmt).init(); + registry + .with(fmt.with_filter(ratelimiter).with_filter(env_filter)) + .init(); tracing::error!( "Could not log to journald directly. Logging to stderr \ as fallback. Error connecting to journald:: {err}" @@ -81,7 +87,7 @@ pub fn setup() { } }; } else { - registry.with(fmt).init(); + registry.with(fmt.with_filter(ratelimiter).with_filter(env_filter)).init(); tracing::info!("Started logging & tracing to stderr"); } } From c9cb6f02ac1e409d107b3a1aeba221ed4ae2b1f3 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 27 Nov 2024 18:25:19 +0100 Subject: [PATCH 447/687] fix warnings --- crates/brain/src/controller/mod.rs | 1 - crates/zigbee-bridge/src/lights/cached_bridge/changes.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 7f4faf92..171311e1 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -6,7 +6,6 @@ use serde::{Deserialize, Serialize}; use time::{OffsetDateTime, UtcOffset}; use tokio::sync::broadcast; use tokio::task::JoinSet; -use tracing::warn; use zigbee_bridge::lights::{mired_to_kelvin, normalize}; // now_local works some of the time only... this replaces it with....... diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index cd5f7646..ca92c0a8 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -3,7 +3,7 @@ use std::time::{Duration, Instant}; use tokio::sync::{mpsc, RwLock}; use tokio::time::{sleep, timeout}; -use tracing::{debug, instrument, trace, warn}; +use tracing::{debug, instrument, trace}; use super::mqtt::Mqtt; use super::{MQTT_MIGHT_BE_DOWN_TIMEOUT, WAIT_FOR_INIT_STATES}; From be59d6ff213658ecb3fd7294828d21e5c69ca777 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 27 Nov 2024 18:26:16 +0100 Subject: [PATCH 448/687] finish merge --- crates/ratelimited-logger/Cargo.toml | 13 ---- crates/ratelimited-logger/examples/log.rs | 24 ------- crates/ratelimited-logger/src/lib.rs | 87 ----------------------- 3 files changed, 124 deletions(-) delete mode 100644 crates/ratelimited-logger/Cargo.toml delete mode 100644 crates/ratelimited-logger/examples/log.rs delete mode 100644 crates/ratelimited-logger/src/lib.rs diff --git a/crates/ratelimited-logger/Cargo.toml b/crates/ratelimited-logger/Cargo.toml deleted file mode 100644 index 8cb70372..00000000 --- a/crates/ratelimited-logger/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "ratelimited-logger" -version = "0.1.0" -rust-version.workspace = true -edition.workspace = true -license.workspace = true -authors.workspace = true - -[dependencies] -tracing = { workspace = true } -tracing-error = { workspace = true } -tracing-subscriber = { workspace = true, features = ["env-filter"] } -governor = "0.6.3" diff --git a/crates/ratelimited-logger/examples/log.rs b/crates/ratelimited-logger/examples/log.rs deleted file mode 100644 index 10e463d1..00000000 --- a/crates/ratelimited-logger/examples/log.rs +++ /dev/null @@ -1,24 +0,0 @@ -use ratelimited_logger::{warn, RateLimitedLogger}; - -fn main() { - setup_tracing(); - let mut logger = RateLimitedLogger::default(); - - warn!(logger; "oh no the number is: {}", 5); -} - -fn setup_tracing() { - use tracing_error::ErrorLayer; - use tracing_subscriber::filter; -use tracing_subscriber::util::SubscriberInitExt; - use tracing_subscriber::{self, layer::SubscriberExt, Layer}; - - let subscriber = tracing_subscriber::fmt::layer() - .with_line_number(true) - .with_target(true) - .with_filter(filter::LevelFilter::INFO); - tracing_subscriber::registry() - .with(subscriber) - .with(ErrorLayer::default()) - .init(); -} diff --git a/crates/ratelimited-logger/src/lib.rs b/crates/ratelimited-logger/src/lib.rs deleted file mode 100644 index aca52b45..00000000 --- a/crates/ratelimited-logger/src/lib.rs +++ /dev/null @@ -1,87 +0,0 @@ -use governor::clock::DefaultClock; -use governor::middleware::NoOpMiddleware; -use governor::state::keyed::DefaultKeyedStateStore; -use governor::state::InMemoryState; -use governor::state::NotKeyed; -use governor::Quota; -use governor::RateLimiter; -use std::num::NonZeroU32; -use std::time::Duration; - -pub struct RateLimitedLogger { - pub msg_rate_limiter: - RateLimiter, DefaultClock, NoOpMiddleware>, - pub global_rate_limiter: RateLimiter, - pub withheld: usize, -} - -#[macro_export] -macro_rules! warn { - ($limiter:ident; $($arg:tt)*) => { - { // scope so msg cannot interfere with locals with same name - let msg = format!($($arg)*); - if $limiter.global_rate_limiter.check().is_err() { - $limiter.withheld += 1; - } else if $limiter.msg_rate_limiter.check_key(&msg).is_err() { - $limiter.withheld += 1; - } else { - if $limiter.withheld > 0 { - tracing::warn!("Logs are being spammed, withheld {} copies of this msg", $limiter.withheld); - $limiter.withheld = 0; - } - - tracing::warn!("{msg}"); - } - } - }; -} - -#[macro_export] -macro_rules! info { - ($limiter:ident; $($arg:tt)*) => { - { // scope so msg cannot interfere with locals with same name - let msg = format!($($arg)*); - if $limiter.global_rate_limiter.check().is_err() { - $limiter.withheld += 1; - } else if $limiter.msg_rate_limiter.check_key(&msg).is_err() { - $limiter.withheld += 1; - } else { - if $limiter.withheld > 0 { - tracing::info!("Logs are being spammed, withheld {} copies of this msgs", $limiter.withheld); - $limiter.withheld = 0; - } - - tracing::info!("{msg}"); - } - } - }; -} - -impl Default for RateLimitedLogger { - fn default() -> Self { - let per_msg_quota = Quota::with_period(Duration::from_secs(5)) - .unwrap() - .allow_burst(NonZeroU32::new(5).unwrap()); - let global_quota = Quota::with_period(Duration::from_secs(1)) - .unwrap() - .allow_burst(NonZeroU32::new(25).unwrap()); - Self { - msg_rate_limiter: RateLimiter::keyed(per_msg_quota), - global_rate_limiter: RateLimiter::direct(global_quota), - withheld: 0, - } - } -} - -impl RateLimitedLogger { - pub fn with_per_msg_period(self, one_msg_per: Duration) -> Self { - let quota = Quota::with_period(one_msg_per) - .unwrap() - .allow_burst(NonZeroU32::new(5).unwrap()); - Self { - msg_rate_limiter: RateLimiter::keyed(quota), - global_rate_limiter: self.global_rate_limiter, - withheld: self.withheld, - } - } -} From f8b45c7cede0bc2f325ee91b3ae4ea5015297989 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 27 Nov 2024 18:32:08 +0100 Subject: [PATCH 449/687] removing ratelimited_logger object --- Cargo.lock | 18 ++----- Cargo.toml | 2 +- crates/desk-sensors/Cargo.toml | 2 +- crates/desk-sensors/src/main.rs | 23 +-------- crates/rpc/Cargo.toml | 2 +- crates/rpc/src/server.rs | 49 ++++++++++++------- crates/usb-bridge/Cargo.toml | 2 +- crates/zigbee-bridge/Cargo.toml | 2 +- .../src/lights/cached_bridge/poll.rs | 5 +- 9 files changed, 44 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 807161a0..ba5f892f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1067,8 +1067,8 @@ dependencies = [ "gpiocdev-embedded-hal", "heapless 0.8.0", "linux-embedded-hal", + "logger", "protocol", - "ratelimited-logger", "tokio", "tracing", "tracing-error", @@ -3196,16 +3196,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "ratelimited-logger" -version = "0.1.0" -dependencies = [ - "governor", - "tracing", - "tracing-error", - "tracing-subscriber", -] - [[package]] name = "raw-cpuid" version = "11.2.0" @@ -3358,7 +3348,7 @@ dependencies = [ "color-eyre", "futures", "governor", - "ratelimited-logger", + "logger", "serde", "thiserror", "tokio", @@ -4226,9 +4216,9 @@ dependencies = [ "color-eyre", "data-server", "heapless 0.8.0", + "logger", "nusb", "protocol", - "ratelimited-logger", "tokio", "tracing", "tracing-error", @@ -4752,7 +4742,7 @@ dependencies = [ "futures", "futures-concurrency", "itertools", - "ratelimited-logger", + "logger", "regex", "rumqttc", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 95c506f5..259630e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ log-store = { path = "crates/log-store" } protocol = { path = "crates/protocol" } zigbee-bridge = { path = "crates/zigbee-bridge" } rpc = { path = "crates/rpc" } -ratelimited-logger = { path = "crates/ratelimited-logger" } +logger = { path = "crates/logger" } byteseries = { git = "https://github.com/dvdsk/byteseries" } diff --git a/crates/desk-sensors/Cargo.toml b/crates/desk-sensors/Cargo.toml index a3c59ce9..48ac7ee2 100644 --- a/crates/desk-sensors/Cargo.toml +++ b/crates/desk-sensors/Cargo.toml @@ -18,7 +18,7 @@ color-eyre = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace =true, features = ["env-filter"] } tracing-error = { workspace = true } -ratelimited-logger = { workspace = true } +logger = { workspace = true } tokio = { workspace = true, features = ["rt", "time", "macros"] } embedded-hal-async = "1.0.0" diff --git a/crates/desk-sensors/src/main.rs b/crates/desk-sensors/src/main.rs index 666aedef..89aa1f1f 100644 --- a/crates/desk-sensors/src/main.rs +++ b/crates/desk-sensors/src/main.rs @@ -2,7 +2,6 @@ use clap::Parser; use color_eyre::eyre::Context; use color_eyre::Result; use data_server::api::data_source::reconnecting::Client; -use ratelimited_logger::RateLimitedLogger; use std::net::SocketAddr; use tokio::sync::mpsc; @@ -30,8 +29,7 @@ async fn main() { color_eyre::install().unwrap(); let cli = Cli::parse(); - setup_tracing().unwrap(); - let mut logger = RateLimitedLogger::default(); + logger::tracing::setup().unwrap(); let (tx, mut rx) = mpsc::channel(100); sensors::start_monitoring(tx.clone(), cli.bedroom); @@ -54,24 +52,7 @@ async fn main() { }; if let Err(e) = res { - ratelimited_logger::warn!(logger; "{e}"); + tracing::warn!("{e}"); } } } - -fn setup_tracing() -> Result<()> { - use tracing_error::ErrorLayer; - use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt, Layer}; - - let file_subscriber = tracing_subscriber::fmt::layer() - .with_file(true) - .with_line_number(true) - .with_target(false) - .with_ansi(false) - .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()); - tracing_subscriber::registry() - .with(file_subscriber) - .with(ErrorLayer::default()) - .init(); - Ok(()) -} diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index 84c96a07..aabcf80e 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -14,7 +14,7 @@ tokio = { workspace = true, features = ["net", "rt", "sync", "time"] } tokio-util = { version = "0.7.11", features = ["codec"] } tracing.workspace = true -ratelimited-logger = { workspace = true } +logger = { workspace = true } serde = { version = "1.0.209", features = ["derive"] } tokio-serde = { version = "0.9.0", features = ["bincode"] } thiserror.workspace = true diff --git a/crates/rpc/src/server.rs b/crates/rpc/src/server.rs index 2be207c1..5852f388 100644 --- a/crates/rpc/src/server.rs +++ b/crates/rpc/src/server.rs @@ -16,7 +16,6 @@ use tokio::pin; use tokio_serde::formats::Bincode; use tokio_util::codec::{Framed, LengthDelimitedCodec}; -use ratelimited_logger::{self as rlog, RateLimitedLogger}; use tracing::{debug, error, instrument}; type Conn = tokio_serde::Framed< @@ -29,7 +28,9 @@ type Conn = tokio_serde::Framed< pub async fn run( port: u16, perform_request: impl Fn(RpcReq, &str) -> PerfFut + Clone + Send + 'static, - sub_handler: Option + Clone + 'static>, + sub_handler: Option< + impl SubscriberHandler + Clone + 'static, + >, ) -> color_eyre::Result<()> where RpcReq: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, @@ -44,26 +45,29 @@ where .await .wrap_err("Could not bind to address") .with_note(|| format!("port: {port}"))?; - let mut logger = RateLimitedLogger::default(); loop { let (socket, source) = match listener.accept().await { Err(e) => { - rlog::warn!(logger; "client could not connect: {e}"); + tracing::warn!("client could not connect: {e}"); continue; } Ok(res) => res, }; let Some((mut conn, name)) = - handshake_and_log::(socket, source, &mut logger).await + handshake_and_log::(socket, source).await else { continue; }; - if let Err(allowed_again) = limiter.check_key(&(source.ip(), name.clone())) { - let allowed_in = allowed_again.wait_time_from(DefaultClock::default().now()); - let _ignore_err = conn.send(crate::Response::TooManyReq { allowed_in }).await; + if let Err(allowed_again) = + limiter.check_key(&(source.ip(), name.clone())) + { + let allowed_in = + allowed_again.wait_time_from(DefaultClock::default().now()); + let _ignore_err = + conn.send(crate::Response::TooManyReq { allowed_in }).await; continue; } @@ -84,7 +88,6 @@ where async fn handshake_and_log( stream: TcpStream, source: SocketAddr, - logger: &mut RateLimitedLogger, ) -> Option<(Conn, String)> where RpcReq: Unpin + Serialize + DeserializeOwned + fmt::Debug + Send + 'static, @@ -96,19 +99,25 @@ where .max_frame_length(super::MAX_PACKAGE_SIZE) .new_codec(), ); - let mut stream: tokio_serde::Framed<_, crate::Request, crate::Response, _> = - tokio_serde::Framed::new(length_delimited, Bincode::default()); + let mut stream: tokio_serde::Framed< + _, + crate::Request, + crate::Response, + _, + > = tokio_serde::Framed::new(length_delimited, Bincode::default()); match stream.try_next().await { Ok(Some(crate::Request::Handshake { client_name })) => { return Some((stream, client_name)); } Ok(Some(other)) => { - rlog::warn!(logger; "client from {source} tried to connected without handshake, it send: {other:?}") + tracing::warn!("client from {source} tried to connected without handshake, it send: {other:?}") + } + Ok(None) => { + tracing::warn!("client from {source} closed connection immediately") } - Ok(None) => rlog::warn!(logger; "client from {source} closed connection immediately"), Err(e) => { - rlog::warn!(logger; "connection or decoding issue while receiving handshake from {source}, error: {e:?}") + tracing::warn!("connection or decoding issue while receiving handshake from {source}, error: {e:?}") } } @@ -146,7 +155,9 @@ async fn handle_client( match request { crate::Request::Rpc(rpc_request) => { let response = perform_request(rpc_request, &client_name).await; - if let Err(e) = conn.send(crate::Response::RpcResponse(response)).await { + if let Err(e) = + conn.send(crate::Response::RpcResponse(response)).await + { error!("Error sending response to client: {e:?}"); return; } @@ -155,7 +166,9 @@ async fn handle_client( if let Some(mut sub_handler) = sub_handler.take() { let stream = sub_handler.setup().await; pin!(stream); - if let Err(e) = conn.send(crate::Response::SubscribeOk).await { + if let Err(e) = + conn.send(crate::Response::SubscribeOk).await + { debug!("Error sending response to client: {e:?}"); return; } @@ -165,7 +178,9 @@ async fn handle_client( .next() .await .expect("subscribe stream should never end"); - if let Err(e) = conn.send(crate::Response::Update(update)).await { + if let Err(e) = + conn.send(crate::Response::Update(update)).await + { debug!("Error sending response to client: {e:?}"); return; } diff --git a/crates/usb-bridge/Cargo.toml b/crates/usb-bridge/Cargo.toml index e9658f22..c1eb389a 100644 --- a/crates/usb-bridge/Cargo.toml +++ b/crates/usb-bridge/Cargo.toml @@ -11,7 +11,7 @@ heapless = "0.8.0" protocol = { workspace = true } data-server = { workspace = true } -ratelimited-logger = { workspace = true } +logger = { workspace = true } tokio = { workspace = true } clap = { workspace = true } diff --git a/crates/zigbee-bridge/Cargo.toml b/crates/zigbee-bridge/Cargo.toml index eb87f1eb..5d3afca2 100644 --- a/crates/zigbee-bridge/Cargo.toml +++ b/crates/zigbee-bridge/Cargo.toml @@ -18,7 +18,7 @@ tokio = { workspace = true, features = ["sync"] } tracing = { workspace = true } futures = "0.3.31" strum = { version = "0.26.3", features = ["derive"] } -ratelimited-logger = { workspace = true } +logger = { workspace = true } color-eyre.workspace = true itertools = "0.13.0" regex = "1.11.1" diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 3033c5e3..fb72ab4b 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -2,7 +2,6 @@ use std::{collections::HashMap, time::Duration}; use color_eyre::eyre::{Context, OptionExt}; use color_eyre::Section; -use ratelimited_logger::RateLimitedLogger; use regex::Regex; use rumqttc::v5::{Event, EventLoop, Incoming}; use serde_json::Value; @@ -17,8 +16,6 @@ pub(super) async fn poll_mqtt( mut eventloop: EventLoop, known_states: &RwLock>, ) -> ! { - let mut logger = RateLimitedLogger::default(); - loop { let message = match eventloop.poll().await { Ok(message) => message, @@ -32,7 +29,7 @@ pub(super) async fn poll_mqtt( let message = match parse_message(message) { Ok(message) => message, Err(err) => { - ratelimited_logger::warn!(logger; "ZB error parsing mqtt message: {err}"); + warn!("ZB error parsing mqtt message: {err}"); continue; } }; From 420ff16a69f5b1403b01798b8f2801fcb57e8643 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 27 Nov 2024 18:49:02 +0100 Subject: [PATCH 450/687] remove last object based ratelimited logger --- Cargo.lock | 12 +++++++---- crates/brain/Cargo.toml | 3 +-- crates/brain/src/main.rs | 37 +++----------------------------- crates/data-server/Cargo.toml | 1 + crates/data-server/src/main.rs | 20 +---------------- crates/data-store/Cargo.toml | 1 + crates/data-store/src/main.rs | 22 +------------------ crates/desk-sensors/src/main.rs | 3 +-- crates/log-store/Cargo.toml | 1 + crates/log-store/src/main.rs | 22 +------------------ crates/sensor-tui/Cargo.toml | 1 + crates/sensor-tui/src/main.rs | 22 +------------------ crates/text-widget/Cargo.toml | 1 + crates/text-widget/src/main.rs | 38 +++++---------------------------- crates/usb-bridge/Cargo.lock | 6 +++--- crates/usb-bridge/src/main.rs | 19 +---------------- crates/usb-bridge/src/usb.rs | 13 +++-------- 17 files changed, 34 insertions(+), 188 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ba5f892f..cdb7f4dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -494,6 +494,7 @@ dependencies = [ "futures-concurrency", "futures-util", "hueclient", + "logger", "mpd", "protocol", "rand", @@ -505,8 +506,6 @@ dependencies = [ "time", "tokio", "tracing", - "tracing-journald", - "tracing-subscriber", "tz-rs", "zigbee-bridge", ] @@ -945,6 +944,7 @@ dependencies = [ "futures", "futures-concurrency", "governor", + "logger", "protocol", "reserve-port", "rpc", @@ -974,6 +974,7 @@ dependencies = [ "futures-concurrency", "hdrhistogram", "jiff", + "logger", "nucleo-matcher", "num", "protocol", @@ -1702,6 +1703,7 @@ dependencies = [ "data-store", "dirs", "gethostname", + "logger", "nucleo-matcher", "promptly", "protocol", @@ -2362,6 +2364,7 @@ dependencies = [ "hdrhistogram", "heapless 0.8.0", "jiff", + "logger", "nucleo-matcher", "num", "protocol", @@ -3478,6 +3481,7 @@ dependencies = [ "itertools", "jiff", "log-store", + "logger", "protocol", "ratatui", "strip-ansi-escapes", @@ -4021,9 +4025,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-attributes", diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 7e3e2c76..8e351e08 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -38,8 +38,7 @@ rand = "0.8" futures-util = "0.3.30" tracing = {workspace = true} -tracing-subscriber = { workspace = true, features = ["env-filter"] } -tracing-journald = "0.3.0" +logger.workspace = true clap = { workspace = true } futures-concurrency = { workspace = true } strum = { version = "0.26.2", default-features = false, features = ["derive"] } diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index ffcef047..667a022a 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -3,8 +3,6 @@ use std::net::{IpAddr, SocketAddr}; use clap::Parser; use tokio::sync::broadcast; -use tracing::warn; - mod controller; mod system; @@ -14,11 +12,11 @@ mod input; #[derive(Parser)] #[command(version, about, long_about=None)] struct Opt { - /// ip address whete to subscribe for updates + /// IP address where to subscribe for updates #[clap(short, long)] data_server: SocketAddr, - /// ip address for mpd server + /// IP address for mpd server #[clap(short, long)] mpd_ip: IpAddr, @@ -34,7 +32,7 @@ struct Opt { #[tokio::main] async fn main() -> Result<(), Box> { - setup_tracing(); + logger::tracing::setup(); let opt = Opt::parse(); let db = sled::Config::default() //651ms @@ -61,32 +59,3 @@ async fn main() -> Result<(), Box> { unreachable!(); } - -pub fn setup_tracing() { - use tracing_subscriber::filter; - use tracing_subscriber::fmt; - use tracing_subscriber::prelude::*; - - let filter = filter::EnvFilter::builder() - .with_regex(true) - .try_from_env() - .unwrap_or_else(|_| { - filter::EnvFilter::builder() - .parse("brain=debug,info") - .unwrap() - }); - - let fmt = fmt::layer() - .pretty() - .with_line_number(true) - .with_test_writer(); - - let registry = tracing_subscriber::registry().with(filter).with(fmt); - match tracing_journald::layer() { - Ok(journal) => registry.with(journal).init(), - Err(err) => { - warn!("Failed to init journald logging, error: {err}"); - registry.init() - } - }; -} diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index 30e4a616..89e92fb8 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -15,6 +15,7 @@ color-eyre = { workspace = true } tracing = { workspace = true } tracing-error = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } +logger = { workspace = true } rpc = { workspace = true } protocol = { workspace = true, features = ["alloc", "thiserror"] } diff --git a/crates/data-server/src/main.rs b/crates/data-server/src/main.rs index 24fee887..1fd6ba29 100644 --- a/crates/data-server/src/main.rs +++ b/crates/data-server/src/main.rs @@ -29,7 +29,7 @@ struct Cli { #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { - setup_tracing(); + logger::tracing::setup(); let Cli { subscribe_addr, @@ -59,21 +59,3 @@ async fn main() -> Result<()> { } } } - -fn setup_tracing() { - use tracing_error::ErrorLayer; - use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt, Layer}; - - color_eyre::install().unwrap(); - - let file_subscriber = tracing_subscriber::fmt::layer() - .with_file(true) - .with_line_number(true) - .with_target(false) - .with_ansi(false) - .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()); - tracing_subscriber::registry() - .with(file_subscriber) - .with(ErrorLayer::default()) - .init(); -} diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index 55386560..9f40fb9c 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -14,6 +14,7 @@ default = ["api", "server"] [dependencies] clap = { workspace = true } color-eyre = { workspace = true } +logger.workspace = true tracing = { workspace = true } tracing-error = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } diff --git a/crates/data-store/src/main.rs b/crates/data-store/src/main.rs index 2af935d9..b0aaa5bf 100644 --- a/crates/data-store/src/main.rs +++ b/crates/data-store/src/main.rs @@ -22,29 +22,9 @@ struct Cli { #[tokio::main] async fn main() -> Result<()> { - setup_tracing().unwrap(); + logger::tracing::setup(); let cli = Cli::parse(); tracing::info!("started data-server, args: {cli:?}"); data_store::server::run(cli.data_server, cli.client_port, &cli.data_dir).await } - -fn setup_tracing() -> Result<()> { - use tracing_error::ErrorLayer; - use tracing_subscriber::filter; - use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt}; - - color_eyre::install().unwrap(); - - let filter = filter::EnvFilter::builder().from_env().unwrap(); - let fmt = tracing_subscriber::fmt::layer() - .pretty() - .with_line_number(true); - - tracing_subscriber::registry() - .with(filter) - .with(fmt) - .with(ErrorLayer::default()) - .init(); - Ok(()) -} diff --git a/crates/desk-sensors/src/main.rs b/crates/desk-sensors/src/main.rs index 89aa1f1f..cb391e06 100644 --- a/crates/desk-sensors/src/main.rs +++ b/crates/desk-sensors/src/main.rs @@ -1,6 +1,5 @@ use clap::Parser; use color_eyre::eyre::Context; -use color_eyre::Result; use data_server::api::data_source::reconnecting::Client; use std::net::SocketAddr; @@ -29,7 +28,7 @@ async fn main() { color_eyre::install().unwrap(); let cli = Cli::parse(); - logger::tracing::setup().unwrap(); + logger::tracing::setup(); let (tx, mut rx) = mpsc::channel(100); sensors::start_monitoring(tx.clone(), cli.bedroom); diff --git a/crates/log-store/Cargo.toml b/crates/log-store/Cargo.toml index a589c539..e5d52bc2 100644 --- a/crates/log-store/Cargo.toml +++ b/crates/log-store/Cargo.toml @@ -14,6 +14,7 @@ default = ["api", "server"] [dependencies] clap = { workspace = true } color-eyre = { workspace = true } +logger = { workspace = true } tracing = { workspace = true } tracing-error = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } diff --git a/crates/log-store/src/main.rs b/crates/log-store/src/main.rs index 7ea76d64..bac872a7 100644 --- a/crates/log-store/src/main.rs +++ b/crates/log-store/src/main.rs @@ -22,29 +22,9 @@ struct Cli { #[tokio::main] async fn main() -> Result<()> { - setup_tracing().unwrap(); + logger::tracing::setup(); let cli = Cli::parse(); tracing::info!("started log-store, args: {cli:?}"); log_store::server::run(cli.data_server, cli.client_port, &cli.log_dir).await } - -fn setup_tracing() -> Result<()> { - use tracing_error::ErrorLayer; - use tracing_subscriber::filter; - use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt}; - - color_eyre::install().unwrap(); - - let filter = filter::EnvFilter::builder().from_env().unwrap(); - let fmt = tracing_subscriber::fmt::layer() - .pretty() - .with_line_number(true); - - tracing_subscriber::registry() - .with(filter) - .with(fmt) - .with(ErrorLayer::default()) - .init(); - Ok(()) -} diff --git a/crates/sensor-tui/Cargo.toml b/crates/sensor-tui/Cargo.toml index 8e2e1dbe..e0e1e646 100644 --- a/crates/sensor-tui/Cargo.toml +++ b/crates/sensor-tui/Cargo.toml @@ -15,6 +15,7 @@ tui-tree-widget = { version = "0.22.0", git = "https://github.com/dvdsk/tui-rs-t clap = { workspace = true } tokio = { workspace = true, features = ["macros"] } +logger = { workspace = true } tracing.workspace = true tracing-error = { workspace = true } tracing-subscriber.workspace = true diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index 53059476..65654ef1 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -34,7 +34,7 @@ struct Cli { #[tokio::main] async fn main() -> Result<()> { - setup_tracing().unwrap(); + logger::tracing::setup(); let Cli { data_server, @@ -65,26 +65,6 @@ async fn main() -> Result<()> { Ok(()) } -fn setup_tracing() -> Result<()> { - use tracing_error::ErrorLayer; - use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt, Layer}; - - color_eyre::install().unwrap(); - - let log_file = std::fs::File::create("log.txt")?; - let file_subscriber = tracing_subscriber::fmt::layer() - .with_file(true) - .with_line_number(true) - .with_writer(log_file) - .with_target(false) - .with_ansi(false) - .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()); - tracing_subscriber::registry() - .with(file_subscriber) - .with(ErrorLayer::default()) - .init(); - Ok(()) -} /// Similar to the `std::dbg!` macro, but generates `tracing` events rather /// than printing to stdout. diff --git a/crates/text-widget/Cargo.toml b/crates/text-widget/Cargo.toml index 005435a9..ac4e2195 100644 --- a/crates/text-widget/Cargo.toml +++ b/crates/text-widget/Cargo.toml @@ -16,6 +16,7 @@ nucleo-matcher = "0.3.1" tokio = { workspace = true} gethostname = "0.5.0" +logger.workspace = true tracing.workspace = true tracing-error.workspace = true tracing-subscriber.workspace = true diff --git a/crates/text-widget/src/main.rs b/crates/text-widget/src/main.rs index e5bafce7..2b4d33fd 100644 --- a/crates/text-widget/src/main.rs +++ b/crates/text-widget/src/main.rs @@ -30,12 +30,10 @@ struct Cli { json: bool, /// String describing the reading. Something like temp can resolve to - /// `large_bedroom desk temperature` + /// `large_bedroom desk temperature`. + /// + /// Run with RUST_LOG=debug to print the resolved string reading: String, - - /// prints the resolved string - #[arg(short, long)] - debug: bool, } async fn wait_for_update(client: &mut ReconnectingSubscribedClient, needed: &Reading) -> Reading { @@ -69,8 +67,9 @@ async fn setup(cli: &Cli, client: &mut ReconnectingSubscribedClient) -> Result

Result<()> { + color_eyre::install().unwrap(); let cli = Cli::parse(); - setup_tracing(cli.debug)?; + logger::tracing::setup(); let mut client = ReconnectingClient::new(cli.server, name()).subscribe(); @@ -115,30 +114,3 @@ fn print(use_json: bool, msg: &str) { println!("{msg}"); } } - -fn setup_tracing(debug: bool) -> Result<()> { - use tracing_error::ErrorLayer; - use tracing_subscriber::filter; - use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt}; - - color_eyre::install().unwrap(); - - let filter = filter::EnvFilter::builder().from_env().unwrap(); - let filter = if debug { - let directive = concat!(env!("CARGO_PKG_NAME"), "=debug").parse()?; - filter.add_directive(directive) - } else { - filter - }; - - let fmt = tracing_subscriber::fmt::layer() - .pretty() - .with_line_number(true); - - tracing_subscriber::registry() - .with(filter) - .with(fmt) - .with(ErrorLayer::default()) - .init(); - Ok(()) -} diff --git a/crates/usb-bridge/Cargo.lock b/crates/usb-bridge/Cargo.lock index 8ce9d5ac..ebc632be 100644 --- a/crates/usb-bridge/Cargo.lock +++ b/crates/usb-bridge/Cargo.lock @@ -761,7 +761,7 @@ dependencies = [ "postcard", "postcard-rpc", "protocol", - "ratelimited-logger", + "ratelimited", "schema", "tokio", "tracing", @@ -1229,7 +1229,7 @@ dependencies = [ ] [[package]] -name = "ratelimited-logger" +name = "ratelimited" version = "0.1.0" dependencies = [ "governor", @@ -1307,7 +1307,7 @@ dependencies = [ "color-eyre", "futures", "governor", - "ratelimited-logger", + "ratelimited", "serde", "thiserror", "tokio", diff --git a/crates/usb-bridge/src/main.rs b/crates/usb-bridge/src/main.rs index b9ec53b8..82bcc014 100644 --- a/crates/usb-bridge/src/main.rs +++ b/crates/usb-bridge/src/main.rs @@ -25,7 +25,7 @@ struct Cli { #[tokio::main(flavor = "current_thread")] async fn main() -> Result<(), color_eyre::Report> { color_eyre::install().unwrap(); - setup_tracing(); + logger::tracing::setup(); let args = Cli::parse(); debug!("Started usb-bridge"); @@ -52,20 +52,3 @@ async fn main() -> Result<(), color_eyre::Report> { .suggestion("Check if this needs to be updated")?; } } - -fn setup_tracing() { - use tracing_error::ErrorLayer; - use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt, Layer}; - - let file_subscriber = tracing_subscriber::fmt::layer() - .with_file(true) - .with_line_number(true) - .with_target(false) - .without_time() - .with_ansi(false) - .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()); - tracing_subscriber::registry() - .with(file_subscriber) - .with(ErrorLayer::default()) - .init(); -} diff --git a/crates/usb-bridge/src/usb.rs b/crates/usb-bridge/src/usb.rs index a47ce1ba..84aed57c 100644 --- a/crates/usb-bridge/src/usb.rs +++ b/crates/usb-bridge/src/usb.rs @@ -1,7 +1,6 @@ use nusb::transfer; use tokio::sync::mpsc; -use ratelimited_logger as rl; use tokio::time::{sleep, sleep_until, timeout}; use protocol::Affector; @@ -21,7 +20,6 @@ pub(crate) struct ReconnectingUsb { pub(crate) next_poll: Instant, pub(crate) conn: Option, pub(crate) bytes: vec::IntoIter, - pub(crate) logger: ratelimited_logger::RateLimitedLogger, pub(crate) to_send: mpsc::Receiver, } @@ -37,8 +35,6 @@ impl ReconnectingUsb { next_poll: Instant::now(), conn: None, bytes: Vec::new().into_iter(), - logger: ratelimited_logger::RateLimitedLogger::default() - .with_per_msg_period(Duration::from_secs(60)), to_send, } } @@ -52,8 +48,7 @@ impl ReconnectingUsb { Ok(Some(msg)) => break msg, Ok(None) => continue, // needs another call to decode more Err(e) => { - let logger = &mut self.logger; - rl::warn!(logger; "Error trying get affector list: {e}"); + tracing::warn!("Error trying get affector list: {e}"); sleep(Duration::from_secs(5)).await; } } @@ -100,8 +95,7 @@ impl ReconnectingUsb { Ok(Some(bytes)) => break bytes.into_iter(), Ok(None) => continue, Err(e) => { - let logger = &mut self.logger; - rl::warn!(logger; "could not receive sensor message: {e:?}"); + tracing::warn!("could not receive sensor message: {e:?}"); *retry_period *= 2; *retry_period = (*retry_period).min(Duration::from_secs(30)); sleep(*retry_period).await; @@ -120,8 +114,7 @@ impl ReconnectingUsb { Ok(Status::Done) => break, Ok(Status::CallAgain) => continue, Err(e) => { - let logger = &mut self.logger; - rl::warn!(logger; "could not send affector order: {e:?}"); + tracing::warn!("could not send affector order: {e:?}"); *retry_period *= 2; *retry_period = (*retry_period).min(Duration::from_secs(30)); sleep(*retry_period).await; From b88e503c31e0489454ab0c2613a712a2bcda6474 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Wed, 27 Nov 2024 12:23:55 +0100 Subject: [PATCH 451/687] Make color less extreme and switch log to ceiling --- .../src/lights/cached_bridge/mqtt.rs | 4 +-- .../src/lights/cached_bridge/poll.rs | 25 +++++++++++-------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index f34667de..20929343 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -142,8 +142,8 @@ impl Mqtt { ..Default::default() }; - if topic.contains("kitchen:fridge") { - warn!("ZB to MQTT (fridge): {payload}"); + if topic.contains("kitchen:ceiling") { + warn!("ZB to MQTT (ceiling): {payload}"); } self.client .publish_with_properties( diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index fb72ab4b..4adc5fb8 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -8,7 +8,7 @@ use serde_json::Value; use tokio::{sync::RwLock, time::sleep}; use tracing::{instrument, trace, warn}; -use crate::lights::kelvin_to_mired; +use crate::lights::denormalize; use crate::lights::lamp::{self, Lamp}; use crate::lights::parse_state::parse_lamp_properties; @@ -54,22 +54,25 @@ async fn update_state( .entry(light_name.to_owned()) .or_insert_with(|| Lamp::new(light_name)); for property in new { - match property { - lamp::Property::ColorTempK(temp) => { - if light_name == "kitchen:fridge" { + if light_name == "kitchen:ceiling" { + match property { + lamp::Property::Brightness(bri) => { warn!( - "ZB received fridge color temp change: {}", - kelvin_to_mired(temp) + "ZB received ceiling brightness change: {}", + denormalize(bri) ); } - } - lamp::Property::Online(new_online) => { - if new_online != current_lamp.is_online { - warn!("ZB received fridge online change: {new_online}"); + lamp::Property::Online(new_online) => { + if new_online != current_lamp.is_online { + warn!( + "ZB received ceiling online change: {new_online}" + ); + } } + _ => (), } - _ => (), } + current_lamp.apply(property); } } From 9454464e3c17cf9a7617f1aac5cf6c538656a702 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 28 Nov 2024 12:35:06 +0100 Subject: [PATCH 452/687] adds debug statements to dserver watch + stronger ratelimits --- crates/data-server/src/server/watch.rs | 42 ++++++++++---- crates/logger/src/ratelimited.rs | 77 ++++++++++++++++++++++---- crates/logger/src/tracing.rs | 23 ++++++-- 3 files changed, 116 insertions(+), 26 deletions(-) diff --git a/crates/data-server/src/server/watch.rs b/crates/data-server/src/server/watch.rs index d4b1f18a..4577da0e 100644 --- a/crates/data-server/src/server/watch.rs +++ b/crates/data-server/src/server/watch.rs @@ -19,7 +19,9 @@ struct LastSeen { impl LastSeen { fn update(&mut self, reading: Reading) { - if let Some((_, time)) = self.map.iter_mut().find(|(r, _)| r.is_same_as(&reading)) { + if let Some((_, time)) = + self.map.iter_mut().find(|(r, _)| r.is_same_as(&reading)) + { *time = Instant::now(); } else { self.map.push((reading, Instant::now())); @@ -48,18 +50,28 @@ impl LastSeen { .filter_map(|(reading, _)| { match reading { Reading::LargeBedroom(large_bedroom::Reading::Bed(_)) => { - Some(Affector::LargeBedroom(large_bedroom::Affector::Bed( - large_bedroom::bed::Affector::ResetNode, - ))) + Some(Affector::LargeBedroom( + large_bedroom::Affector::Bed( + large_bedroom::bed::Affector::ResetNode, + ), + )) + } + Reading::LargeBedroom(large_bedroom::Reading::Desk(_)) => { + None } - Reading::LargeBedroom(large_bedroom::Reading::Desk(_)) => None, Reading::SmallBedroom(small_bedroom::Reading::Bed(_)) => { - Some(Affector::SmallBedroom(small_bedroom::Affector::Bed( - small_bedroom::bed::Affector::ResetNode, - ))) + Some(Affector::SmallBedroom( + small_bedroom::Affector::Bed( + small_bedroom::bed::Affector::ResetNode, + ), + )) + } + Reading::SmallBedroom(small_bedroom::Reading::Desk(_)) => { + None } - Reading::SmallBedroom(small_bedroom::Reading::Desk(_)) => None, - Reading::SmallBedroom(small_bedroom::Reading::ButtonPanel(_)) => None, + Reading::SmallBedroom( + small_bedroom::Reading::ButtonPanel(_), + ) => None, } .map(|reset_cmd| (reading, reset_cmd)) }) @@ -70,7 +82,10 @@ impl LastSeen { .find(|(a, _)| a.is_same_as(reset_cmd)) .map(|(_, at)| at) .copied(); - !last_reset.is_some_and(|last_reset| last_reset.elapsed() < MIN_RESET_INTERVAL) + dbg!(&self.last_reset); + !last_reset.is_some_and(|last_reset| { + last_reset.elapsed() < MIN_RESET_INTERVAL + }) }) .map(|(reading, reset_cmd)| (reading.clone(), reset_cmd)) .collect(); @@ -85,7 +100,10 @@ impl LastSeen { } } -pub async fn node_watchdog(registar: AffectorRegistar, sub_tx: &mpsc::Sender) -> ! { +pub async fn node_watchdog( + registar: AffectorRegistar, + sub_tx: &mpsc::Sender, +) -> ! { let (tx, mut rx) = mpsc::channel(128); sub_tx .send(Event::NewSub { tx }) diff --git a/crates/logger/src/ratelimited.rs b/crates/logger/src/ratelimited.rs index dd96a913..509eaa1f 100644 --- a/crates/logger/src/ratelimited.rs +++ b/crates/logger/src/ratelimited.rs @@ -80,13 +80,14 @@ impl Inner { hash: LogMsgHash(0), // placeholder }; event.record(&mut visitor); - let msg = callsite - .msg - .entry(visitor.hash) - .or_insert_with(|| LimitState { - limiter: RateLimiter::direct(quoti.msg), - supressed: 0, - }); + let msg = + callsite + .msg + .entry(visitor.hash) + .or_insert_with(|| LimitState { + limiter: RateLimiter::direct(quoti.msg), + supressed: 0, + }); if msg.limiter.check().is_err() { msg.supressed += 1; @@ -118,7 +119,8 @@ impl Default for Quoti { .allow_burst(NonZero::new(9).unwrap()), callsite: Quota::per_second(NonZero::new(6).unwrap()) .allow_burst(NonZero::new(6).unwrap()), - msg: Quota::per_second(NonZero::new(1).unwrap()).allow_burst(NonZero::new(1).unwrap()), + msg: Quota::per_second(NonZero::new(1).unwrap()) + .allow_burst(NonZero::new(1).unwrap()), } } } @@ -164,7 +166,11 @@ struct Visitor { } impl Visit for Visitor { - fn record_debug(&mut self, _field: &tracing_core::Field, value: &dyn std::fmt::Debug) { + fn record_debug( + &mut self, + _field: &tracing_core::Field, + value: &dyn std::fmt::Debug, + ) { self.hash = debug_hash(&value) } } @@ -232,7 +238,10 @@ impl Limiter { self } - pub fn with_callsite_period(mut self, one_callsite_log_per: Duration) -> Self { + pub fn with_callsite_period( + mut self, + one_callsite_log_per: Duration, + ) -> Self { self.quoti.callsite = Quota::with_period(one_callsite_log_per) .expect("duration may not be zero") .allow_burst(self.quoti.callsite.burst_size()); @@ -264,4 +273,52 @@ impl Limiter { self } + + pub fn with_global_burst(mut self, burst_size: u32) -> Self { + self.quoti.global = + Quota::with_period(self.quoti.global.replenish_interval()) + .expect("duration may not be zero") + .allow_burst(NonZero::new(burst_size).unwrap()); + + { + let mut inner = self.inner.lock().unwrap(); + inner.global.limiter = RateLimiter::direct(self.quoti.global) + } + + self + } + pub fn with_callsite_burst(mut self, burst_size: u32) -> Self { + self.quoti.callsite = + Quota::with_period(self.quoti.callsite.replenish_interval()) + .expect("duration may not be zero") + .allow_burst(NonZero::new(burst_size).unwrap()); + + { + let mut inner = self.inner.lock().unwrap(); + for CallSite { state, .. } in inner.callsite.values_mut() { + state.limiter = RateLimiter::direct(self.quoti.callsite) + } + } + + self + } + pub fn with_msg_burst(mut self, burst_size: u32) -> Self { + self.quoti.callsite = + Quota::with_period(self.quoti.msg.replenish_interval()) + .expect("duration may not be zero") + .allow_burst(NonZero::new(burst_size).unwrap()); + + { + let mut inner = self.inner.lock().unwrap(); + for msg_state in inner + .callsite + .values_mut() + .flat_map(|CallSite { msg, .. }| msg.values_mut()) + { + msg_state.limiter = RateLimiter::direct(self.quoti.msg) + } + } + + self + } } diff --git a/crates/logger/src/tracing.rs b/crates/logger/src/tracing.rs index 0f6946ab..fc03b024 100644 --- a/crates/logger/src/tracing.rs +++ b/crates/logger/src/tracing.rs @@ -1,3 +1,5 @@ +use std::time::Duration; + use tracing::level_filters::LevelFilter; use crate::ratelimited; @@ -55,7 +57,13 @@ pub fn setup() { .parse_lossy("") }); - let ratelimiter = ratelimited::Limiter::default(); + let ratelimiter = ratelimited::Limiter::default() + .with_global_period(Duration::from_secs(1)) + .with_global_burst(20) + .with_callsite_period(Duration::from_secs(5)) + .with_global_burst(10) + .with_msg_period(Duration::from_secs(20)) + .with_msg_burst(10); let fmt = fmt::layer() .pretty() @@ -65,14 +73,19 @@ pub fn setup() { .with_target(false) .with_ansi(true); - let registry = tracing_subscriber::Registry::default().with(ErrorLayer::default()); + let registry = + tracing_subscriber::Registry::default().with(ErrorLayer::default()); use tracing_subscriber::Layer; if libsystemd::logging::connected_to_journal() { match tracing_journald::layer() { Ok(journal) => { registry - .with(journal.with_filter(ratelimiter).with_filter(env_filter)) + .with( + journal + .with_filter(ratelimiter) + .with_filter(env_filter), + ) .init(); tracing::info!("Started logging & tracing to journald"); } @@ -87,7 +100,9 @@ pub fn setup() { } }; } else { - registry.with(fmt.with_filter(ratelimiter).with_filter(env_filter)).init(); + registry + .with(fmt.with_filter(ratelimiter).with_filter(env_filter)) + .init(); tracing::info!("Started logging & tracing to stderr"); } } From c676e988ffb94fdd04690112cdedb0dee454c7a1 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 28 Nov 2024 12:42:59 +0100 Subject: [PATCH 453/687] fix overflow when device sampling is dur::max --- crates/data-server/src/api/data_source/reconnecting.rs | 1 - crates/data-server/src/server/affector.rs | 1 - crates/data-server/src/server/watch.rs | 3 +-- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/data-server/src/api/data_source/reconnecting.rs b/crates/data-server/src/api/data_source/reconnecting.rs index 647ab1b4..acb015f8 100644 --- a/crates/data-server/src/api/data_source/reconnecting.rs +++ b/crates/data-server/src/api/data_source/reconnecting.rs @@ -46,7 +46,6 @@ async fn handle_conn( } } } else { - dbg!(); handle_sending(conn.sender, &mut msgs_to_send).await; } } diff --git a/crates/data-server/src/server/affector.rs b/crates/data-server/src/server/affector.rs index 7a13be49..9c91c088 100644 --- a/crates/data-server/src/server/affector.rs +++ b/crates/data-server/src/server/affector.rs @@ -110,7 +110,6 @@ pub enum AffectorError { pub(super) async fn control_affectors(mut writer: OwnedWriteHalf, mut rx: Receiver) { while let Some(new_order) = rx.recv().await { let buf = new_order.encode(); - dbg!(&buf); if let Err(e) = writer.write_all(&buf).await { warn!("Could not send affector order: {e}"); break; diff --git a/crates/data-server/src/server/watch.rs b/crates/data-server/src/server/watch.rs index 4577da0e..ca15cb68 100644 --- a/crates/data-server/src/server/watch.rs +++ b/crates/data-server/src/server/watch.rs @@ -43,7 +43,7 @@ impl LastSeen { fn check_and_bite(&mut self, registar: &AffectorRegistar) { let to_reset = self.map.iter().filter(|(reading, last_seen)| { let max_interval = reading.leaf().device.info().max_sample_interval; - last_seen.elapsed() > max_interval * 10 + last_seen.elapsed() > max_interval.saturating_mul(10) }); let mut reset_commands: Vec<_> = to_reset @@ -82,7 +82,6 @@ impl LastSeen { .find(|(a, _)| a.is_same_as(reset_cmd)) .map(|(_, at)| at) .copied(); - dbg!(&self.last_reset); !last_reset.is_some_and(|last_reset| { last_reset.elapsed() < MIN_RESET_INTERVAL }) From b28fb68d2c9a050e8075d1dadbea99265d7e308f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 28 Nov 2024 16:52:48 +0100 Subject: [PATCH 454/687] add affector status + fix sending of orders --- crates/sensor-tui/src/control.rs | 82 ++++++++++++++++-- crates/sensor-tui/src/lib.rs | 4 + crates/sensor-tui/src/main.rs | 2 +- crates/sensor-tui/src/tui.rs | 40 ++++++--- crates/sensor-tui/src/tui/affectors.rs | 86 +++++++++++++------ .../src/tui/affectors/handle_key.rs | 3 + crates/sensor-tui/src/tui/affectors/render.rs | 39 +++++++-- 7 files changed, 206 insertions(+), 50 deletions(-) diff --git a/crates/sensor-tui/src/control.rs b/crates/sensor-tui/src/control.rs index 4f1a5a6a..c2d1a938 100644 --- a/crates/sensor-tui/src/control.rs +++ b/crates/sensor-tui/src/control.rs @@ -1,13 +1,47 @@ use std::net::SocketAddr; +use std::time::Duration; -use data_server::api::subscriber::Client; +use data_server::api::subscriber::client::Error; +use data_server::api::subscriber::{AffectorError, Client}; use protocol::Affector; +use std::sync::mpsc as std_mpsc; use tokio::sync::mpsc; +use tokio::time::sleep; use tracing::error; -use crate::client_name; +use crate::{client_name, Update}; -pub async fn watch_and_send(data_server: SocketAddr, mut rx: mpsc::Receiver) { +#[derive(Debug)] +pub enum AffectorStatus { + Send, + RateLimited, + NodeOffline, + /// connection to data_server is/was down, retrying + ConnIssues, +} + +impl std::fmt::Display for AffectorStatus { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AffectorStatus::Send => f.write_str("Send succesfully"), + AffectorStatus::RateLimited => f.write_str( + "Dropped, affector is rate limited, try again later", + ), + AffectorStatus::NodeOffline => { + f.write_str("Dropped, node is offline") + } + AffectorStatus::ConnIssues => { + f.write_str("Queued, trying to resolve connection issues") + } + } + } +} + +pub async fn watch_and_send( + data_server: SocketAddr, + mut rx: mpsc::Receiver, + tx: std_mpsc::Sender, +) { let mut connected_client: Option = None; let mut queued = None; @@ -22,12 +56,44 @@ pub async fn watch_and_send(data_server: SocketAddr, mut rx: mpsc::Receiver { + connected_client = Some(client); + AffectorStatus::Send + } + Err(Error::Request(AffectorError::RateLimited)) => { + connected_client = Some(client); + AffectorStatus::RateLimited + } + Err(Error::Request(AffectorError::Offline)) => { + connected_client = Some(client); + AffectorStatus::NodeOffline + } + Err(e) => { + queued = Some(order); + error!( + "Could not actuate affector, error interfacing with data-server, \ + queing order for when its resolved: {e:?}" + ); + AffectorStatus::ConnIssues + } + }; + tx.send(Update::AffectorOrderStatus { + affector: order.clone(), + status, + }) + .expect("Update listener only stops on program exit"); + } else { + match Client::connect(data_server, client_name()).await { + Ok(c) => { + queued = Some(order); + connected_client = Some(c) + } + Err(e) => { + error!("Could not connect to data_server: {e}"); + sleep(Duration::from_secs(5)).await; + } } - connected_client = Some(client) - } else if let Ok(c) = Client::connect(data_server, client_name()).await { - connected_client = Some(c) } } } diff --git a/crates/sensor-tui/src/lib.rs b/crates/sensor-tui/src/lib.rs index d718c56e..5b5bf0be 100644 --- a/crates/sensor-tui/src/lib.rs +++ b/crates/sensor-tui/src/lib.rs @@ -47,6 +47,10 @@ pub enum Update { controlled_by: String, }, AffectorList(Vec), + AffectorOrderStatus { + affector: protocol::Affector, + status: control::AffectorStatus, + }, PopulateError(color_eyre::Report), } diff --git a/crates/sensor-tui/src/main.rs b/crates/sensor-tui/src/main.rs index 65654ef1..4ba7cfee 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/sensor-tui/src/main.rs @@ -59,7 +59,7 @@ async fn main() -> Result<()> { log_store, tx1_clone2, )); - task::spawn(control::watch_and_send(data_server, rx3)); + task::spawn(control::watch_and_send(data_server, rx3, tx1)); let UserIntent::Shutdown = rx2.recv()?; Ok(()) diff --git a/crates/sensor-tui/src/tui.rs b/crates/sensor-tui/src/tui.rs index 60a6a584..57aa9a82 100644 --- a/crates/sensor-tui/src/tui.rs +++ b/crates/sensor-tui/src/tui.rs @@ -1,6 +1,9 @@ use crossterm::{ event::{self, KeyCode, KeyEventKind, KeyModifiers}, - terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, + terminal::{ + disable_raw_mode, enable_raw_mode, EnterAlternateScreen, + LeaveAlternateScreen, + }, ExecutableCommand, }; use protocol::Affector; @@ -100,8 +103,12 @@ impl App { terminal.draw(|frame| { let layout = render(frame, self); match self.active_tab { - ActiveTab::Readings => self.readings_tab.render(frame, layout, &self.theme), - ActiveTab::Affectors => self.affectors_tab.render(frame, layout, &self.theme), + ActiveTab::Readings => { + self.readings_tab.render(frame, layout, &self.theme) + } + ActiveTab::Affectors => { + self.affectors_tab.render(frame, layout, &self.theme) + } } })?; @@ -114,16 +121,22 @@ impl App { tracing::trace!("key pressed: {key:?}"); if key.kind == KeyEventKind::Press { let res = match key.code { - KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => { + KeyCode::Char('c') + if key + .modifiers + .contains(KeyModifiers::CONTROL) => + { break Ok(()); } _ => Some(key), } .and_then(|key| match self.active_tab { - ActiveTab::Readings => self.readings_tab.handle_key(key), - ActiveTab::Affectors => { - self.affectors_tab.handle_key(key, &mut control_tx) + ActiveTab::Readings => { + self.readings_tab.handle_key(key) } + ActiveTab::Affectors => self + .affectors_tab + .handle_key(key, &mut control_tx), }) .and_then(|key| self.reports.handle_key(key)); @@ -135,7 +148,9 @@ impl App { KeyCode::Right => { self.active_tab = self.active_tab.swap(); } - KeyCode::Char('q') | KeyCode::Esc => return Ok(()), + KeyCode::Char('q') | KeyCode::Esc => { + return Ok(()) + } _ => (), } } @@ -165,9 +180,14 @@ impl App { | Update::Fetched { .. } | Update::ReadingList(_) | Update::SensorError(_) + | Update::AffectorOrderStatus { .. } | Update::SensorReading(_) => return Some(update), - Update::PopulateError(e) => self.reports.add(e.wrap_err("Error populating lists")), - Update::FetchError(e) => self.reports.add(e.wrap_err("Error fetching")), + Update::PopulateError(e) => { + self.reports.add(e.wrap_err("Error populating lists")) + } + Update::FetchError(e) => { + self.reports.add(e.wrap_err("Error fetching")) + } Update::SubscribeError(e) => self .reports .add(e.wrap_err("Error while subscribing to data-server")), diff --git a/crates/sensor-tui/src/tui/affectors.rs b/crates/sensor-tui/src/tui/affectors.rs index 592126f6..923f7530 100644 --- a/crates/sensor-tui/src/tui/affectors.rs +++ b/crates/sensor-tui/src/tui/affectors.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::time::Instant; use crossterm::event::{KeyCode, KeyEvent}; use protocol::{affector, Affector}; @@ -7,6 +8,7 @@ use ratatui::Frame; use tokio::sync::mpsc; use tui_tree_widget::{TreeItem, TreeState}; +use crate::control; use crate::Update; use super::Theme; @@ -22,7 +24,9 @@ pub type TreeKey = [u8; 6]; struct AffectorState { affector: Affector, selected_control: usize, + last_input: Option, last_controlled_by: Option, + last_order_status: Option, info: affector::Info, device_broken: DeviceBroken, } @@ -37,9 +41,11 @@ pub struct Tab { impl Tab { pub fn render(&mut self, frame: &mut Frame, layout: Rect, theme: &Theme) { let [main, footer] = - Layout::vertical([Constraint::Fill(1), Constraint::Max(1)]).areas(layout); + Layout::vertical([Constraint::Fill(1), Constraint::Max(1)]) + .areas(layout); let [left, right] = - Layout::horizontal([Constraint::Fill(1), Constraint::Fill(1)]).areas(main); + Layout::horizontal([Constraint::Fill(1), Constraint::Fill(1)]) + .areas(main); render::tree(frame, left, &self.ground, &mut self.tree_state); @@ -51,7 +57,8 @@ impl Tab { if let Some(ref mut data) = data { let [top, bottom] = - Layout::vertical([Constraint::Fill(1), Constraint::Fill(1)]).areas(right); + Layout::vertical([Constraint::Fill(1), Constraint::Fill(1)]) + .areas(right); render::details(frame, data, top); render::controls(frame, data, bottom); }; @@ -102,22 +109,26 @@ impl Tab { affector, controlled_by, } => { - self.update_tree(&affector, Some(controlled_by), DeviceBroken::No); + self.mark_controlled(&affector, controlled_by); None } Update::SensorError(ref err) => { let broken = err.device().info().affectors; for affector in broken { - self.update_tree(affector, None, DeviceBroken::Yes); + self.mark_broken(affector); } Some(update) } Update::AffectorList(affectors) => { for affector in affectors { - self.update_tree(&affector, None, DeviceBroken::No); + self.add(&affector); } None } + Update::AffectorOrderStatus { affector, status } => { + self.update_order_status(&affector, status); + None + } }; if self.tree_state.selected().is_empty() { @@ -135,15 +146,47 @@ enum DeviceBroken { } impl Tab { + fn mark_controlled( + &mut self, + affector: &protocol::Affector, + controlled_by: String, + ) { + self.update_tree(affector, move |state| { + state.last_controlled_by = Some(controlled_by); + }) + } + + fn mark_broken(&mut self, affector: &protocol::Affector) { + self.update_tree(affector, move |state| { + state.device_broken = DeviceBroken::Yes; + }) + } + + fn add(&mut self, affector: &protocol::Affector) { + self.update_tree(affector, move |state| { + state.affector = *affector; + }) + } + + fn update_order_status( + &mut self, + affector: &protocol::Affector, + status: control::AffectorStatus, + ) { + self.update_tree(affector, move |state| { + state.last_order_status = Some(status); + }) + } + fn update_tree( &mut self, affector: &protocol::Affector, - controller: Option, - broken: DeviceBroken, + update: impl FnOnce(&mut AffectorState) -> (), ) { let key = tree_key(affector); - let mut tree = add_root(affector as &dyn AffectorTree, &mut self.ground); + let mut tree = + add_root(affector as &dyn AffectorTree, &mut self.ground); let mut tree_node = match affector.inner() { Item::Leaf(_) => unreachable!("no values at level 0"), Item::Node(inner) => inner, @@ -153,21 +196,16 @@ impl Tab { Item::Leaf(info) => { let text = tree_node.name(); add_leaf(text, tree, key); - self.data - .entry(key) - .and_modify(|state| state.affector = *affector) - .and_modify(|state| { - if controller.is_some() { - state.last_controlled_by = controller.clone(); - } - }) - .or_insert(AffectorState { - affector: *affector, - info, - selected_control: 0, - last_controlled_by: controller, - device_broken: broken, - }); + let item = self.data.entry(key).or_insert(AffectorState { + affector: *affector, + info, + selected_control: 0, + last_controlled_by: None, + device_broken: DeviceBroken::No, + last_input: None, + last_order_status: None, + }); + update(item); return; } Item::Node(inner) => { diff --git a/crates/sensor-tui/src/tui/affectors/handle_key.rs b/crates/sensor-tui/src/tui/affectors/handle_key.rs index 6e4989a7..d2e69b74 100644 --- a/crates/sensor-tui/src/tui/affectors/handle_key.rs +++ b/crates/sensor-tui/src/tui/affectors/handle_key.rs @@ -1,3 +1,5 @@ +use std::time::Instant; + use crossterm::event::{KeyCode, KeyEvent}; use protocol::affector::ControlValue as C; use tokio::sync::mpsc; @@ -11,6 +13,7 @@ pub(crate) fn handle( state: &mut AffectorState, control_tx: &mut mpsc::Sender, ) -> Option { + state.last_input = Some(Instant::now()); let mut controls = state.affector.controls(); let control = &mut controls[state.selected_control].value; diff --git a/crates/sensor-tui/src/tui/affectors/render.rs b/crates/sensor-tui/src/tui/affectors/render.rs index 9220a440..5796c93c 100644 --- a/crates/sensor-tui/src/tui/affectors/render.rs +++ b/crates/sensor-tui/src/tui/affectors/render.rs @@ -33,13 +33,33 @@ pub(super) fn tree( ); } -pub(super) fn details(frame: &mut Frame, data: &&mut AffectorState, top: Rect) { +pub(super) fn details(frame: &mut Frame, data: &mut AffectorState, top: Rect) { let mut text = vec![data.info.description.to_owned()]; if let Some(ref name) = data.last_controlled_by { text.push(format!("\nlast controlled by: {name}")); } + if let Some(ref at) = data.last_input { + let input_action = match data + .affector + .controls() + .get(data.selected_control) + .expect("controls are never removed") + .value + { + affector::ControlValue::Trigger => "trigged", + affector::ControlValue::SetNum { .. } => "set", + }; + let elapsed = crate::time::format::duration(at.elapsed().as_secs_f64()); + text.push(format!("\nwe last {input_action}: {elapsed} ago")); + } + if let Some(ref status) = data.last_order_status { + text.push(format!("\nstatus: {status}")); + } if let DeviceBroken::Yes = data.device_broken { - text.push("\nWarning: Device reports error, affector might not work".to_owned()); + text.push( + "\nWarning: Device reports error, affector might not work" + .to_owned(), + ); } let text = text.join("\n"); @@ -51,12 +71,16 @@ pub(super) fn details(frame: &mut Frame, data: &&mut AffectorState, top: Rect) { ) } -pub(crate) fn controls(frame: &mut Frame, data: &mut &mut AffectorState, bottom: Rect) { +pub(crate) fn controls( + frame: &mut Frame, + data: &mut &mut AffectorState, + bottom: Rect, +) { use affector::ControlValue as V; let controls = data.affector.controls(); - let constraints = - iter::once(Constraint::Max(1)).chain(controls.iter().map(|_| Constraint::Max(3))); + let constraints = iter::once(Constraint::Max(1)) + .chain(controls.iter().map(|_| Constraint::Max(3))); let layout = Layout::default().constraints(constraints).split(bottom); let mut layout = layout.iter(); @@ -75,7 +99,7 @@ pub(crate) fn controls(frame: &mut Frame, data: &mut &mut AffectorState, bottom: frame, *layout, control.name, - valid_range, + &valid_range, *value, is_selected, ), @@ -98,7 +122,8 @@ fn render_slider( Style::default() }; - let percentage = (current_value as u64 * 100) / (valid_range.end - valid_range.start); + let percentage = + (current_value as u64 * 100) / (valid_range.end - valid_range.start); frame.render_widget( Gauge::default() .block(Block::bordered().title(name).style(style)) From 14ed8ffc7d1a2728ec96c19966696e3091a3955e Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 28 Nov 2024 16:53:08 +0100 Subject: [PATCH 455/687] update embassy version --- crates/usb-bridge/src/usb.rs | 1 + sensor-nodes/Cargo.lock | 310 ++++++++++++++++--------- sensor-nodes/Cargo.toml | 22 +- sensor-nodes/bed-sb/src/comms.rs | 1 + sensor-nodes/bed-sb/src/usb_wrapper.rs | 1 - 5 files changed, 214 insertions(+), 121 deletions(-) diff --git a/crates/usb-bridge/src/usb.rs b/crates/usb-bridge/src/usb.rs index 84aed57c..726d665e 100644 --- a/crates/usb-bridge/src/usb.rs +++ b/crates/usb-bridge/src/usb.rs @@ -105,6 +105,7 @@ impl ReconnectingUsb { } pub(crate) async fn send_order(&mut self, retry_period: &mut Duration, order: Affector) { + tracing::info!("sending order"); let data = order.encode(); for _ in 0..2 { match self diff --git a/sensor-nodes/Cargo.lock b/sensor-nodes/Cargo.lock index dcb647aa..e1d631ed 100644 --- a/sensor-nodes/Cargo.lock +++ b/sensor-nodes/Cargo.lock @@ -20,7 +20,19 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "377e4c0ba83e4431b10df45c1d4666f178ea9c552cac93e60c3a88bf32785923" dependencies = [ - "as-slice", + "as-slice 0.2.1", +] + +[[package]] +name = "as-slice" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" +dependencies = [ + "generic-array 0.12.4", + "generic-array 0.13.3", + "generic-array 0.14.7", + "stable_deref_trait", ] [[package]] @@ -41,11 +53,23 @@ dependencies = [ "critical-section", ] +[[package]] +name = "atomic-pool" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c5fc22e05ec2884db458bf307dc7b278c9428888d2b6e6fad9c0ae7804f5f6" +dependencies = [ + "as-slice 0.1.5", + "as-slice 0.2.1", + "atomic-polyfill", + "stable_deref_trait", +] + [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "bare-metal" @@ -138,22 +162,22 @@ dependencies = [ [[package]] name = "cortex-m-rt" -version = "0.7.3" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1" +checksum = "801d4dec46b34c299ccf6b036717ae0fce602faa4f4fe816d9013b9a7c9f5ba6" dependencies = [ "cortex-m-rt-macros", ] [[package]] name = "cortex-m-rt-macros" -version = "0.7.0" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" +checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.89", ] [[package]] @@ -173,9 +197,9 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "critical-section" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "darling" @@ -198,7 +222,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.77", + "syn 2.0.89", ] [[package]] @@ -209,14 +233,14 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.77", + "syn 2.0.89", ] [[package]] name = "defmt" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0" +checksum = "9112096fbf91d9458d3dc1bca22e87e2684cad608c032f80135e2471614ceebe" dependencies = [ "bitflags 1.3.2", "defmt-macros", @@ -224,22 +248,22 @@ dependencies = [ [[package]] name = "defmt-macros" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb" +checksum = "9e40098d5ffbf1b3c88dff66c3b168a7dc4f3e8ff8604a00441660040a134e20" dependencies = [ "defmt-parser", - "proc-macro-error", + "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.89", ] [[package]] name = "defmt-parser" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" +checksum = "3983b127f13995e68c1e29071e5d115cd96f215ccb5e6812e3728cd6f92653b3" dependencies = [ "thiserror", ] @@ -266,11 +290,11 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" dependencies = [ "defmt", "embassy-futures", - "embassy-sync", + "embassy-sync 0.6.1", "embassy-time", "embedded-hal 0.2.7", "embedded-hal 1.0.0", @@ -282,8 +306,8 @@ dependencies = [ [[package]] name = "embassy-executor" -version = "0.6.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +version = "0.6.3" +source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" dependencies = [ "cortex-m", "critical-section", @@ -296,24 +320,24 @@ dependencies = [ [[package]] name = "embassy-executor-macros" -version = "0.5.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +version = "0.6.2" +source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.89", ] [[package]] name = "embassy-futures" version = "0.1.1" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" [[package]] name = "embassy-hal-internal" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" dependencies = [ "cortex-m", "critical-section", @@ -324,24 +348,39 @@ dependencies = [ [[package]] name = "embassy-net" version = "0.4.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cf91dd36dfd623de32242af711fd294d41159f02130052fc93c5c5ba93febe" dependencies = [ + "as-slice 0.2.1", + "atomic-pool", "defmt", "document-features", - "embassy-net-driver", - "embassy-sync", + "embassy-net-driver 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "embassy-sync 0.5.0", "embassy-time", "embedded-io-async", "embedded-nal-async", + "futures", + "generic-array 0.14.7", "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "managed", "smoltcp", + "stable_deref_trait", ] [[package]] name = "embassy-net-driver" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d" +dependencies = [ + "defmt", +] + +[[package]] +name = "embassy-net-driver" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" dependencies = [ "defmt", ] @@ -349,17 +388,17 @@ dependencies = [ [[package]] name = "embassy-net-driver-channel" version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" dependencies = [ "embassy-futures", - "embassy-net-driver", - "embassy-sync", + "embassy-net-driver 0.2.0 (git+https://github.com/embassy-rs/embassy?rev=0349a8d)", + "embassy-sync 0.6.1", ] [[package]] name = "embassy-net-wiznet" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" dependencies = [ "defmt", "embassy-futures", @@ -372,7 +411,7 @@ dependencies = [ [[package]] name = "embassy-stm32" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" dependencies = [ "aligned", "bit_field", @@ -387,8 +426,8 @@ dependencies = [ "embassy-embedded-hal", "embassy-futures", "embassy-hal-internal", - "embassy-net-driver", - "embassy-sync", + "embassy-net-driver 0.2.0 (git+https://github.com/embassy-rs/embassy?rev=0349a8d)", + "embassy-sync 0.6.1", "embassy-time", "embassy-time-driver", "embassy-usb-driver", @@ -417,13 +456,27 @@ dependencies = [ [[package]] name = "embassy-sync" -version = "0.6.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd938f25c0798db4280fcd8026bf4c2f48789aebf8f77b6e5cf8a7693ba114ec" +dependencies = [ + "cfg-if", + "critical-section", + "embedded-io-async", + "futures-util", + "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "embassy-sync" +version = "0.6.1" +source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" dependencies = [ "cfg-if", "critical-section", "defmt", "embedded-io-async", + "futures-sink", "futures-util", "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -431,7 +484,7 @@ dependencies = [ [[package]] name = "embassy-time" version = "0.3.2" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" dependencies = [ "cfg-if", "critical-section", @@ -449,7 +502,7 @@ dependencies = [ [[package]] name = "embassy-time-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" dependencies = [ "document-features", ] @@ -457,17 +510,17 @@ dependencies = [ [[package]] name = "embassy-time-queue-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" [[package]] name = "embassy-usb" version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" dependencies = [ "defmt", "embassy-futures", "embassy-net-driver-channel", - "embassy-sync", + "embassy-sync 0.6.1", "embassy-usb-driver", "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "ssmarshal", @@ -477,7 +530,7 @@ dependencies = [ [[package]] name = "embassy-usb-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" dependencies = [ "defmt", ] @@ -485,10 +538,11 @@ dependencies = [ [[package]] name = "embassy-usb-synopsys-otg" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=af6fbb0#af6fbb0ee19c5200bb4bafb9a10c7557fbcd460c" +source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" dependencies = [ "critical-section", - "embassy-sync", + "defmt", + "embassy-sync 0.6.1", "embassy-usb-driver", ] @@ -622,9 +676,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -636,9 +690,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -646,44 +700,44 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.89", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-macro", @@ -693,6 +747,34 @@ dependencies = [ "pin-utils", ] +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "hash32" version = "0.2.1" @@ -782,7 +864,7 @@ dependencies = [ "embassy-net", "embassy-net-wiznet", "embassy-stm32", - "embassy-sync", + "embassy-sync 0.6.1", "embassy-time", "embedded-hal 1.0.0", "embedded-hal-async", @@ -893,9 +975,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "panic-probe" @@ -909,9 +991,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -921,15 +1003,15 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "portable-atomic" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" [[package]] name = "postcard" -version = "1.0.10" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" +checksum = "f63d01def49fc815900a83e7a4a5083d2abc81b7ddd569a3fa0477778ae9b3ec" dependencies = [ "cobs", "defmt", @@ -950,34 +1032,32 @@ dependencies = [ ] [[package]] -name = "proc-macro-error" -version = "1.0.4" +name = "proc-macro-error-attr2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" dependencies = [ - "proc-macro-error-attr", "proc-macro2", "quote", - "syn 1.0.109", - "version_check", ] [[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +name = "proc-macro-error2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" dependencies = [ + "proc-macro-error-attr2", "proc-macro2", "quote", - "version_check", + "syn 2.0.89", ] [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -1037,9 +1117,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "scopeguard" @@ -1076,22 +1156,22 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.89", ] [[package]] @@ -1118,7 +1198,7 @@ dependencies = [ "embassy-executor", "embassy-futures", "embassy-stm32", - "embassy-sync", + "embassy-sync 0.6.1", "embassy-time", "embassy-usb", "embedded-hal 1.0.0", @@ -1142,7 +1222,8 @@ dependencies = [ [[package]] name = "smoltcp" version = "0.11.0" -source = "git+https://github.com/smoltcp-rs/smoltcp?rev=dd43c8f189178b0ab3bda798ed8578b5b0a6f094#dd43c8f189178b0ab3bda798ed8578b5b0a6f094" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a1a996951e50b5971a2c8c0fa05a381480d70a933064245c4a223ddc87ccc97" dependencies = [ "bitflags 1.3.2", "byteorder", @@ -1217,7 +1298,7 @@ dependencies = [ [[package]] name = "stm32-metapac" version = "15.0.0" -source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-9b7414490b10ffbd5beb1b0dcf14adb018cbe37f#dc782d51865ba6a0a8dd79a4d6972864b33b6f00" +source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-04833817666290047257c65c6547d28e1bd10dc9#f3cb9f3c385bcbfa1e6ee525b2a7cb84967c7996" dependencies = [ "cortex-m", "cortex-m-rt", @@ -1248,7 +1329,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.77", + "syn 2.0.89", ] [[package]] @@ -1264,9 +1345,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", @@ -1275,29 +1356,35 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.89", ] +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "usb-device" @@ -1390,5 +1477,10 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.89", ] + +[[patch.unused]] +name = "embassy-net" +version = "0.5.0" +source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" diff --git a/sensor-nodes/Cargo.toml b/sensor-nodes/Cargo.toml index 935e2f00..33432c97 100644 --- a/sensor-nodes/Cargo.toml +++ b/sensor-nodes/Cargo.toml @@ -18,17 +18,17 @@ embassy-time = { version = "0.3.2", features = ["defmt", embassy-futures = { version = "0.1.0"} [patch.crates-io] -embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } -embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "af6fbb0" } +embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } +embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } +embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } +embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } +embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } +embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } +embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } +embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } +embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } +embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } +embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } [workspace.package] rust-version = "1.78" diff --git a/sensor-nodes/bed-sb/src/comms.rs b/sensor-nodes/bed-sb/src/comms.rs index 3306460a..e650383c 100644 --- a/sensor-nodes/bed-sb/src/comms.rs +++ b/sensor-nodes/bed-sb/src/comms.rs @@ -191,6 +191,7 @@ async fn receive_orders(usb: UsbReceiver<'_>, driver_orderers: &slow::DriverOrde } bed::Affector::ResetNode => { defmt::info!("resetting node as orderd via affector"); + defmt::flush(); cortex_m::peripheral::SCB::sys_reset(); } } diff --git a/sensor-nodes/bed-sb/src/usb_wrapper.rs b/sensor-nodes/bed-sb/src/usb_wrapper.rs index 56fa601f..d621d9cb 100644 --- a/sensor-nodes/bed-sb/src/usb_wrapper.rs +++ b/sensor-nodes/bed-sb/src/usb_wrapper.rs @@ -85,7 +85,6 @@ impl embassy_usb::Handler for UsbControlHandler<'_> { return Some(InResponse::Rejected); } - defmt::info!("usb request: {:?}", req); if req.request == usb::GET_AFFECTOR_LIST { self.send_affector_list(buf); Some(InResponse::Accepted(buf)) From 6df8db7e1dd0a0955fbaebbffe2ff17a9126e997 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 28 Nov 2024 17:27:19 +0100 Subject: [PATCH 456/687] fixes is_same_as not being correct for smallbedroom bed --- crates/data-server/src/server/affector.rs | 52 +++++++++++++++++------ crates/protocol/src/small_bedroom/bed.rs | 48 ++++++++++++++------- 2 files changed, 73 insertions(+), 27 deletions(-) diff --git a/crates/data-server/src/server/affector.rs b/crates/data-server/src/server/affector.rs index 9c91c088..e72970c7 100644 --- a/crates/data-server/src/server/affector.rs +++ b/crates/data-server/src/server/affector.rs @@ -12,13 +12,20 @@ use tokio::sync::mpsc::{Receiver, Sender}; use tracing::{instrument, warn}; -#[derive(Debug)] pub(crate) struct Registration { tx: tokio::sync::mpsc::Sender, controls: Vec, rate_limiter: governor::DefaultDirectRateLimiter, } +impl std::fmt::Debug for Registration { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Registration") + .field("controls", &self.controls) + .finish() + } +} + impl Registration { fn update(&mut self, new: Affector) { let curr = self @@ -30,11 +37,23 @@ impl Registration { } } -#[derive(Debug, Clone, Default)] +#[derive(Clone, Default)] pub struct Registar(Arc>>); +impl std::fmt::Debug for Registar { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let this = self.0.lock().unwrap(); + let list: Vec<_> = this.values().map(|r| format!("{r:?}")).collect(); + f.debug_struct("Registar").field("0", &list).finish() + } +} + impl Registar { - pub(crate) fn register(&self, tx: Sender, affectors: Vec) -> DefaultKey { + pub(crate) fn register( + &self, + tx: Sender, + affectors: Vec, + ) -> DefaultKey { let mut this = self.0.lock().expect("nothing should panic"); let to_remove: Vec<_> = this @@ -69,21 +88,27 @@ impl Registar { let _ = this.remove(key); // Could have been removed by register } - pub(crate) fn activate(&self, order: Affector) -> Result<(), AffectorError> { - tracing::info!("client is trying to activate: {order:?}"); + pub(crate) fn activate( + &self, + order: Affector, + ) -> Result<(), AffectorError> { + tracing::debug!("client is trying to activate: {order:?}"); let mut this = self.0.lock().expect("nothing should panic"); - for possible_controller in this.iter_mut().map(|(_, reg)| reg).filter(|reg| { - reg.controls - .iter() - .any(|control| control.is_same_as(&order)) - }) { + for possible_controller in + this.iter_mut().map(|(_, reg)| reg).filter(|reg| { + reg.controls + .iter() + .any(|control| control.is_same_as(&order)) + }) + { if possible_controller.rate_limiter.check().is_err() { return Err(AffectorError::RateLimited); } if possible_controller.tx.try_send(order).is_ok() { possible_controller.update(order); + tracing::info!("client activated: {order:?}"); return Ok(()); - } + }; } Err(AffectorError::Offline) @@ -107,7 +132,10 @@ pub enum AffectorError { } #[instrument(skip_all)] -pub(super) async fn control_affectors(mut writer: OwnedWriteHalf, mut rx: Receiver) { +pub(super) async fn control_affectors( + mut writer: OwnedWriteHalf, + mut rx: Receiver, +) { while let Some(new_order) = rx.recv().await { let buf = new_order.encode(); if let Err(e) = writer.write_all(&buf).await { diff --git a/crates/protocol/src/small_bedroom/bed.rs b/crates/protocol/src/small_bedroom/bed.rs index 62139576..c94e64e2 100644 --- a/crates/protocol/src/small_bedroom/bed.rs +++ b/crates/protocol/src/small_bedroom/bed.rs @@ -263,14 +263,18 @@ impl Reading { | (Self::NumberPm2_5(_), Self::NumberPm2_5(_)) | (Self::NumberPm4_0(_), Self::NumberPm4_0(_)) | (Self::NumberPm10(_), Self::NumberPm10(_)) - | (Self::TypicalParticleSize(_), Self::TypicalParticleSize(_)) => true, + | (Self::TypicalParticleSize(_), Self::TypicalParticleSize(_)) => { + true + } (Self::Button(a), Self::Button(b)) => a.is_same_as(b), _ => false, } } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +#[derive( + Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq, +)] pub enum Error { Running(SensorError), Setup(SensorError), @@ -282,8 +286,12 @@ impl Error { #[must_use] pub(crate) fn device(&self) -> Device { match self { - Self::Running(sensor_err) | Self::Setup(sensor_err) => sensor_err.device(), - Self::SetupTimedOut(device) | Self::Timeout(device) => device.clone(), + Self::Running(sensor_err) | Self::Setup(sensor_err) => { + sensor_err.device() + } + Self::SetupTimedOut(device) | Self::Timeout(device) => { + device.clone() + } } } } @@ -299,7 +307,9 @@ impl core::fmt::Display for Error { } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, Eq, PartialEq)] +#[derive( + Clone, Debug, defmt::Format, Serialize, Deserialize, Eq, PartialEq, +)] pub enum SensorError { Sht31(heapless::String<200>), Bme680(heapless::String<200>), @@ -343,7 +353,17 @@ impl SensorError { } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq, Hash)] +#[derive( + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + Eq, + PartialEq, + Hash, +)] pub enum Device { Sht31, Bme680, @@ -486,13 +506,7 @@ pub enum Affector { impl Affector { #[must_use] pub fn is_same_as(&self, other: &Self) -> bool { - #[allow(clippy::match_like_matches_macro)] - match (self, other) { - (Affector::Sps30FanClean, Affector::Sps30FanClean) => true, - (Affector::MhzZeroPointCalib, Affector::MhzZeroPointCalib) => true, - (Affector::Nau7802Calib, Affector::Nau7802Calib) => true, - _ => false, - } + self.eq(other) } #[cfg(feature = "alloc")] @@ -545,8 +559,12 @@ mod test { fn test_is_same_as() { assert!(Reading::Co2(5).is_same_as(&Reading::Co2(0))); - let a = crate::Reading::SmallBedroom(crate::small_bedroom::Reading::Bed(Reading::Co2(5))); - let b = crate::Reading::SmallBedroom(crate::small_bedroom::Reading::Bed(Reading::Co2(0))); + let a = crate::Reading::SmallBedroom( + crate::small_bedroom::Reading::Bed(Reading::Co2(5)), + ); + let b = crate::Reading::SmallBedroom( + crate::small_bedroom::Reading::Bed(Reading::Co2(0)), + ); assert!(a.is_same_as(&b)); } From cca3047d03c31f85258ed090e493f6272fff73b1 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 29 Nov 2024 12:59:28 +0100 Subject: [PATCH 457/687] Add button logic for lights --- crates/brain/src/controller/mod.rs | 35 ++++++++++++ .../src/controller/rooms/small_bedroom.rs | 54 +++++++++++++------ 2 files changed, 72 insertions(+), 17 deletions(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 171311e1..b4eba288 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -36,6 +36,41 @@ struct RestrictedSystem { } impl RestrictedSystem { + async fn one_lamp_ct(&mut self, name: &'static str, ct: u16, bri: u8) { + if self.allowed_lights.contains(&name) { + self.system.lights.set_ct(name, bri, ct).await.unwrap(); + } + + if self.allowed_lights_new.contains(&name) { + self.system + .lights_new + .set_color_temp(name, mired_to_kelvin(ct.into())); + self.system.lights_new.set_brightness(name, normalize(bri)); + } + } + + async fn one_lamp_on(&mut self, name: &'static str) { + if self.allowed_lights.contains(&name) { + self.system.lights.single_on(name).await.unwrap(); + } + + if self.allowed_lights_new.contains(&name) { + self.system.lights_new.set_on(name); + } + + } + + async fn one_lamp_off(&mut self, name: &'static str) { + if self.allowed_lights.contains(&name) { + self.system.lights.single_off(name).await.unwrap(); + } + + if self.allowed_lights_new.contains(&name) { + self.system.lights_new.set_off(name); + } + + } + async fn all_lamps_ct(&mut self, ct: u16, bri: u8) { for name in &self.allowed_lights { self.system.lights.set_ct(name, bri, ct).await.unwrap(); diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index c3915cbb..628a953b 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -5,19 +5,21 @@ use futures_util::FutureExt; use protocol::small_bedroom::ButtonPanel; use protocol::{small_bedroom, Reading}; use tokio::sync::broadcast; -use tokio::time::{sleep_until, Instant}; +use tokio::time::{sleep, sleep_until, Instant}; use zigbee_bridge::lights::{denormalize, kelvin_to_mired}; use crate::controller::{local_now, Event, RestrictedSystem}; +#[derive(PartialEq, Eq, Debug)] enum State { - _Sleep, - _Wakeup, + Sleep, + Wakeup, Normal, - _Away, + Override, } -const INTERVAL: Duration = Duration::from_secs(5); +const UPDATE_INTERVAL: Duration = Duration::from_secs(5); +const OFF_DELAY: Duration = Duration::from_secs(60); trait RecvFiltered { async fn recv_filter_mapped( @@ -66,8 +68,8 @@ pub async fn run( _event_tx: broadcast::Sender, mut system: RestrictedSystem, ) { - let _state = State::Normal; - let mut next_update = Instant::now() + INTERVAL; + let mut room_state = State::Normal; + let mut next_update = Instant::now() + UPDATE_INTERVAL; loop { let get_event = event_rx .recv_filter_mapped(event_filter) @@ -77,11 +79,12 @@ pub async fn run( let trigger = (get_event, tick).race().await; match trigger { Trigger::Event(RelevantEvent::Button(button)) => { - handle_buttonpress(&mut system, button).await; + handle_buttonpress(&mut system, &mut room_state, button).await; + } } Trigger::ShouldUpdate => { - update(&mut system).await; - next_update = Instant::now() + INTERVAL; + set_time_color(&mut system, &room_state).await; + next_update = Instant::now() + UPDATE_INTERVAL; } } } @@ -89,20 +92,37 @@ pub async fn run( async fn handle_buttonpress( system: &mut RestrictedSystem, + room_state: &mut State, button: ButtonPanel, ) { - dbg!(&button); + dbg!(button); match button { - ButtonPanel::BottomLeft(_) => system.all_lamps_off().await, - ButtonPanel::BottomMiddle(_) => system.all_lamps_on().await, - ButtonPanel::BOttomRight(_) => system.all_lamps_ct(2000, 254).await, + ButtonPanel::BottomLeft(_) => { + *room_state = State::Sleep; + system.one_lamp_off("small_bedroom:bureau").await; + system.one_lamp_off("small_bedroom:piano").await; + sleep(OFF_DELAY).await; + system.all_lamps_off().await; + } + ButtonPanel::BottomMiddle(_) => { + *room_state = State::Normal; + system.all_lamps_on().await; + set_time_color(system, &room_state).await; + } + ButtonPanel::BOttomRight(_) => { + *room_state = State::Override; + system.all_lamps_on().await; + system.all_lamps_ct(2000, 254).await; + } _ => (), } } -async fn update(system: &mut RestrictedSystem) { - let (new_ct, new_bri) = optimal_ct_bri(); - system.all_lamps_ct(new_ct, new_bri).await; +async fn set_time_color(system: &mut RestrictedSystem, room_state: &State) { + if room_state == &State::Normal { + let (new_ct, new_bri) = optimal_ct_bri(); + system.all_lamps_ct(new_ct, new_bri).await; + } } const fn time(hour: u8, minute: u8) -> f64 { From ffb2fe2eb987d14eefca45687e2e34f69bc41ac7 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 29 Nov 2024 12:59:49 +0100 Subject: [PATCH 458/687] Add wakeup logic --- .../src/controller/rooms/small_bedroom.rs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 628a953b..34274cdb 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -45,6 +45,7 @@ impl RecvFiltered for broadcast::Receiver { #[derive(Debug)] enum RelevantEvent { Button(ButtonPanel), + Wakeup, } fn event_filter(event: Event) -> Option { @@ -81,6 +82,8 @@ pub async fn run( Trigger::Event(RelevantEvent::Button(button)) => { handle_buttonpress(&mut system, &mut room_state, button).await; } + Trigger::Event(RelevantEvent::Wakeup) => { + run_wakeup(&mut system, &mut room_state).await; } Trigger::ShouldUpdate => { set_time_color(&mut system, &room_state).await; @@ -90,6 +93,39 @@ pub async fn run( } } +async fn run_wakeup(system: &mut RestrictedSystem, room_state: &mut State) { + *room_state = State::Wakeup; + + let light_name = "small_bedroom:piano"; + let bri = 1; + let ct = 2000; + let bri_growth: f64 = 1.32; + let ct_growth: f64 = 1.028; + + system + .one_lamp_ct(light_name, kelvin_to_mired(ct).try_into().unwrap(), bri) + .await; + // Make sure the light is the right ct and bri before turning it on + sleep(Duration::from_secs(1)).await; + system.one_lamp_on(light_name).await; + + for minute in 1..=20 { + sleep(Duration::from_secs(1)).await; + let new_bri = ((bri as f64) * bri_growth.powi(minute)).round() as u8; + let new_ct = (ct as f64 * ct_growth.powi(minute)).round() as usize; + + system + .one_lamp_ct( + light_name, + kelvin_to_mired(new_ct).try_into().unwrap(), + new_bri, + ) + .await; + } + + *room_state = State::Normal; +} + async fn handle_buttonpress( system: &mut RestrictedSystem, room_state: &mut State, From 7d34931a76745b5c6bfcdc37d9c7d210cdb21729 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 30 Nov 2024 11:54:40 +0100 Subject: [PATCH 459/687] Fix accidentally blocking sleeps --- crates/brain/src/controller/mod.rs | 1 + .../src/controller/rooms/small_bedroom.rs | 83 ++++++++++++++----- 2 files changed, 63 insertions(+), 21 deletions(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index b4eba288..4bd45d46 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -29,6 +29,7 @@ pub enum Event { WakeUp, } +#[derive(Clone)] struct RestrictedSystem { allowed_lights: Vec<&'static str>, allowed_lights_new: Vec<&'static str>, diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 34274cdb..4afdb2fd 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -1,11 +1,15 @@ +use std::sync::Arc; use std::time::Duration; use futures_concurrency::future::Race; use futures_util::FutureExt; use protocol::small_bedroom::ButtonPanel; use protocol::{small_bedroom, Reading}; -use tokio::sync::broadcast; +use tokio::sync::broadcast::error::RecvError; +use tokio::sync::{broadcast, Mutex}; +use tokio::task; use tokio::time::{sleep, sleep_until, Instant}; +use tracing::warn; use zigbee_bridge::lights::{denormalize, kelvin_to_mired}; use crate::controller::{local_now, Event, RestrictedSystem}; @@ -34,7 +38,14 @@ impl RecvFiltered for broadcast::Receiver { filter_map: impl Fn(Event) -> Option, ) -> T { loop { - let event = self.recv().await.unwrap(); + let event = match self.recv().await { + Ok(event) => event, + Err(RecvError::Lagged(n)) => { + warn!("SB missed {n} events"); + continue; + } + Err(err) => panic!("{err}"), + }; if let Some(relevant) = filter_map(event) { return relevant; } @@ -69,7 +80,7 @@ pub async fn run( _event_tx: broadcast::Sender, mut system: RestrictedSystem, ) { - let mut room_state = State::Normal; + let room_state = Arc::new(Mutex::new(State::Normal)); let mut next_update = Instant::now() + UPDATE_INTERVAL; loop { let get_event = event_rx @@ -80,21 +91,27 @@ pub async fn run( let trigger = (get_event, tick).race().await; match trigger { Trigger::Event(RelevantEvent::Button(button)) => { - handle_buttonpress(&mut system, &mut room_state, button).await; + handle_buttonpress(system.clone(), room_state.clone(), button) + .await; } Trigger::Event(RelevantEvent::Wakeup) => { - run_wakeup(&mut system, &mut room_state).await; + task::spawn(run_wakeup(system.clone(), room_state.clone())); } Trigger::ShouldUpdate => { - set_time_color(&mut system, &room_state).await; + set_time_color(&mut system, room_state.clone()).await; next_update = Instant::now() + UPDATE_INTERVAL; } } } } -async fn run_wakeup(system: &mut RestrictedSystem, room_state: &mut State) { - *room_state = State::Wakeup; +async fn run_wakeup( + mut system: RestrictedSystem, + room_state: Arc>, +) { + { + *room_state.lock().await = State::Wakeup; + } let light_name = "small_bedroom:piano"; let bri = 1; @@ -111,6 +128,11 @@ async fn run_wakeup(system: &mut RestrictedSystem, room_state: &mut State) { for minute in 1..=20 { sleep(Duration::from_secs(1)).await; + // room state has changed, thus wakeup should be aborted + if *room_state.lock().await != State::Wakeup { + return; + } + let new_bri = ((bri as f64) * bri_growth.powi(minute)).round() as u8; let new_ct = (ct as f64 * ct_growth.powi(minute)).round() as usize; @@ -123,39 +145,58 @@ async fn run_wakeup(system: &mut RestrictedSystem, room_state: &mut State) { .await; } - *room_state = State::Normal; + *room_state.lock().await = State::Normal; +} + +async fn delayed_off( + mut system: RestrictedSystem, + room_state: Arc>, +) { + sleep(OFF_DELAY).await; + // room state has changed, thus off should be aborted + if *room_state.lock().await != State::Sleep { + return; + } + system.all_lamps_off().await; } async fn handle_buttonpress( - system: &mut RestrictedSystem, - room_state: &mut State, + mut system: RestrictedSystem, + room_state: Arc>, button: ButtonPanel, ) { dbg!(button); match button { ButtonPanel::BottomLeft(_) => { - *room_state = State::Sleep; + { + *room_state.lock().await = State::Sleep; + } system.one_lamp_off("small_bedroom:bureau").await; system.one_lamp_off("small_bedroom:piano").await; - sleep(OFF_DELAY).await; - system.all_lamps_off().await; + task::spawn(delayed_off(system.clone(), room_state.clone())); } ButtonPanel::BottomMiddle(_) => { - *room_state = State::Normal; + { + *room_state.lock().await = State::Normal; + } system.all_lamps_on().await; - set_time_color(system, &room_state).await; + set_time_color(&mut system, room_state).await; } ButtonPanel::BOttomRight(_) => { - *room_state = State::Override; - system.all_lamps_on().await; - system.all_lamps_ct(2000, 254).await; + task::spawn(run_wakeup(system.clone(), room_state.clone())); + // *room_state = State::Override; + // system.all_lamps_on().await; + // system.all_lamps_ct(2000, 254).await; } _ => (), } } -async fn set_time_color(system: &mut RestrictedSystem, room_state: &State) { - if room_state == &State::Normal { +async fn set_time_color( + system: &mut RestrictedSystem, + room_state: Arc>, +) { + if *room_state.lock().await == State::Normal { let (new_ct, new_bri) = optimal_ct_bri(); system.all_lamps_ct(new_ct, new_bri).await; } From 5bc814cb1dfdecbbe400cef6b87c7050b96aa512 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 30 Nov 2024 13:24:28 +0100 Subject: [PATCH 460/687] Change chrono and time to jiff in brain (untested) If it compiles it works, right? The database tree was renamed from alarms to jobs, so that should not give issues --- Cargo.lock | 64 +------- crates/brain/Cargo.toml | 2 +- crates/brain/src/controller/mod.rs | 18 --- crates/brain/src/controller/rooms/kitchen.rs | 4 +- .../src/controller/rooms/large_bedroom.rs | 19 ++- .../src/controller/rooms/small_bedroom.rs | 6 +- crates/brain/src/input/api.rs | 4 +- crates/brain/src/input/jobs.rs | 139 ++++++++---------- crates/brain/src/input/jobs/wakeup.rs | 58 ++++---- crates/brain/src/main.rs | 9 +- crates/brain/src/time.rs | 7 + 11 files changed, 128 insertions(+), 202 deletions(-) create mode 100644 crates/brain/src/time.rs diff --git a/Cargo.lock b/Cargo.lock index cdb7f4dd..c797c6e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,21 +38,6 @@ version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - [[package]] name = "anstream" version = "0.6.18" @@ -487,13 +472,13 @@ dependencies = [ "bincode", "byteorder", "bytes", - "chrono", "clap", "data-server", "futures", "futures-concurrency", "futures-util", "hueclient", + "jiff", "logger", "mpd", "protocol", @@ -597,21 +582,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chrono" -version = "0.4.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-targets 0.52.6", -] - [[package]] name = "clap" version = "4.5.21" @@ -1930,29 +1900,6 @@ dependencies = [ "nix 0.26.4", ] -[[package]] -name = "iana-time-zone" -version = "0.1.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - [[package]] name = "icu_collections" version = "1.5.0" @@ -4444,15 +4391,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-registry" version = "0.2.0" diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 8e351e08..24a0ed16 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -24,7 +24,7 @@ bincode = "1.3" thiserror = "1.0" -chrono = { version = "0.4", features = ["serde"] } +jiff = { workspace = true, features = ["serde"] } time = { workspace = true, features = ["macros"] } tz-rs = "0.6.14" diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 4bd45d46..74b6c313 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -3,26 +3,10 @@ mod rooms; use crate::system::System; pub use protocol::Reading; use serde::{Deserialize, Serialize}; -use time::{OffsetDateTime, UtcOffset}; use tokio::sync::broadcast; use tokio::task::JoinSet; use zigbee_bridge::lights::{mired_to_kelvin, normalize}; -// now_local works some of the time only... this replaces it with....... -// horrible hard coded time stuff. Chrono does provide reliable now_local -// however it has disadvantages (unsound + other flaws) -pub fn local_now() -> OffsetDateTime { - let utc = OffsetDateTime::now_utc(); - let offset = tz::TimeZone::local() - .unwrap() - .find_current_local_time_type() - .unwrap() - .ut_offset(); - - let offset = UtcOffset::from_whole_seconds(offset).unwrap(); - utc.to_offset(offset) -} - #[derive(Clone, Debug, Serialize, Deserialize)] pub enum Event { Sensor(Reading), @@ -58,7 +42,6 @@ impl RestrictedSystem { if self.allowed_lights_new.contains(&name) { self.system.lights_new.set_on(name); } - } async fn one_lamp_off(&mut self, name: &'static str) { @@ -69,7 +52,6 @@ impl RestrictedSystem { if self.allowed_lights_new.contains(&name) { self.system.lights_new.set_off(name); } - } async fn all_lamps_ct(&mut self, ct: u16, bri: u8) { diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index eba54e54..74e2358c 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -7,7 +7,7 @@ use tokio::time::{sleep_until, Instant}; use tracing::warn; use crate::controller::rooms::small_bedroom; -use crate::controller::{local_now, Event, RestrictedSystem}; +use crate::controller::{Event, RestrictedSystem}; enum State { // Sleep, @@ -90,7 +90,7 @@ async fn update(system: &mut RestrictedSystem) { } fn _testing_ct_bri() -> (u16, u8) { - let now = local_now(); + let now = crate::time::now(); // let optimal = match now.hour() { let optimal = match now.minute() { min if min % 2 == 0 => (400, u8::MAX), // Even hour: orange diff --git a/crates/brain/src/controller/rooms/large_bedroom.rs b/crates/brain/src/controller/rooms/large_bedroom.rs index 60e51689..32f97cfc 100644 --- a/crates/brain/src/controller/rooms/large_bedroom.rs +++ b/crates/brain/src/controller/rooms/large_bedroom.rs @@ -6,7 +6,7 @@ use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; use tracing::{info, warn}; -use crate::controller::{local_now, Event, RestrictedSystem}; +use crate::controller::{Event, RestrictedSystem}; #[derive(Debug, Clone, PartialEq, Eq)] enum State { @@ -22,11 +22,17 @@ enum State { const INTERVAL: Duration = Duration::from_secs(5); trait RecvFiltered { - async fn recv_filter_mapped(&mut self, filter_map: impl Fn(Event) -> Option) -> T; + async fn recv_filter_mapped( + &mut self, + filter_map: impl Fn(Event) -> Option, + ) -> T; } impl RecvFiltered for broadcast::Receiver { - async fn recv_filter_mapped(&mut self, filter_map: impl Fn(Event) -> Option) -> T { + async fn recv_filter_mapped( + &mut self, + filter_map: impl Fn(Event) -> Option, + ) -> T { loop { let event = self.recv().await.unwrap(); if let Some(relevant) = filter_map(event) { @@ -130,12 +136,13 @@ async fn update(system: &mut RestrictedSystem, state: &State) -> Option { } fn optimal_ct_bri() -> (u16, u8) { - let now = local_now(); + let now = crate::time::now(); match now.hour() { 0..=5 | 22.. => (500, 170), 6..=16 => (254, u8::MAX), 17..=19 => (320, u8::MAX), 20..=21 => (320, 220), + _ => (320, u8::MAX), } } @@ -154,7 +161,9 @@ fn handle_event(e: RelevantEvent) -> Option { } } -fn handle_desk_button(b: protocol::large_bedroom::desk::Button) -> Option { +fn handle_desk_button( + b: protocol::large_bedroom::desk::Button, +) -> Option { use protocol::large_bedroom::desk::Button; println!("button pressed: {b:?}"); diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 4afdb2fd..97e6a437 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -12,7 +12,7 @@ use tokio::time::{sleep, sleep_until, Instant}; use tracing::warn; use zigbee_bridge::lights::{denormalize, kelvin_to_mired}; -use crate::controller::{local_now, Event, RestrictedSystem}; +use crate::controller::{Event, RestrictedSystem}; #[derive(PartialEq, Eq, Debug)] enum State { @@ -202,12 +202,12 @@ async fn set_time_color( } } -const fn time(hour: u8, minute: u8) -> f64 { +const fn time(hour: i8, minute: i8) -> f64 { hour as f64 + minute as f64 / 60. } pub(crate) fn optimal_ct_bri() -> (u16, u8) { - let now = local_now(); + let now = crate::time::now(); const T0_00: f64 = time(0, 0); const T8_00: f64 = time(8, 0); const T9_00: f64 = time(9, 0); diff --git a/crates/brain/src/input/api.rs b/crates/brain/src/input/api.rs index b8041ce2..e8dd5094 100644 --- a/crates/brain/src/input/api.rs +++ b/crates/brain/src/input/api.rs @@ -27,7 +27,7 @@ async fn tomorrow(aState(state): aState) -> Vec { } async fn set_usually(aState(state): aState, body: Bytes) -> StatusCode { - let time: Option<(u8, u8)> = bincode::deserialize(&body[..]) + let time: Option<(i8, i8)> = bincode::deserialize(&body[..]) .map_err(|_| "Could not deserialize into time") .unwrap(); state @@ -41,7 +41,7 @@ async fn set_usually(aState(state): aState, body: Bytes) -> StatusCode { } async fn set_tomorrow(aState(state): aState, body: Bytes) -> StatusCode { - let time: Option<(u8, u8)> = bincode::deserialize(&body[..]) + let time: Option<(i8, i8)> = bincode::deserialize(&body[..]) .map_err(|_| "Could not deserialize into time") .unwrap(); state diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index 535ac087..313499c1 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -1,12 +1,9 @@ -use std::ops::Sub; -use std::sync::mpsc; -use std::thread; +use jiff::{Span, Zoned}; +use std::{sync::mpsc, thread, time::Duration}; use tokio::sync::broadcast; -use tracing::error; -use tracing::info; +use tracing::{error, info}; use byteorder::{BigEndian, ReadBytesExt}; -use chrono::{self, DateTime, Utc}; use serde::{Deserialize, Serialize}; use sled; @@ -25,18 +22,18 @@ pub enum Error { #[derive(Serialize, Deserialize, Debug)] pub struct Job { - pub time: DateTime, + pub time: Zoned, pub event: Event, - /// how long after the time was missed the alarm + /// how long after the time was missed the job /// should still go off - pub expiration: Option, + pub expiration: Option, } impl Job { pub fn from( - time: DateTime, + time: Zoned, event: Event, - expiration: Option, + expiration: Option, ) -> Self { Job { time, @@ -46,21 +43,6 @@ impl Job { } } -impl Sub for Job { - type Output = chrono::Duration; - - fn sub(self, other: Job) -> chrono::Duration { - self.time - other.time - } -} -impl Sub> for &Job { - type Output = chrono::Duration; - - fn sub(self, other: chrono::DateTime) -> chrono::Duration { - self.time - other - } -} - #[derive(Debug, Clone)] pub struct Jobs { waker_tx: mpsc::Sender<()>, @@ -74,28 +56,30 @@ struct JobList { use mpsc::RecvTimeoutError::*; fn waker( - mut alarm_list: JobList, + mut job_list: JobList, event_tx: broadcast::Sender, waker_rx: mpsc::Receiver<()>, ) { loop { - //This can fail #TODO make sure an non waking error alarm is send to the user - if let Some((id, current_alarm)) = alarm_list.peek_next() { - let now = Utc::now(); - let timeout = ¤t_alarm - now; + // This can fail + // TODO make sure an non waking error alarm is send to the user + if let Some((id, current_alarm)) = job_list.peek_next() { + let now = crate::time::now(); + let timeout = ¤t_alarm.time - &now; if let Some(expiration) = current_alarm.expiration { - if timeout < -chrono::Duration::from_std(expiration).unwrap() { - error!("skipping alarm to far in the past"); - alarm_list.remove_alarm(id).unwrap(); - continue; //alarm to far in the past, skip and get next + if now + > ¤t_alarm.time + Span::try_from(expiration).unwrap() + { + error!("skipping alarm too far in the past"); + job_list.remove_job(id).unwrap(); + continue; // alarm too far in the past, skip and get next } } - let timeout = timeout - .to_std() - .unwrap_or(std::time::Duration::from_secs(0)); + let timeout = + Duration::try_from(timeout).unwrap_or(Duration::from_secs(0)); info!("next alarm is in: {} seconds", timeout.as_secs()); - //do we sound an alarm or should we add or remove one? + // do we sound an alarm or should we add or remove one? match waker_rx.recv_timeout(timeout) { Ok(_) => continue, // new alarm entered restart loop Err(Disconnected) => return, @@ -104,7 +88,7 @@ fn waker( event_tx .send(current_alarm.event) .expect("controller should listen on this"); - alarm_list.remove_alarm(id).unwrap(); + job_list.remove_job(id).unwrap(); continue; //get next alarm } } @@ -113,7 +97,7 @@ fn waker( info!("no alarm in the future"); //A message through the mpsc signals an alarm has been added match waker_rx.recv() { - Ok(_) => break, //alarms were added or remove, go back and start waiting on it + Ok(_) => break, //alarms were added or remove, go back and start waiting on it Err(_) => return, //cant have timed out thus program should exit } } @@ -126,30 +110,33 @@ impl Jobs { db: sled::Db, ) -> Result<(Self, thread::JoinHandle<()>), Error> { let list = JobList { - db: db.open_tree("alarms")?, + db: db.open_tree("jobs")?, }; let (waker_tx, waker_rx) = mpsc::channel(); let waker_db_copy = list.clone(); - let waker_thread = thread::spawn(move || waker(waker_db_copy, event_tx, waker_rx)); + let waker_thread = + thread::spawn(move || waker(waker_db_copy, event_tx, waker_rx)); Ok((Self { list, waker_tx }, waker_thread)) } - // we decrease the time till the alarm until there is a place in the database - // as only one alarm can fire at the time, after an alarm gets a timeslot it is never changed - pub async fn add_alarm(&self, to_add: Job) -> Result { - let id = self.list.add_alarm(to_add).await?; + // we decrease the time till the job until there is a place in the database + // as only one job can fire at the time, after a job gets a timeslot + // it is never changed + pub async fn add_job(&self, to_add: Job) -> Result { + let id = self.list.add_job(to_add).await?; //signal waker to update its next alarm + // TODO this feels like it shouldn't be here in this way self.waker_tx.send(())?; Ok(id) } - pub fn remove_alarm(&self, to_remove: u64) -> Result, Error> { - let removed_alarm = self.list.remove_alarm(to_remove)?; + pub fn remove_job(&self, to_remove: i64) -> Result, Error> { + let removed_alarm = self.list.remove_job(to_remove)?; self.waker_tx.send(())?; //signal waker to update its next alarm Ok(removed_alarm) } - pub fn get(&self, id: u64) -> Result, Error> { + pub fn get(&self, id: i64) -> Result, Error> { self.list.get_alarm(id) } @@ -168,7 +155,7 @@ impl Jobs { } impl JobList { - pub fn get_alarm(&self, id: u64) -> Result, Error> { + pub fn get_alarm(&self, id: i64) -> Result, Error> { Ok(self .db .get(id.to_be_bytes())? @@ -176,50 +163,48 @@ impl JobList { } // we decrease the time till the alarm until there is a place in the database - // as only one alarm can fire at the time, after an alarm gets a timeslot it is never changed + // as only one alarm can fire at the time, after an alarm gets a timeslot + // it is never changed /// return the key for the alarm - async fn add_alarm(&self, to_add: Job) -> Result { - let mut timestamp = to_add.time.timestamp() as u64; - let mut timestamp_array = timestamp.to_be_bytes(); - let alarm = bincode::serialize(&to_add).unwrap(); - - //create alarm entry if there is no alarm at this timestamp yet - //if there is already an alarm scheduled, postpone this one until there is a spot free - //self.db.cas(&[1], None as Option<&[u8]>, Some(&[10]) - //TODO check how this works and expand sled documentation for fail cases + async fn add_job(&self, to_add: Job) -> Result { + let mut timestamp = to_add.time.timestamp().as_millisecond(); + let job = bincode::serialize(&to_add).unwrap(); + + // create alarm entry if there is no alarm at this timestamp yet + // if there is already an alarm scheduled, change the key for this one + // until there is a spot free + // TODO check how this works and expand sled documentation for fail cases while let Err(_old_event) = self.db.compare_and_swap( - timestamp_array, + timestamp.to_be_bytes(), None as Option<&[u8]>, - Some(alarm.clone()), + Some(job.clone()), )? { - //cas unique creation + // create unique key timestamp -= 1; - timestamp_array = timestamp.to_be_bytes(); } self.db.flush_async().await?; Ok(timestamp) } - pub fn remove_alarm(&self, to_remove: u64) -> Result, Error> { - let old_alarm = self + pub fn remove_job(&self, to_remove: i64) -> Result, Error> { + let old_job = self .db .remove(to_remove.to_be_bytes())? .map(|k| bincode::deserialize::(&k).unwrap()); self.db.flush()?; - Ok(old_alarm) + Ok(old_job) } - /// calculate time to the earliest alarm, remove it from the list if the current time is later - /// then the alarm - fn peek_next(&mut self) -> Option<(u64, Job)> { - //get earliest alarm time in db + /// calculate time to the earliest job, remove it from the list if the + /// current time is later than the job + fn peek_next(&mut self) -> Option<(i64, Job)> { + // get earliest job time in db match self.db.get_gt(0u64.to_be_bytes()) { Ok(entry) => { - if let Some(entry) = entry { - let (id, alarm) = entry; - let id = id.as_ref().read_u64::().unwrap(); - let alarm = bincode::deserialize(&alarm).unwrap(); - Some((id, alarm)) + if let Some((id, job)) = entry { + let id = id.as_ref().read_i64::().unwrap(); + let job = bincode::deserialize(&job).unwrap(); + Some((id, job)) } else { None } diff --git a/crates/brain/src/input/jobs/wakeup.rs b/crates/brain/src/input/jobs/wakeup.rs index 694c3721..0777278f 100644 --- a/crates/brain/src/input/jobs/wakeup.rs +++ b/crates/brain/src/input/jobs/wakeup.rs @@ -1,7 +1,7 @@ use crate::controller::Event; use super::{Job, Jobs}; -use chrono::{DateTime, Local, Timelike, Utc}; +use jiff::Zoned; use std::sync::Arc; use std::time::Duration; use tokio::runtime::Runtime; @@ -22,7 +22,10 @@ pub enum Error { JobError(#[from] super::Error), } -async fn reset_on_wakeup(wake_up: WakeUp, mut event_rx: broadcast::Receiver) { +async fn reset_on_wakeup( + wake_up: WakeUp, + mut event_rx: broadcast::Receiver, +) { loop { match event_rx.recv().await { Ok(Event::WakeUp) => { @@ -55,10 +58,10 @@ impl WakeUp { Ok(Self(inner)) } - pub async fn tomorrow(&self) -> Option<(u8, u8)> { + pub async fn tomorrow(&self) -> Option<(i8, i8)> { self.0.lock().await.tomorrow } - pub async fn usually(&self) -> Option<(u8, u8)> { + pub async fn usually(&self) -> Option<(i8, i8)> { self.0.lock().await.usually } pub fn reset(&self) -> Result<(), Error> { @@ -78,12 +81,12 @@ impl WakeUp { } } -type Time = Option<(u8, u8)>; +type Time = Option<(i8, i8)>; struct Inner { db: sled::Tree, pub tomorrow: Time, pub usually: Time, - job_id: Option, + job_id: Option, jobs: Jobs, } @@ -93,15 +96,15 @@ impl Inner { let usually = db .get("usually")? - // we want bincode to deserialize to Option<(u8,u8)> not (u8,u8) + // we want bincode to deserialize to Option<(i8,i8)> not (i8,i8) .and_then(|b| bincode::deserialize(&b).unwrap()); - let job_id = db.get("job_id")?.map(|b| bincode::deserialize(&b).unwrap()); + let job_id = + db.get("job_id")?.map(|b| bincode::deserialize(&b).unwrap()); let next_alarm = job_id .as_ref() .and_then(|id| jobs.get(*id).unwrap()) - .map(|job| job.time.into()) - .map(|t: DateTime| t) - .map(|t| (t.hour() as u8, t.minute() as u8)); + .map(|job| job.time) + .map(|t| (t.hour() as i8, t.minute() as i8)); let tomorrow = next_alarm.filter(|tomorrow| Some(*tomorrow) != usually); Ok(Self { @@ -114,12 +117,12 @@ impl Inner { } /// stores a new job - fn save_job_id(&mut self, id: u64) -> Result<(), Error> { + fn save_job_id(&mut self, id: i64) -> Result<(), Error> { self.job_id = Some(id); let bytes = bincode::serialize(&id).unwrap(); if let Some(bytes) = self.db.insert("job_id", bytes)? { let old_job_id = bincode::deserialize(&bytes).unwrap(); - self.jobs.remove_alarm(old_job_id)?; + self.jobs.remove_job(old_job_id)?; } self.db.flush().unwrap(); Ok(()) @@ -133,13 +136,13 @@ impl Inner { } async fn replace_job(&mut self, job: Job) -> Result<(), Error> { - let id = self.jobs.add_alarm(job).await?; + let id = self.jobs.add_job(job).await?; self.save_job_id(id)?; Ok(()) } fn remove_job(&mut self) -> Result<(), Error> { - self.jobs.remove_alarm(self.job_id.unwrap())?; + self.jobs.remove_job(self.job_id.unwrap())?; self.job_id = None; Ok(()) } @@ -187,7 +190,7 @@ impl Inner { } } -fn job_from(hour: u8, min: u8) -> Job { +fn job_from(hour: i8, min: i8) -> Job { Job { time: to_datetime(hour, min), event: Event::WakeUp, @@ -195,21 +198,20 @@ fn job_from(hour: u8, min: u8) -> Job { } } -fn to_datetime(hour: u8, min: u8) -> DateTime { - let (hour, min) = (hour as u32, min as u32); - let now = Local::now(); - let today = now.date_naive(); - let alarm = today.and_hms_opt(hour, min, 0).unwrap(); +fn to_datetime(hour: i8, min: i8) -> Zoned { + let now = crate::time::now(); + let job_time = now.with().hour(hour).minute(min).second(0).build().unwrap(); - if alarm < now.naive_local() { - let tomorrow = now.date_naive().succ_opt().unwrap(); + if job_time < now { + let tomorrow = now.tomorrow().unwrap(); tomorrow - .and_hms_opt(hour, min, 0) + .with() + .hour(hour) + .minute(min) + .second(0) + .build() .unwrap() - .and_local_timezone(Local) - .unwrap() - .with_timezone(&Utc) } else { - alarm.and_local_timezone(Local).unwrap().with_timezone(&Utc) + job_time } } diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index 667a022a..96a706c6 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -3,11 +3,12 @@ use std::net::{IpAddr, SocketAddr}; use clap::Parser; use tokio::sync::broadcast; + mod controller; mod system; - mod errors; mod input; +mod time; #[derive(Parser)] #[command(version, about, long_about=None)] @@ -46,8 +47,10 @@ async fn main() -> Result<(), Box> { let (event_tx, event_rx) = broadcast::channel(250); let subscribed_rxs = array::from_fn(|_| event_tx.subscribe()); - let (jobs, _waker_thread) = input::jobs::Jobs::setup(event_tx.clone(), db.clone())?; - let wakeup = input::jobs::WakeUp::setup(db.clone(), jobs.clone(), event_rx)?; + let (jobs, _waker_thread) = + input::jobs::Jobs::setup(event_tx.clone(), db.clone())?; + let wakeup = + input::jobs::WakeUp::setup(db.clone(), jobs.clone(), event_rx)?; // let (_mpd_status, _mpd_watcher_thread, _updater_tx) = // input::MpdStatus::start_updating(opt.mpd_ip)?; diff --git a/crates/brain/src/time.rs b/crates/brain/src/time.rs new file mode 100644 index 00000000..b34d479e --- /dev/null +++ b/crates/brain/src/time.rs @@ -0,0 +1,7 @@ +use jiff::{tz::TimeZone, Timestamp, Zoned}; + +// Because the pi might be set to UTC, we need to manually add the tz +pub(crate) fn now() -> Zoned { + let local = TimeZone::get("Amsterdam").unwrap(); + Timestamp::now().to_zoned(local) +} From ab59cccb09914301fc9ff3c4b21f8f544f860803 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 1 Dec 2024 11:57:32 +0100 Subject: [PATCH 461/687] Rename alarm.. to job.., move to_datetime out of wakeup --- crates/brain/src/input/jobs.rs | 50 ++++++++++++++------------- crates/brain/src/input/jobs/wakeup.rs | 38 ++++++-------------- crates/brain/src/time.rs | 18 ++++++++++ 3 files changed, 54 insertions(+), 52 deletions(-) diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index 313499c1..dc743f40 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -7,7 +7,7 @@ use byteorder::{BigEndian, ReadBytesExt}; use serde::{Deserialize, Serialize}; use sled; -use crate::controller::Event; +use crate::{controller::Event, time::to_datetime}; pub mod wakeup; pub use wakeup::WakeUp; @@ -30,13 +30,14 @@ pub struct Job { } impl Job { - pub fn from( - time: Zoned, + fn at_next( + hour: i8, + min: i8, event: Event, expiration: Option, - ) -> Self { + ) -> Job { Job { - time, + time: to_datetime(hour, min), event, expiration, } @@ -63,42 +64,43 @@ fn waker( loop { // This can fail // TODO make sure an non waking error alarm is send to the user - if let Some((id, current_alarm)) = job_list.peek_next() { + if let Some((id, current_job)) = job_list.peek_next() { let now = crate::time::now(); - let timeout = ¤t_alarm.time - &now; - if let Some(expiration) = current_alarm.expiration { - if now - > ¤t_alarm.time + Span::try_from(expiration).unwrap() + let timeout = ¤t_job.time - &now; + if let Some(expiration) = current_job.expiration { + if now > ¤t_job.time + Span::try_from(expiration).unwrap() { - error!("skipping alarm too far in the past"); + error!("skipping job too far in the past"); job_list.remove_job(id).unwrap(); - continue; // alarm too far in the past, skip and get next + continue; // job too far in the past, skip and get next } } let timeout = Duration::try_from(timeout).unwrap_or(Duration::from_secs(0)); - info!("next alarm is in: {} seconds", timeout.as_secs()); + info!("next job is in: {} seconds", timeout.as_secs()); - // do we sound an alarm or should we add or remove one? + // do we send out the event or should we add or remove a job? match waker_rx.recv_timeout(timeout) { - Ok(_) => continue, // new alarm entered restart loop + Ok(_) => continue, // new job entered, restart loop Err(Disconnected) => return, Err(Timeout) => { - // time to sound the alarm + // time to send the job event event_tx - .send(current_alarm.event) + .send(current_job.event) .expect("controller should listen on this"); job_list.remove_job(id).unwrap(); - continue; //get next alarm + continue; //get next job } } } else { //no alarm to wait on, wait for instructions - info!("no alarm in the future"); + info!("no job in the future"); //A message through the mpsc signals an alarm has been added match waker_rx.recv() { - Ok(_) => break, //alarms were added or remove, go back and start waiting on it - Err(_) => return, //cant have timed out thus program should exit + // jobs were added or removed, go back and start waiting on them + Ok(_) => break, + // can't have timed out thus program should exit + Err(_) => return, } } } @@ -109,16 +111,16 @@ impl Jobs { event_tx: broadcast::Sender, db: sled::Db, ) -> Result<(Self, thread::JoinHandle<()>), Error> { - let list = JobList { + let job_list = JobList { db: db.open_tree("jobs")?, }; let (waker_tx, waker_rx) = mpsc::channel(); - let waker_db_copy = list.clone(); + let waker_db_copy = job_list.clone(); let waker_thread = thread::spawn(move || waker(waker_db_copy, event_tx, waker_rx)); - Ok((Self { list, waker_tx }, waker_thread)) + Ok((Self { list: job_list, waker_tx }, waker_thread)) } // we decrease the time till the job until there is a place in the database diff --git a/crates/brain/src/input/jobs/wakeup.rs b/crates/brain/src/input/jobs/wakeup.rs index 0777278f..03cf77c5 100644 --- a/crates/brain/src/input/jobs/wakeup.rs +++ b/crates/brain/src/input/jobs/wakeup.rs @@ -1,7 +1,6 @@ use crate::controller::Event; use super::{Job, Jobs}; -use jiff::Zoned; use std::sync::Arc; use std::time::Duration; use tokio::runtime::Runtime; @@ -151,7 +150,7 @@ impl Inner { /// time we set that, otherwise remove all pub fn reset(&mut self) -> Result<(), Error> { if let Some((hour, min)) = self.usually { - let job = job_from(hour, min); + let job = wakeup_at_next(hour, min); let add = self.replace_job(job); let rt = Runtime::new().unwrap(); rt.block_on(add)?; @@ -164,7 +163,7 @@ impl Inner { match time { None => self.reset()?, Some((hour, min)) => { - let job = job_from(hour, min); + let job = wakeup_at_next(hour, min); self.replace_job(job).await?; } } @@ -176,7 +175,7 @@ impl Inner { self.save_usually(&time)?; match time { Some((hour, min)) => { - let job = job_from(hour, min); + let job = wakeup_at_next(hour, min); self.replace_job(job).await?; } None => { @@ -190,28 +189,11 @@ impl Inner { } } -fn job_from(hour: i8, min: i8) -> Job { - Job { - time: to_datetime(hour, min), - event: Event::WakeUp, - expiration: Some(Duration::from_secs(3 * 60 * 60)), - } -} - -fn to_datetime(hour: i8, min: i8) -> Zoned { - let now = crate::time::now(); - let job_time = now.with().hour(hour).minute(min).second(0).build().unwrap(); - - if job_time < now { - let tomorrow = now.tomorrow().unwrap(); - tomorrow - .with() - .hour(hour) - .minute(min) - .second(0) - .build() - .unwrap() - } else { - job_time - } +fn wakeup_at_next(hour: i8, min: i8) -> Job { + Job::at_next( + hour, + min, + Event::WakeUp, + Some(Duration::from_secs(3 * 60 * 60)), + ) } diff --git a/crates/brain/src/time.rs b/crates/brain/src/time.rs index b34d479e..03a6eb21 100644 --- a/crates/brain/src/time.rs +++ b/crates/brain/src/time.rs @@ -5,3 +5,21 @@ pub(crate) fn now() -> Zoned { let local = TimeZone::get("Amsterdam").unwrap(); Timestamp::now().to_zoned(local) } + +pub(crate) fn to_datetime(hour: i8, min: i8) -> Zoned { + let now = crate::time::now(); + let job_time = now.with().hour(hour).minute(min).second(0).build().unwrap(); + + if job_time < now { + let tomorrow = now.tomorrow().unwrap(); + tomorrow + .with() + .hour(hour) + .minute(min) + .second(0) + .build() + .unwrap() + } else { + job_time + } +} From a41cce87cade41cbe4801febeaa4aec7738eab0f Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 1 Dec 2024 12:10:24 +0100 Subject: [PATCH 462/687] Renames in jobs --- crates/brain/src/input/jobs.rs | 80 ++++++++++++++++------------------ crates/brain/src/main.rs | 2 +- 2 files changed, 38 insertions(+), 44 deletions(-) diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index dc743f40..42799b85 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -14,9 +14,9 @@ pub use wakeup::WakeUp; #[derive(thiserror::Error, Debug)] pub enum Error { - #[error("Could store/edit job on disk")] + #[error("Could not store/edit job on disk")] DbError(#[from] sled::Error), - #[error("Could not inform waker about new job")] + #[error("Could not inform event timer about new job")] CommError(#[from] mpsc::SendError<()>), } @@ -25,7 +25,7 @@ pub struct Job { pub time: Zoned, pub event: Event, /// how long after the time was missed the job - /// should still go off + /// should still be executed pub expiration: Option, } @@ -46,7 +46,7 @@ impl Job { #[derive(Debug, Clone)] pub struct Jobs { - waker_tx: mpsc::Sender<()>, + job_change_tx: mpsc::Sender<()>, list: JobList, } @@ -56,10 +56,10 @@ struct JobList { } use mpsc::RecvTimeoutError::*; -fn waker( +fn event_timer( mut job_list: JobList, event_tx: broadcast::Sender, - waker_rx: mpsc::Receiver<()>, + job_change_rx: mpsc::Receiver<()>, ) { loop { // This can fail @@ -80,7 +80,7 @@ fn waker( info!("next job is in: {} seconds", timeout.as_secs()); // do we send out the event or should we add or remove a job? - match waker_rx.recv_timeout(timeout) { + match job_change_rx.recv_timeout(timeout) { Ok(_) => continue, // new job entered, restart loop Err(Disconnected) => return, Err(Timeout) => { @@ -93,10 +93,10 @@ fn waker( } } } else { - //no alarm to wait on, wait for instructions + //no job to wait on, wait for instructions info!("no job in the future"); - //A message through the mpsc signals an alarm has been added - match waker_rx.recv() { + //A message through the mpsc signals a job has been added + match job_change_rx.recv() { // jobs were added or removed, go back and start waiting on them Ok(_) => break, // can't have timed out thus program should exit @@ -115,12 +115,19 @@ impl Jobs { db: db.open_tree("jobs")?, }; - let (waker_tx, waker_rx) = mpsc::channel(); - let waker_db_copy = job_list.clone(); - let waker_thread = - thread::spawn(move || waker(waker_db_copy, event_tx, waker_rx)); - - Ok((Self { list: job_list, waker_tx }, waker_thread)) + let (job_change_tx, job_change_rx) = mpsc::channel(); + let job_list_clone = job_list.clone(); + let event_timer_thread = thread::spawn(move || { + event_timer(job_list_clone, event_tx, job_change_rx) + }); + + Ok(( + Self { + list: job_list, + job_change_tx, + }, + event_timer_thread, + )) } // we decrease the time till the job until there is a place in the database @@ -128,52 +135,39 @@ impl Jobs { // it is never changed pub async fn add_job(&self, to_add: Job) -> Result { let id = self.list.add_job(to_add).await?; - //signal waker to update its next alarm - // TODO this feels like it shouldn't be here in this way - self.waker_tx.send(())?; + //signal event timer to update its next job + self.job_change_tx.send(())?; Ok(id) } pub fn remove_job(&self, to_remove: i64) -> Result, Error> { - let removed_alarm = self.list.remove_job(to_remove)?; - self.waker_tx.send(())?; //signal waker to update its next alarm - Ok(removed_alarm) + let removed_job = self.list.remove_job(to_remove)?; + //signal event timer to update its next job + self.job_change_tx.send(())?; + Ok(removed_job) } pub fn get(&self, id: i64) -> Result, Error> { - self.list.get_alarm(id) + self.list.get_job(id) } - - // pub fn list(&self) -> Vec<(u64, Job)> { - // let start: &[u8] = &[0]; - // let alarms = self.list.db.range(start..); - // - // let mut list = Vec::new(); - // for (key, alarm) in alarms.filter_map(Result::ok) { - // let alarm = bincode::deserialize(&alarm).unwrap(); - // let key = key.as_ref().read_u64::().unwrap(); - // list.push((key, alarm)); - // } - // list - // } } impl JobList { - pub fn get_alarm(&self, id: i64) -> Result, Error> { + pub fn get_job(&self, id: i64) -> Result, Error> { Ok(self .db .get(id.to_be_bytes())? .map(|k| bincode::deserialize::(&k).unwrap())) } - // we decrease the time till the alarm until there is a place in the database - // as only one alarm can fire at the time, after an alarm gets a timeslot + // we decrease the time till the job until there is a place in the database + // as only one job can fire at the time, after a job gets a timeslot // it is never changed - /// return the key for the alarm + /// return the key for the job async fn add_job(&self, to_add: Job) -> Result { let mut timestamp = to_add.time.timestamp().as_millisecond(); let job = bincode::serialize(&to_add).unwrap(); - // create alarm entry if there is no alarm at this timestamp yet - // if there is already an alarm scheduled, change the key for this one + // create job entry if there is no job at this timestamp yet + // if there is already a job scheduled, change the key for this one // until there is a spot free // TODO check how this works and expand sled documentation for fail cases while let Err(_old_event) = self.db.compare_and_swap( @@ -212,7 +206,7 @@ impl JobList { } } Err(error) => { - error!("Could not retrieve next alarm: {:?}", error); + error!("Could not retrieve next job: {:?}", error); None } } diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index 96a706c6..56c38493 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -47,7 +47,7 @@ async fn main() -> Result<(), Box> { let (event_tx, event_rx) = broadcast::channel(250); let subscribed_rxs = array::from_fn(|_| event_tx.subscribe()); - let (jobs, _waker_thread) = + let (jobs, _event_timer_thread) = input::jobs::Jobs::setup(event_tx.clone(), db.clone())?; let wakeup = input::jobs::WakeUp::setup(db.clone(), jobs.clone(), event_rx)?; From d4bbeb14f0b72a2bcc43d9abf9af253435522321 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 1 Dec 2024 12:28:41 +0100 Subject: [PATCH 463/687] Small rearrangements, yagni and less pub --- crates/brain/src/input/jobs.rs | 158 ++++++++++++++++----------------- crates/brain/src/main.rs | 13 +-- 2 files changed, 86 insertions(+), 85 deletions(-) diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index 42799b85..e9a46897 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -1,11 +1,11 @@ -use jiff::{Span, Zoned}; use std::{sync::mpsc, thread, time::Duration}; -use tokio::sync::broadcast; -use tracing::{error, info}; use byteorder::{BigEndian, ReadBytesExt}; +use jiff::{Span, Zoned}; +use mpsc::RecvTimeoutError::*; use serde::{Deserialize, Serialize}; -use sled; +use tokio::sync::broadcast; +use tracing::{error, info}; use crate::{controller::Event, time::to_datetime}; @@ -13,7 +13,7 @@ pub mod wakeup; pub use wakeup::WakeUp; #[derive(thiserror::Error, Debug)] -pub enum Error { +pub(crate) enum Error { #[error("Could not store/edit job on disk")] DbError(#[from] sled::Error), #[error("Could not inform event timer about new job")] @@ -21,12 +21,12 @@ pub enum Error { } #[derive(Serialize, Deserialize, Debug)] -pub struct Job { - pub time: Zoned, - pub event: Event, +pub(crate) struct Job { + pub(crate) time: Zoned, + pub(crate) event: Event, /// how long after the time was missed the job /// should still be executed - pub expiration: Option, + pub(crate) expiration: Option, } impl Job { @@ -45,7 +45,7 @@ impl Job { } #[derive(Debug, Clone)] -pub struct Jobs { +pub(crate) struct Jobs { job_change_tx: mpsc::Sender<()>, list: JobList, } @@ -55,103 +55,53 @@ struct JobList { db: sled::Tree, } -use mpsc::RecvTimeoutError::*; -fn event_timer( - mut job_list: JobList, - event_tx: broadcast::Sender, - job_change_rx: mpsc::Receiver<()>, -) { - loop { - // This can fail - // TODO make sure an non waking error alarm is send to the user - if let Some((id, current_job)) = job_list.peek_next() { - let now = crate::time::now(); - let timeout = ¤t_job.time - &now; - if let Some(expiration) = current_job.expiration { - if now > ¤t_job.time + Span::try_from(expiration).unwrap() - { - error!("skipping job too far in the past"); - job_list.remove_job(id).unwrap(); - continue; // job too far in the past, skip and get next - } - } - let timeout = - Duration::try_from(timeout).unwrap_or(Duration::from_secs(0)); - info!("next job is in: {} seconds", timeout.as_secs()); - - // do we send out the event or should we add or remove a job? - match job_change_rx.recv_timeout(timeout) { - Ok(_) => continue, // new job entered, restart loop - Err(Disconnected) => return, - Err(Timeout) => { - // time to send the job event - event_tx - .send(current_job.event) - .expect("controller should listen on this"); - job_list.remove_job(id).unwrap(); - continue; //get next job - } - } - } else { - //no job to wait on, wait for instructions - info!("no job in the future"); - //A message through the mpsc signals a job has been added - match job_change_rx.recv() { - // jobs were added or removed, go back and start waiting on them - Ok(_) => break, - // can't have timed out thus program should exit - Err(_) => return, - } - } - } -} - impl Jobs { - pub fn setup( + pub(crate) fn setup( event_tx: broadcast::Sender, db: sled::Db, - ) -> Result<(Self, thread::JoinHandle<()>), Error> { - let job_list = JobList { - db: db.open_tree("jobs")?, - }; + ) -> Result { + let job_list = JobList::new(db)?; let (job_change_tx, job_change_rx) = mpsc::channel(); let job_list_clone = job_list.clone(); - let event_timer_thread = thread::spawn(move || { + thread::spawn(move || { event_timer(job_list_clone, event_tx, job_change_rx) }); - Ok(( - Self { - list: job_list, - job_change_tx, - }, - event_timer_thread, - )) + Ok(Self { + list: job_list, + job_change_tx, + }) } // we decrease the time till the job until there is a place in the database // as only one job can fire at the time, after a job gets a timeslot // it is never changed - pub async fn add_job(&self, to_add: Job) -> Result { + pub(crate) async fn add_job(&self, to_add: Job) -> Result { let id = self.list.add_job(to_add).await?; //signal event timer to update its next job self.job_change_tx.send(())?; Ok(id) } - pub fn remove_job(&self, to_remove: i64) -> Result, Error> { + pub(crate) fn remove_job(&self, to_remove: i64) -> Result, Error> { let removed_job = self.list.remove_job(to_remove)?; //signal event timer to update its next job self.job_change_tx.send(())?; Ok(removed_job) } - pub fn get(&self, id: i64) -> Result, Error> { + pub(crate) fn get(&self, id: i64) -> Result, Error> { self.list.get_job(id) } } impl JobList { - pub fn get_job(&self, id: i64) -> Result, Error> { + fn new(db: sled::Db) -> Result { + Ok(JobList { + db: db.open_tree("jobs")?, + }) + } + + fn get_job(&self, id: i64) -> Result, Error> { Ok(self .db .get(id.to_be_bytes())? @@ -182,7 +132,7 @@ impl JobList { Ok(timestamp) } - pub fn remove_job(&self, to_remove: i64) -> Result, Error> { + fn remove_job(&self, to_remove: i64) -> Result, Error> { let old_job = self .db .remove(to_remove.to_be_bytes())? @@ -212,3 +162,53 @@ impl JobList { } } } + +fn event_timer( + mut job_list: JobList, + event_tx: broadcast::Sender, + job_change_rx: mpsc::Receiver<()>, +) { + loop { + // This can fail + // TODO make sure an non waking error alarm is send to the user + if let Some((id, current_job)) = job_list.peek_next() { + let now = crate::time::now(); + let timeout = ¤t_job.time - &now; + if let Some(expiration) = current_job.expiration { + if now > ¤t_job.time + Span::try_from(expiration).unwrap() + { + error!("skipping job too far in the past"); + job_list.remove_job(id).unwrap(); + continue; // job too far in the past, skip and get next + } + } + let timeout = + Duration::try_from(timeout).unwrap_or(Duration::from_secs(0)); + info!("next job is in: {} seconds", timeout.as_secs()); + + // do we send out the event or should we add or remove a job? + match job_change_rx.recv_timeout(timeout) { + Ok(_) => continue, // new job entered, restart loop + Err(Disconnected) => return, + Err(Timeout) => { + // time to send the job event + event_tx + .send(current_job.event) + .expect("controller should listen on this"); + job_list.remove_job(id).unwrap(); + continue; //get next job + } + } + } else { + //no job to wait on, wait for instructions + info!("no job in the future"); + //A message through the mpsc signals a job has been added + match job_change_rx.recv() { + // jobs were added or removed, go back and start waiting on them + Ok(_) => break, + // can't have timed out thus program should exit + Err(_) => return, + } + } + } +} diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index 56c38493..fc368f3e 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -4,10 +4,13 @@ use std::net::{IpAddr, SocketAddr}; use clap::Parser; use tokio::sync::broadcast; +use self::input::jobs::{Jobs, WakeUp}; +use self::system::System; + mod controller; -mod system; mod errors; mod input; +mod system; mod time; #[derive(Parser)] @@ -47,14 +50,12 @@ async fn main() -> Result<(), Box> { let (event_tx, event_rx) = broadcast::channel(250); let subscribed_rxs = array::from_fn(|_| event_tx.subscribe()); - let (jobs, _event_timer_thread) = - input::jobs::Jobs::setup(event_tx.clone(), db.clone())?; - let wakeup = - input::jobs::WakeUp::setup(db.clone(), jobs.clone(), event_rx)?; + let jobs = Jobs::setup(event_tx.clone(), db.clone())?; + let wakeup = WakeUp::setup(db.clone(), jobs.clone(), event_rx)?; // let (_mpd_status, _mpd_watcher_thread, _updater_tx) = // input::MpdStatus::start_updating(opt.mpd_ip)?; - let system = system::System::init(jobs, opt.hue_bridge_ip); + let system = System::init(jobs, opt.hue_bridge_ip); let _tasks = controller::start(subscribed_rxs, event_tx.clone(), system); tokio::task::spawn(input::sensors::subscribe(event_tx, opt.data_server)); From 2e4ed7f76de385649ac3695ed69a751871bf642c Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 1 Dec 2024 12:54:51 +0100 Subject: [PATCH 464/687] Move wakeup mod to large_bedroom It's still entangled with everything though --- crates/brain/src/controller/mod.rs | 3 ++- crates/brain/src/controller/rooms/large_bedroom.rs | 4 +++- .../jobs => controller/rooms/large_bedroom}/wakeup.rs | 4 ++-- crates/brain/src/errors.rs | 2 +- crates/brain/src/input/api.rs | 3 ++- crates/brain/src/input/jobs.rs | 5 +---- crates/brain/src/main.rs | 11 +++++++---- 7 files changed, 18 insertions(+), 14 deletions(-) rename crates/brain/src/{input/jobs => controller/rooms/large_bedroom}/wakeup.rs (98%) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 74b6c313..33632253 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -1,4 +1,5 @@ mod rooms; +pub(crate) use rooms::large_bedroom; use crate::system::System; pub use protocol::Reading; @@ -14,7 +15,7 @@ pub enum Event { } #[derive(Clone)] -struct RestrictedSystem { +pub(crate) struct RestrictedSystem { allowed_lights: Vec<&'static str>, allowed_lights_new: Vec<&'static str>, system: System, diff --git a/crates/brain/src/controller/rooms/large_bedroom.rs b/crates/brain/src/controller/rooms/large_bedroom.rs index 32f97cfc..93a68db3 100644 --- a/crates/brain/src/controller/rooms/large_bedroom.rs +++ b/crates/brain/src/controller/rooms/large_bedroom.rs @@ -8,6 +8,8 @@ use tracing::{info, warn}; use crate::controller::{Event, RestrictedSystem}; +pub(crate) mod wakeup; + #[derive(Debug, Clone, PartialEq, Eq)] enum State { // Sleep, @@ -71,7 +73,7 @@ fn filter(event: Event) -> Option { }) } -pub async fn run( +pub(crate) async fn run( mut event_rx: broadcast::Receiver, // todo if state change message everyone using this _event_tx: broadcast::Sender, diff --git a/crates/brain/src/input/jobs/wakeup.rs b/crates/brain/src/controller/rooms/large_bedroom/wakeup.rs similarity index 98% rename from crates/brain/src/input/jobs/wakeup.rs rename to crates/brain/src/controller/rooms/large_bedroom/wakeup.rs index 03cf77c5..fe865ac0 100644 --- a/crates/brain/src/input/jobs/wakeup.rs +++ b/crates/brain/src/controller/rooms/large_bedroom/wakeup.rs @@ -1,6 +1,6 @@ use crate::controller::Event; +use crate::input::jobs::{self, Job, Jobs}; -use super::{Job, Jobs}; use std::sync::Arc; use std::time::Duration; use tokio::runtime::Runtime; @@ -18,7 +18,7 @@ pub enum Error { #[error("Error modifying wakeup alarms: {0}")] DbError(#[from] sled::Error), #[error("Could not create/edit wakeup job")] - JobError(#[from] super::Error), + JobError(#[from] jobs::Error), } async fn reset_on_wakeup( diff --git a/crates/brain/src/errors.rs b/crates/brain/src/errors.rs index 6f432c3e..cafd131c 100644 --- a/crates/brain/src/errors.rs +++ b/crates/brain/src/errors.rs @@ -11,5 +11,5 @@ pub enum Error { #[error("Error contacting mpd")] Mpd(#[from] mpd::error::Error), #[error("Error in the wakeup alarm system")] - SetWakeUp(#[from] crate::input::jobs::wakeup::Error), + SetWakeUp(#[from] crate::controller::large_bedroom::wakeup::Error), } diff --git a/crates/brain/src/input/api.rs b/crates/brain/src/input/api.rs index e8dd5094..0c08e12e 100644 --- a/crates/brain/src/input/api.rs +++ b/crates/brain/src/input/api.rs @@ -4,7 +4,8 @@ use axum::http::StatusCode; use axum::routing::get; use axum::Router; -use super::jobs::WakeUp; +use crate::controller::large_bedroom::wakeup::WakeUp; + #[derive(Debug, thiserror::Error)] pub enum Error { diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index e9a46897..12b5fb51 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -9,9 +9,6 @@ use tracing::{error, info}; use crate::{controller::Event, time::to_datetime}; -pub mod wakeup; -pub use wakeup::WakeUp; - #[derive(thiserror::Error, Debug)] pub(crate) enum Error { #[error("Could not store/edit job on disk")] @@ -30,7 +27,7 @@ pub(crate) struct Job { } impl Job { - fn at_next( + pub(crate) fn at_next( hour: i8, min: i8, event: Event, diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index fc368f3e..b21e5fc7 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -4,7 +4,7 @@ use std::net::{IpAddr, SocketAddr}; use clap::Parser; use tokio::sync::broadcast; -use self::input::jobs::{Jobs, WakeUp}; +use self::input::jobs::Jobs; use self::system::System; mod controller; @@ -51,9 +51,12 @@ async fn main() -> Result<(), Box> { let subscribed_rxs = array::from_fn(|_| event_tx.subscribe()); let jobs = Jobs::setup(event_tx.clone(), db.clone())?; - let wakeup = WakeUp::setup(db.clone(), jobs.clone(), event_rx)?; - // let (_mpd_status, _mpd_watcher_thread, _updater_tx) = - // input::MpdStatus::start_updating(opt.mpd_ip)?; + // TODO: untangle the large bedroom wakeup logic from everything else + let wakeup = controller::large_bedroom::wakeup::WakeUp::setup( + db.clone(), + jobs.clone(), + event_rx, + )?; let system = System::init(jobs, opt.hue_bridge_ip); let _tasks = controller::start(subscribed_rxs, event_tx.clone(), system); From 2c2406d14a94386a9b32b8063a39b42afe26506b Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 1 Dec 2024 13:34:06 +0100 Subject: [PATCH 465/687] Fix critical time zone crash on startup --- crates/brain/src/time.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/brain/src/time.rs b/crates/brain/src/time.rs index 03a6eb21..fffe7bee 100644 --- a/crates/brain/src/time.rs +++ b/crates/brain/src/time.rs @@ -2,7 +2,7 @@ use jiff::{tz::TimeZone, Timestamp, Zoned}; // Because the pi might be set to UTC, we need to manually add the tz pub(crate) fn now() -> Zoned { - let local = TimeZone::get("Amsterdam").unwrap(); + let local = TimeZone::get("Europe/Amsterdam").unwrap(); Timestamp::now().to_zoned(local) } From eb2ab823a593dd958a55bb2cc570ac1fcffd1a33 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 1 Dec 2024 13:38:23 +0100 Subject: [PATCH 466/687] Add wakeup to small bedroom (only once) --- crates/brain/src/controller/mod.rs | 3 +- .../src/controller/rooms/large_bedroom.rs | 4 +- .../controller/rooms/large_bedroom/wakeup.rs | 4 +- .../src/controller/rooms/small_bedroom.rs | 40 ++++++++++++++----- 4 files changed, 35 insertions(+), 16 deletions(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 33632253..a6776b37 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -11,7 +11,8 @@ use zigbee_bridge::lights::{mired_to_kelvin, normalize}; #[derive(Clone, Debug, Serialize, Deserialize)] pub enum Event { Sensor(Reading), - WakeUp, + WakeupLB, + WakeupSB, } #[derive(Clone)] diff --git a/crates/brain/src/controller/rooms/large_bedroom.rs b/crates/brain/src/controller/rooms/large_bedroom.rs index 93a68db3..35d77675 100644 --- a/crates/brain/src/controller/rooms/large_bedroom.rs +++ b/crates/brain/src/controller/rooms/large_bedroom.rs @@ -60,10 +60,10 @@ fn filter(event: Event) -> Option { use protocol::large_bedroom::desk::Reading as D; use protocol::large_bedroom::Reading as R; use protocol::Reading::LargeBedroom as LB; - use Event::{Sensor, WakeUp}; + use Event::{Sensor, WakeupLB}; Some(match event { - WakeUp => RelevantEvent::WakeUp, + WakeupLB => RelevantEvent::WakeUp, Sensor(LB(R::Desk(D::Button(b)))) => RelevantEvent::DeskButton(b), Sensor(LB(R::Bed(B::Button(b)))) => RelevantEvent::BedButton(b), // Sensor(LB(R::Bed(B::Brightness(l)))) => RelevantEvent::Brightness(l), diff --git a/crates/brain/src/controller/rooms/large_bedroom/wakeup.rs b/crates/brain/src/controller/rooms/large_bedroom/wakeup.rs index fe865ac0..e27e62d1 100644 --- a/crates/brain/src/controller/rooms/large_bedroom/wakeup.rs +++ b/crates/brain/src/controller/rooms/large_bedroom/wakeup.rs @@ -27,7 +27,7 @@ async fn reset_on_wakeup( ) { loop { match event_rx.recv().await { - Ok(Event::WakeUp) => { + Ok(Event::WakeupLB) => { if let Err(e) = wake_up.reset() { /* TODO: this should make more "noise" then this <28-04-24, dvdsk> */ error!("Could not reset wakeup system for next wake: {e}"); @@ -193,7 +193,7 @@ fn wakeup_at_next(hour: i8, min: i8) -> Job { Job::at_next( hour, min, - Event::WakeUp, + Event::WakeupLB, Some(Duration::from_secs(3 * 60 * 60)), ) } diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 97e6a437..7f24e592 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -13,18 +13,20 @@ use tracing::warn; use zigbee_bridge::lights::{denormalize, kelvin_to_mired}; use crate::controller::{Event, RestrictedSystem}; +use crate::input::jobs::Job; -#[derive(PartialEq, Eq, Debug)] -enum State { +const UPDATE_INTERVAL: Duration = Duration::from_secs(5); +const OFF_DELAY: Duration = Duration::from_secs(60); +const WAKEUP_EXPIRATION: Duration = Duration::from_secs(60 * 60); + +#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)] +pub(crate) enum State { Sleep, Wakeup, Normal, Override, } -const UPDATE_INTERVAL: Duration = Duration::from_secs(5); -const OFF_DELAY: Duration = Duration::from_secs(60); - trait RecvFiltered { async fn recv_filter_mapped( &mut self, @@ -64,6 +66,7 @@ fn event_filter(event: Event) -> Option { Event::Sensor(Reading::SmallBedroom( small_bedroom::Reading::ButtonPanel(button), )) => Some(RelevantEvent::Button(button)), + Event::WakeupSB => Some(RelevantEvent::Wakeup), _ => None, } } @@ -82,6 +85,18 @@ pub async fn run( ) { let room_state = Arc::new(Mutex::new(State::Normal)); let mut next_update = Instant::now() + UPDATE_INTERVAL; + + let _ = system + .system + .jobs + .add_job(Job::at_next( + 9, + 0, + Event::WakeupSB, + Some(WAKEUP_EXPIRATION), + )) + .await; + loop { let get_event = event_rx .recv_filter_mapped(event_filter) @@ -127,7 +142,7 @@ async fn run_wakeup( system.one_lamp_on(light_name).await; for minute in 1..=20 { - sleep(Duration::from_secs(1)).await; + sleep(Duration::from_secs(60)).await; // room state has changed, thus wakeup should be aborted if *room_state.lock().await != State::Wakeup { return; @@ -146,6 +161,8 @@ async fn run_wakeup( } *room_state.lock().await = State::Normal; + set_time_color(&mut system, room_state).await; + system.all_lamps_on().await; } async fn delayed_off( @@ -179,14 +196,15 @@ async fn handle_buttonpress( { *room_state.lock().await = State::Normal; } - system.all_lamps_on().await; set_time_color(&mut system, room_state).await; + system.all_lamps_on().await; } ButtonPanel::BOttomRight(_) => { - task::spawn(run_wakeup(system.clone(), room_state.clone())); - // *room_state = State::Override; - // system.all_lamps_on().await; - // system.all_lamps_ct(2000, 254).await; + { + *room_state.lock().await = State::Override; + } + system.all_lamps_on().await; + system.all_lamps_ct(2000, 254).await; } _ => (), } From 84341327b15ff297f60937123f997c317128fbaf Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 3 Dec 2024 15:55:32 +0100 Subject: [PATCH 467/687] move remaining lamps to zigbee_bridge --- crates/brain/src/controller/mod.rs | 12 ++++--- crates/zigbee-bridge/src/lib.rs | 15 ++++++-- crates/zigbee-bridge/src/lights/lamp/model.rs | 34 ++++++++++++++----- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 171311e1..0f4399f8 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -81,25 +81,25 @@ pub fn start( let restricted = RestrictedSystem { system: system.clone(), - allowed_lights: vec![ + allowed_lights_new: vec![ "large_bedroom:cabinet", "large_bedroom:ceiling", "large_bedroom:desk", "large_bedroom:wardrobe", "large_bedroom:bed", ], - allowed_lights_new: vec![], + allowed_lights: vec![], }; tasks.spawn(rooms::large_bedroom::run(rx1, sender.clone(), restricted)); let restricted = RestrictedSystem { system: system.clone(), - allowed_lights: vec![ + allowed_lights_new: vec![ "small_bedroom:ceiling", "small_bedroom:bureau", "small_bedroom:piano", ], - allowed_lights_new: vec![], + allowed_lights: vec![], }; tasks.spawn(rooms::small_bedroom::run(rx2, sender.clone(), restricted)); @@ -116,5 +116,9 @@ pub fn start( }; tasks.spawn(rooms::kitchen::run(rx3, sender, restricted)); + // "hallway:ceiling" + // "bathroom:ceiling" + // "toilet:ceiling" + tasks } diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 992c38b9..0915af83 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -10,12 +10,23 @@ pub mod lights; const MQTT_IP: &str = "192.168.1.43"; const MQTT_PORT: u16 = 1883; -const LIGHT_MODELS: [(&str, Model); 5] = [ - ("kitchen:fridge", Model::TradfriE14), +const LIGHT_MODELS: [(&str, Model); 16] = [ + ("kitchen:fridge", Model::TradfriE14Color), ("kitchen:hallway", Model::TradfriE27), ("kitchen:hood_left", Model::TradfriCandle), ("kitchen:hood_right", Model::TradfriCandle), ("kitchen:ceiling", Model::HueGen4), + ("large_bedroom:cabinet", Model::TradfriGU10), + ("large_bedroom:ceiling", Model::TradfriE27), + ("large_bedroom:desk", Model::TradfriE27), + ("large_bedroom:wardrobe", Model::TradfriE27), + ("large_bedroom:bed", Model::TradfriE14White), + ("small_bedroom:ceiling", Model::HueGen4), + ("small_bedroom:bureau", Model::HueGen4), + ("small_bedroom:piano", Model::HueGen4), + ("bathroom:ceiling", Model::HueGen4), + ("hallway:ceiling", Model::TradfriE27), + ("toilet:ceiling", Model::HueGen4), ]; #[cfg(test)] diff --git a/crates/zigbee-bridge/src/lights/lamp/model.rs b/crates/zigbee-bridge/src/lights/lamp/model.rs index 711bfbfb..729945df 100644 --- a/crates/zigbee-bridge/src/lights/lamp/model.rs +++ b/crates/zigbee-bridge/src/lights/lamp/model.rs @@ -6,9 +6,17 @@ use crate::LIGHT_MODELS; #[derive(Debug, Clone, PartialEq, Eq)] pub(crate) enum Model { + /// LED2107C4 TRADFRI bulb E14, white spectrum, candle, opal, 470 lm TradfriCandle, + /// LED2109G6 TRADFRI bulb E26/E27, color/white spectrum, globe, opal, 800/806/810 lm TradfriE27, - TradfriE14, + /// LED1923R5 TRADFRI bulb GU10, color/white spectrum, 345/380 lm + TradfriGU10, + /// LED2111G6 TRADFRI bulb E14, color/white spectrum, globe, opal, 806 lm + TradfriE14Color, + /// LED2101G4 TRADFRI bulb E12/E14, white spectrum, globe, opal, 450/470 lm + TradfriE14White, + /// 9290012573A Hue white and color ambiance E26/E27/E14 HueGen4, #[allow(unused)] TradfriOther(String), @@ -32,8 +40,11 @@ impl Model { pub(super) fn supports_xy(&self) -> bool { #[allow(clippy::match_same_arms)] // clearer comment match self { - Model::TradfriE27 | Model::TradfriE14 | Model::HueGen4 => true, - Model::TradfriCandle => false, + Model::TradfriE27 + | Model::TradfriE14Color + | Model::HueGen4 + | Model::TradfriGU10 => true, + Model::TradfriCandle | Model::TradfriE14White => false, // We assume no so that things at least don't break Model::TradfriOther(_) | Model::HueOther(_) | Model::Other(_) => { false @@ -43,8 +54,9 @@ impl Model { pub(super) fn temp_k_range(&self) -> Range { match self { - Model::TradfriCandle => 2200..4000, - Model::TradfriE27 | Model::TradfriE14 => 1780..4000, + Model::TradfriCandle | Model::TradfriGU10 => 2200..4000, + Model::TradfriE27 | Model::TradfriE14Color => 1780..4000, + Model::TradfriE14White => 2000..4000, Model::HueGen4 => 2000..6500, Model::TradfriOther(_) => 2200..4000, Model::HueOther(_) => 2200..6500, @@ -57,11 +69,13 @@ impl Model { match self { Model::TradfriCandle => todo!(), Model::TradfriE27 => todo!(), - Model::TradfriE14 => todo!(), + Model::TradfriE14Color => todo!(), Model::HueGen4 => todo!(), Model::TradfriOther(_) => todo!(), Model::HueOther(_) => todo!(), Model::Other(_) => todo!(), + Model::TradfriGU10 => todo!(), + Model::TradfriE14White => todo!(), } } @@ -93,7 +107,7 @@ impl Model { (4250, 0.0007), ], // 204.391.94 data - Model::TradfriE14 => vec![ + Model::TradfriE14Color => vec![ (1841, -0.0032), (2055, -0.0034), (2120, 0.0012), @@ -119,6 +133,8 @@ impl Model { ], Model::TradfriOther(_) => todo!(), Model::Other(_) => todo!(), + Model::TradfriGU10 => todo!(), + Model::TradfriE14White => todo!(), } .into_iter() .collect() @@ -132,12 +148,14 @@ impl Model { vec![(2200, 30), (2700, 20), (4000, 50)] } Model::TradfriE27 => vec![(2200, 110), (2700, 30), (4000, -110)], - Model::TradfriE14 => vec![(2200, 70), (2700, -40), (4000, 20)], + Model::TradfriE14Color => vec![(2200, 70), (2700, -40), (4000, 20)], Model::HueGen4 | Model::HueOther(_) => { vec![(2200, 2), (2700, 5), (4000, -10), (5500, 45), (6500, 5)] } Model::TradfriOther(_) => todo!(), Model::Other(_) => todo!(), + Model::TradfriGU10 => todo!(), + Model::TradfriE14White => todo!(), } .into_iter() .collect() From d4e7aa72a02714e79821efdb3d94edc0e72f0f1d Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 3 Dec 2024 16:31:27 +0100 Subject: [PATCH 468/687] removes now unused hue bridge light system --- crates/brain/src/controller/mod.rs | 34 +-- .../src/controller/rooms/small_bedroom.rs | 1 + crates/brain/src/errors.rs | 2 - crates/brain/src/main.rs | 6 +- crates/brain/src/system.rs | 7 +- .../brain/src/system/lamps/bridge_connect.rs | 102 ------- .../lamps/eventually_consistent_bridge.rs | 250 ------------------ crates/brain/src/system/lamps/lamp.rs | 72 ----- crates/brain/src/system/lamps/mod.rs | 106 -------- 9 files changed, 6 insertions(+), 574 deletions(-) delete mode 100644 crates/brain/src/system/lamps/bridge_connect.rs delete mode 100644 crates/brain/src/system/lamps/eventually_consistent_bridge.rs delete mode 100644 crates/brain/src/system/lamps/lamp.rs delete mode 100644 crates/brain/src/system/lamps/mod.rs diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 7bf4e806..55d0b288 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -18,17 +18,12 @@ pub enum Event { #[derive(Clone)] pub(crate) struct RestrictedSystem { allowed_lights: Vec<&'static str>, - allowed_lights_new: Vec<&'static str>, system: System, } impl RestrictedSystem { async fn one_lamp_ct(&mut self, name: &'static str, ct: u16, bri: u8) { if self.allowed_lights.contains(&name) { - self.system.lights.set_ct(name, bri, ct).await.unwrap(); - } - - if self.allowed_lights_new.contains(&name) { self.system .lights_new .set_color_temp(name, mired_to_kelvin(ct.into())); @@ -38,30 +33,18 @@ impl RestrictedSystem { async fn one_lamp_on(&mut self, name: &'static str) { if self.allowed_lights.contains(&name) { - self.system.lights.single_on(name).await.unwrap(); - } - - if self.allowed_lights_new.contains(&name) { self.system.lights_new.set_on(name); } } async fn one_lamp_off(&mut self, name: &'static str) { if self.allowed_lights.contains(&name) { - self.system.lights.single_off(name).await.unwrap(); - } - - if self.allowed_lights_new.contains(&name) { self.system.lights_new.set_off(name); } } async fn all_lamps_ct(&mut self, ct: u16, bri: u8) { for name in &self.allowed_lights { - self.system.lights.set_ct(name, bri, ct).await.unwrap(); - } - - for name in &self.allowed_lights_new { self.system .lights_new .set_color_temp(name, mired_to_kelvin(ct.into())); @@ -71,20 +54,12 @@ impl RestrictedSystem { async fn all_lamps_off(&mut self) { for name in &self.allowed_lights { - self.system.lights.single_off(name).await.unwrap(); - } - - for name in &self.allowed_lights_new { self.system.lights_new.set_off(name); } } async fn all_lamps_on(&mut self) { for name in &self.allowed_lights { - self.system.lights.single_on(name).await.unwrap(); - } - - for name in &self.allowed_lights_new { self.system.lights_new.set_on(name); } } @@ -101,32 +76,29 @@ pub fn start( let restricted = RestrictedSystem { system: system.clone(), - allowed_lights_new: vec![ + allowed_lights: vec![ "large_bedroom:cabinet", "large_bedroom:ceiling", "large_bedroom:desk", "large_bedroom:wardrobe", "large_bedroom:bed", ], - allowed_lights: vec![], }; tasks.spawn(rooms::large_bedroom::run(rx1, sender.clone(), restricted)); let restricted = RestrictedSystem { system: system.clone(), - allowed_lights_new: vec![ + allowed_lights: vec![ "small_bedroom:ceiling", "small_bedroom:bureau", "small_bedroom:piano", ], - allowed_lights: vec![], }; tasks.spawn(rooms::small_bedroom::run(rx2, sender.clone(), restricted)); let restricted = RestrictedSystem { system: system.clone(), - allowed_lights: vec![], - allowed_lights_new: vec![ + allowed_lights: vec![ "kitchen:ceiling", "kitchen:hood_left", "kitchen:hood_right", diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 7f24e592..35732258 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use std::time::Duration; +use serde::{Serialize, Deserialize}; use futures_concurrency::future::Race; use futures_util::FutureExt; use protocol::small_bedroom::ButtonPanel; diff --git a/crates/brain/src/errors.rs b/crates/brain/src/errors.rs index cafd131c..3c9503a2 100644 --- a/crates/brain/src/errors.rs +++ b/crates/brain/src/errors.rs @@ -6,8 +6,6 @@ pub enum Error { YamlParsing(#[from] serde_yaml::Error), #[error("Database error")] DataBase(#[from] sled::Error), - #[error("Error while adjusting lighting: {0}")] - Lamps(#[from] crate::system::lamps::Error), #[error("Error contacting mpd")] Mpd(#[from] mpd::error::Error), #[error("Error in the wakeup alarm system")] diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index b21e5fc7..ae7c2411 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -28,10 +28,6 @@ struct Opt { /// a loadbalancer/reverse proxy to get traffic to this #[clap(short, long)] port: u16, - - /// ip address of the hue bridge, format as: 127.0.0.1 - #[clap(short = 'b', long)] - hue_bridge_ip: String, } #[tokio::main] @@ -58,7 +54,7 @@ async fn main() -> Result<(), Box> { event_rx, )?; - let system = System::init(jobs, opt.hue_bridge_ip); + let system = System::init(jobs); let _tasks = controller::start(subscribed_rxs, event_tx.clone(), system); tokio::task::spawn(input::sensors::subscribe(event_tx, opt.data_server)); diff --git a/crates/brain/src/system.rs b/crates/brain/src/system.rs index 886cacd3..b9dcc3c1 100644 --- a/crates/brain/src/system.rs +++ b/crates/brain/src/system.rs @@ -1,7 +1,4 @@ -pub mod lamps; // pub mod mpd_control; - -pub use lamps::Lighting; use zigbee_bridge::lights; // pub use mpd_control::Mpd; @@ -11,16 +8,14 @@ use crate::input::jobs::Jobs; pub struct System { #[allow(dead_code)] pub jobs: Jobs, - pub lights: Lighting, pub lights_new: lights::Controller, // pub mpd: Mpd, } impl System { - pub fn init(jobs: Jobs, hue_bridge_ip: String) -> Self { + pub fn init(jobs: Jobs) -> Self { Self { jobs, - lights: Lighting::start_init(hue_bridge_ip), lights_new: lights::Controller::start_bridge(), // mpd: Mpd, } diff --git a/crates/brain/src/system/lamps/bridge_connect.rs b/crates/brain/src/system/lamps/bridge_connect.rs deleted file mode 100644 index 5a9525f5..00000000 --- a/crates/brain/src/system/lamps/bridge_connect.rs +++ /dev/null @@ -1,102 +0,0 @@ -use hueclient::Bridge; -use hueclient::HueError; -use tracing::{error, info}; - -use super::Error; -use std::fs::File; -use std::net::IpAddr; -use std::path::Path; -use std::time::Duration; - -#[derive(Debug, thiserror::Error)] -pub enum RegisterError { - #[error("Something went wrong registering the user inside the hue library")] - HueError(hueclient::HueError), - #[error("Link button was not pressed within 25 seconds")] - Timedout, -} - -async fn register(ip: IpAddr) -> Result { - for _ in 0..5 { - //try 5 times to connect - let bridge = Bridge::for_ip(ip); - match bridge.register_user("ha-brain").await { - Ok(bridge) => { - println!("Success, linked to bridge"); - info!("User registered: {}, on IP: {ip:?}", bridge.username); - return Ok(bridge); - } - Err(HueError::BridgeError { code: 101, .. }) => { - println!("Please, press the link on the bridge. Retrying in 5 seconds"); - tokio::time::sleep(Duration::from_secs(5)).await; - } - Err(e) => { - println!("Unexpected error occurred: {}", e); - return Err(RegisterError::HueError(e)); - } - } - } - Err(RegisterError::Timedout) -} - -fn saved_bridge_info() -> Result<(String, String), ()> { - let path = Path::new("hueBridgeLogin"); - match File::open(path) { - Err(e) => error!("find ip and login file, error: {}", e), - Ok(f) => match serde_yaml::from_reader(f) { - Ok((ip, login)) => return Ok((ip, login)), - Err(_) => error!("could not read ip and login from file"), - }, - } - Err(()) -} - -#[derive(Debug, thiserror::Error)] -pub enum SaveBridgeError { - #[error("Could not create file {path:?} to store bridge logins in: {err}")] - CreatingFile { - path: &'static Path, - err: std::io::Error, - }, - #[error("Error writing bridge logins to file: {0}")] - Writing(serde_yaml::Error), -} -fn update_saved_bridge_info(bridge_ip: IpAddr, login: &str) -> Result<(), SaveBridgeError> { - let path = Path::new("hueBridgeLogin"); - let file = File::create(path).map_err(|err| SaveBridgeError::CreatingFile { err, path })?; - serde_yaml::to_writer(file, &(bridge_ip, login)).map_err(SaveBridgeError::Writing) -} - -pub async fn get_bridge_and_status( - ip: &str, -) -> Result<(Bridge, Vec), Error> { - let ip: IpAddr = ip.parse().expect("string should be an ip"); - let Ok((ip, login)) = saved_bridge_info() else { - let bridge = register(ip).await?; - update_saved_bridge_info(ip, &bridge.username)?; - - let lights_info = bridge - .get_all_lights() - .await - .map_err(Error::GettingLights)?; - return Ok((bridge, lights_info)); - }; - - let ip: IpAddr = ip.parse().expect("string should be an ip"); - let bridge = Bridge::for_ip(ip).with_user(login); - let res = bridge.get_all_lights().await; - - match res { - Ok(lights_info) => Ok((bridge, lights_info)), - Err(_) => { - let bridge = register(ip).await?; - update_saved_bridge_info(ip, &bridge.username)?; - - let lights_info = bridge - .get_all_lights() - .await - .map_err(Error::GettingLights)?; - Ok((bridge, lights_info)) - } - } -} diff --git a/crates/brain/src/system/lamps/eventually_consistent_bridge.rs b/crates/brain/src/system/lamps/eventually_consistent_bridge.rs deleted file mode 100644 index 1331b3d2..00000000 --- a/crates/brain/src/system/lamps/eventually_consistent_bridge.rs +++ /dev/null @@ -1,250 +0,0 @@ -use super::{bridge_connect, lamp::Lamp}; -use super::{ApplyChangeError, State}; -use crate::errors::Error; -use futures_util::stream::Peekable; -use futures_util::{Stream, StreamExt}; -use std::collections::{HashMap, HashSet}; -use std::pin::Pin; -use std::time::{Duration, Instant}; -use tokio::sync::oneshot; -use tokio::time::{timeout, timeout_at}; -use tracing::{error, warn}; - -use hueclient::Bridge; - -#[derive(Debug)] -pub(crate) enum Change { - AllOff, - AllOn, - Off { - name: &'static str, - }, - On { - name: &'static str, - }, - CtBri { - name: &'static str, - bri: u8, - ct: u16, - }, - XyBri { - name: &'static str, - bri: u8, - xy: (f32, f32), - }, - AllCtBri { - bri: u8, - ct: u16, - }, - AllXY { - bri: u8, - xy: (f32, f32), - }, -} - -type LampId = usize; -pub(crate) struct CachedBridge { - last_cmd_send: Instant, - pub(crate) bridge: Bridge, - pub(crate) needed_state: State, - pub(crate) known_state: State, - // get names using: curl 192.168.1.11/api//lights | jq | grep '"name": "' - lookup: HashMap, - reported_missing: HashSet, -} - -impl CachedBridge { - pub(crate) async fn try_init(ip: &str) -> Result { - let (bridge, lights_info) = bridge_connect::get_bridge_and_status(ip).await?; - let state: HashMap = lights_info - .iter() - .map(|light| (light.id, Lamp::from(&light.light.state))) - .collect(); - let lookup = lights_info - .into_iter() - .map(|light| (light.light.name, light.id)) - .collect(); - - Ok(Self { - bridge, - needed_state: state.clone(), - known_state: state, - lookup, - reported_missing: HashSet::new(), - last_cmd_send: Instant::now(), - }) - } - - fn report_missing_if_not_reported_yet(&mut self, missing_lamp: &str) { - let new = self.reported_missing.insert(missing_lamp.to_string()); - if new { - error!("no lamp with name: {missing_lamp} in lookup table, was recently (re)named?"); - } - } - - pub(crate) async fn apply_changes(&mut self) -> Result<(), Error> { - for (id, lamp) in self.known_state.iter_mut() { - let Some(needed) = self.needed_state.get(id) else { - continue; - }; - - if lamp != needed { - let next_send_possible = self.last_cmd_send + Duration::from_millis(100); - tokio::time::sleep_until(next_send_possible.into()).await; - if let Err(e) = self.bridge.set_light_state(*id, &needed.light_cmd()).await { - warn!("could not apply changes to lamp: {e}") - } - self.last_cmd_send = Instant::now(); - *lamp = needed.clone() - } - } - - Ok(()) - } - - async fn push_state(&mut self) -> Result<(), Error> { - for (id, lamp) in self.known_state.iter_mut() { - let next_send_possible = self.last_cmd_send + Duration::from_millis(100); - tokio::time::sleep_until(next_send_possible.into()).await; - if let Err(e) = self.bridge.set_light_state(*id, &lamp.light_cmd()).await { - warn!("could not apply changes to lamp: {e}") - } - self.last_cmd_send = Instant::now(); - } - Ok(()) - } - - pub(crate) fn prep_change(&mut self, change: &Change) { - match change { - Change::AllOff => { - self.needed_state - .values_mut() - .for_each(|lamp| lamp.on = false); - } - Change::AllOn => { - self.needed_state - .values_mut() - .for_each(|lamp| lamp.on = true); - } - Change::Off { name } => { - let Some(lamp_id) = self.lookup.get(*name) else { - self.report_missing_if_not_reported_yet(name); - return; - }; - if let Some(lamp) = self.needed_state.get_mut(lamp_id) { - lamp.on = false; - } else { - error!("no lamp with id: {lamp_id} exists"); - } - } - Change::On { name } => { - let Some(lamp_id) = self.lookup.get(*name) else { - self.report_missing_if_not_reported_yet(name); - return; - }; - if let Some(lamp) = self.needed_state.get_mut(lamp_id) { - lamp.on = true; - } else { - error!("no lamp with id: {lamp_id} exists"); - } - } - Change::CtBri { name, bri, ct } => { - let Some(lamp_id) = self.lookup.get(*name) else { - self.report_missing_if_not_reported_yet(name); - return; - }; - if let Some(lamp) = self.needed_state.get_mut(lamp_id) { - lamp.bri = *bri; - lamp.ct = Some(*ct); - lamp.xy = None; - } - } - Change::XyBri { name, bri, xy } => { - let Some(lamp_id) = self.lookup.get(*name) else { - self.report_missing_if_not_reported_yet(name); - return; - }; - if let Some(lamp) = self.needed_state.get_mut(lamp_id) { - lamp.bri = *bri; - lamp.xy = Some(*xy); - lamp.ct = None; - } - } - Change::AllCtBri { bri, ct } => { - self.needed_state.values_mut().for_each(|lamp| { - lamp.bri = *bri; - lamp.ct = Some(*ct); - lamp.xy = None; - }); - } - Change::AllXY { bri, xy } => { - self.needed_state.values_mut().for_each(|lamp| { - lamp.bri = *bri; - lamp.xy = Some(*xy); - lamp.ct = None; - }); - } - } - } -} - -pub(crate) async fn process_lamp_changes( - stream: &mut Pin<&mut Peekable>, - mut bridge: CachedBridge, -) -> Error -where - S: Stream>, Change)>, -{ - const MAX_DUR: Duration = Duration::from_millis(5); - let mut last_state_push = Instant::now(); - loop { - if last_state_push.elapsed() > Duration::from_secs(5) { - if let Err(err) = bridge.push_state().await { - return err; - } - last_state_push = Instant::now(); - } - - let (tx, change) = match timeout(Duration::from_secs(5), stream.next()).await { - Ok(Some(next)) => next, - Ok(None) => unreachable!("light system should not drop"), - Err(_timeout) => { - if let Err(err) = bridge.push_state().await { - return err; - } else { - continue; - } - } - }; - - bridge.prep_change(&change); - let mut to_answer = vec![tx]; - - let now = Instant::now(); - let deadline = tokio::time::Instant::from(now) + MAX_DUR; - - // process backlog - while now.elapsed() < MAX_DUR { - match timeout_at(deadline, stream.next()).await { - Err(_timeout) => break, - Ok(None) => unreachable!("light system should not drop"), - Ok(Some((tx, change))) => { - bridge.prep_change(&change); - to_answer.push(tx); - } - }; - } - - if let Err(e) = bridge.apply_changes().await { - error!("Could not apply changes to bridge immediately, err: {e}"); - for tx in to_answer { - let _ignore_canceled_requester = tx.send(Err(ApplyChangeError)); - } - return e; - } else { - for tx in to_answer { - let _ignore_canceled_requester = tx.send(Ok(())); - } - } - } -} diff --git a/crates/brain/src/system/lamps/lamp.rs b/crates/brain/src/system/lamps/lamp.rs deleted file mode 100644 index 0b90e5d8..00000000 --- a/crates/brain/src/system/lamps/lamp.rs +++ /dev/null @@ -1,72 +0,0 @@ -use hueclient::{CommandLight, LightState}; - -//adaptation from philipshue LightState that adds some -//values and removes unused -#[derive(Debug, Clone, PartialEq)] -pub struct Lamp { - pub on: bool, - pub bri: u8, - pub hue: Option, - pub sat: Option, - pub xy: Option<(f32, f32)>, - pub ct: Option, -} - -impl Lamp { - pub(crate) fn light_cmd(&self) -> CommandLight { - let mut light_cmd = CommandLight::default().with_bri(self.bri); - light_cmd.on = Some(self.on); - - if let Some((x, y)) = self.xy { - light_cmd.with_xy(x, y) - } else if let Some(ct) = self.ct { - light_cmd.with_ct(ct) - } else { - unreachable!("lamp must have ct or xy set"); - } - } -} - -impl From<&LightState> for Lamp { - fn from(state: &LightState) -> Self { - Lamp { - on: state.on, - bri: state.bri.unwrap_or(0), - hue: state.hue, - sat: state.sat, - xy: state.xy, - ct: state.ct, - } - } -} - -#[allow(dead_code)] -fn gamma_correct(mut x: f32) -> f32 { - if x > 0.04045 { - x = (x + 0.055) / (1f32 + 0.055); - x.powf(2.4) - } else { - x / 12.92 - } -} - -//r,g,b between 0 and one -//https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d -#[allow(dead_code)] -pub fn xy_from_rgb(rgb: (f32, f32, f32)) -> (f32, f32) { - let (r, g, b) = rgb; - let r = gamma_correct(r); - let g = gamma_correct(g); - let b = gamma_correct(b); - - let xyz_x = r * 0.649926 + g * 0.103455 + b * 0.197109; - let xyz_y = r * 0.234327 + g * 0.743075 + b * 0.022598; - let xyz_z = g * 0.053077 + b * 1.035763; - - let hue_x = xyz_x / (xyz_x + xyz_y + xyz_z); - let hue_y = xyz_y / (xyz_x + xyz_y + xyz_z); - - //TODO color gamut triangle stuff for finding closest valid value - - (hue_x, hue_y) -} diff --git a/crates/brain/src/system/lamps/mod.rs b/crates/brain/src/system/lamps/mod.rs deleted file mode 100644 index c49b62b9..00000000 --- a/crates/brain/src/system/lamps/mod.rs +++ /dev/null @@ -1,106 +0,0 @@ -use futures_util::{pin_mut, stream, StreamExt}; -use tokio::sync::{mpsc, oneshot}; -use tracing::error; - -use std::collections::HashMap; -use std::time::Duration; - -use self::bridge_connect::SaveBridgeError; -use self::eventually_consistent_bridge::Change; - -mod bridge_connect; -mod eventually_consistent_bridge; -mod lamp; - -type State = HashMap; - -async fn manage_bridge( - ip: String, - rx: mpsc::UnboundedReceiver<(oneshot::Sender>, Change)>, -) { - let stream = stream::unfold(rx, |mut rx| async move { - let yielded = rx.recv().await; - yielded.map(|item| (item, rx)) - }); - - let mut prev_error = String::new(); - let stream = stream.peekable(); - pin_mut!(stream); - loop { - let error = match eventually_consistent_bridge::CachedBridge::try_init(&ip).await { - Ok(bridge) => { - eventually_consistent_bridge::process_lamp_changes(&mut stream, bridge).await - } - Err(e) => e, - }; - - if prev_error != error.to_string() { - error!("could not connect to bridge: {error:?}"); - prev_error = error.to_string(); - } - tokio::time::sleep(Duration::from_secs(5)).await; - } -} - -#[derive(Debug, Clone)] -pub struct Lighting { - tx: mpsc::UnboundedSender<(oneshot::Sender>, Change)>, -} - -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error("Could not get lights from bridge")] - GettingLights(hueclient::HueError), - #[error("Failed to register on bridge")] - Register(#[from] bridge_connect::RegisterError), - #[error("Something went wrong saving bridge account to disk: {0}")] - SavingBridgeAccount(#[from] SaveBridgeError), -} - -#[derive(Debug, thiserror::Error)] -#[error("Could not apply changes to lighting system. Will simulate this and further changes then automatically apply the simulation outcome once the issue is resolved")] -pub struct ApplyChangeError; - -macro_rules! light_fn { - ($name:ident, $change:ident$(; $($arg:ident: $type:ty),+)?) => { - pub async fn $name(&mut self, $($($arg: $type),+)?) -> Result<(), ApplyChangeError> { - // todo use oneshot to get error back from other side - let (tx, rx) = tokio::sync::oneshot::channel(); - self.tx.send((tx, Change::$change$({$($arg),+})?)).expect("managed_bridge should channel should never drop as managed bridge task should never end"); - let res = rx.await.expect("managed_bridge should not crash and thus not drop the receive end of the channel"); - res - } - }; -} - -#[allow(dead_code)] -impl Lighting { - pub fn start_init(ip: String) -> Self { - let (tx, rx) = mpsc::unbounded_channel(); - let manage_bridge = manage_bridge(ip, rx); - tokio::task::spawn(manage_bridge); - Self { tx } - } - - light_fn! {all_off, AllOff} - light_fn! {all_on, AllOn} - light_fn! {single_off, Off; name: &'static str} - light_fn! {single_on, On; name: &'static str} - - light_fn! {set_ct, CtBri; name: &'static str, bri: u8, ct: u16 } - light_fn! {set_xy, XyBri; name: &'static str, bri: u8, xy: (f32, f32)} - light_fn! {set_all_ct, AllCtBri; bri: u8, ct: u16 } - light_fn! {set_all_xy, AllXY; bri: u8, xy: (f32, f32) } - - pub fn set_all_rgb(&mut self, bri: u8, rgb: (f32, f32, f32)) -> Result<(), ApplyChangeError> { - let xy = lamp::xy_from_rgb(rgb); - let (tx, rx) = tokio::sync::oneshot::channel(); - self.tx - .send((tx, Change::AllXY { bri, xy })) - .expect("manage_bridge should never return"); - - rx.blocking_recv().expect( - "managed_bridge should not crash and thus not drop the receive end of the channel", - ) - } -} From 187d13a0db1c9aeb2827b0a09c07b9e0e8602058 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Wed, 4 Dec 2024 14:55:12 +0100 Subject: [PATCH 469/687] Overhaul structure SB, switch to K and normalized bri --- crates/brain/src/controller/mod.rs | 14 +- crates/brain/src/controller/rooms/kitchen.rs | 11 +- .../src/controller/rooms/large_bedroom.rs | 18 +- .../src/controller/rooms/small_bedroom.rs | 203 +++--------------- .../controller/rooms/small_bedroom/filter.rs | 43 ++++ .../controller/rooms/small_bedroom/state.rs | 122 +++++++++++ crates/zigbee-bridge/src/lights.rs | 4 - .../src/lights/cached_bridge/mqtt.rs | 4 +- .../src/lights/cached_bridge/poll.rs | 13 +- crates/zigbee-bridge/src/lights/conversion.rs | 12 +- .../zigbee-bridge/src/lights/lamp/property.rs | 3 +- .../zigbee-bridge/src/lights/parse_state.rs | 2 +- 12 files changed, 229 insertions(+), 220 deletions(-) create mode 100644 crates/brain/src/controller/rooms/small_bedroom/filter.rs create mode 100644 crates/brain/src/controller/rooms/small_bedroom/state.rs diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 55d0b288..a1de9933 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -6,13 +6,13 @@ pub use protocol::Reading; use serde::{Deserialize, Serialize}; use tokio::sync::broadcast; use tokio::task::JoinSet; -use zigbee_bridge::lights::{mired_to_kelvin, normalize}; #[derive(Clone, Debug, Serialize, Deserialize)] pub enum Event { Sensor(Reading), WakeupLB, WakeupSB, + StateChangeSB(rooms::small_bedroom::State), } #[derive(Clone)] @@ -22,12 +22,12 @@ pub(crate) struct RestrictedSystem { } impl RestrictedSystem { - async fn one_lamp_ct(&mut self, name: &'static str, ct: u16, bri: u8) { + async fn one_lamp_ct(&mut self, name: &'static str, kelvin: usize, bri: f64) { if self.allowed_lights.contains(&name) { self.system .lights_new - .set_color_temp(name, mired_to_kelvin(ct.into())); - self.system.lights_new.set_brightness(name, normalize(bri)); + .set_color_temp(name, kelvin); + self.system.lights_new.set_brightness(name, bri); } } @@ -43,12 +43,12 @@ impl RestrictedSystem { } } - async fn all_lamps_ct(&mut self, ct: u16, bri: u8) { + async fn all_lamps_ct(&mut self, kelvin: usize, bri: f64) { for name in &self.allowed_lights { self.system .lights_new - .set_color_temp(name, mired_to_kelvin(ct.into())); - self.system.lights_new.set_brightness(name, normalize(bri)); + .set_color_temp(name, kelvin); + self.system.lights_new.set_brightness(name, bri); } } diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index 74e2358c..b3585dfb 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -42,6 +42,7 @@ impl RecvFiltered for broadcast::Receiver { #[derive(Debug)] enum RelevantEvent { // DeskButton(protocol::large_bedroom::DeskButton), + SBState(small_bedroom::State), } fn filter(_event: Event) -> Option { @@ -83,19 +84,19 @@ pub async fn run( } async fn update(system: &mut RestrictedSystem) { - let (new_ct, new_bri) = small_bedroom::optimal_ct_bri(); + let (new_ct, new_bri) = small_bedroom::daylight_now(); // let (new_ct, new_bri) = _testing_ct_bri(); system.all_lamps_ct(new_ct, new_bri).await; tracing::trace!("updated lamps"); } -fn _testing_ct_bri() -> (u16, u8) { +fn _testing_ct_bri() -> (usize, f64) { let now = crate::time::now(); // let optimal = match now.hour() { let optimal = match now.minute() { - min if min % 2 == 0 => (400, u8::MAX), // Even hour: orange - min if min % 2 == 1 => (250, u8::MAX), // Odd hour: blue - _ => (400, u8::MAX), + min if min % 2 == 0 => (2000, 1.0), // Even hour: orange + min if min % 2 == 1 => (4000, 1.0), // Odd hour: blue + _ => (2000, 1.0), }; // if now.minute() == 0 && now.second() <= 9 { if now.second() <= 9 { diff --git a/crates/brain/src/controller/rooms/large_bedroom.rs b/crates/brain/src/controller/rooms/large_bedroom.rs index 35d77675..d2dc525a 100644 --- a/crates/brain/src/controller/rooms/large_bedroom.rs +++ b/crates/brain/src/controller/rooms/large_bedroom.rs @@ -124,11 +124,13 @@ async fn update(system: &mut RestrictedSystem, state: &State) -> Option { } State::Bright => { system.all_lamps_on().await; - system.all_lamps_ct(254, u8::MAX).await; + system.all_lamps_ct(3900, 1.0).await; } State::FadeOut(started) => { system.all_lamps_on().await; - system.all_lamps_ct(1, u8::MAX).await; + // TODO: this was set to 1 mired (= 1M(!!) Kelvin) and 100% brightness + // not sure that is the intended behaviour + system.all_lamps_ct(3900, 1.0).await; if started.elapsed() > Duration::from_secs(40) { return Some(State::Off); } @@ -137,14 +139,14 @@ async fn update(system: &mut RestrictedSystem, state: &State) -> Option { None } -fn optimal_ct_bri() -> (u16, u8) { +fn optimal_ct_bri() -> (usize, f64) { let now = crate::time::now(); match now.hour() { - 0..=5 | 22.. => (500, 170), - 6..=16 => (254, u8::MAX), - 17..=19 => (320, u8::MAX), - 20..=21 => (320, 220), - _ => (320, u8::MAX), + 0..=5 | 22.. => (2000, 0.67), + 6..=16 => (3900, 1.0), + 17..=19 => (3100, 1.0), + 20..=21 => (3100, 0.87), + _ => (3100, 1.0), } } diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 35732258..01a792e1 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -1,232 +1,80 @@ -use std::sync::Arc; use std::time::Duration; -use serde::{Serialize, Deserialize}; use futures_concurrency::future::Race; use futures_util::FutureExt; use protocol::small_bedroom::ButtonPanel; -use protocol::{small_bedroom, Reading}; -use tokio::sync::broadcast::error::RecvError; -use tokio::sync::{broadcast, Mutex}; -use tokio::task; -use tokio::time::{sleep, sleep_until, Instant}; -use tracing::warn; -use zigbee_bridge::lights::{denormalize, kelvin_to_mired}; +use tokio::sync::broadcast; +use tokio::time::{sleep_until, Instant}; +use self::filter::{recv_filtered, RelevantEvent, Trigger}; +use self::state::Room; +pub(crate) use self::state::State; use crate::controller::{Event, RestrictedSystem}; use crate::input::jobs::Job; +mod filter; +mod state; + const UPDATE_INTERVAL: Duration = Duration::from_secs(5); const OFF_DELAY: Duration = Duration::from_secs(60); const WAKEUP_EXPIRATION: Duration = Duration::from_secs(60 * 60); -#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)] -pub(crate) enum State { - Sleep, - Wakeup, - Normal, - Override, -} - -trait RecvFiltered { - async fn recv_filter_mapped( - &mut self, - filter_map: impl Fn(Event) -> Option, - ) -> T; -} - -impl RecvFiltered for broadcast::Receiver { - async fn recv_filter_mapped( - &mut self, - filter_map: impl Fn(Event) -> Option, - ) -> T { - loop { - let event = match self.recv().await { - Ok(event) => event, - Err(RecvError::Lagged(n)) => { - warn!("SB missed {n} events"); - continue; - } - Err(err) => panic!("{err}"), - }; - if let Some(relevant) = filter_map(event) { - return relevant; - } - } - } -} - -#[derive(Debug)] -enum RelevantEvent { - Button(ButtonPanel), - Wakeup, -} - -fn event_filter(event: Event) -> Option { - match event { - Event::Sensor(Reading::SmallBedroom( - small_bedroom::Reading::ButtonPanel(button), - )) => Some(RelevantEvent::Button(button)), - Event::WakeupSB => Some(RelevantEvent::Wakeup), - _ => None, - } -} - -#[derive(Debug)] -enum Trigger { - Event(RelevantEvent), - ShouldUpdate, -} - pub async fn run( mut event_rx: broadcast::Receiver, - // todo if state change message everyone using this - _event_tx: broadcast::Sender, - mut system: RestrictedSystem, + event_tx: broadcast::Sender, + system: RestrictedSystem, ) { - let room_state = Arc::new(Mutex::new(State::Normal)); + let mut room = Room::new(event_tx, system.clone()); let mut next_update = Instant::now() + UPDATE_INTERVAL; let _ = system .system .jobs - .add_job(Job::at_next( - 9, - 0, - Event::WakeupSB, - Some(WAKEUP_EXPIRATION), - )) + .add_job(Job::at_next(9, 0, Event::WakeupSB, Some(WAKEUP_EXPIRATION))) .await; loop { - let get_event = event_rx - .recv_filter_mapped(event_filter) - .map(Trigger::Event); + let get_event = recv_filtered(&mut event_rx); let tick = sleep_until(next_update).map(|_| Trigger::ShouldUpdate); let trigger = (get_event, tick).race().await; match trigger { Trigger::Event(RelevantEvent::Button(button)) => { - handle_buttonpress(system.clone(), room_state.clone(), button) - .await; - } - Trigger::Event(RelevantEvent::Wakeup) => { - task::spawn(run_wakeup(system.clone(), room_state.clone())); + handle_buttonpress(&mut room, button).await; } + Trigger::Event(RelevantEvent::Wakeup) => room.to_wakeup().await, Trigger::ShouldUpdate => { - set_time_color(&mut system, room_state.clone()).await; + room.all_lights_daylight().await; next_update = Instant::now() + UPDATE_INTERVAL; } } } } -async fn run_wakeup( - mut system: RestrictedSystem, - room_state: Arc>, -) { - { - *room_state.lock().await = State::Wakeup; - } - - let light_name = "small_bedroom:piano"; - let bri = 1; - let ct = 2000; - let bri_growth: f64 = 1.32; - let ct_growth: f64 = 1.028; - - system - .one_lamp_ct(light_name, kelvin_to_mired(ct).try_into().unwrap(), bri) - .await; - // Make sure the light is the right ct and bri before turning it on - sleep(Duration::from_secs(1)).await; - system.one_lamp_on(light_name).await; - - for minute in 1..=20 { - sleep(Duration::from_secs(60)).await; - // room state has changed, thus wakeup should be aborted - if *room_state.lock().await != State::Wakeup { - return; - } - - let new_bri = ((bri as f64) * bri_growth.powi(minute)).round() as u8; - let new_ct = (ct as f64 * ct_growth.powi(minute)).round() as usize; - - system - .one_lamp_ct( - light_name, - kelvin_to_mired(new_ct).try_into().unwrap(), - new_bri, - ) - .await; - } - - *room_state.lock().await = State::Normal; - set_time_color(&mut system, room_state).await; - system.all_lamps_on().await; -} - -async fn delayed_off( - mut system: RestrictedSystem, - room_state: Arc>, -) { - sleep(OFF_DELAY).await; - // room state has changed, thus off should be aborted - if *room_state.lock().await != State::Sleep { - return; - } - system.all_lamps_off().await; -} - -async fn handle_buttonpress( - mut system: RestrictedSystem, - room_state: Arc>, - button: ButtonPanel, -) { +async fn handle_buttonpress(room: &mut Room, button: ButtonPanel) { dbg!(button); match button { ButtonPanel::BottomLeft(_) => { - { - *room_state.lock().await = State::Sleep; - } - system.one_lamp_off("small_bedroom:bureau").await; - system.one_lamp_off("small_bedroom:piano").await; - task::spawn(delayed_off(system.clone(), room_state.clone())); + room.to_sleep().await; } ButtonPanel::BottomMiddle(_) => { - { - *room_state.lock().await = State::Normal; - } - set_time_color(&mut system, room_state).await; - system.all_lamps_on().await; + room.to_daylight().await; } ButtonPanel::BOttomRight(_) => { - { - *room_state.lock().await = State::Override; - } - system.all_lamps_on().await; - system.all_lamps_ct(2000, 254).await; + room.to_override().await; } _ => (), } } -async fn set_time_color( - system: &mut RestrictedSystem, - room_state: Arc>, -) { - if *room_state.lock().await == State::Normal { - let (new_ct, new_bri) = optimal_ct_bri(); - system.all_lamps_ct(new_ct, new_bri).await; - } -} - const fn time(hour: i8, minute: i8) -> f64 { hour as f64 + minute as f64 / 60. } -pub(crate) fn optimal_ct_bri() -> (u16, u8) { +// TODO: move to jobs system and remove update trigger +pub(super) fn daylight_now() -> (usize, f64) { let now = crate::time::now(); + const T0_00: f64 = time(0, 0); const T8_00: f64 = time(8, 0); const T9_00: f64 = time(9, 0); @@ -235,7 +83,7 @@ pub(crate) fn optimal_ct_bri() -> (u16, u8) { const T21_30: f64 = time(21, 30); const T22_00: f64 = time(22, 0); - let (temp, bri) = match time(now.hour(), now.minute()) { + match time(now.hour(), now.minute()) { T8_00..T9_00 => (2000, 0.5), T9_00..T17_00 => (3500, 1.0), T17_00..T20_30 => (2300, 1.0), @@ -243,6 +91,5 @@ pub(crate) fn optimal_ct_bri() -> (u16, u8) { T21_30..T22_00 => (1900, 0.4), T22_00.. | T0_00..T8_00 => (1800, 0.1), _ => (2300, 1.0), - }; - (kelvin_to_mired(temp).try_into().unwrap(), denormalize(bri)) + } } diff --git a/crates/brain/src/controller/rooms/small_bedroom/filter.rs b/crates/brain/src/controller/rooms/small_bedroom/filter.rs new file mode 100644 index 00000000..e4515110 --- /dev/null +++ b/crates/brain/src/controller/rooms/small_bedroom/filter.rs @@ -0,0 +1,43 @@ +use tokio::sync::broadcast::{error::RecvError, Receiver}; +use tracing::warn; + +use crate::controller::Event; +use protocol::{small_bedroom, Reading}; + +#[derive(Debug)] +pub(super) enum Trigger { + Event(RelevantEvent), + ShouldUpdate, +} + +#[derive(Debug)] +pub(super) enum RelevantEvent { + Button(small_bedroom::ButtonPanel), + Wakeup, +} + +pub(super) async fn recv_filtered(event_rx: &mut Receiver) -> Trigger { + loop { + let event = match event_rx.recv().await { + Ok(event) => event, + Err(RecvError::Lagged(n)) => { + warn!("SB missed {n} events"); + continue; + } + Err(err) => panic!("{err}"), + }; + if let Some(relevant) = event_filter(event) { + return Trigger::Event(relevant); + } + } +} + +fn event_filter(event: Event) -> Option { + match event { + Event::Sensor(Reading::SmallBedroom( + small_bedroom::Reading::ButtonPanel(button), + )) => Some(RelevantEvent::Button(button)), + Event::WakeupSB => Some(RelevantEvent::Wakeup), + _ => None, + } +} diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs new file mode 100644 index 00000000..e4ae1791 --- /dev/null +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -0,0 +1,122 @@ +use std::sync::Arc; +use std::time::Duration; + +use serde::{Deserialize, Serialize}; +use tokio::sync::{broadcast, Mutex, RwLock}; +use tokio::task::{self, JoinHandle}; +use tokio::time::sleep; + +use super::{daylight_now, OFF_DELAY}; +use crate::controller::{Event, RestrictedSystem}; + +#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)] +pub(crate) enum State { + Sleep, + Wakeup, + Daylight, + Override, + DelayedOff, +} + +#[derive(Clone)] +pub(super) struct Room { + state: Arc>, + system: RestrictedSystem, + event_tx: broadcast::Sender, + task_handle: Arc>>>, +} + +impl Room { + pub(super) fn new( + event_tx: broadcast::Sender, + system: RestrictedSystem, + ) -> Self { + Self { + state: Arc::new(RwLock::new(State::Daylight)), + system, + event_tx, + task_handle: Arc::new(Mutex::new(None)), + } + } + + pub(super) async fn to_sleep(&mut self) { + self.to_state_cancel_prev(State::DelayedOff).await; + + self.system.one_lamp_off("small_bedroom:bureau").await; + self.system.one_lamp_off("small_bedroom:piano").await; + + let task_handle = task::spawn(self.clone().delayed_off_then_sleep()); + *self.task_handle.lock().await = Some(task_handle); + } + + pub(super) async fn to_wakeup(&mut self) { + self.to_state_cancel_prev(State::Wakeup).await; + + let task_handle = task::spawn(self.clone().run_wakeup_then_daylight()); + *self.task_handle.lock().await = Some(task_handle); + } + + pub(super) async fn to_daylight(&mut self) { + self.to_state_cancel_prev(State::Daylight).await; + self.all_lights_daylight().await; + self.system.all_lamps_on().await; + } + + pub(super) async fn to_override(&mut self) { + self.to_state_cancel_prev(State::Override).await; + self.system.all_lamps_ct(2000, 1.0).await; + self.system.all_lamps_on().await; + } + + async fn to_state_cancel_prev(&mut self, state: State) { + self.cancel_task().await; + *self.state.write().await = state.clone(); + let _ = self.event_tx.send(Event::StateChangeSB(state)); + } + + async fn cancel_task(&mut self) { + if let Some(ref task) = *self.task_handle.lock().await { + task.abort(); + } + } + + async fn delayed_off_then_sleep(mut self) { + sleep(OFF_DELAY).await; + self.system.all_lamps_off().await; + *self.state.write().await = State::Sleep; + } + + async fn run_wakeup_then_daylight(mut self) { + let light_name = "small_bedroom:piano"; + let bri = 1. / 254.; + let ct = 2000; + let bri_growth: f64 = 1.32; + let ct_growth: f64 = 1.028; + + self.system.one_lamp_ct(light_name, ct, bri).await; + // Make sure the light is the right ct and bri before turning it on + sleep(Duration::from_secs(1)).await; + self.system.one_lamp_on(light_name).await; + + for minute in 1..=20 { + sleep(Duration::from_secs(60)).await; + + let new_bri = bri * bri_growth.powi(minute); + let new_ct = (ct as f64 * ct_growth.powi(minute)).round() as usize; + + self.system.one_lamp_ct(light_name, new_ct, new_bri).await; + } + + *self.state.write().await = State::Daylight; + self.all_lights_daylight().await; + self.system.all_lamps_on().await; + } + + // TODO: make private once updates are in job system + pub(super) async fn all_lights_daylight(&mut self) { + if *self.state.read().await == State::Daylight { + let (new_ct, new_bri) = daylight_now(); + self.system.all_lamps_ct(new_ct, new_bri).await; + } + } +} diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index e842eac3..103e53b7 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -2,10 +2,6 @@ use tokio::sync::mpsc; use tracing::trace; -// TODO: make private once system is ported -pub use conversion::{ - denormalize, kelvin_to_mired, mired_to_kelvin, normalize, -}; pub(crate) use lamp::Model; mod cached_bridge; diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index 20929343..cc5b08e9 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -142,8 +142,8 @@ impl Mqtt { ..Default::default() }; - if topic.contains("kitchen:ceiling") { - warn!("ZB to MQTT (ceiling): {payload}"); + if topic.contains("small_bedroom:bureau") { + warn!("ZB to MQTT (bureau): {payload}"); } self.client .publish_with_properties( diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 4adc5fb8..3686d6cf 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -8,7 +8,6 @@ use serde_json::Value; use tokio::{sync::RwLock, time::sleep}; use tracing::{instrument, trace, warn}; -use crate::lights::denormalize; use crate::lights::lamp::{self, Lamp}; use crate::lights::parse_state::parse_lamp_properties; @@ -54,18 +53,18 @@ async fn update_state( .entry(light_name.to_owned()) .or_insert_with(|| Lamp::new(light_name)); for property in new { - if light_name == "kitchen:ceiling" { + if light_name == "small_bedroom:bureau" { match property { lamp::Property::Brightness(bri) => { - warn!( - "ZB received ceiling brightness change: {}", - denormalize(bri) - ); + warn!("ZB received bureau brightness change: {bri}"); + } + lamp::Property::ColorXY(xy) => { + warn!("ZB received bureau color change: {xy:?}"); } lamp::Property::Online(new_online) => { if new_online != current_lamp.is_online { warn!( - "ZB received ceiling online change: {new_online}" + "ZB received bureau online change: {new_online}" ); } } diff --git a/crates/zigbee-bridge/src/lights/conversion.rs b/crates/zigbee-bridge/src/lights/conversion.rs index 2492bf4c..cabcc278 100644 --- a/crates/zigbee-bridge/src/lights/conversion.rs +++ b/crates/zigbee-bridge/src/lights/conversion.rs @@ -4,32 +4,32 @@ use colorimetry::{cct::CCT, xyz::XYZ}; const DUV_IKEA: f64 = -0.002; #[must_use] -pub fn mired_to_kelvin(mired: usize) -> usize { +pub(super) fn mired_to_kelvin(mired: usize) -> usize { 1_000_000 / mired } #[must_use] -pub fn kelvin_to_mired(kelvin: usize) -> usize { +pub(super) fn kelvin_to_mired(kelvin: usize) -> usize { 1_000_000 / kelvin } #[must_use] -pub fn normalize(brightness: u8) -> f64 { +pub(super) fn normalize(brightness: u8) -> f64 { f64::from(brightness) / 254. } #[must_use] #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] -pub fn denormalize(brightness: f64) -> u8 { +pub(super) fn denormalize(brightness: f64) -> u8 { (brightness * 254.).round() as u8 } #[allow(clippy::doc_markdown)] /// 1000K < `color_temp` < 1_000_000K -pub(super) fn temp_to_xy(color_temp: usize) -> (f64, f64) { +pub(super) fn temp_to_xy(color_temp_k: usize) -> (f64, f64) { // TODO: use table from black body deviation measurements #[allow(clippy::cast_precision_loss)] - let cct = CCT::try_new(color_temp as f64, DUV_IKEA).unwrap(); + let cct = CCT::try_new(color_temp_k as f64, DUV_IKEA).unwrap(); let xyz: XYZ = cct.try_into().unwrap(); let (x, y) = xyz_to_xy(xyz); diff --git a/crates/zigbee-bridge/src/lights/lamp/property.rs b/crates/zigbee-bridge/src/lights/lamp/property.rs index fedaf324..1139c147 100644 --- a/crates/zigbee-bridge/src/lights/lamp/property.rs +++ b/crates/zigbee-bridge/src/lights/lamp/property.rs @@ -2,8 +2,7 @@ use serde_json::json; use strum::EnumDiscriminants; use tracing::error; -use crate::lights::{denormalize, kelvin_to_mired}; - +use crate::lights::conversion::{denormalize, kelvin_to_mired}; use super::Color; #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs index 22312a42..f2c2dce1 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -2,7 +2,7 @@ use color_eyre::eyre::{bail, Context, OptionExt, Report}; use color_eyre::Section; use serde_json::Value; -use crate::lights::{mired_to_kelvin, normalize}; +use crate::lights::conversion::{mired_to_kelvin, normalize}; use super::lamp; From d64d5a2a25d5b6bc3dac2e0f74980b6efb188dda Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Wed, 4 Dec 2024 15:10:35 +0100 Subject: [PATCH 470/687] Make wakeup length setting --- .../controller/rooms/small_bedroom/state.rs | 48 ++++++++++++------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index e4ae1791..089d6e16 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -87,24 +87,36 @@ impl Room { } async fn run_wakeup_then_daylight(mut self) { - let light_name = "small_bedroom:piano"; - let bri = 1. / 254.; - let ct = 2000; - let bri_growth: f64 = 1.32; - let ct_growth: f64 = 1.028; - - self.system.one_lamp_ct(light_name, ct, bri).await; - // Make sure the light is the right ct and bri before turning it on - sleep(Duration::from_secs(1)).await; - self.system.one_lamp_on(light_name).await; - - for minute in 1..=20 { - sleep(Duration::from_secs(60)).await; - - let new_bri = bri * bri_growth.powi(minute); - let new_ct = (ct as f64 * ct_growth.powi(minute)).round() as usize; - - self.system.one_lamp_ct(light_name, new_ct, new_bri).await; + const LIGHT_NAME: &str = "small_bedroom:piano"; + const RUNTIME_MINS: i32 = 7; + const STEP_SIZE_SECS: i32 = 30; + const N_STEPS: i32 = RUNTIME_MINS / STEP_SIZE_SECS; + + const START_BRI: f64 = 1. / 254.; + const START_CT: usize = 2000; + const END_BRI: f64 = 1.0; + const END_CT: usize = 3500; + + let bri_growth = (END_BRI / START_BRI).powf(1. / N_STEPS as f64); + let ct_growth = + (END_CT as f64 / START_CT as f64).powf(1. / N_STEPS as f64); + + self.system + .one_lamp_ct(LIGHT_NAME, START_CT, START_BRI) + .await; + self.system.one_lamp_on(LIGHT_NAME).await; + + for step in 1..=N_STEPS { + sleep(Duration::from_secs( + STEP_SIZE_SECS.try_into().expect("Should be positive"), + )) + .await; + + let new_bri = START_BRI * bri_growth.powi(step); + let new_ct = + (START_CT as f64 * ct_growth.powi(step)).round() as usize; + + self.system.one_lamp_ct(LIGHT_NAME, new_ct, new_bri).await; } *self.state.write().await = State::Daylight; From 6c8327cf5a5b63a3f1e8a7ab6ed60d623cb199ba Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Wed, 4 Dec 2024 15:28:42 +0100 Subject: [PATCH 471/687] Turn kitchen lights off when SB sleep --- crates/brain/src/controller/mod.rs | 23 +++++++--- crates/brain/src/controller/rooms/kitchen.rs | 44 ++++++++++++------- .../controller/rooms/small_bedroom/state.rs | 11 +++-- 3 files changed, 51 insertions(+), 27 deletions(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index a1de9933..851b8732 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -22,11 +22,14 @@ pub(crate) struct RestrictedSystem { } impl RestrictedSystem { - async fn one_lamp_ct(&mut self, name: &'static str, kelvin: usize, bri: f64) { + async fn one_lamp_ct( + &mut self, + name: &'static str, + kelvin: usize, + bri: f64, + ) { if self.allowed_lights.contains(&name) { - self.system - .lights_new - .set_color_temp(name, kelvin); + self.system.lights_new.set_color_temp(name, kelvin); self.system.lights_new.set_brightness(name, bri); } } @@ -45,9 +48,7 @@ impl RestrictedSystem { async fn all_lamps_ct(&mut self, kelvin: usize, bri: f64) { for name in &self.allowed_lights { - self.system - .lights_new - .set_color_temp(name, kelvin); + self.system.lights_new.set_color_temp(name, kelvin); self.system.lights_new.set_brightness(name, bri); } } @@ -63,6 +64,14 @@ impl RestrictedSystem { self.system.lights_new.set_on(name); } } + + async fn all_lamps_but_one_on(&mut self, leave_this_off: &str) { + for name in &self.allowed_lights { + if *name != leave_this_off { + self.system.lights_new.set_on(name); + } + } + } } pub fn start( diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index b3585dfb..1a599411 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -9,11 +9,10 @@ use tracing::warn; use crate::controller::rooms::small_bedroom; use crate::controller::{Event, RestrictedSystem}; +#[derive(PartialEq, Eq)] enum State { - // Sleep, - // Wakeup, - Normal, - // Away, + Sleep, + Daylight, } const INTERVAL: Duration = Duration::from_secs(5); @@ -41,18 +40,20 @@ impl RecvFiltered for broadcast::Receiver { #[derive(Debug)] enum RelevantEvent { - // DeskButton(protocol::large_bedroom::DeskButton), - SBState(small_bedroom::State), + Sleep, + Daylight, } -fn filter(_event: Event) -> Option { - // match event { - // // Event::Sensor(SensorValue::ButtonPress(Button::LargeBedroomDesk(desk))) => { - // // Some(RelevantEvent::DeskButton(desk)) - // // } - // _ => None, - // } - None +fn filter(event: Event) -> Option { + match event { + Event::StateChangeSB(small_bedroom::State::Sleep) => { + Some(RelevantEvent::Sleep) + } + Event::StateChangeSB(small_bedroom::State::Daylight) => { + Some(RelevantEvent::Daylight) + } + _ => None, + } } pub async fn run( @@ -66,7 +67,7 @@ pub async fn run( ShouldUpdate, } - let _state = State::Normal; + let mut state = State::Daylight; let mut next_update = Instant::now() + INTERVAL; loop { let get_event = event_rx.recv_filter_mapped(filter).map(Res::Event); @@ -74,11 +75,20 @@ pub async fn run( let res = (get_event, tick).race().await; match res { - Res::Event(_) => (), // handle_event(e), - Res::ShouldUpdate => { + Res::Event(RelevantEvent::Sleep) => { + state = State::Sleep; + system.all_lamps_off().await; + } + Res::Event(RelevantEvent::Daylight) => { + state = State::Daylight; + update(&mut system).await; + system.all_lamps_but_one_on("kitchen:hallway").await; + }, + Res::ShouldUpdate if state == State::Daylight => { update(&mut system).await; next_update = Instant::now() + INTERVAL; } + _ => (), } } } diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index 089d6e16..edfdd570 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -71,7 +71,12 @@ impl Room { async fn to_state_cancel_prev(&mut self, state: State) { self.cancel_task().await; *self.state.write().await = state.clone(); - let _ = self.event_tx.send(Event::StateChangeSB(state)); + let _ = dbg!(self.event_tx.send(Event::StateChangeSB(state))); + } + + async fn to_state(&mut self, state: State) { + *self.state.write().await = state.clone(); + let _ = dbg!(self.event_tx.send(Event::StateChangeSB(state))); } async fn cancel_task(&mut self) { @@ -83,7 +88,7 @@ impl Room { async fn delayed_off_then_sleep(mut self) { sleep(OFF_DELAY).await; self.system.all_lamps_off().await; - *self.state.write().await = State::Sleep; + self.to_state(State::Sleep).await; } async fn run_wakeup_then_daylight(mut self) { @@ -119,7 +124,7 @@ impl Room { self.system.one_lamp_ct(LIGHT_NAME, new_ct, new_bri).await; } - *self.state.write().await = State::Daylight; + self.to_state(State::Daylight).await; self.all_lights_daylight().await; self.system.all_lamps_on().await; } From 2fdc28d27b8737a6de43b9ab99b3b51696795ba1 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Wed, 4 Dec 2024 15:28:42 +0100 Subject: [PATCH 472/687] Turn kitchen lights off when SB sleep --- crates/brain/src/controller/mod.rs | 6 +++--- crates/brain/src/controller/rooms/kitchen.rs | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 851b8732..4eed71fa 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -65,10 +65,10 @@ impl RestrictedSystem { } } - async fn all_lamps_but_one_on(&mut self, leave_this_off: &str) { + async fn all_lamps_but_one_off(&mut self, leave_this_on: &str) { for name in &self.allowed_lights { - if *name != leave_this_off { - self.system.lights_new.set_on(name); + if *name != leave_this_on { + self.system.lights_new.set_off(name); } } } diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index 1a599411..6f2ed039 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -77,15 +77,18 @@ pub async fn run( match res { Res::Event(RelevantEvent::Sleep) => { state = State::Sleep; - system.all_lamps_off().await; + system.all_lamps_but_one_off("kitchen:hallway").await; } Res::Event(RelevantEvent::Daylight) => { state = State::Daylight; update(&mut system).await; - system.all_lamps_but_one_on("kitchen:hallway").await; + // TODO: only when LB also awake + // then turn all lamps off when SB sleep + system.all_lamps_on().await; }, Res::ShouldUpdate if state == State::Daylight => { update(&mut system).await; + system.all_lamps_on().await; next_update = Instant::now() + INTERVAL; } _ => (), From 148bdd811537d3c959c602add2a14fcc1428a4d5 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 5 Dec 2024 10:47:22 +0100 Subject: [PATCH 473/687] Add tracing for wakeup --- crates/brain/src/controller/rooms/small_bedroom/state.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index edfdd570..d866e7fa 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize}; use tokio::sync::{broadcast, Mutex, RwLock}; use tokio::task::{self, JoinHandle}; use tokio::time::sleep; +use tracing::warn; use super::{daylight_now, OFF_DELAY}; use crate::controller::{Event, RestrictedSystem}; @@ -50,6 +51,7 @@ impl Room { } pub(super) async fn to_wakeup(&mut self) { + warn!("Starting wakeup"); self.to_state_cancel_prev(State::Wakeup).await; let task_handle = task::spawn(self.clone().run_wakeup_then_daylight()); @@ -110,6 +112,7 @@ impl Room { .one_lamp_ct(LIGHT_NAME, START_CT, START_BRI) .await; self.system.one_lamp_on(LIGHT_NAME).await; + warn!("Wakeup lamp should be on now"); for step in 1..=N_STEPS { sleep(Duration::from_secs( @@ -127,6 +130,7 @@ impl Room { self.to_state(State::Daylight).await; self.all_lights_daylight().await; self.system.all_lamps_on().await; + warn!("Wakeup done"); } // TODO: make private once updates are in job system From 0bcd9ad1ff3b7f202264359341477dd116e014ae Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 5 Dec 2024 10:47:45 +0100 Subject: [PATCH 474/687] Add every day option to Job --- crates/brain/src/input/jobs.rs | 38 ++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index 12b5fb51..4e3c272e 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -1,7 +1,7 @@ use std::{sync::mpsc, thread, time::Duration}; use byteorder::{BigEndian, ReadBytesExt}; -use jiff::{Span, Zoned}; +use jiff::{Span, ToSpan, Zoned}; use mpsc::RecvTimeoutError::*; use serde::{Deserialize, Serialize}; use tokio::sync::broadcast; @@ -21,6 +21,7 @@ pub(crate) enum Error { pub(crate) struct Job { pub(crate) time: Zoned, pub(crate) event: Event, + pub(crate) every_day: bool, /// how long after the time was missed the job /// should still be executed pub(crate) expiration: Option, @@ -35,10 +36,30 @@ impl Job { ) -> Job { Job { time: to_datetime(hour, min), + every_day: false, event, expiration, } } + + pub(crate) fn every_day_at( + hour: i8, + min: i8, + event: Event, + expiration: Option, + ) -> Job { + Job { + time: to_datetime(hour, min), + every_day: true, + event, + expiration, + } + } + + pub(crate) fn add_one_day(mut self) -> Self { + self.time = self.time.checked_add(1.day()).unwrap(); + self + } } #[derive(Debug, Clone)] @@ -80,7 +101,10 @@ impl Jobs { self.job_change_tx.send(())?; Ok(id) } - pub(crate) fn remove_job(&self, to_remove: i64) -> Result, Error> { + pub(crate) fn remove_job( + &self, + to_remove: i64, + ) -> Result, Error> { let removed_job = self.list.remove_job(to_remove)?; //signal event timer to update its next job self.job_change_tx.send(())?; @@ -160,7 +184,7 @@ impl JobList { } } -fn event_timer( +async fn event_timer( mut job_list: JobList, event_tx: broadcast::Sender, job_change_rx: mpsc::Receiver<()>, @@ -190,8 +214,14 @@ fn event_timer( Err(Timeout) => { // time to send the job event event_tx - .send(current_job.event) + .send(current_job.event.clone()) .expect("controller should listen on this"); + if current_job.every_day { + job_list + .add_job(current_job.add_one_day()) + .await + .unwrap(); + } job_list.remove_job(id).unwrap(); continue; //get next job } From 07f6201cd4186d5f8087153a00253027e0006fd6 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 7 Dec 2024 13:37:41 +0100 Subject: [PATCH 475/687] Remove old wakeup and port jobs to dbstruct, untested --- Cargo.lock | 49 ++++- crates/brain/Cargo.toml | 1 + crates/brain/src/controller/mod.rs | 1 - .../src/controller/rooms/large_bedroom.rs | 2 - .../controller/rooms/large_bedroom/wakeup.rs | 199 ------------------ .../src/controller/rooms/small_bedroom.rs | 4 +- crates/brain/src/errors.rs | 2 - crates/brain/src/input/api.rs | 75 ------- crates/brain/src/input/jobs.rs | 115 ++++------ crates/brain/src/input/mod.rs | 1 - crates/brain/src/main.rs | 19 +- 11 files changed, 97 insertions(+), 371 deletions(-) delete mode 100644 crates/brain/src/controller/rooms/large_bedroom/wakeup.rs delete mode 100644 crates/brain/src/input/api.rs diff --git a/Cargo.lock b/Cargo.lock index c797c6e6..8da9ff8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -474,6 +474,7 @@ dependencies = [ "bytes", "clap", "data-server", + "dbstruct", "futures", "futures-concurrency", "futures-util", @@ -531,7 +532,7 @@ version = "0.7.1" source = "git+https://github.com/dvdsk/byteseries#eb057c6363548fa1fc2fbe5a89395b81238152f5" dependencies = [ "arraydeque", - "itertools", + "itertools 0.13.0", "num-traits", "ron", "serde", @@ -960,6 +961,33 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "dbstruct" +version = "0.4.1" +source = "git+https://github.com/dvdsk/dbstruct#e2f1147accff6a4d71d307d2311c7f493b31606e" +dependencies = [ + "bincode", + "dbstruct-derive", + "serde", + "sled", + "thiserror", + "tracing", +] + +[[package]] +name = "dbstruct-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "393042992e6516cf869ab7148ac3507ae1b9ce15d50b8f9bf43c8b05567b8acd" +dependencies = [ + "itertools 0.11.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.89", + "thiserror", +] + [[package]] name = "defmt" version = "0.3.8" @@ -2077,7 +2105,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "477e2e7ec7379407656293ff74902caea786a1dda427ca1f84b923c4fdeb7659" dependencies = [ "either", - "itertools", + "itertools 0.13.0", "proc-macro2", "quote", "strum", @@ -2142,6 +2170,15 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.13.0" @@ -3136,7 +3173,7 @@ dependencies = [ "compact_str", "crossterm", "instability", - "itertools", + "itertools 0.13.0", "lru", "paste", "strum", @@ -3425,7 +3462,7 @@ dependencies = [ "gethostname", "hdrhistogram", "indextree", - "itertools", + "itertools 0.13.0", "jiff", "log-store", "logger", @@ -4125,7 +4162,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" dependencies = [ - "itertools", + "itertools 0.13.0", "unicode-segmentation", "unicode-width", ] @@ -4683,7 +4720,7 @@ dependencies = [ "colorimetry", "futures", "futures-concurrency", - "itertools", + "itertools 0.13.0", "logger", "regex", "rumqttc", diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 24a0ed16..2b60b2cc 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -42,3 +42,4 @@ logger.workspace = true clap = { workspace = true } futures-concurrency = { workspace = true } strum = { version = "0.26.2", default-features = false, features = ["derive"] } +dbstruct = { git = "https://github.com/dvdsk/dbstruct" } diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 4eed71fa..4c22ab06 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -1,5 +1,4 @@ mod rooms; -pub(crate) use rooms::large_bedroom; use crate::system::System; pub use protocol::Reading; diff --git a/crates/brain/src/controller/rooms/large_bedroom.rs b/crates/brain/src/controller/rooms/large_bedroom.rs index d2dc525a..18def619 100644 --- a/crates/brain/src/controller/rooms/large_bedroom.rs +++ b/crates/brain/src/controller/rooms/large_bedroom.rs @@ -8,8 +8,6 @@ use tracing::{info, warn}; use crate::controller::{Event, RestrictedSystem}; -pub(crate) mod wakeup; - #[derive(Debug, Clone, PartialEq, Eq)] enum State { // Sleep, diff --git a/crates/brain/src/controller/rooms/large_bedroom/wakeup.rs b/crates/brain/src/controller/rooms/large_bedroom/wakeup.rs deleted file mode 100644 index e27e62d1..00000000 --- a/crates/brain/src/controller/rooms/large_bedroom/wakeup.rs +++ /dev/null @@ -1,199 +0,0 @@ -use crate::controller::Event; -use crate::input::jobs::{self, Job, Jobs}; - -use std::sync::Arc; -use std::time::Duration; -use tokio::runtime::Runtime; -use tokio::sync::{broadcast, Mutex}; -use tokio::task; -use tracing::{error, info}; - -// TODO FIXME multiple things left to do: -// - usually and tomorrow are not written to db -// - setting usually none goes wrong if tomorrow is not none -// - recheck set tomorrow and set usually - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Error modifying wakeup alarms: {0}")] - DbError(#[from] sled::Error), - #[error("Could not create/edit wakeup job")] - JobError(#[from] jobs::Error), -} - -async fn reset_on_wakeup( - wake_up: WakeUp, - mut event_rx: broadcast::Receiver, -) { - loop { - match event_rx.recv().await { - Ok(Event::WakeupLB) => { - if let Err(e) = wake_up.reset() { - /* TODO: this should make more "noise" then this <28-04-24, dvdsk> */ - error!("Could not reset wakeup system for next wake: {e}"); - } - } - Err(broadcast::error::RecvError::Closed) => return, - _ => (), - } - } -} - -#[derive(Clone)] -pub struct WakeUp(Arc>); -impl WakeUp { - /// # Important - /// The receiver must be subscribed before the jobs system is started - /// or it can miss alarms - pub fn setup( - db: sled::Db, - jobs: Jobs, - event_rx: broadcast::Receiver, - ) -> Result { - let inner = Inner::setup(db, jobs)?; - let inner = Arc::new(Mutex::new(inner)); - let this = Self(inner.clone()); - task::spawn(reset_on_wakeup(this, event_rx)); - - Ok(Self(inner)) - } - pub async fn tomorrow(&self) -> Option<(i8, i8)> { - self.0.lock().await.tomorrow - } - pub async fn usually(&self) -> Option<(i8, i8)> { - self.0.lock().await.usually - } - pub fn reset(&self) -> Result<(), Error> { - self.0.blocking_lock().reset()?; - info!("alarm system reset correctly"); - Ok(()) - } - pub async fn set_tomorrow(&self, time: Time) -> Result<(), Error> { - self.0.lock().await.set_tomorrow(time).await?; - info!("alarm tomorrow set to: time"); - Ok(()) - } - pub async fn set_usually(&self, time: Time) -> Result<(), Error> { - self.0.lock().await.set_usually(time).await?; - info!("alarm usually set to: time"); - Ok(()) - } -} - -type Time = Option<(i8, i8)>; -struct Inner { - db: sled::Tree, - pub tomorrow: Time, - pub usually: Time, - job_id: Option, - jobs: Jobs, -} - -impl Inner { - pub fn setup(db: sled::Db, jobs: Jobs) -> Result { - let db = db.open_tree("wakeup")?; - - let usually = db - .get("usually")? - // we want bincode to deserialize to Option<(i8,i8)> not (i8,i8) - .and_then(|b| bincode::deserialize(&b).unwrap()); - let job_id = - db.get("job_id")?.map(|b| bincode::deserialize(&b).unwrap()); - let next_alarm = job_id - .as_ref() - .and_then(|id| jobs.get(*id).unwrap()) - .map(|job| job.time) - .map(|t| (t.hour() as i8, t.minute() as i8)); - let tomorrow = next_alarm.filter(|tomorrow| Some(*tomorrow) != usually); - - Ok(Self { - db, - tomorrow, - usually, - job_id, - jobs, - }) - } - - /// stores a new job - fn save_job_id(&mut self, id: i64) -> Result<(), Error> { - self.job_id = Some(id); - let bytes = bincode::serialize(&id).unwrap(); - if let Some(bytes) = self.db.insert("job_id", bytes)? { - let old_job_id = bincode::deserialize(&bytes).unwrap(); - self.jobs.remove_job(old_job_id)?; - } - self.db.flush().unwrap(); - Ok(()) - } - - fn save_usually(&mut self, usually: &Time) -> Result<(), Error> { - let bytes = bincode::serialize(usually).unwrap(); - self.db.insert("usually", bytes)?; - self.db.flush()?; - Ok(()) - } - - async fn replace_job(&mut self, job: Job) -> Result<(), Error> { - let id = self.jobs.add_job(job).await?; - self.save_job_id(id)?; - Ok(()) - } - - fn remove_job(&mut self) -> Result<(), Error> { - self.jobs.remove_job(self.job_id.unwrap())?; - self.job_id = None; - Ok(()) - } - - /// reset the alarm, if there is a usual alarm - /// time we set that, otherwise remove all - pub fn reset(&mut self) -> Result<(), Error> { - if let Some((hour, min)) = self.usually { - let job = wakeup_at_next(hour, min); - let add = self.replace_job(job); - let rt = Runtime::new().unwrap(); - rt.block_on(add)?; - } - self.tomorrow = None; - Ok(()) - } - - pub async fn set_tomorrow(&mut self, time: Time) -> Result<(), Error> { - match time { - None => self.reset()?, - Some((hour, min)) => { - let job = wakeup_at_next(hour, min); - self.replace_job(job).await?; - } - } - self.tomorrow = time; - Ok(()) - } - - pub async fn set_usually(&mut self, time: Time) -> Result<(), Error> { - self.save_usually(&time)?; - match time { - Some((hour, min)) => { - let job = wakeup_at_next(hour, min); - self.replace_job(job).await?; - } - None => { - if self.job_id.is_some() && self.tomorrow.is_none() { - self.remove_job()?; - } - } - } - self.usually = time; - Ok(()) - } -} - -fn wakeup_at_next(hour: i8, min: i8) -> Job { - Job::at_next( - hour, - min, - Event::WakeupLB, - Some(Duration::from_secs(3 * 60 * 60)), - ) -} diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 01a792e1..877b549a 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -5,6 +5,7 @@ use futures_util::FutureExt; use protocol::small_bedroom::ButtonPanel; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; +use tracing::warn; use self::filter::{recv_filtered, RelevantEvent, Trigger}; use self::state::Room; @@ -30,8 +31,9 @@ pub async fn run( let _ = system .system .jobs - .add_job(Job::at_next(9, 0, Event::WakeupSB, Some(WAKEUP_EXPIRATION))) + .add(Job::at_next(9, 0, Event::WakeupSB, Some(WAKEUP_EXPIRATION))) .await; + warn!("Added job for SB wakeup"); loop { let get_event = recv_filtered(&mut event_rx); diff --git a/crates/brain/src/errors.rs b/crates/brain/src/errors.rs index 3c9503a2..5537f6a5 100644 --- a/crates/brain/src/errors.rs +++ b/crates/brain/src/errors.rs @@ -8,6 +8,4 @@ pub enum Error { DataBase(#[from] sled::Error), #[error("Error contacting mpd")] Mpd(#[from] mpd::error::Error), - #[error("Error in the wakeup alarm system")] - SetWakeUp(#[from] crate::controller::large_bedroom::wakeup::Error), } diff --git a/crates/brain/src/input/api.rs b/crates/brain/src/input/api.rs deleted file mode 100644 index 0c08e12e..00000000 --- a/crates/brain/src/input/api.rs +++ /dev/null @@ -1,75 +0,0 @@ -use axum::body::Bytes; -use axum::extract::State as aState; -use axum::http::StatusCode; -use axum::routing::get; -use axum::Router; - -use crate::controller::large_bedroom::wakeup::WakeUp; - - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Could not bind to port {port} on 127.0.0.1, error: {err}")] - Binding { err: std::io::Error, port: u16 }, - #[error("Can not run server, io error: {0:?}")] - Serving(std::io::Error), -} - -/// sends back bincode serialized -async fn usually(aState(state): aState) -> Vec { - let usually = state.wakeup.usually().await; - bincode::serialize(&usually).expect("Should be serializable") -} - -/// sends back bincode serialized -async fn tomorrow(aState(state): aState) -> Vec { - let tomorrow = state.wakeup.tomorrow().await; - bincode::serialize(&tomorrow).expect("Should be serializable") -} - -async fn set_usually(aState(state): aState, body: Bytes) -> StatusCode { - let time: Option<(i8, i8)> = bincode::deserialize(&body[..]) - .map_err(|_| "Could not deserialize into time") - .unwrap(); - state - .wakeup - .set_usually(time) - .await - .map_err(|_| "Could not save new alarm time") - .unwrap(); - - StatusCode::OK -} - -async fn set_tomorrow(aState(state): aState, body: Bytes) -> StatusCode { - let time: Option<(i8, i8)> = bincode::deserialize(&body[..]) - .map_err(|_| "Could not deserialize into time") - .unwrap(); - state - .wakeup - .set_tomorrow(time) - .await - .map_err(|_| "Could not save new alarm time") - .unwrap(); - - StatusCode::OK -} - -#[derive(Clone)] -pub struct State { - wakeup: WakeUp, -} - -pub async fn setup(wakeup: WakeUp, port: u16) -> Result<(), Error> { - let app = Router::new() - .route("/alarm/usually", get(usually).post(set_usually)) - .route("/alarm/tomorrow", get(tomorrow).post(set_tomorrow)) - .with_state(State { wakeup }); - - // https is done at the loadbalancer - let listener = tokio::net::TcpListener::bind(format!("127.0.0.1:{port}")) - .await - .map_err(|err| Error::Binding { err, port })?; - tracing::debug!("listening on {}", listener.local_addr().unwrap()); - axum::serve(listener, app).await.map_err(Error::Serving) -} diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index 4e3c272e..40a0d054 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -1,10 +1,11 @@ -use std::{sync::mpsc, thread, time::Duration}; +use std::{ + fmt, sync::{mpsc, Arc}, thread, time::Duration +}; -use byteorder::{BigEndian, ReadBytesExt}; use jiff::{Span, ToSpan, Zoned}; use mpsc::RecvTimeoutError::*; use serde::{Deserialize, Serialize}; -use tokio::sync::broadcast; +use tokio::sync::{broadcast, Mutex}; use tracing::{error, info}; use crate::{controller::Event, time::to_datetime}; @@ -15,9 +16,13 @@ pub(crate) enum Error { DbError(#[from] sled::Error), #[error("Could not inform event timer about new job")] CommError(#[from] mpsc::SendError<()>), + #[error("Dbstruct error")] + DbStructError(#[from] dbstruct::Error), + // #[error("Dbstruct error")] + // DbStructDoubleError(#[from] dbstruct::Error>), } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub(crate) struct Job { pub(crate) time: Zoned, pub(crate) event: Event, @@ -62,23 +67,29 @@ impl Job { } } -#[derive(Debug, Clone)] +#[derive(Clone)] pub(crate) struct Jobs { job_change_tx: mpsc::Sender<()>, - list: JobList, + list: Arc>, } -#[derive(Debug, Clone)] +impl fmt::Debug for Jobs { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Jobs db and manager") + } +} + +#[dbstruct::dbstruct(db=sled)] struct JobList { - db: sled::Tree, + jobs: HashMap, } impl Jobs { pub(crate) fn setup( event_tx: broadcast::Sender, - db: sled::Db, + db_path: &str, ) -> Result { - let job_list = JobList::new(db)?; + let job_list = Arc::new(Mutex::new(JobList::new(db_path)?)); let (job_change_tx, job_change_rx) = mpsc::channel(); let job_list_clone = job_list.clone(); @@ -95,111 +106,75 @@ impl Jobs { // we decrease the time till the job until there is a place in the database // as only one job can fire at the time, after a job gets a timeslot // it is never changed - pub(crate) async fn add_job(&self, to_add: Job) -> Result { - let id = self.list.add_job(to_add).await?; + pub(crate) async fn add(&self, to_add: Job) -> Result { + let id = self.list.lock().await.add_job(to_add).await?; //signal event timer to update its next job self.job_change_tx.send(())?; Ok(id) } - pub(crate) fn remove_job( + pub(crate) async fn remove( &self, to_remove: i64, ) -> Result, Error> { - let removed_job = self.list.remove_job(to_remove)?; + let removed_job = self.list.lock().await.remove_job(to_remove)?; //signal event timer to update its next job self.job_change_tx.send(())?; Ok(removed_job) } - pub(crate) fn get(&self, id: i64) -> Result, Error> { - self.list.get_job(id) + pub(crate) async fn get(&self, id: i64) -> Result, Error> { + self.list.lock().await.get_job(id) } } impl JobList { - fn new(db: sled::Db) -> Result { - Ok(JobList { - db: db.open_tree("jobs")?, - }) - } - fn get_job(&self, id: i64) -> Result, Error> { - Ok(self - .db - .get(id.to_be_bytes())? - .map(|k| bincode::deserialize::(&k).unwrap())) + Ok(self.jobs().get(&id)?) } - // we decrease the time till the job until there is a place in the database - // as only one job can fire at the time, after a job gets a timeslot - // it is never changed - /// return the key for the job + // we decrease the id for the job until there is a place in the database + // after a job gets an id it is never changed + /// return the id for the job async fn add_job(&self, to_add: Job) -> Result { - let mut timestamp = to_add.time.timestamp().as_millisecond(); - let job = bincode::serialize(&to_add).unwrap(); + let mut new_id = to_add.time.timestamp().as_millisecond(); // create job entry if there is no job at this timestamp yet - // if there is already a job scheduled, change the key for this one + // if there is already a job scheduled, change the id for this one // until there is a spot free - // TODO check how this works and expand sled documentation for fail cases - while let Err(_old_event) = self.db.compare_and_swap( - timestamp.to_be_bytes(), - None as Option<&[u8]>, - Some(job.clone()), - )? { + while let Some(_old_job) = self.jobs().get(&new_id)? { // create unique key - timestamp -= 1; + new_id -= 1; } - self.db.flush_async().await?; - Ok(timestamp) + self.jobs().insert(&new_id, &to_add)?; + Ok(new_id) } fn remove_job(&self, to_remove: i64) -> Result, Error> { - let old_job = self - .db - .remove(to_remove.to_be_bytes())? - .map(|k| bincode::deserialize::(&k).unwrap()); - self.db.flush()?; + let old_job = self.jobs().remove(&to_remove)?; Ok(old_job) } - /// calculate time to the earliest job, remove it from the list if the - /// current time is later than the job fn peek_next(&mut self) -> Option<(i64, Job)> { - // get earliest job time in db - match self.db.get_gt(0u64.to_be_bytes()) { - Ok(entry) => { - if let Some((id, job)) = entry { - let id = id.as_ref().read_i64::().unwrap(); - let job = bincode::deserialize(&job).unwrap(); - Some((id, job)) - } else { - None - } - } - Err(error) => { - error!("Could not retrieve next job: {:?}", error); - None - } - } + let list: Vec<_> = self.jobs().iter().filter_map(|r| r.ok()).collect(); + list.get(0).cloned() } } async fn event_timer( - mut job_list: JobList, + job_list: Arc>, event_tx: broadcast::Sender, job_change_rx: mpsc::Receiver<()>, ) { loop { // This can fail // TODO make sure an non waking error alarm is send to the user - if let Some((id, current_job)) = job_list.peek_next() { + if let Some((id, current_job)) = job_list.lock().await.peek_next() { let now = crate::time::now(); let timeout = ¤t_job.time - &now; if let Some(expiration) = current_job.expiration { if now > ¤t_job.time + Span::try_from(expiration).unwrap() { error!("skipping job too far in the past"); - job_list.remove_job(id).unwrap(); + job_list.lock().await.remove_job(id).unwrap(); continue; // job too far in the past, skip and get next } } @@ -218,11 +193,13 @@ async fn event_timer( .expect("controller should listen on this"); if current_job.every_day { job_list + .lock() + .await .add_job(current_job.add_one_day()) .await .unwrap(); } - job_list.remove_job(id).unwrap(); + job_list.lock().await.remove_job(id).unwrap(); continue; //get next job } } diff --git a/crates/brain/src/input/mod.rs b/crates/brain/src/input/mod.rs index cdc636d1..40e97747 100644 --- a/crates/brain/src/input/mod.rs +++ b/crates/brain/src/input/mod.rs @@ -1,5 +1,4 @@ pub mod jobs; -pub mod api; pub mod sensors; // pub mod mpd_status; // pub use mpd_status::MpdStatus; diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index ae7c2411..9d5904f3 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -13,6 +13,8 @@ mod input; mod system; mod time; +const JOBS_DB_PATH: &str = "database/jobs"; + #[derive(Parser)] #[command(version, about, long_about=None)] struct Opt { @@ -35,30 +37,17 @@ async fn main() -> Result<(), Box> { logger::tracing::setup(); let opt = Opt::parse(); - let db = sled::Config::default() //651ms - .path("database") - .flush_every_ms(None) //do not flush to disk unless explicitly asked - .cache_capacity(1024 * 1024 * 32) //32 mb cache - .open()?; - // must create all listeners before jobs/alarm events can be send // or they may be lost. - let (event_tx, event_rx) = broadcast::channel(250); + let (event_tx, _event_rx) = broadcast::channel(250); let subscribed_rxs = array::from_fn(|_| event_tx.subscribe()); - let jobs = Jobs::setup(event_tx.clone(), db.clone())?; - // TODO: untangle the large bedroom wakeup logic from everything else - let wakeup = controller::large_bedroom::wakeup::WakeUp::setup( - db.clone(), - jobs.clone(), - event_rx, - )?; + let jobs = Jobs::setup(event_tx.clone(), JOBS_DB_PATH)?; let system = System::init(jobs); let _tasks = controller::start(subscribed_rxs, event_tx.clone(), system); tokio::task::spawn(input::sensors::subscribe(event_tx, opt.data_server)); - input::api::setup(wakeup.clone(), opt.port).await?; unreachable!(); } From 3fc2066392f62fe94f8cba9a0a4d68d074561fe3 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 7 Dec 2024 13:41:48 +0100 Subject: [PATCH 476/687] Don't add jobs that already exist --- crates/brain/src/controller/mod.rs | 2 +- crates/brain/src/input/jobs.rs | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 4c22ab06..3ec03f2a 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use tokio::sync::broadcast; use tokio::task::JoinSet; -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum Event { Sensor(Reading), WakeupLB, diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index 40a0d054..6df0895f 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -22,7 +22,7 @@ pub(crate) enum Error { // DbStructDoubleError(#[from] dbstruct::Error>), } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub(crate) struct Job { pub(crate) time: Zoned, pub(crate) event: Event, @@ -134,17 +134,20 @@ impl JobList { // we decrease the id for the job until there is a place in the database // after a job gets an id it is never changed /// return the id for the job - async fn add_job(&self, to_add: Job) -> Result { - let mut new_id = to_add.time.timestamp().as_millisecond(); + async fn add_job(&self, new_job: Job) -> Result { + let mut new_id = new_job.time.timestamp().as_millisecond(); // create job entry if there is no job at this timestamp yet - // if there is already a job scheduled, change the id for this one - // until there is a spot free - while let Some(_old_job) = self.jobs().get(&new_id)? { + // if there is already a job scheduled, and it is not exactly the same, + // change the id for this one until there is a spot free + while let Some(old_job) = self.jobs().get(&new_id)? { + if old_job == new_job { + return Ok(new_id) + } // create unique key new_id -= 1; } - self.jobs().insert(&new_id, &to_add)?; + self.jobs().insert(&new_id, &new_job)?; Ok(new_id) } From 101b80fb8ce3dd417935e9cbeb33c60d804b45d8 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 7 Dec 2024 13:46:22 +0100 Subject: [PATCH 477/687] Set wakeup SB to repeat every day --- crates/brain/src/controller/rooms/small_bedroom.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 877b549a..85587dd1 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -31,7 +31,12 @@ pub async fn run( let _ = system .system .jobs - .add(Job::at_next(9, 0, Event::WakeupSB, Some(WAKEUP_EXPIRATION))) + .add(Job::every_day_at( + 9, + 0, + Event::WakeupSB, + Some(WAKEUP_EXPIRATION), + )) .await; warn!("Added job for SB wakeup"); From a551e8dc5dd87e635086774fdae95a7758dbb441 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 7 Dec 2024 14:46:49 +0100 Subject: [PATCH 478/687] Merge payloads for hue lights --- .../src/lights/cached_bridge/changes.rs | 5 ++- .../src/lights/cached_bridge/mqtt.rs | 32 +++++++++++++++++-- crates/zigbee-bridge/src/lights/lamp.rs | 4 +++ crates/zigbee-bridge/src/lights/lamp/model.rs | 14 ++++++++ .../zigbee-bridge/src/lights/lamp/property.rs | 5 ++- 5 files changed, 53 insertions(+), 7 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index ca92c0a8..40fe3b3c 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -74,7 +74,10 @@ async fn send_diff_get_timeout( }; if is_online { - let _ = mqtt.send_diff_where_due(light_name, &diff).await; + let merged_payloads = needed.is_hue_lamp(); + let _ = mqtt + .send_diff_where_due(light_name, merged_payloads, &diff) + .await; } if let Some(deadline) = mqtt.next_deadline(light_name, &diff) { diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index cc5b08e9..a622f36d 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -4,7 +4,7 @@ use std::time::Instant; use rumqttc::v5::mqttbytes::QoS; use rumqttc::v5::{AsyncClient, ClientError}; use serde_json::json; -use tracing::{instrument, trace, warn}; +use tracing::{trace, warn}; use crate::lights::lamp; @@ -89,15 +89,17 @@ impl Mqtt { deadline < Instant::now() } - #[instrument(skip(self))] pub(super) async fn send_diff_where_due( &mut self, light_name: &str, + merged_payloads: bool, diff: &[lamp::Property], ) -> Result<(), ClientError> { + let mut due_changes = Vec::new(); + for change in diff { if self.is_due(&light_name, change) { - self.set(&light_name, change.payload()).await?; + due_changes.push(change); let light_send_record = self.last_sent.entry(light_name.to_owned()).or_default(); @@ -106,6 +108,17 @@ impl Mqtt { } } + if !due_changes.is_empty() { + if merged_payloads { + let payload = merge_payloads(due_changes); + self.set(&light_name, payload.to_string()).await?; + } else { + for change in due_changes { + self.set(&light_name, change.payload().to_string()).await?; + } + } + } + Ok(()) } @@ -156,3 +169,16 @@ impl Mqtt { .await } } + +fn merge_payloads(mut changes: Vec<&lamp::Property>) -> serde_json::Value { + let payload = changes + .iter_mut() + .map(|c| c.payload()) + .map(|p| p.as_object().expect("Should be a map").to_owned()) + .reduce(|mut acc, mut e| { + acc.append(&mut e); + acc + }) + .unwrap(); + serde_json::Value::Object(payload.clone()) +} diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index a4120001..f645d038 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -45,6 +45,10 @@ impl Lamp { } } + pub(super) fn is_hue_lamp(&self) -> bool { + self.model.is_hue() + } + #[instrument] pub(super) fn changes_relative_to(&self, other: &Self) -> Vec { let mut res = Vec::new(); diff --git a/crates/zigbee-bridge/src/lights/lamp/model.rs b/crates/zigbee-bridge/src/lights/lamp/model.rs index 729945df..3b337cd6 100644 --- a/crates/zigbee-bridge/src/lights/lamp/model.rs +++ b/crates/zigbee-bridge/src/lights/lamp/model.rs @@ -160,4 +160,18 @@ impl Model { .into_iter() .collect() } + + pub(crate) fn is_hue(&self) -> bool { + match self { + Model::TradfriCandle + | Model::TradfriE27 + | Model::TradfriGU10 + | Model::TradfriE14Color + | Model::TradfriE14White + | Model::TradfriOther(_) => false, + Model::HueGen4 | Model::HueOther(_) => true, + // I guess we default to sending payloads separately + Model::Other(_) => false, + } + } } diff --git a/crates/zigbee-bridge/src/lights/lamp/property.rs b/crates/zigbee-bridge/src/lights/lamp/property.rs index 1139c147..68f9313e 100644 --- a/crates/zigbee-bridge/src/lights/lamp/property.rs +++ b/crates/zigbee-bridge/src/lights/lamp/property.rs @@ -2,8 +2,8 @@ use serde_json::json; use strum::EnumDiscriminants; use tracing::error; -use crate::lights::conversion::{denormalize, kelvin_to_mired}; use super::Color; +use crate::lights::conversion::{denormalize, kelvin_to_mired}; #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] pub(crate) enum ColorTempStartup { @@ -46,7 +46,7 @@ impl PartialEq for Property { impl Eq for Property {} impl Property { - pub(crate) fn payload(&self) -> String { + pub(crate) fn payload(&self) -> serde_json::Value { match *self { Property::Brightness(bri) => { json!({ "brightness": denormalize(bri) }) @@ -68,7 +68,6 @@ impl Property { json!({"state": ""}) } } - .to_string() } } From 3a6058067f7965a822b8a2bf1f5bd6285b1fe085 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 7 Dec 2024 15:06:57 +0100 Subject: [PATCH 479/687] Fix critical crash in brain Introduced with old wakeup removal --- crates/brain/src/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index 9d5904f3..7bfcb73a 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -47,7 +47,8 @@ async fn main() -> Result<(), Box> { let system = System::init(jobs); let _tasks = controller::start(subscribed_rxs, event_tx.clone(), system); - tokio::task::spawn(input::sensors::subscribe(event_tx, opt.data_server)); + // This never returns, should be replaced by an endless loop if (re)moved + input::sensors::subscribe(event_tx, opt.data_server).await; unreachable!(); } From e7d016b215b79335d7fcce91ada12eb798a8c6c8 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 7 Dec 2024 15:07:30 +0100 Subject: [PATCH 480/687] Fix hue issues by collecting changes before sending --- .../zigbee-bridge/src/lights/cached_bridge.rs | 1 + .../src/lights/cached_bridge/changes.rs | 49 ++++++++++++------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index f38c86d3..02f2ee7a 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -16,6 +16,7 @@ const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); // unfortunately we have to use the zigbee-herdsman timeout to prevent // the z2m queue from getting filled up const TIME_IT_TAKES_TO_APPLY_CHANGE: Duration = Duration::from_secs(10); +const CHANGE_ACCUMULATION_TIME: Duration = Duration::from_millis(100); pub(super) async fn run( change_receiver: mpsc::UnboundedReceiver<(String, lamp::Property)>, diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index 40fe3b3c..dabbcf6a 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -6,7 +6,9 @@ use tokio::time::{sleep, timeout}; use tracing::{debug, instrument, trace}; use super::mqtt::Mqtt; -use super::{MQTT_MIGHT_BE_DOWN_TIMEOUT, WAIT_FOR_INIT_STATES}; +use super::{ + CHANGE_ACCUMULATION_TIME, MQTT_MIGHT_BE_DOWN_TIMEOUT, WAIT_FOR_INIT_STATES, +}; use crate::lights::lamp::{self, Lamp}; pub(super) async fn handle( @@ -22,26 +24,37 @@ pub(super) async fn handle( loop { debug!("timeout: {call_at_least_in:?}"); - if let Ok(update) = - timeout(call_at_least_in, change_receiver.recv()).await - { - let (light_name, change) = - update.expect("Channel should never close"); - - trace!("Received change: {change:?} for lamp {light_name}"); - apply_change_to_needed( - light_name, - change, - known_states, - &mut needed_states, - ) - .await; - }; + match timeout(call_at_least_in, change_receiver.recv()).await { + // On change, update needed, but only actually send the changes + // after a timeout + Ok(update) => { + let (light_name, change) = + update.expect("Channel should never close"); + + trace!("Received change: {change:?} for lamp {light_name}"); + apply_change_to_needed( + light_name, + change, + known_states, + &mut needed_states, + ) + .await; - call_at_least_in = - send_diff_get_timeout(known_states, &mut needed_states, mqtt) + // When there hasn't been a new change in 100 ms, we will timeout + // and send the accumulated changes + call_at_least_in = CHANGE_ACCUMULATION_TIME; + } + _ => { + // Send the accumulated changes and get the timeout for resending + call_at_least_in = send_diff_get_timeout( + known_states, + &mut needed_states, + mqtt, + ) .await .min(MQTT_MIGHT_BE_DOWN_TIMEOUT); + } + }; } } From e5a683c85ce0077aa6cce5424213278781022ad0 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 7 Dec 2024 15:25:27 +0100 Subject: [PATCH 481/687] Remove dbg statements --- crates/brain/src/controller/rooms/small_bedroom.rs | 1 - crates/brain/src/controller/rooms/small_bedroom/state.rs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 85587dd1..37f9fa95 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -59,7 +59,6 @@ pub async fn run( } async fn handle_buttonpress(room: &mut Room, button: ButtonPanel) { - dbg!(button); match button { ButtonPanel::BottomLeft(_) => { room.to_sleep().await; diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index d866e7fa..350b2e87 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -73,12 +73,12 @@ impl Room { async fn to_state_cancel_prev(&mut self, state: State) { self.cancel_task().await; *self.state.write().await = state.clone(); - let _ = dbg!(self.event_tx.send(Event::StateChangeSB(state))); + let _ = self.event_tx.send(Event::StateChangeSB(state)); } async fn to_state(&mut self, state: State) { *self.state.write().await = state.clone(); - let _ = dbg!(self.event_tx.send(Event::StateChangeSB(state))); + let _ = self.event_tx.send(Event::StateChangeSB(state)); } async fn cancel_task(&mut self) { From f318618d95b61e0d030a17d5f86fcd4bc5fe062a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 7 Dec 2024 16:39:37 +0100 Subject: [PATCH 482/687] moved sensors retry/reinit + driver trait to seperate crate --- sensor-nodes/Cargo.lock | 19 +++ sensor-nodes/Cargo.toml | 4 +- sensor-nodes/bed-sb/Cargo.toml | 18 ++- sensor-nodes/bed-sb/src/channel.rs | 10 +- sensor-nodes/bed-sb/src/error_cache.rs | 57 -------- sensor-nodes/bed-sb/src/main.rs | 1 - sensor-nodes/bed-sb/src/sensors.rs | 113 ++-------------- sensor-nodes/bed-sb/src/sensors/fast.rs | 27 ++-- sensor-nodes/bed-sb/src/sensors/retry.rs | 127 ------------------ sensor-nodes/bed-sb/src/sensors/slow.rs | 10 +- sensor-nodes/sensors/Cargo.toml | 24 ++++ sensor-nodes/sensors/src/drivers.rs | 40 ++++++ .../sensors/src/drivers/driver_impl_bme680.rs | 34 +++++ .../src/drivers/driver_impl_max44009.rs | 31 +++++ .../src/drivers/driver_impl_nau7802.rs | 31 +++++ .../sensors/src/drivers/driver_impl_sht31.rs | 37 +++++ .../src/drivers}/reinit_on_error.rs | 30 ++--- sensor-nodes/sensors/src/drivers/wrap_mhz.rs | 44 ++++++ .../src/drivers/wrap_sps30.rs} | 26 ++-- sensor-nodes/sensors/src/errors.rs | 84 ++++++++++++ sensor-nodes/sensors/src/lib.rs | 34 +++++ 21 files changed, 447 insertions(+), 354 deletions(-) delete mode 100644 sensor-nodes/bed-sb/src/error_cache.rs delete mode 100644 sensor-nodes/bed-sb/src/sensors/retry.rs create mode 100644 sensor-nodes/sensors/Cargo.toml create mode 100644 sensor-nodes/sensors/src/drivers.rs create mode 100644 sensor-nodes/sensors/src/drivers/driver_impl_bme680.rs create mode 100644 sensor-nodes/sensors/src/drivers/driver_impl_max44009.rs create mode 100644 sensor-nodes/sensors/src/drivers/driver_impl_nau7802.rs create mode 100644 sensor-nodes/sensors/src/drivers/driver_impl_sht31.rs rename sensor-nodes/{bed-sb/src/sensors/retry => sensors/src/drivers}/reinit_on_error.rs (79%) create mode 100644 sensor-nodes/sensors/src/drivers/wrap_mhz.rs rename sensor-nodes/{bed-sb/src/sensors/retry/retry_init.rs => sensors/src/drivers/wrap_sps30.rs} (80%) create mode 100644 sensor-nodes/sensors/src/errors.rs create mode 100644 sensor-nodes/sensors/src/lib.rs diff --git a/sensor-nodes/Cargo.lock b/sensor-nodes/Cargo.lock index e1d631ed..9ff6a993 100644 --- a/sensor-nodes/Cargo.lock +++ b/sensor-nodes/Cargo.lock @@ -1154,6 +1154,24 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "sensors" +version = "0.1.0" +dependencies = [ + "bosch-bme680", + "defmt", + "embassy-embedded-hal", + "embassy-stm32", + "embassy-sync 0.6.1", + "embassy-time", + "max44009", + "mhzx", + "nau7802-async", + "protocol", + "sht31", + "sps30-async", +] + [[package]] name = "serde" version = "1.0.215" @@ -1214,6 +1232,7 @@ dependencies = [ "panic-probe", "protocol", "rand", + "sensors", "sht31", "sps30-async", "static_cell", diff --git a/sensor-nodes/Cargo.toml b/sensor-nodes/Cargo.toml index 33432c97..c22e5f14 100644 --- a/sensor-nodes/Cargo.toml +++ b/sensor-nodes/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "2" -members = ["bed-sb", "bed-lb"] +members = ["bed-sb", "bed-lb", "sensors"] [workspace.dependencies] protocol = { path = "../crates/protocol" } @@ -17,6 +17,8 @@ embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime-ms", "tick-hz-32_768"] } embassy-futures = { version = "0.1.0"} +defmt = "0.3" + [patch.crates-io] embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } diff --git a/sensor-nodes/bed-sb/Cargo.toml b/sensor-nodes/bed-sb/Cargo.toml index 701b3ce6..734e6bcc 100644 --- a/sensor-nodes/bed-sb/Cargo.toml +++ b/sensor-nodes/bed-sb/Cargo.toml @@ -7,18 +7,15 @@ license = "GPLv3" authors = ["David Kleingeld & Eva van Houten"] [dependencies] -embassy-stm32 = { version = "0.1.0", features = [ "defmt", "stm32f401cc", -"unstable-pac", "memory-x", "time-driver-tim9", "time", "exti" ] } -embassy-sync = { version = "0.6.0", features = ["defmt"] } -embassy-executor = { version = "0.6.0", features = ["arch-cortex-m", -"executor-thread", "defmt", "integrated-timers", "executor-interrupt"] } -embassy-embedded-hal = { version = "0.2.0" } -embassy-time = { version = "0.3.2", features = ["defmt", -"defmt-timestamp-uptime-ms", "tick-hz-32_768"] } -embassy-futures = { version = "0.1.0"} +embassy-stm32.workspace = true +embassy-sync.workspace = true +embassy-executor.workspace = true +embassy-embedded-hal.workspace = true +embassy-time.workspace = true +embassy-futures.workspace = true embassy-usb = { version = "0.3.0", features = ["defmt"] } -defmt = "0.3" +defmt.workspace = true defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } @@ -35,6 +32,7 @@ rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } static_cell = "2.0.0" # sensors +sensors = { path = "../sensors" } bosch-bme680 = { version = "1.0.2", path = "/home/david/Documents/async-bosch-bme680" } max44009 = { version = "0.2", git = "https://github.com/dvdsk/max44009-rs" } sht31 = { version = "0.3.0", git = "https://github.com/dvdsk/SHT31-rs", features = ["postcard"] } diff --git a/sensor-nodes/bed-sb/src/channel.rs b/sensor-nodes/bed-sb/src/channel.rs index fb7448f3..89385fca 100644 --- a/sensor-nodes/bed-sb/src/channel.rs +++ b/sensor-nodes/bed-sb/src/channel.rs @@ -7,18 +7,16 @@ use embassy_time::{Duration, Instant}; use heapless::HistoryBuffer; use protocol::small_bedroom::bed::Reading; -use crate::error_cache; - pub struct Queues { sensor_queue: PriorityChannel, - error_queue: Channel, - recent_errors: Mutex>, + error_queue: Channel, + recent_errors: Mutex>, recent_is_since: Instant, } pub enum QueueItem { Reading(PriorityValue), - Error(error_cache::Error), + Error(sensors::Error), } impl Queues { @@ -56,7 +54,7 @@ impl Queues { self.sensor_queue.try_receive().ok() } - pub fn queue_error(&self, error: error_cache::Error) { + pub fn queue_error(&self, error: sensors::Error) { // unwrap safe: is not used in interrupts let mut recent_errors = defmt::unwrap!(self.recent_errors.try_lock()); if self.recent_is_since.elapsed() > Duration::from_secs(60 * 5) { diff --git a/sensor-nodes/bed-sb/src/error_cache.rs b/sensor-nodes/bed-sb/src/error_cache.rs deleted file mode 100644 index ab74aa72..00000000 --- a/sensor-nodes/bed-sb/src/error_cache.rs +++ /dev/null @@ -1,57 +0,0 @@ -use protocol::small_bedroom::bed::{self, Device}; -use protocol::make_error_string; - -use crate::sensors::{I2cError, UartError}; - -#[derive(defmt::Format, PartialEq, Eq, Clone)] -pub(crate) enum SensorError { - Mhz14(mhzx::Error), - Sps30(sps30_async::Error), - Sht31(sht31::SHTError), - Bme680(bosch_bme680::BmeError), - Max44(max44009::Error), - Nau7802(nau7802_async::Error), - Button(PressTooLong), -} - -#[derive(defmt::Format, PartialEq, Eq, Clone)] -pub(crate) struct PressTooLong { - pub(crate) button: &'static str, -} - -impl core::fmt::Debug for PressTooLong { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.write_fmt(format_args!("Button {}, pressed too long", self.button)) - } -} - -impl From for bed::SensorError { - fn from(val: SensorError) -> Self { - match val { - SensorError::Mhz14(e) => bed::SensorError::Mhz14(make_error_string(e)), - SensorError::Sps30(e) => bed::SensorError::Sps30(make_error_string(e)), - SensorError::Sht31(e) => bed::SensorError::Sht31(make_error_string(e)), - SensorError::Bme680(e) => bed::SensorError::Bme680(make_error_string(e)), - SensorError::Max44(e) => bed::SensorError::Max44(make_error_string(e)), - SensorError::Nau7802(e) => bed::SensorError::Nau7802(make_error_string(e)), - SensorError::Button(e) => bed::SensorError::Button(make_error_string(e)), - } - } -} - -#[derive(defmt::Format, PartialEq, Eq, Clone)] -pub(crate) enum Error { - Running(SensorError), - Setup(SensorError), - Timeout(Device), -} - -impl From for bed::Error { - fn from(val: Error) -> Self { - match val { - Error::Running(e) => bed::Error::Running(e.into()), - Error::Setup(e) => bed::Error::Setup(e.into()), - Error::Timeout(dev) => bed::Error::Timeout(dev), - } - } -} diff --git a/sensor-nodes/bed-sb/src/main.rs b/sensor-nodes/bed-sb/src/main.rs index fb6d0af9..6b846727 100644 --- a/sensor-nodes/bed-sb/src/main.rs +++ b/sensor-nodes/bed-sb/src/main.rs @@ -25,7 +25,6 @@ use {defmt_rtt as _, panic_probe as _}; mod channel; mod comms; -mod error_cache; mod sensors; mod usb_wrapper; use crate::channel::Queues; diff --git a/sensor-nodes/bed-sb/src/sensors.rs b/sensor-nodes/bed-sb/src/sensors.rs index 9840ae71..5b8d7789 100644 --- a/sensor-nodes/bed-sb/src/sensors.rs +++ b/sensor-nodes/bed-sb/src/sensors.rs @@ -1,44 +1,26 @@ use defmt::info; -use embassy_embedded_hal::shared_bus::I2cDeviceError; use embassy_futures::join; use embassy_stm32::i2c::I2c; use embassy_stm32::mode::Async; use embassy_stm32::usart::Uart; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; -use embassy_time::Delay; use fast::ButtonInputs; -use mhzx::MHZ; use protocol::small_bedroom::bed::Device; -use sps30_async::Sps30; use crate::channel::Queues; -use crate::error_cache::{Error, SensorError}; +use sensors::{Error, SPS30_UART_BUF_SIZE}; pub mod fast; -pub mod retry; pub mod slow; -use retry::{Bme680Driver, Driver, Max44Driver, Nau7802Driver, Sht31Driver, Sps30Driver}; +use sensors::{ + Bme680Driver, Max44Driver, Nau7802Driver, Sht31Driver, Sps30Driver, MhzDriver +}; -pub type I2cError = I2cDeviceError; -pub type UartError = embassy_stm32::usart::Error; - -pub mod concrete_types { - use embassy_embedded_hal::shared_bus; - use embassy_stm32::i2c::I2c; - use embassy_stm32::mode::Async; - use embassy_stm32::usart::{RingBufferedUartRx, UartTx}; - use embassy_sync::blocking_mutex::raw::NoopRawMutex; - use shared_bus::asynch::i2c::I2cDevice; - - pub type ConcreteSharedI2c<'a> = I2cDevice<'a, NoopRawMutex, I2c<'static, Async>>; - pub type ConcreteTx<'a> = UartTx<'a, Async>; - pub type ConcreteRx<'a> = RingBufferedUartRx<'a>; +fn local_dev(dev: protocol::small_bedroom::bed::Device) -> protocol::Device { + protocol::Device::SmallBedroom(protocol::small_bedroom::Device::Bed(dev)) } -const SPS30_UART_BUF_SIZE: usize = 150; -const SPS30_DRIVER_BUF_SIZE: usize = 2 * SPS30_UART_BUF_SIZE; - pub async fn init_then_measure( publish: &Queues, orderers: &slow::DriverOrderers, @@ -49,20 +31,20 @@ pub async fn init_then_measure( buttons: ButtonInputs, ) -> Result<(), Error> { info!("initializing sensors"); - let bme = Bme680Driver::new(&i2c_3, Device::Bme680); - let max44009 = Max44Driver::new(&i2c_1, Device::Max44); - let sht = Sht31Driver::new(&i2c_1, Device::Sht31); - let nau = Nau7802Driver::new(&i2c_3, Device::Nau7802); + let bme = Bme680Driver::new(&i2c_3, local_dev(Device::Bme680)); + let max44009 = Max44Driver::new(&i2c_1, local_dev(Device::Max44)); + let sht = Sht31Driver::new(&i2c_1, local_dev(Device::Sht31)); + let nau = Nau7802Driver::new(&i2c_3, local_dev(Device::Nau7802)); let (tx, rx) = usart_mhz.split(); let mut usart_buf = [0u8; 9 * 10]; // 9 byte messages let rx = rx.into_ring_buffered(&mut usart_buf); - let mhz = MHZ::from_tx_rx(tx, rx); + let mhz = MhzDriver::new(tx, rx, local_dev(Device::Mhz14)); let (tx, rx) = usart_sps.split(); let mut usart_buf = [0u8; SPS30_UART_BUF_SIZE]; let rx = rx.into_ring_buffered(&mut usart_buf); - let sps30 = Sps30Driver::init(tx, rx); + let sps30 = Sps30Driver::init(tx, rx, local_dev(Device::Sps30)); let sensors_fast = fast::read(max44009, nau, buttons, publish); let drivers = slow::Drivers { @@ -76,74 +58,3 @@ pub async fn init_then_measure( defmt::unreachable!(); } - -use concrete_types::ConcreteRx as Rx; -use concrete_types::ConcreteTx as Tx; -impl<'a> Driver for MHZ, Rx<'a>> { - type Measurement = mhzx::Measurement; - type Affector = (); - - #[inline(always)] - async fn try_measure(&mut self) -> Result { - self.read_co2() - .await - .map_err(SensorError::Mhz14) - .map_err(Error::Running) - } - - #[inline(always)] - fn device(&self) -> protocol::small_bedroom::bed::Device { - Device::Mhz14 - } -} - -impl<'a> Driver for Sps30, Rx<'a>, Delay> { - type Measurement = sps30_async::Measurement; - type Affector = (); - - #[inline(always)] - async fn try_measure(&mut self) -> Result { - self.read_measurement() - .await - .map_err(SensorError::Sps30) - .map_err(Error::Running) - } - - #[inline(always)] - fn device(&self) -> protocol::small_bedroom::bed::Device { - Device::Sps30 - } -} - -pub(crate) struct I2cWrapper(Mutex); - -impl embedded_hal_async::i2c::ErrorType for &I2cWrapper { - type Error = ::Error; -} - -impl embedded_hal_async::i2c::I2c for &I2cWrapper { - async fn transaction( - &mut self, - address: u8, - operations: &mut [embedded_hal_async::i2c::Operation<'_>], - ) -> Result<(), Self::Error> { - self.0.lock().await.transaction(address, operations) - } - - async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { - self.0.lock().await.read(address, read) - } - - async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { - self.0.lock().await.write(address, write) - } - - async fn write_read( - &mut self, - address: u8, - write: &[u8], - read: &mut [u8], - ) -> Result<(), Self::Error> { - self.0.lock().await.write_read(address, write, read) - } -} diff --git a/sensor-nodes/bed-sb/src/sensors/fast.rs b/sensor-nodes/bed-sb/src/sensors/fast.rs index e33c5e65..fcc0c012 100644 --- a/sensor-nodes/bed-sb/src/sensors/fast.rs +++ b/sensor-nodes/bed-sb/src/sensors/fast.rs @@ -5,8 +5,8 @@ use embassy_time::{Duration, Instant, Timer}; use protocol::small_bedroom::{bed::Button, bed::Reading}; -use super::retry::{Max44Driver, Nau7802Driver}; use crate::channel::Queues; +use sensors::{Max44Driver, Nau7802Driver}; fn sig_lux_diff(old: f32, new: f32) -> bool { let diff = old - new; @@ -51,16 +51,20 @@ async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues) { } trait Nau { - async fn try_measure(&mut self) -> Result; + async fn try_measure(&mut self) -> Result; } impl Nau for Nau7802Driver<'_> { - async fn try_measure(&mut self) -> Result { + async fn try_measure(&mut self) -> Result { Nau7802Driver::try_measure(self).await } } -async fn report_weight(mut nau: impl Nau, wrap: impl Fn(u32) -> Reading, publish: &Queues) { +async fn report_weight( + mut nau: impl Nau, + wrap: impl Fn(u32) -> Reading, + publish: &Queues, +) { const MAX_INTERVAL: Duration = Duration::from_secs(5); let mut prev_weight = u32::MAX; @@ -96,7 +100,7 @@ async fn watch_button( event: impl Fn(protocol::button::Press) -> Button, channel: &Queues, ) { - use crate::error_cache::{Error, PressTooLong, SensorError}; + use sensors::{errors::PressTooLong, errors::SensorError, Error}; let mut went_high_at: Option = None; loop { @@ -106,9 +110,9 @@ async fn watch_button( let Ok(press) = press.as_millis().try_into() else { let event_for_printing = (event)(protocol::button::Press(0)); let name = event_for_printing.variant_name(); - channel.queue_error(Error::Running(SensorError::Button(PressTooLong { - button: name, - }))); + channel.queue_error(Error::Running(SensorError::Button( + PressTooLong { button: name }, + ))); continue; }; let event = (event)(protocol::button::Press(press)); @@ -156,10 +160,5 @@ pub(crate) async fn read( let watch_lux = report_lux(max44, publish); let report_weight = report_weight(nau, Reading::Weight, publish); - join::join3( - report_weight, - watch_lux, - watch_buttons, - ) - .await; + join::join3(report_weight, watch_lux, watch_buttons).await; } diff --git a/sensor-nodes/bed-sb/src/sensors/retry.rs b/sensor-nodes/bed-sb/src/sensors/retry.rs deleted file mode 100644 index f25e1046..00000000 --- a/sensor-nodes/bed-sb/src/sensors/retry.rs +++ /dev/null @@ -1,127 +0,0 @@ -use bosch_bme680::Bme680; -use embassy_embedded_hal::shared_bus; -use embassy_stm32::i2c::I2c; -use embassy_stm32::mode::Async; -use embassy_sync::blocking_mutex::raw::NoopRawMutex; -use embassy_sync::mutex::Mutex; -use embassy_time::{Delay, Timer}; -use max44009::{Max44009, SlaveAddr}; -use nau7802_async::Nau7802; -use sht31::mode::SingleShot; -use sht31::SHT31; - -use super::concrete_types::ConcreteSharedI2c; -use crate::error_cache::SensorError; - -mod reinit_on_error; -pub use reinit_on_error::{ - Bme680Driver, Max44Driver, Nau7802Driver, Sht31Driver, -}; - -mod retry_init; -pub use retry_init::Sps30Driver; - -impl<'a> ReInitableDriver for SHT31> { - type Parts = &'a Mutex>; - type Measurement = sht31::Reading; - - async fn init(parts: Self::Parts) -> Result { - let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); - Ok(SHT31::new(shared_i2c, Delay) - .with_mode(SingleShot) - .with_unit(sht31::TemperatureUnit::Celsius) - .with_accuracy(sht31::Accuracy::High)) - } - - async fn measure(&mut self) -> Result { - use sht31::mode::Sht31Measure; - use sht31::mode::Sht31Reader; - - Sht31Measure::measure(self) - .await - .map_err(SensorError::Sht31)?; - Timer::after_secs(1).await; - self.read().await.map_err(SensorError::Sht31) - } -} - -impl<'a> ReInitableDriver for Bme680, Delay> { - type Parts = &'a Mutex>; - type Measurement = bosch_bme680::MeasurementData; - - async fn init(parts: Self::Parts) -> Result { - let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); - Bme680::new( - shared_i2c, - bosch_bme680::DeviceAddress::Secondary, - Delay, - &bosch_bme680::Configuration::default(), - 21, - ) - .await - .map_err(SensorError::Bme680) - } - - async fn measure(&mut self) -> Result { - self.measure().await.map_err(SensorError::Bme680) - } -} - -impl<'a> ReInitableDriver for Max44009> { - type Parts = &'a Mutex>; - type Measurement = f32; - - async fn init(parts: Self::Parts) -> Result { - let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); - // Wrap these two into something returning Ok or Err - // then make it a generic arg, maybe Driverfactory::init - let mut driver = Max44009::new(shared_i2c, SlaveAddr::default()); - driver - .set_measurement_mode(max44009::MeasurementMode::Continuous) - .await - .map_err(SensorError::Max44)?; - Ok(driver) - } - async fn measure(&mut self) -> Result { - self.read_lux().await.map_err(SensorError::Max44) - } -} - -impl<'a> ReInitableDriver for Nau7802, Delay> { - type Parts = &'a Mutex>; - type Measurement = u32; - - async fn init(parts: Self::Parts) -> Result { - let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); - // Wrap these two into something returning Ok or Err - // then make it a generic arg, maybe Driverfactory::init - let driver = Nau7802::new(shared_i2c, Delay) - .await - .map_err(SensorError::Nau7802)?; - Ok(driver) - } - - async fn measure(&mut self) -> Result { - self.read().await.map_err(SensorError::Nau7802) - } -} - -/// A driver that can be re-initialized from copy-able parts -pub trait ReInitableDriver: Sized { - type Parts: Clone; - type Measurement; - - async fn init(parts: Self::Parts) -> Result; - async fn measure(&mut self) -> Result; -} - -pub trait Driver { - type Measurement; - type Affector; - async fn try_measure(&mut self) -> Result; - /// For example calibrate, run sensor cleaning etc - async fn affect(&mut self, _: Self::Affector) -> Result<(), crate::error_cache::Error> { - Ok(()) - } - fn device(&self) -> protocol::small_bedroom::bed::Device; -} diff --git a/sensor-nodes/bed-sb/src/sensors/slow.rs b/sensor-nodes/bed-sb/src/sensors/slow.rs index 097b5339..e81e8b08 100644 --- a/sensor-nodes/bed-sb/src/sensors/slow.rs +++ b/sensor-nodes/bed-sb/src/sensors/slow.rs @@ -6,19 +6,15 @@ use embassy_sync::channel::Channel; use embassy_time::Timer; use embassy_time::{with_timeout, Duration}; -use mhzx::MHZ; use protocol::small_bedroom::bed::Reading; use bosch_bme680::MeasurementData; use sps30_async as sps30; use crate::channel::Queues; -use crate::error_cache::Error; +use sensors::{Error, MhzDriver}; -use super::retry::{Bme680Driver, Driver, Sht31Driver, Sps30Driver}; - -use super::concrete_types::ConcreteRx as Rx; -use super::concrete_types::ConcreteTx as Tx; +use sensors::{Bme680Driver, Driver, Sht31Driver, Sps30Driver}; type Signal = embassy_sync::signal::Signal; @@ -70,7 +66,7 @@ async fn order_measurements_every_period(signals: &[Signal]) { pub(crate) struct Drivers<'a> { pub sht: Sht31Driver<'a>, pub bme: Bme680Driver<'a>, - pub mhz: MHZ, Rx<'a>>, + pub mhz: MhzDriver<'a>, pub sps: Sps30Driver<'a>, } diff --git a/sensor-nodes/sensors/Cargo.toml b/sensor-nodes/sensors/Cargo.toml new file mode 100644 index 00000000..8086c3bb --- /dev/null +++ b/sensor-nodes/sensors/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "sensors" +version = "0.1.0" +rust-version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true + +[dependencies] +protocol = { workspace = true } +embassy-stm32.workspace = true +embassy-sync.workspace = true +embassy-time.workspace = true +embassy-embedded-hal.workspace = true + +defmt.workspace = true + +# sensors +bosch-bme680 = { version = "1.0.2", path = "/home/david/Documents/async-bosch-bme680" } +max44009 = { version = "0.2", git = "https://github.com/dvdsk/max44009-rs" } +sht31 = { version = "0.3.0", git = "https://github.com/dvdsk/SHT31-rs", features = ["postcard"] } +mhzx = { version = "0.3.0", path = "/home/david/tmp/mh-zx-driver", features = ["serde", "postcard"] } +sps30-async = { version = "0.3.0", path = "/home/david/tmp/sps30", features = ["serde", "postcard"] } +nau7802-async = { path = "/home/david/tmp/nau7802-rs", features = ["serde", "postcard", "defmt"] } diff --git a/sensor-nodes/sensors/src/drivers.rs b/sensor-nodes/sensors/src/drivers.rs new file mode 100644 index 00000000..1785d120 --- /dev/null +++ b/sensor-nodes/sensors/src/drivers.rs @@ -0,0 +1,40 @@ +mod reinit_on_error; + +mod driver_impl_bme680; +mod driver_impl_max44009; +mod driver_impl_nau7802; +mod driver_impl_sht31; +mod wrap_mhz; +mod wrap_sps30; + +use reinit_on_error::ReInitOnErrorDriver; + +use embassy_embedded_hal::shared_bus; +use embassy_stm32::i2c::I2c; +use embassy_stm32::mode::Async; +use embassy_stm32::usart::{RingBufferedUartRx, UartTx}; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use shared_bus::asynch::i2c::I2cDevice; + +pub type ConcreteSharedI2c<'a> = + I2cDevice<'a, NoopRawMutex, I2c<'static, Async>>; +pub type ConcreteTx<'a> = UartTx<'a, Async>; +pub type ConcreteRx<'a> = RingBufferedUartRx<'a>; + +use bosch_bme680::Bme680; +use embassy_time::Delay; +use max44009::Max44009; +use nau7802_async::Nau7802; +use sht31::mode::SingleShot; +use sht31::SHT31; + +// Driver type aliases/wrapper structs. These auto correct/re-init on error +pub use wrap_mhz::MhzDriver; +pub use wrap_sps30::{Sps30Driver, SPS30_DRIVER_BUF_SIZE, SPS30_UART_BUF_SIZE}; +pub type Nau7802Driver<'a> = + ReInitOnErrorDriver, Delay>>; +pub type Max44Driver<'a> = ReInitOnErrorDriver>>; +pub type Bme680Driver<'a> = + ReInitOnErrorDriver, Delay>>; +pub type Sht31Driver<'a> = + ReInitOnErrorDriver>>; diff --git a/sensor-nodes/sensors/src/drivers/driver_impl_bme680.rs b/sensor-nodes/sensors/src/drivers/driver_impl_bme680.rs new file mode 100644 index 00000000..f56f3411 --- /dev/null +++ b/sensor-nodes/sensors/src/drivers/driver_impl_bme680.rs @@ -0,0 +1,34 @@ +use bosch_bme680::Bme680; +use embassy_embedded_hal::shared_bus; +use embassy_stm32::i2c::I2c; +use embassy_stm32::mode::Async; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::mutex::Mutex; +use embassy_time::Delay; + +use crate::errors::SensorError; +use crate::ReInitableDriver; + +use super::ConcreteSharedI2c; + +impl<'a> ReInitableDriver for Bme680, Delay> { + type Parts = &'a Mutex>; + type Measurement = bosch_bme680::MeasurementData; + + async fn init(parts: Self::Parts) -> Result { + let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); + Bme680::new( + shared_i2c, + bosch_bme680::DeviceAddress::Secondary, + Delay, + &bosch_bme680::Configuration::default(), + 21, + ) + .await + .map_err(SensorError::Bme680) + } + + async fn measure(&mut self) -> Result { + self.measure().await.map_err(SensorError::Bme680) + } +} diff --git a/sensor-nodes/sensors/src/drivers/driver_impl_max44009.rs b/sensor-nodes/sensors/src/drivers/driver_impl_max44009.rs new file mode 100644 index 00000000..e0a7c36c --- /dev/null +++ b/sensor-nodes/sensors/src/drivers/driver_impl_max44009.rs @@ -0,0 +1,31 @@ +use embassy_embedded_hal::shared_bus; +use embassy_stm32::i2c::I2c; +use embassy_stm32::mode::Async; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::mutex::Mutex; +use max44009::{Max44009, SlaveAddr}; + +use crate::errors::SensorError; +use crate::ReInitableDriver; + +use super::ConcreteSharedI2c; + +impl<'a> ReInitableDriver for Max44009> { + type Parts = &'a Mutex>; + type Measurement = f32; + + async fn init(parts: Self::Parts) -> Result { + let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); + // Wrap these two into something returning Ok or Err + // then make it a generic arg, maybe Driverfactory::init + let mut driver = Max44009::new(shared_i2c, SlaveAddr::default()); + driver + .set_measurement_mode(max44009::MeasurementMode::Continuous) + .await + .map_err(SensorError::Max44)?; + Ok(driver) + } + async fn measure(&mut self) -> Result { + self.read_lux().await.map_err(SensorError::Max44) + } +} diff --git a/sensor-nodes/sensors/src/drivers/driver_impl_nau7802.rs b/sensor-nodes/sensors/src/drivers/driver_impl_nau7802.rs new file mode 100644 index 00000000..f38391c4 --- /dev/null +++ b/sensor-nodes/sensors/src/drivers/driver_impl_nau7802.rs @@ -0,0 +1,31 @@ +use embassy_embedded_hal::shared_bus; +use embassy_stm32::i2c::I2c; +use embassy_stm32::mode::Async; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::mutex::Mutex; +use embassy_time::Delay; +use nau7802_async::Nau7802; + +use crate::errors::SensorError; +use crate::ReInitableDriver; + +use super::ConcreteSharedI2c; + +impl<'a> ReInitableDriver for Nau7802, Delay> { + type Parts = &'a Mutex>; + type Measurement = u32; + + async fn init(parts: Self::Parts) -> Result { + let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); + // Wrap these two into something returning Ok or Err + // then make it a generic arg, maybe Driverfactory::init + let driver = Nau7802::new(shared_i2c, Delay) + .await + .map_err(SensorError::Nau7802)?; + Ok(driver) + } + + async fn measure(&mut self) -> Result { + self.read().await.map_err(SensorError::Nau7802) + } +} diff --git a/sensor-nodes/sensors/src/drivers/driver_impl_sht31.rs b/sensor-nodes/sensors/src/drivers/driver_impl_sht31.rs new file mode 100644 index 00000000..a279f8b7 --- /dev/null +++ b/sensor-nodes/sensors/src/drivers/driver_impl_sht31.rs @@ -0,0 +1,37 @@ +use embassy_embedded_hal::shared_bus; +use embassy_stm32::i2c::I2c; +use embassy_stm32::mode::Async; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::mutex::Mutex; +use embassy_time::{Delay, Timer}; +use sht31::mode::SingleShot; +use sht31::SHT31; + +use crate::errors::SensorError; +use crate::ReInitableDriver; + +use super::ConcreteSharedI2c; + +impl<'a> ReInitableDriver for SHT31> { + type Parts = &'a Mutex>; + type Measurement = sht31::Reading; + + async fn init(parts: Self::Parts) -> Result { + let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); + Ok(SHT31::new(shared_i2c, Delay) + .with_mode(SingleShot) + .with_unit(sht31::TemperatureUnit::Celsius) + .with_accuracy(sht31::Accuracy::High)) + } + + async fn measure(&mut self) -> Result { + use sht31::mode::Sht31Measure; + use sht31::mode::Sht31Reader; + + Sht31Measure::measure(self) + .await + .map_err(SensorError::Sht31)?; + Timer::after_secs(1).await; + self.read().await.map_err(SensorError::Sht31) + } +} diff --git a/sensor-nodes/bed-sb/src/sensors/retry/reinit_on_error.rs b/sensor-nodes/sensors/src/drivers/reinit_on_error.rs similarity index 79% rename from sensor-nodes/bed-sb/src/sensors/retry/reinit_on_error.rs rename to sensor-nodes/sensors/src/drivers/reinit_on_error.rs index cec44184..ef7a00cf 100644 --- a/sensor-nodes/bed-sb/src/sensors/retry/reinit_on_error.rs +++ b/sensor-nodes/sensors/src/drivers/reinit_on_error.rs @@ -1,24 +1,7 @@ -use bosch_bme680::Bme680; -use embassy_time::Delay; -use max44009::Max44009; -use nau7802_async::Nau7802; -use protocol::small_bedroom::bed::Device; -use sht31::mode::SingleShot; -use sht31::SHT31; +use protocol::Device; -use super::super::concrete_types::ConcreteSharedI2c; -use super::ReInitableDriver; -use crate::error_cache::Error; - -pub type Nau7802Driver<'a> = ReInitOnErrorDriver, Delay>>; -pub type Max44Driver<'a> = ReInitOnErrorDriver>>; -pub type Bme680Driver<'a> = ReInitOnErrorDriver, Delay>>; -pub type Sht31Driver<'a> = ReInitOnErrorDriver>>; - -enum State { - Ready { driver: D }, - Uninit, -} +use crate::errors::Error; +use crate::{Driver, ReInitableDriver}; pub struct ReInitOnErrorDriver where @@ -29,7 +12,12 @@ where device: Device, } -impl super::Driver for ReInitOnErrorDriver { +enum State { + Ready { driver: D }, + Uninit, +} + +impl Driver for ReInitOnErrorDriver { type Measurement = D::Measurement; type Affector = (); diff --git a/sensor-nodes/sensors/src/drivers/wrap_mhz.rs b/sensor-nodes/sensors/src/drivers/wrap_mhz.rs new file mode 100644 index 00000000..c25ae57d --- /dev/null +++ b/sensor-nodes/sensors/src/drivers/wrap_mhz.rs @@ -0,0 +1,44 @@ +use mhzx::MHZ; +use protocol::Device; + +use crate::errors::SensorError; +use crate::{Driver, Error}; + +use super::{ConcreteRx, ConcreteTx}; + +pub struct MhzDriver<'a> { + driver: MHZ, ConcreteRx<'a>>, + device: protocol::Device, +} + +impl<'a> MhzDriver<'a> { + pub fn new( + uart_tx: ConcreteTx<'a>, + uart_rx: ConcreteRx<'a>, + device: Device, + ) -> Self { + Self { + driver: MHZ::from_tx_rx(uart_tx, uart_rx), + device, + } + } +} + +impl<'a> Driver for MhzDriver<'a> { + type Measurement = mhzx::Measurement; + type Affector = (); + + #[inline(always)] + async fn try_measure(&mut self) -> Result { + self.driver + .read_co2() + .await + .map_err(SensorError::Mhz14) + .map_err(Error::Running) + } + + #[inline(always)] + fn device(&self) -> protocol::Device { + self.device.clone() + } +} diff --git a/sensor-nodes/bed-sb/src/sensors/retry/retry_init.rs b/sensor-nodes/sensors/src/drivers/wrap_sps30.rs similarity index 80% rename from sensor-nodes/bed-sb/src/sensors/retry/retry_init.rs rename to sensor-nodes/sensors/src/drivers/wrap_sps30.rs index 8f2e0cda..09f2f4a9 100644 --- a/sensor-nodes/bed-sb/src/sensors/retry/retry_init.rs +++ b/sensor-nodes/sensors/src/drivers/wrap_sps30.rs @@ -1,24 +1,32 @@ use embassy_time::Delay; use sps30_async::Sps30; -use crate::error_cache::{Error, SensorError}; -use crate::sensors::concrete_types::{ConcreteRx, ConcreteTx}; -use crate::sensors::SPS30_DRIVER_BUF_SIZE; +use crate::errors::{Error, SensorError}; +use crate::Driver; -use super::Driver; +use super::{ConcreteRx, ConcreteTx}; + +pub const SPS30_UART_BUF_SIZE: usize = 150; +pub const SPS30_DRIVER_BUF_SIZE: usize = 2 * SPS30_UART_BUF_SIZE; /// reset the device when an error occurs pub struct Sps30Driver<'a> { is_init: bool, driver: Sps30, ConcreteRx<'a>, Delay>, + device: protocol::Device, } impl<'a> Sps30Driver<'a> { - pub fn init(tx: ConcreteTx<'a>, rx: ConcreteRx<'a>) -> Self { + pub fn init( + tx: ConcreteTx<'a>, + rx: ConcreteRx<'a>, + device: protocol::Device, + ) -> Self { let driver = Sps30::from_tx_rx_uninit(tx, rx, Delay); Self { is_init: false, driver, + device, } } @@ -61,11 +69,11 @@ impl<'a> Driver for Sps30Driver<'a> { type Measurement = sps30_async::Measurement; type Affector = (); - async fn try_measure(&mut self) -> Result { + async fn try_measure(&mut self) -> Result { self.measure().await } - async fn affect(&mut self, _: Self::Affector) -> Result<(), crate::error_cache::Error> { + async fn affect(&mut self, _: Self::Affector) -> Result<(), Error> { self.driver .start_fan_cleaning() .await @@ -77,7 +85,7 @@ impl<'a> Driver for Sps30Driver<'a> { Ok(()) } - fn device(&self) -> protocol::small_bedroom::bed::Device { - protocol::small_bedroom::bed::Device::Sps30 + fn device(&self) -> protocol::Device { + self.device.clone() } } diff --git a/sensor-nodes/sensors/src/errors.rs b/sensor-nodes/sensors/src/errors.rs new file mode 100644 index 00000000..50bfd60a --- /dev/null +++ b/sensor-nodes/sensors/src/errors.rs @@ -0,0 +1,84 @@ +use embassy_embedded_hal::shared_bus::I2cDeviceError; +use protocol::make_error_string; + +pub type I2cError = I2cDeviceError; +pub type UartError = embassy_stm32::usart::Error; + +#[derive(defmt::Format, PartialEq, Eq, Clone)] +pub struct PressTooLong { + pub button: &'static str, +} + +impl core::fmt::Debug for PressTooLong { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.write_fmt(format_args!("Button {}, pressed too long", self.button)) + } +} + +#[derive(defmt::Format, PartialEq, Eq, Clone)] +pub enum SensorError { + Mhz14(mhzx::Error), + Sps30(sps30_async::Error), + Sht31(sht31::SHTError), + Bme680(bosch_bme680::BmeError), + Max44(max44009::Error), + Nau7802(nau7802_async::Error), + Button(PressTooLong), +} + +/// This error type is as small as possible. It is meant for +/// devices to deduplicate errors that happen rapidly and only +/// send such errors every once in a while to the host +#[derive(defmt::Format, PartialEq, Eq, Clone)] +pub enum Error { + Running(SensorError), + Setup(SensorError), + Timeout(protocol::Device), +} + +impl From for protocol::small_bedroom::bed::SensorError { + fn from(val: SensorError) -> Self { + use protocol::small_bedroom::bed; + match val { + SensorError::Mhz14(e) => { + bed::SensorError::Mhz14(make_error_string(e)) + } + SensorError::Sps30(e) => { + bed::SensorError::Sps30(make_error_string(e)) + } + SensorError::Sht31(e) => { + bed::SensorError::Sht31(make_error_string(e)) + } + SensorError::Bme680(e) => { + bed::SensorError::Bme680(make_error_string(e)) + } + SensorError::Max44(e) => { + bed::SensorError::Max44(make_error_string(e)) + } + SensorError::Nau7802(e) => { + bed::SensorError::Nau7802(make_error_string(e)) + } + SensorError::Button(e) => { + bed::SensorError::Button(make_error_string(e)) + } + } + } +} + +impl From for protocol::small_bedroom::bed::Error { + fn from(val: Error) -> Self { + use protocol::small_bedroom::bed; + match val { + Error::Running(e) => bed::Error::Running(e.into()), + Error::Setup(e) => bed::Error::Setup(e.into()), + Error::Timeout(protocol::Device::SmallBedroom( + protocol::small_bedroom::Device::Bed(dev), + )) => bed::Error::Timeout(dev), + Error::Timeout(incorrect_dev) => defmt::unreachable!( + "Should only contain small_bedroom::bed devices, got {} which \ + is not part of small_bedroom::bed::Device", + incorrect_dev + ), + } + } +} diff --git a/sensor-nodes/sensors/src/lib.rs b/sensor-nodes/sensors/src/lib.rs new file mode 100644 index 00000000..c67d0cb4 --- /dev/null +++ b/sensor-nodes/sensors/src/lib.rs @@ -0,0 +1,34 @@ +#![no_std] + +mod drivers; +pub mod errors; + +pub use drivers::{ + Bme680Driver, Max44Driver, Nau7802Driver, Sps30Driver, Sht31Driver, MhzDriver, + SPS30_DRIVER_BUF_SIZE, SPS30_UART_BUF_SIZE, +}; +pub use errors::Error; +use errors::SensorError; + +#[allow(async_fn_in_trait)] +pub trait Driver { + type Measurement; + type Affector; + + async fn try_measure(&mut self) -> Result; + /// For example calibrate, run sensor cleaning etc + async fn affect(&mut self, _: Self::Affector) -> Result<(), Error> { + Ok(()) + } + fn device(&self) -> protocol::Device; +} + +/// A driver that can be re-initialized from copy-able parts +#[allow(async_fn_in_trait)] +pub trait ReInitableDriver: Sized { + type Parts: Clone; + type Measurement; + + async fn init(parts: Self::Parts) -> Result; + async fn measure(&mut self) -> Result; +} From 0b72b37424bb134843e30723d7546a9275f6c632 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 7 Dec 2024 16:57:21 +0100 Subject: [PATCH 483/687] nodes no long depend on sensor driver crates --- sensor-nodes/Cargo.lock | 9 ----- sensor-nodes/Cargo.toml | 11 ++++++ sensor-nodes/bed-sb/Cargo.toml | 29 ++++++---------- sensor-nodes/bed-sb/src/sensors/slow.rs | 44 ++++++++++++++++-------- sensor-nodes/sensors/src/lib.rs | 2 ++ sensor-nodes/sensors/src/measurements.rs | 8 +++++ 6 files changed, 61 insertions(+), 42 deletions(-) create mode 100644 sensor-nodes/sensors/src/measurements.rs diff --git a/sensor-nodes/Cargo.lock b/sensor-nodes/Cargo.lock index 9ff6a993..73b41bb5 100644 --- a/sensor-nodes/Cargo.lock +++ b/sensor-nodes/Cargo.lock @@ -1207,7 +1207,6 @@ dependencies = [ name = "small-bedroom-sensor-node" version = "0.2.0" dependencies = [ - "bosch-bme680", "cortex-m", "cortex-m-rt", "defmt", @@ -1225,17 +1224,9 @@ dependencies = [ "embedded-io-async", "futures", "heapless 0.8.0 (git+https://github.com/rust-embedded/heapless?rev=0ebca23)", - "max44009", - "mhzx", - "nau7802-async", - "nb 1.1.0", "panic-probe", "protocol", - "rand", "sensors", - "sht31", - "sps30-async", - "static_cell", ] [[package]] diff --git a/sensor-nodes/Cargo.toml b/sensor-nodes/Cargo.toml index c22e5f14..c361474a 100644 --- a/sensor-nodes/Cargo.toml +++ b/sensor-nodes/Cargo.toml @@ -5,6 +5,9 @@ members = ["bed-sb", "bed-lb", "sensors"] [workspace.dependencies] protocol = { path = "../crates/protocol" } +cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } +cortex-m-rt = "0.7.0" + embassy-stm32 = { version = "0.1.0", features = [ "defmt", "stm32f401cc", "unstable-pac", "memory-x", "time-driver-tim9", "time", "exti" ] } embassy-net = { version = "0.4.0", features = ["defmt", "proto-ipv4", "tcp", "dhcpv4","medium-ethernet"] } @@ -17,7 +20,15 @@ embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime-ms", "tick-hz-32_768"] } embassy-futures = { version = "0.1.0"} +embedded-hal = "1.0.0" +embedded-hal-async = "1.0" +embedded-hal-bus = { version = "0.2", features = ["async", "defmt-03"] } +embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } +futures = { version = "0.3.17", default-features = false, features = ["async-await"] } + defmt = "0.3" +defmt-rtt = "0.4" +panic-probe = { version = "0.3", features = ["print-defmt"] } [patch.crates-io] embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } diff --git a/sensor-nodes/bed-sb/Cargo.toml b/sensor-nodes/bed-sb/Cargo.toml index 734e6bcc..43549399 100644 --- a/sensor-nodes/bed-sb/Cargo.toml +++ b/sensor-nodes/bed-sb/Cargo.toml @@ -7,6 +7,9 @@ license = "GPLv3" authors = ["David Kleingeld & Eva van Houten"] [dependencies] +cortex-m.workspace = true +cortex-m-rt.workspace = true + embassy-stm32.workspace = true embassy-sync.workspace = true embassy-executor.workspace = true @@ -16,29 +19,19 @@ embassy-futures.workspace = true embassy-usb = { version = "0.3.0", features = ["defmt"] } defmt.workspace = true -defmt-rtt = "0.4" +defmt-rtt.workspace = true + +embedded-hal.workspace = true +embedded-hal-async.workspace = true +embedded-hal-bus.workspace = true +embedded-io-async.workspace = true -cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } -cortex-m-rt = "0.7.0" -embedded-hal = "1.0.0" -embedded-hal-async = "1.0" -embedded-hal-bus = { version = "0.2", features = ["async", "defmt-03"] } -embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } -panic-probe = { version = "0.3", features = ["print-defmt"] } -futures = { version = "0.3.17", default-features = false, features = ["async-await"] } +panic-probe.workspace = true +futures.workspace = true heapless = { git = "https://github.com/rust-embedded/heapless", version = "0.8", rev = "0ebca23", default-features = false } -nb = "1.0.0" -rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } -static_cell = "2.0.0" # sensors sensors = { path = "../sensors" } -bosch-bme680 = { version = "1.0.2", path = "/home/david/Documents/async-bosch-bme680" } -max44009 = { version = "0.2", git = "https://github.com/dvdsk/max44009-rs" } -sht31 = { version = "0.3.0", git = "https://github.com/dvdsk/SHT31-rs", features = ["postcard"] } -mhzx = { version = "0.3.0", path = "/home/david/tmp/mh-zx-driver", features = ["serde", "postcard"] } -sps30-async = { version = "0.3.0", path = "/home/david/tmp/sps30", features = ["serde", "postcard"] } -nau7802-async = { path = "/home/david/tmp/nau7802-rs", features = ["serde", "postcard", "defmt"] } # encoding protocol = { workspace = true } diff --git a/sensor-nodes/bed-sb/src/sensors/slow.rs b/sensor-nodes/bed-sb/src/sensors/slow.rs index e81e8b08..f1d1a973 100644 --- a/sensor-nodes/bed-sb/src/sensors/slow.rs +++ b/sensor-nodes/bed-sb/src/sensors/slow.rs @@ -8,13 +8,10 @@ use embassy_time::{with_timeout, Duration}; use protocol::small_bedroom::bed::Reading; -use bosch_bme680::MeasurementData; -use sps30_async as sps30; - use crate::channel::Queues; -use sensors::{Error, MhzDriver}; - +use sensors::measurements; use sensors::{Bme680Driver, Driver, Sht31Driver, Sps30Driver}; +use sensors::{Error, MhzDriver}; type Signal = embassy_sync::signal::Signal; @@ -88,7 +85,11 @@ impl DriverOrderers { } #[inline(always)] -pub async fn read(drivers: Drivers<'_>, orderers: &DriverOrderers, publish: &'_ Queues) { +pub async fn read( + drivers: Drivers<'_>, + orderers: &DriverOrderers, + publish: &'_ Queues, +) { let signals = [const { Signal::new() }; 4]; join5( @@ -121,9 +122,12 @@ pub async fn read(drivers: Drivers<'_>, orderers: &DriverOrderers, publish: &'_ .await; } -fn publish_sps_result(sps_res: Result, publish: &Queues) { +fn publish_sps_result( + sps_res: Result, + publish: &Queues, +) { match sps_res { - Ok(sps30::Measurement { + Ok(measurements::Sps30 { mass_pm1_0, mass_pm2_5, mass_pm4_0, @@ -145,15 +149,19 @@ fn publish_sps_result(sps_res: Result, publish: &Queu publish.send_p0(Reading::NumberPm2_5(number_pm2_5)); publish.send_p0(Reading::NumberPm4_0(number_pm4_0)); publish.send_p0(Reading::NumberPm10(number_pm10)); - publish.send_p0(Reading::TypicalParticleSize(typical_particle_size)); + publish + .send_p0(Reading::TypicalParticleSize(typical_particle_size)); } Err(err) => publish.queue_error(err), } } -fn publish_mhz_result(mhz_res: Result, publish: &Queues) { +fn publish_mhz_result( + mhz_res: Result, + publish: &Queues, +) { match mhz_res { - Ok(mhzx::Measurement { co2, .. }) => { + Ok(measurements::Mhz { co2, .. }) => { publish.send_p0(Reading::Co2(co2)); } Err(err) => { @@ -162,9 +170,12 @@ fn publish_mhz_result(mhz_res: Result, publish: &Queue } } -fn publish_sht_result(sht_res: Result, publish: &Queues) { +fn publish_sht_result( + sht_res: Result, + publish: &Queues, +) { match sht_res { - Ok(sht31::Reading { + Ok(measurements::Sht31 { temperature, humidity, }) => { @@ -175,9 +186,12 @@ fn publish_sht_result(sht_res: Result, publish: } } -fn publish_bme_result(bme_res: Result, publish: &Queues) { +fn publish_bme_result( + bme_res: Result, + publish: &Queues, +) { match bme_res { - Ok(MeasurementData { + Ok(measurements::Bme { pressure, gas_resistance, .. diff --git a/sensor-nodes/sensors/src/lib.rs b/sensor-nodes/sensors/src/lib.rs index c67d0cb4..e2c01155 100644 --- a/sensor-nodes/sensors/src/lib.rs +++ b/sensor-nodes/sensors/src/lib.rs @@ -1,12 +1,14 @@ #![no_std] mod drivers; +pub mod measurements; pub mod errors; pub use drivers::{ Bme680Driver, Max44Driver, Nau7802Driver, Sps30Driver, Sht31Driver, MhzDriver, SPS30_DRIVER_BUF_SIZE, SPS30_UART_BUF_SIZE, }; + pub use errors::Error; use errors::SensorError; diff --git a/sensor-nodes/sensors/src/measurements.rs b/sensor-nodes/sensors/src/measurements.rs new file mode 100644 index 00000000..e865c5da --- /dev/null +++ b/sensor-nodes/sensors/src/measurements.rs @@ -0,0 +1,8 @@ +// cannot get to this type through trait yet: +// https://github.com/rust-lang/rust/issues/86935 +// so this is an alternative + +pub use bosch_bme680::MeasurementData as Bme; +pub use sps30_async::Measurement as Sps30; +pub use mhzx::Measurement as Mhz; +pub use sht31::Reading as Sht31; From 0c579c90eaf3de6804b3bfee2f3132ba93ba9c98 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 9 Dec 2024 11:33:03 +0100 Subject: [PATCH 484/687] Rename datetime fn and remove unused time crate --- Cargo.lock | 52 ---------------------------------- Cargo.toml | 1 - crates/brain/Cargo.toml | 1 - crates/brain/src/input/jobs.rs | 6 ++-- crates/brain/src/time.rs | 2 +- 5 files changed, 4 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8da9ff8c..a0a189c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -489,7 +489,6 @@ dependencies = [ "sled", "strum", "thiserror", - "time", "tokio", "tracing", "tz-rs", @@ -1020,15 +1019,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - [[package]] name = "derivative" version = "2.2.0" @@ -2737,12 +2727,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - [[package]] name = "num-integer" version = "0.1.46" @@ -2991,12 +2975,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - [[package]] name = "ppv-lite86" version = "0.2.20" @@ -3872,36 +3850,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" -dependencies = [ - "num-conv", - "time-core", -] - [[package]] name = "tinystr" version = "0.7.6" diff --git a/Cargo.toml b/Cargo.toml index 259630e7..010defbc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,6 @@ tracing = "0.1.40" tracing-error = "0.2.0" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } futures-concurrency = "7.6.2" -time = "0.3.36" jiff = "0.1" clap = { version = "4", features = ["derive"]} thiserror = "1" diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 2b60b2cc..2ac1dcb3 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -25,7 +25,6 @@ bincode = "1.3" thiserror = "1.0" jiff = { workspace = true, features = ["serde"] } -time = { workspace = true, features = ["macros"] } tz-rs = "0.6.14" bytes = "1.5" diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index 6df0895f..0c4b23c4 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; use tokio::sync::{broadcast, Mutex}; use tracing::{error, info}; -use crate::{controller::Event, time::to_datetime}; +use crate::{controller::Event, time::to_next_datetime}; #[derive(thiserror::Error, Debug)] pub(crate) enum Error { @@ -40,7 +40,7 @@ impl Job { expiration: Option, ) -> Job { Job { - time: to_datetime(hour, min), + time: to_next_datetime(hour, min), every_day: false, event, expiration, @@ -54,7 +54,7 @@ impl Job { expiration: Option, ) -> Job { Job { - time: to_datetime(hour, min), + time: to_next_datetime(hour, min), every_day: true, event, expiration, diff --git a/crates/brain/src/time.rs b/crates/brain/src/time.rs index fffe7bee..6c0605f8 100644 --- a/crates/brain/src/time.rs +++ b/crates/brain/src/time.rs @@ -6,7 +6,7 @@ pub(crate) fn now() -> Zoned { Timestamp::now().to_zoned(local) } -pub(crate) fn to_datetime(hour: i8, min: i8) -> Zoned { +pub(crate) fn to_next_datetime(hour: i8, min: i8) -> Zoned { let now = crate::time::now(); let job_time = now.with().hour(hour).minute(min).second(0).build().unwrap(); From 2651f409e53b0407474e2820b53c618adc7f4e4d Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 9 Dec 2024 11:33:29 +0100 Subject: [PATCH 485/687] Add nightlight --- .../src/controller/rooms/small_bedroom.rs | 31 +++++++++++-------- .../controller/rooms/small_bedroom/state.rs | 7 +++++ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 37f9fa95..b7690bc9 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -20,6 +20,18 @@ const UPDATE_INTERVAL: Duration = Duration::from_secs(5); const OFF_DELAY: Duration = Duration::from_secs(60); const WAKEUP_EXPIRATION: Duration = Duration::from_secs(60 * 60); +const fn time(hour: i8, minute: i8) -> f64 { + hour as f64 + minute as f64 / 60. +} +const T0_00: f64 = time(0, 0); +const T8_00: f64 = time(8, 0); +const T9_00: f64 = time(9, 0); +const T17_00: f64 = time(17, 0); +const T20_30: f64 = time(20, 30); +const T21_30: f64 = time(21, 30); +const T22_00: f64 = time(22, 0); +const T23_00: f64 = time(22, 0); + pub async fn run( mut event_rx: broadcast::Receiver, event_tx: broadcast::Sender, @@ -64,7 +76,12 @@ async fn handle_buttonpress(room: &mut Room, button: ButtonPanel) { room.to_sleep().await; } ButtonPanel::BottomMiddle(_) => { - room.to_daylight().await; + use crate::time; + let now = time::now(); + match time(now.hour(), now.minute()) { + T23_00.. | T0_00..T9_00 => room.to_nightlight().await, + _ => room.to_daylight().await, + } } ButtonPanel::BOttomRight(_) => { room.to_override().await; @@ -73,22 +90,10 @@ async fn handle_buttonpress(room: &mut Room, button: ButtonPanel) { } } -const fn time(hour: i8, minute: i8) -> f64 { - hour as f64 + minute as f64 / 60. -} - // TODO: move to jobs system and remove update trigger pub(super) fn daylight_now() -> (usize, f64) { let now = crate::time::now(); - const T0_00: f64 = time(0, 0); - const T8_00: f64 = time(8, 0); - const T9_00: f64 = time(9, 0); - const T17_00: f64 = time(17, 0); - const T20_30: f64 = time(20, 30); - const T21_30: f64 = time(21, 30); - const T22_00: f64 = time(22, 0); - match time(now.hour(), now.minute()) { T8_00..T9_00 => (2000, 0.5), T9_00..T17_00 => (3500, 1.0), diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index 350b2e87..e5ec1910 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -17,6 +17,7 @@ pub(crate) enum State { Daylight, Override, DelayedOff, + Nightlight, } #[derive(Clone)] @@ -64,6 +65,12 @@ impl Room { self.system.all_lamps_on().await; } + pub(super) async fn to_nightlight(&mut self) { + self.to_state_cancel_prev(State::Nightlight).await; + self.system.one_lamp_ct("small_bedroom:ceiling", 1800, 0.1).await; + self.system.one_lamp_on("small_bedroom:ceiling").await; + } + pub(super) async fn to_override(&mut self) { self.to_state_cancel_prev(State::Override).await; self.system.all_lamps_ct(2000, 1.0).await; From 2153269c4b6357f5c68efe7270abe26b0fc4b00e Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 9 Dec 2024 11:41:26 +0100 Subject: [PATCH 486/687] Add logging to job event and repeat --- crates/brain/src/input/jobs.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index 0c4b23c4..e5c7e8ef 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -1,12 +1,15 @@ use std::{ - fmt, sync::{mpsc, Arc}, thread, time::Duration + fmt, + sync::{mpsc, Arc}, + thread, + time::Duration, }; use jiff::{Span, ToSpan, Zoned}; use mpsc::RecvTimeoutError::*; use serde::{Deserialize, Serialize}; use tokio::sync::{broadcast, Mutex}; -use tracing::{error, info}; +use tracing::{error, info, warn}; use crate::{controller::Event, time::to_next_datetime}; @@ -142,7 +145,7 @@ impl JobList { // change the id for this one until there is a spot free while let Some(old_job) = self.jobs().get(&new_id)? { if old_job == new_job { - return Ok(new_id) + return Ok(new_id); } // create unique key new_id -= 1; @@ -190,19 +193,23 @@ async fn event_timer( Ok(_) => continue, // new job entered, restart loop Err(Disconnected) => return, Err(Timeout) => { + warn!("Sending out event for job {current_job:#?}"); // time to send the job event event_tx .send(current_job.event.clone()) .expect("controller should listen on this"); + + job_list.lock().await.remove_job(id).unwrap(); if current_job.every_day { - job_list + let new_job = current_job.add_one_day(); + let new_id = job_list .lock() .await - .add_job(current_job.add_one_day()) + .add_job(new_job.clone()) .await .unwrap(); + warn!("Added repeat job {new_job:#?} with id {new_id}"); } - job_list.lock().await.remove_job(id).unwrap(); continue; //get next job } } From 09830863473ddbf62cc1258faf2ba6d8923ddf5b Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 10 Dec 2024 12:21:05 +0100 Subject: [PATCH 487/687] Update test script --- crates/brain/test.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/brain/test.sh b/crates/brain/test.sh index 4d9f82b9..58ae43cb 100755 --- a/crates/brain/test.sh +++ b/crates/brain/test.sh @@ -1,7 +1,6 @@ #!/usr/bin/env bash -RUST_LOG=reqwest::connect=info,hyper_util=info,sled=info,rumqttc::v5::state=info,zigbee_bridge::lights::cached_bridge::poll=trace,debug RUST_BACKTRACE=1 cargo r -- \ +RUST_LOG=brain=trace,zigbee_bridge=info,info RUST_BACKTRACE=1 cargo r -- \ --data-server 192.168.1.43:1235 \ --mpd-ip 192.168.1.43 \ --port 34326 \ - --hue-bridge-ip 192.168.1.11 From 527ab715f37ebcfd962ae8b01e77bdcf7c3579a0 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 10 Dec 2024 12:21:23 +0100 Subject: [PATCH 488/687] Add thorough debugging code --- .../src/controller/rooms/small_bedroom.rs | 22 +-- .../controller/rooms/small_bedroom/filter.rs | 1 + crates/brain/src/input/jobs.rs | 134 ++++++++++-------- 3 files changed, 89 insertions(+), 68 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index b7690bc9..7778660b 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -2,6 +2,7 @@ use std::time::Duration; use futures_concurrency::future::Race; use futures_util::FutureExt; +use jiff::ToSpan; use protocol::small_bedroom::ButtonPanel; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; @@ -40,17 +41,16 @@ pub async fn run( let mut room = Room::new(event_tx, system.clone()); let mut next_update = Instant::now() + UPDATE_INTERVAL; - let _ = system - .system - .jobs - .add(Job::every_day_at( - 9, - 0, - Event::WakeupSB, - Some(WAKEUP_EXPIRATION), - )) - .await; - warn!("Added job for SB wakeup"); + let soon = crate::time::now().checked_add(5.minutes()).unwrap(); + let wakeup_job = Job::at_next( + soon.hour(), + soon.minute(), + Event::WakeupSB, + Some(WAKEUP_EXPIRATION), + ); + let res = system.system.jobs.add(wakeup_job.clone()).await; + warn!("Tried to add job for SB wakeup: {wakeup_job:#?}"); + warn!("Jobs returned: {res:#?}"); loop { let get_event = recv_filtered(&mut event_rx); diff --git a/crates/brain/src/controller/rooms/small_bedroom/filter.rs b/crates/brain/src/controller/rooms/small_bedroom/filter.rs index e4515110..6db943da 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/filter.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/filter.rs @@ -27,6 +27,7 @@ pub(super) async fn recv_filtered(event_rx: &mut Receiver) -> Trigger { Err(err) => panic!("{err}"), }; if let Some(relevant) = event_filter(event) { + warn!("SB received relevant event: {relevant:?}"); return Trigger::Event(relevant); } } diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index e5c7e8ef..96c57f75 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -87,6 +87,16 @@ struct JobList { jobs: HashMap, } +struct DropNotifier { + job_change_rx: mpsc::Receiver<()>, +} + +impl Drop for DropNotifier { + fn drop(&mut self) { + eprintln!("Dropping queue rx!"); + } +} + impl Jobs { pub(crate) fn setup( event_tx: broadcast::Sender, @@ -96,8 +106,9 @@ impl Jobs { let (job_change_tx, job_change_rx) = mpsc::channel(); let job_list_clone = job_list.clone(); + let drop_notifier = DropNotifier { job_change_rx }; thread::spawn(move || { - event_timer(job_list_clone, event_tx, job_change_rx) + event_timer(job_list_clone, event_tx, drop_notifier) }); Ok(Self { @@ -168,61 +179,70 @@ impl JobList { async fn event_timer( job_list: Arc>, event_tx: broadcast::Sender, - job_change_rx: mpsc::Receiver<()>, + drop_notifier: DropNotifier, + // job_change_rx: mpsc::Receiver<()>, ) { - loop { - // This can fail - // TODO make sure an non waking error alarm is send to the user - if let Some((id, current_job)) = job_list.lock().await.peek_next() { - let now = crate::time::now(); - let timeout = ¤t_job.time - &now; - if let Some(expiration) = current_job.expiration { - if now > ¤t_job.time + Span::try_from(expiration).unwrap() - { - error!("skipping job too far in the past"); - job_list.lock().await.remove_job(id).unwrap(); - continue; // job too far in the past, skip and get next - } - } - let timeout = - Duration::try_from(timeout).unwrap_or(Duration::from_secs(0)); - info!("next job is in: {} seconds", timeout.as_secs()); - - // do we send out the event or should we add or remove a job? - match job_change_rx.recv_timeout(timeout) { - Ok(_) => continue, // new job entered, restart loop - Err(Disconnected) => return, - Err(Timeout) => { - warn!("Sending out event for job {current_job:#?}"); - // time to send the job event - event_tx - .send(current_job.event.clone()) - .expect("controller should listen on this"); - - job_list.lock().await.remove_job(id).unwrap(); - if current_job.every_day { - let new_job = current_job.add_one_day(); - let new_id = job_list - .lock() - .await - .add_job(new_job.clone()) - .await - .unwrap(); - warn!("Added repeat job {new_job:#?} with id {new_id}"); - } - continue; //get next job - } - } - } else { - //no job to wait on, wait for instructions - info!("no job in the future"); - //A message through the mpsc signals a job has been added - match job_change_rx.recv() { - // jobs were added or removed, go back and start waiting on them - Ok(_) => break, - // can't have timed out thus program should exit - Err(_) => return, - } - } - } + loop {} + // loop { + // // This can fail + // // TODO make sure an non waking error alarm is send to the user + // if let Some((id, current_job)) = job_list.lock().await.peek_next() { + // let now = crate::time::now(); + // let timeout = ¤t_job.time - &now; + // if let Some(expiration) = current_job.expiration { + // if now > ¤t_job.time + Span::try_from(expiration).unwrap() + // { + // error!("skipping job too far in the past"); + // job_list.lock().await.remove_job(id).unwrap(); + // continue; // job too far in the past, skip and get next + // } + // } + // let timeout = + // Duration::try_from(timeout).unwrap_or(Duration::from_secs(0)); + // info!("next job is in: {} seconds", timeout.as_secs()); + // + // // do we send out the event or should we add or remove a job? + // match job_change_rx.recv_timeout(timeout) { + // Ok(_) => continue, // new job entered, restart loop + // Err(Disconnected) => { + // error!("1 job_change_rx disconnected"); + // return; + // } + // Err(Timeout) => { + // warn!("Sending out event for job {current_job:#?}"); + // // time to send the job event + // event_tx + // .send(current_job.event.clone()) + // .expect("controller should listen on this"); + // + // job_list.lock().await.remove_job(id).unwrap(); + // if current_job.every_day { + // let new_job = current_job.add_one_day(); + // let new_id = job_list + // .lock() + // .await + // .add_job(new_job.clone()) + // .await + // .unwrap(); + // warn!("Added repeat job {new_job:#?} with id {new_id}"); + // } + // continue; //get next job + // } + // } + // } else { + // //no job to wait on, wait for instructions + // info!("no job in the future"); + // //A message through the mpsc signals a job has been added + // match job_change_rx.recv() { + // // jobs were added or removed, go back and start waiting on them + // Ok(_) => break, + // // can't have timed out thus program should exit + // Err(_) => { + // error!("2 job_change_rx disconnected"); + // return; + // } + // } + // } + // } + unreachable!() } From 0f17f8bfa5c495ac76b47c3786ebc7b8d9e2988f Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 10 Dec 2024 13:05:27 +0100 Subject: [PATCH 489/687] Fix event timer not running and job list deadlock Don't mix threads and async kids --- .../src/controller/rooms/small_bedroom.rs | 10 +- crates/brain/src/input/jobs.rs | 172 ++++++++---------- .../src/lights/cached_bridge/mqtt.rs | 4 +- .../src/lights/cached_bridge/poll.rs | 8 +- 4 files changed, 90 insertions(+), 104 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 7778660b..169c9e36 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -41,12 +41,12 @@ pub async fn run( let mut room = Room::new(event_tx, system.clone()); let mut next_update = Instant::now() + UPDATE_INTERVAL; - let soon = crate::time::now().checked_add(5.minutes()).unwrap(); - let wakeup_job = Job::at_next( - soon.hour(), - soon.minute(), + // let soon = crate::time::now().checked_add(1.minutes()).unwrap(); + let wakeup_job = Job::every_day_at( + 9, + 0, Event::WakeupSB, - Some(WAKEUP_EXPIRATION), + Some(Duration::from_secs(0)), ); let res = system.system.jobs.add(wakeup_job.clone()).await; warn!("Tried to add job for SB wakeup: {wakeup_job:#?}"); diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index 96c57f75..00086018 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -1,14 +1,9 @@ -use std::{ - fmt, - sync::{mpsc, Arc}, - thread, - time::Duration, -}; +use std::{fmt, sync::Arc, time::Duration}; use jiff::{Span, ToSpan, Zoned}; -use mpsc::RecvTimeoutError::*; use serde::{Deserialize, Serialize}; -use tokio::sync::{broadcast, Mutex}; +use tokio::sync::{broadcast, mpsc, Mutex}; +use tokio::{task, time}; use tracing::{error, info, warn}; use crate::{controller::Event, time::to_next_datetime}; @@ -18,7 +13,7 @@ pub(crate) enum Error { #[error("Could not store/edit job on disk")] DbError(#[from] sled::Error), #[error("Could not inform event timer about new job")] - CommError(#[from] mpsc::SendError<()>), + CommError(#[from] mpsc::error::SendError<()>), #[error("Dbstruct error")] DbStructError(#[from] dbstruct::Error), // #[error("Dbstruct error")] @@ -87,16 +82,6 @@ struct JobList { jobs: HashMap, } -struct DropNotifier { - job_change_rx: mpsc::Receiver<()>, -} - -impl Drop for DropNotifier { - fn drop(&mut self) { - eprintln!("Dropping queue rx!"); - } -} - impl Jobs { pub(crate) fn setup( event_tx: broadcast::Sender, @@ -104,12 +89,9 @@ impl Jobs { ) -> Result { let job_list = Arc::new(Mutex::new(JobList::new(db_path)?)); - let (job_change_tx, job_change_rx) = mpsc::channel(); + let (job_change_tx, job_change_rx) = mpsc::channel(250); let job_list_clone = job_list.clone(); - let drop_notifier = DropNotifier { job_change_rx }; - thread::spawn(move || { - event_timer(job_list_clone, event_tx, drop_notifier) - }); + task::spawn(event_timer(job_list_clone, event_tx, job_change_rx)); Ok(Self { list: job_list, @@ -121,18 +103,21 @@ impl Jobs { // as only one job can fire at the time, after a job gets a timeslot // it is never changed pub(crate) async fn add(&self, to_add: Job) -> Result { - let id = self.list.lock().await.add_job(to_add).await?; + let id = { + let list = self.list.lock().await; + list.add_job(to_add).await? + }; //signal event timer to update its next job - self.job_change_tx.send(())?; + self.job_change_tx.send(()).await?; Ok(id) } pub(crate) async fn remove( &self, to_remove: i64, ) -> Result, Error> { - let removed_job = self.list.lock().await.remove_job(to_remove)?; + let removed_job = { self.list.lock().await.remove_job(to_remove)? }; //signal event timer to update its next job - self.job_change_tx.send(())?; + self.job_change_tx.send(()).await?; Ok(removed_job) } pub(crate) async fn get(&self, id: i64) -> Result, Error> { @@ -179,70 +164,71 @@ impl JobList { async fn event_timer( job_list: Arc>, event_tx: broadcast::Sender, - drop_notifier: DropNotifier, - // job_change_rx: mpsc::Receiver<()>, + mut job_change_rx: mpsc::Receiver<()>, ) { - loop {} - // loop { - // // This can fail - // // TODO make sure an non waking error alarm is send to the user - // if let Some((id, current_job)) = job_list.lock().await.peek_next() { - // let now = crate::time::now(); - // let timeout = ¤t_job.time - &now; - // if let Some(expiration) = current_job.expiration { - // if now > ¤t_job.time + Span::try_from(expiration).unwrap() - // { - // error!("skipping job too far in the past"); - // job_list.lock().await.remove_job(id).unwrap(); - // continue; // job too far in the past, skip and get next - // } - // } - // let timeout = - // Duration::try_from(timeout).unwrap_or(Duration::from_secs(0)); - // info!("next job is in: {} seconds", timeout.as_secs()); - // - // // do we send out the event or should we add or remove a job? - // match job_change_rx.recv_timeout(timeout) { - // Ok(_) => continue, // new job entered, restart loop - // Err(Disconnected) => { - // error!("1 job_change_rx disconnected"); - // return; - // } - // Err(Timeout) => { - // warn!("Sending out event for job {current_job:#?}"); - // // time to send the job event - // event_tx - // .send(current_job.event.clone()) - // .expect("controller should listen on this"); - // - // job_list.lock().await.remove_job(id).unwrap(); - // if current_job.every_day { - // let new_job = current_job.add_one_day(); - // let new_id = job_list - // .lock() - // .await - // .add_job(new_job.clone()) - // .await - // .unwrap(); - // warn!("Added repeat job {new_job:#?} with id {new_id}"); - // } - // continue; //get next job - // } - // } - // } else { - // //no job to wait on, wait for instructions - // info!("no job in the future"); - // //A message through the mpsc signals a job has been added - // match job_change_rx.recv() { - // // jobs were added or removed, go back and start waiting on them - // Ok(_) => break, - // // can't have timed out thus program should exit - // Err(_) => { - // error!("2 job_change_rx disconnected"); - // return; - // } - // } - // } - // } - unreachable!() + loop { + // This can fail + // TODO make sure an non waking error alarm is send to the user + let peeked = { + let mut job_list = job_list.lock().await; + job_list.peek_next() + }; + if let Some((id, current_job)) = peeked { + let now = crate::time::now(); + let timeout = ¤t_job.time - &now; + if let Some(expiration) = current_job.expiration { + if now > ¤t_job.time + Span::try_from(expiration).unwrap() + { + error!("skipping job too far in the past"); + job_list.lock().await.remove_job(id).unwrap(); + continue; // job too far in the past, skip and get next + } + } + let timeout = + Duration::try_from(timeout).unwrap_or(Duration::from_secs(0)); + info!("next job is in: {} seconds", timeout.as_secs()); + + // do we send out the event or should we add or remove a job? + match time::timeout(timeout, job_change_rx.recv()).await { + Ok(Some(_)) => continue, // new job entered, restart loop + Ok(None) => { + error!("1 job_change_rx disconnected"); + return; + } + Err(_) => { + warn!("Sending out event for job {current_job:#?}"); + // time to send the job event + event_tx + .send(current_job.event.clone()) + .expect("controller should listen on this"); + + job_list.lock().await.remove_job(id).unwrap(); + if current_job.every_day { + let new_job = current_job.add_one_day(); + let new_id = job_list + .lock() + .await + .add_job(new_job.clone()) + .await + .unwrap(); + warn!("Added repeat job {new_job:#?} with id {new_id}"); + } + continue; //get next job + } + } + } else { + //no job to wait on, wait for instructions + info!("no job in the future"); + //A message through the mpsc signals a job has been added + match job_change_rx.recv().await { + // jobs were added or removed, go back and start waiting on them + Some(_) => (), + // can't have timed out thus program should exit + None => { + error!("2 job_change_rx disconnected"); + return; + } + } + } + } } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index a622f36d..a2314756 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -155,8 +155,8 @@ impl Mqtt { ..Default::default() }; - if topic.contains("small_bedroom:bureau") { - warn!("ZB to MQTT (bureau): {payload}"); + if topic.contains("small_bedroom:piano") { + warn!("ZB to MQTT (piano): {payload}"); } self.client .publish_with_properties( diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index 3686d6cf..c7fb3ec8 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -53,18 +53,18 @@ async fn update_state( .entry(light_name.to_owned()) .or_insert_with(|| Lamp::new(light_name)); for property in new { - if light_name == "small_bedroom:bureau" { + if light_name == "small_bedroom:piano" { match property { lamp::Property::Brightness(bri) => { - warn!("ZB received bureau brightness change: {bri}"); + warn!("ZB received piano brightness change: {bri}"); } lamp::Property::ColorXY(xy) => { - warn!("ZB received bureau color change: {xy:?}"); + warn!("ZB received piano color change: {xy:?}"); } lamp::Property::Online(new_online) => { if new_online != current_lamp.is_online { warn!( - "ZB received bureau online change: {new_online}" + "ZB received piano online change: {new_online}" ); } } From 3fc8547e961d37ade29c0dd31f823fa89ad6a817 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Wed, 11 Dec 2024 11:32:31 +0100 Subject: [PATCH 490/687] Fix wakeup logic --- crates/brain/src/controller/rooms/small_bedroom.rs | 5 ++--- crates/brain/src/controller/rooms/small_bedroom/state.rs | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 169c9e36..b8d25832 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -2,7 +2,6 @@ use std::time::Duration; use futures_concurrency::future::Race; use futures_util::FutureExt; -use jiff::ToSpan; use protocol::small_bedroom::ButtonPanel; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; @@ -19,7 +18,7 @@ mod state; const UPDATE_INTERVAL: Duration = Duration::from_secs(5); const OFF_DELAY: Duration = Duration::from_secs(60); -const WAKEUP_EXPIRATION: Duration = Duration::from_secs(60 * 60); +const WAKEUP_EXPIRATION: Duration = Duration::from_secs(60); const fn time(hour: i8, minute: i8) -> f64 { hour as f64 + minute as f64 / 60. @@ -46,7 +45,7 @@ pub async fn run( 9, 0, Event::WakeupSB, - Some(Duration::from_secs(0)), + Some(WAKEUP_EXPIRATION), ); let res = system.system.jobs.add(wakeup_job.clone()).await; warn!("Tried to add job for SB wakeup: {wakeup_job:#?}"); diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index e5ec1910..f6c1684a 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -104,7 +104,7 @@ impl Room { const LIGHT_NAME: &str = "small_bedroom:piano"; const RUNTIME_MINS: i32 = 7; const STEP_SIZE_SECS: i32 = 30; - const N_STEPS: i32 = RUNTIME_MINS / STEP_SIZE_SECS; + const N_STEPS: i32 = RUNTIME_MINS * 60 / STEP_SIZE_SECS; const START_BRI: f64 = 1. / 254.; const START_CT: usize = 2000; From 9e7cc08e3ffdbad5b69f8de23d0c003e20572706 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Wed, 11 Dec 2024 11:50:06 +0100 Subject: [PATCH 491/687] Add mqtt ip cli parameter for testing --- crates/brain/src/main.rs | 14 +++++++++----- crates/brain/src/system.rs | 6 ++++-- crates/brain/test.sh | 3 ++- crates/zigbee-bridge/src/lib.rs | 4 ++-- crates/zigbee-bridge/src/lights.rs | 6 ++++-- crates/zigbee-bridge/src/lights/cached_bridge.rs | 7 ++++--- 6 files changed, 25 insertions(+), 15 deletions(-) diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index 7bfcb73a..07b9da9b 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -19,17 +19,21 @@ const JOBS_DB_PATH: &str = "database/jobs"; #[command(version, about, long_about=None)] struct Opt { /// IP address where to subscribe for updates - #[clap(short, long)] + #[clap(long)] data_server: SocketAddr, /// IP address for mpd server - #[clap(short, long)] + #[clap(long)] mpd_ip: IpAddr, /// http api listens on this port at 127.0.0.1 use /// a loadbalancer/reverse proxy to get traffic to this - #[clap(short, long)] - port: u16, + #[clap(long)] + http_port: u16, + + /// IP address for MQTT broker + #[clap(long)] + mqtt_ip: IpAddr, } #[tokio::main] @@ -44,7 +48,7 @@ async fn main() -> Result<(), Box> { let jobs = Jobs::setup(event_tx.clone(), JOBS_DB_PATH)?; - let system = System::init(jobs); + let system = System::init(opt.mqtt_ip, jobs); let _tasks = controller::start(subscribed_rxs, event_tx.clone(), system); // This never returns, should be replaced by an endless loop if (re)moved diff --git a/crates/brain/src/system.rs b/crates/brain/src/system.rs index b9dcc3c1..d71d5da3 100644 --- a/crates/brain/src/system.rs +++ b/crates/brain/src/system.rs @@ -1,3 +1,5 @@ +use std::net::IpAddr; + // pub mod mpd_control; use zigbee_bridge::lights; // pub use mpd_control::Mpd; @@ -13,10 +15,10 @@ pub struct System { } impl System { - pub fn init(jobs: Jobs) -> Self { + pub fn init(mqtt_ip: IpAddr, jobs: Jobs) -> Self { Self { jobs, - lights_new: lights::Controller::start_bridge(), + lights_new: lights::Controller::start_bridge(mqtt_ip), // mpd: Mpd, } } diff --git a/crates/brain/test.sh b/crates/brain/test.sh index 58ae43cb..00bad8b1 100755 --- a/crates/brain/test.sh +++ b/crates/brain/test.sh @@ -3,4 +3,5 @@ RUST_LOG=brain=trace,zigbee_bridge=info,info RUST_BACKTRACE=1 cargo r -- \ --data-server 192.168.1.43:1235 \ --mpd-ip 192.168.1.43 \ - --port 34326 \ + --http-port 34326 \ + --mqtt-ip 192.168.1.43 diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 0915af83..33b8ac71 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -8,7 +8,6 @@ use lights::Model; pub mod lights; -const MQTT_IP: &str = "192.168.1.43"; const MQTT_PORT: u16 = 1883; const LIGHT_MODELS: [(&str, Model); 16] = [ ("kitchen:fridge", Model::TradfriE14Color), @@ -38,7 +37,8 @@ mod tests { #[tokio::test] async fn change_fridge_light() { std::env::set_var("RUST_LOG", "brain=trace,zigbee_bridge=trace,info"); - let controller = Controller::start_bridge(); + let controller = + Controller::start_bridge("192.168.1.43".parse().unwrap()); let light = "kitchen:fridge"; println!("Setting to on, 2200"); diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index 103e53b7..12de0039 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -1,4 +1,6 @@ #![allow(clippy::missing_panics_doc)] +use std::net::IpAddr; + use tokio::sync::mpsc; use tracing::trace; @@ -16,10 +18,10 @@ pub struct Controller { impl Controller { #[must_use] - pub fn start_bridge() -> Self { + pub fn start_bridge(mqtt_ip: IpAddr) -> Self { let (change_sender, change_receiver) = mpsc::unbounded_channel(); - let run_bridge = cached_bridge::run(change_receiver); + let run_bridge = cached_bridge::run(mqtt_ip, change_receiver); trace!("Spawning zigbee bridge task"); tokio::task::spawn(run_bridge); diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 02f2ee7a..984e49ae 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -1,11 +1,11 @@ -use std::{collections::HashMap, time::Duration}; +use std::{collections::HashMap, net::IpAddr, time::Duration}; use rumqttc::v5::{AsyncClient, MqttOptions}; use tokio::sync::{mpsc, RwLock}; use tracing::trace; use self::mqtt::Mqtt; -use crate::{lights::lamp, LIGHT_MODELS, MQTT_IP, MQTT_PORT}; +use crate::{lights::lamp, LIGHT_MODELS, MQTT_PORT}; mod changes; mod mqtt; @@ -19,10 +19,11 @@ const TIME_IT_TAKES_TO_APPLY_CHANGE: Duration = Duration::from_secs(10); const CHANGE_ACCUMULATION_TIME: Duration = Duration::from_millis(100); pub(super) async fn run( + mqtt_ip: IpAddr, change_receiver: mpsc::UnboundedReceiver<(String, lamp::Property)>, ) -> ! { let mut options = - MqttOptions::new("ha-lightcontroller", MQTT_IP, MQTT_PORT); + MqttOptions::new("ha-lightcontroller", mqtt_ip.to_string(), MQTT_PORT); // Set max mqtt packet size to 4kB options.set_max_packet_size(Some(4096)); // Keep subscriptions when reconnecting!!!! From 71531203d199173f7d67fbb6c917c3886e89e238 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 11 Dec 2024 12:13:19 +0100 Subject: [PATCH 492/687] ported bed-lb node to new sensors crate --- crates/protocol/src/affector.rs | 2 +- sensor-nodes/Cargo.lock | 235 +++++------------- sensor-nodes/Cargo.toml | 32 +-- sensor-nodes/bed-lb/.gitignore | 1 - sensor-nodes/bed-lb/Cargo.lock | 217 ++++++++++------ sensor-nodes/bed-lb/Cargo.toml | 55 ++-- sensor-nodes/bed-lb/src/channel.rs | 21 +- sensor-nodes/bed-lb/src/error_cache.rs | 59 ----- sensor-nodes/bed-lb/src/main.rs | 58 +++-- sensor-nodes/bed-lb/src/network.rs | 50 +++- sensor-nodes/bed-lb/src/sensors.rs | 123 ++------- sensor-nodes/bed-lb/src/sensors/fast.rs | 69 +++-- sensor-nodes/bed-lb/src/sensors/retry.rs | 147 ----------- .../src/sensors/retry/reinit_on_error.rs | 119 --------- .../bed-lb/src/sensors/retry/retry_init.rs | 83 ------- sensor-nodes/bed-lb/src/sensors/slow.rs | 52 ++-- sensor-nodes/sensors/Cargo.toml | 3 + sensor-nodes/sensors/src/drivers.rs | 11 +- .../src/drivers/driver_impl_nau7802.rs | 27 +- .../sensors/src/drivers/i2c_wrapper.rs | 69 +++++ sensor-nodes/sensors/src/errors.rs | 93 ++++++- sensor-nodes/sensors/src/lib.rs | 7 +- 22 files changed, 621 insertions(+), 912 deletions(-) delete mode 100644 sensor-nodes/bed-lb/.gitignore delete mode 100644 sensor-nodes/bed-lb/src/error_cache.rs delete mode 100644 sensor-nodes/bed-lb/src/sensors/retry.rs delete mode 100644 sensor-nodes/bed-lb/src/sensors/retry/reinit_on_error.rs delete mode 100644 sensor-nodes/bed-lb/src/sensors/retry/retry_init.rs create mode 100644 sensor-nodes/sensors/src/drivers/i2c_wrapper.rs diff --git a/crates/protocol/src/affector.rs b/crates/protocol/src/affector.rs index c8f64b03..f09c2844 100644 --- a/crates/protocol/src/affector.rs +++ b/crates/protocol/src/affector.rs @@ -94,7 +94,7 @@ impl Default for Decoder { } } -#[derive(Debug)] +#[derive(Debug, defmt::Format)] pub struct DeserializeError; impl Decoder { diff --git a/sensor-nodes/Cargo.lock b/sensor-nodes/Cargo.lock index 73b41bb5..1c47f081 100644 --- a/sensor-nodes/Cargo.lock +++ b/sensor-nodes/Cargo.lock @@ -20,19 +20,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "377e4c0ba83e4431b10df45c1d4666f178ea9c552cac93e60c3a88bf32785923" dependencies = [ - "as-slice 0.2.1", -] - -[[package]] -name = "as-slice" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" -dependencies = [ - "generic-array 0.12.4", - "generic-array 0.13.3", - "generic-array 0.14.7", - "stable_deref_trait", + "as-slice", ] [[package]] @@ -53,18 +41,6 @@ dependencies = [ "critical-section", ] -[[package]] -name = "atomic-pool" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58c5fc22e05ec2884db458bf307dc7b278c9428888d2b6e6fad9c0ae7804f5f6" -dependencies = [ - "as-slice 0.1.5", - "as-slice 0.2.1", - "atomic-polyfill", - "stable_deref_trait", -] - [[package]] name = "autocfg" version = "1.4.0" @@ -177,7 +153,7 @@ checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -222,7 +198,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -233,14 +209,14 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] name = "defmt" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9112096fbf91d9458d3dc1bca22e87e2684cad608c032f80135e2471614ceebe" +checksum = "86f6162c53f659f65d00619fe31f14556a6e9f8752ccc4a41bd177ffcf3d6130" dependencies = [ "bitflags 1.3.2", "defmt-macros", @@ -248,15 +224,15 @@ dependencies = [ [[package]] name = "defmt-macros" -version = "0.3.10" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e40098d5ffbf1b3c88dff66c3b168a7dc4f3e8ff8604a00441660040a134e20" +checksum = "9d135dd939bad62d7490b0002602d35b358dce5fd9233a709d3c1ef467d4bde6" dependencies = [ "defmt-parser", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -290,11 +266,11 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" +source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" dependencies = [ "defmt", "embassy-futures", - "embassy-sync 0.6.1", + "embassy-sync", "embassy-time", "embedded-hal 0.2.7", "embedded-hal 1.0.0", @@ -307,7 +283,7 @@ dependencies = [ [[package]] name = "embassy-executor" version = "0.6.3" -source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" +source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" dependencies = [ "cortex-m", "critical-section", @@ -321,23 +297,23 @@ dependencies = [ [[package]] name = "embassy-executor-macros" version = "0.6.2" -source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" +source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] name = "embassy-futures" version = "0.1.1" -source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" +source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" [[package]] name = "embassy-hal-internal" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" +source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" dependencies = [ "cortex-m", "critical-section", @@ -347,40 +323,25 @@ dependencies = [ [[package]] name = "embassy-net" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cf91dd36dfd623de32242af711fd294d41159f02130052fc93c5c5ba93febe" +version = "0.5.0" +source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" dependencies = [ - "as-slice 0.2.1", - "atomic-pool", "defmt", "document-features", - "embassy-net-driver 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "embassy-sync 0.5.0", + "embassy-net-driver", + "embassy-sync", "embassy-time", "embedded-io-async", "embedded-nal-async", - "futures", - "generic-array 0.14.7", "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "managed", "smoltcp", - "stable_deref_trait", ] [[package]] name = "embassy-net-driver" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d" -dependencies = [ - "defmt", -] - -[[package]] -name = "embassy-net-driver" -version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" +source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" dependencies = [ "defmt", ] @@ -388,17 +349,17 @@ dependencies = [ [[package]] name = "embassy-net-driver-channel" version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" +source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" dependencies = [ "embassy-futures", - "embassy-net-driver 0.2.0 (git+https://github.com/embassy-rs/embassy?rev=0349a8d)", - "embassy-sync 0.6.1", + "embassy-net-driver", + "embassy-sync", ] [[package]] name = "embassy-net-wiznet" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" +source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" dependencies = [ "defmt", "embassy-futures", @@ -411,7 +372,7 @@ dependencies = [ [[package]] name = "embassy-stm32" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" +source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" dependencies = [ "aligned", "bit_field", @@ -426,8 +387,8 @@ dependencies = [ "embassy-embedded-hal", "embassy-futures", "embassy-hal-internal", - "embassy-net-driver 0.2.0 (git+https://github.com/embassy-rs/embassy?rev=0349a8d)", - "embassy-sync 0.6.1", + "embassy-net-driver", + "embassy-sync", "embassy-time", "embassy-time-driver", "embassy-usb-driver", @@ -454,23 +415,10 @@ dependencies = [ "volatile-register", ] -[[package]] -name = "embassy-sync" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd938f25c0798db4280fcd8026bf4c2f48789aebf8f77b6e5cf8a7693ba114ec" -dependencies = [ - "cfg-if", - "critical-section", - "embedded-io-async", - "futures-util", - "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "embassy-sync" version = "0.6.1" -source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" +source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" dependencies = [ "cfg-if", "critical-section", @@ -484,7 +432,7 @@ dependencies = [ [[package]] name = "embassy-time" version = "0.3.2" -source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" +source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" dependencies = [ "cfg-if", "critical-section", @@ -502,7 +450,7 @@ dependencies = [ [[package]] name = "embassy-time-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" +source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" dependencies = [ "document-features", ] @@ -510,17 +458,17 @@ dependencies = [ [[package]] name = "embassy-time-queue-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" +source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" [[package]] name = "embassy-usb" version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" +source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" dependencies = [ "defmt", "embassy-futures", "embassy-net-driver-channel", - "embassy-sync 0.6.1", + "embassy-sync", "embassy-usb-driver", "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "ssmarshal", @@ -530,19 +478,19 @@ dependencies = [ [[package]] name = "embassy-usb-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" +source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" dependencies = [ "defmt", ] [[package]] name = "embassy-usb-synopsys-otg" -version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" dependencies = [ "critical-section", "defmt", - "embassy-sync 0.6.1", + "embassy-sync", "embassy-usb-driver", ] @@ -628,23 +576,21 @@ dependencies = [ [[package]] name = "embedded-nal" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a943fad5ed3d3f8a00f1e80f6bba371f1e7f0df28ec38477535eb318dc19cc" +checksum = "c56a28be191a992f28f178ec338a0bf02f63d7803244add736d026a471e6ed77" dependencies = [ "nb 1.1.0", - "no-std-net", ] [[package]] name = "embedded-nal-async" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72229137a4fc12d239b0b7f50f04b30790678da6d782a0f3f1909bf57ec4b759" +checksum = "76959917cd2b86f40a98c28dd5624eddd1fa69d746241c8257eac428d83cb211" dependencies = [ "embedded-io-async", "embedded-nal", - "no-std-net", ] [[package]] @@ -718,7 +664,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -747,34 +693,6 @@ dependencies = [ "pin-utils", ] -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "hash32" version = "0.2.1" @@ -850,10 +768,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] -name = "large-bedroom-bed-node" +name = "large-bedroom-sensor-node" version = "0.2.0" dependencies = [ - "bosch-bme680", "cortex-m", "cortex-m-rt", "defmt", @@ -864,7 +781,7 @@ dependencies = [ "embassy-net", "embassy-net-wiznet", "embassy-stm32", - "embassy-sync 0.6.1", + "embassy-sync", "embassy-time", "embedded-hal 1.0.0", "embedded-hal-async", @@ -872,15 +789,10 @@ dependencies = [ "embedded-io-async", "futures", "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "max44009", - "mhzx", - "nau7802-async", - "nb 1.1.0", "panic-probe", "protocol", "rand", - "sht31", - "sps30-async", + "sensors", "static_cell", ] @@ -958,12 +870,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" -[[package]] -name = "no-std-net" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" - [[package]] name = "num-traits" version = "0.2.19" @@ -1009,9 +915,9 @@ checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" [[package]] name = "postcard" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63d01def49fc815900a83e7a4a5083d2abc81b7ddd569a3fa0477778ae9b3ec" +checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8" dependencies = [ "cobs", "defmt", @@ -1050,7 +956,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1162,8 +1068,10 @@ dependencies = [ "defmt", "embassy-embedded-hal", "embassy-stm32", - "embassy-sync 0.6.1", + "embassy-sync", "embassy-time", + "embedded-hal 1.0.0", + "embedded-hal-async", "max44009", "mhzx", "nau7802-async", @@ -1189,7 +1097,7 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1215,7 +1123,7 @@ dependencies = [ "embassy-executor", "embassy-futures", "embassy-stm32", - "embassy-sync 0.6.1", + "embassy-sync", "embassy-time", "embassy-usb", "embedded-hal 1.0.0", @@ -1231,9 +1139,9 @@ dependencies = [ [[package]] name = "smoltcp" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a1a996951e50b5971a2c8c0fa05a381480d70a933064245c4a223ddc87ccc97" +checksum = "dad095989c1533c1c266d9b1e8d70a1329dd3723c3edac6d03bbd67e7bf6f4bb" dependencies = [ "bitflags 1.3.2", "byteorder", @@ -1308,7 +1216,7 @@ dependencies = [ [[package]] name = "stm32-metapac" version = "15.0.0" -source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-04833817666290047257c65c6547d28e1bd10dc9#f3cb9f3c385bcbfa1e6ee525b2a7cb84967c7996" +source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-ddb0e7abab14bf3e1399875767b8834442382988#15c2d08f1b0e5877c787bddb1f35a49cbe180f36" dependencies = [ "cortex-m", "cortex-m-rt", @@ -1339,7 +1247,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1355,9 +1263,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.89" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -1366,30 +1274,24 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.3" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +checksum = "8fec2a1820ebd077e2b90c4df007bebf344cd394098a13c563957d0afc83ea47" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.3" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +checksum = "d65750cab40f4ff1929fb1ba509e9914eb756131cef4210da8d5d700d26f6312" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - [[package]] name = "unicode-ident" version = "1.0.14" @@ -1487,10 +1389,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] - -[[patch.unused]] -name = "embassy-net" -version = "0.5.0" -source = "git+https://github.com/embassy-rs/embassy?rev=0349a8d#0349a8d3731527ed5deb869fb4fe172b838cef86" diff --git a/sensor-nodes/Cargo.toml b/sensor-nodes/Cargo.toml index c361474a..aaa90b94 100644 --- a/sensor-nodes/Cargo.toml +++ b/sensor-nodes/Cargo.toml @@ -10,38 +10,38 @@ cortex-m-rt = "0.7.0" embassy-stm32 = { version = "0.1.0", features = [ "defmt", "stm32f401cc", "unstable-pac", "memory-x", "time-driver-tim9", "time", "exti" ] } -embassy-net = { version = "0.4.0", features = ["defmt", "proto-ipv4", "tcp", "dhcpv4","medium-ethernet"] } +embassy-net = { version = "0.5.0", features = ["defmt", "proto-ipv4", "tcp", "dhcpv4","medium-ethernet"] } embassy-net-wiznet = { version = "0.1.0", features = ["defmt"] } -embassy-sync = { version = "0.6.0", features = ["defmt"] } -embassy-executor = { version = "0.6.0", features = ["arch-cortex-m", +embassy-sync = { version = "0.6.1", features = ["defmt"] } +embassy-executor = { version = "0.6.3", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers", "executor-interrupt"] } embassy-embedded-hal = { version = "0.2.0" } embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime-ms", "tick-hz-32_768"] } -embassy-futures = { version = "0.1.0"} +embassy-futures = { version = "0.1.1"} embedded-hal = "1.0.0" embedded-hal-async = "1.0" embedded-hal-bus = { version = "0.2", features = ["async", "defmt-03"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } -futures = { version = "0.3.17", default-features = false, features = ["async-await"] } +futures = { version = "0.3.31", default-features = false, features = ["async-await"] } defmt = "0.3" defmt-rtt = "0.4" panic-probe = { version = "0.3", features = ["print-defmt"] } [patch.crates-io] -embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } -embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } -embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } -embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } -embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } -embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } -embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } -embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } -embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } -embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } -embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "0349a8d" } +embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } +embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } +embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } +embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } +embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } +embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } +embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } +embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } +embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } +embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } +embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } [workspace.package] rust-version = "1.78" diff --git a/sensor-nodes/bed-lb/.gitignore b/sensor-nodes/bed-lb/.gitignore deleted file mode 100644 index ea8c4bf7..00000000 --- a/sensor-nodes/bed-lb/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/sensor-nodes/bed-lb/Cargo.lock b/sensor-nodes/bed-lb/Cargo.lock index ee2fcc0e..50cd7987 100644 --- a/sensor-nodes/bed-lb/Cargo.lock +++ b/sensor-nodes/bed-lb/Cargo.lock @@ -2,6 +2,18 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aligned" version = "0.4.2" @@ -56,11 +68,10 @@ dependencies = [ "embassy-embedded-hal", "embassy-executor", "embassy-futures", - "embassy-net", - "embassy-net-wiznet", "embassy-stm32", "embassy-sync", "embassy-time", + "embassy-usb", "embedded-hal 1.0.0", "embedded-hal-async", "embedded-hal-bus", @@ -344,23 +355,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "embassy-net" -version = "0.4.0" -source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" -dependencies = [ - "defmt", - "document-features", - "embassy-net-driver", - "embassy-sync", - "embassy-time", - "embedded-io-async", - "embedded-nal-async", - "heapless 0.8.0", - "managed", - "smoltcp", -] - [[package]] name = "embassy-net-driver" version = "0.2.0" @@ -379,19 +373,6 @@ dependencies = [ "embassy-sync", ] -[[package]] -name = "embassy-net-wiznet" -version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" -dependencies = [ - "defmt", - "embassy-futures", - "embassy-net-driver-channel", - "embassy-time", - "embedded-hal 1.0.0", - "embedded-hal-async", -] - [[package]] name = "embassy-stm32" version = "0.1.0" @@ -482,6 +463,21 @@ name = "embassy-time-queue-driver" version = "0.1.0" source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +[[package]] +name = "embassy-usb" +version = "0.3.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "defmt", + "embassy-futures", + "embassy-net-driver-channel", + "embassy-sync", + "embassy-usb-driver", + "heapless 0.8.0", + "ssmarshal", + "usbd-hid", +] + [[package]] name = "embassy-usb-driver" version = "0.1.0" @@ -580,27 +576,6 @@ dependencies = [ "embedded-io", ] -[[package]] -name = "embedded-nal" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a943fad5ed3d3f8a00f1e80f6bba371f1e7f0df28ec38477535eb318dc19cc" -dependencies = [ - "nb 1.1.0", - "no-std-net", -] - -[[package]] -name = "embedded-nal-async" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72229137a4fc12d239b0b7f50f04b30790678da6d782a0f3f1909bf57ec4b759" -dependencies = [ - "embedded-io-async", - "embedded-nal", - "no-std-net", -] - [[package]] name = "embedded-storage" version = "0.3.1" @@ -616,6 +591,12 @@ dependencies = [ "embedded-storage", ] +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "fnv" version = "1.0.7" @@ -713,6 +694,15 @@ dependencies = [ "byteorder", ] +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + [[package]] name = "heapless" version = "0.7.17" @@ -768,10 +758,10 @@ dependencies = [ ] [[package]] -name = "managed" -version = "0.8.0" +name = "log" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "max44009" @@ -819,12 +809,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" -[[package]] -name = "no-std-net" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" - [[package]] name = "num-traits" version = "0.2.19" @@ -834,6 +818,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + [[package]] name = "panic-probe" version = "0.3.2" @@ -858,9 +848,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "portable-atomic" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" +checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce" [[package]] name = "postcard" @@ -869,6 +859,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" dependencies = [ "cobs", + "defmt", "heapless 0.7.17", "postcard-derive", "serde", @@ -1041,19 +1032,6 @@ dependencies = [ "postcard", ] -[[package]] -name = "smoltcp" -version = "0.11.0" -source = "git+https://github.com/smoltcp-rs/smoltcp?rev=dd43c8f189178b0ab3bda798ed8578b5b0a6f094#dd43c8f189178b0ab3bda798ed8578b5b0a6f094" -dependencies = [ - "bitflags 1.3.2", - "byteorder", - "cfg-if", - "defmt", - "heapless 0.8.0", - "managed", -] - [[package]] name = "spin" version = "0.9.8" @@ -1076,6 +1054,16 @@ dependencies = [ "serde", ] +[[package]] +name = "ssmarshal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3e6ad23b128192ed337dfa4f1b8099ced0c2bf30d61e551b65fda5916dbb850" +dependencies = [ + "encode_unicode", + "serde", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1167,18 +1155,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", @@ -1191,6 +1179,53 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +[[package]] +name = "usb-device" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98816b1accafbb09085168b90f27e93d790b4bfa19d883466b5e53315b5f06a6" +dependencies = [ + "heapless 0.8.0", + "portable-atomic", +] + +[[package]] +name = "usbd-hid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6f291ab53d428685cc780f08a2eb9d5d6ff58622db2b36e239a4f715f1e184c" +dependencies = [ + "serde", + "ssmarshal", + "usb-device", + "usbd-hid-macros", +] + +[[package]] +name = "usbd-hid-descriptors" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee54712c5d778d2fb2da43b1ce5a7b5060886ef7b09891baeb4bf36910a3ed" +dependencies = [ + "bitfield 0.14.0", +] + +[[package]] +name = "usbd-hid-macros" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb573c76e7884035ac5e1ab4a81234c187a82b6100140af0ab45757650ccda38" +dependencies = [ + "byteorder", + "hashbrown", + "log", + "proc-macro2", + "quote", + "serde", + "syn 1.0.109", + "usbd-hid-descriptors", +] + [[package]] name = "vcell" version = "0.1.3" @@ -1217,3 +1252,23 @@ checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" dependencies = [ "vcell", ] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] diff --git a/sensor-nodes/bed-lb/Cargo.toml b/sensor-nodes/bed-lb/Cargo.toml index 3ee7a2d2..ccbde18d 100644 --- a/sensor-nodes/bed-lb/Cargo.toml +++ b/sensor-nodes/bed-lb/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "large-bedroom-bed-node" +name = "large-bedroom-sensor-node" version = "0.2.0" rust-version = "1.78" edition = "2021" @@ -7,41 +7,34 @@ license = "GPLv3" authors = ["David Kleingeld & Eva van Houten"] [dependencies] -embassy-stm32 = { version = "0.1.0", features = [ "defmt", "stm32f401cc", -"unstable-pac", "memory-x", "time-driver-tim9", "time", "exti" ] } -embassy-net = { version = "0.4.0", features = ["defmt", "proto-ipv4", "tcp", "dhcpv4","medium-ethernet"] } -embassy-net-wiznet = { version = "0.1.0", features = ["defmt"] } -embassy-sync = { version = "0.6.0", features = ["defmt"] } -embassy-executor = { version = "0.6.0", features = ["arch-cortex-m", -"executor-thread", "defmt", "integrated-timers", "executor-interrupt"] } -embassy-embedded-hal = { version = "0.2.0" } -embassy-time = { version = "0.3.2", features = ["defmt", -"defmt-timestamp-uptime-ms", "tick-hz-32_768"] } -embassy-futures = { version = "0.1.0"} +cortex-m.workspace = true +cortex-m-rt.workspace = true -defmt = "0.3" -defmt-rtt = "0.4" +embassy-stm32.workspace = true +embassy-sync.workspace = true +embassy-executor.workspace = true +embassy-net.workspace = true +embassy-net-wiznet.workspace = true +embassy-embedded-hal.workspace = true +embassy-time.workspace = true +embassy-futures.workspace = true -cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } -cortex-m-rt = "0.7.0" -embedded-hal = "1.0.0" -embedded-hal-async = "1.0" -embedded-hal-bus = { version = "0.2", features = ["async", "defmt-03"] } -embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } -panic-probe = { version = "0.3", features = ["print-defmt"] } -futures = { version = "0.3.17", default-features = false, features = ["async-await"] } -heapless = { version = "0.8", default-features = false } -nb = "1.0.0" -rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } +defmt.workspace = true +defmt-rtt.workspace = true + +embedded-hal.workspace = true +embedded-hal-async.workspace = true +embedded-hal-bus.workspace = true +embedded-io-async.workspace = true + +panic-probe.workspace = true +futures.workspace = true static_cell = "2.0.0" +rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } +heapless = { version = "0.8", default-features = false } # sensors -bosch-bme680 = { version = "1.0.2", path = "/home/david/Documents/async-bosch-bme680" } -max44009 = { version = "0.2", git = "https://github.com/dvdsk/max44009-rs" } -sht31 = { version = "0.3.0", git = "https://github.com/dvdsk/SHT31-rs", features = ["postcard"] } -mhzx = { version = "0.3.0", path = "/home/david/tmp/mh-zx-driver", features = ["serde", "postcard"] } -sps30-async = { version = "0.3.0", path = "/home/david/tmp/sps30", features = ["serde", "postcard"] } -nau7802-async = { path = "/home/david/tmp/nau7802-rs", features = ["serde", "postcard", "defmt"] } +sensors = { path = "../sensors" } # encoding protocol = { workspace = true } diff --git a/sensor-nodes/bed-lb/src/channel.rs b/sensor-nodes/bed-lb/src/channel.rs index f263c26c..2f7fe5ae 100644 --- a/sensor-nodes/bed-lb/src/channel.rs +++ b/sensor-nodes/bed-lb/src/channel.rs @@ -7,18 +7,16 @@ use embassy_time::{Duration, Instant}; use heapless::HistoryBuffer; use protocol::large_bedroom::bed::Reading; -use crate::error_cache; - pub struct Queues { sensor_queue: PriorityChannel, - error_queue: Channel, - recent_errors: Mutex>, + error_queue: Channel, + recent_errors: Mutex>, recent_is_since: Instant, } pub enum QueueItem { Reading(PriorityValue), - Error(error_cache::Error), + Error(sensors::Error), } impl Queues { @@ -56,7 +54,7 @@ impl Queues { self.sensor_queue.try_receive().ok() } - pub fn queue_error(&self, error: error_cache::Error) { + pub fn queue_error(&self, error: sensors::Error) { // unwrap safe: is not used in interrupts let mut recent_errors = defmt::unwrap!(self.recent_errors.try_lock()); if self.recent_is_since.elapsed() > Duration::from_secs(60 * 5) { @@ -74,30 +72,33 @@ impl Queues { } pub fn send_p0(&self, value: Reading) { + use protocol::large_bedroom::Reading::Bed; let entry = PriorityValue { priority: 0, - value: protocol::Reading::LargeBedroom(protocol::large_bedroom::Reading::Bed(value)), + value: protocol::Reading::LargeBedroom(Bed(value)), }; let _ignore_full = self.sensor_queue.try_send(entry); } pub fn send_p1(&self, value: Reading) { + use protocol::large_bedroom::Reading::Bed; let entry = PriorityValue { priority: 1, - value: protocol::Reading::LargeBedroom(protocol::large_bedroom::Reading::Bed(value)), + value: protocol::Reading::LargeBedroom(Bed(value)), }; let _ignore_full = self.sensor_queue.try_send(entry); } pub fn send_p2(&self, value: Reading) { + use protocol::large_bedroom::Reading::Bed; let entry = PriorityValue { priority: 2, - value: protocol::Reading::LargeBedroom(protocol::large_bedroom::Reading::Bed(value)), + value: protocol::Reading::LargeBedroom(Bed(value)), }; let _ignore_full = self.sensor_queue.try_send(entry); } } -/// Higher prio will be send earlier +/// Higher priority will be send earlier pub struct PriorityValue { priority: u8, pub value: protocol::Reading, diff --git a/sensor-nodes/bed-lb/src/error_cache.rs b/sensor-nodes/bed-lb/src/error_cache.rs deleted file mode 100644 index 416736ee..00000000 --- a/sensor-nodes/bed-lb/src/error_cache.rs +++ /dev/null @@ -1,59 +0,0 @@ -use protocol::large_bedroom::bed::{self, Device}; -use protocol::make_error_string; - -use crate::sensors::{I2cError, UartError}; - -#[derive(defmt::Format, PartialEq, Eq, Clone)] -pub(crate) enum SensorError { - Mhz14(mhzx::Error), - Sps30(sps30_async::Error), - Sht31(sht31::SHTError), - Bme680(bosch_bme680::BmeError), - Max44(max44009::Error), - Nau7802Left(nau7802_async::Error), - Nau7802Right(nau7802_async::Error), - Button(PressTooLong), -} - -#[derive(defmt::Format, PartialEq, Eq, Clone)] -pub(crate) struct PressTooLong { - pub(crate) button: &'static str, -} - -impl core::fmt::Debug for PressTooLong { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.write_fmt(format_args!("Button {}, pressed too long", self.button)) - } -} - -impl From for bed::SensorError { - fn from(val: SensorError) -> Self { - match val { - SensorError::Mhz14(e) => bed::SensorError::Mhz14(make_error_string(e)), - SensorError::Sps30(e) => bed::SensorError::Sps30(make_error_string(e)), - SensorError::Sht31(e) => bed::SensorError::Sht31(make_error_string(e)), - SensorError::Bme680(e) => bed::SensorError::Bme680(make_error_string(e)), - SensorError::Max44(e) => bed::SensorError::Max44(make_error_string(e)), - SensorError::Nau7802Left(e) => bed::SensorError::Nau7802Left(make_error_string(e)), - SensorError::Nau7802Right(e) => bed::SensorError::Nau7802Right(make_error_string(e)), - SensorError::Button(e) => bed::SensorError::Button(make_error_string(e)), - } - } -} - -#[derive(defmt::Format, PartialEq, Eq, Clone)] -pub(crate) enum Error { - Running(SensorError), - Setup(SensorError), - Timeout(Device), -} - -impl From for bed::Error { - fn from(val: Error) -> Self { - match val { - Error::Running(e) => bed::Error::Running(e.into()), - Error::Setup(e) => bed::Error::Setup(e.into()), - Error::Timeout(dev) => bed::Error::Timeout(dev), - } - } -} diff --git a/sensor-nodes/bed-lb/src/main.rs b/sensor-nodes/bed-lb/src/main.rs index 693fcc72..9a5098ad 100644 --- a/sensor-nodes/bed-lb/src/main.rs +++ b/sensor-nodes/bed-lb/src/main.rs @@ -30,7 +30,6 @@ use defmt::{error, trace, unwrap}; use {defmt_rtt as _, panic_probe as _}; mod channel; -mod error_cache; mod network; mod rgb_led; mod rng; @@ -49,21 +48,29 @@ embassy_stm32::bind_interrupts!(struct Irqs { type EthernetSPI = ExclusiveDevice, Output<'static>, Delay>; #[embassy_executor::task] async fn ethernet_task( - runner: Runner<'static, W5500, EthernetSPI, ExtiInput<'static>, Output<'static>>, + runner: Runner< + 'static, + W5500, + EthernetSPI, + ExtiInput<'static>, + Output<'static>, + >, ) -> ! { runner.run().await } #[embassy_executor::task] -async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { +async fn net_task( + mut runner: embassy_net::Runner<'static, Device<'static>>, +) -> ! { runner.run().await } // 84 Mhz clock stm32f401 fn config() -> Config { use embassy_stm32::rcc::{ - AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllPreDiv, PllSource, - Sysclk, + AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, + PllPreDiv, PllSource, Sysclk, }; let mut config = Config::default(); @@ -122,7 +129,7 @@ async fn main(spawner: Spawner) { )); // We are out of DMA, so we need to use a blocking interface - // these sensors are only read once every 5s + // these sensors are only read once every 5 seconds let i2c_1 = I2c::new( p.I2C1, p.PB8, @@ -174,7 +181,8 @@ async fn main(spawner: Spawner) { let mut spi_cfg = SpiConfig::default(); spi_cfg.frequency = Hertz(5_000_000); // Up to 50m works let (miso, mosi, clk) = (p.PA6, p.PA7, p.PA5); - let spi = Spi::new(p.SPI1, clk, mosi, miso, p.DMA2_CH3, p.DMA2_CH0, spi_cfg); + let spi = + Spi::new(p.SPI1, clk, mosi, miso, p.DMA2_CH3, p.DMA2_CH0, spi_cfg); let cs = Output::new(p.PA4, Level::High, Speed::VeryHigh); let spi = unwrap!(ExclusiveDevice::new(spi, cs, Delay)); @@ -184,23 +192,26 @@ async fn main(spawner: Spawner) { let mac_addr = [0x02, 234, 3, 4, 82, 231]; static STATE: StaticCell> = StaticCell::new(); let state = STATE.init(State::<3, 2>::new()); - let (device, runner) = - unwrap!(embassy_net_wiznet::new(mac_addr, state, spi, w5500_int, w5500_reset).await); + let (device, runner) = unwrap!( + embassy_net_wiznet::new(mac_addr, state, spi, w5500_int, w5500_reset) + .await + ); unwrap!(spawner.spawn(ethernet_task(runner))); // Init network stack - let mut dns_servers: Vec<_, 3> = Vec::new(); - unwrap!(dns_servers.push(Ipv4Address::new(192, 168, 1, 1))); - unwrap!(dns_servers.push(Ipv4Address::new(192, 168, 1, 1))); - unwrap!(dns_servers.push(Ipv4Address::new(192, 168, 1, 1))); static RESOURCES: StaticCell> = StaticCell::new(); - let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { - address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 1, 7), 24), - gateway: Some(Ipv4Address::new(192, 168, 1, 1)), - dns_servers, - }); - let (stack, runner) = - embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); + let config = + embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { + address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 1, 7), 24), + gateway: Some(Ipv4Address::new(192, 168, 1, 1)), + dns_servers: Vec::new(), + }); + let (stack, runner) = embassy_net::new( + device, + config, + RESOURCES.init(StackResources::new()), + seed, + ); // Launch network task unwrap!(spawner.spawn(net_task(runner))); @@ -211,7 +222,8 @@ async fn main(spawner: Spawner) { let driver_orderers = slow::DriverOrderers::new(); let publish = Queues::new(); - let handle_network = network::handle(&stack, &publish, led_handle.clone(), &driver_orderers); + let handle_network = + network::handle(&stack, &publish, led_handle.clone(), &driver_orderers); pin_mut!(handle_network); let init_then_measure = sensors::init_then_measure( @@ -233,7 +245,9 @@ async fn main(spawner: Spawner) { ) .await; let unrecoverable_err = match res { - Either3::First(()) | Either3::Third(()) | Either3::Second(Ok(())) => defmt::unreachable!(), + Either3::First(()) | Either3::Third(()) | Either3::Second(Ok(())) => { + defmt::unreachable!() + } Either3::Second(Err(err)) => err, }; diff --git a/sensor-nodes/bed-lb/src/network.rs b/sensor-nodes/bed-lb/src/network.rs index 03a36709..e0121033 100644 --- a/sensor-nodes/bed-lb/src/network.rs +++ b/sensor-nodes/bed-lb/src/network.rs @@ -4,6 +4,7 @@ use embassy_net::tcp::{TcpReader, TcpSocket, TcpWriter}; use embassy_net::{Ipv4Address, Stack}; use embassy_time::{with_timeout, Duration, Instant, Timer}; use embedded_io_async::Write; +use protocol::affector::DeserializeError; use protocol::large_bedroom::{self, bed}; use protocol::{affector, Affector, ErrorReport, SensorMessage}; @@ -13,7 +14,10 @@ use crate::sensors::slow; type SensMsg = SensorMessage<10>; -async fn collect_pending(publish: &Queues, reading: PriorityValue) -> SensorMessage<10> { +async fn collect_pending( + publish: &Queues, + reading: PriorityValue, +) -> SensorMessage<10> { let mut msg = SensMsg::default(); let low_priority = reading.low_priority(); unwrap!(msg.values.push(reading.value)); @@ -56,7 +60,8 @@ async fn get_messages<'a>(publish: &Queues, buf: &'a mut [u8]) -> &'a [u8] { QueueItem::Error(error) => { let error = protocol::large_bedroom::Error::Bed(error.into()); let error = protocol::Error::LargeBedroom(error); - let encoded_len = ErrorReport::new(error).encode_slice(&mut buf[1..]).len(); + let encoded_len = + ErrorReport::new(error).encode_slice(&mut buf[1..]).len(); buf[0] = protocol::Msg::<0>::ERROR_REPORT; &buf[..=encoded_len] } @@ -74,7 +79,8 @@ pub async fn handle( driver_orderers: &slow::DriverOrderers, ) { let mut rx_buffer = [0; 1024]; - let mut tx_buffer = [0; max(SensMsg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE) * 2]; + let mut tx_buffer = + [0; max(SensMsg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE) * 2]; let mut socket = TcpSocket::new(*stack, &mut rx_buffer, &mut tx_buffer); socket.set_timeout(Some(Duration::from_secs(5))); @@ -101,7 +107,9 @@ pub async fn handle( ) .await { - select::Either::First(e) => warn!("Error while sending messages: {}", e), + select::Either::First(e) => { + warn!("Error while sending messages: {}", e) + } select::Either::Second(e) => warn!("Error receiving orders: {}", e), }; // Or the socket will hang for a while waiting to close this makes sure @@ -124,19 +132,26 @@ fn affector_list() -> affector::ListMessage<5> { protocol::large_bedroom::Affector::Bed(bed::Affector::Sps30FanClean), ))); unwrap!(list.values.push(Affector::LargeBedroom( - protocol::large_bedroom::Affector::Bed(bed::Affector::MhzZeroPointCalib), + protocol::large_bedroom::Affector::Bed( + bed::Affector::MhzZeroPointCalib + ), ))); unwrap!(list.values.push(Affector::LargeBedroom( protocol::large_bedroom::Affector::Bed(bed::Affector::Nau7802LeftCalib), ))); unwrap!(list.values.push(Affector::LargeBedroom( - protocol::large_bedroom::Affector::Bed(bed::Affector::Nau7802RightCalib), + protocol::large_bedroom::Affector::Bed( + bed::Affector::Nau7802RightCalib + ), ))); list } -async fn send_messages(mut tcp: TcpWriter<'_>, publish: &Queues) -> embassy_net::tcp::Error { +async fn send_messages( + mut tcp: TcpWriter<'_>, + publish: &Queues, +) -> embassy_net::tcp::Error { let mut buf = [0; 1 + max( max(SensMsg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE), affector::ListMessage::<5>::ENCODED_SIZE, @@ -160,6 +175,7 @@ async fn send_messages(mut tcp: TcpWriter<'_>, publish: &Queues) -> embassy_net: enum ReadError { ConnectionClosed, TcpError(embassy_net::tcp::Error), + Deserialize(DeserializeError), } async fn receive_orders( @@ -178,11 +194,19 @@ async fn receive_orders( Err(e) => return ReadError::TcpError(e), }; let mut read = &buf[..n_read]; - while let Some((item, remaining)) = decoder.feed(read) { + + loop { + let (item, remaining) = match decoder.feed(read) { + Ok(Some((item, remaining))) => (item, remaining), + Ok(None) => break, + Err(e) => return ReadError::Deserialize(e), + }; + read = remaining; #[allow(irrefutable_let_patterns)] // Will change in the future - let Affector::LargeBedroom(large_bedroom::Affector::Bed(affector)) = item + let Affector::LargeBedroom(large_bedroom::Affector::Bed(affector)) = + item else { defmt::error!("Got affector for other node"); continue; @@ -190,7 +214,8 @@ async fn receive_orders( defmt::info!("got affector order: {:?}", affector); match affector { - bed::Affector::Nau7802LeftCalib | bed::Affector::Nau7802RightCalib => { + bed::Affector::Nau7802LeftCalib + | bed::Affector::Nau7802RightCalib => { defmt::warn!("unimplemented affector: {:?}", affector) } bed::Affector::MhzZeroPointCalib => { @@ -207,6 +232,11 @@ async fn receive_orders( ) .await } + bed::Affector::ResetNode => { + defmt::info!("resetting node as orderd via affector"); + defmt::flush(); + cortex_m::peripheral::SCB::sys_reset(); + } } } } diff --git a/sensor-nodes/bed-lb/src/sensors.rs b/sensor-nodes/bed-lb/src/sensors.rs index 3b067d6d..0d1c51a9 100644 --- a/sensor-nodes/bed-lb/src/sensors.rs +++ b/sensor-nodes/bed-lb/src/sensors.rs @@ -1,52 +1,28 @@ use defmt::info; -use embassy_embedded_hal::shared_bus::I2cDeviceError; use embassy_futures::join; use embassy_stm32::i2c::I2c; use embassy_stm32::mode::{Async, Blocking}; use embassy_stm32::usart::Uart; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; -use embassy_time::Delay; use fast::ButtonInputs; -use mhzx::MHZ; use protocol::large_bedroom::bed::Device; -use sps30_async::Sps30; use crate::channel::Queues; -use crate::error_cache::{Error, SensorError}; use crate::rgb_led; - +use sensors::{Error, I2cWrapper, Nau7802DriverBlocking, SPS30_UART_BUF_SIZE}; pub mod fast; -pub mod retry; pub mod slow; -use retry::{ - Bme680Driver, Driver, Max44Driver, Nau7802Driver, Nau7802DriverBlocking, Sht31Driver, +use sensors::{ + Bme680Driver, Max44Driver, MhzDriver, Nau7802Driver, Sht31Driver, Sps30Driver, }; -pub type I2cError = I2cDeviceError; -pub type UartError = embassy_stm32::usart::Error; - -pub mod concrete_types { - use embassy_embedded_hal::shared_bus; - use embassy_stm32::i2c::I2c; - use embassy_stm32::mode::{Async, Blocking}; - use embassy_stm32::usart::{RingBufferedUartRx, UartTx}; - use embassy_sync::blocking_mutex::raw::NoopRawMutex; - use shared_bus::asynch::i2c::I2cDevice; - - use super::I2cWrapper; - - pub type ConcreteSharedI2c<'a> = I2cDevice<'a, NoopRawMutex, I2c<'static, Async>>; - pub type ConcreteBlockingI2c<'a> = &'a I2cWrapper>; - pub type ConcreteTx<'a> = UartTx<'a, Async>; - pub type ConcreteRx<'a> = RingBufferedUartRx<'a>; +fn local_dev(dev: protocol::large_bedroom::bed::Device) -> protocol::Device { + protocol::Device::LargeBedroom(protocol::large_bedroom::Device::Bed(dev)) } -const SPS30_UART_BUF_SIZE: usize = 150; -const SPS30_DRIVER_BUF_SIZE: usize = 2 * SPS30_UART_BUF_SIZE; - pub async fn init_then_measure( publish: &Queues, orderers: &slow::DriverOrderers, @@ -59,24 +35,26 @@ pub async fn init_then_measure( buttons: ButtonInputs, ) -> Result<(), Error> { info!("initializing sensors"); - let bme = Bme680Driver::new(&i2c_3, Device::Bme680); - let max44009 = Max44Driver::new(&i2c_1, Device::Max44); - let sht = Sht31Driver::new(&i2c_1, Device::Sht31); + let bme = Bme680Driver::new(&i2c_3, local_dev(Device::Bme680)); + let max44009 = Max44Driver::new(&i2c_1, local_dev(Device::Max44)); + let sht = Sht31Driver::new(&i2c_1, local_dev(Device::Sht31)); let i2c_2 = I2cWrapper(i2c_2); - let nau_right = Nau7802DriverBlocking::new(&i2c_2, Device::Nau7802Right); - let nau_left = Nau7802Driver::new(&i2c_3, Device::Nau7802Left); + let nau_right = + Nau7802DriverBlocking::new(&i2c_2, local_dev(Device::Nau7802Right)); + let nau_left = Nau7802Driver::new(&i2c_3, local_dev(Device::Nau7802Left)); let (tx, rx) = usart_mhz.split(); let mut usart_buf = [0u8; 9 * 10]; // 9 byte messages let rx = rx.into_ring_buffered(&mut usart_buf); - let mhz = MHZ::from_tx_rx(tx, rx); + let mhz = MhzDriver::new(tx, rx, local_dev(Device::Mhz14)); let (tx, rx) = usart_sps.split(); let mut usart_buf = [0u8; SPS30_UART_BUF_SIZE]; let rx = rx.into_ring_buffered(&mut usart_buf); - let sps30 = Sps30Driver::init(tx, rx); + let sps30 = Sps30Driver::init(tx, rx, local_dev(Device::Sps30)); - let sensors_fast = fast::read(max44009, nau_right, nau_left, buttons, publish, rgb_led); + let sensors_fast = + fast::read(max44009, nau_right, nau_left, buttons, publish, rgb_led); let drivers = slow::Drivers { sht, bme, @@ -88,74 +66,3 @@ pub async fn init_then_measure( defmt::unreachable!(); } - -use concrete_types::ConcreteRx as Rx; -use concrete_types::ConcreteTx as Tx; -impl<'a> Driver for MHZ, Rx<'a>> { - type Measurement = mhzx::Measurement; - type Affector = (); - - #[inline(always)] - async fn try_measure(&mut self) -> Result { - self.read_co2() - .await - .map_err(SensorError::Mhz14) - .map_err(Error::Running) - } - - #[inline(always)] - fn device(&self) -> protocol::large_bedroom::bed::Device { - Device::Mhz14 - } -} - -impl<'a> Driver for Sps30, Rx<'a>, Delay> { - type Measurement = sps30_async::Measurement; - type Affector = (); - - #[inline(always)] - async fn try_measure(&mut self) -> Result { - self.read_measurement() - .await - .map_err(SensorError::Sps30) - .map_err(Error::Running) - } - - #[inline(always)] - fn device(&self) -> protocol::large_bedroom::bed::Device { - Device::Sps30 - } -} - -pub(crate) struct I2cWrapper(Mutex); - -impl embedded_hal_async::i2c::ErrorType for &I2cWrapper { - type Error = ::Error; -} - -impl embedded_hal_async::i2c::I2c for &I2cWrapper { - async fn transaction( - &mut self, - address: u8, - operations: &mut [embedded_hal_async::i2c::Operation<'_>], - ) -> Result<(), Self::Error> { - self.0.lock().await.transaction(address, operations) - } - - async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { - self.0.lock().await.read(address, read) - } - - async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { - self.0.lock().await.write(address, write) - } - - async fn write_read( - &mut self, - address: u8, - write: &[u8], - read: &mut [u8], - ) -> Result<(), Self::Error> { - self.0.lock().await.write_read(address, write, read) - } -} diff --git a/sensor-nodes/bed-lb/src/sensors/fast.rs b/sensor-nodes/bed-lb/src/sensors/fast.rs index 7df50ecc..70f1a2b8 100644 --- a/sensor-nodes/bed-lb/src/sensors/fast.rs +++ b/sensor-nodes/bed-lb/src/sensors/fast.rs @@ -1,13 +1,14 @@ -use embassy_futures::join::{join3, join4}; -use embassy_futures::{join, yield_now}; +use embassy_futures::{ + join::{self, join3, join4}, + yield_now, +}; use embassy_stm32::exti::ExtiInput; use embassy_time::{Duration, Instant, Timer}; use protocol::large_bedroom::{bed::Button, bed::Reading}; -use super::retry::{Max44Driver, Nau7802Driver, Nau7802DriverBlocking}; -use crate::channel::Queues; -use crate::rgb_led; +use crate::{channel::Queues, rgb_led}; +use sensors::{Max44Driver, Nau7802Driver, Nau7802DriverBlocking}; fn sig_lux_diff(old: f32, new: f32) -> bool { let diff = old - new; @@ -20,7 +21,11 @@ fn sig_weight_diff(old: u32, new: u32) -> bool { diff > 2000 } -async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues, rgb_led: rgb_led::LedHandle<'_>) { +async fn report_lux( + mut max44: Max44Driver<'_>, + publish: &Queues, + rgb_led: rgb_led::LedHandle<'_>, +) { const MAX_INTERVAL: Duration = Duration::from_secs(5); let mut prev_lux = f32::MAX; @@ -53,22 +58,32 @@ async fn report_lux(mut max44: Max44Driver<'_>, publish: &Queues, rgb_led: rgb_l } trait Nau { - async fn try_measure(&mut self) -> Result; + async fn try_measure(&mut self) -> Result; } impl Nau for Nau7802Driver<'_> { - async fn try_measure(&mut self) -> Result { + async fn try_measure(&mut self) -> Result { Nau7802Driver::try_measure(self).await } } impl Nau for Nau7802DriverBlocking<'_> { - async fn try_measure(&mut self) -> Result { + async fn try_measure(&mut self) -> Result { Nau7802DriverBlocking::try_measure(self).await } } -async fn report_weight(mut nau: impl Nau, wrap: impl Fn(u32) -> Reading, publish: &Queues) { +enum Position { + Left, + Right, +} + +async fn report_weight( + mut nau: impl Nau, + wrap_reading: impl Fn(u32) -> Reading, + position: Position, + publish: &Queues, +) { const MAX_INTERVAL: Duration = Duration::from_secs(5); let mut prev_weight = u32::MAX; @@ -79,6 +94,11 @@ async fn report_weight(mut nau: impl Nau, wrap: impl Fn(u32) -> Reading, publish let weight = match nau.try_measure().await { Ok(lux) => lux, Err(err) if reported_at.elapsed() > MAX_INTERVAL => { + let err = if matches!(position, Position::Right) { + err.into_right() + } else { + err // default is left + }; publish.queue_error(err); continue; } @@ -86,9 +106,9 @@ async fn report_weight(mut nau: impl Nau, wrap: impl Fn(u32) -> Reading, publish }; if sig_weight_diff(prev_weight, weight) { - publish.send_p2(wrap(weight)); + publish.send_p2(wrap_reading(weight)); } else if reported_at.elapsed() > MAX_INTERVAL { - publish.send_p1(wrap(weight)); + publish.send_p1(wrap_reading(weight)); } else { yield_now().await; continue; @@ -104,7 +124,7 @@ async fn watch_button( event: impl Fn(protocol::button::Press) -> Button, channel: &Queues, ) { - use crate::error_cache::{Error, PressTooLong, SensorError}; + use sensors::{errors::PressTooLong, errors::SensorError, Error}; let mut went_high_at: Option = None; loop { @@ -114,9 +134,9 @@ async fn watch_button( let Ok(press) = press.as_millis().try_into() else { let event_for_printing = (event)(protocol::button::Press(0)); let name = event_for_printing.variant_name(); - channel.queue_error(Error::Running(SensorError::Button(PressTooLong { - button: name, - }))); + channel.queue_error(Error::Running(SensorError::Button( + PressTooLong { button: name }, + ))); continue; }; let event = (event)(protocol::button::Press(press)); @@ -172,17 +192,22 @@ pub(crate) async fn read( watch_button(inputs.lower_outer, Button::LowerOuter, publish), ); - let watch_buttons = join::join(watch_buttons_1, watch_buttons_2); - let watch_lux = report_lux(max44, publish, rgb_led); - let report_right_weight = report_weight(nau_right, Reading::WeightRight, publish); - let report_left_weight = report_weight(nau_left, Reading::WeightLeft, publish); + let report_right_weight = report_weight( + nau_right, + Reading::WeightRight, + Position::Right, + publish, + ); + let report_left_weight = + report_weight(nau_left, Reading::WeightLeft, Position::Left, publish); - join::join4( + join::join5( report_left_weight, report_right_weight, watch_lux, - watch_buttons, + watch_buttons_1, + watch_buttons_2, ) .await; } diff --git a/sensor-nodes/bed-lb/src/sensors/retry.rs b/sensor-nodes/bed-lb/src/sensors/retry.rs deleted file mode 100644 index 6ad85fd1..00000000 --- a/sensor-nodes/bed-lb/src/sensors/retry.rs +++ /dev/null @@ -1,147 +0,0 @@ -use bosch_bme680::Bme680; -use embassy_embedded_hal::shared_bus; -use embassy_stm32::i2c::I2c; -use embassy_stm32::mode::{Async, Blocking}; -use embassy_sync::blocking_mutex::raw::NoopRawMutex; -use embassy_sync::mutex::Mutex; -use embassy_time::{Delay, Timer}; -use max44009::{Max44009, SlaveAddr}; -use nau7802_async::Nau7802; -use sht31::mode::SingleShot; -use sht31::SHT31; - -use super::concrete_types::{ConcreteBlockingI2c, ConcreteSharedI2c}; -use super::I2cWrapper; -use crate::error_cache::SensorError; - -mod reinit_on_error; -pub use reinit_on_error::{ - Bme680Driver, Max44Driver, Nau7802Driver, Nau7802DriverBlocking, Sht31Driver, -}; - -mod retry_init; -pub use retry_init::Sps30Driver; - -impl<'a> ReInitableDriver for SHT31> { - type Parts = &'a Mutex>; - type Measurement = sht31::Reading; - - async fn init(parts: Self::Parts) -> Result { - let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); - Ok(SHT31::new(shared_i2c, Delay) - .with_mode(SingleShot) - .with_unit(sht31::TemperatureUnit::Celsius) - .with_accuracy(sht31::Accuracy::High)) - } - - async fn measure(&mut self) -> Result { - use sht31::mode::Sht31Measure; - use sht31::mode::Sht31Reader; - - Sht31Measure::measure(self) - .await - .map_err(SensorError::Sht31)?; - Timer::after_secs(1).await; - self.read().await.map_err(SensorError::Sht31) - } -} - -impl<'a> ReInitableDriver for Bme680, Delay> { - type Parts = &'a Mutex>; - type Measurement = bosch_bme680::MeasurementData; - - async fn init(parts: Self::Parts) -> Result { - let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); - Bme680::new( - shared_i2c, - bosch_bme680::DeviceAddress::Secondary, - Delay, - &bosch_bme680::Configuration::default(), - 21, - ) - .await - .map_err(SensorError::Bme680) - } - - async fn measure(&mut self) -> Result { - self.measure().await.map_err(SensorError::Bme680) - } -} - -impl<'a> ReInitableDriver for Max44009> { - type Parts = &'a Mutex>; - type Measurement = f32; - - async fn init(parts: Self::Parts) -> Result { - let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); - // Wrap these two into something returning Ok or Err - // then make it a generic arg, maybe Driverfactory::init - let mut driver = Max44009::new(shared_i2c, SlaveAddr::default()); - driver - .set_measurement_mode(max44009::MeasurementMode::Continuous) - .await - .map_err(SensorError::Max44)?; - Ok(driver) - } - async fn measure(&mut self) -> Result { - self.read_lux().await.map_err(SensorError::Max44) - } -} - -impl<'a> ReInitableDriver for Nau7802, Delay> { - type Parts = &'a Mutex>; - type Measurement = u32; - - async fn init(parts: Self::Parts) -> Result { - let shared_i2c = shared_bus::asynch::i2c::I2cDevice::new(parts); - // Wrap these two into something returning Ok or Err - // then make it a generic arg, maybe Driverfactory::init - let driver = Nau7802::new(shared_i2c, Delay) - .await - .map_err(SensorError::Nau7802Left)?; - Ok(driver) - } - - async fn measure(&mut self) -> Result { - self.read().await.map_err(SensorError::Nau7802Left) - } -} - -impl<'a> ReInitableDriver for Nau7802, Delay> { - type Parts = &'a I2cWrapper>; - type Measurement = u32; - - async fn init(parts: Self::Parts) -> Result { - let shared_i2c = parts; - // Wrap these two into something returning Ok or Err - // then make it a generic arg, maybe Driverfactory::init - let driver = Nau7802::new(shared_i2c, Delay) - .await - .map_err(SensorError::Nau7802Right)?; - Ok(driver) - } - - async fn measure(&mut self) -> Result { - self.read().await.map_err(SensorError::Nau7802Right) - } -} - -/// A driver that can be re-initialized from copy-able parts -pub trait ReInitableDriver: Sized { - type Parts: Clone; - type Measurement; - - async fn init(parts: Self::Parts) -> Result; - async fn measure(&mut self) -> Result; -} - -pub trait Driver { - type Measurement; - type Affector; - async fn try_measure(&mut self) -> Result; - /// For example calibrate, run sensor cleaning etc - async fn affect(&mut self, _: Self::Affector) -> Result<(), crate::error_cache::Error> { - Ok(()) - } - fn device(&self) -> protocol::large_bedroom::bed::Device; -} diff --git a/sensor-nodes/bed-lb/src/sensors/retry/reinit_on_error.rs b/sensor-nodes/bed-lb/src/sensors/retry/reinit_on_error.rs deleted file mode 100644 index 2f638603..00000000 --- a/sensor-nodes/bed-lb/src/sensors/retry/reinit_on_error.rs +++ /dev/null @@ -1,119 +0,0 @@ -use bosch_bme680::Bme680; -use embassy_time::Delay; -use max44009::Max44009; -use nau7802_async::Nau7802; -use protocol::large_bedroom::bed::Device; -use sht31::mode::SingleShot; -use sht31::SHT31; - -use super::super::concrete_types::ConcreteSharedI2c; -use super::ReInitableDriver; -use crate::error_cache::Error; -use crate::sensors::concrete_types::ConcreteBlockingI2c; - -pub type Nau7802DriverBlocking<'a> = ReInitOnErrorDriver, Delay>>; -pub type Nau7802Driver<'a> = ReInitOnErrorDriver, Delay>>; -pub type Max44Driver<'a> = ReInitOnErrorDriver>>; -pub type Bme680Driver<'a> = ReInitOnErrorDriver, Delay>>; -pub type Sht31Driver<'a> = ReInitOnErrorDriver>>; - -enum State { - Ready { driver: D }, - Uninit, -} - -pub struct ReInitOnErrorDriver -where - D: ReInitableDriver, -{ - state: State, - parts: D::Parts, - device: Device, -} - -impl super::Driver for ReInitOnErrorDriver { - type Measurement = D::Measurement; - type Affector = (); - - #[inline(always)] - async fn try_measure(&mut self) -> Result { - self.try_measure().await - } - - #[inline(always)] - fn device(&self) -> Device { - self.device.clone() - } -} - -impl ReInitOnErrorDriver -where - D: ReInitableDriver, -{ - #[inline(always)] - pub fn new(parts: D::Parts, device: Device) -> Self { - Self { - state: State::Uninit, - parts, - device, - } - } - - #[inline(always)] - pub async fn try_measure(&mut self) -> Result { - let mut owned_self = State::Uninit; - core::mem::swap(&mut owned_self, &mut self.state); - let (mut new_self, res) = advance_state(owned_self, &self.parts).await; - core::mem::swap(&mut new_self, &mut self.state); - res - } -} - -#[inline(always)] -async fn advance_state( - state: State, - parts: &D::Parts, -) -> (State, Result) { - match state { - State::Ready { - mut driver, - // make a trait over driver that has a measure method - } => match driver.measure().await { - Ok(val) => { - let new_state = State::Ready { driver }; - (new_state, Ok(val)) - } - Err(err) => { - let new_state = State::Uninit; - (new_state, Err(Error::Running(err))) - } - }, - State::Uninit => { - match D::init(parts.clone()).await { - Ok(mut driver) => { - // uses driver::measure again, make that return a SensorError - match driver.measure().await { - Ok(val) => { - let new_state = State::Ready { driver }; - (new_state, Ok(val)) - } - Err(err) => { - let new_state = State::Uninit; - let err = Error::Running(err); - (new_state, Err(err)) - } - } - } - Err(err) => { - // drivers might contain blocking code in their - // error path, this makes sure the executor - // will not block on retrying. - embassy_time::Timer::after_millis(250).await; - let new_state = State::Uninit; - let err = Error::Setup(err); - (new_state, Err(err)) - } - } - } - } -} diff --git a/sensor-nodes/bed-lb/src/sensors/retry/retry_init.rs b/sensor-nodes/bed-lb/src/sensors/retry/retry_init.rs deleted file mode 100644 index 706be28e..00000000 --- a/sensor-nodes/bed-lb/src/sensors/retry/retry_init.rs +++ /dev/null @@ -1,83 +0,0 @@ -use embassy_time::Delay; -use sps30_async::Sps30; - -use crate::error_cache::{Error, SensorError}; -use crate::sensors::concrete_types::{ConcreteRx, ConcreteTx}; -use crate::sensors::SPS30_DRIVER_BUF_SIZE; - -use super::Driver; - -/// reset the device when an error occurs -pub struct Sps30Driver<'a> { - is_init: bool, - driver: Sps30, ConcreteRx<'a>, Delay>, -} - -impl<'a> Sps30Driver<'a> { - pub fn init(tx: ConcreteTx<'a>, rx: ConcreteRx<'a>) -> Self { - let driver = Sps30::from_tx_rx_uninit(tx, rx, Delay); - Self { - is_init: false, - driver, - } - } - - async fn measure(&mut self) -> Result { - if self.is_init { - let res = self - .driver - .read_measurement() - .await - .map_err(SensorError::Sps30) - .map_err(Error::Running); - self.is_init = res.is_ok(); - return res; - } - - self.driver - .reset() - .await - .map_err(SensorError::Sps30) - .map_err(Error::Setup)?; - self.driver - .start_measurement() - .await - .map_err(SensorError::Sps30) - .map_err(Error::Setup)?; - - let res = self - .driver - .read_measurement() - .await - .map_err(SensorError::Sps30) - .map_err(Error::Running); - - self.is_init = res.is_ok(); - res - } -} - -impl<'a> Driver for Sps30Driver<'a> { - type Measurement = sps30_async::Measurement; - type Affector = (); - - async fn try_measure(&mut self) -> Result { - self.measure().await - } - - async fn affect(&mut self, _: Self::Affector) -> Result<(), crate::error_cache::Error> { - self.driver - .start_fan_cleaning() - .await - .map_err(SensorError::Sps30) - .map_err(Error::Running)?; - // Fan cleaning takes 10 seconds, make sure its done before - // allowing the next reading - embassy_time::Timer::after(embassy_time::Duration::from_secs(11)).await; - Ok(()) - } - - fn device(&self) -> protocol::large_bedroom::bed::Device { - protocol::large_bedroom::bed::Device::Sps30 - } -} diff --git a/sensor-nodes/bed-lb/src/sensors/slow.rs b/sensor-nodes/bed-lb/src/sensors/slow.rs index a3661401..e556c937 100644 --- a/sensor-nodes/bed-lb/src/sensors/slow.rs +++ b/sensor-nodes/bed-lb/src/sensors/slow.rs @@ -6,19 +6,12 @@ use embassy_sync::channel::Channel; use embassy_time::Timer; use embassy_time::{with_timeout, Duration}; -use mhzx::MHZ; use protocol::large_bedroom::bed::Reading; -use bosch_bme680::MeasurementData; -use sps30_async as sps30; - use crate::channel::Queues; -use crate::error_cache::Error; - -use super::retry::{Bme680Driver, Driver, Sht31Driver, Sps30Driver}; - -use super::concrete_types::ConcreteRx as Rx; -use super::concrete_types::ConcreteTx as Tx; +use sensors::measurements; +use sensors::{Bme680Driver, Driver, Sht31Driver, Sps30Driver}; +use sensors::{Error, MhzDriver}; type Signal = embassy_sync::signal::Signal; @@ -70,7 +63,7 @@ async fn order_measurements_every_period(signals: &[Signal]) { pub(crate) struct Drivers<'a> { pub sht: Sht31Driver<'a>, pub bme: Bme680Driver<'a>, - pub mhz: MHZ, Rx<'a>>, + pub mhz: MhzDriver<'a>, pub sps: Sps30Driver<'a>, } @@ -92,7 +85,11 @@ impl DriverOrderers { } #[inline(always)] -pub async fn read(drivers: Drivers<'_>, orderers: &DriverOrderers, publish: &'_ Queues) { +pub async fn read( + drivers: Drivers<'_>, + orderers: &DriverOrderers, + publish: &'_ Queues, +) { let signals = [const { Signal::new() }; 4]; join5( @@ -125,9 +122,12 @@ pub async fn read(drivers: Drivers<'_>, orderers: &DriverOrderers, publish: &'_ .await; } -fn publish_sps_result(sps_res: Result, publish: &Queues) { +fn publish_sps_result( + sps_res: Result, + publish: &Queues, +) { match sps_res { - Ok(sps30::Measurement { + Ok(measurements::Sps30 { mass_pm1_0, mass_pm2_5, mass_pm4_0, @@ -149,15 +149,19 @@ fn publish_sps_result(sps_res: Result, publish: &Queu publish.send_p0(Reading::NumberPm2_5(number_pm2_5)); publish.send_p0(Reading::NumberPm4_0(number_pm4_0)); publish.send_p0(Reading::NumberPm10(number_pm10)); - publish.send_p0(Reading::TypicalParticleSize(typical_particle_size)); + publish + .send_p0(Reading::TypicalParticleSize(typical_particle_size)); } Err(err) => publish.queue_error(err), } } -fn publish_mhz_result(mhz_res: Result, publish: &Queues) { +fn publish_mhz_result( + mhz_res: Result, + publish: &Queues, +) { match mhz_res { - Ok(mhzx::Measurement { co2, .. }) => { + Ok(measurements::Mhz { co2, .. }) => { publish.send_p0(Reading::Co2(co2)); } Err(err) => { @@ -166,9 +170,12 @@ fn publish_mhz_result(mhz_res: Result, publish: &Queue } } -fn publish_sht_result(sht_res: Result, publish: &Queues) { +fn publish_sht_result( + sht_res: Result, + publish: &Queues, +) { match sht_res { - Ok(sht31::Reading { + Ok(measurements::Sht31 { temperature, humidity, }) => { @@ -179,9 +186,12 @@ fn publish_sht_result(sht_res: Result, publish: } } -fn publish_bme_result(bme_res: Result, publish: &Queues) { +fn publish_bme_result( + bme_res: Result, + publish: &Queues, +) { match bme_res { - Ok(MeasurementData { + Ok(measurements::Bme { pressure, gas_resistance, .. diff --git a/sensor-nodes/sensors/Cargo.toml b/sensor-nodes/sensors/Cargo.toml index 8086c3bb..bb3043af 100644 --- a/sensor-nodes/sensors/Cargo.toml +++ b/sensor-nodes/sensors/Cargo.toml @@ -15,6 +15,9 @@ embassy-embedded-hal.workspace = true defmt.workspace = true +embedded-hal = "1.0.0" +embedded-hal-async = "1.0" + # sensors bosch-bme680 = { version = "1.0.2", path = "/home/david/Documents/async-bosch-bme680" } max44009 = { version = "0.2", git = "https://github.com/dvdsk/max44009-rs" } diff --git a/sensor-nodes/sensors/src/drivers.rs b/sensor-nodes/sensors/src/drivers.rs index 1785d120..d5d34165 100644 --- a/sensor-nodes/sensors/src/drivers.rs +++ b/sensor-nodes/sensors/src/drivers.rs @@ -1,5 +1,3 @@ -mod reinit_on_error; - mod driver_impl_bme680; mod driver_impl_max44009; mod driver_impl_nau7802; @@ -7,17 +5,22 @@ mod driver_impl_sht31; mod wrap_mhz; mod wrap_sps30; +mod reinit_on_error; +mod i2c_wrapper; + +pub use i2c_wrapper::I2cWrapper; use reinit_on_error::ReInitOnErrorDriver; use embassy_embedded_hal::shared_bus; use embassy_stm32::i2c::I2c; -use embassy_stm32::mode::Async; +use embassy_stm32::mode::{Async, Blocking}; use embassy_stm32::usart::{RingBufferedUartRx, UartTx}; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use shared_bus::asynch::i2c::I2cDevice; pub type ConcreteSharedI2c<'a> = I2cDevice<'a, NoopRawMutex, I2c<'static, Async>>; +pub type ConcreteBlockingI2c<'a> = &'a I2cWrapper>; pub type ConcreteTx<'a> = UartTx<'a, Async>; pub type ConcreteRx<'a> = RingBufferedUartRx<'a>; @@ -31,6 +34,8 @@ use sht31::SHT31; // Driver type aliases/wrapper structs. These auto correct/re-init on error pub use wrap_mhz::MhzDriver; pub use wrap_sps30::{Sps30Driver, SPS30_DRIVER_BUF_SIZE, SPS30_UART_BUF_SIZE}; +pub type Nau7802DriverBlocking<'a> = + ReInitOnErrorDriver, Delay>>; pub type Nau7802Driver<'a> = ReInitOnErrorDriver, Delay>>; pub type Max44Driver<'a> = ReInitOnErrorDriver>>; diff --git a/sensor-nodes/sensors/src/drivers/driver_impl_nau7802.rs b/sensor-nodes/sensors/src/drivers/driver_impl_nau7802.rs index f38391c4..e4206886 100644 --- a/sensor-nodes/sensors/src/drivers/driver_impl_nau7802.rs +++ b/sensor-nodes/sensors/src/drivers/driver_impl_nau7802.rs @@ -1,6 +1,6 @@ use embassy_embedded_hal::shared_bus; use embassy_stm32::i2c::I2c; -use embassy_stm32::mode::Async; +use embassy_stm32::mode::{Async, Blocking}; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; use embassy_time::Delay; @@ -9,7 +9,7 @@ use nau7802_async::Nau7802; use crate::errors::SensorError; use crate::ReInitableDriver; -use super::ConcreteSharedI2c; +use super::{ConcreteBlockingI2c, ConcreteSharedI2c, I2cWrapper}; impl<'a> ReInitableDriver for Nau7802, Delay> { type Parts = &'a Mutex>; @@ -21,11 +21,30 @@ impl<'a> ReInitableDriver for Nau7802, Delay> { // then make it a generic arg, maybe Driverfactory::init let driver = Nau7802::new(shared_i2c, Delay) .await - .map_err(SensorError::Nau7802)?; + .map_err(SensorError::Nau7802Left)?; Ok(driver) } async fn measure(&mut self) -> Result { - self.read().await.map_err(SensorError::Nau7802) + self.read().await.map_err(SensorError::Nau7802Left) + } +} + +impl<'a> ReInitableDriver for Nau7802, Delay> { + type Parts = &'a I2cWrapper>; + type Measurement = u32; + + async fn init(parts: Self::Parts) -> Result { + let shared_i2c = parts; + // Wrap these two into something returning Ok or Err + // then make it a generic arg, maybe Driverfactory::init + let driver = Nau7802::new(shared_i2c, Delay) + .await + .map_err(SensorError::Nau7802Left)?; + Ok(driver) + } + + async fn measure(&mut self) -> Result { + self.read().await.map_err(SensorError::Nau7802Left) } } diff --git a/sensor-nodes/sensors/src/drivers/i2c_wrapper.rs b/sensor-nodes/sensors/src/drivers/i2c_wrapper.rs new file mode 100644 index 00000000..a3248fc9 --- /dev/null +++ b/sensor-nodes/sensors/src/drivers/i2c_wrapper.rs @@ -0,0 +1,69 @@ +use embassy_embedded_hal::shared_bus::I2cDeviceError; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::mutex::Mutex; + +pub struct I2cWrapper(pub Mutex); + +/// Make sure the error type is the same as when +/// embassy_embedded_hal::shared_bus async is used. We do so by wrapping +/// underlying errors in [`I2cDevice`]. +/// +/// [`I2cDevice`](embassy_embedded_hal::shared_bus::asynch::i2c::I2cDevice) +impl embedded_hal_async::i2c::ErrorType + for &I2cWrapper +{ + type Error = I2cDeviceError<::Error>; +} + +impl embedded_hal_async::i2c::I2c + for &I2cWrapper +{ + async fn transaction( + &mut self, + address: u8, + operations: &mut [embedded_hal_async::i2c::Operation<'_>], + ) -> Result<(), Self::Error> { + self.0 + .lock() + .await + .transaction(address, operations) + .map_err(I2cDeviceError::I2c) + } + + async fn read( + &mut self, + address: u8, + read: &mut [u8], + ) -> Result<(), Self::Error> { + self.0 + .lock() + .await + .read(address, read) + .map_err(I2cDeviceError::I2c) + } + + async fn write( + &mut self, + address: u8, + write: &[u8], + ) -> Result<(), Self::Error> { + self.0 + .lock() + .await + .write(address, write) + .map_err(I2cDeviceError::I2c) + } + + async fn write_read( + &mut self, + address: u8, + write: &[u8], + read: &mut [u8], + ) -> Result<(), Self::Error> { + self.0 + .lock() + .await + .write_read(address, write, read) + .map_err(I2cDeviceError::I2c) + } +} diff --git a/sensor-nodes/sensors/src/errors.rs b/sensor-nodes/sensors/src/errors.rs index 50bfd60a..83aa50e6 100644 --- a/sensor-nodes/sensors/src/errors.rs +++ b/sensor-nodes/sensors/src/errors.rs @@ -22,10 +22,27 @@ pub enum SensorError { Sht31(sht31::SHTError), Bme680(bosch_bme680::BmeError), Max44(max44009::Error), - Nau7802(nau7802_async::Error), + /// Nodes with only one Nau7802 should use left, + /// it is what the driver returns by default + Nau7802Left(nau7802_async::Error), + Nau7802Right(nau7802_async::Error), Button(PressTooLong), } +impl SensorError { + /// ugly hack to allow users of sensors to get a different error for two + /// identical devices by calling into_right on the error the default error + /// is the 'left device'. Works only if there is a right device. Needs + /// the From for protocol::_::_Error to map right devices to right + /// devices + fn into_right(self) -> Self { + match self { + Self::Nau7802Left(e) => Self::Nau7802Right(e), + ref _other => self, + } + } +} + /// This error type is as small as possible. It is meant for /// devices to deduplicate errors that happen rapidly and only /// send such errors every once in a while to the host @@ -36,6 +53,25 @@ pub enum Error { Timeout(protocol::Device), } +impl Error { + /// ugly hack to allow users of sensors to get a different error for two + /// identical devices by calling into_right on the error the default error + /// is the 'left device'. Works only if there is a right device. Needs + /// the From for protocol::_::_Error to map right devices to right + /// devices + pub fn into_right(self) -> Self { + match self { + Self::Running(sensor_error) => { + Self::Running(sensor_error.into_right()) + } + Self::Setup(sensor_error) => { + Self::Setup(sensor_error.into_right()) + } + Self::Timeout(ref _device) => self, + } + } +} + impl From for protocol::small_bedroom::bed::SensorError { fn from(val: SensorError) -> Self { use protocol::small_bedroom::bed; @@ -55,12 +91,15 @@ impl From for protocol::small_bedroom::bed::SensorError { SensorError::Max44(e) => { bed::SensorError::Max44(make_error_string(e)) } - SensorError::Nau7802(e) => { + SensorError::Nau7802Left(e) => { bed::SensorError::Nau7802(make_error_string(e)) } SensorError::Button(e) => { bed::SensorError::Button(make_error_string(e)) } + SensorError::Nau7802Right(_) => { + unreachable!("Not installed for small_bedroom bed sensor") + } } } } @@ -82,3 +121,53 @@ impl From for protocol::small_bedroom::bed::Error { } } } + +impl From for protocol::large_bedroom::bed::SensorError { + fn from(val: SensorError) -> Self { + use protocol::large_bedroom::bed; + match val { + SensorError::Mhz14(e) => { + bed::SensorError::Mhz14(make_error_string(e)) + } + SensorError::Sps30(e) => { + bed::SensorError::Sps30(make_error_string(e)) + } + SensorError::Sht31(e) => { + bed::SensorError::Sht31(make_error_string(e)) + } + SensorError::Bme680(e) => { + bed::SensorError::Bme680(make_error_string(e)) + } + SensorError::Max44(e) => { + bed::SensorError::Max44(make_error_string(e)) + } + SensorError::Nau7802Left(e) => { + bed::SensorError::Nau7802Left(make_error_string(e)) + } + SensorError::Nau7802Right(e) => { + bed::SensorError::Nau7802Right(make_error_string(e)) + } + SensorError::Button(e) => { + bed::SensorError::Button(make_error_string(e)) + } + } + } +} + +impl From for protocol::large_bedroom::bed::Error { + fn from(val: Error) -> Self { + use protocol::large_bedroom::bed; + match val { + Error::Running(e) => bed::Error::Running(e.into()), + Error::Setup(e) => bed::Error::Setup(e.into()), + Error::Timeout(protocol::Device::LargeBedroom( + protocol::large_bedroom::Device::Bed(dev), + )) => bed::Error::Timeout(dev), + Error::Timeout(incorrect_dev) => defmt::unreachable!( + "Should only contain small_bedroom::bed devices, got {} which \ + is not part of small_bedroom::bed::Device", + incorrect_dev + ), + } + } +} diff --git a/sensor-nodes/sensors/src/lib.rs b/sensor-nodes/sensors/src/lib.rs index e2c01155..2e84ca50 100644 --- a/sensor-nodes/sensors/src/lib.rs +++ b/sensor-nodes/sensors/src/lib.rs @@ -1,12 +1,13 @@ #![no_std] mod drivers; -pub mod measurements; pub mod errors; +pub mod measurements; +pub use drivers::I2cWrapper; pub use drivers::{ - Bme680Driver, Max44Driver, Nau7802Driver, Sps30Driver, Sht31Driver, MhzDriver, - SPS30_DRIVER_BUF_SIZE, SPS30_UART_BUF_SIZE, + Bme680Driver, Max44Driver, MhzDriver, Nau7802Driver, Nau7802DriverBlocking, + Sht31Driver, Sps30Driver, SPS30_DRIVER_BUF_SIZE, SPS30_UART_BUF_SIZE, }; pub use errors::Error; From 9a0b43340a1c503d8c80aa7470c48a7e1c7c83e5 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Wed, 11 Dec 2024 13:22:16 +0100 Subject: [PATCH 493/687] Rewrite lights system to use new Device trait --- crates/zigbee-bridge/src/device.rs | 37 ++++++ crates/zigbee-bridge/src/lib.rs | 1 + crates/zigbee-bridge/src/lights.rs | 14 +- .../zigbee-bridge/src/lights/cached_bridge.rs | 8 +- .../src/lights/cached_bridge/changes.rs | 40 +++--- .../src/lights/cached_bridge/mqtt.rs | 14 +- .../src/lights/cached_bridge/poll.rs | 36 +++--- crates/zigbee-bridge/src/lights/lamp.rs | 120 +++++++++--------- .../zigbee-bridge/src/lights/lamp/property.rs | 52 ++++---- .../zigbee-bridge/src/lights/parse_state.rs | 12 +- 10 files changed, 184 insertions(+), 150 deletions(-) create mode 100644 crates/zigbee-bridge/src/device.rs diff --git a/crates/zigbee-bridge/src/device.rs b/crates/zigbee-bridge/src/device.rs new file mode 100644 index 00000000..043956f1 --- /dev/null +++ b/crates/zigbee-bridge/src/device.rs @@ -0,0 +1,37 @@ +use std::collections::HashMap; +use std::fmt::Debug; + +use crate::{lights::lamp::{property::{LampProperty, LampPropertyDiscriminants}, Lamp}, LIGHT_MODELS}; + +pub(crate) trait Device: Sync + Send + Debug { + fn new(name: &str) -> Self + where + Self: Sized; + + fn clone_dyn(&self) -> Box; + + fn apply(&mut self, change: LampProperty); + fn changes_relative_to(&self, other: &Box) -> Vec; + fn all_set_properties( + &self, + ) -> HashMap; + + fn needs_merged_payloads(&self) -> bool; + fn is_online(&self) -> bool; +} + +impl Clone for Box { + fn clone(&self) -> Self { + self.clone_dyn() + } +} + +pub(crate) fn init_states() -> HashMap> { + let mut states = HashMap::new(); + for (light_name, _) in LIGHT_MODELS { + let device: Box = Box::new(Lamp::new(light_name)); + states.insert(light_name.to_owned(), device); + + } + states +} diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 33b8ac71..e3162f25 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -7,6 +7,7 @@ use lights::Model; pub mod lights; +mod device; const MQTT_PORT: u16 = 1883; const LIGHT_MODELS: [(&str, Model); 16] = [ diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs index 12de0039..fbbb2cca 100644 --- a/crates/zigbee-bridge/src/lights.rs +++ b/crates/zigbee-bridge/src/lights.rs @@ -8,12 +8,12 @@ pub(crate) use lamp::Model; mod cached_bridge; mod conversion; -mod lamp; +pub(crate) mod lamp; mod parse_state; #[derive(Debug, Clone)] pub struct Controller { - change_sender: mpsc::UnboundedSender<(String, lamp::Property)>, + change_sender: mpsc::UnboundedSender<(String, lamp::LampProperty)>, } impl Controller { @@ -30,13 +30,13 @@ impl Controller { pub fn set_on(&self, friendly_name: &str) { self.change_sender - .send((friendly_name.to_string(), lamp::Property::On(true))) + .send((friendly_name.to_string(), lamp::LampProperty::On(true))) .expect("Sender should never be dropped"); } pub fn set_off(&self, friendly_name: &str) { self.change_sender - .send((friendly_name.to_string(), lamp::Property::On(false))) + .send((friendly_name.to_string(), lamp::LampProperty::On(false))) .expect("Sender should never be dropped"); } @@ -45,7 +45,7 @@ impl Controller { self.change_sender .send(( friendly_name.to_string(), - lamp::Property::Brightness(brightness), + lamp::LampProperty::Brightness(brightness), )) .expect("Sender should never be dropped"); } @@ -54,14 +54,14 @@ impl Controller { self.change_sender .send(( friendly_name.to_string(), - lamp::Property::ColorTempK(kelvin), + lamp::LampProperty::ColorTempK(kelvin), )) .expect("Sender should never be dropped"); } pub fn set_color_xy(&self, friendly_name: &str, xy: (f64, f64)) { self.change_sender - .send((friendly_name.to_string(), lamp::Property::ColorXY(xy))) + .send((friendly_name.to_string(), lamp::LampProperty::ColorXY(xy))) .expect("Sender should never be dropped"); } } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/lights/cached_bridge.rs index 984e49ae..33b9c580 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge.rs @@ -1,11 +1,11 @@ -use std::{collections::HashMap, net::IpAddr, time::Duration}; +use std::{net::IpAddr, time::Duration}; use rumqttc::v5::{AsyncClient, MqttOptions}; use tokio::sync::{mpsc, RwLock}; use tracing::trace; use self::mqtt::Mqtt; -use crate::{lights::lamp, LIGHT_MODELS, MQTT_PORT}; +use crate::{device::init_states, lights::lamp::LampProperty, LIGHT_MODELS, MQTT_PORT}; mod changes; mod mqtt; @@ -20,7 +20,7 @@ const CHANGE_ACCUMULATION_TIME: Duration = Duration::from_millis(100); pub(super) async fn run( mqtt_ip: IpAddr, - change_receiver: mpsc::UnboundedReceiver<(String, lamp::Property)>, + change_receiver: mpsc::UnboundedReceiver<(String, LampProperty)>, ) -> ! { let mut options = MqttOptions::new("ha-lightcontroller", mqtt_ip.to_string(), MQTT_PORT); @@ -29,7 +29,7 @@ pub(super) async fn run( // Keep subscriptions when reconnecting!!!! options.set_clean_start(false); - let known_states = RwLock::new(HashMap::new()); + let known_states = RwLock::new(init_states()); // Reconnecting to broker is handled by Eventloop::poll let channel_capacity = 128; diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs index dabbcf6a..eb8c625d 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs @@ -3,18 +3,19 @@ use std::time::{Duration, Instant}; use tokio::sync::{mpsc, RwLock}; use tokio::time::{sleep, timeout}; -use tracing::{debug, instrument, trace}; +use tracing::{debug, error, instrument, trace}; use super::mqtt::Mqtt; use super::{ CHANGE_ACCUMULATION_TIME, MQTT_MIGHT_BE_DOWN_TIMEOUT, WAIT_FOR_INIT_STATES, }; -use crate::lights::lamp::{self, Lamp}; +use crate::device::Device; +use crate::lights::lamp::LampProperty; pub(super) async fn handle( - mut change_receiver: mpsc::UnboundedReceiver<(String, lamp::Property)>, + mut change_receiver: mpsc::UnboundedReceiver<(String, LampProperty)>, mqtt: &mut Mqtt, - known_states: &RwLock>, + known_states: &RwLock>>, ) -> ! { // Give the initial known states a chance to be fetched sleep(WAIT_FOR_INIT_STATES).await; @@ -65,8 +66,8 @@ pub(super) async fn handle( /// to do so we return Duration::MAX. #[instrument(skip_all)] async fn send_diff_get_timeout( - known_states: &RwLock>, - needed_states: &mut HashMap, + known_states: &RwLock>>, + needed_states: &mut HashMap>, mqtt: &mut Mqtt, ) -> Duration { let known_states = known_states.read().await; @@ -77,17 +78,17 @@ async fn send_diff_get_timeout( let diff = match known_states.get(light_name) { Some(known) => needed.changes_relative_to(known), - None => needed.all_as_changes(), + None => needed.all_set_properties().values().cloned().collect(), }; let is_online = match known_states.get(light_name) { - Some(known) => known.is_online, + Some(known) => known.is_online(), // we assume the lamp is online so that init messages get sent None => true, }; if is_online { - let merged_payloads = needed.is_hue_lamp(); + let merged_payloads = needed.needs_merged_payloads(); let _ = mqtt .send_diff_where_due(light_name, merged_payloads, &diff) .await; @@ -108,21 +109,24 @@ async fn send_diff_get_timeout( #[instrument(skip_all)] async fn apply_change_to_needed( light_name: String, - change: lamp::Property, - known_states: &RwLock>, - needed_states: &mut HashMap, + change: LampProperty, + known_states: &RwLock>>, + needed_states: &mut HashMap>, ) { let known_states = known_states.read().await; - let known = known_states - .get(&light_name) - .map(|l| l.to_owned()) - .unwrap_or_else(|| Lamp::new(&light_name)); + let Some(known) = known_states.get(&light_name) else { + error!( + "Unknown device name {light_name}, not applying change {change:?}!" + ); + return; + }; + let mut needed = match needed_states.get(&light_name) { Some(needed) => needed.clone(), - None => known, + None => known.clone(), }; needed.apply(change); - needed_states.insert(light_name, needed); + needed_states.insert(light_name, needed.clone()); } diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs index a2314756..0fd04156 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs @@ -6,7 +6,7 @@ use rumqttc::v5::{AsyncClient, ClientError}; use serde_json::json; use tracing::{trace, warn}; -use crate::lights::lamp; +use crate::lights::lamp::{self, LampPropertyDiscriminants}; use super::TIME_IT_TAKES_TO_APPLY_CHANGE; @@ -15,7 +15,7 @@ pub(super) struct Mqtt { // TODO: extract into SendTracker struct? last_sent: HashMap< String, - HashMap, + HashMap, >, } @@ -47,7 +47,7 @@ impl Mqtt { pub(super) fn next_deadline( &self, light_name: &str, - diff: &[lamp::Property], + diff: &[lamp::LampProperty], ) -> Option { diff.into_iter() .map(|change| self.change_next_due(light_name, &change)) @@ -57,7 +57,7 @@ impl Mqtt { fn change_next_due( &self, light_name: &str, - change: &lamp::Property, + change: &lamp::LampProperty, ) -> Instant { let Some(light_send_record) = self.last_sent.get(light_name) else { // lamp has never been sent before @@ -84,7 +84,7 @@ impl Mqtt { *sent_at + TIME_IT_TAKES_TO_APPLY_CHANGE } - fn is_due(&self, light_name: &str, change: &lamp::Property) -> bool { + fn is_due(&self, light_name: &str, change: &lamp::LampProperty) -> bool { let deadline = self.change_next_due(light_name, change); deadline < Instant::now() } @@ -93,7 +93,7 @@ impl Mqtt { &mut self, light_name: &str, merged_payloads: bool, - diff: &[lamp::Property], + diff: &[lamp::LampProperty], ) -> Result<(), ClientError> { let mut due_changes = Vec::new(); @@ -170,7 +170,7 @@ impl Mqtt { } } -fn merge_payloads(mut changes: Vec<&lamp::Property>) -> serde_json::Value { +fn merge_payloads(mut changes: Vec<&lamp::LampProperty>) -> serde_json::Value { let payload = changes .iter_mut() .map(|c| c.payload()) diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs index c7fb3ec8..869af00a 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs @@ -6,14 +6,15 @@ use regex::Regex; use rumqttc::v5::{Event, EventLoop, Incoming}; use serde_json::Value; use tokio::{sync::RwLock, time::sleep}; -use tracing::{instrument, trace, warn}; +use tracing::{error, instrument, trace, warn}; -use crate::lights::lamp::{self, Lamp}; +use crate::device::Device; +use crate::lights::lamp::{self, LampProperty}; use crate::lights::parse_state::parse_lamp_properties; pub(super) async fn poll_mqtt( mut eventloop: EventLoop, - known_states: &RwLock>, + known_states: &RwLock>>, ) -> ! { loop { let message = match eventloop.poll().await { @@ -44,28 +45,27 @@ pub(super) async fn poll_mqtt( } async fn update_state( - known_states: &RwLock>, + known_states: &RwLock>>, light_name: &str, - new: Vec, + new: Vec, ) { let mut known_states = known_states.write().await; - let current_lamp = known_states - .entry(light_name.to_owned()) - .or_insert_with(|| Lamp::new(light_name)); + let Some(current_lamp) = known_states.get_mut(light_name) else { + error!("Trying to update state for unknown device: {light_name}, ignoring!"); + return; + }; for property in new { if light_name == "small_bedroom:piano" { match property { - lamp::Property::Brightness(bri) => { + LampProperty::Brightness(bri) => { warn!("ZB received piano brightness change: {bri}"); } - lamp::Property::ColorXY(xy) => { + LampProperty::ColorXY(xy) => { warn!("ZB received piano color change: {xy:?}"); } - lamp::Property::Online(new_online) => { - if new_online != current_lamp.is_online { - warn!( - "ZB received piano online change: {new_online}" - ); + LampProperty::Online(new_online) => { + if new_online != current_lamp.is_online() { + warn!("ZB received piano online change: {new_online}"); } } _ => (), @@ -145,7 +145,7 @@ fn parse_bridge_event( _ => return Ok(Message::Other), }; - let update = (light_name, vec![lamp::Property::Online(is_online)]); + let update = (light_name, vec![lamp::LampProperty::Online(is_online)]); Ok(Message::StateUpdate(update)) } @@ -168,7 +168,7 @@ fn parse_log_message( if level == "error" { if let Some(caps) = regex.captures(message) { let light_name = caps[1].to_string(); - let update = (light_name, vec![lamp::Property::Online(false)]); + let update = (light_name, vec![lamp::LampProperty::Online(false)]); return Ok(Message::StateUpdate(update)); } } @@ -178,6 +178,6 @@ fn parse_log_message( #[derive(Debug)] enum Message { - StateUpdate((String, Vec)), + StateUpdate((String, Vec)), Other, } diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lights/lamp.rs index f645d038..77463643 100644 --- a/crates/zigbee-bridge/src/lights/lamp.rs +++ b/crates/zigbee-bridge/src/lights/lamp.rs @@ -1,13 +1,15 @@ -pub(crate) use model::Model; -pub(super) use property::{Property, PropertyDiscriminants}; +use std::collections::HashMap; -use self::property::{bri_is_close, color_is_close}; -use tracing::{error, instrument}; +use strum::IntoEnumIterator; +use tracing::instrument; use super::conversion::temp_to_xy; +use crate::device::Device; +pub(crate) use model::Model; +pub(super) use property::{LampProperty, LampPropertyDiscriminants}; mod model; -mod property; +pub(crate) mod property; #[derive(Clone, Copy, Debug)] enum Color { @@ -23,7 +25,7 @@ impl Color { // TODO: some way to enforce read-only (thus known-updatable-only) fields? #[derive(Clone, Debug)] -pub(super) struct Lamp { +pub(crate) struct Lamp { model: Model, pub(super) is_online: bool, brightness: Option, @@ -32,8 +34,8 @@ pub(super) struct Lamp { color_temp_startup: property::ColorTempStartup, } -impl Lamp { - pub(super) fn new(name: &str) -> Self { +impl Device for Lamp { + fn new(name: &str) -> Self { Self { model: Model::from_light(name), // we assume the lamp is online so that init messages get sent @@ -45,65 +47,52 @@ impl Lamp { } } - pub(super) fn is_hue_lamp(&self) -> bool { + fn clone_dyn(&self) -> Box { + Box::new(self.clone()) + } + + fn needs_merged_payloads(&self) -> bool { self.model.is_hue() } + fn is_online(&self) -> bool { + self.is_online + } + #[instrument] - pub(super) fn changes_relative_to(&self, other: &Self) -> Vec { + fn changes_relative_to( + &self, + other: &Box, + ) -> Vec { let mut res = Vec::new(); - // Ignore model and is_online, because they are read-only + let self_properties = self.all_set_properties(); + let other_properties = other.all_set_properties(); - if let Some(bri_self) = self.brightness { - if other - .brightness - .is_none_or(|bri_other| !bri_is_close(bri_other, bri_self)) - { - res.push(Property::Brightness(bri_self)); - } - } + for property in LampProperty::iter() { + let self_prop = self_properties.get(&property.into()); + let other_prop = other_properties.get(&property.into()); - if let Some(color_self) = self.color { - let log_err = |err| { - error!("Comparing incompatible lamp states, defaulting to same\nSelf: {self:?}\nOther: {other:?}\nErr: {err}"); - }; - - let color_is_close = match other.color { - None => false, - Some(color_other) => color_is_close(color_other, color_self) - .unwrap_or_else(|err| { - log_err(err); - true - }), - }; - - if !color_is_close { - match color_self { - Color::XY(xy) => res.push(Property::ColorXY(xy)), - Color::TempK(temp) => res.push(Property::ColorTempK(temp)), - } + // Ignore model (not a prop) and online, because they are read-only + if let Some(LampProperty::Online(_)) = self_prop { + continue; } - } - if let Some(on_self) = self.is_on { - if other.is_on.is_none_or(|on_other| on_other != on_self) { - res.push(Property::On(on_self)); + if let Some(self_prop) = self_prop { + if other_prop.is_none_or(|other_prop| self_prop != other_prop) { + res.push(*self_prop); + } } } - if self.color_temp_startup != other.color_temp_startup { - res.push(Property::ColorTempStartup(self.color_temp_startup)); - } - res } - pub(super) fn apply(&mut self, change: Property) { + fn apply(&mut self, change: LampProperty) { match change { - Property::On(is_on) => self.is_on = Some(is_on), - Property::Brightness(bri) => self.brightness = Some(bri), - Property::ColorTempK(temp) => { + LampProperty::On(is_on) => self.is_on = Some(is_on), + LampProperty::Brightness(bri) => self.brightness = Some(bri), + LampProperty::ColorTempK(temp) => { // if we know the model, we know how to apply temp if self.model.supports_xy() { self.color = Some(Color::xy_from_temp(temp)); @@ -113,37 +102,46 @@ impl Lamp { self.color = Some(Color::TempK(temp)) } } - Property::ColorXY(xy) => { + LampProperty::ColorXY(xy) => { // don't apply xy to unknown or non-color lamp if self.model.supports_xy() { self.color = Some(Color::XY(xy)) } } - Property::ColorTempStartup(behaviour) => { + LampProperty::ColorTempStartup(behaviour) => { self.color_temp_startup = behaviour } - Property::Online(is_online) => self.is_online = is_online, + LampProperty::Online(is_online) => self.is_online = is_online, } } - pub(crate) fn all_as_changes(&self) -> Vec { - let mut list = Vec::new(); + fn all_set_properties( + &self, + ) -> HashMap { + let mut properties = HashMap::new(); + + let mut insert_prop = + |prop: LampProperty| properties.insert(prop.into(), prop); // Ignore model and is_online, because they are read-only if let Some(val) = (&self).brightness { - list.push(Property::Brightness(val)); + insert_prop(LampProperty::Brightness(val)); } if let Some(val) = &self.color { match val { - Color::XY(xy) => list.push(Property::ColorXY(*xy)), - Color::TempK(temp) => list.push(Property::ColorTempK(*temp)), + Color::XY(xy) => { + insert_prop(LampProperty::ColorXY(*xy)); + } + Color::TempK(temp) => { + insert_prop(LampProperty::ColorTempK(*temp)); + } } } if let Some(val) = (&self).is_on { - list.push(Property::On(val)); + insert_prop(LampProperty::On(val)); } - list.push(Property::ColorTempStartup((&self).color_temp_startup)); - list + insert_prop(LampProperty::ColorTempStartup((&self).color_temp_startup)); + properties } } diff --git a/crates/zigbee-bridge/src/lights/lamp/property.rs b/crates/zigbee-bridge/src/lights/lamp/property.rs index 68f9313e..2f4de6bc 100644 --- a/crates/zigbee-bridge/src/lights/lamp/property.rs +++ b/crates/zigbee-bridge/src/lights/lamp/property.rs @@ -1,8 +1,7 @@ use serde_json::json; -use strum::EnumDiscriminants; +use strum::{EnumDiscriminants, EnumIter}; use tracing::error; -use super::Color; use crate::lights::conversion::{denormalize, kelvin_to_mired}; #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] @@ -11,9 +10,9 @@ pub(crate) enum ColorTempStartup { Previous, } -#[derive(Debug, EnumDiscriminants, Clone, Copy)] +#[derive(Debug, EnumDiscriminants, EnumIter, Clone, Copy)] #[strum_discriminants(derive(Hash))] -pub(crate) enum Property { +pub(crate) enum LampProperty { Online(bool), Brightness(f64), ColorTempK(usize), @@ -22,48 +21,51 @@ pub(crate) enum Property { ColorTempStartup(ColorTempStartup), } -impl PartialEq for Property { +impl PartialEq for LampProperty { fn eq(&self, other: &Self) -> bool { match (self, other) { - (Property::Brightness(a), Property::Brightness(b)) => { + (LampProperty::Brightness(a), LampProperty::Brightness(b)) => { bri_is_close(*a, *b) } - (Property::ColorTempK(a), Property::ColorTempK(b)) => { + (LampProperty::ColorTempK(a), LampProperty::ColorTempK(b)) => { temp_is_close(*a, *b) } - (Property::ColorXY(a), Property::ColorXY(b)) => xy_is_close(*a, *b), - (Property::On(a), Property::On(b)) => a == b, - (Property::ColorTempStartup(a), Property::ColorTempStartup(b)) => { - a == b + (LampProperty::ColorXY(a), LampProperty::ColorXY(b)) => { + xy_is_close(*a, *b) } + (LampProperty::On(a), LampProperty::On(b)) => a == b, + ( + LampProperty::ColorTempStartup(a), + LampProperty::ColorTempStartup(b), + ) => a == b, // we never need to update this, thus we always consider it the same - (Property::Online(_), Property::Online(_)) => true, + (LampProperty::Online(_), LampProperty::Online(_)) => true, (_, _) => false, } } } -impl Eq for Property {} +impl Eq for LampProperty {} -impl Property { +impl LampProperty { pub(crate) fn payload(&self) -> serde_json::Value { match *self { - Property::Brightness(bri) => { + LampProperty::Brightness(bri) => { json!({ "brightness": denormalize(bri) }) } - Property::ColorTempK(k) => { + LampProperty::ColorTempK(k) => { json!({ "color_temp": kelvin_to_mired(k) }) } - Property::ColorXY((x, y)) => { + LampProperty::ColorXY((x, y)) => { json!({ "color": {"x": x, "y": y} }) } - Property::On(lamp_on) if lamp_on => json!({"state": "ON"}), - Property::On(_) => json!({"state": "OFF"}), - Property::ColorTempStartup(ColorTempStartup::Previous) => { + LampProperty::On(lamp_on) if lamp_on => json!({"state": "ON"}), + LampProperty::On(_) => json!({"state": "OFF"}), + LampProperty::ColorTempStartup(ColorTempStartup::Previous) => { json!({"color_temp_startup": "previous"}) } // read-only, shouldn't be called, safe default - Property::Online(_) => { + LampProperty::Online(_) => { error!("Tried to convert Online to payload"); json!({"state": ""}) } @@ -75,14 +77,6 @@ pub(super) fn bri_is_close(a: f64, b: f64) -> bool { (a - b).abs() < 1. / 250. } -pub(super) fn color_is_close(a: Color, b: Color) -> Result { - match (a, b) { - (Color::XY(a), Color::XY(b)) => Ok(xy_is_close(a, b)), - (Color::TempK(a), Color::TempK(b)) => Ok(temp_is_close(a, b)), - (_, _) => Err("Comparing XY and Temp".to_owned()), - } -} - fn temp_is_close(a: usize, b: usize) -> bool { a.abs_diff(b) < 50 } diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/lights/parse_state.rs index f2c2dce1..c54bd5af 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/lights/parse_state.rs @@ -8,7 +8,7 @@ use super::lamp; pub(super) fn parse_lamp_properties( bytes: &[u8], -) -> color_eyre::Result> { +) -> color_eyre::Result> { let mut list = Vec::new(); let json: Value = @@ -23,7 +23,7 @@ pub(super) fn parse_lamp_properties( .transpose()? .map(mired_to_kelvin) { - list.push(lamp::Property::ColorTempK(kelvin)); + list.push(lamp::LampProperty::ColorTempK(kelvin)); } if let Some(xy) = map @@ -40,7 +40,7 @@ pub(super) fn parse_lamp_properties( }) .transpose()? { - list.push(lamp::Property::ColorXY(xy)); + list.push(lamp::LampProperty::ColorXY(xy)); } if let Some(brightness) = map @@ -49,7 +49,7 @@ pub(super) fn parse_lamp_properties( .transpose()? .map(normalize) { - list.push(lamp::Property::Brightness(brightness)); + list.push(lamp::LampProperty::Brightness(brightness)); } if let Some(on) = map @@ -65,11 +65,11 @@ pub(super) fn parse_lamp_properties( }) .transpose()? { - list.push(lamp::Property::On(on)); + list.push(lamp::LampProperty::On(on)); } // we have just received a state message, so the lamp must be online - list.push(lamp::Property::Online(true)); + list.push(lamp::LampProperty::Online(true)); Ok(list) } From 9cf43c182e3f19bd1c3051c9c3c2a17d4a8c2aef Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Wed, 11 Dec 2024 14:32:23 +0100 Subject: [PATCH 494/687] Move contents of lights mod to lib to reduce nesting --- .../src/{lights => }/cached_bridge.rs | 2 +- .../src/{lights => }/cached_bridge/changes.rs | 2 +- .../src/{lights => }/cached_bridge/mqtt.rs | 2 +- .../src/{lights => }/cached_bridge/poll.rs | 4 +- .../src/{lights => }/conversion.rs | 0 crates/zigbee-bridge/src/device.rs | 12 ++- crates/zigbee-bridge/src/{lights => }/lamp.rs | 0 .../src/{lights => }/lamp/model.rs | 0 .../src/{lights => }/lamp/property.rs | 2 +- crates/zigbee-bridge/src/lib.rs | 90 ++++++++++++------- crates/zigbee-bridge/src/lights.rs | 67 -------------- .../src/{lights => }/parse_state.rs | 2 +- crates/zigbee-bridge/src/tests.rs | 35 ++++++++ 13 files changed, 107 insertions(+), 111 deletions(-) rename crates/zigbee-bridge/src/{lights => }/cached_bridge.rs (95%) rename crates/zigbee-bridge/src/{lights => }/cached_bridge/changes.rs (99%) rename crates/zigbee-bridge/src/{lights => }/cached_bridge/mqtt.rs (98%) rename crates/zigbee-bridge/src/{lights => }/cached_bridge/poll.rs (98%) rename crates/zigbee-bridge/src/{lights => }/conversion.rs (100%) rename crates/zigbee-bridge/src/{lights => }/lamp.rs (100%) rename crates/zigbee-bridge/src/{lights => }/lamp/model.rs (100%) rename crates/zigbee-bridge/src/{lights => }/lamp/property.rs (97%) delete mode 100644 crates/zigbee-bridge/src/lights.rs rename crates/zigbee-bridge/src/{lights => }/parse_state.rs (97%) create mode 100644 crates/zigbee-bridge/src/tests.rs diff --git a/crates/zigbee-bridge/src/lights/cached_bridge.rs b/crates/zigbee-bridge/src/cached_bridge.rs similarity index 95% rename from crates/zigbee-bridge/src/lights/cached_bridge.rs rename to crates/zigbee-bridge/src/cached_bridge.rs index 33b9c580..2641733a 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge.rs +++ b/crates/zigbee-bridge/src/cached_bridge.rs @@ -5,7 +5,7 @@ use tokio::sync::{mpsc, RwLock}; use tracing::trace; use self::mqtt::Mqtt; -use crate::{device::init_states, lights::lamp::LampProperty, LIGHT_MODELS, MQTT_PORT}; +use crate::{device::init_states, lamp::LampProperty, LIGHT_MODELS, MQTT_PORT}; mod changes; mod mqtt; diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs b/crates/zigbee-bridge/src/cached_bridge/changes.rs similarity index 99% rename from crates/zigbee-bridge/src/lights/cached_bridge/changes.rs rename to crates/zigbee-bridge/src/cached_bridge/changes.rs index eb8c625d..619537b2 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/cached_bridge/changes.rs @@ -10,7 +10,7 @@ use super::{ CHANGE_ACCUMULATION_TIME, MQTT_MIGHT_BE_DOWN_TIMEOUT, WAIT_FOR_INIT_STATES, }; use crate::device::Device; -use crate::lights::lamp::LampProperty; +use crate::lamp::LampProperty; pub(super) async fn handle( mut change_receiver: mpsc::UnboundedReceiver<(String, LampProperty)>, diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/cached_bridge/mqtt.rs similarity index 98% rename from crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs rename to crates/zigbee-bridge/src/cached_bridge/mqtt.rs index 0fd04156..c333ab43 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/cached_bridge/mqtt.rs @@ -6,7 +6,7 @@ use rumqttc::v5::{AsyncClient, ClientError}; use serde_json::json; use tracing::{trace, warn}; -use crate::lights::lamp::{self, LampPropertyDiscriminants}; +use crate::lamp::{self, LampPropertyDiscriminants}; use super::TIME_IT_TAKES_TO_APPLY_CHANGE; diff --git a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs b/crates/zigbee-bridge/src/cached_bridge/poll.rs similarity index 98% rename from crates/zigbee-bridge/src/lights/cached_bridge/poll.rs rename to crates/zigbee-bridge/src/cached_bridge/poll.rs index 869af00a..968de4e2 100644 --- a/crates/zigbee-bridge/src/lights/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/cached_bridge/poll.rs @@ -9,8 +9,8 @@ use tokio::{sync::RwLock, time::sleep}; use tracing::{error, instrument, trace, warn}; use crate::device::Device; -use crate::lights::lamp::{self, LampProperty}; -use crate::lights::parse_state::parse_lamp_properties; +use crate::lamp::{self, LampProperty}; +use crate::parse_state::parse_lamp_properties; pub(super) async fn poll_mqtt( mut eventloop: EventLoop, diff --git a/crates/zigbee-bridge/src/lights/conversion.rs b/crates/zigbee-bridge/src/conversion.rs similarity index 100% rename from crates/zigbee-bridge/src/lights/conversion.rs rename to crates/zigbee-bridge/src/conversion.rs diff --git a/crates/zigbee-bridge/src/device.rs b/crates/zigbee-bridge/src/device.rs index 043956f1..6311d623 100644 --- a/crates/zigbee-bridge/src/device.rs +++ b/crates/zigbee-bridge/src/device.rs @@ -1,7 +1,13 @@ use std::collections::HashMap; use std::fmt::Debug; -use crate::{lights::lamp::{property::{LampProperty, LampPropertyDiscriminants}, Lamp}, LIGHT_MODELS}; +use crate::{ + lamp::{ + property::{LampProperty, LampPropertyDiscriminants}, + Lamp, + }, + LIGHT_MODELS, +}; pub(crate) trait Device: Sync + Send + Debug { fn new(name: &str) -> Self @@ -11,7 +17,8 @@ pub(crate) trait Device: Sync + Send + Debug { fn clone_dyn(&self) -> Box; fn apply(&mut self, change: LampProperty); - fn changes_relative_to(&self, other: &Box) -> Vec; + fn changes_relative_to(&self, other: &Box) + -> Vec; fn all_set_properties( &self, ) -> HashMap; @@ -31,7 +38,6 @@ pub(crate) fn init_states() -> HashMap> { for (light_name, _) in LIGHT_MODELS { let device: Box = Box::new(Lamp::new(light_name)); states.insert(light_name.to_owned(), device); - } states } diff --git a/crates/zigbee-bridge/src/lights/lamp.rs b/crates/zigbee-bridge/src/lamp.rs similarity index 100% rename from crates/zigbee-bridge/src/lights/lamp.rs rename to crates/zigbee-bridge/src/lamp.rs diff --git a/crates/zigbee-bridge/src/lights/lamp/model.rs b/crates/zigbee-bridge/src/lamp/model.rs similarity index 100% rename from crates/zigbee-bridge/src/lights/lamp/model.rs rename to crates/zigbee-bridge/src/lamp/model.rs diff --git a/crates/zigbee-bridge/src/lights/lamp/property.rs b/crates/zigbee-bridge/src/lamp/property.rs similarity index 97% rename from crates/zigbee-bridge/src/lights/lamp/property.rs rename to crates/zigbee-bridge/src/lamp/property.rs index 2f4de6bc..199416c7 100644 --- a/crates/zigbee-bridge/src/lights/lamp/property.rs +++ b/crates/zigbee-bridge/src/lamp/property.rs @@ -2,7 +2,7 @@ use serde_json::json; use strum::{EnumDiscriminants, EnumIter}; use tracing::error; -use crate::lights::conversion::{denormalize, kelvin_to_mired}; +use crate::conversion::{denormalize, kelvin_to_mired}; #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] pub(crate) enum ColorTempStartup { diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index e3162f25..f67ed72b 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -1,13 +1,18 @@ -// hue_power_on_behavior: "recover" / power_on_behavior: "previous" -// color_temp_startup -// color_xy -// Set to on, off after 30s -// on_time: 30, off_wait_time: 30 +#![allow(clippy::missing_panics_doc)] +use std::net::IpAddr; -use lights::Model; +use tokio::sync::mpsc; +use tracing::trace; -pub mod lights; +pub(crate) use lamp::Model; + +mod cached_bridge; +mod conversion; mod device; +pub(crate) mod lamp; +mod parse_state; +#[cfg(test)] +mod tests; const MQTT_PORT: u16 = 1883; const LIGHT_MODELS: [(&str, Model); 16] = [ @@ -29,40 +34,57 @@ const LIGHT_MODELS: [(&str, Model); 16] = [ ("toilet:ceiling", Model::HueGen4), ]; -#[cfg(test)] -mod tests { - use crate::lights::Controller; - use std::time::Duration; - - #[ignore] - #[tokio::test] - async fn change_fridge_light() { - std::env::set_var("RUST_LOG", "brain=trace,zigbee_bridge=trace,info"); - let controller = - Controller::start_bridge("192.168.1.43".parse().unwrap()); - let light = "kitchen:fridge"; +#[derive(Debug, Clone)] +pub struct Controller { + change_sender: mpsc::UnboundedSender<(String, lamp::LampProperty)>, +} - println!("Setting to on, 2200"); - controller.set_on(light); - controller.set_color_temp(light, 2200); +impl Controller { + #[must_use] + pub fn start_bridge(mqtt_ip: IpAddr) -> Self { + let (change_sender, change_receiver) = mpsc::unbounded_channel(); - tokio::time::sleep(Duration::from_secs(1)).await; + let run_bridge = cached_bridge::run(mqtt_ip, change_receiver); + trace!("Spawning zigbee bridge task"); + tokio::task::spawn(run_bridge); - println!("Turning off"); - controller.set_off(light); + Self { change_sender } + } - tokio::time::sleep(Duration::from_secs(1)).await; + pub fn set_on(&self, friendly_name: &str) { + self.change_sender + .send((friendly_name.to_string(), lamp::LampProperty::On(true))) + .expect("Sender should never be dropped"); + } - println!("Turning on to 4000"); - controller.set_on(light); - controller.set_color_temp(light, 4000); + pub fn set_off(&self, friendly_name: &str) { + self.change_sender + .send((friendly_name.to_string(), lamp::LampProperty::On(false))) + .expect("Sender should never be dropped"); + } - tokio::time::sleep(Duration::from_secs(1)).await; + /// Brightness from 0 to 1 + pub fn set_brightness(&self, friendly_name: &str, brightness: f64) { + self.change_sender + .send(( + friendly_name.to_string(), + lamp::LampProperty::Brightness(brightness), + )) + .expect("Sender should never be dropped"); + } - println!("Setting bri to 1.0"); - controller.set_brightness(light, 1.0); + pub fn set_color_temp(&self, friendly_name: &str, kelvin: usize) { + self.change_sender + .send(( + friendly_name.to_string(), + lamp::LampProperty::ColorTempK(kelvin), + )) + .expect("Sender should never be dropped"); + } - let () = std::future::pending().await; - unreachable!(); + pub fn set_color_xy(&self, friendly_name: &str, xy: (f64, f64)) { + self.change_sender + .send((friendly_name.to_string(), lamp::LampProperty::ColorXY(xy))) + .expect("Sender should never be dropped"); } } diff --git a/crates/zigbee-bridge/src/lights.rs b/crates/zigbee-bridge/src/lights.rs deleted file mode 100644 index fbbb2cca..00000000 --- a/crates/zigbee-bridge/src/lights.rs +++ /dev/null @@ -1,67 +0,0 @@ -#![allow(clippy::missing_panics_doc)] -use std::net::IpAddr; - -use tokio::sync::mpsc; -use tracing::trace; - -pub(crate) use lamp::Model; - -mod cached_bridge; -mod conversion; -pub(crate) mod lamp; -mod parse_state; - -#[derive(Debug, Clone)] -pub struct Controller { - change_sender: mpsc::UnboundedSender<(String, lamp::LampProperty)>, -} - -impl Controller { - #[must_use] - pub fn start_bridge(mqtt_ip: IpAddr) -> Self { - let (change_sender, change_receiver) = mpsc::unbounded_channel(); - - let run_bridge = cached_bridge::run(mqtt_ip, change_receiver); - trace!("Spawning zigbee bridge task"); - tokio::task::spawn(run_bridge); - - Self { change_sender } - } - - pub fn set_on(&self, friendly_name: &str) { - self.change_sender - .send((friendly_name.to_string(), lamp::LampProperty::On(true))) - .expect("Sender should never be dropped"); - } - - pub fn set_off(&self, friendly_name: &str) { - self.change_sender - .send((friendly_name.to_string(), lamp::LampProperty::On(false))) - .expect("Sender should never be dropped"); - } - - /// Brightness from 0 to 1 - pub fn set_brightness(&self, friendly_name: &str, brightness: f64) { - self.change_sender - .send(( - friendly_name.to_string(), - lamp::LampProperty::Brightness(brightness), - )) - .expect("Sender should never be dropped"); - } - - pub fn set_color_temp(&self, friendly_name: &str, kelvin: usize) { - self.change_sender - .send(( - friendly_name.to_string(), - lamp::LampProperty::ColorTempK(kelvin), - )) - .expect("Sender should never be dropped"); - } - - pub fn set_color_xy(&self, friendly_name: &str, xy: (f64, f64)) { - self.change_sender - .send((friendly_name.to_string(), lamp::LampProperty::ColorXY(xy))) - .expect("Sender should never be dropped"); - } -} diff --git a/crates/zigbee-bridge/src/lights/parse_state.rs b/crates/zigbee-bridge/src/parse_state.rs similarity index 97% rename from crates/zigbee-bridge/src/lights/parse_state.rs rename to crates/zigbee-bridge/src/parse_state.rs index c54bd5af..b6ad946d 100644 --- a/crates/zigbee-bridge/src/lights/parse_state.rs +++ b/crates/zigbee-bridge/src/parse_state.rs @@ -2,7 +2,7 @@ use color_eyre::eyre::{bail, Context, OptionExt, Report}; use color_eyre::Section; use serde_json::Value; -use crate::lights::conversion::{mired_to_kelvin, normalize}; +use crate::conversion::{mired_to_kelvin, normalize}; use super::lamp; diff --git a/crates/zigbee-bridge/src/tests.rs b/crates/zigbee-bridge/src/tests.rs new file mode 100644 index 00000000..fe7f74c8 --- /dev/null +++ b/crates/zigbee-bridge/src/tests.rs @@ -0,0 +1,35 @@ +use crate::Controller; +use std::time::Duration; + +#[ignore] +#[tokio::test] +async fn change_fridge_light() { + std::env::set_var("RUST_LOG", "brain=trace,zigbee_bridge=trace,info"); + let controller = + Controller::start_bridge("192.168.1.43".parse().unwrap()); + let light = "kitchen:fridge"; + + println!("Setting to on, 2200"); + controller.set_on(light); + controller.set_color_temp(light, 2200); + + tokio::time::sleep(Duration::from_secs(1)).await; + + println!("Turning off"); + controller.set_off(light); + + tokio::time::sleep(Duration::from_secs(1)).await; + + println!("Turning on to 4000"); + controller.set_on(light); + controller.set_color_temp(light, 4000); + + tokio::time::sleep(Duration::from_secs(1)).await; + + println!("Setting bri to 1.0"); + controller.set_brightness(light, 1.0); + + let () = std::future::pending().await; + unreachable!(); +} + From a02070034564f50ba648a3236fd04ccd152adfbb Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Wed, 11 Dec 2024 14:51:41 +0100 Subject: [PATCH 495/687] Rename light to device where appropriate --- .../src/cached_bridge/changes.rs | 38 +++++++-------- .../zigbee-bridge/src/cached_bridge/mqtt.rs | 46 +++++++++---------- .../zigbee-bridge/src/cached_bridge/poll.rs | 26 +++++------ crates/zigbee-bridge/src/lib.rs | 28 +++++------ crates/zigbee-bridge/src/parse_state.rs | 15 +++--- 5 files changed, 77 insertions(+), 76 deletions(-) diff --git a/crates/zigbee-bridge/src/cached_bridge/changes.rs b/crates/zigbee-bridge/src/cached_bridge/changes.rs index 619537b2..9b656ab5 100644 --- a/crates/zigbee-bridge/src/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/cached_bridge/changes.rs @@ -29,12 +29,12 @@ pub(super) async fn handle( // On change, update needed, but only actually send the changes // after a timeout Ok(update) => { - let (light_name, change) = + let (device_name, change) = update.expect("Channel should never close"); - trace!("Received change: {change:?} for lamp {light_name}"); + trace!("Received change: {change:?} for device {device_name}"); apply_change_to_needed( - light_name, + device_name, change, known_states, &mut needed_states, @@ -59,7 +59,7 @@ pub(super) async fn handle( } } -/// Might not be done in case a light property in needed does not match known +/// Might not be done in case a device property in needed does not match known /// however has recently been set/send. Needs a recheck in the near future to /// make sure the set/send takes effect. We do not send it again now as that /// would be a little spammy. Returns when we need to recheck. If we do not need @@ -71,35 +71,35 @@ async fn send_diff_get_timeout( mqtt: &mut Mqtt, ) -> Duration { let known_states = known_states.read().await; - let mut light_deadlines = Vec::new(); + let mut device_deadlines = Vec::new(); - for (light_name, needed) in needed_states { - tracing::Span::current().record("light_name", light_name); + for (device_name, needed) in needed_states { + tracing::Span::current().record("device_name", device_name); - let diff = match known_states.get(light_name) { + let diff = match known_states.get(device_name) { Some(known) => needed.changes_relative_to(known), None => needed.all_set_properties().values().cloned().collect(), }; - let is_online = match known_states.get(light_name) { + let is_online = match known_states.get(device_name) { Some(known) => known.is_online(), - // we assume the lamp is online so that init messages get sent + // we assume the device is online so that init messages get sent None => true, }; if is_online { let merged_payloads = needed.needs_merged_payloads(); let _ = mqtt - .send_diff_where_due(light_name, merged_payloads, &diff) + .send_diff_where_due(device_name, merged_payloads, &diff) .await; } - if let Some(deadline) = mqtt.next_deadline(light_name, &diff) { - light_deadlines.push(deadline); + if let Some(deadline) = mqtt.next_deadline(device_name, &diff) { + device_deadlines.push(deadline); } } - light_deadlines + device_deadlines .into_iter() .min() .map(|deadline| deadline.saturating_duration_since(Instant::now())) @@ -108,25 +108,25 @@ async fn send_diff_get_timeout( #[instrument(skip_all)] async fn apply_change_to_needed( - light_name: String, + device_name: String, change: LampProperty, known_states: &RwLock>>, needed_states: &mut HashMap>, ) { let known_states = known_states.read().await; - let Some(known) = known_states.get(&light_name) else { + let Some(known) = known_states.get(&device_name) else { error!( - "Unknown device name {light_name}, not applying change {change:?}!" + "Unknown device name {device_name}, not applying change {change:?}!" ); return; }; - let mut needed = match needed_states.get(&light_name) { + let mut needed = match needed_states.get(&device_name) { Some(needed) => needed.clone(), None => known.clone(), }; needed.apply(change); - needed_states.insert(light_name, needed.clone()); + needed_states.insert(device_name, needed.clone()); } diff --git a/crates/zigbee-bridge/src/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/cached_bridge/mqtt.rs index c333ab43..0ac82f1e 100644 --- a/crates/zigbee-bridge/src/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/cached_bridge/mqtt.rs @@ -6,7 +6,7 @@ use rumqttc::v5::{AsyncClient, ClientError}; use serde_json::json; use tracing::{trace, warn}; -use crate::lamp::{self, LampPropertyDiscriminants}; +use crate::lamp::{LampProperty, LampPropertyDiscriminants}; use super::TIME_IT_TAKES_TO_APPLY_CHANGE; @@ -15,7 +15,7 @@ pub(super) struct Mqtt { // TODO: extract into SendTracker struct? last_sent: HashMap< String, - HashMap, + HashMap, >, } @@ -33,12 +33,12 @@ impl Mqtt { ) -> Result<(), ClientError> { // Its okay for messages to arrive twice or more. MQTT guarantees // ordering and we only do something if the cached bridge indicates we - // need to so light states arriving twice is not an issue. + // need to so device states arriving twice is not an issue. self.client.subscribe(topic, QoS::AtLeastOnce).await } pub(super) async fn request_state(&self, name: &str) { - trace!("Requesting state for light {name}"); + trace!("Requesting state for device {name}"); let payload = json!({"state": ""}); self.get(name, payload.to_string()).await.unwrap(); @@ -46,26 +46,26 @@ impl Mqtt { pub(super) fn next_deadline( &self, - light_name: &str, - diff: &[lamp::LampProperty], + device_name: &str, + diff: &[LampProperty], ) -> Option { diff.into_iter() - .map(|change| self.change_next_due(light_name, &change)) + .map(|change| self.change_next_due(device_name, &change)) .min() } fn change_next_due( &self, - light_name: &str, - change: &lamp::LampProperty, + device_name: &str, + change: &LampProperty, ) -> Instant { - let Some(light_send_record) = self.last_sent.get(light_name) else { + let Some(device_send_record) = self.last_sent.get(device_name) else { // lamp has never been sent before return Instant::now(); }; let Some((sent_at, prev_change)) = - light_send_record.get(&change.into()) + device_send_record.get(&change.into()) else { // property has never been sent before return Instant::now(); @@ -84,26 +84,26 @@ impl Mqtt { *sent_at + TIME_IT_TAKES_TO_APPLY_CHANGE } - fn is_due(&self, light_name: &str, change: &lamp::LampProperty) -> bool { - let deadline = self.change_next_due(light_name, change); + fn is_due(&self, device_name: &str, change: &LampProperty) -> bool { + let deadline = self.change_next_due(device_name, change); deadline < Instant::now() } pub(super) async fn send_diff_where_due( &mut self, - light_name: &str, + device_name: &str, merged_payloads: bool, - diff: &[lamp::LampProperty], + diff: &[LampProperty], ) -> Result<(), ClientError> { let mut due_changes = Vec::new(); for change in diff { - if self.is_due(&light_name, change) { + if self.is_due(&device_name, change) { due_changes.push(change); - let light_send_record = - self.last_sent.entry(light_name.to_owned()).or_default(); - light_send_record + let device_send_record = + self.last_sent.entry(device_name.to_owned()).or_default(); + device_send_record .insert(change.into(), (Instant::now(), *change)); } } @@ -111,10 +111,10 @@ impl Mqtt { if !due_changes.is_empty() { if merged_payloads { let payload = merge_payloads(due_changes); - self.set(&light_name, payload.to_string()).await?; + self.set(&device_name, payload.to_string()).await?; } else { for change in due_changes { - self.set(&light_name, change.payload().to_string()).await?; + self.set(&device_name, change.payload().to_string()).await?; } } } @@ -129,7 +129,7 @@ impl Mqtt { ) -> Result<(), ClientError> { let topic = format!("zigbee2mqtt/{friendly_name}/set"); - trace!("Sending payload {payload} to lamp {friendly_name}"); + trace!("Sending payload {payload} to device {friendly_name}"); self.publish(&topic, payload).await?; Ok(()) } @@ -170,7 +170,7 @@ impl Mqtt { } } -fn merge_payloads(mut changes: Vec<&lamp::LampProperty>) -> serde_json::Value { +fn merge_payloads(mut changes: Vec<&LampProperty>) -> serde_json::Value { let payload = changes .iter_mut() .map(|c| c.payload()) diff --git a/crates/zigbee-bridge/src/cached_bridge/poll.rs b/crates/zigbee-bridge/src/cached_bridge/poll.rs index 968de4e2..6f34ef9d 100644 --- a/crates/zigbee-bridge/src/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/cached_bridge/poll.rs @@ -9,7 +9,7 @@ use tokio::{sync::RwLock, time::sleep}; use tracing::{error, instrument, trace, warn}; use crate::device::Device; -use crate::lamp::{self, LampProperty}; +use crate::lamp::LampProperty; use crate::parse_state::parse_lamp_properties; pub(super) async fn poll_mqtt( @@ -35,8 +35,8 @@ pub(super) async fn poll_mqtt( }; match message { - Message::StateUpdate((light_name, changed_properties)) => { - update_state(known_states, &light_name, changed_properties) + Message::StateUpdate((device_name, changed_properties)) => { + update_state(known_states, &device_name, changed_properties) .await; } Message::Other => (), @@ -46,16 +46,16 @@ pub(super) async fn poll_mqtt( async fn update_state( known_states: &RwLock>>, - light_name: &str, + device_name: &str, new: Vec, ) { let mut known_states = known_states.write().await; - let Some(current_lamp) = known_states.get_mut(light_name) else { - error!("Trying to update state for unknown device: {light_name}, ignoring!"); + let Some(current_device) = known_states.get_mut(device_name) else { + error!("Trying to update state for unknown device: {device_name}, ignoring!"); return; }; for property in new { - if light_name == "small_bedroom:piano" { + if device_name == "small_bedroom:piano" { match property { LampProperty::Brightness(bri) => { warn!("ZB received piano brightness change: {bri}"); @@ -64,7 +64,7 @@ async fn update_state( warn!("ZB received piano color change: {xy:?}"); } LampProperty::Online(new_online) => { - if new_online != current_lamp.is_online() { + if new_online != current_device.is_online() { warn!("ZB received piano online change: {new_online}"); } } @@ -72,7 +72,7 @@ async fn update_state( } } - current_lamp.apply(property); + current_device.apply(property); } } @@ -132,7 +132,7 @@ fn parse_bridge_event( .ok_or_eyre("no data in bridge event")? .as_object() .ok_or_eyre("bridge event data is not a map")?; - let light_name = data + let device_name = data .get("friendly_name") .ok_or_eyre("no name in bridge event data")? .as_str() @@ -145,7 +145,7 @@ fn parse_bridge_event( _ => return Ok(Message::Other), }; - let update = (light_name, vec![lamp::LampProperty::Online(is_online)]); + let update = (device_name, vec![LampProperty::Online(is_online)]); Ok(Message::StateUpdate(update)) } @@ -167,8 +167,8 @@ fn parse_log_message( if level == "error" { if let Some(caps) = regex.captures(message) { - let light_name = caps[1].to_string(); - let update = (light_name, vec![lamp::LampProperty::Online(false)]); + let device_name = caps[1].to_string(); + let update = (device_name, vec![LampProperty::Online(false)]); return Ok(Message::StateUpdate(update)); } } diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index f67ed72b..fdd7f7e2 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -6,6 +6,8 @@ use tracing::trace; pub(crate) use lamp::Model; +use self::lamp::LampProperty; + mod cached_bridge; mod conversion; mod device; @@ -36,7 +38,7 @@ const LIGHT_MODELS: [(&str, Model); 16] = [ #[derive(Debug, Clone)] pub struct Controller { - change_sender: mpsc::UnboundedSender<(String, lamp::LampProperty)>, + change_sender: mpsc::UnboundedSender<(String, LampProperty)>, } impl Controller { @@ -51,40 +53,40 @@ impl Controller { Self { change_sender } } - pub fn set_on(&self, friendly_name: &str) { + pub fn set_on(&self, light_name: &str) { self.change_sender - .send((friendly_name.to_string(), lamp::LampProperty::On(true))) + .send((light_name.to_string(), LampProperty::On(true))) .expect("Sender should never be dropped"); } - pub fn set_off(&self, friendly_name: &str) { + pub fn set_off(&self, light_name: &str) { self.change_sender - .send((friendly_name.to_string(), lamp::LampProperty::On(false))) + .send((light_name.to_string(), LampProperty::On(false))) .expect("Sender should never be dropped"); } /// Brightness from 0 to 1 - pub fn set_brightness(&self, friendly_name: &str, brightness: f64) { + pub fn set_brightness(&self, light_name: &str, brightness: f64) { self.change_sender .send(( - friendly_name.to_string(), - lamp::LampProperty::Brightness(brightness), + light_name.to_string(), + LampProperty::Brightness(brightness), )) .expect("Sender should never be dropped"); } - pub fn set_color_temp(&self, friendly_name: &str, kelvin: usize) { + pub fn set_color_temp(&self, light_name: &str, kelvin: usize) { self.change_sender .send(( - friendly_name.to_string(), - lamp::LampProperty::ColorTempK(kelvin), + light_name.to_string(), + LampProperty::ColorTempK(kelvin), )) .expect("Sender should never be dropped"); } - pub fn set_color_xy(&self, friendly_name: &str, xy: (f64, f64)) { + pub fn set_color_xy(&self, light_name: &str, xy: (f64, f64)) { self.change_sender - .send((friendly_name.to_string(), lamp::LampProperty::ColorXY(xy))) + .send((light_name.to_string(), LampProperty::ColorXY(xy))) .expect("Sender should never be dropped"); } } diff --git a/crates/zigbee-bridge/src/parse_state.rs b/crates/zigbee-bridge/src/parse_state.rs index b6ad946d..918794cd 100644 --- a/crates/zigbee-bridge/src/parse_state.rs +++ b/crates/zigbee-bridge/src/parse_state.rs @@ -3,12 +3,11 @@ use color_eyre::Section; use serde_json::Value; use crate::conversion::{mired_to_kelvin, normalize}; - -use super::lamp; +use crate::lamp::LampProperty; pub(super) fn parse_lamp_properties( bytes: &[u8], -) -> color_eyre::Result> { +) -> color_eyre::Result> { let mut list = Vec::new(); let json: Value = @@ -23,7 +22,7 @@ pub(super) fn parse_lamp_properties( .transpose()? .map(mired_to_kelvin) { - list.push(lamp::LampProperty::ColorTempK(kelvin)); + list.push(LampProperty::ColorTempK(kelvin)); } if let Some(xy) = map @@ -40,7 +39,7 @@ pub(super) fn parse_lamp_properties( }) .transpose()? { - list.push(lamp::LampProperty::ColorXY(xy)); + list.push(LampProperty::ColorXY(xy)); } if let Some(brightness) = map @@ -49,7 +48,7 @@ pub(super) fn parse_lamp_properties( .transpose()? .map(normalize) { - list.push(lamp::LampProperty::Brightness(brightness)); + list.push(LampProperty::Brightness(brightness)); } if let Some(on) = map @@ -65,11 +64,11 @@ pub(super) fn parse_lamp_properties( }) .transpose()? { - list.push(lamp::LampProperty::On(on)); + list.push(LampProperty::On(on)); } // we have just received a state message, so the lamp must be online - list.push(lamp::LampProperty::Online(true)); + list.push(LampProperty::Online(true)); Ok(list) } From eaf3b95c797b21556d6f0e1de3d9e0ea1d9c43c0 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 12 Dec 2024 12:52:51 +0100 Subject: [PATCH 496/687] Rewrite everything to use Property --- crates/zigbee-bridge/src/cached_bridge.rs | 5 +- .../src/cached_bridge/changes.rs | 7 +- .../zigbee-bridge/src/cached_bridge/mqtt.rs | 21 +++--- .../zigbee-bridge/src/cached_bridge/poll.rs | 66 ++++++++++++------- crates/zigbee-bridge/src/device.rs | 53 +++++++++++---- crates/zigbee-bridge/src/lamp.rs | 31 ++++----- crates/zigbee-bridge/src/lamp/property.rs | 29 +++++++- crates/zigbee-bridge/src/lib.rs | 39 +++++------ crates/zigbee-bridge/src/parse_state.rs | 36 ++++++++-- crates/zigbee-bridge/src/radiator.rs | 42 ++++++++++++ 10 files changed, 234 insertions(+), 95 deletions(-) create mode 100644 crates/zigbee-bridge/src/radiator.rs diff --git a/crates/zigbee-bridge/src/cached_bridge.rs b/crates/zigbee-bridge/src/cached_bridge.rs index 2641733a..cd2573ef 100644 --- a/crates/zigbee-bridge/src/cached_bridge.rs +++ b/crates/zigbee-bridge/src/cached_bridge.rs @@ -5,7 +5,8 @@ use tokio::sync::{mpsc, RwLock}; use tracing::trace; use self::mqtt::Mqtt; -use crate::{device::init_states, lamp::LampProperty, LIGHT_MODELS, MQTT_PORT}; +use crate::device::{init_states, Property}; +use crate::{LIGHT_MODELS, MQTT_PORT}; mod changes; mod mqtt; @@ -20,7 +21,7 @@ const CHANGE_ACCUMULATION_TIME: Duration = Duration::from_millis(100); pub(super) async fn run( mqtt_ip: IpAddr, - change_receiver: mpsc::UnboundedReceiver<(String, LampProperty)>, + change_receiver: mpsc::UnboundedReceiver<(String, Property)>, ) -> ! { let mut options = MqttOptions::new("ha-lightcontroller", mqtt_ip.to_string(), MQTT_PORT); diff --git a/crates/zigbee-bridge/src/cached_bridge/changes.rs b/crates/zigbee-bridge/src/cached_bridge/changes.rs index 9b656ab5..0751c3d9 100644 --- a/crates/zigbee-bridge/src/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/cached_bridge/changes.rs @@ -9,11 +9,10 @@ use super::mqtt::Mqtt; use super::{ CHANGE_ACCUMULATION_TIME, MQTT_MIGHT_BE_DOWN_TIMEOUT, WAIT_FOR_INIT_STATES, }; -use crate::device::Device; -use crate::lamp::LampProperty; +use crate::device::{Device, Property}; pub(super) async fn handle( - mut change_receiver: mpsc::UnboundedReceiver<(String, LampProperty)>, + mut change_receiver: mpsc::UnboundedReceiver<(String, Property)>, mqtt: &mut Mqtt, known_states: &RwLock>>, ) -> ! { @@ -109,7 +108,7 @@ async fn send_diff_get_timeout( #[instrument(skip_all)] async fn apply_change_to_needed( device_name: String, - change: LampProperty, + change: Property, known_states: &RwLock>>, needed_states: &mut HashMap>, ) { diff --git a/crates/zigbee-bridge/src/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/cached_bridge/mqtt.rs index 0ac82f1e..7c318eaf 100644 --- a/crates/zigbee-bridge/src/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/cached_bridge/mqtt.rs @@ -6,7 +6,7 @@ use rumqttc::v5::{AsyncClient, ClientError}; use serde_json::json; use tracing::{trace, warn}; -use crate::lamp::{LampProperty, LampPropertyDiscriminants}; +use crate::device::{Property, PropertyDiscriminants}; use super::TIME_IT_TAKES_TO_APPLY_CHANGE; @@ -15,7 +15,7 @@ pub(super) struct Mqtt { // TODO: extract into SendTracker struct? last_sent: HashMap< String, - HashMap, + HashMap, >, } @@ -47,7 +47,7 @@ impl Mqtt { pub(super) fn next_deadline( &self, device_name: &str, - diff: &[LampProperty], + diff: &[Property], ) -> Option { diff.into_iter() .map(|change| self.change_next_due(device_name, &change)) @@ -57,7 +57,7 @@ impl Mqtt { fn change_next_due( &self, device_name: &str, - change: &LampProperty, + change: &Property, ) -> Instant { let Some(device_send_record) = self.last_sent.get(device_name) else { // lamp has never been sent before @@ -65,7 +65,7 @@ impl Mqtt { }; let Some((sent_at, prev_change)) = - device_send_record.get(&change.into()) + device_send_record.get(&(*change).into()) else { // property has never been sent before return Instant::now(); @@ -84,7 +84,7 @@ impl Mqtt { *sent_at + TIME_IT_TAKES_TO_APPLY_CHANGE } - fn is_due(&self, device_name: &str, change: &LampProperty) -> bool { + fn is_due(&self, device_name: &str, change: &Property) -> bool { let deadline = self.change_next_due(device_name, change); deadline < Instant::now() } @@ -93,7 +93,7 @@ impl Mqtt { &mut self, device_name: &str, merged_payloads: bool, - diff: &[LampProperty], + diff: &[Property], ) -> Result<(), ClientError> { let mut due_changes = Vec::new(); @@ -104,7 +104,7 @@ impl Mqtt { let device_send_record = self.last_sent.entry(device_name.to_owned()).or_default(); device_send_record - .insert(change.into(), (Instant::now(), *change)); + .insert((*change).into(), (Instant::now(), *change)); } } @@ -114,7 +114,8 @@ impl Mqtt { self.set(&device_name, payload.to_string()).await?; } else { for change in due_changes { - self.set(&device_name, change.payload().to_string()).await?; + self.set(&device_name, change.payload().to_string()) + .await?; } } } @@ -170,7 +171,7 @@ impl Mqtt { } } -fn merge_payloads(mut changes: Vec<&LampProperty>) -> serde_json::Value { +fn merge_payloads(mut changes: Vec<&Property>) -> serde_json::Value { let payload = changes .iter_mut() .map(|c| c.payload()) diff --git a/crates/zigbee-bridge/src/cached_bridge/poll.rs b/crates/zigbee-bridge/src/cached_bridge/poll.rs index 6f34ef9d..7ed7d2af 100644 --- a/crates/zigbee-bridge/src/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/cached_bridge/poll.rs @@ -8,9 +8,11 @@ use serde_json::Value; use tokio::{sync::RwLock, time::sleep}; use tracing::{error, instrument, trace, warn}; -use crate::device::Device; +use crate::device::{Device, Property}; use crate::lamp::LampProperty; -use crate::parse_state::parse_lamp_properties; +use crate::parse_state::parse_properties; +use crate::radiator::RadiatorProperty; +use crate::{light_names, RADIATOR_NAMES}; pub(super) async fn poll_mqtt( mut eventloop: EventLoop, @@ -47,7 +49,7 @@ pub(super) async fn poll_mqtt( async fn update_state( known_states: &RwLock>>, device_name: &str, - new: Vec, + new: Vec, ) { let mut known_states = known_states.write().await; let Some(current_device) = known_states.get_mut(device_name) else { @@ -56,19 +58,23 @@ async fn update_state( }; for property in new { if device_name == "small_bedroom:piano" { - match property { - LampProperty::Brightness(bri) => { - warn!("ZB received piano brightness change: {bri}"); - } - LampProperty::ColorXY(xy) => { - warn!("ZB received piano color change: {xy:?}"); - } - LampProperty::Online(new_online) => { - if new_online != current_device.is_online() { - warn!("ZB received piano online change: {new_online}"); + if let Property::Lamp(lamp_prop) = property { + match lamp_prop { + LampProperty::Brightness(bri) => { + warn!("ZB received piano brightness change: {bri}"); + } + LampProperty::ColorXY(xy) => { + warn!("ZB received piano color change: {xy:?}"); + } + LampProperty::Online(new_online) => { + if new_online != current_device.is_online() { + warn!( + "ZB received piano online change: {new_online}" + ); + } } + _ => (), } - _ => (), } } @@ -110,11 +116,11 @@ fn parse_message(event: Event) -> color_eyre::Result { } topic => { let topic: Vec<_> = topic.split('/').collect(); - let name = topic[1].to_string(); - let state = parse_lamp_properties(&message.payload) + let device_name = topic[1].to_string(); + let state = parse_properties(&device_name, &message.payload) .wrap_err("failed to parse lamp state") .with_note(|| format!("topic: {topic:?}"))?; - Ok(Message::StateUpdate((name, state))) + Ok(Message::StateUpdate((device_name, state))) } } } @@ -145,8 +151,7 @@ fn parse_bridge_event( _ => return Ok(Message::Other), }; - let update = (device_name, vec![LampProperty::Online(is_online)]); - Ok(Message::StateUpdate(update)) + Ok(online_message(device_name, is_online)) } fn parse_log_message( @@ -168,16 +173,33 @@ fn parse_log_message( if level == "error" { if let Some(caps) = regex.captures(message) { let device_name = caps[1].to_string(); - let update = (device_name, vec![LampProperty::Online(false)]); - return Ok(Message::StateUpdate(update)); + + return Ok(online_message(device_name, false)); } } Ok(Message::Other) } +fn online_message(device_name: String, is_online: bool) -> Message { + if light_names().contains(&device_name.as_str()) { + Message::StateUpdate(( + device_name, + vec![LampProperty::Online(is_online).into()], + )) + } else if RADIATOR_NAMES.contains(&device_name.as_str()) { + Message::StateUpdate(( + device_name, + vec![RadiatorProperty::Online(is_online).into()], + )) + } else { + error!("Unknown device name {device_name}, could not parse log"); + Message::Other + } +} + #[derive(Debug)] enum Message { - StateUpdate((String, Vec)), + StateUpdate((String, Vec)), Other, } diff --git a/crates/zigbee-bridge/src/device.rs b/crates/zigbee-bridge/src/device.rs index 6311d623..a27a96e2 100644 --- a/crates/zigbee-bridge/src/device.rs +++ b/crates/zigbee-bridge/src/device.rs @@ -1,13 +1,43 @@ use std::collections::HashMap; use std::fmt::Debug; -use crate::{ - lamp::{ - property::{LampProperty, LampPropertyDiscriminants}, - Lamp, - }, - LIGHT_MODELS, -}; +use crate::lamp::{Lamp, LampProperty, LampPropertyDiscriminants}; +use crate::radiator::{RadiatorProperty, RadiatorPropertyDiscriminants}; +use crate::LIGHT_MODELS; + +#[derive(PartialEq, Debug, Clone, Copy)] +pub(crate) enum Property { + Lamp(LampProperty), + Radiator(RadiatorProperty), +} + +impl Property { + pub(crate) fn payload(&self) -> serde_json::Value { + match self { + Property::Lamp(lamp_prop) => lamp_prop.payload(), + Property::Radiator(rad_prop) => rad_prop.payload(), + } + } +} + +#[derive(PartialEq, Eq, Hash)] +pub(crate) enum PropertyDiscriminants { + Lamp(LampPropertyDiscriminants), + Radiator(RadiatorPropertyDiscriminants), +} + +impl Into for Property { + fn into(self) -> PropertyDiscriminants { + match self { + Property::Lamp(lamp_prop) => { + PropertyDiscriminants::Lamp(lamp_prop.into()) + } + Property::Radiator(rad_prop) => { + PropertyDiscriminants::Radiator(rad_prop.into()) + } + } + } +} pub(crate) trait Device: Sync + Send + Debug { fn new(name: &str) -> Self @@ -16,12 +46,9 @@ pub(crate) trait Device: Sync + Send + Debug { fn clone_dyn(&self) -> Box; - fn apply(&mut self, change: LampProperty); - fn changes_relative_to(&self, other: &Box) - -> Vec; - fn all_set_properties( - &self, - ) -> HashMap; + fn apply(&mut self, change: Property); + fn changes_relative_to(&self, other: &Box) -> Vec; + fn all_set_properties(&self) -> HashMap; fn needs_merged_payloads(&self) -> bool; fn is_online(&self) -> bool; diff --git a/crates/zigbee-bridge/src/lamp.rs b/crates/zigbee-bridge/src/lamp.rs index 77463643..39297670 100644 --- a/crates/zigbee-bridge/src/lamp.rs +++ b/crates/zigbee-bridge/src/lamp.rs @@ -1,15 +1,15 @@ use std::collections::HashMap; use strum::IntoEnumIterator; -use tracing::instrument; +use tracing::{error, instrument}; use super::conversion::temp_to_xy; -use crate::device::Device; +use crate::device::{Device, Property, PropertyDiscriminants}; pub(crate) use model::Model; -pub(super) use property::{LampProperty, LampPropertyDiscriminants}; +pub(crate) use property::{LampProperty, LampPropertyDiscriminants}; mod model; -pub(crate) mod property; +mod property; #[derive(Clone, Copy, Debug)] enum Color { @@ -60,10 +60,7 @@ impl Device for Lamp { } #[instrument] - fn changes_relative_to( - &self, - other: &Box, - ) -> Vec { + fn changes_relative_to(&self, other: &Box) -> Vec { let mut res = Vec::new(); let self_properties = self.all_set_properties(); @@ -74,7 +71,7 @@ impl Device for Lamp { let other_prop = other_properties.get(&property.into()); // Ignore model (not a prop) and online, because they are read-only - if let Some(LampProperty::Online(_)) = self_prop { + if let Some(Property::Lamp(LampProperty::Online(_))) = self_prop { continue; } @@ -88,7 +85,12 @@ impl Device for Lamp { res } - fn apply(&mut self, change: LampProperty) { + fn apply(&mut self, change: Property) { + let Property::Lamp(change) = change else { + error!("Trying to apply non-lamp change {change:?} to lamp!"); + return; + }; + match change { LampProperty::On(is_on) => self.is_on = Some(is_on), LampProperty::Brightness(bri) => self.brightness = Some(bri), @@ -115,13 +117,12 @@ impl Device for Lamp { } } - fn all_set_properties( - &self, - ) -> HashMap { - let mut properties = HashMap::new(); + fn all_set_properties(&self) -> HashMap { + let mut properties: HashMap = + HashMap::new(); let mut insert_prop = - |prop: LampProperty| properties.insert(prop.into(), prop); + |prop: LampProperty| properties.insert(prop.into(), prop.into()); // Ignore model and is_online, because they are read-only diff --git a/crates/zigbee-bridge/src/lamp/property.rs b/crates/zigbee-bridge/src/lamp/property.rs index 199416c7..b7c18020 100644 --- a/crates/zigbee-bridge/src/lamp/property.rs +++ b/crates/zigbee-bridge/src/lamp/property.rs @@ -2,7 +2,10 @@ use serde_json::json; use strum::{EnumDiscriminants, EnumIter}; use tracing::error; -use crate::conversion::{denormalize, kelvin_to_mired}; +use crate::{ + conversion::{denormalize, kelvin_to_mired}, + device::{Property, PropertyDiscriminants}, +}; #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] pub(crate) enum ColorTempStartup { @@ -21,6 +24,30 @@ pub(crate) enum LampProperty { ColorTempStartup(ColorTempStartup), } +impl From for Property { + fn from(value: LampProperty) -> Self { + Self::Lamp(value) + } +} + +impl From for PropertyDiscriminants { + fn from(value: LampProperty) -> Self { + Self::Lamp(value.into()) + } +} + +impl TryFrom for LampProperty { + type Error = String; + + fn try_from(value: Property) -> Result { + match value { + Property::Lamp(lamp_prop) => Ok(lamp_prop), + _ => Err("Tried to interpret non-lamp property as lamp property" + .to_owned()), + } + } +} + impl PartialEq for LampProperty { fn eq(&self, other: &Self) -> bool { match (self, other) { diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index fdd7f7e2..d94d1f58 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -6,13 +6,14 @@ use tracing::trace; pub(crate) use lamp::Model; -use self::lamp::LampProperty; +use self::{device::Property, lamp::LampProperty}; mod cached_bridge; mod conversion; mod device; pub(crate) mod lamp; mod parse_state; +mod radiator; #[cfg(test)] mod tests; @@ -35,10 +36,16 @@ const LIGHT_MODELS: [(&str, Model); 16] = [ ("hallway:ceiling", Model::TradfriE27), ("toilet:ceiling", Model::HueGen4), ]; +const RADIATOR_NAMES: [&str; 2] = + ["small_bedroom:radiator", "large_bedroom:radiator"]; + +fn light_names() -> Vec<&'static str> { + LIGHT_MODELS.into_iter().map(|(k, _)| k).collect() +} #[derive(Debug, Clone)] pub struct Controller { - change_sender: mpsc::UnboundedSender<(String, LampProperty)>, + change_sender: mpsc::UnboundedSender<(String, Property)>, } impl Controller { @@ -54,39 +61,29 @@ impl Controller { } pub fn set_on(&self, light_name: &str) { - self.change_sender - .send((light_name.to_string(), LampProperty::On(true))) - .expect("Sender should never be dropped"); + self.send_to_light(light_name, LampProperty::On(true)); } pub fn set_off(&self, light_name: &str) { - self.change_sender - .send((light_name.to_string(), LampProperty::On(false))) - .expect("Sender should never be dropped"); + self.send_to_light(light_name, LampProperty::On(false)); } /// Brightness from 0 to 1 pub fn set_brightness(&self, light_name: &str, brightness: f64) { - self.change_sender - .send(( - light_name.to_string(), - LampProperty::Brightness(brightness), - )) - .expect("Sender should never be dropped"); + self.send_to_light(light_name, LampProperty::Brightness(brightness)); } pub fn set_color_temp(&self, light_name: &str, kelvin: usize) { - self.change_sender - .send(( - light_name.to_string(), - LampProperty::ColorTempK(kelvin), - )) - .expect("Sender should never be dropped"); + self.send_to_light(light_name, LampProperty::ColorTempK(kelvin)); } pub fn set_color_xy(&self, light_name: &str, xy: (f64, f64)) { + self.send_to_light(light_name, LampProperty::ColorXY(xy)); + } + + fn send_to_light(&self, light_name: &str, lamp_property: LampProperty) { self.change_sender - .send((light_name.to_string(), LampProperty::ColorXY(xy))) + .send((light_name.to_string(), lamp_property.into())) .expect("Sender should never be dropped"); } } diff --git a/crates/zigbee-bridge/src/parse_state.rs b/crates/zigbee-bridge/src/parse_state.rs index 918794cd..fa04a0e4 100644 --- a/crates/zigbee-bridge/src/parse_state.rs +++ b/crates/zigbee-bridge/src/parse_state.rs @@ -1,13 +1,35 @@ use color_eyre::eyre::{bail, Context, OptionExt, Report}; use color_eyre::Section; use serde_json::Value; +use tracing::error; use crate::conversion::{mired_to_kelvin, normalize}; +use crate::device::Property; use crate::lamp::LampProperty; +use crate::{light_names, RADIATOR_NAMES}; -pub(super) fn parse_lamp_properties( +pub(super) fn parse_properties( + device_name: &str, bytes: &[u8], -) -> color_eyre::Result> { +) -> color_eyre::Result> { + if light_names().contains(&device_name) { + parse_lamp_properties(bytes) + } else if RADIATOR_NAMES.contains(&device_name) { + parse_radiator_properties(bytes) + } else { + error!("Unknown device name {device_name}, could not parse properties"); + // TODO make actual error + return Ok(Vec::new()); + } +} + +fn parse_radiator_properties(bytes: &[u8]) -> Result, Report> { + Ok(Vec::new()) +} + +fn parse_lamp_properties( + bytes: &[u8], +) -> color_eyre::Result> { let mut list = Vec::new(); let json: Value = @@ -22,7 +44,7 @@ pub(super) fn parse_lamp_properties( .transpose()? .map(mired_to_kelvin) { - list.push(LampProperty::ColorTempK(kelvin)); + list.push(LampProperty::ColorTempK(kelvin).into()); } if let Some(xy) = map @@ -39,7 +61,7 @@ pub(super) fn parse_lamp_properties( }) .transpose()? { - list.push(LampProperty::ColorXY(xy)); + list.push(LampProperty::ColorXY(xy).into()); } if let Some(brightness) = map @@ -48,7 +70,7 @@ pub(super) fn parse_lamp_properties( .transpose()? .map(normalize) { - list.push(LampProperty::Brightness(brightness)); + list.push(LampProperty::Brightness(brightness).into()); } if let Some(on) = map @@ -64,11 +86,11 @@ pub(super) fn parse_lamp_properties( }) .transpose()? { - list.push(LampProperty::On(on)); + list.push(LampProperty::On(on).into()); } // we have just received a state message, so the lamp must be online - list.push(LampProperty::Online(true)); + list.push(LampProperty::Online(true).into()); Ok(list) } diff --git a/crates/zigbee-bridge/src/radiator.rs b/crates/zigbee-bridge/src/radiator.rs new file mode 100644 index 00000000..be92c105 --- /dev/null +++ b/crates/zigbee-bridge/src/radiator.rs @@ -0,0 +1,42 @@ +use strum::EnumDiscriminants; + +use crate::device::{Property, PropertyDiscriminants}; + +#[derive(PartialEq, Eq, EnumDiscriminants, Debug, Clone, Copy)] +#[strum_discriminants(derive(Hash))] +pub(crate) enum RadiatorProperty { + SetPoint, + Online(bool), +} + +impl RadiatorProperty { + pub(crate) fn payload(&self) -> serde_json::Value { + todo!() + } +} + +impl From for Property { + fn from(value: RadiatorProperty) -> Self { + Self::Radiator(value) + } +} + +impl From for PropertyDiscriminants { + fn from(value: RadiatorProperty) -> Self { + Self::Radiator(value.into()) + } +} + +impl TryFrom for RadiatorProperty { + type Error = String; + + fn try_from(value: Property) -> Result { + match value { + Property::Radiator(lamp_prop) => Ok(lamp_prop), + _ => Err( + "Tried to interpret non-radiator property as radiator property" + .to_owned(), + ), + } + } +} From 8aa48fc0be3f1cf18572633713f9c8c125131ee4 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 14 Dec 2024 12:27:51 +0100 Subject: [PATCH 497/687] Add radiator, mostly tested and working --- crates/zigbee-bridge/src/cached_bridge.rs | 8 +- crates/zigbee-bridge/src/conversion.rs | 9 ++ crates/zigbee-bridge/src/device.rs | 8 +- crates/zigbee-bridge/src/lamp.rs | 2 +- crates/zigbee-bridge/src/lib.rs | 20 ++- crates/zigbee-bridge/src/parse_state.rs | 44 ++++- crates/zigbee-bridge/src/radiator.rs | 186 +++++++++++++++++++++- crates/zigbee-bridge/src/tests.rs | 12 ++ 8 files changed, 275 insertions(+), 14 deletions(-) diff --git a/crates/zigbee-bridge/src/cached_bridge.rs b/crates/zigbee-bridge/src/cached_bridge.rs index cd2573ef..92d479f0 100644 --- a/crates/zigbee-bridge/src/cached_bridge.rs +++ b/crates/zigbee-bridge/src/cached_bridge.rs @@ -6,7 +6,7 @@ use tracing::trace; use self::mqtt::Mqtt; use crate::device::{init_states, Property}; -use crate::{LIGHT_MODELS, MQTT_PORT}; +use crate::{LIGHT_MODELS, MQTT_PORT, RADIATOR_NAMES}; mod changes; mod mqtt; @@ -46,6 +46,12 @@ pub(super) async fn run( .unwrap(); mqtt.request_state(light).await; } + for radiator in RADIATOR_NAMES { + mqtt.subscribe(&format!("zigbee2mqtt/{radiator}")) + .await + .unwrap(); + mqtt.request_state(radiator).await; + } trace!("Starting main zigbee management loops"); let poll_mqtt = poll::poll_mqtt(eventloop, &known_states); diff --git a/crates/zigbee-bridge/src/conversion.rs b/crates/zigbee-bridge/src/conversion.rs index cabcc278..4ede4860 100644 --- a/crates/zigbee-bridge/src/conversion.rs +++ b/crates/zigbee-bridge/src/conversion.rs @@ -24,6 +24,14 @@ pub(super) fn denormalize(brightness: f64) -> u8 { (brightness * 254.).round() as u8 } +pub(super) fn round_to_half(setpoint: f64) -> f64 { + (setpoint * 2.).round() / 2. +} + +pub(super) fn times_100_int(reference: f64) -> usize { + (reference * 100.).round() as usize +} + #[allow(clippy::doc_markdown)] /// 1000K < `color_temp` < 1_000_000K pub(super) fn temp_to_xy(color_temp_k: usize) -> (f64, f64) { @@ -46,6 +54,7 @@ fn xyz_to_xy(xyz: XYZ) -> (f64, f64) { mod tests { use super::*; + #[ignore] #[test] fn temp_to_xy_works() { dbg!(temp_to_xy(2200)); diff --git a/crates/zigbee-bridge/src/device.rs b/crates/zigbee-bridge/src/device.rs index a27a96e2..85a4ba6a 100644 --- a/crates/zigbee-bridge/src/device.rs +++ b/crates/zigbee-bridge/src/device.rs @@ -2,8 +2,8 @@ use std::collections::HashMap; use std::fmt::Debug; use crate::lamp::{Lamp, LampProperty, LampPropertyDiscriminants}; -use crate::radiator::{RadiatorProperty, RadiatorPropertyDiscriminants}; -use crate::LIGHT_MODELS; +use crate::radiator::{Radiator, RadiatorProperty, RadiatorPropertyDiscriminants}; +use crate::{LIGHT_MODELS, RADIATOR_NAMES}; #[derive(PartialEq, Debug, Clone, Copy)] pub(crate) enum Property { @@ -66,5 +66,9 @@ pub(crate) fn init_states() -> HashMap> { let device: Box = Box::new(Lamp::new(light_name)); states.insert(light_name.to_owned(), device); } + for radiator_name in RADIATOR_NAMES { + let device: Box = Box::new(Radiator::new(radiator_name)); + states.insert(radiator_name.to_owned(), device); + } states } diff --git a/crates/zigbee-bridge/src/lamp.rs b/crates/zigbee-bridge/src/lamp.rs index 39297670..f7dadde2 100644 --- a/crates/zigbee-bridge/src/lamp.rs +++ b/crates/zigbee-bridge/src/lamp.rs @@ -27,7 +27,7 @@ impl Color { #[derive(Clone, Debug)] pub(crate) struct Lamp { model: Model, - pub(super) is_online: bool, + is_online: bool, brightness: Option, color: Option, is_on: Option, diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index d94d1f58..b32cc338 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -6,7 +6,7 @@ use tracing::trace; pub(crate) use lamp::Model; -use self::{device::Property, lamp::LampProperty}; +use self::{device::Property, lamp::LampProperty, radiator::RadiatorProperty}; mod cached_bridge; mod conversion; @@ -81,6 +81,24 @@ impl Controller { self.send_to_light(light_name, LampProperty::ColorXY(xy)); } + pub fn set_radiator_setpoint(&self, radiator_name: &str, setpoint: f64) { + self.change_sender + .send(( + radiator_name.to_owned(), + RadiatorProperty::Setpoint(setpoint).into(), + )) + .expect("Sender should never be dropped"); + } + + pub fn set_radiator_reference(&self, radiator_name: &str, reference: f64) { + self.change_sender + .send(( + radiator_name.to_owned(), + RadiatorProperty::Reference(reference).into(), + )) + .expect("Sender should never be dropped"); + } + fn send_to_light(&self, light_name: &str, lamp_property: LampProperty) { self.change_sender .send((light_name.to_string(), lamp_property.into())) diff --git a/crates/zigbee-bridge/src/parse_state.rs b/crates/zigbee-bridge/src/parse_state.rs index fa04a0e4..cde09a32 100644 --- a/crates/zigbee-bridge/src/parse_state.rs +++ b/crates/zigbee-bridge/src/parse_state.rs @@ -6,6 +6,7 @@ use tracing::error; use crate::conversion::{mired_to_kelvin, normalize}; use crate::device::Property; use crate::lamp::LampProperty; +use crate::radiator::RadiatorProperty; use crate::{light_names, RADIATOR_NAMES}; pub(super) fn parse_properties( @@ -24,12 +25,47 @@ pub(super) fn parse_properties( } fn parse_radiator_properties(bytes: &[u8]) -> Result, Report> { - Ok(Vec::new()) + let mut list = Vec::new(); + + let json: Value = + serde_json::from_slice(bytes).wrap_err("Could not deserialize")?; + let map = json + .as_object() + .ok_or_eyre("Top level json must be object")?; + + if let Some(setpoint) = map + .get("occupied_heating_setpoint") + .map(json_to_f64) + .transpose()? + { + list.push(RadiatorProperty::Setpoint(setpoint).into()); + } + + if let Some(reference) = map + .get("external_measured_room_sensor") + .map(json_to_usize) + .transpose()? + .map(|int| int as f64 / 100.) + { + list.push(RadiatorProperty::Reference(reference).into()); + } + + if let Some(set_method) = map + .get("setpoint_change_source") + .map(|s| { + s.as_str() + .ok_or_eyre("Setpoint change source not a string") + .map(|s| s.parse().unwrap()) + }) + .transpose()? + { + list.push(RadiatorProperty::SetByMethod(set_method).into()); + } + + Ok(list) } -fn parse_lamp_properties( - bytes: &[u8], -) -> color_eyre::Result> { +fn parse_lamp_properties(bytes: &[u8]) -> color_eyre::Result> { let mut list = Vec::new(); let json: Value = diff --git a/crates/zigbee-bridge/src/radiator.rs b/crates/zigbee-bridge/src/radiator.rs index be92c105..ef43e42f 100644 --- a/crates/zigbee-bridge/src/radiator.rs +++ b/crates/zigbee-bridge/src/radiator.rs @@ -1,17 +1,193 @@ -use strum::EnumDiscriminants; +use std::{collections::HashMap, str::FromStr}; -use crate::device::{Property, PropertyDiscriminants}; +use serde_json::json; +use strum::{EnumDiscriminants, EnumIter, IntoEnumIterator}; +use tracing::error; -#[derive(PartialEq, Eq, EnumDiscriminants, Debug, Clone, Copy)] +use crate::{ + conversion::{round_to_half, times_100_int}, + device::{Device, Property, PropertyDiscriminants}, +}; + +#[derive(Debug, Clone)] +pub(crate) struct Radiator { + is_online: bool, + setpoint: Option, + reference: Option, + set_by_method: Option, +} + +#[derive(Debug, Clone, Copy, Default)] +pub(crate) enum SetMethod { + Manual, + Schedule, + #[default] + External, +} + +impl FromStr for SetMethod { + type Err = String; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "manual" => Ok(SetMethod::Manual), + "schedule" => Ok(SetMethod::Schedule), + "externally" => Ok(SetMethod::External), + invalid => { + Err(format!("Unknown set method encountered: {invalid}")) + } + } + } +} + +impl Device for Radiator { + fn new(_name: &str) -> Self + where + Self: Sized, + { + Self { + is_online: true, + setpoint: None, + reference: None, + set_by_method: None, + } + } + + fn clone_dyn(&self) -> Box { + Box::new(self.clone()) + } + + fn apply(&mut self, change: Property) { + let Property::Radiator(change) = change else { + error!( + "Trying to apply non-radiator change {change:?} to radiator!" + ); + return; + }; + + match change { + RadiatorProperty::Online(is_online) => self.is_online = is_online, + RadiatorProperty::Setpoint(setpoint) => { + self.setpoint = Some(setpoint) + } + RadiatorProperty::Reference(reference) => { + self.reference = Some(reference) + } + RadiatorProperty::SetByMethod(set_method) => { + self.set_by_method = Some(set_method) + } + } + } + + fn changes_relative_to(&self, other: &Box) -> Vec { + let mut res = Vec::new(); + + let self_properties = self.all_set_properties(); + let other_properties = other.all_set_properties(); + + for property in RadiatorProperty::iter() { + let self_prop = self_properties.get(&property.into()); + let other_prop = other_properties.get(&property.into()); + + // Ignore set_by_method and online, because they are read-only + if let Some(Property::Radiator( + RadiatorProperty::Online(_) | RadiatorProperty::SetByMethod(_), + )) = self_prop + { + continue; + } + + if let Some(self_prop) = self_prop { + if other_prop.is_none_or(|other_prop| self_prop != other_prop) { + res.push(*self_prop); + } + } + } + + res + } + + fn all_set_properties( + &self, + ) -> std::collections::HashMap { + let mut properties: HashMap = + HashMap::new(); + + let mut insert_prop = |prop: RadiatorProperty| { + properties.insert(prop.into(), prop.into()) + }; + + // Ignore set_by_method and online, because they are read-only + + if let Some(val) = (&self).setpoint { + insert_prop(RadiatorProperty::Setpoint(val)); + } + if let Some(val) = (&self).reference { + insert_prop(RadiatorProperty::Reference(val)); + } + + properties + } + + fn needs_merged_payloads(&self) -> bool { + false + } + + fn is_online(&self) -> bool { + self.is_online + } +} + +#[derive(Debug, EnumDiscriminants, EnumIter, Clone, Copy)] #[strum_discriminants(derive(Hash))] pub(crate) enum RadiatorProperty { - SetPoint, Online(bool), + Setpoint(f64), + Reference(f64), + SetByMethod(SetMethod), +} + +impl PartialEq for RadiatorProperty { + fn eq(&self, other: &Self) -> bool { + match (*self, *other) { + (RadiatorProperty::Setpoint(a), RadiatorProperty::Setpoint(b)) => { + round_to_half(a) == round_to_half(b) + } + ( + RadiatorProperty::Reference(a), + RadiatorProperty::Reference(b), + ) => times_100_int(a) == times_100_int(b), + // we never need to update these, so we always consider them the same + (RadiatorProperty::Online(_), RadiatorProperty::Online(_)) => true, + ( + RadiatorProperty::SetByMethod(_), + RadiatorProperty::SetByMethod(_), + ) => true, + (_, _) => false, + } + } } impl RadiatorProperty { pub(crate) fn payload(&self) -> serde_json::Value { - todo!() + match *self { + RadiatorProperty::Setpoint(setpoint) => { + json!({"occupied_heating_setpoint": round_to_half(setpoint) }) + } + RadiatorProperty::Reference(reference) => { + json!({"external_measured_room_sensor": times_100_int(reference) }) + } + // read-only, shouldn't be called, safe default + RadiatorProperty::Online(_) => { + error!("Tried to convert Online to payload"); + json!({"state": ""}) + } + // read-only, shouldn't be called, safe default + RadiatorProperty::SetByMethod(_) => { + error!("Tried to convert SetByMethod to payload"); + json!({"state": ""}) + } + } } } diff --git a/crates/zigbee-bridge/src/tests.rs b/crates/zigbee-bridge/src/tests.rs index fe7f74c8..52bf2219 100644 --- a/crates/zigbee-bridge/src/tests.rs +++ b/crates/zigbee-bridge/src/tests.rs @@ -33,3 +33,15 @@ async fn change_fridge_light() { unreachable!(); } +#[tokio::test] +async fn change_radiator_temp() { + std::env::set_var("RUST_LOG", "brain=trace,zigbee_bridge=trace,info"); + let controller = + Controller::start_bridge("192.168.1.43".parse().unwrap()); + let radiator = "small_bedroom:radiator"; + + controller.set_radiator_setpoint(radiator, 22.); + + let () = std::future::pending().await; + unreachable!(); +} From 144c0304a48b02aa05803dea2467d886e7f223f2 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 14 Dec 2024 13:06:18 +0100 Subject: [PATCH 498/687] Fix brain to work with new zigbee bridge structure --- crates/brain/src/system.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/brain/src/system.rs b/crates/brain/src/system.rs index d71d5da3..b8bda4fc 100644 --- a/crates/brain/src/system.rs +++ b/crates/brain/src/system.rs @@ -1,7 +1,7 @@ use std::net::IpAddr; // pub mod mpd_control; -use zigbee_bridge::lights; +use zigbee_bridge::Controller; // pub use mpd_control::Mpd; use crate::input::jobs::Jobs; @@ -10,7 +10,7 @@ use crate::input::jobs::Jobs; pub struct System { #[allow(dead_code)] pub jobs: Jobs, - pub lights_new: lights::Controller, + pub lights_new: Controller, // pub mpd: Mpd, } @@ -18,7 +18,7 @@ impl System { pub fn init(mqtt_ip: IpAddr, jobs: Jobs) -> Self { Self { jobs, - lights_new: lights::Controller::start_bridge(mqtt_ip), + lights_new: Controller::start_bridge(mqtt_ip), // mpd: Mpd, } } From a31e89650df55d3a68768380623e9c2af92a2fe6 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 14 Dec 2024 13:07:28 +0100 Subject: [PATCH 499/687] Add fn to remove old jobs for a certain event --- crates/brain/src/input/jobs.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index 00086018..6e7292a8 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -111,6 +111,34 @@ impl Jobs { self.job_change_tx.send(()).await?; Ok(id) } + + pub(crate) async fn remove_all_with_event( + &self, + event_to_remove: Event, + ) -> Result, Error> { + let ids_to_remove: Vec<_> = { + let list = self.list.lock().await; + let jobs = list.jobs(); + + jobs.iter() + .filter_map(|res| res.ok()) + .filter(|(_, job)| job.event == event_to_remove) + .map(|(id, _)| id) + .collect() + }; + + let mut removed = Vec::new(); + + for id in ids_to_remove { + let old_job = self.remove(id).await?; + if let Some(old_job) = old_job { + removed.push(old_job); + } + } + + Ok(removed) + } + pub(crate) async fn remove( &self, to_remove: i64, From ea41cc7bbc3dc91bedb51092a5ed6c92b45ce2d2 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 14 Dec 2024 13:08:02 +0100 Subject: [PATCH 500/687] Tweak SB wakeup --- crates/brain/src/controller/rooms/small_bedroom.rs | 13 ++++++++----- .../src/controller/rooms/small_bedroom/state.rs | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index b8d25832..befbb796 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -5,7 +5,7 @@ use futures_util::FutureExt; use protocol::small_bedroom::ButtonPanel; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; -use tracing::warn; +use tracing::{info, trace, warn}; use self::filter::{recv_filtered, RelevantEvent, Trigger}; use self::state::Room; @@ -42,14 +42,17 @@ pub async fn run( // let soon = crate::time::now().checked_add(1.minutes()).unwrap(); let wakeup_job = Job::every_day_at( - 9, - 0, + 8, + 57, Event::WakeupSB, Some(WAKEUP_EXPIRATION), ); + + let res = system.system.jobs.remove_all_with_event(Event::WakeupSB).await; + trace!("Removing old SB wakeup jobs returned: {res:#?}"); let res = system.system.jobs.add(wakeup_job.clone()).await; - warn!("Tried to add job for SB wakeup: {wakeup_job:#?}"); - warn!("Jobs returned: {res:#?}"); + trace!("Tried to add job for SB wakeup: {wakeup_job:#?}"); + trace!("Jobs returned: {res:#?}"); loop { let get_event = recv_filtered(&mut event_rx); diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index f6c1684a..4dbeedc7 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -102,7 +102,7 @@ impl Room { async fn run_wakeup_then_daylight(mut self) { const LIGHT_NAME: &str = "small_bedroom:piano"; - const RUNTIME_MINS: i32 = 7; + const RUNTIME_MINS: i32 = 10; const STEP_SIZE_SECS: i32 = 30; const N_STEPS: i32 = RUNTIME_MINS * 60 / STEP_SIZE_SECS; From 7addcae38f370289289cd29470c376cf3ca09f4b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 23 Dec 2024 11:47:46 +0100 Subject: [PATCH 501/687] refactor&fix zigbee-bridge + adds radiator bridge refactor - moves tests to examples since they have no asserts and rely purly on user inspection of the system. - removes if (condition) print debugging. Instead store function information in spans to allow runtime filtering through tracing fix - mqtt client name is random on startup (fixes retained radiator messages not deliverd after startup) rather big sorry --- Cargo.lock | 385 ++++++++++-------- Cargo.toml | 2 +- crates/brain/src/main.rs | 2 +- crates/brain/src/system.rs | 2 +- crates/data-server/tests/source_api.rs | 48 +-- crates/logger/Cargo.toml | 1 + crates/logger/src/tracing.rs | 84 +++- crates/radiator-bridge/.cargo/config.toml | 5 + crates/radiator-bridge/Cargo.toml | 17 + crates/radiator-bridge/deploy.sh | 19 + crates/radiator-bridge/src/main.rs | 129 ++++++ crates/radiator-bridge/test.sh | 16 + crates/zigbee-bridge/Cargo.toml | 4 + .../change_fridge_light.rs} | 29 +- .../examples/change_radiator_reference.rs | 17 + .../examples/change_radiator_set_point.rs | 17 + crates/zigbee-bridge/src/cached_bridge.rs | 8 +- .../src/cached_bridge/changes.rs | 8 +- .../zigbee-bridge/src/cached_bridge/mqtt.rs | 22 +- .../zigbee-bridge/src/cached_bridge/poll.rs | 27 +- crates/zigbee-bridge/src/conversion.rs | 14 - crates/zigbee-bridge/src/lib.rs | 6 +- crates/zigbee-bridge/src/parse_state.rs | 8 +- crates/zigbee-bridge/src/radiator.rs | 3 +- 24 files changed, 567 insertions(+), 306 deletions(-) create mode 100644 crates/radiator-bridge/.cargo/config.toml create mode 100644 crates/radiator-bridge/Cargo.toml create mode 100755 crates/radiator-bridge/deploy.sh create mode 100644 crates/radiator-bridge/src/main.rs create mode 100755 crates/radiator-bridge/test.sh rename crates/zigbee-bridge/{src/tests.rs => examples/change_fridge_light.rs} (51%) create mode 100644 crates/zigbee-bridge/examples/change_radiator_reference.rs create mode 100644 crates/zigbee-bridge/examples/change_radiator_set_point.rs diff --git a/Cargo.lock b/Cargo.lock index a0a189c6..ddff632a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,9 +34,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "anstream" @@ -143,7 +143,7 @@ checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ "async-task", "concurrent-queue", - "fastrand 2.2.0", + "fastrand 2.3.0", "futures-lite 2.5.0", "slab", ] @@ -293,7 +293,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -340,7 +340,7 @@ dependencies = [ "pin-project-lite", "rustversion", "serde", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", "tower", "tower-layer", @@ -362,7 +362,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.2", + "sync_wrapper", "tower-layer", "tower-service", ] @@ -375,7 +375,7 @@ checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -488,7 +488,7 @@ dependencies = [ "serde_yaml", "sled", "strum", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "tz-rs", @@ -521,22 +521,22 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "byteseries" version = "0.7.1" -source = "git+https://github.com/dvdsk/byteseries#eb057c6363548fa1fc2fbe5a89395b81238152f5" +source = "git+https://github.com/dvdsk/byteseries#bd2928fdf8ba4a921c777f8a444b134bb579ae39" dependencies = [ "arraydeque", "itertools 0.13.0", "num-traits", "ron", "serde", - "smallvec 2.0.0-alpha.7", - "thiserror", + "smallvec 2.0.0-alpha.8", + "thiserror 1.0.69", "tracing", ] @@ -563,9 +563,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.1" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" +checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf" dependencies = [ "shlex", ] @@ -584,9 +584,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -594,9 +594,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -613,14 +613,14 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] name = "clap_lex" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "clipboard-win" @@ -697,7 +697,7 @@ dependencies = [ "paste", "strum", "strum_macros", - "thiserror", + "thiserror 1.0.69", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -878,7 +878,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -889,7 +889,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -921,7 +921,7 @@ dependencies = [ "serde", "slotmap", "socket2", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-serde", "tokio-stream", @@ -951,9 +951,9 @@ dependencies = [ "reserve-port", "rpc", "serde", - "smallvec 2.0.0-alpha.7", + "smallvec 2.0.0-alpha.8", "temp-dir", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "tracing-error", @@ -969,7 +969,7 @@ dependencies = [ "dbstruct-derive", "serde", "sled", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -983,15 +983,15 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.89", - "thiserror", + "syn 2.0.90", + "thiserror 1.0.69", ] [[package]] name = "defmt" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0" +checksum = "86f6162c53f659f65d00619fe31f14556a6e9f8752ccc4a41bd177ffcf3d6130" dependencies = [ "bitflags 1.3.2", "defmt-macros", @@ -999,24 +999,24 @@ dependencies = [ [[package]] name = "defmt-macros" -version = "0.3.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb" +checksum = "9d135dd939bad62d7490b0002602d35b358dce5fd9233a709d3c1ef467d4bde6" dependencies = [ "defmt-parser", - "proc-macro-error", + "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] name = "defmt-parser" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" +checksum = "3983b127f13995e68c1e29071e5d115cd96f215ccb5e6812e3728cd6f92653b3" dependencies = [ - "thiserror", + "thiserror 2.0.7", ] [[package]] @@ -1040,7 +1040,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1137,7 +1137,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1159,7 +1159,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1228,7 +1228,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1253,12 +1253,12 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1290,9 +1290,9 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" dependencies = [ "event-listener 5.3.1", "pin-project-lite", @@ -1319,9 +1319,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fd-lock" @@ -1488,7 +1488,7 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" dependencies = [ - "fastrand 2.2.0", + "fastrand 2.3.0", "futures-core", "futures-io", "parking", @@ -1503,7 +1503,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1652,7 +1652,7 @@ checksum = "4ea1a9715542f84bc7b67cbb01c02ed3a72a919750b7d8611cc5bd684449386e" dependencies = [ "futures", "gpiocdev-uapi", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", ] @@ -1666,7 +1666,7 @@ dependencies = [ "embedded-hal", "embedded-hal-async", "gpiocdev", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1678,7 +1678,7 @@ dependencies = [ "bitflags 2.6.0", "ioctl-sys", "libc", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1784,12 +1784,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hermit-abi" version = "0.4.0" @@ -1807,9 +1801,9 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -1863,7 +1857,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", ] @@ -2033,7 +2027,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2071,9 +2065,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -2099,8 +2093,8 @@ dependencies = [ "proc-macro2", "quote", "strum", - "syn 2.0.89", - "thiserror", + "syn 2.0.90", + "thiserror 1.0.69", ] [[package]] @@ -2120,7 +2114,7 @@ dependencies = [ "pretty_assertions", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2186,9 +2180,9 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jiff" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d9d414fc817d3e3d62b2598616733f76c4cc74fbac96069674739b881295c8" +checksum = "db69f08d4fb10524cacdb074c10b296299d71274ddbc830a8ee65666867002e9" dependencies = [ "jiff-tzdb-platform", "serde", @@ -2212,10 +2206,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -2236,9 +2231,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.166" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2ccc108bbc0b1331bd061864e7cd823c0cab660bbe6970e66e2c0614decde36" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libm" @@ -2270,7 +2265,7 @@ dependencies = [ "once_cell", "serde", "sha2", - "thiserror", + "thiserror 1.0.69", "uuid", ] @@ -2345,9 +2340,9 @@ dependencies = [ "reserve-port", "rpc", "serde", - "smallvec 2.0.0-alpha.7", + "smallvec 2.0.0-alpha.8", "temp-dir", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "tracing-error", @@ -2358,6 +2353,7 @@ dependencies = [ name = "logger" version = "0.1.0" dependencies = [ + "color-eyre", "governor", "libsystemd", "tracing", @@ -2408,7 +2404,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2541,11 +2537,10 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi 0.3.9", "libc", "log", "wasi", @@ -2585,7 +2580,7 @@ checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2868,7 +2863,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.5.7", + "redox_syscall 0.5.8", "smallvec 1.13.2", "windows-targets 0.52.6", ] @@ -2902,7 +2897,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2924,7 +2919,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand 2.2.0", + "fastrand 2.3.0", "futures-io", ] @@ -2936,7 +2931,7 @@ checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ "cfg-if 1.0.0", "concurrent-queue", - "hermit-abi 0.4.0", + "hermit-abi", "pin-project-lite", "rustix", "tracing", @@ -2951,9 +2946,9 @@ checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" [[package]] name = "postcard" -version = "1.0.10" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" +checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8" dependencies = [ "cobs", "defmt", @@ -3018,6 +3013,28 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "proc-macro-utils" version = "0.10.0" @@ -3056,7 +3073,7 @@ dependencies = [ "postcard", "serde", "strum", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3072,9 +3089,9 @@ dependencies = [ [[package]] name = "quanta" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5" +checksum = "773ce68d0bb9bc7ef20be3536ffe94e223e1f365bd374108b2659fac0c65cfe6" dependencies = [ "crossbeam-utils", "libc", @@ -3100,6 +3117,19 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radiator-bridge" +version = "0.1.0" +dependencies = [ + "clap", + "data-server", + "logger", + "protocol", + "tokio", + "tracing", + "zigbee-bridge", +] + [[package]] name = "radix_trie" version = "0.2.1" @@ -3187,9 +3217,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags 2.6.0", ] @@ -3202,7 +3232,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3274,7 +3304,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", "tower-service", "url", @@ -3291,7 +3321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9838134a2bfaa8e1f40738fcc972ac799de6e0e06b5157acb95fc2b05a0ea283" dependencies = [ "lazy_static", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3315,7 +3345,7 @@ dependencies = [ "governor", "logger", "serde", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-serde", "tokio-util", @@ -3332,7 +3362,7 @@ dependencies = [ "flume", "futures-util", "log", - "thiserror", + "thiserror 1.0.69", "tokio", ] @@ -3353,15 +3383,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.41" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3423,9 +3453,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" [[package]] name = "sensor-tui" @@ -3447,7 +3477,7 @@ dependencies = [ "protocol", "ratatui", "strip-ansi-escapes", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "tracing-error", @@ -3457,22 +3487,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -3514,9 +3544,9 @@ dependencies = [ [[package]] name = "serialport" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7331eefcaafaa382c0df95bcd84068f0b3e3c215c300750dde2316e9b8806ed5" +checksum = "779e2977f0cc2ff39708fef48f96f3768ac8ddd8c6caaaab82e83bd240ef99b2" dependencies = [ "bitflags 2.6.0", "cfg-if 1.0.0", @@ -3641,15 +3671,15 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smallvec" -version = "2.0.0-alpha.7" +version = "2.0.0-alpha.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6a96cb564e12be8458b004bd829787ebe887de197d94516d2ba5a2a32235a0c" +checksum = "abfdb29d53c8bdb1b13f07f3b8895ba7efef32412fb23f57246f238ed586d369" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3736,7 +3766,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -3758,21 +3788,15 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.89" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - [[package]] name = "sync_wrapper" version = "1.0.2" @@ -3802,7 +3826,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -3826,7 +3850,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767" +dependencies = [ + "thiserror-impl 2.0.7", ] [[package]] @@ -3837,7 +3870,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", ] [[package]] @@ -3862,9 +3906,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -3886,7 +3930,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -3906,9 +3950,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -3917,9 +3961,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -3930,14 +3974,14 @@ dependencies = [ [[package]] name = "tower" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", "pin-project-lite", - "sync_wrapper 0.1.2", + "sync_wrapper", "tokio", "tower-layer", "tower-service", @@ -3974,7 +4018,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -3989,9 +4033,9 @@ dependencies = [ [[package]] name = "tracing-error" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" dependencies = [ "tracing", "tracing-subscriber", @@ -4009,9 +4053,9 @@ dependencies = [ [[package]] name = "tracing-journald" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba316a74e8fc3c3896a850dba2375928a9fa171b085ecddfc7c054d39970f3fd" +checksum = "fc0b4143302cf1022dac868d521e36e8b27691f72c84b3311750d5188ebba657" dependencies = [ "libc", "tracing-core", @@ -4031,9 +4075,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term", @@ -4083,7 +4127,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c878a167baa8afd137494101a688ef8c67125089ff2249284bd2b5f9bfedb815" dependencies = [ - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4260,9 +4304,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if 1.0.0", "once_cell", @@ -4271,36 +4315,36 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.45" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ "cfg-if 1.0.0", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4308,28 +4352,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" dependencies = [ "js-sys", "wasm-bindgen", @@ -4592,7 +4636,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", "synstructure 0.13.1", ] @@ -4614,7 +4658,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -4634,7 +4678,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", "synstructure 0.13.1", ] @@ -4657,7 +4701,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -4670,11 +4714,12 @@ dependencies = [ "futures-concurrency", "itertools 0.13.0", "logger", + "rand", "regex", "rumqttc", "serde_json", "strum", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] diff --git a/Cargo.toml b/Cargo.toml index 010defbc..bfda2fdb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ logger = { path = "crates/logger" } byteseries = { git = "https://github.com/dvdsk/byteseries" } -tokio = "1.38" +tokio = { version = "1.38", features = ["rt-multi-thread"] } color-eyre = "0.6.3" tracing = "0.1.40" tracing-error = "0.2.0" diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index 07b9da9b..d0f4b3a4 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -26,7 +26,7 @@ struct Opt { #[clap(long)] mpd_ip: IpAddr, - /// http api listens on this port at 127.0.0.1 use + /// http API listens on this port at 127.0.0.1 use /// a loadbalancer/reverse proxy to get traffic to this #[clap(long)] http_port: u16, diff --git a/crates/brain/src/system.rs b/crates/brain/src/system.rs index b8bda4fc..b2e5488c 100644 --- a/crates/brain/src/system.rs +++ b/crates/brain/src/system.rs @@ -18,7 +18,7 @@ impl System { pub fn init(mqtt_ip: IpAddr, jobs: Jobs) -> Self { Self { jobs, - lights_new: Controller::start_bridge(mqtt_ip), + lights_new: Controller::start_bridge(mqtt_ip, "brain"), // mpd: Mpd, } } diff --git a/crates/data-server/tests/source_api.rs b/crates/data-server/tests/source_api.rs index b180e43e..eaf871e4 100644 --- a/crates/data-server/tests/source_api.rs +++ b/crates/data-server/tests/source_api.rs @@ -22,10 +22,12 @@ enum Done { Test, } -const TEST_READING: Reading = - Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::NumberPm2_5(0.0))); -const TEST_AFFECTOR: Affector = - Affector::LargeBedroom(large_bedroom::Affector::Bed(bed::Affector::ResetNode)); +const TEST_READING: Reading = Reading::LargeBedroom( + large_bedroom::Reading::Bed(bed::Reading::NumberPm2_5(0.0)), +); +const TEST_AFFECTOR: Affector = Affector::LargeBedroom( + large_bedroom::Affector::Bed(bed::Affector::ResetNode), +); async fn run_server( client_addr: impl Into, @@ -107,7 +109,7 @@ async fn list_affectors_inner(sub_port: u16) -> Result { #[tokio::test] async fn subscribe_and_receive() { - setup_tracing(); + logger::tracing::setup_for_tests(); let sub_port = reserve_port::ReservedPort::random().unwrap(); let data_port = reserve_port::ReservedPort::random().unwrap(); @@ -121,7 +123,7 @@ async fn subscribe_and_receive() { #[tokio::test] async fn list_affectors() { - setup_tracing(); + logger::tracing::setup_for_tests(); let sub_port = reserve_port::ReservedPort::random().unwrap(); let data_port = reserve_port::ReservedPort::random().unwrap(); @@ -156,10 +158,11 @@ async fn recv_affector_order(data_port: u16) -> Result { .await .unwrap(); - let affector_order = tokio::time::timeout(Duration::from_secs(1), rx.recv()) - .await - .unwrap() - .unwrap(); + let affector_order = + tokio::time::timeout(Duration::from_secs(1), rx.recv()) + .await + .unwrap() + .unwrap(); assert_eq!(affector_order, TEST_AFFECTOR); @@ -168,7 +171,7 @@ async fn recv_affector_order(data_port: u16) -> Result { #[tokio::test] async fn recv_affector() { - setup_tracing(); + logger::tracing::setup_for_tests(); let sub_port = reserve_port::ReservedPort::random().unwrap(); let data_port = reserve_port::ReservedPort::random().unwrap(); @@ -179,26 +182,3 @@ async fn recv_affector() { }; assert_eq!(res.unwrap(), Done::Test); } - -fn setup_tracing() { - // use std::sync::Once; - // use tracing_error::ErrorLayer; - // use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt, Layer}; - // - // static INIT: Once = Once::new(); - // - // INIT.call_once(|| { - // color_eyre::install().unwrap(); - // - // let file_subscriber = tracing_subscriber::fmt::layer() - // .with_file(true) - // .with_line_number(true) - // .with_target(false) - // .with_ansi(false) - // .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()); - // tracing_subscriber::registry() - // .with(file_subscriber) - // .with(ErrorLayer::default()) - // .init(); - // }) -} diff --git a/crates/logger/Cargo.toml b/crates/logger/Cargo.toml index 2ff605db..960b78a8 100644 --- a/crates/logger/Cargo.toml +++ b/crates/logger/Cargo.toml @@ -14,3 +14,4 @@ tracing-journald = "0.3" libsystemd = "0.7" governor = "0.6.3" tracing-core = "0.1.32" +color-eyre.workspace = true diff --git a/crates/logger/src/tracing.rs b/crates/logger/src/tracing.rs index fc03b024..43909bba 100644 --- a/crates/logger/src/tracing.rs +++ b/crates/logger/src/tracing.rs @@ -1,19 +1,37 @@ use std::time::Duration; -use tracing::level_filters::LevelFilter; - use crate::ratelimited; +use tracing::level_filters::LevelFilter; +use tracing_error::ErrorLayer; +use tracing_subscriber::filter; +use tracing_subscriber::fmt; +use tracing_subscriber::util::SubscriberInitExt; +use tracing_subscriber::Layer; +use tracing_subscriber::{self, layer::SubscriberExt}; + /// # WARNING /// part of the filter syntax is broken (sad) /// see: https://github.com/tokio-rs/tracing/issues/1181 /// /// ## what does work -/// Filter directives like: `crate::module::submodule=trace,crate::module=info,error` +/// +/// ### log everything in module: +/// Filter directives like: +/// `RUST_LOG=crate::module::submodule=trace,crate::module=info,error` /// which logs everything in `submodule`, in `module` things are logged at level /// info, warn or error and for the rest of the crate and all dependencies only /// errors are logged /// +/// ### log everything in function +/// RUST_LOG='[function_name]=trace' +/// +/// ### Print if argument matches regex: +/// you can do this with: RUST_LOG='[{topic=.*small_bedroom:piano.*}]=trace,info' +/// that will print every log at trace level or higher that is inside an +/// instrumented function with an argument topic for which the regex +/// .*small_bedroom.* evaluates as true +/// /// ## what should work but only does so sporadically /// Filter directives allowing you to match field values (values recorded by for /// example `#[instrument]`), @@ -42,12 +60,6 @@ use crate::ratelimited; /// /// for full docs see: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html pub fn setup() { - use tracing_error::ErrorLayer; - use tracing_subscriber::filter; - use tracing_subscriber::fmt; - use tracing_subscriber::util::SubscriberInitExt; - use tracing_subscriber::{self, layer::SubscriberExt}; - let env_filter = filter::EnvFilter::builder() .with_regex(true) .try_from_env() @@ -75,7 +87,6 @@ pub fn setup() { let registry = tracing_subscriber::Registry::default().with(ErrorLayer::default()); - use tracing_subscriber::Layer; if libsystemd::logging::connected_to_journal() { match tracing_journald::layer() { @@ -106,3 +117,56 @@ pub fn setup() { tracing::info!("Started logging & tracing to stderr"); } } + +pub fn setup_unlimited() { + let env_filter = filter::EnvFilter::builder() + .with_regex(true) + .try_from_env() + .unwrap_or_else(|_| { + filter::EnvFilter::builder() + .with_default_directive(LevelFilter::INFO.into()) + .parse_lossy("") + }); + + let fmt = fmt::layer() + .pretty() + .with_writer(std::io::stderr) // to stderr as to not disrupt TUI's + .with_file(true) + .with_line_number(true) + .with_target(false) + .with_ansi(true); + + tracing_subscriber::Registry::default() + .with(ErrorLayer::default()) + .with(fmt.with_filter(env_filter)) + .init(); +} + +pub fn setup_for_tests() { + use std::sync::Once; + use tracing_error::ErrorLayer; + use tracing_subscriber::{ + self, layer::SubscriberExt, util::SubscriberInitExt, Layer, + }; + + static INIT: Once = Once::new(); + + INIT.call_once(|| { + color_eyre::install().unwrap(); + + let file_subscriber = tracing_subscriber::fmt::layer() + .with_test_writer() + .with_file(true) + .with_line_number(true) + .with_target(false) + .with_ansi(true) + .pretty() + .with_filter( + tracing_subscriber::filter::EnvFilter::from_default_env(), + ); + tracing_subscriber::registry() + .with(file_subscriber) + .with(ErrorLayer::default()) + .init(); + }) +} diff --git a/crates/radiator-bridge/.cargo/config.toml b/crates/radiator-bridge/.cargo/config.toml new file mode 100644 index 00000000..0127ae27 --- /dev/null +++ b/crates/radiator-bridge/.cargo/config.toml @@ -0,0 +1,5 @@ +[target.aarch64-unknown-linux-musl] +rustflags = ["-Clinker=rust-lld"] + +[target.armv7-unknown-linux-musleabihf] +rustflags = ["-Clinker=rust-lld"] diff --git a/crates/radiator-bridge/Cargo.toml b/crates/radiator-bridge/Cargo.toml new file mode 100644 index 00000000..15b09ad3 --- /dev/null +++ b/crates/radiator-bridge/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "radiator-bridge" +version = "0.1.0" +rust-version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true + +[dependencies] +protocol = { workspace = true, features = ["alloc"] } +data-server = { workspace = true } +zigbee-bridge = { workspace = true } + +tokio = { workspace = true } +clap = { workspace = true } +logger = { workspace = true } +tracing = { workspace = true } diff --git a/crates/radiator-bridge/deploy.sh b/crates/radiator-bridge/deploy.sh new file mode 100755 index 00000000..65f7205a --- /dev/null +++ b/crates/radiator-bridge/deploy.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -e + +BUILD_ARG=--release +SERVER="sgc" # ssh config name or full address +NAME=radiator-bridge + +cargo build --target=aarch64-unknown-linux-musl $BUILD_ARG +rsync -vh --progress \ + ../../target/aarch64-unknown-linux-musl/release/$NAME \ + $SERVER:/tmp/ + +cmds=" +sudo mv /tmp/$NAME /home/ha/$NAME +sudo chown ha:ha /home/ha/$NAME +sudo systemctl restart $NAME.service +" + +ssh -t $SERVER "$cmds" diff --git a/crates/radiator-bridge/src/main.rs b/crates/radiator-bridge/src/main.rs new file mode 100644 index 00000000..96652f0d --- /dev/null +++ b/crates/radiator-bridge/src/main.rs @@ -0,0 +1,129 @@ +use std::net::{IpAddr, SocketAddr}; +use std::time::{Duration, Instant}; + +use clap::Parser; +use data_server::api::subscriber::ReconnectingClient; +use data_server::api::subscriber::SubMessage as M; + +#[derive(Parser)] +#[command(version, about, long_about=None)] +struct Opt { + /// IP address where to subscribe for updates + #[clap(long)] + data_server: SocketAddr, + + /// IP address for MQTT broker + #[clap(long)] + mqtt_ip: IpAddr, +} + +enum RelevantMsg { + SmallBedroom(f64), + LargeBedroom(f64), +} + +#[derive(Debug, Default)] +struct RadiatorState { + last_set_at: Option, + last_set_value: Option, +} + +impl RadiatorState { + // You *must* set the `External_measured_room_sensor` property *at least* + // every 3 hours. After 3 hours the TRV disables this function and resets + // the value of the `External_measured_room_sensor` property to -8000 + // (disabled). + // + // You *should* set the `External_measured_room_sensor` + // property *at most* every 30 minutes or every 0.1°C change in measured + // room temperature. + // + // If `Radiator_covered` is `true` (Room Sensor Mode): + // You *must* set the `External_measured_room_sensor` property *at least* + // every 30 minutes. After 35 minutes the TRV disables this function and + // resets the value of the `External_measured_room_sensor` property to + // -8000 (disabled). + // + // You *should* set the `External_measured_room_sensor` + // property *at most* every 5 minutes or every 0.1°C change in measured + // room temperature. The unit of this value is 0.01 `°C` (so e.g. 21°C + // would be represented as 2100). + fn should_update_given(&mut self, temp: f64) -> bool { + const T30MINUTES: Duration = Duration::from_secs(60 * 30); + + if self + .last_set_value + .is_none_or(|val| (val - temp).abs() >= 0.1) + || self.last_set_at.is_none_or(|at| at.elapsed() > T30MINUTES) + { + self.last_set_at = Some(Instant::now()); + self.last_set_value = Some(temp); + true + } else { + false + } + } +} + +// #[tokio::main(flavor = "current_thread")] +#[tokio::main] +async fn main() { + let args = Opt::parse(); + logger::tracing::setup_unlimited(); + + let mut data_server = ReconnectingClient::new( + args.data_server, + env!("CARGO_PKG_NAME").to_owned(), + ) + .subscribe(); + + let zigbee = + zigbee_bridge::Controller::start_bridge(args.mqtt_ip, "temp-bridge"); + let mut lb_ratiator = RadiatorState::default(); + let mut sb_ratiator = RadiatorState::default(); + + loop { + let msg = data_server.next().await; + let Some(relevant_msg) = RelevantMsg::from(msg) else { + continue; + }; + + match relevant_msg { + RelevantMsg::SmallBedroom(temp) => { + if sb_ratiator.should_update_given(temp) { + zigbee + .set_radiator_reference("small_bedroom:radiator", temp) + } + } + RelevantMsg::LargeBedroom(temp) => { + if lb_ratiator.should_update_given(temp) { + tracing::info!("setting temp"); + zigbee + .set_radiator_reference("large_bedroom:radiator", temp) + } + } + } + } +} + +impl RelevantMsg { + fn from(msg: M) -> Option { + use protocol::large_bedroom; + use protocol::large_bedroom::desk as ldesk; + use protocol::small_bedroom; + use protocol::small_bedroom::desk as sdesk; + use protocol::Reading; + + match msg { + M::Reading(Reading::LargeBedroom( + large_bedroom::Reading::Desk(ldesk::Reading::Temperature(temp)), + )) => Some(RelevantMsg::LargeBedroom(temp as f64)), + M::Reading(Reading::SmallBedroom( + small_bedroom::Reading::Desk(sdesk::Reading::Temperature(temp)), + )) => Some(RelevantMsg::SmallBedroom(temp as f64)), + M::ErrorReport(_) + | M::Reading(_) + | M::AffectorControlled { .. } => None, + } + } +} diff --git a/crates/radiator-bridge/test.sh b/crates/radiator-bridge/test.sh new file mode 100755 index 00000000..16dcc55f --- /dev/null +++ b/crates/radiator-bridge/test.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +# Print if argument matches regex: +# +# you can do this with: RUST_LOG='[{topic=.*small_bedroom:piano.*}]=trace,info' +# that will print every log at trace level or higher that is inside an +# instrumented function with an argument topic for which the regex +# .*small_bedroom.* evaluates as true +# +# +# Print if in function: +# RUST_LOG='[function_name]=trace' + +RUST_LOG='[parse_message]=trace,[{device_name=.*:radi.*}]=trace,[{friendly_name=.*:radi.*}]=trace,info' cargo r -- \ + --data-server=192.168.1.43:1235 \ + --mqtt-ip=192.168.1.43 diff --git a/crates/zigbee-bridge/Cargo.toml b/crates/zigbee-bridge/Cargo.toml index 5d3afca2..a6ee34dd 100644 --- a/crates/zigbee-bridge/Cargo.toml +++ b/crates/zigbee-bridge/Cargo.toml @@ -22,3 +22,7 @@ logger = { workspace = true } color-eyre.workspace = true itertools = "0.13.0" regex = "1.11.1" +rand = "0.8.5" + +[dev-dependencies] +logger.workspace = true diff --git a/crates/zigbee-bridge/src/tests.rs b/crates/zigbee-bridge/examples/change_fridge_light.rs similarity index 51% rename from crates/zigbee-bridge/src/tests.rs rename to crates/zigbee-bridge/examples/change_fridge_light.rs index 52bf2219..f25f0966 100644 --- a/crates/zigbee-bridge/src/tests.rs +++ b/crates/zigbee-bridge/examples/change_fridge_light.rs @@ -1,12 +1,14 @@ -use crate::Controller; +use zigbee_bridge::Controller; use std::time::Duration; -#[ignore] -#[tokio::test] -async fn change_fridge_light() { - std::env::set_var("RUST_LOG", "brain=trace,zigbee_bridge=trace,info"); - let controller = - Controller::start_bridge("192.168.1.43".parse().unwrap()); +#[tokio::main] +async fn main() { + logger::tracing::setup_for_tests(); + + let controller = Controller::start_bridge( + "192.168.1.43".parse().unwrap(), + "test change fridge light", + ); let light = "kitchen:fridge"; println!("Setting to on, 2200"); @@ -32,16 +34,3 @@ async fn change_fridge_light() { let () = std::future::pending().await; unreachable!(); } - -#[tokio::test] -async fn change_radiator_temp() { - std::env::set_var("RUST_LOG", "brain=trace,zigbee_bridge=trace,info"); - let controller = - Controller::start_bridge("192.168.1.43".parse().unwrap()); - let radiator = "small_bedroom:radiator"; - - controller.set_radiator_setpoint(radiator, 22.); - - let () = std::future::pending().await; - unreachable!(); -} diff --git a/crates/zigbee-bridge/examples/change_radiator_reference.rs b/crates/zigbee-bridge/examples/change_radiator_reference.rs new file mode 100644 index 00000000..308755e2 --- /dev/null +++ b/crates/zigbee-bridge/examples/change_radiator_reference.rs @@ -0,0 +1,17 @@ +use zigbee_bridge::Controller; + +#[tokio::main] +async fn main() { + logger::tracing::setup_for_tests(); + + let controller = Controller::start_bridge( + "192.168.1.43".parse().unwrap(), + "test change radiator temp", + ); + let radiator = "small_bedroom:radiator"; + + controller.set_radiator_reference(radiator, 22.); + + let () = std::future::pending().await; + unreachable!(); +} diff --git a/crates/zigbee-bridge/examples/change_radiator_set_point.rs b/crates/zigbee-bridge/examples/change_radiator_set_point.rs new file mode 100644 index 00000000..4e47998e --- /dev/null +++ b/crates/zigbee-bridge/examples/change_radiator_set_point.rs @@ -0,0 +1,17 @@ +use zigbee_bridge::Controller; + +#[tokio::main] +async fn main() { + logger::tracing::setup_for_tests(); + + let controller = Controller::start_bridge( + "192.168.1.43".parse().unwrap(), + "test change radiator temp", + ); + let radiator = "small_bedroom:radiator"; + + controller.set_radiator_setpoint(radiator, 22.); + + let () = std::future::pending().await; + unreachable!(); +} diff --git a/crates/zigbee-bridge/src/cached_bridge.rs b/crates/zigbee-bridge/src/cached_bridge.rs index 92d479f0..fe80e205 100644 --- a/crates/zigbee-bridge/src/cached_bridge.rs +++ b/crates/zigbee-bridge/src/cached_bridge.rs @@ -22,11 +22,13 @@ const CHANGE_ACCUMULATION_TIME: Duration = Duration::from_millis(100); pub(super) async fn run( mqtt_ip: IpAddr, change_receiver: mpsc::UnboundedReceiver<(String, Property)>, + name: String, ) -> ! { - let mut options = - MqttOptions::new("ha-lightcontroller", mqtt_ip.to_string(), MQTT_PORT); + // The id string must be random or subscribe does not work + let id = name + " " + &rand::random::().to_string(); + let mut options = MqttOptions::new(id, mqtt_ip.to_string(), MQTT_PORT); // Set max mqtt packet size to 4kB - options.set_max_packet_size(Some(4096)); + options.set_max_packet_size(Some(8192)); // Keep subscriptions when reconnecting!!!! options.set_clean_start(false); diff --git a/crates/zigbee-bridge/src/cached_bridge/changes.rs b/crates/zigbee-bridge/src/cached_bridge/changes.rs index 0751c3d9..07f0e910 100644 --- a/crates/zigbee-bridge/src/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/cached_bridge/changes.rs @@ -31,7 +31,7 @@ pub(super) async fn handle( let (device_name, change) = update.expect("Channel should never close"); - trace!("Received change: {change:?} for device {device_name}"); + tracing::info!("Received change order: {change:?} for device {device_name}"); apply_change_to_needed( device_name, change, @@ -105,7 +105,7 @@ async fn send_diff_get_timeout( .unwrap_or(Duration::MAX) } -#[instrument(skip_all)] +#[instrument(skip(known_states, needed_states))] async fn apply_change_to_needed( device_name: String, change: Property, @@ -115,9 +115,7 @@ async fn apply_change_to_needed( let known_states = known_states.read().await; let Some(known) = known_states.get(&device_name) else { - error!( - "Unknown device name {device_name}, not applying change {change:?}!" - ); + error!("Unknown device name, not applying change!"); return; }; diff --git a/crates/zigbee-bridge/src/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/cached_bridge/mqtt.rs index 7c318eaf..4ddec45e 100644 --- a/crates/zigbee-bridge/src/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/cached_bridge/mqtt.rs @@ -4,7 +4,7 @@ use std::time::Instant; use rumqttc::v5::mqttbytes::QoS; use rumqttc::v5::{AsyncClient, ClientError}; use serde_json::json; -use tracing::{trace, warn}; +use tracing::{instrument, trace, warn}; use crate::device::{Property, PropertyDiscriminants}; @@ -13,10 +13,8 @@ use super::TIME_IT_TAKES_TO_APPLY_CHANGE; pub(super) struct Mqtt { client: AsyncClient, // TODO: extract into SendTracker struct? - last_sent: HashMap< - String, - HashMap, - >, + last_sent: + HashMap>, } impl Mqtt { @@ -54,11 +52,7 @@ impl Mqtt { .min() } - fn change_next_due( - &self, - device_name: &str, - change: &Property, - ) -> Instant { + fn change_next_due(&self, device_name: &str, change: &Property) -> Instant { let Some(device_send_record) = self.last_sent.get(device_name) else { // lamp has never been sent before return Instant::now(); @@ -123,6 +117,7 @@ impl Mqtt { Ok(()) } + #[instrument(skip(self))] async fn set( &self, friendly_name: &str, @@ -130,7 +125,7 @@ impl Mqtt { ) -> Result<(), ClientError> { let topic = format!("zigbee2mqtt/{friendly_name}/set"); - trace!("Sending payload {payload} to device {friendly_name}"); + trace!("Sending"); self.publish(&topic, payload).await?; Ok(()) } @@ -146,6 +141,7 @@ impl Mqtt { Ok(()) } + #[instrument(skip(self))] async fn publish( &self, topic: &str, @@ -156,9 +152,7 @@ impl Mqtt { ..Default::default() }; - if topic.contains("small_bedroom:piano") { - warn!("ZB to MQTT (piano): {payload}"); - } + trace!("publishing"); self.client .publish_with_properties( topic, diff --git a/crates/zigbee-bridge/src/cached_bridge/poll.rs b/crates/zigbee-bridge/src/cached_bridge/poll.rs index 7ed7d2af..b2d2e631 100644 --- a/crates/zigbee-bridge/src/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/cached_bridge/poll.rs @@ -46,6 +46,7 @@ pub(super) async fn poll_mqtt( } } +#[instrument(skip(known_states))] async fn update_state( known_states: &RwLock>>, device_name: &str, @@ -53,31 +54,11 @@ async fn update_state( ) { let mut known_states = known_states.write().await; let Some(current_device) = known_states.get_mut(device_name) else { - error!("Trying to update state for unknown device: {device_name}, ignoring!"); + error!("Trying to update state for unknown device, ignoring!"); return; }; + trace!("applying properties"); for property in new { - if device_name == "small_bedroom:piano" { - if let Property::Lamp(lamp_prop) = property { - match lamp_prop { - LampProperty::Brightness(bri) => { - warn!("ZB received piano brightness change: {bri}"); - } - LampProperty::ColorXY(xy) => { - warn!("ZB received piano color change: {xy:?}"); - } - LampProperty::Online(new_online) => { - if new_online != current_device.is_online() { - warn!( - "ZB received piano online change: {new_online}" - ); - } - } - _ => (), - } - } - } - current_device.apply(property); } } @@ -92,9 +73,7 @@ fn parse_message(event: Event) -> color_eyre::Result { return Ok(Message::Other); }; - trace!("message: {message:?}"); let topic: &str = &String::from_utf8_lossy(&message.topic); - match topic { "zigbee2mqtt/bridge/event" => { let json: Value = serde_json::from_slice(&message.payload) diff --git a/crates/zigbee-bridge/src/conversion.rs b/crates/zigbee-bridge/src/conversion.rs index 4ede4860..849843e7 100644 --- a/crates/zigbee-bridge/src/conversion.rs +++ b/crates/zigbee-bridge/src/conversion.rs @@ -49,17 +49,3 @@ fn xyz_to_xy(xyz: XYZ) -> (f64, f64) { let [x, y, z] = xyz.values(); (x / (x + y + z), y / (x + y + z)) } - -#[cfg(test)] -mod tests { - use super::*; - - #[ignore] - #[test] - fn temp_to_xy_works() { - dbg!(temp_to_xy(2200)); - dbg!(temp_to_xy(2500)); - dbg!(temp_to_xy(3000)); - dbg!(temp_to_xy(4000)); - } -} diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index b32cc338..2ceabe46 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -14,8 +14,6 @@ mod device; pub(crate) mod lamp; mod parse_state; mod radiator; -#[cfg(test)] -mod tests; const MQTT_PORT: u16 = 1883; const LIGHT_MODELS: [(&str, Model); 16] = [ @@ -50,10 +48,10 @@ pub struct Controller { impl Controller { #[must_use] - pub fn start_bridge(mqtt_ip: IpAddr) -> Self { + pub fn start_bridge(mqtt_ip: IpAddr, name: &str) -> Self { let (change_sender, change_receiver) = mpsc::unbounded_channel(); - let run_bridge = cached_bridge::run(mqtt_ip, change_receiver); + let run_bridge = cached_bridge::run(mqtt_ip, change_receiver, name.to_string()); trace!("Spawning zigbee bridge task"); tokio::task::spawn(run_bridge); diff --git a/crates/zigbee-bridge/src/parse_state.rs b/crates/zigbee-bridge/src/parse_state.rs index cde09a32..ea929b01 100644 --- a/crates/zigbee-bridge/src/parse_state.rs +++ b/crates/zigbee-bridge/src/parse_state.rs @@ -1,7 +1,7 @@ use color_eyre::eyre::{bail, Context, OptionExt, Report}; use color_eyre::Section; use serde_json::Value; -use tracing::error; +use tracing::instrument; use crate::conversion::{mired_to_kelvin, normalize}; use crate::device::Property; @@ -9,6 +9,7 @@ use crate::lamp::LampProperty; use crate::radiator::RadiatorProperty; use crate::{light_names, RADIATOR_NAMES}; +#[instrument(skip(bytes))] pub(super) fn parse_properties( device_name: &str, bytes: &[u8], @@ -18,9 +19,7 @@ pub(super) fn parse_properties( } else if RADIATOR_NAMES.contains(&device_name) { parse_radiator_properties(bytes) } else { - error!("Unknown device name {device_name}, could not parse properties"); - // TODO make actual error - return Ok(Vec::new()); + bail!("Unknown device name, could not parse properties"); } } @@ -62,6 +61,7 @@ fn parse_radiator_properties(bytes: &[u8]) -> Result, Report> { list.push(RadiatorProperty::SetByMethod(set_method).into()); } + tracing::info!("list: {list:?}"); Ok(list) } diff --git a/crates/zigbee-bridge/src/radiator.rs b/crates/zigbee-bridge/src/radiator.rs index ef43e42f..7732a57f 100644 --- a/crates/zigbee-bridge/src/radiator.rs +++ b/crates/zigbee-bridge/src/radiator.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, str::FromStr}; use serde_json::json; use strum::{EnumDiscriminants, EnumIter, IntoEnumIterator}; -use tracing::error; +use tracing::{error, instrument}; use crate::{ conversion::{round_to_half, times_100_int}, @@ -57,6 +57,7 @@ impl Device for Radiator { Box::new(self.clone()) } + #[instrument] fn apply(&mut self, change: Property) { let Property::Radiator(change) = change else { error!( From 462fff6855f5ee7f4f2c3f87c82e61bb193f0e5e Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 23 Dec 2024 12:06:40 +0100 Subject: [PATCH 502/687] Fix? Ikea lights only partially responding Add a sleep between non-merged sends, so that they don't bombard the light with updates. Hopefully this fixes the issue. --- crates/zigbee-bridge/src/cached_bridge.rs | 1 + crates/zigbee-bridge/src/cached_bridge/mqtt.rs | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/zigbee-bridge/src/cached_bridge.rs b/crates/zigbee-bridge/src/cached_bridge.rs index fe80e205..75ab8c41 100644 --- a/crates/zigbee-bridge/src/cached_bridge.rs +++ b/crates/zigbee-bridge/src/cached_bridge.rs @@ -18,6 +18,7 @@ const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); // the z2m queue from getting filled up const TIME_IT_TAKES_TO_APPLY_CHANGE: Duration = Duration::from_secs(10); const CHANGE_ACCUMULATION_TIME: Duration = Duration::from_millis(100); +const MIN_TIME_BETWEEN_SENDS: Duration = Duration::from_millis(10); pub(super) async fn run( mqtt_ip: IpAddr, diff --git a/crates/zigbee-bridge/src/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/cached_bridge/mqtt.rs index 4ddec45e..c9bce9ff 100644 --- a/crates/zigbee-bridge/src/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/cached_bridge/mqtt.rs @@ -4,11 +4,12 @@ use std::time::Instant; use rumqttc::v5::mqttbytes::QoS; use rumqttc::v5::{AsyncClient, ClientError}; use serde_json::json; +use tokio::time::sleep; use tracing::{instrument, trace, warn}; use crate::device::{Property, PropertyDiscriminants}; -use super::TIME_IT_TAKES_TO_APPLY_CHANGE; +use super::{MIN_TIME_BETWEEN_SENDS, TIME_IT_TAKES_TO_APPLY_CHANGE}; pub(super) struct Mqtt { client: AsyncClient, @@ -110,6 +111,7 @@ impl Mqtt { for change in due_changes { self.set(&device_name, change.payload().to_string()) .await?; + sleep(MIN_TIME_BETWEEN_SENDS).await; } } } From 2c0ef0d47da3b4bbcd73a9bc643fa29fa68117a9 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 23 Dec 2024 12:25:11 +0100 Subject: [PATCH 503/687] Fix? conflicts between zigbee-bridge instances Don't derive needed from known anymore, so only a change within the same zigbee-bridge instance can ever trigger an update. --- crates/zigbee-bridge/src/cached_bridge.rs | 9 +++-- .../src/cached_bridge/changes.rs | 33 +++++++------------ 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/crates/zigbee-bridge/src/cached_bridge.rs b/crates/zigbee-bridge/src/cached_bridge.rs index 75ab8c41..5e4817b5 100644 --- a/crates/zigbee-bridge/src/cached_bridge.rs +++ b/crates/zigbee-bridge/src/cached_bridge.rs @@ -34,6 +34,7 @@ pub(super) async fn run( options.set_clean_start(false); let known_states = RwLock::new(init_states()); + let needed_states = init_states(); // Reconnecting to broker is handled by Eventloop::poll let channel_capacity = 128; @@ -58,8 +59,12 @@ pub(super) async fn run( trace!("Starting main zigbee management loops"); let poll_mqtt = poll::poll_mqtt(eventloop, &known_states); - let handle_changes = - changes::handle(change_receiver, &mut mqtt, &known_states); + let handle_changes = changes::handle( + change_receiver, + &mut mqtt, + &known_states, + needed_states, + ); tokio::select! { () = handle_changes => unreachable!("should not panic"), diff --git a/crates/zigbee-bridge/src/cached_bridge/changes.rs b/crates/zigbee-bridge/src/cached_bridge/changes.rs index 07f0e910..8faefa86 100644 --- a/crates/zigbee-bridge/src/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/cached_bridge/changes.rs @@ -3,7 +3,7 @@ use std::time::{Duration, Instant}; use tokio::sync::{mpsc, RwLock}; use tokio::time::{sleep, timeout}; -use tracing::{debug, error, instrument, trace}; +use tracing::{debug, error, instrument}; use super::mqtt::Mqtt; use super::{ @@ -15,11 +15,13 @@ pub(super) async fn handle( mut change_receiver: mpsc::UnboundedReceiver<(String, Property)>, mqtt: &mut Mqtt, known_states: &RwLock>>, + // Must be passed so it can be statically initialized in cached_bridge + // with concrete types + mut needed_states: HashMap>, ) -> ! { // Give the initial known states a chance to be fetched sleep(WAIT_FOR_INIT_STATES).await; - let mut needed_states = HashMap::new(); let mut call_at_least_in = MQTT_MIGHT_BE_DOWN_TIMEOUT; loop { @@ -32,13 +34,7 @@ pub(super) async fn handle( update.expect("Channel should never close"); tracing::info!("Received change order: {change:?} for device {device_name}"); - apply_change_to_needed( - device_name, - change, - known_states, - &mut needed_states, - ) - .await; + apply_change_to_needed(device_name, change, &mut needed_states); // When there hasn't been a new change in 100 ms, we will timeout // and send the accumulated changes @@ -48,7 +44,7 @@ pub(super) async fn handle( // Send the accumulated changes and get the timeout for resending call_at_least_in = send_diff_get_timeout( known_states, - &mut needed_states, + &needed_states, mqtt, ) .await @@ -66,7 +62,7 @@ pub(super) async fn handle( #[instrument(skip_all)] async fn send_diff_get_timeout( known_states: &RwLock>>, - needed_states: &mut HashMap>, + needed_states: &HashMap>, mqtt: &mut Mqtt, ) -> Duration { let known_states = known_states.read().await; @@ -105,25 +101,18 @@ async fn send_diff_get_timeout( .unwrap_or(Duration::MAX) } -#[instrument(skip(known_states, needed_states))] -async fn apply_change_to_needed( +#[instrument(skip(needed_states))] +fn apply_change_to_needed( device_name: String, change: Property, - known_states: &RwLock>>, needed_states: &mut HashMap>, ) { - let known_states = known_states.read().await; - - let Some(known) = known_states.get(&device_name) else { + let Some(needed) = needed_states.get(&device_name) else { error!("Unknown device name, not applying change!"); return; }; - let mut needed = match needed_states.get(&device_name) { - Some(needed) => needed.clone(), - None => known.clone(), - }; - + let mut needed = needed.clone(); needed.apply(change); needed_states.insert(device_name, needed.clone()); } From b28bee2e0065a05bd4db8003ca9169a49416a819 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 24 Dec 2024 11:49:31 +0100 Subject: [PATCH 504/687] Fix radiator parsing and color eyre logging Radiator reporting -8000 for reference temp (expired) is now ignored, keeping known state the same --- Cargo.lock | 1 + crates/brain/Cargo.toml | 1 + crates/brain/src/main.rs | 1 + .../zigbee-bridge/src/cached_bridge/poll.rs | 6 +++--- crates/zigbee-bridge/src/parse_state.rs | 19 ++++++++++++++++--- crates/zigbee-bridge/src/radiator.rs | 9 +++++++++ 6 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ddff632a..bec5a819 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -473,6 +473,7 @@ dependencies = [ "byteorder", "bytes", "clap", + "color-eyre", "data-server", "dbstruct", "futures", diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 2ac1dcb3..b4bef717 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -42,3 +42,4 @@ clap = { workspace = true } futures-concurrency = { workspace = true } strum = { version = "0.26.2", default-features = false, features = ["derive"] } dbstruct = { git = "https://github.com/dvdsk/dbstruct" } +color-eyre.workspace = true diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index d0f4b3a4..d1f79696 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -38,6 +38,7 @@ struct Opt { #[tokio::main] async fn main() -> Result<(), Box> { + color_eyre::install().unwrap(); logger::tracing::setup(); let opt = Opt::parse(); diff --git a/crates/zigbee-bridge/src/cached_bridge/poll.rs b/crates/zigbee-bridge/src/cached_bridge/poll.rs index b2d2e631..e792de01 100644 --- a/crates/zigbee-bridge/src/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/cached_bridge/poll.rs @@ -31,7 +31,7 @@ pub(super) async fn poll_mqtt( let message = match parse_message(message) { Ok(message) => message, Err(err) => { - warn!("ZB error parsing mqtt message: {err}"); + warn!("ZB error parsing mqtt message: {err:?}"); continue; } }; @@ -54,7 +54,7 @@ async fn update_state( ) { let mut known_states = known_states.write().await; let Some(current_device) = known_states.get_mut(device_name) else { - error!("Trying to update state for unknown device, ignoring!"); + error!("Trying to update state for unknown device {device_name}, ignoring!"); return; }; trace!("applying properties"); @@ -97,7 +97,7 @@ fn parse_message(event: Event) -> color_eyre::Result { let topic: Vec<_> = topic.split('/').collect(); let device_name = topic[1].to_string(); let state = parse_properties(&device_name, &message.payload) - .wrap_err("failed to parse lamp state") + .wrap_err("failed to parse device state") .with_note(|| format!("topic: {topic:?}"))?; Ok(Message::StateUpdate((device_name, state))) } diff --git a/crates/zigbee-bridge/src/parse_state.rs b/crates/zigbee-bridge/src/parse_state.rs index ea929b01..6c528c7c 100644 --- a/crates/zigbee-bridge/src/parse_state.rs +++ b/crates/zigbee-bridge/src/parse_state.rs @@ -42,11 +42,15 @@ fn parse_radiator_properties(bytes: &[u8]) -> Result, Report> { if let Some(reference) = map .get("external_measured_room_sensor") - .map(json_to_usize) + .map(json_to_i64) .transpose()? - .map(|int| int as f64 / 100.) { - list.push(RadiatorProperty::Reference(reference).into()); + if reference == -8000 { + list.push(RadiatorProperty::NoReference.into()); + } else { + let reference = reference as f64 / 100.; + list.push(RadiatorProperty::Reference(reference).into()); + } } if let Some(set_method) = map @@ -154,6 +158,15 @@ fn json_to_u64(json: &Value) -> color_eyre::Result { .with_note(|| format!("got: {json:?}")) } +fn json_to_i64(json: &Value) -> color_eyre::Result { + json.as_number() + .ok_or_eyre("Must be a number") + .with_note(|| format!("got: {json:?}"))? + .as_i64() + .ok_or_eyre("Must be an integer") + .with_note(|| format!("got: {json:?}")) +} + fn json_to_f64(json: &Value) -> color_eyre::Result { Ok(json .as_number() diff --git a/crates/zigbee-bridge/src/radiator.rs b/crates/zigbee-bridge/src/radiator.rs index 7732a57f..47d9edab 100644 --- a/crates/zigbee-bridge/src/radiator.rs +++ b/crates/zigbee-bridge/src/radiator.rs @@ -74,6 +74,9 @@ impl Device for Radiator { RadiatorProperty::Reference(reference) => { self.reference = Some(reference) } + // Ignore radiator reporting reference expired, so we don't start + // sending an old value + RadiatorProperty::NoReference => (), RadiatorProperty::SetByMethod(set_method) => { self.set_by_method = Some(set_method) } @@ -145,6 +148,7 @@ pub(crate) enum RadiatorProperty { Online(bool), Setpoint(f64), Reference(f64), + NoReference, SetByMethod(SetMethod), } @@ -179,6 +183,11 @@ impl RadiatorProperty { json!({"external_measured_room_sensor": times_100_int(reference) }) } // read-only, shouldn't be called, safe default + RadiatorProperty::NoReference => { + error!("Tried to convert NoReference to payload"); + json!({"state": ""}) + } + // read-only, shouldn't be called, safe default RadiatorProperty::Online(_) => { error!("Tried to convert Online to payload"); json!({"state": ""}) From d960441266a306ad93bebc08298d7909326419c2 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 24 Dec 2024 12:17:15 +0100 Subject: [PATCH 505/687] Change small bedroom and kitchen light behavior Tweaks and nap behavior --- crates/brain/src/controller/rooms/kitchen.rs | 10 ++++-- .../src/controller/rooms/small_bedroom.rs | 35 +++++++++++++------ .../controller/rooms/small_bedroom/state.rs | 15 ++++++-- 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index 6f2ed039..cfe13756 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -2,12 +2,14 @@ use std::time::Duration; use futures_concurrency::future::Race; use futures_util::FutureExt; +use jiff::civil::Time; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; use tracing::warn; use crate::controller::rooms::small_bedroom; use crate::controller::{Event, RestrictedSystem}; +use crate::time; #[derive(PartialEq, Eq)] enum State { @@ -77,7 +79,11 @@ pub async fn run( match res { Res::Event(RelevantEvent::Sleep) => { state = State::Sleep; - system.all_lamps_but_one_off("kitchen:hallway").await; + if small_bedroom::is_nap_time() { + system.all_lamps_off().await; + } else { + system.all_lamps_but_one_off("kitchen:hallway").await; + } } Res::Event(RelevantEvent::Daylight) => { state = State::Daylight; @@ -85,7 +91,7 @@ pub async fn run( // TODO: only when LB also awake // then turn all lamps off when SB sleep system.all_lamps_on().await; - }, + } Res::ShouldUpdate if state == State::Daylight => { update(&mut system).await; system.all_lamps_on().await; diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index befbb796..8523713d 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -2,16 +2,18 @@ use std::time::Duration; use futures_concurrency::future::Race; use futures_util::FutureExt; +use jiff::civil::Time; use protocol::small_bedroom::ButtonPanel; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; -use tracing::{info, trace, warn}; +use tracing::trace; use self::filter::{recv_filtered, RelevantEvent, Trigger}; use self::state::Room; pub(crate) use self::state::State; use crate::controller::{Event, RestrictedSystem}; use crate::input::jobs::Job; +use crate::time; mod filter; mod state; @@ -19,6 +21,7 @@ mod state; const UPDATE_INTERVAL: Duration = Duration::from_secs(5); const OFF_DELAY: Duration = Duration::from_secs(60); const WAKEUP_EXPIRATION: Duration = Duration::from_secs(60); +const NAP_TIME: Duration = Duration::from_secs(30 * 60); const fn time(hour: i8, minute: i8) -> f64 { hour as f64 + minute as f64 / 60. @@ -26,7 +29,9 @@ const fn time(hour: i8, minute: i8) -> f64 { const T0_00: f64 = time(0, 0); const T8_00: f64 = time(8, 0); const T9_00: f64 = time(9, 0); +const T16_00: f64 = time(16, 0); const T17_00: f64 = time(17, 0); +const T18_00: f64 = time(18, 0); const T20_30: f64 = time(20, 30); const T21_30: f64 = time(21, 30); const T22_00: f64 = time(22, 0); @@ -40,15 +45,14 @@ pub async fn run( let mut room = Room::new(event_tx, system.clone()); let mut next_update = Instant::now() + UPDATE_INTERVAL; - // let soon = crate::time::now().checked_add(1.minutes()).unwrap(); - let wakeup_job = Job::every_day_at( - 8, - 57, - Event::WakeupSB, - Some(WAKEUP_EXPIRATION), - ); + let wakeup_job = + Job::every_day_at(8, 47, Event::WakeupSB, Some(WAKEUP_EXPIRATION)); - let res = system.system.jobs.remove_all_with_event(Event::WakeupSB).await; + let res = system + .system + .jobs + .remove_all_with_event(Event::WakeupSB) + .await; trace!("Removing old SB wakeup jobs returned: {res:#?}"); let res = system.system.jobs.add(wakeup_job.clone()).await; trace!("Tried to add job for SB wakeup: {wakeup_job:#?}"); @@ -92,14 +96,23 @@ async fn handle_buttonpress(room: &mut Room, button: ButtonPanel) { } } +pub(super) fn is_nap_time() -> bool { + let now = time::now().datetime().time(); + + now > Time::new(13, 0, 0, 0).unwrap() + && now < Time::new(20, 0, 0, 0).unwrap() +} + // TODO: move to jobs system and remove update trigger pub(super) fn daylight_now() -> (usize, f64) { let now = crate::time::now(); match time(now.hour(), now.minute()) { T8_00..T9_00 => (2000, 0.5), - T9_00..T17_00 => (3500, 1.0), - T17_00..T20_30 => (2300, 1.0), + T9_00..T16_00 => (4000, 1.0), + T16_00..T17_00 => (3500, 1.0), + T17_00..T18_00 => (2800, 1.0), + T18_00..T20_30 => (2300, 1.0), T20_30..T21_30 => (2000, 0.7), T21_30..T22_00 => (1900, 0.4), T22_00.. | T0_00..T8_00 => (1800, 0.1), diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index 4dbeedc7..f83d4ba8 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -7,7 +7,7 @@ use tokio::task::{self, JoinHandle}; use tokio::time::sleep; use tracing::warn; -use super::{daylight_now, OFF_DELAY}; +use super::{daylight_now, is_nap_time, NAP_TIME, OFF_DELAY}; use crate::controller::{Event, RestrictedSystem}; #[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)] @@ -67,7 +67,9 @@ impl Room { pub(super) async fn to_nightlight(&mut self) { self.to_state_cancel_prev(State::Nightlight).await; - self.system.one_lamp_ct("small_bedroom:ceiling", 1800, 0.1).await; + self.system + .one_lamp_ct("small_bedroom:ceiling", 1800, 0.1) + .await; self.system.one_lamp_on("small_bedroom:ceiling").await; } @@ -98,11 +100,18 @@ impl Room { sleep(OFF_DELAY).await; self.system.all_lamps_off().await; self.to_state(State::Sleep).await; + + if is_nap_time() { + sleep(NAP_TIME).await; + self.to_state(State::Daylight).await; + self.all_lights_daylight().await; + self.system.all_lamps_on().await; + } } async fn run_wakeup_then_daylight(mut self) { const LIGHT_NAME: &str = "small_bedroom:piano"; - const RUNTIME_MINS: i32 = 10; + const RUNTIME_MINS: i32 = 20; const STEP_SIZE_SECS: i32 = 30; const N_STEPS: i32 = RUNTIME_MINS * 60 / STEP_SIZE_SECS; From f2459019d793756131b20e8300deb54b95a9cde2 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 25 Dec 2024 17:45:53 +0100 Subject: [PATCH 506/687] expand byteseries error handling in data-store --- Cargo.lock | 419 ++++++++++++---------- Cargo.toml | 2 +- crates/data-store/Cargo.toml | 1 + crates/data-store/src/server/db.rs | 55 ++- crates/data-store/src/server/db/series.rs | 75 ++-- 5 files changed, 317 insertions(+), 235 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a0a189c6..65538ada 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,9 +34,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "anstream" @@ -143,7 +143,7 @@ checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ "async-task", "concurrent-queue", - "fastrand 2.2.0", + "fastrand 2.3.0", "futures-lite 2.5.0", "slab", ] @@ -293,7 +293,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -340,7 +340,7 @@ dependencies = [ "pin-project-lite", "rustversion", "serde", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", "tower", "tower-layer", @@ -362,7 +362,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.2", + "sync_wrapper", "tower-layer", "tower-service", ] @@ -375,7 +375,7 @@ checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -488,7 +488,7 @@ dependencies = [ "serde_yaml", "sled", "strum", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "tz-rs", @@ -509,9 +509,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.20.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" [[package]] name = "byteorder" @@ -521,22 +521,22 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "byteseries" version = "0.7.1" -source = "git+https://github.com/dvdsk/byteseries#eb057c6363548fa1fc2fbe5a89395b81238152f5" +source = "git+https://github.com/dvdsk/byteseries?rev=90efa57d021d39bc9cb4d9151c3a88acdbe62e25#90efa57d021d39bc9cb4d9151c3a88acdbe62e25" dependencies = [ "arraydeque", "itertools 0.13.0", "num-traits", "ron", "serde", - "smallvec 2.0.0-alpha.7", - "thiserror", + "smallvec 2.0.0-alpha.9", + "thiserror 1.0.69", "tracing", ] @@ -563,9 +563,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.1" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" +checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" dependencies = [ "shlex", ] @@ -584,9 +584,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -594,9 +594,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -613,14 +613,14 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] name = "clap_lex" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "clipboard-win" @@ -674,12 +674,12 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "colored" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -697,7 +697,7 @@ dependencies = [ "paste", "strum", "strum_macros", - "thiserror", + "thiserror 1.0.69", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -800,9 +800,9 @@ checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" dependencies = [ "crossbeam-utils", ] @@ -818,9 +818,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crossterm" @@ -878,7 +878,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -889,7 +889,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -921,7 +921,7 @@ dependencies = [ "serde", "slotmap", "socket2", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-serde", "tokio-stream", @@ -949,11 +949,12 @@ dependencies = [ "num", "protocol", "reserve-port", + "ron", "rpc", "serde", - "smallvec 2.0.0-alpha.7", + "smallvec 2.0.0-alpha.9", "temp-dir", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "tracing-error", @@ -969,7 +970,7 @@ dependencies = [ "dbstruct-derive", "serde", "sled", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -983,15 +984,15 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.89", - "thiserror", + "syn 2.0.91", + "thiserror 1.0.69", ] [[package]] name = "defmt" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0" +checksum = "86f6162c53f659f65d00619fe31f14556a6e9f8752ccc4a41bd177ffcf3d6130" dependencies = [ "bitflags 1.3.2", "defmt-macros", @@ -999,24 +1000,24 @@ dependencies = [ [[package]] name = "defmt-macros" -version = "0.3.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb" +checksum = "9d135dd939bad62d7490b0002602d35b358dce5fd9233a709d3c1ef467d4bde6" dependencies = [ "defmt-parser", - "proc-macro-error", + "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] name = "defmt-parser" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" +checksum = "3983b127f13995e68c1e29071e5d115cd96f215ccb5e6812e3728cd6f92653b3" dependencies = [ - "thiserror", + "thiserror 2.0.9", ] [[package]] @@ -1040,7 +1041,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -1137,7 +1138,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -1159,7 +1160,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -1228,7 +1229,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -1253,12 +1254,12 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1290,9 +1291,9 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" dependencies = [ "event-listener 5.3.1", "pin-project-lite", @@ -1319,9 +1320,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fd-lock" @@ -1347,7 +1348,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide 0.8.2", ] [[package]] @@ -1369,9 +1370,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" [[package]] name = "form_urlencoded" @@ -1488,7 +1489,7 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" dependencies = [ - "fastrand 2.2.0", + "fastrand 2.3.0", "futures-core", "futures-io", "parking", @@ -1503,7 +1504,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -1652,7 +1653,7 @@ checksum = "4ea1a9715542f84bc7b67cbb01c02ed3a72a919750b7d8611cc5bd684449386e" dependencies = [ "futures", "gpiocdev-uapi", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", ] @@ -1666,7 +1667,7 @@ dependencies = [ "embedded-hal", "embedded-hal-async", "gpiocdev", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1678,7 +1679,7 @@ dependencies = [ "bitflags 2.6.0", "ioctl-sys", "libc", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1784,12 +1785,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hermit-abi" version = "0.4.0" @@ -1807,9 +1802,9 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -1863,15 +1858,15 @@ dependencies = [ "reqwest", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", ] [[package]] name = "hyper" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" dependencies = [ "bytes", "futures-channel", @@ -2033,7 +2028,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -2071,9 +2066,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -2099,8 +2094,8 @@ dependencies = [ "proc-macro2", "quote", "strum", - "syn 2.0.89", - "thiserror", + "syn 2.0.91", + "thiserror 1.0.69", ] [[package]] @@ -2111,16 +2106,16 @@ checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] name = "instability" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b829f37dead9dc39df40c2d3376c179fdfd2ac771f53f55d3c30dc096a3c0c6e" +checksum = "898e106451f7335950c9cc64f8ec67b5f65698679ac67ed00619aeef14e1cf75" dependencies = [ "darling", "indoc", "pretty_assertions", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -2186,9 +2181,9 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jiff" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d9d414fc817d3e3d62b2598616733f76c4cc74fbac96069674739b881295c8" +checksum = "db69f08d4fb10524cacdb074c10b296299d71274ddbc830a8ee65666867002e9" dependencies = [ "jiff-tzdb-platform", "serde", @@ -2212,10 +2207,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -2236,9 +2232,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.166" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2ccc108bbc0b1331bd061864e7cd823c0cab660bbe6970e66e2c0614decde36" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libm" @@ -2270,7 +2266,7 @@ dependencies = [ "once_cell", "serde", "sha2", - "thiserror", + "thiserror 1.0.69", "uuid", ] @@ -2345,9 +2341,9 @@ dependencies = [ "reserve-port", "rpc", "serde", - "smallvec 2.0.0-alpha.7", + "smallvec 2.0.0-alpha.9", "temp-dir", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "tracing-error", @@ -2408,7 +2404,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -2532,20 +2528,19 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" dependencies = [ "adler2", ] [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi 0.3.9", "libc", "log", "wasi", @@ -2585,7 +2580,7 @@ checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -2868,7 +2863,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.5.7", + "redox_syscall 0.5.8", "smallvec 1.13.2", "windows-targets 0.52.6", ] @@ -2902,7 +2897,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -2924,7 +2919,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand 2.2.0", + "fastrand 2.3.0", "futures-io", ] @@ -2936,7 +2931,7 @@ checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ "cfg-if 1.0.0", "concurrent-queue", - "hermit-abi 0.4.0", + "hermit-abi", "pin-project-lite", "rustix", "tracing", @@ -2951,9 +2946,9 @@ checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" [[package]] name = "postcard" -version = "1.0.10" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" +checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8" dependencies = [ "cobs", "defmt", @@ -3018,6 +3013,28 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.91", +] + [[package]] name = "proc-macro-utils" version = "0.10.0" @@ -3056,7 +3073,7 @@ dependencies = [ "postcard", "serde", "strum", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3072,9 +3089,9 @@ dependencies = [ [[package]] name = "quanta" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5" +checksum = "773ce68d0bb9bc7ef20be3536ffe94e223e1f365bd374108b2659fac0c65cfe6" dependencies = [ "crossbeam-utils", "libc", @@ -3187,9 +3204,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags 2.6.0", ] @@ -3202,7 +3219,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3274,7 +3291,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", "tower-service", "url", @@ -3291,7 +3308,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9838134a2bfaa8e1f40738fcc972ac799de6e0e06b5157acb95fc2b05a0ea283" dependencies = [ "lazy_static", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3315,7 +3332,7 @@ dependencies = [ "governor", "logger", "serde", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-serde", "tokio-util", @@ -3332,7 +3349,7 @@ dependencies = [ "flume", "futures-util", "log", - "thiserror", + "thiserror 1.0.69", "tokio", ] @@ -3353,15 +3370,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.41" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3402,9 +3419,9 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "safe_arch" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3460605018fdc9612bce72735cba0d27efbcd9904780d44c7e3a9948f96148a" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" dependencies = [ "bytemuck", ] @@ -3423,9 +3440,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" [[package]] name = "sensor-tui" @@ -3447,7 +3464,7 @@ dependencies = [ "protocol", "ratatui", "strip-ansi-escapes", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "tracing-error", @@ -3457,29 +3474,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] name = "serde_json" -version = "1.0.133" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" dependencies = [ "itoa", "memchr", @@ -3514,9 +3531,9 @@ dependencies = [ [[package]] name = "serialport" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7331eefcaafaa382c0df95bcd84068f0b3e3c215c300750dde2316e9b8806ed5" +checksum = "779e2977f0cc2ff39708fef48f96f3768ac8ddd8c6caaaab82e83bd240ef99b2" dependencies = [ "bitflags 2.6.0", "cfg-if 1.0.0", @@ -3641,15 +3658,15 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smallvec" -version = "2.0.0-alpha.7" +version = "2.0.0-alpha.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6a96cb564e12be8458b004bd829787ebe887de197d94516d2ba5a2a32235a0c" +checksum = "5e22442b16a0c1bfae679ffed8ec5e160ae2aa8495cea891f0d2ff7b84fe5c4c" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3736,7 +3753,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -3758,21 +3775,15 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.89" +version = "2.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" +checksum = "d53cbcb5a243bd33b7858b1d7f4aca2153490815872d86d955d6ea29f743c035" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - [[package]] name = "sync_wrapper" version = "1.0.2" @@ -3802,7 +3813,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -3826,7 +3837,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" +dependencies = [ + "thiserror-impl 2.0.9", ] [[package]] @@ -3837,7 +3857,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.91", ] [[package]] @@ -3862,9 +3893,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -3886,7 +3917,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -3906,9 +3937,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -3917,9 +3948,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -3930,14 +3961,14 @@ dependencies = [ [[package]] name = "tower" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", "pin-project-lite", - "sync_wrapper 0.1.2", + "sync_wrapper", "tokio", "tower-layer", "tower-service", @@ -3974,7 +4005,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -3989,9 +4020,9 @@ dependencies = [ [[package]] name = "tracing-error" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" dependencies = [ "tracing", "tracing-subscriber", @@ -4009,9 +4040,9 @@ dependencies = [ [[package]] name = "tracing-journald" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba316a74e8fc3c3896a850dba2375928a9fa171b085ecddfc7c054d39970f3fd" +checksum = "fc0b4143302cf1022dac868d521e36e8b27691f72c84b3311750d5188ebba657" dependencies = [ "libc", "tracing-core", @@ -4031,9 +4062,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term", @@ -4083,14 +4114,14 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c878a167baa8afd137494101a688ef8c67125089ff2249284bd2b5f9bfedb815" dependencies = [ - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "unicase" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-ident" @@ -4260,9 +4291,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if 1.0.0", "once_cell", @@ -4271,36 +4302,36 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.45" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ "cfg-if 1.0.0", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4308,28 +4339,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" dependencies = [ "js-sys", "wasm-bindgen", @@ -4592,7 +4623,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", "synstructure 0.13.1", ] @@ -4614,7 +4645,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -4634,7 +4665,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", "synstructure 0.13.1", ] @@ -4657,7 +4688,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.91", ] [[package]] @@ -4674,7 +4705,7 @@ dependencies = [ "rumqttc", "serde_json", "strum", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] diff --git a/Cargo.toml b/Cargo.toml index 010defbc..195200bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ zigbee-bridge = { path = "crates/zigbee-bridge" } rpc = { path = "crates/rpc" } logger = { path = "crates/logger" } -byteseries = { git = "https://github.com/dvdsk/byteseries" } +byteseries = { git = "https://github.com/dvdsk/byteseries", rev="90efa57d021d39bc9cb4d9151c3a88acdbe62e25" } tokio = "1.38" color-eyre = "0.6.3" diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index 9f40fb9c..9a990622 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -33,6 +33,7 @@ futures = "0.3.30" smallvec = "2.0.0-alpha.6" num = "0.4.3" hdrhistogram = "7.5.4" +ron = "0.8.1" [dev-dependencies] futures-concurrency = { workspace = true } diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index 29e57720..c8f0c380 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -15,9 +15,14 @@ use series::Series; use crate::api; -pub(crate) async fn run(data_server_addr: SocketAddr, data: Data, data_dir: &Path) -> Result<()> { +pub(crate) async fn run( + data_server_addr: SocketAddr, + data: Data, + data_dir: &Path, +) -> Result<()> { let mut sub = - ReconnectingClient::new(data_server_addr, "ha-data-store".to_string()).subscribe(); + ReconnectingClient::new(data_server_addr, "ha-data-store".to_string()) + .subscribe(); let mut recently_logged = (Instant::now(), String::new()); loop { @@ -32,11 +37,12 @@ pub(crate) async fn run(data_server_addr: SocketAddr, data: Data, data_dir: &Pat const FIVE_MIN: Duration = Duration::from_secs(60 * 5); if let Err(report) = res { - let e = format!("got error with report: {report:?}"); - if recently_logged.1 == e && recently_logged.0.elapsed() <= FIVE_MIN { + let e = format!("{report:?}"); + if recently_logged.1 == e && recently_logged.0.elapsed() <= FIVE_MIN + { continue; } else { - tracing::error!("Error processing new reading: {e}"); + tracing::error!("Error processing new reading {reading:?},\nerror: {e}"); recently_logged = (Instant::now(), e); } } @@ -44,7 +50,9 @@ pub(crate) async fn run(data_server_addr: SocketAddr, data: Data, data_dir: &Pat } #[derive(Debug, Clone)] -pub(crate) struct Data(pub(crate) Arc>>); +pub(crate) struct Data( + pub(crate) Arc>>, +); impl Data { pub(crate) async fn list(&self) -> Vec { @@ -68,21 +76,30 @@ impl Data { let key = reading.device(); let mut all_series = self.0.lock().await; - let series = all_series - .get_mut(&key) - .ok_or_else(|| api::GetDataError::NotInStore { + let series = all_series.get_mut(&key).ok_or_else(|| { + api::GetDataError::NotInStore { reading: reading.clone(), - })?; + } + })?; - let (time, mut data) = series - .read(&[reading], start, end, n) - .map_err(|e| match e { - Be::InvalidRange(Se::NotFound) => api::GetDataError::NotFound, - Be::InvalidRange(Se::EmptyFile) => api::GetDataError::EmptyFile, - Be::InvalidRange(Se::StartAfterData) => api::GetDataError::StartAfterData, - Be::InvalidRange(Se::StopBeforeData) => api::GetDataError::StopBeforeData, - _ => api::GetDataError::ReadingFromStore(e.to_string()), - })?; + let (time, mut data) = + series + .read(&[reading], start, end, n) + .map_err(|e| match e { + Be::InvalidRange(Se::NotFound) => { + api::GetDataError::NotFound + } + Be::InvalidRange(Se::EmptyFile) => { + api::GetDataError::EmptyFile + } + Be::InvalidRange(Se::StartAfterData { .. }) => { + api::GetDataError::StartAfterData + } + Be::InvalidRange(Se::StopBeforeData) => { + api::GetDataError::StopBeforeData + } + _ => api::GetDataError::ReadingFromStore(e.to_string()), + })?; Ok(api::Data { time, values: data.pop().expect("one reading is put in so one comes out"), diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index 9298e9ae..7b20fc8c 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -43,18 +43,29 @@ struct Header { encoding: Vec>, } +impl Header { + fn serialized(&self) -> Result> { + let config = ron::ser::PrettyConfig::new(); + ron::ser::to_string_pretty(self, config) + .map(|s| s.into_bytes()) + .wrap_err("Could not serialize header") + } +} + impl Series { #[instrument] fn open_or_create(reading: &protocol::Reading, dir: &Path) -> Result { let readings = reading.device().info().affects_readings; let specs = to_speclist(readings); let fields = bitspec::speclist_to_fields(specs); - let (meta_list, payload_size) = meta_list_and_payload_size(readings, &fields); + let (meta_list, payload_size) = + meta_list_and_payload_size(readings, &fields); let expected_header = Header { readings: readings.to_vec(), encoding: fields.clone(), - }; + } + .serialized()?; let (resampler, configs) = resample_setup(&fields, payload_size); @@ -68,9 +79,10 @@ impl Series { let byteseries = match res { Ok((byteseries, _)) => byteseries, - Err(Open(DataOpenError::File(FileOpenError::Io(e)))) - if e.kind() == io::ErrorKind::NotFound => - { + Err(Open(DataOpenError::File { + source: FileOpenError::Io(e), + .. + })) if e.kind() == io::ErrorKind::NotFound => { if let Some(dirs) = path.parent() { create_dir_all(dirs) .wrap_err("Could not create dirs structure for reading") @@ -87,7 +99,11 @@ impl Series { .with_note(|| format!("path: {}", path.display())) .map(|(db, _)| db)? } - Err(e) => return Err(e).wrap_err("Could not open existing byteseries")?, + Err(e) => { + return Err(e) + .wrap_err("Could not open existing byteseries") + .with_note(|| format!("path: {}", path.display()))? + } }; Ok(Self { @@ -168,7 +184,8 @@ impl Series { start: jiff::Timestamp, end: jiff::Timestamp, n: usize, - ) -> Result<(Vec, Vec>), byteseries::series::Error> { + ) -> Result<(Vec, Vec>), byteseries::series::Error> + { let device_info = readings .first() .expect("There is at least one reading to read") @@ -224,7 +241,9 @@ impl Series { .len(); let mut data = vec![Vec::new(); len]; for interleaved in interleaved_data { - for (interleaved, data) in interleaved.into_iter().zip(data.iter_mut()) { + for (interleaved, data) in + interleaved.into_iter().zip(data.iter_mut()) + { data.push(interleaved); } } @@ -257,7 +276,9 @@ fn meta_list_and_payload_size( /// Multiplying the time for this sample by this factor /// allows you to save the whole number and retain the required /// temporal_resolution and min_sample_interval. -pub fn millis_to_minimal_representation(device_info: protocol::DeviceInfo) -> u64 { +pub fn millis_to_minimal_representation( + device_info: protocol::DeviceInfo, +) -> u64 { let needed_interval = device_info .temporal_resolution .min(device_info.min_sample_interval) @@ -268,7 +289,11 @@ pub fn millis_to_minimal_representation(device_info: protocol::DeviceInfo) -> u6 } #[instrument(level = "debug", skip(data))] -pub(crate) async fn store(data: &Data, reading: &protocol::Reading, data_dir: &Path) -> Result<()> { +pub(crate) async fn store( + data: &Data, + reading: &protocol::Reading, + data_dir: &Path, +) -> Result<()> { let mut data = data.0.lock().await; let key = reading.device(); @@ -377,28 +402,36 @@ mod test { #[test] fn readings_from_same_device_have_same_path() { - let reading_a = - Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::Temperature(0.0))); - let reading_b = - Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::Humidity(0.0))); + let reading_a = Reading::LargeBedroom(large_bedroom::Reading::Bed( + bed::Reading::Temperature(0.0), + )); + let reading_b = Reading::LargeBedroom(large_bedroom::Reading::Bed( + bed::Reading::Humidity(0.0), + )); assert_eq!(base_path(&reading_a), base_path(&reading_b)); } #[test] fn reading_path_different_between_locations() { - let reading_a = - Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::Humidity(0.0))); - let reading_b = - Reading::LargeBedroom(large_bedroom::Reading::Desk(desk::Reading::Humidity(0.0))); + let reading_a = Reading::LargeBedroom(large_bedroom::Reading::Bed( + bed::Reading::Humidity(0.0), + )); + let reading_b = Reading::LargeBedroom(large_bedroom::Reading::Desk( + desk::Reading::Humidity(0.0), + )); assert_ne!(base_path(&reading_a), base_path(&reading_b)); } #[test] fn reading_path_is_expected() { - let reading = - Reading::LargeBedroom(large_bedroom::Reading::Bed(bed::Reading::Humidity(0.0))); - assert_eq!(base_path(&reading), PathBuf::from("largebedroom/bed/sht31")); + let reading = Reading::LargeBedroom(large_bedroom::Reading::Bed( + bed::Reading::Humidity(0.0), + )); + assert_eq!( + base_path(&reading), + PathBuf::from("largebedroom/bed/sht31") + ); } } From 7d8011e3e2d7f512135a9653936e70f97b0ffac5 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 25 Dec 2024 17:50:46 +0100 Subject: [PATCH 507/687] update byteseries (critical bug fix) --- Cargo.lock | 2 +- Cargo.toml | 2 +- crates/log-store/src/server/db/log.rs | 57 ++++++++++++++++----------- 3 files changed, 37 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 65538ada..098b4476 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -528,7 +528,7 @@ checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "byteseries" version = "0.7.1" -source = "git+https://github.com/dvdsk/byteseries?rev=90efa57d021d39bc9cb4d9151c3a88acdbe62e25#90efa57d021d39bc9cb4d9151c3a88acdbe62e25" +source = "git+https://github.com/dvdsk/byteseries?rev=16d410071cb61a8e375183ca3ce0c7fbdefc9e6b#16d410071cb61a8e375183ca3ce0c7fbdefc9e6b" dependencies = [ "arraydeque", "itertools 0.13.0", diff --git a/Cargo.toml b/Cargo.toml index 195200bc..404b3041 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ zigbee-bridge = { path = "crates/zigbee-bridge" } rpc = { path = "crates/rpc" } logger = { path = "crates/logger" } -byteseries = { git = "https://github.com/dvdsk/byteseries", rev="90efa57d021d39bc9cb4d9151c3a88acdbe62e25" } +byteseries = { git = "https://github.com/dvdsk/byteseries", rev="16d410071cb61a8e375183ca3ce0c7fbdefc9e6b" } tokio = "1.38" color-eyre = "0.6.3" diff --git a/crates/log-store/src/server/db/log.rs b/crates/log-store/src/server/db/log.rs index ea3c0788..72cefdfd 100644 --- a/crates/log-store/src/server/db/log.rs +++ b/crates/log-store/src/server/db/log.rs @@ -70,15 +70,16 @@ impl CurrentError { } fn take(&mut self) -> Result> { - self.file - .set_len(0) - .wrap_err("Could not set on disk backup of current error to None")?; + self.file.set_len(0).wrap_err( + "Could not set on disk backup of current error to None", + )?; Ok(self.value.take()) } fn set(&mut self, report: protocol::Error) -> Result<()> { let value = (jiff::Timestamp::now(), report); - let bytes = bincode::serialize(&value).wrap_err("could not serialize current error")?; + let bytes = bincode::serialize(&value) + .wrap_err("could not serialize current error")?; self.file .set_len(0) .wrap_err("Could not clear file prior to backing up value")?; @@ -112,14 +113,15 @@ impl Log { let res = ByteSeries::builder() .payload_size(payload_size) - .with_header(header.clone()) + .with_header(header.as_bytes().to_vec()) .open(&path); let history = match res { Ok((byteseries, _)) => byteseries, - Err(Open(DataOpenError::File(FileOpenError::Io(e)))) - if e.kind() == io::ErrorKind::NotFound => - { + Err(Open(DataOpenError::File { + source: FileOpenError::Io(e), + .. + })) if e.kind() == io::ErrorKind::NotFound => { if let Some(dirs) = path.parent() { std::fs::create_dir_all(dirs) .wrap_err("Could not create dirs structure for reading") @@ -128,7 +130,7 @@ impl Log { info!("creating new byteseries"); ByteSeries::builder() .payload_size(payload_size) - .with_header(header) + .with_header(header.into_bytes()) .create_new(true) .open(&path) .wrap_err("Could not create new byteseries") @@ -161,7 +163,8 @@ impl Log { end: jiff::Timestamp::now(), error: report.clone(), }; - let line = bincode::serialize(&line).wrap_err("Could not serialize ErrorEvent")?; + let line = bincode::serialize(&line) + .wrap_err("Could not serialize ErrorEvent")?; let payload_size = protocol::Error::max_size(); let line: Vec<_> = line .into_iter() @@ -189,8 +192,11 @@ impl Log { Ok(()) } - fn get(&mut self, range: RangeInclusive) -> GetLogResponse { - use byteseries::seek::Error::{EmptyFile, StartAfterData, StopBeforeData}; + fn get( + &mut self, + range: RangeInclusive, + ) -> GetLogResponse { + use byteseries::seek::Error::{EmptyFile, StopBeforeData}; use byteseries::series::Error::InvalidRange; const MAX_IN_ONE_READ: usize = 200; @@ -220,7 +226,7 @@ impl Log { &mut data, ) { Ok(()) => (), - Err(InvalidRange(StartAfterData | StopBeforeData | EmptyFile)) => { + Err(InvalidRange(StopBeforeData | EmptyFile)) => { return GetLogResponse::All(current.collect()) } Err(other) => { @@ -243,11 +249,9 @@ impl Log { .collect(); if res.len() < MAX_IN_ONE_READ { - res.extend( - current.filter(|ErrorEvent { start, .. }| { - start >= range.start() && start <= range.end() - }), - ); + res.extend(current.filter(|ErrorEvent { start, .. }| { + start >= range.start() && start <= range.end() + })); GetLogResponse::All(res) } else { @@ -268,7 +272,8 @@ impl byteseries::Decoder for Decoder { type Item = StoredErrorEvent; fn decode_payload(&mut self, payload: &[u8]) -> Self::Item { - bincode::deserialize(payload).expect("if its successfully serialized it should deserialize") + bincode::deserialize(payload) + .expect("if its successfully serialized it should deserialize") } } @@ -276,7 +281,11 @@ impl byteseries::Decoder for Decoder { pub(crate) struct Logs(pub(crate) Arc>>); impl Logs { - pub async fn set_err(&self, report: protocol::Error, log_dir: &Path) -> Result<()> { + pub async fn set_err( + &self, + report: protocol::Error, + log_dir: &Path, + ) -> Result<()> { let device = report.device(); let mut map = self.0.lock().await; if let Some(log) = map.get_mut(&device) { @@ -303,7 +312,10 @@ impl Logs { } } - pub(crate) async fn clear_err(&self, device: protocol::Device) -> Result<()> { + pub(crate) async fn clear_err( + &self, + device: protocol::Device, + ) -> Result<()> { let mut map = self.0.lock().await; if let Some(log) = map.get_mut(&device) { log.clear()?; @@ -327,7 +339,8 @@ fn base_path(device: &protocol::Device) -> PathBuf { .info() .affects_readings .first() - .expect("a device has at least one reading it affects") as &dyn Tree; + .expect("a device has at least one reading it affects") + as &dyn Tree; loop { match current.inner() { Item::Leaf(Info { device, .. }) => { From 5abfe8a5fe32e3112219001fd668ac428bd6c874 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 26 Dec 2024 11:50:20 +0100 Subject: [PATCH 508/687] Increase send delay to hopefully fix Ikea issues --- crates/zigbee-bridge/src/cached_bridge.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/zigbee-bridge/src/cached_bridge.rs b/crates/zigbee-bridge/src/cached_bridge.rs index 5e4817b5..2f276940 100644 --- a/crates/zigbee-bridge/src/cached_bridge.rs +++ b/crates/zigbee-bridge/src/cached_bridge.rs @@ -18,7 +18,7 @@ const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); // the z2m queue from getting filled up const TIME_IT_TAKES_TO_APPLY_CHANGE: Duration = Duration::from_secs(10); const CHANGE_ACCUMULATION_TIME: Duration = Duration::from_millis(100); -const MIN_TIME_BETWEEN_SENDS: Duration = Duration::from_millis(10); +const MIN_TIME_BETWEEN_SENDS: Duration = Duration::from_millis(200); pub(super) async fn run( mqtt_ip: IpAddr, From 7d9040f25534b6b7a286f1d218ebf232e17379ea Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 26 Dec 2024 15:24:03 +0100 Subject: [PATCH 509/687] add radiator to protocol + add callback to get radiator to zigbee bridge + clippy --- crates/data-server/src/server/watch.rs | 18 +-- crates/protocol/src/affector/tree.rs | 8 +- crates/protocol/src/button.rs | 4 +- crates/protocol/src/large_bedroom.rs | 6 +- crates/protocol/src/large_bedroom/bed.rs | 10 +- crates/protocol/src/large_bedroom/desk.rs | 4 +- crates/protocol/src/large_bedroom/radiator.rs | 119 ++++++++++++++++++ crates/protocol/src/lib.rs | 26 ++-- crates/protocol/src/reading/tree.rs | 4 +- crates/protocol/src/small_bedroom.rs | 22 +++- crates/protocol/src/small_bedroom/bed.rs | 11 +- crates/protocol/src/small_bedroom/desk.rs | 4 +- crates/protocol/src/small_bedroom/radiator.rs | 119 ++++++++++++++++++ crates/zigbee-bridge/Cargo.toml | 1 + crates/zigbee-bridge/src/cached_bridge.rs | 3 +- .../src/cached_bridge/changes.rs | 19 ++- .../zigbee-bridge/src/cached_bridge/mqtt.rs | 13 +- .../zigbee-bridge/src/cached_bridge/poll.rs | 77 ++++++++---- crates/zigbee-bridge/src/device.rs | 12 +- crates/zigbee-bridge/src/lamp.rs | 14 +-- crates/zigbee-bridge/src/lib.rs | 17 ++- .../src/{parse_state.rs => parse.rs} | 89 +++++++++---- crates/zigbee-bridge/src/radiator.rs | 6 +- 23 files changed, 471 insertions(+), 135 deletions(-) create mode 100644 crates/protocol/src/large_bedroom/radiator.rs create mode 100644 crates/protocol/src/small_bedroom/radiator.rs rename crates/zigbee-bridge/src/{parse_state.rs => parse.rs} (64%) diff --git a/crates/data-server/src/server/watch.rs b/crates/data-server/src/server/watch.rs index ca15cb68..78652b75 100644 --- a/crates/data-server/src/server/watch.rs +++ b/crates/data-server/src/server/watch.rs @@ -3,7 +3,7 @@ use std::time::Duration; use super::{AffectorRegistar, Event}; use protocol::reading::tree::Tree; -use protocol::{large_bedroom, small_bedroom, Affector, Reading}; +use protocol::{large_bedroom, small_bedroom, Affector, IsSameAs, Reading}; use tokio::sync::mpsc; use tokio::time::{timeout_at, Instant}; use tracing::warn; @@ -56,9 +56,6 @@ impl LastSeen { ), )) } - Reading::LargeBedroom(large_bedroom::Reading::Desk(_)) => { - None - } Reading::SmallBedroom(small_bedroom::Reading::Bed(_)) => { Some(Affector::SmallBedroom( small_bedroom::Affector::Bed( @@ -66,10 +63,15 @@ impl LastSeen { ), )) } - Reading::SmallBedroom(small_bedroom::Reading::Desk(_)) => { - None - } - Reading::SmallBedroom( + Reading::LargeBedroom(large_bedroom::Reading::Desk(_)) + | Reading::LargeBedroom( + large_bedroom::Reading::Radiator(_), + ) + | Reading::SmallBedroom(small_bedroom::Reading::Desk(_)) + | Reading::SmallBedroom( + small_bedroom::Reading::Radiator(_), + ) + | Reading::SmallBedroom( small_bedroom::Reading::ButtonPanel(_), ) => None, } diff --git a/crates/protocol/src/affector/tree.rs b/crates/protocol/src/affector/tree.rs index 18bf9f4e..cddce41e 100644 --- a/crates/protocol/src/affector/tree.rs +++ b/crates/protocol/src/affector/tree.rs @@ -24,19 +24,17 @@ pub trait Tree: core::fmt::Debug { fn name(&self) -> String { let dbg_repr = format!("{self:?}"); let split = dbg_repr.find('(').unwrap_or(dbg_repr.len()); - dbg_repr - .split_at(split).0 - .to_string() + dbg_repr.split_at(split).0.to_string() } fn branch_id(&self) -> Id; } macro_rules! impl_zero { ($name:ident; $($var:ident),*) => { - impl $name { + impl crate::IsSameAs for $name { #[must_use] #[allow(unreachable_patterns)] - pub fn is_same_as(&self, other: &Self) -> bool { + fn is_same_as(&self, other: &Self) -> bool { match (self, other) { $(($name::$var(a), $name::$var(b)) => a.is_same_as(b),)* (_, _) => false, diff --git a/crates/protocol/src/button.rs b/crates/protocol/src/button.rs index 0a9e2428..a498156a 100644 --- a/crates/protocol/src/button.rs +++ b/crates/protocol/src/button.rs @@ -99,9 +99,9 @@ macro_rules! button_enum { } } - impl $name { + impl crate::IsSameAs for $name { #[must_use] - pub fn is_same_as(&self, other: &Self) -> bool { + fn is_same_as(&self, other: &Self) -> bool { match (self, other) { $(($name::$variant(_), $name::$variant(_)) => true,)* (_, _) => false, diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index d560c557..b86cbb74 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -6,6 +6,7 @@ use crate::{reading, affector}; pub mod bed; pub mod desk; +pub mod radiator; #[derive( strum::EnumDiscriminants, @@ -23,10 +24,11 @@ pub mod desk; pub enum Reading { Bed(bed::Reading) = 0, Desk(desk::Reading) = 1, + Radiator(radiator::Reading) = 2, } #[cfg(feature = "alloc")] -reading::tree::all_nodes! {Reading; ReadingDiscriminants; Bed, Desk} +reading::tree::all_nodes! {Reading; ReadingDiscriminants; Bed, Desk, Radiator} #[derive( strum::EnumDiscriminants, @@ -67,6 +69,7 @@ impl core::fmt::Display for Error { pub enum Device { Bed(bed::Device), Desk(desk::Device), + Radiator(radiator::Device), } impl Device { @@ -75,6 +78,7 @@ impl Device { match self { Self::Bed(dev) => dev.info(), Self::Desk(dev) => dev.info(), + Self::Radiator(dev) => dev.info(), } } } diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index e7b1b66d..18cd7c78 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -262,9 +262,9 @@ impl Tree for Reading { } } -impl Reading { +impl crate::IsSameAs for Reading { #[must_use] - pub fn is_same_as(&self, other: &Self) -> bool { + fn is_same_as(&self, other: &Self) -> bool { match (self, other) { (Self::Brightness(_), Self::Brightness(_)) | (Self::Temperature(_), Self::Temperature(_)) @@ -520,9 +520,9 @@ pub enum Affector { ResetNode, } -impl Affector { +impl crate::IsSameAs for Affector { #[must_use] - pub fn is_same_as(&self, other: &Self) -> bool { + fn is_same_as(&self, other: &Self) -> bool { #[allow(clippy::match_like_matches_macro)] match (self, other) { (Affector::Sps30FanClean, Affector::Sps30FanClean) => true, @@ -534,7 +534,9 @@ impl Affector { _ => false, } } +} +impl Affector { #[cfg(feature = "alloc")] pub fn controls(&mut self) -> Vec { match self { diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index 0cc4a710..66f76bdd 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -89,9 +89,9 @@ impl Tree for Reading { } } -impl Reading { +impl crate::IsSameAs for Reading { #[must_use] - pub fn is_same_as(&self, other: &Self) -> bool { + fn is_same_as(&self, other: &Self) -> bool { match (self, other) { (Reading::Temperature(_), Self::Temperature(_)) | (Reading::Humidity(_), Self::Humidity(_)) diff --git a/crates/protocol/src/large_bedroom/radiator.rs b/crates/protocol/src/large_bedroom/radiator.rs new file mode 100644 index 00000000..973b73b5 --- /dev/null +++ b/crates/protocol/src/large_bedroom/radiator.rs @@ -0,0 +1,119 @@ +use core::time::Duration; + +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "alloc")] +use crate::reading::tree::{Item, Tree}; +#[cfg(feature = "alloc")] +use crate::reading::Info; +#[cfg(feature = "alloc")] +use crate::Unit; + +#[derive( + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, +)] +#[strum_discriminants(derive(Hash))] +#[repr(u8)] +pub enum Reading { + Temperature(f32) = 0, + Heating(f32) = 1, +} + +impl crate::IsSameAs for Reading { + fn is_same_as(&self, other: &Self) -> bool { + match (self, other) { + (Reading::Temperature(_), Reading::Temperature(_)) + | (Reading::Heating(_), Reading::Heating(_)) => true, + (_, _) => false, + } + } +} + +#[cfg(feature = "alloc")] +impl Tree for Reading { + #[must_use] + fn inner(&self) -> Item<'_> { + let leaf = match self { + Reading::Temperature(val) => Info { + val: *val, + device: crate::Device::LargeBedroom(super::Device::Radiator( + Device, + )), + resolution: 0.01, + range: -10.0..45.0, + unit: Unit::C, + description: "Temperature", + branch_id: self.branch_id(), + }, + Reading::Heating(val) => Info { + val: *val, + device: crate::Device::LargeBedroom(super::Device::Radiator( + Device, + )), + resolution: 1.0, + range: 0.0..100.0, + unit: Unit::PercentageOpen, + description: "Heating valve", + branch_id: self.branch_id(), + }, + }; + Item::Leaf(leaf) + } + + #[must_use] + fn branch_id(&self) -> crate::reading::tree::Id { + ReadingDiscriminants::from(self) as crate::reading::tree::Id + } +} + +#[derive( + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + Eq, + PartialEq, + Hash, +)] +pub struct Device; + +impl core::fmt::Display for Device { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.info().name) + } +} + +macro_rules! tree { + [$thing:ident; $($item:expr),+] => { + [$(crate::$thing::LargeBedroom( + crate::large_bedroom::$thing::Radiator($item), + )),+] + }; +} + +impl Device { + /// Note the order in which the `affects_readings` occur is the order in which + /// they will be stored, do not change it! + #[must_use] + pub const fn info(&self) -> crate::DeviceInfo { + crate::DeviceInfo { + name: "Radiator", + affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Heating(0.0)], + temporal_resolution: Duration::MAX, + min_sample_interval: Duration::ZERO, + max_sample_interval: Duration::MAX, + affectors: &[], + } + } +} diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 2c8f886f..54ddd8ed 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -27,31 +27,37 @@ pub use reading::Reading; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Unit { - Pa, C, - RH, Lux, - Ohm, - Ppm, MicrogramPerM3, - NumberPerCm3, NanoMeter, None, // for buttons + NumberPerCm3, + Ohm, + Pa, + PercentageOpen, + Ppm, + RH, } impl Display for Unit { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - Unit::Pa => f.write_str("Pa"), Unit::C => f.write_str("°C"), - Unit::RH => f.write_str("%RH"), Unit::Lux => f.write_str("lx"), - Unit::Ohm => f.write_str("Ω"), - Unit::Ppm => f.write_str("ppm"), Unit::MicrogramPerM3 => f.write_str("µg/m³"), - Unit::NumberPerCm3 => f.write_str("#/cm³"), Unit::NanoMeter => f.write_str("nm"), Unit::None => f.write_str(""), + Unit::NumberPerCm3 => f.write_str("#/cm³"), + Unit::Ohm => f.write_str("Ω"), + Unit::Pa => f.write_str("Pa"), + Unit::PercentageOpen => f.write_str("% open"), + Unit::Ppm => f.write_str("ppm"), + Unit::RH => f.write_str("%RH"), } } } + +pub trait IsSameAs { + fn is_same_as(&self, other: &Self) -> bool; +} diff --git a/crates/protocol/src/reading/tree.rs b/crates/protocol/src/reading/tree.rs index 8f8ea856..29453d94 100644 --- a/crates/protocol/src/reading/tree.rs +++ b/crates/protocol/src/reading/tree.rs @@ -33,9 +33,9 @@ pub trait Tree: core::fmt::Debug { macro_rules! impl_zero { ($name:ident; $($var:ident),*) => { - impl $name { + impl crate::IsSameAs for $name { #[must_use] - pub fn is_same_as(&self, other: &Self) -> bool { + fn is_same_as(&self, other: &Self) -> bool { match (self, other) { $(($name::$var(a), $name::$var(b)) => a.is_same_as(b),)* (_, _) => false, diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index 9fee9748..4db01b4b 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -3,12 +3,13 @@ use core::time::Duration; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; -use crate::button::Press; #[cfg(feature = "alloc")] use crate::affector; +use crate::button::Press; -pub mod desk; pub mod bed; +pub mod desk; +pub mod radiator; crate::button_enum! { /// +-----------------------------------------+ @@ -43,10 +44,11 @@ pub enum Reading { ButtonPanel(ButtonPanel) = 0, Desk(desk::Reading) = 1, Bed(bed::Reading) = 2, + Radiator(radiator::Reading) = 3, } #[cfg(feature = "alloc")] -crate::reading::tree::all_nodes!{Reading; ReadingDiscriminants; ButtonPanel, Desk, Bed} +crate::reading::tree::all_nodes! {Reading; ReadingDiscriminants; ButtonPanel, Desk, Bed, Radiator} #[derive( strum::EnumDiscriminants, @@ -83,11 +85,22 @@ impl core::fmt::Display for Error { } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Hash, PartialEq, Eq)] +#[derive( + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + Hash, + PartialEq, + Eq, +)] pub enum Device { Gpio, Desk(desk::Device), Bed(bed::Device), + Radiator(radiator::Device), } macro_rules! tree { @@ -121,6 +134,7 @@ impl Device { }, Device::Desk(device) => device.info(), Device::Bed(device) => device.info(), + Device::Radiator(device) => device.info(), } } } diff --git a/crates/protocol/src/small_bedroom/bed.rs b/crates/protocol/src/small_bedroom/bed.rs index c94e64e2..00792d4b 100644 --- a/crates/protocol/src/small_bedroom/bed.rs +++ b/crates/protocol/src/small_bedroom/bed.rs @@ -243,9 +243,9 @@ impl Tree for Reading { } } -impl Reading { +impl crate::IsSameAs for Reading { #[must_use] - pub fn is_same_as(&self, other: &Self) -> bool { + fn is_same_as(&self, other: &Self) -> bool { match (self, other) { (Self::Brightness(_), Self::Brightness(_)) | (Self::Temperature(_), Self::Temperature(_)) @@ -503,12 +503,13 @@ pub enum Affector { ResetNode, } -impl Affector { +impl crate::IsSameAs for Affector { #[must_use] - pub fn is_same_as(&self, other: &Self) -> bool { + fn is_same_as(&self, other: &Self) -> bool { self.eq(other) } - +} +impl Affector { #[cfg(feature = "alloc")] pub fn controls(&mut self) -> Vec { match self { diff --git a/crates/protocol/src/small_bedroom/desk.rs b/crates/protocol/src/small_bedroom/desk.rs index 28bc2c3e..1a8e4dc0 100644 --- a/crates/protocol/src/small_bedroom/desk.rs +++ b/crates/protocol/src/small_bedroom/desk.rs @@ -71,9 +71,9 @@ impl Tree for Reading { } } -impl Reading { +impl crate::IsSameAs for Reading { #[must_use] - pub fn is_same_as(&self, other: &Self) -> bool { + fn is_same_as(&self, other: &Self) -> bool { #[allow(clippy::match_like_matches_macro)] match (self, other) { (Reading::Temperature(_), Self::Temperature(_)) diff --git a/crates/protocol/src/small_bedroom/radiator.rs b/crates/protocol/src/small_bedroom/radiator.rs new file mode 100644 index 00000000..39149aea --- /dev/null +++ b/crates/protocol/src/small_bedroom/radiator.rs @@ -0,0 +1,119 @@ +use core::time::Duration; + +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "alloc")] +use crate::reading::tree::{Item, Tree}; +#[cfg(feature = "alloc")] +use crate::reading::Info; +#[cfg(feature = "alloc")] +use crate::Unit; + +#[derive( + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, +)] +#[strum_discriminants(derive(Hash))] +#[repr(u8)] +pub enum Reading { + Temperature(f32) = 0, + Heating(f32) = 1, +} + +impl crate::IsSameAs for Reading { + fn is_same_as(&self, other: &Self) -> bool { + match (self, other) { + (Reading::Temperature(_), Reading::Temperature(_)) + | (Reading::Heating(_), Reading::Heating(_)) => true, + (_, _) => false, + } + } +} + +#[cfg(feature = "alloc")] +impl Tree for Reading { + #[must_use] + fn inner(&self) -> Item<'_> { + let leaf = match self { + Reading::Temperature(val) => Info { + val: *val, + device: crate::Device::SmallBedroom(super::Device::Radiator( + Device, + )), + resolution: 0.01, + range: -10.0..45.0, + unit: Unit::C, + description: "Temperature", + branch_id: self.branch_id(), + }, + Reading::Heating(val) => Info { + val: *val, + device: crate::Device::SmallBedroom(super::Device::Radiator( + Device, + )), + resolution: 1.0, + range: 0.0..100.0, + unit: Unit::PercentageOpen, + description: "Heating valve", + branch_id: self.branch_id(), + }, + }; + Item::Leaf(leaf) + } + + #[must_use] + fn branch_id(&self) -> crate::reading::tree::Id { + ReadingDiscriminants::from(self) as crate::reading::tree::Id + } +} + +#[derive( + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + Eq, + PartialEq, + Hash, +)] +pub struct Device; + +impl core::fmt::Display for Device { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.info().name) + } +} + +macro_rules! tree { + [$thing:ident; $($item:expr),+] => { + [$(crate::$thing::SmallBedroom( + crate::small_bedroom::$thing::Radiator($item), + )),+] + }; +} + +impl Device { + /// Note the order in which the `affects_readings` occur is the order in which + /// they will be stored, do not change it! + #[must_use] + pub const fn info(&self) -> crate::DeviceInfo { + crate::DeviceInfo { + name: "Radiator", + affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Heating(0.0)], + temporal_resolution: Duration::MAX, + min_sample_interval: Duration::ZERO, + max_sample_interval: Duration::MAX, + affectors: &[], + } + } +} diff --git a/crates/zigbee-bridge/Cargo.toml b/crates/zigbee-bridge/Cargo.toml index a6ee34dd..ceeb81ee 100644 --- a/crates/zigbee-bridge/Cargo.toml +++ b/crates/zigbee-bridge/Cargo.toml @@ -7,6 +7,7 @@ license.workspace = true authors.workspace = true [dependencies] +protocol.workspace = true colorimetry = { git = "https://github.com/harbik/colorimetry", features = ["cct"] } # default-features enable rustls which we do not need and drags in # C dependencies making deployment a chore diff --git a/crates/zigbee-bridge/src/cached_bridge.rs b/crates/zigbee-bridge/src/cached_bridge.rs index 2f276940..349f739a 100644 --- a/crates/zigbee-bridge/src/cached_bridge.rs +++ b/crates/zigbee-bridge/src/cached_bridge.rs @@ -24,6 +24,7 @@ pub(super) async fn run( mqtt_ip: IpAddr, change_receiver: mpsc::UnboundedReceiver<(String, Property)>, name: String, + on_msg: impl Fn(protocol::Reading), ) -> ! { // The id string must be random or subscribe does not work let id = name + " " + &rand::random::().to_string(); @@ -58,7 +59,7 @@ pub(super) async fn run( } trace!("Starting main zigbee management loops"); - let poll_mqtt = poll::poll_mqtt(eventloop, &known_states); + let poll_mqtt = poll::poll_mqtt(eventloop, &known_states, on_msg); let handle_changes = changes::handle( change_receiver, &mut mqtt, diff --git a/crates/zigbee-bridge/src/cached_bridge/changes.rs b/crates/zigbee-bridge/src/cached_bridge/changes.rs index 8faefa86..9c230f81 100644 --- a/crates/zigbee-bridge/src/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/cached_bridge/changes.rs @@ -36,19 +36,16 @@ pub(super) async fn handle( tracing::info!("Received change order: {change:?} for device {device_name}"); apply_change_to_needed(device_name, change, &mut needed_states); - // When there hasn't been a new change in 100 ms, we will timeout - // and send the accumulated changes + // When there hasn't been a new change in 100 milliseconds, we + // will timeout and send the accumulated changes call_at_least_in = CHANGE_ACCUMULATION_TIME; } _ => { - // Send the accumulated changes and get the timeout for resending - call_at_least_in = send_diff_get_timeout( - known_states, - &needed_states, - mqtt, - ) - .await - .min(MQTT_MIGHT_BE_DOWN_TIMEOUT); + // Send the accumulated changes and get the timeout for re-sending + call_at_least_in = + send_diff_get_timeout(known_states, &needed_states, mqtt) + .await + .min(MQTT_MIGHT_BE_DOWN_TIMEOUT); } }; } @@ -72,7 +69,7 @@ async fn send_diff_get_timeout( tracing::Span::current().record("device_name", device_name); let diff = match known_states.get(device_name) { - Some(known) => needed.changes_relative_to(known), + Some(known) => needed.changes_relative_to(known.as_ref()), None => needed.all_set_properties().values().cloned().collect(), }; diff --git a/crates/zigbee-bridge/src/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/cached_bridge/mqtt.rs index c9bce9ff..1b699c85 100644 --- a/crates/zigbee-bridge/src/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/cached_bridge/mqtt.rs @@ -5,7 +5,7 @@ use rumqttc::v5::mqttbytes::QoS; use rumqttc::v5::{AsyncClient, ClientError}; use serde_json::json; use tokio::time::sleep; -use tracing::{instrument, trace, warn}; +use tracing::{instrument, trace}; use crate::device::{Property, PropertyDiscriminants}; @@ -48,8 +48,8 @@ impl Mqtt { device_name: &str, diff: &[Property], ) -> Option { - diff.into_iter() - .map(|change| self.change_next_due(device_name, &change)) + diff.iter() + .map(|change| self.change_next_due(device_name, change)) .min() } @@ -93,7 +93,7 @@ impl Mqtt { let mut due_changes = Vec::new(); for change in diff { - if self.is_due(&device_name, change) { + if self.is_due(device_name, change) { due_changes.push(change); let device_send_record = @@ -106,11 +106,10 @@ impl Mqtt { if !due_changes.is_empty() { if merged_payloads { let payload = merge_payloads(due_changes); - self.set(&device_name, payload.to_string()).await?; + self.set(device_name, payload.to_string()).await?; } else { for change in due_changes { - self.set(&device_name, change.payload().to_string()) - .await?; + self.set(device_name, change.payload().to_string()).await?; sleep(MIN_TIME_BETWEEN_SENDS).await; } } diff --git a/crates/zigbee-bridge/src/cached_bridge/poll.rs b/crates/zigbee-bridge/src/cached_bridge/poll.rs index e792de01..697cafda 100644 --- a/crates/zigbee-bridge/src/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/cached_bridge/poll.rs @@ -1,7 +1,7 @@ use std::{collections::HashMap, time::Duration}; use color_eyre::eyre::{Context, OptionExt}; -use color_eyre::Section; +use color_eyre::{Result, Section}; use regex::Regex; use rumqttc::v5::{Event, EventLoop, Incoming}; use serde_json::Value; @@ -10,13 +10,14 @@ use tracing::{error, instrument, trace, warn}; use crate::device::{Device, Property}; use crate::lamp::LampProperty; -use crate::parse_state::parse_properties; +use crate::parse; use crate::radiator::RadiatorProperty; use crate::{light_names, RADIATOR_NAMES}; pub(super) async fn poll_mqtt( mut eventloop: EventLoop, known_states: &RwLock>>, + on_msg: impl Fn(protocol::Reading), ) -> ! { loop { let message = match eventloop.poll().await { @@ -37,11 +38,17 @@ pub(super) async fn poll_mqtt( }; match message { - Message::StateUpdate((device_name, changed_properties)) => { - update_state(known_states, &device_name, changed_properties) - .await; + Message::Update { + device_name, + changed, + readings, + } => { + for reading in readings { + on_msg(reading); + } + update_state(known_states, &device_name, changed).await; } - Message::Other => (), + Message::Irrelevant => (), } } } @@ -64,13 +71,13 @@ async fn update_state( } #[instrument(skip_all)] -fn parse_message(event: Event) -> color_eyre::Result { +fn parse_message(event: Event) -> Result { let Event::Incoming(incoming) = event else { - return Ok(Message::Other); + return Ok(Message::Irrelevant); }; let Incoming::Publish(message) = incoming else { - return Ok(Message::Other); + return Ok(Message::Irrelevant); }; let topic: &str = &String::from_utf8_lossy(&message.topic); @@ -96,17 +103,29 @@ fn parse_message(event: Event) -> color_eyre::Result { topic => { let topic: Vec<_> = topic.split('/').collect(); let device_name = topic[1].to_string(); - let state = parse_properties(&device_name, &message.payload) + let json: Value = serde_json::from_slice(&message.payload) + .wrap_err("Could not deserialize")?; + let map = json + .as_object() + .ok_or_eyre("Top level json must be object")?; + let changed = parse::properties(&device_name, map) .wrap_err("failed to parse device state") .with_note(|| format!("topic: {topic:?}"))?; - Ok(Message::StateUpdate((device_name, state))) + let readings = parse::readings(&device_name, map) + .wrap_err("failed to parse device readings") + .with_note(|| format!("topic: {topic:?}"))?; + Ok(Message::Update { + device_name, + changed, + readings, + }) } } } fn parse_bridge_event( payload: &serde_json::Map, -) -> color_eyre::Result { +) -> Result { let event = payload .get("type") .ok_or_eyre("no type in bridge event")? @@ -127,15 +146,13 @@ fn parse_bridge_event( let is_online = match event { "device_joined" | "device_announce" => true, "device_leave" => false, - _ => return Ok(Message::Other), + _ => return Ok(Message::Irrelevant), }; Ok(online_message(device_name, is_online)) } -fn parse_log_message( - log: &serde_json::Map, -) -> color_eyre::Result { +fn parse_log_message(log: &serde_json::Map) -> Result { let level = log.get("level").ok_or_eyre("no level in log message")?; let message = log .get("message") @@ -144,7 +161,7 @@ fn parse_log_message( .ok_or_eyre("log message is not a string")?; if level != "error" { - return Ok(Message::Other); + return Ok(Message::Irrelevant); } let regex = Regex::new(r"Publish.*? to '(.*?)' failed").unwrap(); @@ -157,28 +174,34 @@ fn parse_log_message( } } - Ok(Message::Other) + Ok(Message::Irrelevant) } fn online_message(device_name: String, is_online: bool) -> Message { if light_names().contains(&device_name.as_str()) { - Message::StateUpdate(( + Message::Update { device_name, - vec![LampProperty::Online(is_online).into()], - )) + changed: vec![LampProperty::Online(is_online).into()], + readings: Vec::new(), + } } else if RADIATOR_NAMES.contains(&device_name.as_str()) { - Message::StateUpdate(( + Message::Update { device_name, - vec![RadiatorProperty::Online(is_online).into()], - )) + changed: vec![RadiatorProperty::Online(is_online).into()], + readings: Vec::new(), + } } else { error!("Unknown device name {device_name}, could not parse log"); - Message::Other + Message::Irrelevant } } #[derive(Debug)] enum Message { - StateUpdate((String, Vec)), - Other, + Update { + device_name: String, + changed: Vec, + readings: Vec, + }, + Irrelevant, } diff --git a/crates/zigbee-bridge/src/device.rs b/crates/zigbee-bridge/src/device.rs index 85a4ba6a..306df41b 100644 --- a/crates/zigbee-bridge/src/device.rs +++ b/crates/zigbee-bridge/src/device.rs @@ -2,7 +2,9 @@ use std::collections::HashMap; use std::fmt::Debug; use crate::lamp::{Lamp, LampProperty, LampPropertyDiscriminants}; -use crate::radiator::{Radiator, RadiatorProperty, RadiatorPropertyDiscriminants}; +use crate::radiator::{ + Radiator, RadiatorProperty, RadiatorPropertyDiscriminants, +}; use crate::{LIGHT_MODELS, RADIATOR_NAMES}; #[derive(PartialEq, Debug, Clone, Copy)] @@ -26,9 +28,9 @@ pub(crate) enum PropertyDiscriminants { Radiator(RadiatorPropertyDiscriminants), } -impl Into for Property { - fn into(self) -> PropertyDiscriminants { - match self { +impl From for PropertyDiscriminants { + fn from(val: Property) -> Self { + match val { Property::Lamp(lamp_prop) => { PropertyDiscriminants::Lamp(lamp_prop.into()) } @@ -47,7 +49,7 @@ pub(crate) trait Device: Sync + Send + Debug { fn clone_dyn(&self) -> Box; fn apply(&mut self, change: Property); - fn changes_relative_to(&self, other: &Box) -> Vec; + fn changes_relative_to(&self, other: &dyn Device) -> Vec; fn all_set_properties(&self) -> HashMap; fn needs_merged_payloads(&self) -> bool; diff --git a/crates/zigbee-bridge/src/lamp.rs b/crates/zigbee-bridge/src/lamp.rs index f7dadde2..e3922847 100644 --- a/crates/zigbee-bridge/src/lamp.rs +++ b/crates/zigbee-bridge/src/lamp.rs @@ -60,7 +60,7 @@ impl Device for Lamp { } #[instrument] - fn changes_relative_to(&self, other: &Box) -> Vec { + fn changes_relative_to(&self, other: &dyn Device) -> Vec { let mut res = Vec::new(); let self_properties = self.all_set_properties(); @@ -126,23 +126,23 @@ impl Device for Lamp { // Ignore model and is_online, because they are read-only - if let Some(val) = (&self).brightness { + if let Some(val) = self.brightness { insert_prop(LampProperty::Brightness(val)); } - if let Some(val) = &self.color { + if let Some(val) = self.color { match val { Color::XY(xy) => { - insert_prop(LampProperty::ColorXY(*xy)); + insert_prop(LampProperty::ColorXY(xy)); } Color::TempK(temp) => { - insert_prop(LampProperty::ColorTempK(*temp)); + insert_prop(LampProperty::ColorTempK(temp)); } } } - if let Some(val) = (&self).is_on { + if let Some(val) = self.is_on { insert_prop(LampProperty::On(val)); } - insert_prop(LampProperty::ColorTempStartup((&self).color_temp_startup)); + insert_prop(LampProperty::ColorTempStartup(self.color_temp_startup)); properties } } diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 2ceabe46..0e2de8ad 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -12,7 +12,7 @@ mod cached_bridge; mod conversion; mod device; pub(crate) mod lamp; -mod parse_state; +mod parse; mod radiator; const MQTT_PORT: u16 = 1883; @@ -49,9 +49,22 @@ pub struct Controller { impl Controller { #[must_use] pub fn start_bridge(mqtt_ip: IpAddr, name: &str) -> Self { + Self::start_bridge_with_reading_callback(mqtt_ip, name, |_| ()) + } + #[must_use] + pub fn start_bridge_with_reading_callback( + mqtt_ip: IpAddr, + name: &str, + on_msg: impl Fn(protocol::Reading) + Send + 'static, + ) -> Self { let (change_sender, change_receiver) = mpsc::unbounded_channel(); - let run_bridge = cached_bridge::run(mqtt_ip, change_receiver, name.to_string()); + let run_bridge = cached_bridge::run( + mqtt_ip, + change_receiver, + name.to_string(), + on_msg, + ); trace!("Spawning zigbee bridge task"); tokio::task::spawn(run_bridge); diff --git a/crates/zigbee-bridge/src/parse_state.rs b/crates/zigbee-bridge/src/parse.rs similarity index 64% rename from crates/zigbee-bridge/src/parse_state.rs rename to crates/zigbee-bridge/src/parse.rs index 6c528c7c..17b5904e 100644 --- a/crates/zigbee-bridge/src/parse_state.rs +++ b/crates/zigbee-bridge/src/parse.rs @@ -1,6 +1,6 @@ -use color_eyre::eyre::{bail, Context, OptionExt, Report}; +use color_eyre::eyre::{bail, Context, OptionExt, Report, Result}; use color_eyre::Section; -use serde_json::Value; +use serde_json::{Map, Value}; use tracing::instrument; use crate::conversion::{mired_to_kelvin, normalize}; @@ -9,28 +9,65 @@ use crate::lamp::LampProperty; use crate::radiator::RadiatorProperty; use crate::{light_names, RADIATOR_NAMES}; -#[instrument(skip(bytes))] -pub(super) fn parse_properties( +#[instrument(skip(map))] +pub(super) fn properties( device_name: &str, - bytes: &[u8], -) -> color_eyre::Result> { + map: &Map, +) -> Result> { if light_names().contains(&device_name) { - parse_lamp_properties(bytes) + parse_lamp_properties(map) } else if RADIATOR_NAMES.contains(&device_name) { - parse_radiator_properties(bytes) + parse_radiator_properties(map) } else { bail!("Unknown device name, could not parse properties"); } } -fn parse_radiator_properties(bytes: &[u8]) -> Result, Report> { - let mut list = Vec::new(); +pub(crate) fn readings( + device_name: &str, + map: &Map, +) -> Result> { + use protocol::{large_bedroom, small_bedroom, Reading}; + + macro_rules! radiator_readings { + ($protocol_module:ident, $ReadingVariant:ident) => { + Ok(std::iter::empty() + .into_iter() + .chain( + map.get("local_temperature") + .map(json_to_f32) + .transpose()? + .map($protocol_module::radiator::Reading::Temperature) + .map($protocol_module::Reading::Radiator) + .map(Reading::$ReadingVariant), + ) + .chain( + map.get("pi_heating_demand") + .map(json_to_f32) + .transpose()? + .map($protocol_module::radiator::Reading::Heating) + .map($protocol_module::Reading::Radiator) + .map(Reading::$ReadingVariant), + ) + .collect()) + }; + } + + match device_name { + "small_bedroom:radiator" => { + radiator_readings!(small_bedroom, SmallBedroom) + } + "large_bedroom:radiator" => { + radiator_readings!(large_bedroom, LargeBedroom) + } + _ => Ok(Vec::new()), + } +} - let json: Value = - serde_json::from_slice(bytes).wrap_err("Could not deserialize")?; - let map = json - .as_object() - .ok_or_eyre("Top level json must be object")?; +fn parse_radiator_properties( + map: &Map, +) -> Result> { + let mut list = Vec::new(); if let Some(setpoint) = map .get("occupied_heating_setpoint") @@ -69,15 +106,9 @@ fn parse_radiator_properties(bytes: &[u8]) -> Result, Report> { Ok(list) } -fn parse_lamp_properties(bytes: &[u8]) -> color_eyre::Result> { +fn parse_lamp_properties(map: &Map) -> Result> { let mut list = Vec::new(); - let json: Value = - serde_json::from_slice(bytes).wrap_err("Could not deserialize")?; - let map = json - .as_object() - .ok_or_eyre("Top level json must be object")?; - if let Some(kelvin) = map .get("color_temp") .map(json_to_usize) @@ -135,21 +166,21 @@ fn parse_lamp_properties(bytes: &[u8]) -> color_eyre::Result> { Ok(list) } -fn json_to_usize(json: &Value) -> color_eyre::Result { +fn json_to_usize(json: &Value) -> Result { json_to_u64(json)? .try_into() .wrap_err("Should be a usize integer") .with_note(|| format!("got: {json:?}")) } -fn json_to_u8(json: &Value) -> color_eyre::Result { +fn json_to_u8(json: &Value) -> Result { json_to_u64(json)? .try_into() .wrap_err("Should be a 8 bit integer") .with_note(|| format!("got: {json:?}")) } -fn json_to_u64(json: &Value) -> color_eyre::Result { +fn json_to_u64(json: &Value) -> Result { json.as_number() .ok_or_eyre("Must be a number") .with_note(|| format!("got: {json:?}"))? @@ -158,7 +189,7 @@ fn json_to_u64(json: &Value) -> color_eyre::Result { .with_note(|| format!("got: {json:?}")) } -fn json_to_i64(json: &Value) -> color_eyre::Result { +fn json_to_i64(json: &Value) -> Result { json.as_number() .ok_or_eyre("Must be a number") .with_note(|| format!("got: {json:?}"))? @@ -167,7 +198,7 @@ fn json_to_i64(json: &Value) -> color_eyre::Result { .with_note(|| format!("got: {json:?}")) } -fn json_to_f64(json: &Value) -> color_eyre::Result { +fn json_to_f64(json: &Value) -> Result { Ok(json .as_number() .ok_or_eyre("Must be a number") @@ -175,3 +206,7 @@ fn json_to_f64(json: &Value) -> color_eyre::Result { .as_f64() .expect("Should be Some if not using arbitrary precision")) } + +fn json_to_f32(json: &Value) -> Result { + json_to_f64(json).map(|v| v as f32) +} diff --git a/crates/zigbee-bridge/src/radiator.rs b/crates/zigbee-bridge/src/radiator.rs index 47d9edab..4e359b72 100644 --- a/crates/zigbee-bridge/src/radiator.rs +++ b/crates/zigbee-bridge/src/radiator.rs @@ -83,7 +83,7 @@ impl Device for Radiator { } } - fn changes_relative_to(&self, other: &Box) -> Vec { + fn changes_relative_to(&self, other: &dyn Device) -> Vec { let mut res = Vec::new(); let self_properties = self.all_set_properties(); @@ -123,10 +123,10 @@ impl Device for Radiator { // Ignore set_by_method and online, because they are read-only - if let Some(val) = (&self).setpoint { + if let Some(val) = self.setpoint { insert_prop(RadiatorProperty::Setpoint(val)); } - if let Some(val) = (&self).reference { + if let Some(val) = self.reference { insert_prop(RadiatorProperty::Reference(val)); } From 3dc7c39a4b6a9cfd9c2857aa2f73c06c65c0d41b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 26 Dec 2024 15:44:09 +0100 Subject: [PATCH 510/687] fix errors caused by moving is_same_as to trait --- crates/brain/src/controller/rooms/kitchen.rs | 2 -- crates/data-server/src/server/affector.rs | 2 +- crates/data-store/src/server/db/series.rs | 2 +- crates/protocol/src/large_bedroom/radiator.rs | 2 +- crates/protocol/src/lib.rs | 5 +++-- crates/protocol/src/small_bedroom/radiator.rs | 2 +- crates/sensor-tui/src/fetch.rs | 2 +- crates/sensor-tui/src/tui/readings.rs | 1 + crates/sensor-tui/src/tui/readings/render/chart.rs | 1 + crates/sensor-tui/src/tui/readings/sensor_info.rs | 2 +- crates/text-widget/src/main.rs | 2 +- crates/text-widget/src/resolve/fetch.rs | 1 + 12 files changed, 13 insertions(+), 11 deletions(-) diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index cfe13756..4bacdc4b 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -2,14 +2,12 @@ use std::time::Duration; use futures_concurrency::future::Race; use futures_util::FutureExt; -use jiff::civil::Time; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; use tracing::warn; use crate::controller::rooms::small_bedroom; use crate::controller::{Event, RestrictedSystem}; -use crate::time; #[derive(PartialEq, Eq)] enum State { diff --git a/crates/data-server/src/server/affector.rs b/crates/data-server/src/server/affector.rs index e72970c7..5a95deae 100644 --- a/crates/data-server/src/server/affector.rs +++ b/crates/data-server/src/server/affector.rs @@ -3,7 +3,7 @@ use std::sync::{Arc, Mutex}; use color_eyre::Result; use governor::Quota; -use protocol::Affector; +use protocol::{Affector, IsSameAs}; use serde::{Deserialize, Serialize}; use slotmap::{DefaultKey, SlotMap}; use tokio::io::AsyncWriteExt; diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index 7b20fc8c..27240754 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -6,7 +6,7 @@ use std::time::Instant; use byteseries::{downsample, series, ByteSeries}; use color_eyre::eyre::{eyre, WrapErr}; use color_eyre::{Result, Section}; -use protocol::reading; +use protocol::{reading, IsSameAs}; use protocol::reading::tree::{Item, Tree}; use serde::{Deserialize, Serialize}; use tracing::{instrument, trace}; diff --git a/crates/protocol/src/large_bedroom/radiator.rs b/crates/protocol/src/large_bedroom/radiator.rs index 973b73b5..6dfb833e 100644 --- a/crates/protocol/src/large_bedroom/radiator.rs +++ b/crates/protocol/src/large_bedroom/radiator.rs @@ -61,7 +61,7 @@ impl Tree for Reading { )), resolution: 1.0, range: 0.0..100.0, - unit: Unit::PercentageOpen, + unit: Unit::RelativePower, description: "Heating valve", branch_id: self.branch_id(), }, diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 54ddd8ed..8a9baca4 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -35,7 +35,7 @@ pub enum Unit { NumberPerCm3, Ohm, Pa, - PercentageOpen, + RelativePower, Ppm, RH, } @@ -51,13 +51,14 @@ impl Display for Unit { Unit::NumberPerCm3 => f.write_str("#/cm³"), Unit::Ohm => f.write_str("Ω"), Unit::Pa => f.write_str("Pa"), - Unit::PercentageOpen => f.write_str("% open"), + Unit::RelativePower => f.write_str("% power"), Unit::Ppm => f.write_str("ppm"), Unit::RH => f.write_str("%RH"), } } } +/// Is this the same variant as the other? pub trait IsSameAs { fn is_same_as(&self, other: &Self) -> bool; } diff --git a/crates/protocol/src/small_bedroom/radiator.rs b/crates/protocol/src/small_bedroom/radiator.rs index 39149aea..069fde31 100644 --- a/crates/protocol/src/small_bedroom/radiator.rs +++ b/crates/protocol/src/small_bedroom/radiator.rs @@ -61,7 +61,7 @@ impl Tree for Reading { )), resolution: 1.0, range: 0.0..100.0, - unit: Unit::PercentageOpen, + unit: Unit::RelativePower, description: "Heating valve", branch_id: self.branch_id(), }, diff --git a/crates/sensor-tui/src/fetch.rs b/crates/sensor-tui/src/fetch.rs index 06fe9847..323c1660 100644 --- a/crates/sensor-tui/src/fetch.rs +++ b/crates/sensor-tui/src/fetch.rs @@ -9,7 +9,7 @@ use color_eyre::eyre::{self, Context, Report}; use color_eyre::Result; use jiff::Timestamp; use log_store::api::{ErrorEvent, Percentile}; -use protocol::Reading; +use protocol::{IsSameAs, Reading}; use std::sync::Mutex; use tokio::time::Instant; use tracing::{debug, instrument}; diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/sensor-tui/src/tui/readings.rs index 241abd71..8a0ece42 100644 --- a/crates/sensor-tui/src/tui/readings.rs +++ b/crates/sensor-tui/src/tui/readings.rs @@ -3,6 +3,7 @@ use std::time::Instant; use crossterm::event::KeyEvent; use log_store::api::Percentile; +use protocol::IsSameAs; use ratatui::layout::Rect; use ratatui::widgets::TableState; use ratatui::Frame; diff --git a/crates/sensor-tui/src/tui/readings/render/chart.rs b/crates/sensor-tui/src/tui/readings/render/chart.rs index 75a95cf6..78131cd6 100644 --- a/crates/sensor-tui/src/tui/readings/render/chart.rs +++ b/crates/sensor-tui/src/tui/readings/render/chart.rs @@ -67,6 +67,7 @@ fn plot_colors(unit: protocol::Unit) -> impl Iterator { &[Green, Cyan] as &'static [Color] } U::None => &[] as &'static [Color], + U::RelativePower => &[Red] as &'static [Color], }; preferred.iter().chain(ALL_COLORS.iter()).copied() } diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/sensor-tui/src/tui/readings/sensor_info.rs index 01b4b37d..464e6c72 100644 --- a/crates/sensor-tui/src/tui/readings/sensor_info.rs +++ b/crates/sensor-tui/src/tui/readings/sensor_info.rs @@ -3,7 +3,7 @@ use indextree::{Arena, NodeId}; use itertools::Itertools; use jiff::Unit; use log_store::api::{self, Percentile}; -use protocol::reading; +use protocol::{reading, IsSameAs}; use protocol::reading::tree::{Item, Tree}; use protocol::Reading; use protocol::{Device, Error}; diff --git a/crates/text-widget/src/main.rs b/crates/text-widget/src/main.rs index 2b4d33fd..0cf77d9e 100644 --- a/crates/text-widget/src/main.rs +++ b/crates/text-widget/src/main.rs @@ -4,7 +4,7 @@ use data_server::api::subscriber::SubMessage; use data_server::api::subscriber::{ReconnectingClient, ReconnectingSubscribedClient}; use gethostname::gethostname; use protocol::reading::tree::Tree; -use protocol::Reading; +use protocol::{IsSameAs, Reading}; use std::net::SocketAddr; use std::time::Duration; use tokio::time::timeout; diff --git a/crates/text-widget/src/resolve/fetch.rs b/crates/text-widget/src/resolve/fetch.rs index b55f2bf7..f3a2cfc4 100644 --- a/crates/text-widget/src/resolve/fetch.rs +++ b/crates/text-widget/src/resolve/fetch.rs @@ -1,6 +1,7 @@ use color_eyre::eyre::Context; use data_server::api::subscriber::ReconnectingSubscribedClient; use data_server::api::subscriber::SubMessage; +use protocol::IsSameAs; use std::net::SocketAddr; use data_store::api::Client; From aea4fa320cf79f24bccdc5f44df0c1425eb3667a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 26 Dec 2024 15:47:53 +0100 Subject: [PATCH 511/687] doc is_same_as + set temp_res for radiator --- crates/protocol/src/large_bedroom/radiator.rs | 4 ++-- crates/protocol/src/lib.rs | 5 ++++- crates/protocol/src/small_bedroom/radiator.rs | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/protocol/src/large_bedroom/radiator.rs b/crates/protocol/src/large_bedroom/radiator.rs index 6dfb833e..85aa1de6 100644 --- a/crates/protocol/src/large_bedroom/radiator.rs +++ b/crates/protocol/src/large_bedroom/radiator.rs @@ -110,8 +110,8 @@ impl Device { crate::DeviceInfo { name: "Radiator", affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Heating(0.0)], - temporal_resolution: Duration::MAX, - min_sample_interval: Duration::ZERO, + temporal_resolution: Duration::from_secs(5), // unknown + min_sample_interval: Duration::ZERO, //unknown max_sample_interval: Duration::MAX, affectors: &[], } diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 8a9baca4..6042306e 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -58,7 +58,10 @@ impl Display for Unit { } } -/// Is this the same variant as the other? +/// Is this the same variant as the other? +/// Example: +/// Temperature(5) is the same as Temperature(6) pub trait IsSameAs { + /// Is this the same variant as the other? fn is_same_as(&self, other: &Self) -> bool; } diff --git a/crates/protocol/src/small_bedroom/radiator.rs b/crates/protocol/src/small_bedroom/radiator.rs index 069fde31..08178da0 100644 --- a/crates/protocol/src/small_bedroom/radiator.rs +++ b/crates/protocol/src/small_bedroom/radiator.rs @@ -110,8 +110,8 @@ impl Device { crate::DeviceInfo { name: "Radiator", affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Heating(0.0)], - temporal_resolution: Duration::MAX, - min_sample_interval: Duration::ZERO, + temporal_resolution: Duration::from_secs(5), // unknown + min_sample_interval: Duration::ZERO, // unknown max_sample_interval: Duration::MAX, affectors: &[], } From ddd5c53920866840967ff71ca9acdb5c0b93bd33 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 26 Dec 2024 17:20:13 +0100 Subject: [PATCH 512/687] send readings from mqtt to data-server --- .../src/api/data_source/reconnecting.rs | 4 +- crates/radiator-bridge/Cargo.toml | 2 + crates/radiator-bridge/src/main.rs | 78 +++++++++++++++---- 3 files changed, 70 insertions(+), 14 deletions(-) diff --git a/crates/data-server/src/api/data_source/reconnecting.rs b/crates/data-server/src/api/data_source/reconnecting.rs index acb015f8..bf04e5df 100644 --- a/crates/data-server/src/api/data_source/reconnecting.rs +++ b/crates/data-server/src/api/data_source/reconnecting.rs @@ -114,7 +114,9 @@ impl Client { /// Needs a list of the affectors that can be controlled through this /// node as an argument. If your node provides not controllable affectors /// pass in an empty Vec. - #[must_use] + /// + /// # Errors + /// returns an error if the address could not looked up pub async fn new( addr: A, affectors: Vec, diff --git a/crates/radiator-bridge/Cargo.toml b/crates/radiator-bridge/Cargo.toml index 15b09ad3..76b1ad20 100644 --- a/crates/radiator-bridge/Cargo.toml +++ b/crates/radiator-bridge/Cargo.toml @@ -15,3 +15,5 @@ tokio = { workspace = true } clap = { workspace = true } logger = { workspace = true } tracing = { workspace = true } +futures-concurrency.workspace = true +futures = "0.3.31" diff --git a/crates/radiator-bridge/src/main.rs b/crates/radiator-bridge/src/main.rs index 96652f0d..448b58c6 100644 --- a/crates/radiator-bridge/src/main.rs +++ b/crates/radiator-bridge/src/main.rs @@ -2,8 +2,12 @@ use std::net::{IpAddr, SocketAddr}; use std::time::{Duration, Instant}; use clap::Parser; -use data_server::api::subscriber::ReconnectingClient; +use data_server::api::data_source; +use data_server::api::subscriber; use data_server::api::subscriber::SubMessage as M; +use futures::FutureExt; +use futures_concurrency::future::Race; +use zigbee_bridge::Controller; #[derive(Parser)] #[command(version, about, long_about=None)] @@ -71,34 +75,77 @@ async fn main() { let args = Opt::parse(); logger::tracing::setup_unlimited(); - let mut data_server = ReconnectingClient::new( + let mut data_subscriber = subscriber::ReconnectingClient::new( args.data_server, env!("CARGO_PKG_NAME").to_owned(), ) .subscribe(); - let zigbee = - zigbee_bridge::Controller::start_bridge(args.mqtt_ip, "temp-bridge"); - let mut lb_ratiator = RadiatorState::default(); - let mut sb_ratiator = RadiatorState::default(); + let mut data_source = data_source::reconnecting::Client::new( + args.data_server, + Vec::new(), + None, + ) + .await + .expect("address is correct"); + + let (reading_tx, mut reading_rx) = tokio::sync::mpsc::channel(1024); + let callback = move |reading| { + reading_tx + .try_send(reading) + .expect("reading_rx should keep up and never drop") + }; + let controller = Controller::start_bridge_with_reading_callback( + args.mqtt_ip, + "temp-bridge", + callback, + ); + + let mut radiators = Radiators { + controller, + small_bedroom: RadiatorState::default(), + large_bedroom: RadiatorState::default(), + }; loop { - let msg = data_server.next().await; + let get_reading = reading_rx + .recv() + .map(|r| r.expect("reading_tx should not drop")) + .map(Event::ZigbeeReading); + let get_msg = data_subscriber.next().map(Event::DataServerMsg); + let event = (get_reading, get_msg).race().await; + + match event { + Event::ZigbeeReading(reading) => { + data_source.send_reading(reading).await.unwrap() + } + Event::DataServerMsg(msg) => radiators.update_if_relevant(msg), + } + } +} + +struct Radiators { + controller: Controller, + small_bedroom: RadiatorState, + large_bedroom: RadiatorState, +} + +impl Radiators { + fn update_if_relevant(&mut self, msg: M) { let Some(relevant_msg) = RelevantMsg::from(msg) else { - continue; + return; }; match relevant_msg { RelevantMsg::SmallBedroom(temp) => { - if sb_ratiator.should_update_given(temp) { - zigbee + if self.small_bedroom.should_update_given(temp) { + self.controller .set_radiator_reference("small_bedroom:radiator", temp) } } RelevantMsg::LargeBedroom(temp) => { - if lb_ratiator.should_update_given(temp) { - tracing::info!("setting temp"); - zigbee + if self.large_bedroom.should_update_given(temp) { + self.controller .set_radiator_reference("large_bedroom:radiator", temp) } } @@ -106,6 +153,11 @@ async fn main() { } } +enum Event { + DataServerMsg(data_server::api::subscriber::SubMessage), + ZigbeeReading(protocol::Reading), +} + impl RelevantMsg { fn from(msg: M) -> Option { use protocol::large_bedroom; From 3d6db1154c0015e206b73e259bfff7bf93570216 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 26 Dec 2024 21:27:47 +0100 Subject: [PATCH 513/687] fixes bug where cancelling SubscribedClient::next leads to reconnect --- .../src/api/subscriber/client/reconnecting.rs | 63 ++++++++++++++++--- 1 file changed, 53 insertions(+), 10 deletions(-) diff --git a/crates/data-server/src/api/subscriber/client/reconnecting.rs b/crates/data-server/src/api/subscriber/client/reconnecting.rs index 5f0b5271..f65f066b 100644 --- a/crates/data-server/src/api/subscriber/client/reconnecting.rs +++ b/crates/data-server/src/api/subscriber/client/reconnecting.rs @@ -43,13 +43,19 @@ impl Client { let mut conn = if let Some(conn) = self.connection.take() { conn } else { - get_connection_or_reconnect(self.addr, &self.name, &mut self.retry_period).await + get_connection_or_reconnect( + self.addr, + &self.name, + &mut self.retry_period, + ) + .await }; match conn.actuate_affector(affector).await { Ok(msg) => { self.retry_period /= 2; - self.retry_period = self.retry_period.max(Duration::from_millis(200)); + self.retry_period = + self.retry_period.max(Duration::from_millis(200)); self.connection = Some(conn); return msg; } @@ -69,13 +75,19 @@ impl Client { let mut conn = if let Some(conn) = self.connection.take() { conn } else { - get_connection_or_reconnect(self.addr, &self.name, &mut self.retry_period).await + get_connection_or_reconnect( + self.addr, + &self.name, + &mut self.retry_period, + ) + .await }; match conn.list_affectors().await { Ok(list) => { self.retry_period /= 2; - self.retry_period = self.retry_period.max(Duration::from_millis(200)); + self.retry_period = + self.retry_period.max(Duration::from_millis(200)); self.connection = Some(conn); return list; } @@ -93,6 +105,15 @@ enum ConnState { Subbed(super::Subscribed), } +impl ConnState { + fn expect_subbed(&mut self, msg: &str) -> &mut super::Subscribed { + match self { + ConnState::Connected(_) => panic!("{msg}"), + ConnState::Subbed(subscribed) => subscribed, + } + } +} + #[derive(Debug)] pub struct SubscribedClient { retry_period: Duration, @@ -102,33 +123,55 @@ pub struct SubscribedClient { } impl SubscribedClient { + /// # Cancel safety, + /// + /// This is cancel safe pub async fn next(&mut self) -> subscriber::SubMessage { loop { let conn = if let Some(conn) = self.connection.take() { conn } else { ConnState::Connected( - get_connection_or_reconnect(self.addr, &self.name, &mut self.retry_period) - .await, + get_connection_or_reconnect( + self.addr, + &self.name, + &mut self.retry_period, + ) + .await, ) }; - let mut subbed = match conn { + let subbed = match conn { ConnState::Connected(conn) => match conn.subscribe().await { Ok(subbed) => subbed, - Err(_) => continue, + Err(e) => { + tracing::warn!("Error subscribing to data-server: {e}"); + continue; + } }, ConnState::Subbed(subbed) => subbed, }; + // for the above we want any cancellation to lead to a full reconnect + // and resubscribe. Anything below here should resume fine so should + // stay connected under cancellation. + self.connection = Some(ConnState::Subbed(subbed)); + let subbed = self + .connection + .as_mut() + .expect("set to Some one line up") + .expect_subbed("set to Subbed one line up"); + match subbed.next().await { Ok(msg) => { self.retry_period /= 2; - self.retry_period = self.retry_period.max(Duration::from_millis(200)); - self.connection = Some(ConnState::Subbed(subbed)); + self.retry_period = + self.retry_period.max(Duration::from_millis(200)); + dbg!(); return msg; } Err(issue) => { + self.connection = None; warn!("Conn issue while getting next_msg: {issue}, reconnecting"); } }; From dbd66ed407772a5f28c591c7befdf16e136d081f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 26 Dec 2024 21:27:47 +0100 Subject: [PATCH 514/687] fixes always reconnecting post cancel of SubscribedClient::next --- .../src/api/subscriber/client/reconnecting.rs | 63 ++++++++++++++++--- 1 file changed, 53 insertions(+), 10 deletions(-) diff --git a/crates/data-server/src/api/subscriber/client/reconnecting.rs b/crates/data-server/src/api/subscriber/client/reconnecting.rs index 5f0b5271..f65f066b 100644 --- a/crates/data-server/src/api/subscriber/client/reconnecting.rs +++ b/crates/data-server/src/api/subscriber/client/reconnecting.rs @@ -43,13 +43,19 @@ impl Client { let mut conn = if let Some(conn) = self.connection.take() { conn } else { - get_connection_or_reconnect(self.addr, &self.name, &mut self.retry_period).await + get_connection_or_reconnect( + self.addr, + &self.name, + &mut self.retry_period, + ) + .await }; match conn.actuate_affector(affector).await { Ok(msg) => { self.retry_period /= 2; - self.retry_period = self.retry_period.max(Duration::from_millis(200)); + self.retry_period = + self.retry_period.max(Duration::from_millis(200)); self.connection = Some(conn); return msg; } @@ -69,13 +75,19 @@ impl Client { let mut conn = if let Some(conn) = self.connection.take() { conn } else { - get_connection_or_reconnect(self.addr, &self.name, &mut self.retry_period).await + get_connection_or_reconnect( + self.addr, + &self.name, + &mut self.retry_period, + ) + .await }; match conn.list_affectors().await { Ok(list) => { self.retry_period /= 2; - self.retry_period = self.retry_period.max(Duration::from_millis(200)); + self.retry_period = + self.retry_period.max(Duration::from_millis(200)); self.connection = Some(conn); return list; } @@ -93,6 +105,15 @@ enum ConnState { Subbed(super::Subscribed), } +impl ConnState { + fn expect_subbed(&mut self, msg: &str) -> &mut super::Subscribed { + match self { + ConnState::Connected(_) => panic!("{msg}"), + ConnState::Subbed(subscribed) => subscribed, + } + } +} + #[derive(Debug)] pub struct SubscribedClient { retry_period: Duration, @@ -102,33 +123,55 @@ pub struct SubscribedClient { } impl SubscribedClient { + /// # Cancel safety, + /// + /// This is cancel safe pub async fn next(&mut self) -> subscriber::SubMessage { loop { let conn = if let Some(conn) = self.connection.take() { conn } else { ConnState::Connected( - get_connection_or_reconnect(self.addr, &self.name, &mut self.retry_period) - .await, + get_connection_or_reconnect( + self.addr, + &self.name, + &mut self.retry_period, + ) + .await, ) }; - let mut subbed = match conn { + let subbed = match conn { ConnState::Connected(conn) => match conn.subscribe().await { Ok(subbed) => subbed, - Err(_) => continue, + Err(e) => { + tracing::warn!("Error subscribing to data-server: {e}"); + continue; + } }, ConnState::Subbed(subbed) => subbed, }; + // for the above we want any cancellation to lead to a full reconnect + // and resubscribe. Anything below here should resume fine so should + // stay connected under cancellation. + self.connection = Some(ConnState::Subbed(subbed)); + let subbed = self + .connection + .as_mut() + .expect("set to Some one line up") + .expect_subbed("set to Subbed one line up"); + match subbed.next().await { Ok(msg) => { self.retry_period /= 2; - self.retry_period = self.retry_period.max(Duration::from_millis(200)); - self.connection = Some(ConnState::Subbed(subbed)); + self.retry_period = + self.retry_period.max(Duration::from_millis(200)); + dbg!(); return msg; } Err(issue) => { + self.connection = None; warn!("Conn issue while getting next_msg: {issue}, reconnecting"); } }; From d7d804be8faf1a78c8260eb79ecb0db99c726dfa Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 26 Dec 2024 21:32:10 +0100 Subject: [PATCH 515/687] queued items (mpsc) are only send if within temporal resolution --- .../src/api/data_source/reconnecting.rs | 142 ++++++++++++------ .../data-server/src/api/subscriber/client.rs | 2 +- crates/radiator-bridge/src/main.rs | 10 +- crates/radiator-bridge/test.sh | 7 +- 4 files changed, 109 insertions(+), 52 deletions(-) diff --git a/crates/data-server/src/api/data_source/reconnecting.rs b/crates/data-server/src/api/data_source/reconnecting.rs index bf04e5df..9aeee15d 100644 --- a/crates/data-server/src/api/data_source/reconnecting.rs +++ b/crates/data-server/src/api/data_source/reconnecting.rs @@ -1,17 +1,17 @@ use futures_concurrency::future::Race; use protocol::Affector; use std::net::SocketAddr; -use std::time::Duration; +use std::time::{Duration, Instant}; use tokio::sync::{mpsc, oneshot}; use tokio::task::JoinHandle; use tokio::time::{sleep, timeout}; use tracing::{info, warn}; -use super::{ReceiveError, SendPreEncodedError}; +use super::SendPreEncodedError; pub struct Client { _conn_handler_task: AbortOnDrop, - to_send_tx: mpsc::Sender<(Vec, SendFeedback)>, + to_send_tx: mpsc::Sender, } struct AbortOnDrop(JoinHandle<()>); @@ -21,11 +21,10 @@ impl Drop for AbortOnDrop { } } -type SendFeedback = oneshot::Sender>; async fn handle_conn( addr: SocketAddr, affectors: Vec, - mut msgs_to_send: mpsc::Receiver<(Vec, SendFeedback)>, + mut msgs_to_send: mpsc::Receiver, msgs_recieved: Option>, ) { loop { @@ -33,69 +32,79 @@ async fn handle_conn( let conn = reconnect(addr, &affectors, &mut retry_period).await; if let Some(ref msgs_recieved) = msgs_recieved { - let res = ( + ( handle_sending(conn.sender, &mut msgs_to_send), handle_recieving(conn.receiver, msgs_recieved), ) .race() .await; - match res { - SendOrRecvError::Sending(e) => tracing::error!("Error sending to data-server: {e}"), - SendOrRecvError::Recieving(e) => { - tracing::error!("Error receiving order from data-server: {e}") - } - } } else { handle_sending(conn.sender, &mut msgs_to_send).await; } } } -enum SendOrRecvError { - Sending(std::io::Error), - Recieving(ReceiveError), +struct SendItem { + bytes: Vec, + feedback: oneshot::Sender>, + deadline: Instant, } async fn handle_sending( mut sender: super::Sender, - msgs_to_send: &mut mpsc::Receiver<(Vec, SendFeedback)>, -) -> SendOrRecvError { + msgs_to_send: &mut mpsc::Receiver, +) { loop { - let (msg, feedback_channel) = msgs_to_send - .recv() - .await - .expect("this is canceled before the corrosponding sender is dropped"); - let res = sender.send_bytes(&msg).await; - let _ignore_err = feedback_channel.send(res.as_ref().map_err(|e| e.to_string()).copied()); + let item = msgs_to_send.recv().await.expect( + "this is canceled before the corrosponding sender is dropped", + ); + let res = if item.deadline.elapsed().is_zero() { + sender + .send_bytes(&item.bytes) + .await + .map_err(|e| e.to_string()) + .map_err(SendError::Io) + } else { + Err(SendError::Outdated) + }; + let _ignore_err = item.feedback.send(res.clone()); if let Err(e) = res { - return SendOrRecvError::Sending(e); + tracing::error!("Error sending reading or sensor error: {e}"); + return; } - tracing::debug!("send bytes: {}", msg.len()); + tracing::debug!("send bytes: {}", item.bytes.len()); } } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, Clone, thiserror::Error)] pub enum SendError { - #[error("Error while sending data to data-server: {0}")] - Sending(String), + #[error("Io error while sending data to data-server: {0}")] + Io(String), #[error( "Sending the data was aborted, probably due to \ reconnect due to failed recieve" )] Aborted, /// returns the encoded message that you tried to send - #[error("Sender queue is full, it has probably been disconnected for a while")] + #[error( + "Sender queue is full, it has probably been disconnected for a while" + )] Overloaded { bytes: Vec }, + #[error("Could not send in time (deadline expired)")] + Outdated, } async fn handle_recieving( mut receiver: super::Receiver, msgs_recieved: &mpsc::Sender, -) -> SendOrRecvError { +) { loop { let msg = match receiver.receive().await { Ok(msg) => msg, - Err(err) => return SendOrRecvError::Recieving(err), + Err(err) => { + tracing::error!("Error receiving affector orders: {err}"); + return; + } }; tracing::debug!("recv item: {msg:?}"); @@ -127,7 +136,9 @@ impl Client { .map_err(|e| e.to_string()) .map_err(InvalidAddress)? .next() - .ok_or_else(|| InvalidAddress("No address passed in".to_string()))?; + .ok_or_else(|| { + InvalidAddress("No address passed in".to_string()) + })?; let (to_send_tx, to_send_rx) = mpsc::channel(100); let task = handle_conn(addr, affectors, to_send_rx, affector_tx); @@ -138,18 +149,28 @@ impl Client { }) } - async fn send_bytes(&mut self, bytes: Vec) -> Result<(), SendError> { + async fn send_bytes( + &mut self, + bytes: Vec, + deadline: Instant, + ) -> Result<(), SendError> { let (tx, rx) = oneshot::channel(); - match self.to_send_tx.try_send((bytes, tx)) { + match self.to_send_tx.try_send(SendItem { + bytes, + feedback: tx, + deadline, + }) { Ok(()) => (), - Err(mpsc::error::TrySendError::Full((bytes, _))) => { - return Err(SendError::Overloaded { bytes }) + Err(mpsc::error::TrySendError::Full(SendItem { + bytes, .. + })) => return Err(SendError::Overloaded { bytes }), + Err(mpsc::error::TrySendError::Closed(_)) => { + panic!("re-connect loop should never end") } - Err(mpsc::error::TrySendError::Closed(_)) => panic!("re-connect loop should never end"), } match rx.await { Ok(Ok(())) => Ok(()), - Ok(Err(send)) => Err(SendError::Sending(send)), + Ok(Err(send_error)) => Err(send_error), Err(_) => Err(SendError::Aborted), } } @@ -158,7 +179,13 @@ impl Client { /// This is cancel safe however the connection will need to be re-established /// the next time its called. This will retry forever, you should call this /// in a timeout future if that is a problem. - pub async fn send_reading(&mut self, reading: protocol::Reading) -> Result<(), SendError> { + pub async fn send_reading( + &mut self, + reading: protocol::Reading, + ) -> Result<(), SendError> { + let deadline = + Instant::now() + reading.device().info().temporal_resolution; + let mut readings = protocol::SensorMessage::<1>::default(); readings .values @@ -167,23 +194,46 @@ impl Client { let msg = protocol::Msg::Readings(readings); let bytes = msg.encode(); - self.send_bytes(bytes).await + self.send_bytes(bytes, deadline).await } + const ERROR_REPORT_SEND_DEADLINE: Duration = Duration::from_secs(60 * 15); /// # Cancel safety /// This is cancel safe however the connection will need to be re-established /// the next time its called. This will retry forever, you should call this /// in a timeout future if that is a problem. - pub async fn send_error(&mut self, report: protocol::Error) -> Result<(), SendError> { - let msg = protocol::Msg::<1>::ErrorReport(protocol::ErrorReport::new(report)); + /// + /// # Warning + /// Message is not send if it could not be send within 15 minutes. Client + /// should re-send the error then. + pub async fn send_error( + &mut self, + report: protocol::Error, + ) -> Result<(), SendError> { + let msg = + protocol::Msg::<1>::ErrorReport(protocol::ErrorReport::new(report)); let bytes = msg.encode(); - self.send_bytes(bytes).await + self.send_bytes( + bytes, + Instant::now() + Self::ERROR_REPORT_SEND_DEADLINE, + ) + .await } - pub async fn check_send_encoded(&mut self, msg: Vec) -> Result<(), SendPreEncodedError> { - protocol::Msg::<50>::decode(msg.to_vec()).map_err(SendPreEncodedError::EncodingCheck)?; - self.send_bytes(msg) + pub async fn check_send_encoded( + &mut self, + msg: Vec, + ) -> Result<(), SendPreEncodedError> { + let decoded = protocol::Msg::<50>::decode(msg.to_vec()) + .map_err(SendPreEncodedError::EncodingCheck)?; + let deadline = match decoded { + protocol::Msg::Readings(sensor_message) => sensor_message.values.iter().map(|v| v.device().info().temporal_resolution).min().expect("empty sensormessages are forbidden"), + protocol::Msg::ErrorReport(_) => Self::ERROR_REPORT_SEND_DEADLINE, + protocol::Msg::AffectorList(_) => unreachable!("send by client on reconnect only, never send by user of client"), + }; + + self.send_bytes(msg, Instant::now() + deadline) .await .map_err(SendPreEncodedError::Sending) } diff --git a/crates/data-server/src/api/subscriber/client.rs b/crates/data-server/src/api/subscriber/client.rs index 50ade317..4d126198 100644 --- a/crates/data-server/src/api/subscriber/client.rs +++ b/crates/data-server/src/api/subscriber/client.rs @@ -61,7 +61,7 @@ impl Subscribed { pub async fn next( &mut self, ) -> Result> { - let received = self.0 .0.next().await?; + let received = self.0.0.next().await?; if let subscriber::Response::SubUpdate(update) = received { Ok(update) diff --git a/crates/radiator-bridge/src/main.rs b/crates/radiator-bridge/src/main.rs index 448b58c6..4a8f2467 100644 --- a/crates/radiator-bridge/src/main.rs +++ b/crates/radiator-bridge/src/main.rs @@ -14,7 +14,11 @@ use zigbee_bridge::Controller; struct Opt { /// IP address where to subscribe for updates #[clap(long)] - data_server: SocketAddr, + data_server_subscribe: SocketAddr, + + /// IP address where to send readings + #[clap(long)] + data_server_update: SocketAddr, /// IP address for MQTT broker #[clap(long)] @@ -76,13 +80,13 @@ async fn main() { logger::tracing::setup_unlimited(); let mut data_subscriber = subscriber::ReconnectingClient::new( - args.data_server, + args.data_server_subscribe, env!("CARGO_PKG_NAME").to_owned(), ) .subscribe(); let mut data_source = data_source::reconnecting::Client::new( - args.data_server, + args.data_server_update, Vec::new(), None, ) diff --git a/crates/radiator-bridge/test.sh b/crates/radiator-bridge/test.sh index 16dcc55f..5d448e13 100755 --- a/crates/radiator-bridge/test.sh +++ b/crates/radiator-bridge/test.sh @@ -11,6 +11,9 @@ # Print if in function: # RUST_LOG='[function_name]=trace' -RUST_LOG='[parse_message]=trace,[{device_name=.*:radi.*}]=trace,[{friendly_name=.*:radi.*}]=trace,info' cargo r -- \ - --data-server=192.168.1.43:1235 \ +# RUST_LOG='[parse_message]=trace,[{device_name=.*:radi.*}]=trace,[{friendly_name=.*:radi.*}]=trace,info' + +RUST_LOG=data_server=trace cargo r -- \ + --data-server-subscribe=192.168.1.43:1235 \ + --data-server-update=192.168.1.43:1234 \ --mqtt-ip=192.168.1.43 From a92a002a4a60193d545081bcbd7f8d95fd8aa736 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 26 Dec 2024 21:44:38 +0100 Subject: [PATCH 516/687] removes leftover dbg --- crates/brain/src/input/web_api/music.rs | 2 -- crates/data-server/src/api/subscriber/client/reconnecting.rs | 1 - crates/data-store/examples/last_15m.rs | 2 +- crates/usb-bridge/src/main.rs | 1 - 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/brain/src/input/web_api/music.rs b/crates/brain/src/input/web_api/music.rs index 78d357dc..6021d351 100644 --- a/crates/brain/src/input/web_api/music.rs +++ b/crates/brain/src/input/web_api/music.rs @@ -15,7 +15,6 @@ pub struct SongUrl { pub async fn add_song_from_url(params: Form, state: Data) -> HttpResponse { let url = params.into_inner().url; - dbg!(); if state .youtube_dl @@ -23,7 +22,6 @@ pub async fn add_song_from_url(params: Form, state: Data) -> Htt .await .is_ok() { - dbg!(); HttpResponse::Ok().finish() } else { diff --git a/crates/data-server/src/api/subscriber/client/reconnecting.rs b/crates/data-server/src/api/subscriber/client/reconnecting.rs index f65f066b..f6dd3712 100644 --- a/crates/data-server/src/api/subscriber/client/reconnecting.rs +++ b/crates/data-server/src/api/subscriber/client/reconnecting.rs @@ -167,7 +167,6 @@ impl SubscribedClient { self.retry_period /= 2; self.retry_period = self.retry_period.max(Duration::from_millis(200)); - dbg!(); return msg; } Err(issue) => { diff --git a/crates/data-store/examples/last_15m.rs b/crates/data-store/examples/last_15m.rs index 28c3388c..e13b643a 100644 --- a/crates/data-store/examples/last_15m.rs +++ b/crates/data-store/examples/last_15m.rs @@ -63,5 +63,5 @@ async fn main() { .await .unwrap(); - dbg!(data); + eprintln!("{:?}", data); } diff --git a/crates/usb-bridge/src/main.rs b/crates/usb-bridge/src/main.rs index 82bcc014..140cb686 100644 --- a/crates/usb-bridge/src/main.rs +++ b/crates/usb-bridge/src/main.rs @@ -36,7 +36,6 @@ async fn main() -> Result<(), color_eyre::Report> { .get_affectors() .await .wrap_err("Could not get affector list")?; - dbg!(&affectors); let mut server_client = reconnecting::Client::new( args.data_server, affectors, From e29f0137c74095c0a822e06f012e3a6bbb69bcef Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 26 Dec 2024 22:26:31 +0100 Subject: [PATCH 517/687] data-source api client tries resend on error up to send deadline --- .../src/api/data_source/reconnecting.rs | 87 +++++++++++++------ 1 file changed, 62 insertions(+), 25 deletions(-) diff --git a/crates/data-server/src/api/data_source/reconnecting.rs b/crates/data-server/src/api/data_source/reconnecting.rs index 9aeee15d..d55599b6 100644 --- a/crates/data-server/src/api/data_source/reconnecting.rs +++ b/crates/data-server/src/api/data_source/reconnecting.rs @@ -1,5 +1,6 @@ use futures_concurrency::future::Race; use protocol::Affector; +use std::collections::VecDeque; use std::net::SocketAddr; use std::time::{Duration, Instant}; use tokio::sync::{mpsc, oneshot}; @@ -21,25 +22,56 @@ impl Drop for AbortOnDrop { } } +enum QueuedItem { + Retry { item: SendItem, prev_err: SendError }, + Fresh(SendItem), +} + +struct SendQueue { + rx: mpsc::Receiver, + need_retry: VecDeque<(SendItem, SendError)>, +} + +impl SendQueue { + async fn next(&mut self) -> QueuedItem { + if let Some((item, prev_err)) = self.need_retry.pop_front() { + QueuedItem::Retry { item, prev_err } + } else { + QueuedItem::Fresh(self.rx.recv().await.expect( + "this is canceled before the corrosponding sender is dropped", + )) + } + } + + fn push(&mut self, needs_retry: SendItem, error: SendError) { + self.need_retry.push_back((needs_retry, error)); + } +} + +// Not cancel safe, should never be canceled async fn handle_conn( addr: SocketAddr, affectors: Vec, - mut msgs_to_send: mpsc::Receiver, + msgs_to_send: mpsc::Receiver, msgs_recieved: Option>, -) { +) -> () { + let mut to_send = SendQueue { + rx: msgs_to_send, + need_retry: VecDeque::new(), + }; loop { let mut retry_period = Duration::from_millis(200); let conn = reconnect(addr, &affectors, &mut retry_period).await; if let Some(ref msgs_recieved) = msgs_recieved { ( - handle_sending(conn.sender, &mut msgs_to_send), + handle_sending(conn.sender, &mut to_send), handle_recieving(conn.receiver, msgs_recieved), ) .race() .await; } else { - handle_sending(conn.sender, &mut msgs_to_send).await; + handle_sending(conn.sender, &mut to_send).await; } } } @@ -50,29 +82,34 @@ struct SendItem { deadline: Instant, } -async fn handle_sending( - mut sender: super::Sender, - msgs_to_send: &mut mpsc::Receiver, -) { +async fn handle_sending(mut sender: super::Sender, to_send: &mut SendQueue) { loop { - let item = msgs_to_send.recv().await.expect( - "this is canceled before the corrosponding sender is dropped", - ); - let res = if item.deadline.elapsed().is_zero() { - sender - .send_bytes(&item.bytes) - .await - .map_err(|e| e.to_string()) - .map_err(SendError::Io) - } else { - Err(SendError::Outdated) - }; - let _ignore_err = item.feedback.send(res.clone()); - if let Err(e) = res { - tracing::error!("Error sending reading or sensor error: {e}"); - return; + match to_send.next().await { + QueuedItem::Fresh(item) if item.deadline.elapsed().is_zero() => { + if let Err(err) = sender.send_bytes(&item.bytes).await { + tracing::warn!("Error sending reading or sensor: {err}"); + to_send.push(item, SendError::Io(err.to_string())); + } else { + let _ = item.feedback.send(Ok(())); + } + } + QueuedItem::Fresh(item) => { + let _ = item.feedback.send(Err(SendError::Outdated)); + } + QueuedItem::Retry { item, .. } + if item.deadline.elapsed().is_zero() => + { + if let Err(err) = sender.send_bytes(&item.bytes).await { + tracing::warn!("Error sending reading or sensor: {err}"); + to_send.push(item, SendError::Io(err.to_string())); + } else { + let _ = item.feedback.send(Ok(())); + } + } + QueuedItem::Retry { item, prev_err } => { + let _ = item.feedback.send(Err(prev_err)); + } } - tracing::debug!("send bytes: {}", item.bytes.len()); } } From 0325d13a9a2059bfcd30bdea74c0feaaf849781f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 27 Dec 2024 13:56:20 +0100 Subject: [PATCH 518/687] update byteseries dep --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 92aac51a..95ad8a01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ zigbee-bridge = { path = "crates/zigbee-bridge" } rpc = { path = "crates/rpc" } logger = { path = "crates/logger" } -byteseries = { git = "https://github.com/dvdsk/byteseries", rev="16d410071cb61a8e375183ca3ce0c7fbdefc9e6b" } +byteseries = { git = "https://github.com/dvdsk/byteseries", rev="325c7823aa2d04bba85d0346077fe999e789f3c9" } tokio = { version = "1.38", features = ["rt-multi-thread"] } color-eyre = "0.6.3" From c8a5487785448e071fc402b022f68f7cfb180ef6 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 27 Dec 2024 16:12:53 +0100 Subject: [PATCH 519/687] add profiling setup for radiator-bridge --- Cargo.toml | 3 +- .../src/api/data_source/reconnecting.rs | 2 ++ crates/radiator-bridge/.cargo/config.toml | 2 ++ crates/radiator-bridge/profile.sh | 29 +++++++++++++++++++ crates/radiator-bridge/src/main.rs | 7 +++-- crates/radiator-bridge/test.sh | 2 +- 6 files changed, 41 insertions(+), 4 deletions(-) create mode 100755 crates/radiator-bridge/profile.sh diff --git a/Cargo.toml b/Cargo.toml index 95ad8a01..88823ef8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,5 +30,6 @@ edition = "2021" license = "GPLv3" authors = ["David Kleingeld & Eva van Houten"] -[profile.release] +[profile.release-with-debug] +inherits = "release" debug = true diff --git a/crates/data-server/src/api/data_source/reconnecting.rs b/crates/data-server/src/api/data_source/reconnecting.rs index d55599b6..a3021f6d 100644 --- a/crates/data-server/src/api/data_source/reconnecting.rs +++ b/crates/data-server/src/api/data_source/reconnecting.rs @@ -22,6 +22,7 @@ impl Drop for AbortOnDrop { } } +#[derive(Debug)] enum QueuedItem { Retry { item: SendItem, prev_err: SendError }, Fresh(SendItem), @@ -76,6 +77,7 @@ async fn handle_conn( } } +#[derive(Debug)] struct SendItem { bytes: Vec, feedback: oneshot::Sender>, diff --git a/crates/radiator-bridge/.cargo/config.toml b/crates/radiator-bridge/.cargo/config.toml index 0127ae27..6f758d47 100644 --- a/crates/radiator-bridge/.cargo/config.toml +++ b/crates/radiator-bridge/.cargo/config.toml @@ -3,3 +3,5 @@ rustflags = ["-Clinker=rust-lld"] [target.armv7-unknown-linux-musleabihf] rustflags = ["-Clinker=rust-lld"] + +#Note: If you're using lld or mold on Linux, you must use the --no-rosegment flag. Otherwise perf will not be able to generate accurate stack traces (explanation). For example, for lld: diff --git a/crates/radiator-bridge/profile.sh b/crates/radiator-bridge/profile.sh new file mode 100755 index 00000000..ca30e103 --- /dev/null +++ b/crates/radiator-bridge/profile.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +set -e + +# Print if argument matches regex: +# +# you can do this with: RUST_LOG='[{topic=.*small_bedroom:piano.*}]=trace,info' +# that will print every log at trace level or higher that is inside an +# instrumented function with an argument topic for which the regex +# .*small_bedroom.* evaluates as true +# +# +# Print if in function: +# RUST_LOG='[function_name]=trace' + +# RUST_LOG='[parse_message]=trace,[{device_name=.*:radi.*}]=trace,[{friendly_name=.*:radi.*}]=trace,info' + +cargo build --profile=release-with-debug +echo '1' | sudo tee /proc/sys/kernel/perf_event_paranoid + +# samply record ../../target/release/radiator-bridge \ +# --data-server-subscribe=192.168.1.43:1235 \ +# --data-server-update=192.168.1.43:1234 \ +# --mqtt-ip=192.168.1.43 + +flamegraph -- ../../target/release/radiator-bridge \ + --data-server-subscribe=192.168.1.43:1235 \ + --data-server-update=192.168.1.43:1234 \ + --mqtt-ip=192.168.1.43 diff --git a/crates/radiator-bridge/src/main.rs b/crates/radiator-bridge/src/main.rs index 4a8f2467..dcf87e11 100644 --- a/crates/radiator-bridge/src/main.rs +++ b/crates/radiator-bridge/src/main.rs @@ -7,6 +7,7 @@ use data_server::api::subscriber; use data_server::api::subscriber::SubMessage as M; use futures::FutureExt; use futures_concurrency::future::Race; +use tracing::warn; use zigbee_bridge::Controller; #[derive(Parser)] @@ -77,7 +78,7 @@ impl RadiatorState { #[tokio::main] async fn main() { let args = Opt::parse(); - logger::tracing::setup_unlimited(); + logger::tracing::setup(); let mut data_subscriber = subscriber::ReconnectingClient::new( args.data_server_subscribe, @@ -121,7 +122,9 @@ async fn main() { match event { Event::ZigbeeReading(reading) => { - data_source.send_reading(reading).await.unwrap() + if let Err(e) = data_source.send_reading(reading).await { + warn!("Error sending new reading to data-store: {e}") + } } Event::DataServerMsg(msg) => radiators.update_if_relevant(msg), } diff --git a/crates/radiator-bridge/test.sh b/crates/radiator-bridge/test.sh index 5d448e13..40fd359e 100755 --- a/crates/radiator-bridge/test.sh +++ b/crates/radiator-bridge/test.sh @@ -13,7 +13,7 @@ # RUST_LOG='[parse_message]=trace,[{device_name=.*:radi.*}]=trace,[{friendly_name=.*:radi.*}]=trace,info' -RUST_LOG=data_server=trace cargo r -- \ +cargo r -- \ --data-server-subscribe=192.168.1.43:1235 \ --data-server-update=192.168.1.43:1234 \ --mqtt-ip=192.168.1.43 From 9203076cc68baa6752ebdd91aa39963a93f5a859 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 27 Dec 2024 23:56:28 +0100 Subject: [PATCH 520/687] use source for error chain instead of formatting in msg --- crates/data-server/src/api/data_source.rs | 18 ++++++------ .../data-server/src/api/subscriber/client.rs | 28 +++++++++++-------- crates/rpc/src/client.rs | 20 ++++++------- 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/crates/data-server/src/api/data_source.rs b/crates/data-server/src/api/data_source.rs index 3b0b298a..e7c2e5d9 100644 --- a/crates/data-server/src/api/data_source.rs +++ b/crates/data-server/src/api/data_source.rs @@ -8,10 +8,10 @@ pub mod reconnecting; #[derive(Debug, thiserror::Error)] pub enum Error { - #[error("Could not connect to data-server: {0}")] - Connecting(std::io::Error), - #[error("Could not send handshake to data-server: {0}")] - Handshake(std::io::Error), + #[error("Could not connect to data-server")] + Connecting(#[source] std::io::Error), + #[error("Could not send handshake to data-server")] + Handshake(#[source] std::io::Error), #[error("Too many affectors, max: {max}, requires: {requires}")] TooManyAffectors { max: usize, requires: usize }, } @@ -59,10 +59,10 @@ impl Client { #[derive(Debug, thiserror::Error)] pub enum SendPreEncodedError { - #[error("Pre-encoded message, could not be decoded it might be from a previous version: {0}")] - EncodingCheck(DecodeMsgError), - #[error("Error while sending pre-encoded msg: {0}")] - Sending(SendError), + #[error("Pre-encoded message, could not be decoded it might be from a previous version")] + EncodingCheck(#[source] DecodeMsgError), + #[error("Error while sending pre-encoded msg")] + Sending(#[source] SendError), } impl Sender { @@ -93,7 +93,7 @@ impl Sender { #[derive(Debug, thiserror::Error)] pub enum ReceiveError { #[error("General io error while receiving data from data-server")] - Io(std::io::Error), + Io(#[source] std::io::Error), #[error("The connection was closed by the data-server")] ConnClosed, #[error("Could not deserialize")] diff --git a/crates/data-server/src/api/subscriber/client.rs b/crates/data-server/src/api/subscriber/client.rs index 4d126198..3628ca83 100644 --- a/crates/data-server/src/api/subscriber/client.rs +++ b/crates/data-server/src/api/subscriber/client.rs @@ -48,7 +48,9 @@ impl Client { } } - pub async fn subscribe(mut self) -> Result> { + pub async fn subscribe( + mut self, + ) -> Result> { self.0.subscribe().await?; Ok(Subscribed(self)) } @@ -61,7 +63,7 @@ impl Subscribed { pub async fn next( &mut self, ) -> Result> { - let received = self.0.0.next().await?; + let received = self.0 .0.next().await?; if let subscriber::Response::SubUpdate(update) = received { Ok(update) @@ -76,14 +78,18 @@ impl Subscribed { #[derive(Debug, thiserror::Error)] pub enum Error { - #[error("Error while sending request: {0}")] - Sending(std::io::Error), - #[error("Error while sending request: {0}")] - Receiving(std::io::Error), + #[error("Error while sending request")] + Sending(#[source] std::io::Error), + #[error("Error while sending request")] + Receiving(#[source] std::io::Error), #[error("General error while processing request")] - Server(subscriber::ServerError), - #[error("Server ran into an specific error with our request: {0}")] - Request(T), - #[error("Error while communicating with server: {0}")] - Comms(#[from] RpcError), + Server(#[source] subscriber::ServerError), + #[error("Server ran into an specific error with our request")] + Request(#[source] T), + #[error("Error while communicating with server")] + Comms( + #[from] + #[source] + RpcError, + ), } diff --git a/crates/rpc/src/client.rs b/crates/rpc/src/client.rs index a0c58943..57017b21 100644 --- a/crates/rpc/src/client.rs +++ b/crates/rpc/src/client.rs @@ -38,16 +38,16 @@ impl fmt::Debug for RpcClient { #[derive(Debug, thiserror::Error)] pub enum ConnectError { - #[error("Error while connecting to server: {0}")] - Io(std::io::Error), - #[error("Could not send handshake: {0}")] - Sending(std::io::Error), + #[error("Error while connecting to server")] + Io(#[source] std::io::Error), + #[error("Could not send handshake")] + Sending(#[source] std::io::Error), #[error("Timed out waiting for server")] Timeout, #[error("Server unexpectedly closed the connection")] Closed, - #[error("Could not receive server response: {0:?}")] - Receiving(std::io::Error), + #[error("Could not receive server response")] + Receiving(#[source] std::io::Error), #[error("Client was already connected")] AlreadyConnected, #[error("Client tried to connected too many times, allowed again in: {0:?}")] @@ -58,10 +58,10 @@ pub enum ConnectError { pub enum RpcError { #[error("Got unexpected response response to request.\nRequest was: {request:?},\nGot response: {response:?}")] IncorrectResponse { request: String, response: String }, - #[error("Error while sending request: {0}")] - Sending(std::io::Error), - #[error("Error while sending request: {0}")] - Receiving(std::io::Error), + #[error("Error while sending request")] + Sending(#[source] std::io::Error), + #[error("Error while sending request")] + Receiving(#[source] std::io::Error), #[error("Server closed connection before it awnserd")] ConnectionClosed, } From 79a405059a51d17e5a2bbd3221dffa0220366dc2 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 28 Dec 2024 14:50:38 +0100 Subject: [PATCH 521/687] add journalctl fields example to docs --- crates/logger/src/tracing.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/crates/logger/src/tracing.rs b/crates/logger/src/tracing.rs index 43909bba..ae0df178 100644 --- a/crates/logger/src/tracing.rs +++ b/crates/logger/src/tracing.rs @@ -59,6 +59,19 @@ use tracing_subscriber::{self, layer::SubscriberExt}; /// ``` /// /// for full docs see: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html +/// +/// # Note +/// If the service runs under systemd it logs to the sysjournal. Then: +/// +/// The standard journald CODE_LINE and CODE_FILE fields are automatically +/// emitted. A TARGET field is emitted containing the event’s target. For +/// events recorded inside spans, an additional SPAN_NAME field is emitted +/// with the name of each of the event’s parent spans. User-defined fields +/// other than the event message field have a prefix applied by default to +/// prevent collision with standard fields. +/// +/// example: `journalctl -fu desk-sensors +/// --output-fields=CODE_FILE,CODE_LINE,MESSAGE -o cat` pub fn setup() { let env_filter = filter::EnvFilter::builder() .with_regex(true) From 010a05c0dadf28e10466e310b8cedc58157da7eb Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 28 Dec 2024 14:51:13 +0100 Subject: [PATCH 522/687] fix data_sources not reconnecting but reporting erros forever --- .../src/api/data_source/reconnecting.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/crates/data-server/src/api/data_source/reconnecting.rs b/crates/data-server/src/api/data_source/reconnecting.rs index a3021f6d..fa4f1692 100644 --- a/crates/data-server/src/api/data_source/reconnecting.rs +++ b/crates/data-server/src/api/data_source/reconnecting.rs @@ -87,27 +87,21 @@ struct SendItem { async fn handle_sending(mut sender: super::Sender, to_send: &mut SendQueue) { loop { match to_send.next().await { - QueuedItem::Fresh(item) if item.deadline.elapsed().is_zero() => { + QueuedItem::Retry { item, .. } | QueuedItem::Fresh(item) + if item.deadline.elapsed().is_zero() => + { if let Err(err) = sender.send_bytes(&item.bytes).await { tracing::warn!("Error sending reading or sensor: {err}"); to_send.push(item, SendError::Io(err.to_string())); + return; } else { let _ = item.feedback.send(Ok(())); } } + // expired QueuedItem::Fresh(item) => { let _ = item.feedback.send(Err(SendError::Outdated)); } - QueuedItem::Retry { item, .. } - if item.deadline.elapsed().is_zero() => - { - if let Err(err) = sender.send_bytes(&item.bytes).await { - tracing::warn!("Error sending reading or sensor: {err}"); - to_send.push(item, SendError::Io(err.to_string())); - } else { - let _ = item.feedback.send(Ok(())); - } - } QueuedItem::Retry { item, prev_err } => { let _ = item.feedback.send(Err(prev_err)); } From d65e0adcf9e3d0d9771e982d3cbcab1c74938eac Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 28 Dec 2024 17:20:01 +0100 Subject: [PATCH 523/687] fix crash if report did not contain backtrace --- crates/sensor-tui/src/tui/reports.rs | 31 ++++++++++++++++------------ 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/crates/sensor-tui/src/tui/reports.rs b/crates/sensor-tui/src/tui/reports.rs index edff9c74..d7887db5 100644 --- a/crates/sensor-tui/src/tui/reports.rs +++ b/crates/sensor-tui/src/tui/reports.rs @@ -17,19 +17,21 @@ struct Report { impl From for Report { fn from(value: eyre::Report) -> Self { let detailed = format!("{value:?}"); - let detailed = strip_ansi_escapes::strip_str(&detailed); + let mut detailed = strip_ansi_escapes::strip_str(&detailed); let last_paragraph = detailed .find("Location:") .expect("Detailed report always lists a location"); - let backtrace_start = last_paragraph - + detailed[last_paragraph..] - .find("\n\n") - .expect("Should be a double line-end before backtrace"); - let detailed = &detailed[..backtrace_start]; + let backtrace_start = detailed[last_paragraph..] + .find("\n\n") + .map(|pos| pos + last_paragraph); + + if let Some(pos) = backtrace_start { + detailed.truncate(pos); + } Self { short: value.to_string(), - detailed: detailed.to_owned(), + detailed, } } } @@ -57,13 +59,13 @@ impl Reports { } pub(super) fn render(&self, frame: &mut Frame, layout: Rect) { - let current = self - .current - .as_ref() - .expect("should only be called when current is Some/needed lines > 0"); + let current = self.current.as_ref().expect( + "should only be called when current is Some/needed lines > 0", + ); let [hint, error] = - Layout::vertical([Constraint::Max(1), Constraint::Min(1)]).areas(layout); + Layout::vertical([Constraint::Max(1), Constraint::Min(1)]) + .areas(layout); let error_style = Style::default().on_light_red().fg(Color::White); @@ -87,7 +89,10 @@ impl Reports { .style(error_style), hint, ); - frame.render_widget(Text::raw(¤t.short).style(error_style), error); + frame.render_widget( + Text::raw(¤t.short).style(error_style), + error, + ); } } From 84500e3b3e0fe96402aafff63f2e43cd98ddfc74 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 28 Dec 2024 17:21:22 +0100 Subject: [PATCH 524/687] refactor --- crates/log-store/src/server/db/log.rs | 2 +- crates/logger/src/tracing.rs | 2 ++ crates/radiator-bridge/src/main.rs | 1 + crates/sensor-tui/src/populate.rs | 16 ++++++++++++---- crates/zigbee-bridge/src/cached_bridge.rs | 4 ++-- crates/zigbee-bridge/src/cached_bridge/poll.rs | 4 ++-- crates/zigbee-bridge/src/lib.rs | 4 ++-- 7 files changed, 22 insertions(+), 11 deletions(-) diff --git a/crates/log-store/src/server/db/log.rs b/crates/log-store/src/server/db/log.rs index 72cefdfd..b5daa606 100644 --- a/crates/log-store/src/server/db/log.rs +++ b/crates/log-store/src/server/db/log.rs @@ -108,7 +108,7 @@ impl Log { let payload_size = protocol::Error::max_size(); let header = format!( "Bincode encoded error logs for {device:?}. \ - Each line has a size: {payload_size} + 2" + Each line has size: {payload_size} + 2" ); let res = ByteSeries::builder() diff --git a/crates/logger/src/tracing.rs b/crates/logger/src/tracing.rs index ae0df178..5296c05b 100644 --- a/crates/logger/src/tracing.rs +++ b/crates/logger/src/tracing.rs @@ -24,6 +24,8 @@ use tracing_subscriber::{self, layer::SubscriberExt}; /// errors are logged /// /// ### log everything in function +/// Note the function must be instrumented for this to work +/// (such that a span is created with the functions name) /// RUST_LOG='[function_name]=trace' /// /// ### Print if argument matches regex: diff --git a/crates/radiator-bridge/src/main.rs b/crates/radiator-bridge/src/main.rs index dcf87e11..f364675a 100644 --- a/crates/radiator-bridge/src/main.rs +++ b/crates/radiator-bridge/src/main.rs @@ -122,6 +122,7 @@ async fn main() { match event { Event::ZigbeeReading(reading) => { + tracing::info!("Got new reading from zigbee: {reading:?}"); if let Err(e) = data_source.send_reading(reading).await { warn!("Error sending new reading to data-store: {e}") } diff --git a/crates/sensor-tui/src/populate.rs b/crates/sensor-tui/src/populate.rs index 08e82cee..119f08b3 100644 --- a/crates/sensor-tui/src/populate.rs +++ b/crates/sensor-tui/src/populate.rs @@ -4,6 +4,7 @@ use std::sync::mpsc; use color_eyre::Result; use data_server::api::subscriber; +use tracing::instrument; use crate::{client_name, Update}; @@ -33,7 +34,7 @@ pub async fn tree( ), send_result( list_from_store(data_store_addr), - "COult not get reading list from data-store", + "Coult not get reading list from data-store", tx.clone() ), send_result( @@ -44,22 +45,29 @@ pub async fn tree( ); } +#[instrument] async fn list_from_server(data_server_addr: SocketAddr) -> Result { - let mut client = subscriber::Client::connect(data_server_addr, client_name()).await?; + let mut client = + subscriber::Client::connect(data_server_addr, client_name()).await?; let list = client.list_affectors().await?; tracing::debug!("affector list: {list:?}"); Ok(Update::AffectorList(list)) } +#[instrument] async fn list_from_store(data_store_addr: SocketAddr) -> Result { - let mut client = data_store::api::Client::connect(data_store_addr, client_name()).await?; + let mut client = + data_store::api::Client::connect(data_store_addr, client_name()) + .await?; let list = client.list_data().await?; tracing::debug!("data list: {list:?}"); Ok(Update::ReadingList(list)) } +#[instrument] async fn list_from_logs(log_store_addr: SocketAddr) -> Result { - let mut client = log_store::api::Client::connect(log_store_addr, client_name()).await?; + let mut client = + log_store::api::Client::connect(log_store_addr, client_name()).await?; let list = client.list_devices().await?; tracing::debug!("log list: {list:?}"); Ok(Update::DeviceList(list)) diff --git a/crates/zigbee-bridge/src/cached_bridge.rs b/crates/zigbee-bridge/src/cached_bridge.rs index 349f739a..8e64f96d 100644 --- a/crates/zigbee-bridge/src/cached_bridge.rs +++ b/crates/zigbee-bridge/src/cached_bridge.rs @@ -24,7 +24,7 @@ pub(super) async fn run( mqtt_ip: IpAddr, change_receiver: mpsc::UnboundedReceiver<(String, Property)>, name: String, - on_msg: impl Fn(protocol::Reading), + reading_callback: impl Fn(protocol::Reading), ) -> ! { // The id string must be random or subscribe does not work let id = name + " " + &rand::random::().to_string(); @@ -59,7 +59,7 @@ pub(super) async fn run( } trace!("Starting main zigbee management loops"); - let poll_mqtt = poll::poll_mqtt(eventloop, &known_states, on_msg); + let poll_mqtt = poll::poll_mqtt(eventloop, &known_states, reading_callback); let handle_changes = changes::handle( change_receiver, &mut mqtt, diff --git a/crates/zigbee-bridge/src/cached_bridge/poll.rs b/crates/zigbee-bridge/src/cached_bridge/poll.rs index 697cafda..c3ace215 100644 --- a/crates/zigbee-bridge/src/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/cached_bridge/poll.rs @@ -17,7 +17,7 @@ use crate::{light_names, RADIATOR_NAMES}; pub(super) async fn poll_mqtt( mut eventloop: EventLoop, known_states: &RwLock>>, - on_msg: impl Fn(protocol::Reading), + reading_callback: impl Fn(protocol::Reading), ) -> ! { loop { let message = match eventloop.poll().await { @@ -44,7 +44,7 @@ pub(super) async fn poll_mqtt( readings, } => { for reading in readings { - on_msg(reading); + reading_callback(reading); } update_state(known_states, &device_name, changed).await; } diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 0e2de8ad..3ec19296 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -55,7 +55,7 @@ impl Controller { pub fn start_bridge_with_reading_callback( mqtt_ip: IpAddr, name: &str, - on_msg: impl Fn(protocol::Reading) + Send + 'static, + reading_callback: impl Fn(protocol::Reading) + Send + 'static, ) -> Self { let (change_sender, change_receiver) = mpsc::unbounded_channel(); @@ -63,7 +63,7 @@ impl Controller { mqtt_ip, change_receiver, name.to_string(), - on_msg, + reading_callback, ); trace!("Spawning zigbee bridge task"); tokio::task::spawn(run_bridge); From 925aa857b6ea5be5a59cc07eaf6f112fed015d83 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 28 Dec 2024 17:24:06 +0100 Subject: [PATCH 525/687] remove some unneeded log statements lowerd level of others --- crates/radiator-bridge/src/main.rs | 1 - crates/zigbee-bridge/src/cached_bridge/changes.rs | 2 +- crates/zigbee-bridge/src/parse.rs | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/radiator-bridge/src/main.rs b/crates/radiator-bridge/src/main.rs index f364675a..dcf87e11 100644 --- a/crates/radiator-bridge/src/main.rs +++ b/crates/radiator-bridge/src/main.rs @@ -122,7 +122,6 @@ async fn main() { match event { Event::ZigbeeReading(reading) => { - tracing::info!("Got new reading from zigbee: {reading:?}"); if let Err(e) = data_source.send_reading(reading).await { warn!("Error sending new reading to data-store: {e}") } diff --git a/crates/zigbee-bridge/src/cached_bridge/changes.rs b/crates/zigbee-bridge/src/cached_bridge/changes.rs index 9c230f81..1803454d 100644 --- a/crates/zigbee-bridge/src/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/cached_bridge/changes.rs @@ -33,7 +33,7 @@ pub(super) async fn handle( let (device_name, change) = update.expect("Channel should never close"); - tracing::info!("Received change order: {change:?} for device {device_name}"); + tracing::debug!("Received change order: {change:?} for device {device_name}"); apply_change_to_needed(device_name, change, &mut needed_states); // When there hasn't been a new change in 100 milliseconds, we diff --git a/crates/zigbee-bridge/src/parse.rs b/crates/zigbee-bridge/src/parse.rs index 17b5904e..e9d751a9 100644 --- a/crates/zigbee-bridge/src/parse.rs +++ b/crates/zigbee-bridge/src/parse.rs @@ -102,7 +102,6 @@ fn parse_radiator_properties( list.push(RadiatorProperty::SetByMethod(set_method).into()); } - tracing::info!("list: {list:?}"); Ok(list) } From ebd59aaaeff0d597556a3a9f42a294d1a8a37427 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 28 Dec 2024 17:53:03 +0100 Subject: [PATCH 526/687] fixes div by zero due to min_sample_interval being zero --- crates/data-store/src/server/db/series.rs | 38 ++++++++++++++++--- crates/protocol/src/large_bedroom/radiator.rs | 2 +- crates/protocol/src/small_bedroom/radiator.rs | 2 +- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index 27240754..ae76f97a 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -1,13 +1,13 @@ use std::fs::create_dir_all; use std::io; use std::path::{Path, PathBuf}; -use std::time::Instant; +use std::time::{Duration, Instant}; use byteseries::{downsample, series, ByteSeries}; use color_eyre::eyre::{eyre, WrapErr}; use color_eyre::{Result, Section}; -use protocol::{reading, IsSameAs}; use protocol::reading::tree::{Item, Tree}; +use protocol::{reading, IsSameAs}; use serde::{Deserialize, Serialize}; use tracing::{instrument, trace}; @@ -273,19 +273,31 @@ fn meta_list_and_payload_size( (meta, payload_size) } -/// Multiplying the time for this sample by this factor -/// allows you to save the whole number and retain the required -/// temporal_resolution and min_sample_interval. +/// Scaling factor, when applied to milliseconds it returns some other +/// unit that is the most minimal representation of time for this device. +/// +/// Example given a device with +/// - minimal sample interval 5 seconds +/// - the temporal_resolution 10 seconds +/// We only need to store something every 5 seconds and we can be up to 5 +/// seconds off in both directions. Thus one 'minimal representation unit' is +/// 5 seconds pub fn millis_to_minimal_representation( device_info: protocol::DeviceInfo, ) -> u64 { + assert!( + device_info.min_sample_interval > Duration::ZERO, + "min sample interval may not be zero, device info: {device_info:?}" + ); let needed_interval = device_info .temporal_resolution .min(device_info.min_sample_interval) .as_secs_f32(); let mul_factor = 0.001 / needed_interval; let div_factor = 1. / mul_factor; - div_factor.round() as u64 + let factor = div_factor.round() as u64; + assert_ne!(factor, 0); + factor } #[instrument(level = "debug", skip(data))] @@ -375,6 +387,20 @@ mod test { use protocol::large_bedroom::{bed, desk}; use protocol::{large_bedroom, Reading}; + #[test] + fn millis_to_minimal_representation_factor_is_not_zero() { + let info = protocol::DeviceInfo { + name: "test", + affects_readings: &[], + min_sample_interval: std::time::Duration::ZERO, + max_sample_interval: std::time::Duration::MAX, + temporal_resolution: std::time::Duration::from_secs(5), + affectors: &[], + }; + let factor = millis_to_minimal_representation(info); + assert_eq!(5000 / factor, 5); + } + #[test] fn millis_to_minimal_representation_factor_makes_sense() { let info = protocol::DeviceInfo { diff --git a/crates/protocol/src/large_bedroom/radiator.rs b/crates/protocol/src/large_bedroom/radiator.rs index 85aa1de6..4d08127e 100644 --- a/crates/protocol/src/large_bedroom/radiator.rs +++ b/crates/protocol/src/large_bedroom/radiator.rs @@ -111,7 +111,7 @@ impl Device { name: "Radiator", affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Heating(0.0)], temporal_resolution: Duration::from_secs(5), // unknown - min_sample_interval: Duration::ZERO, //unknown + min_sample_interval: Duration::from_secs(5), // unknown max_sample_interval: Duration::MAX, affectors: &[], } diff --git a/crates/protocol/src/small_bedroom/radiator.rs b/crates/protocol/src/small_bedroom/radiator.rs index 08178da0..583c417a 100644 --- a/crates/protocol/src/small_bedroom/radiator.rs +++ b/crates/protocol/src/small_bedroom/radiator.rs @@ -111,7 +111,7 @@ impl Device { name: "Radiator", affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Heating(0.0)], temporal_resolution: Duration::from_secs(5), // unknown - min_sample_interval: Duration::ZERO, // unknown + min_sample_interval: Duration::from_secs(5), // unknown max_sample_interval: Duration::MAX, affectors: &[], } From cb8e4826ff42816e44f04df6fc5394a35c765af5 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 29 Dec 2024 12:16:48 +0100 Subject: [PATCH 527/687] add profile setup for brain, fix that of radiator-bridge --- crates/brain/profile.sh | 10 ++++++++++ crates/radiator-bridge/profile.sh | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100755 crates/brain/profile.sh diff --git a/crates/brain/profile.sh b/crates/brain/profile.sh new file mode 100755 index 00000000..87e55ab2 --- /dev/null +++ b/crates/brain/profile.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +cargo build --profile=release-with-debug +echo '1' | sudo tee /proc/sys/kernel/perf_event_paranoid + +samply record ../../target/release-with-debug/brain \ + --data-server 192.168.1.43:1235 \ + --mpd-ip 192.168.1.43 \ + --http-port 34326 \ + --mqtt-ip 192.168.1.43 diff --git a/crates/radiator-bridge/profile.sh b/crates/radiator-bridge/profile.sh index ca30e103..2867bc21 100755 --- a/crates/radiator-bridge/profile.sh +++ b/crates/radiator-bridge/profile.sh @@ -18,12 +18,12 @@ set -e cargo build --profile=release-with-debug echo '1' | sudo tee /proc/sys/kernel/perf_event_paranoid -# samply record ../../target/release/radiator-bridge \ +# samply record ../../target/release-with-debug/radiator-bridge \ # --data-server-subscribe=192.168.1.43:1235 \ # --data-server-update=192.168.1.43:1234 \ # --mqtt-ip=192.168.1.43 -flamegraph -- ../../target/release/radiator-bridge \ +flamegraph -- ../../target/release-with-debug/radiator-bridge \ --data-server-subscribe=192.168.1.43:1235 \ --data-server-update=192.168.1.43:1234 \ --mqtt-ip=192.168.1.43 From c3ccc3bdafae4bf335a8c217bf842aa63b36bf24 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 29 Dec 2024 12:37:24 +0100 Subject: [PATCH 528/687] update deps + remove unused deps --- Cargo.toml | 4 +++- crates/brain/Cargo.toml | 9 ++------- crates/data-server/Cargo.toml | 7 +++---- crates/data-store/Cargo.toml | 3 +-- crates/desk-sensors/Cargo.toml | 4 +--- crates/log-store/Cargo.toml | 3 +-- crates/logger/Cargo.toml | 2 +- crates/protocol/Cargo.toml | 2 +- crates/rpc/Cargo.toml | 5 ++--- crates/text-widget/Cargo.toml | 2 +- crates/zigbee-bridge/Cargo.toml | 7 ------- 11 files changed, 16 insertions(+), 32 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 88823ef8..403cec44 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,9 @@ logger = { path = "crates/logger" } byteseries = { git = "https://github.com/dvdsk/byteseries", rev="325c7823aa2d04bba85d0346077fe999e789f3c9" } +serde = { version = "1", features = ["derive"] } tokio = { version = "1.38", features = ["rt-multi-thread"] } +governor = "0.8" color-eyre = "0.6.3" tracing = "0.1.40" tracing-error = "0.2.0" @@ -22,7 +24,7 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } futures-concurrency = "7.6.2" jiff = "0.1" clap = { version = "4", features = ["derive"]} -thiserror = "1" +thiserror = "2" [workspace.package] rust-version = "1.82" diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index b4bef717..99834bb4 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -13,19 +13,14 @@ zigbee-bridge = { workspace = true } futures = "0.3" tokio = { workspace = true, features = ["full"] } -axum = { version = "0.7.4", default-features = false, features = ["tokio", "http1"] } -axum-macros = "0.4.1" -hueclient = { git = "https://github.com/dvdsk/hue.rs"} - -serde = { version = "1.0", features = ["derive"] } +serde.workspace = true serde_yaml = "0.9" bincode = "1.3" -thiserror = "1.0" +thiserror.workspace = true jiff = { workspace = true, features = ["serde"] } -tz-rs = "0.6.14" bytes = "1.5" byteorder = "1.4" diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index 89e92fb8..990915c8 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -20,17 +20,16 @@ rpc = { workspace = true } protocol = { workspace = true, features = ["alloc", "thiserror"] } tokio = { workspace = true, features = ["rt", "macros", "net", "sync", "io-util"] } -tokio-stream = { version = "0.1.15", features = ["net"] } -thiserror = "1.0.61" +thiserror.workspace = true futures = "0.3.30" tokio-serde = { version = "0.9.0", features = ["bincode"] } tokio-util = { version = "0.7.11", features = ["codec"] } -serde = { version = "1.0.208", features = ["derive"] } +serde.workspace = true futures-concurrency = { workspace = true } slotmap = "1.0.7" tracing-futures = "0.2.5" socket2 = "0.5.7" -governor = "0.6.3" +governor.workspace = true [dev-dependencies] reserve-port = "2" diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index 9a990622..aec4d5d1 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -27,12 +27,11 @@ data-server = { workspace = true } byteseries = { workspace = true } tokio = { workspace = true, features = ["fs", "net", "rt-multi-thread", "sync"] } futures-concurrency = { workspace = true } -serde = { version = "1.0.203", features = ["derive"] } +serde.workspace = true thiserror = { workspace = true } futures = "0.3.30" smallvec = "2.0.0-alpha.6" num = "0.4.3" -hdrhistogram = "7.5.4" ron = "0.8.1" [dev-dependencies] diff --git a/crates/desk-sensors/Cargo.toml b/crates/desk-sensors/Cargo.toml index 48ac7ee2..46b0d743 100644 --- a/crates/desk-sensors/Cargo.toml +++ b/crates/desk-sensors/Cargo.toml @@ -7,7 +7,6 @@ authors.workspace = true [dependencies] linux-embedded-hal = "0.4" -gpiocdev-embedded-hal = { version = "0.1.1", features = ["async_tokio"] } bme280 = { version = "0.5", git = "https://github.com/dvdsk/bme280-rs", features = ["postcard", "serde", "with_std"] } data-server = { workspace = true } @@ -21,6 +20,5 @@ tracing-error = { workspace = true } logger = { workspace = true } tokio = { workspace = true, features = ["rt", "time", "macros"] } -embedded-hal-async = "1.0.0" heapless = "0.8.0" -governor = "0.6.3" +governor.workspace = true diff --git a/crates/log-store/Cargo.toml b/crates/log-store/Cargo.toml index e5d52bc2..acbc3af4 100644 --- a/crates/log-store/Cargo.toml +++ b/crates/log-store/Cargo.toml @@ -27,12 +27,11 @@ rpc = { workspace = true } tokio = { workspace = true, features = ["fs", "net", "rt-multi-thread", "sync"] } futures-concurrency = { workspace = true } -serde = { version = "1.0.203", features = ["derive"] } +serde.workspace = true bincode = "1.3.3" thiserror = { workspace = true } futures = "0.3.30" smallvec = "2.0.0-alpha.6" -num = "0.4.3" hdrhistogram = "7.5.4" derivative = "2.2.0" diff --git a/crates/logger/Cargo.toml b/crates/logger/Cargo.toml index 960b78a8..d9dcd350 100644 --- a/crates/logger/Cargo.toml +++ b/crates/logger/Cargo.toml @@ -12,6 +12,6 @@ tracing-error = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } tracing-journald = "0.3" libsystemd = "0.7" -governor = "0.6.3" +governor.workspace = true tracing-core = "0.1.32" color-eyre.workspace = true diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index 76620158..3d968c31 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -9,7 +9,7 @@ authors.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -serde = { version = "1.0", features = ["derive"], default-features = false } +serde.workspace = true postcard = { version = "1.0.10", features = ["experimental-derive", "use-defmt"] } heapless = { version = "0.8.0", features = ["serde", "defmt-03"] } strum = { version = "0.26.2", default-features = false, features = ["derive"] } diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index aabcf80e..75606b97 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -9,12 +9,11 @@ authors.workspace = true [dependencies] color-eyre = "0.6.3" futures = "0.3.30" -governor = "0.6.3" +governor.workspace = true tokio = { workspace = true, features = ["net", "rt", "sync", "time"] } tokio-util = { version = "0.7.11", features = ["codec"] } tracing.workspace = true -logger = { workspace = true } -serde = { version = "1.0.209", features = ["derive"] } +serde.workspace = true tokio-serde = { version = "0.9.0", features = ["bincode"] } thiserror.workspace = true diff --git a/crates/text-widget/Cargo.toml b/crates/text-widget/Cargo.toml index ac4e2195..10f8d896 100644 --- a/crates/text-widget/Cargo.toml +++ b/crates/text-widget/Cargo.toml @@ -21,6 +21,6 @@ tracing.workspace = true tracing-error.workspace = true tracing-subscriber.workspace = true dirs = "5.0.1" -serde = { version = "1.0.204", features = ["derive"] } +serde.workspace = true promptly = "0.3.1" ron = "0.8.1" diff --git a/crates/zigbee-bridge/Cargo.toml b/crates/zigbee-bridge/Cargo.toml index ceeb81ee..7000fe07 100644 --- a/crates/zigbee-bridge/Cargo.toml +++ b/crates/zigbee-bridge/Cargo.toml @@ -14,16 +14,9 @@ colorimetry = { git = "https://github.com/harbik/colorimetry", features = ["cct" rumqttc = { version = "0.24.0", default-features = false } serde_json = "1.0.132" thiserror.workspace = true -futures-concurrency = { workspace = true } tokio = { workspace = true, features = ["sync"] } tracing = { workspace = true } -futures = "0.3.31" strum = { version = "0.26.3", features = ["derive"] } -logger = { workspace = true } color-eyre.workspace = true -itertools = "0.13.0" regex = "1.11.1" rand = "0.8.5" - -[dev-dependencies] -logger.workspace = true From 2102f26b633e1c66405058ca6428385f400a42b9 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 29 Dec 2024 12:43:21 +0100 Subject: [PATCH 529/687] fixes test --- crates/protocol/src/small_bedroom/bed.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/protocol/src/small_bedroom/bed.rs b/crates/protocol/src/small_bedroom/bed.rs index 00792d4b..7d09016d 100644 --- a/crates/protocol/src/small_bedroom/bed.rs +++ b/crates/protocol/src/small_bedroom/bed.rs @@ -558,6 +558,8 @@ mod test { #[test] #[cfg(feature = "alloc")] fn test_is_same_as() { + use crate::IsSameAs; + assert!(Reading::Co2(5).is_same_as(&Reading::Co2(0))); let a = crate::Reading::SmallBedroom( From fcbb96bae063a19390e2cd34249eb9edaa6acaaa Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 29 Dec 2024 23:50:01 +0100 Subject: [PATCH 530/687] add support for ikea symphonisk panel in small bedroom --- crates/protocol/src/small_bedroom.rs | 6 +- .../small_bedroom/portable_button_panel.rs | 130 ++++++++++++++++++ .../zigbee-bridge/src/cached_bridge/poll.rs | 5 +- crates/zigbee-bridge/src/parse.rs | 41 +++++- 4 files changed, 179 insertions(+), 3 deletions(-) create mode 100644 crates/protocol/src/small_bedroom/portable_button_panel.rs diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index 4db01b4b..c7b41e59 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -9,6 +9,7 @@ use crate::button::Press; pub mod bed; pub mod desk; +pub mod portable_button_panel; pub mod radiator; crate::button_enum! { @@ -41,6 +42,7 @@ crate::button_enum! { )] #[repr(u8)] pub enum Reading { + PortableButtonPanel(portable_button_panel::Reading) = 4, ButtonPanel(ButtonPanel) = 0, Desk(desk::Reading) = 1, Bed(bed::Reading) = 2, @@ -48,7 +50,7 @@ pub enum Reading { } #[cfg(feature = "alloc")] -crate::reading::tree::all_nodes! {Reading; ReadingDiscriminants; ButtonPanel, Desk, Bed, Radiator} +crate::reading::tree::all_nodes! {Reading; ReadingDiscriminants; ButtonPanel, Desk, Bed, Radiator, PortableButtonPanel} #[derive( strum::EnumDiscriminants, @@ -101,6 +103,7 @@ pub enum Device { Desk(desk::Device), Bed(bed::Device), Radiator(radiator::Device), + PortableButtonPanel(portable_button_panel::Device), } macro_rules! tree { @@ -135,6 +138,7 @@ impl Device { Device::Desk(device) => device.info(), Device::Bed(device) => device.info(), Device::Radiator(device) => device.info(), + Device::PortableButtonPanel(device) => device.info(), } } } diff --git a/crates/protocol/src/small_bedroom/portable_button_panel.rs b/crates/protocol/src/small_bedroom/portable_button_panel.rs new file mode 100644 index 00000000..6f291a3e --- /dev/null +++ b/crates/protocol/src/small_bedroom/portable_button_panel.rs @@ -0,0 +1,130 @@ +use core::time::Duration; + +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "alloc")] +use crate::reading::tree::{Item, Tree}; +use crate::IsSameAs; + +#[derive( + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, +)] +#[repr(u8)] +pub enum Reading { + PlayPause, + TrackNext, + TrackPrevious, + VolumeUp, + VolumeUpHold, + VolumeDown, + VolumeDownHold, + Dots1InitialPress, + Dots1ShortRelease, + Dots1DoublePress, + Dots1LongPress, + Dots1LongRelease, + Dots2InitialPress, + Dots2ShortRelease, + Dots2DoublePress, + Dots2LongPress, + Dots2LongRelease, +} + +#[cfg(feature = "alloc")] +impl Tree for Reading { + #[must_use] + fn inner(&self) -> Item<'_> { + Item::Leaf(crate::reading::Info { + val: 1.0, + device: crate::Device::SmallBedroom( + super::Device::PortableButtonPanel(Device), + ), + description: "button", + range: 0.0..3.0, + resolution: 1.0, + unit: crate::Unit::None, + branch_id: self.branch_id(), + }) + } + + #[must_use] + fn branch_id(&self) -> crate::reading::tree::Id { + ReadingDiscriminants::from(self) as crate::reading::tree::Id + } +} + +impl IsSameAs for Reading { + fn is_same_as(&self, other: &Self) -> bool { + self.eq(other) + } +} + +#[derive( + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + Eq, + PartialEq, + Hash, +)] +pub struct Device; + +impl core::fmt::Display for Device { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.info().name) + } +} + +macro_rules! tree { + [$thing:ident; $($item:expr),+] => { + [$(crate::$thing::SmallBedroom( + crate::small_bedroom::$thing::PortableButtonPanel($item), + )),+] + }; +} + +impl Device { + /// Note the order in which the `affects_readings` occur is the order in which + /// they will be stored, do not change it! + #[must_use] + pub const fn info(&self) -> crate::DeviceInfo { + crate::DeviceInfo { + name: "Ikea Symfonisk", + affects_readings: &tree![Reading; + Reading::PlayPause, + Reading::TrackNext, + Reading::TrackPrevious, + Reading::VolumeUp, + Reading::VolumeUpHold, + Reading::VolumeDown, + Reading::VolumeDownHold, + Reading::Dots1InitialPress, + Reading::Dots1ShortRelease, + Reading::Dots1DoublePress, + Reading::Dots1LongPress, + Reading::Dots1LongRelease, + Reading::Dots2InitialPress, + Reading::Dots2ShortRelease, + Reading::Dots2DoublePress, + Reading::Dots2LongPress, + Reading::Dots2LongRelease + ], + temporal_resolution: Duration::from_secs(1), // unknown + min_sample_interval: Duration::from_secs(5), // unknown + max_sample_interval: Duration::MAX, + affectors: &[], + } + } +} diff --git a/crates/zigbee-bridge/src/cached_bridge/poll.rs b/crates/zigbee-bridge/src/cached_bridge/poll.rs index c3ace215..b5713dc2 100644 --- a/crates/zigbee-bridge/src/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/cached_bridge/poll.rs @@ -111,7 +111,10 @@ fn parse_message(event: Event) -> Result { let changed = parse::properties(&device_name, map) .wrap_err("failed to parse device state") .with_note(|| format!("topic: {topic:?}"))?; - let readings = parse::readings(&device_name, map) + let readings = parse::radiator_readings(&device_name, map) + .wrap_err("failed to parse device readings") + .with_note(|| format!("topic: {topic:?}"))?; + let readings = parse::media_buttons(&device_name, map) .wrap_err("failed to parse device readings") .with_note(|| format!("topic: {topic:?}"))?; Ok(Message::Update { diff --git a/crates/zigbee-bridge/src/parse.rs b/crates/zigbee-bridge/src/parse.rs index e9d751a9..9f3d60d5 100644 --- a/crates/zigbee-bridge/src/parse.rs +++ b/crates/zigbee-bridge/src/parse.rs @@ -1,5 +1,6 @@ use color_eyre::eyre::{bail, Context, OptionExt, Report, Result}; use color_eyre::Section; +use protocol::small_bedroom; use serde_json::{Map, Value}; use tracing::instrument; @@ -23,7 +24,45 @@ pub(super) fn properties( } } -pub(crate) fn readings( +pub(crate) fn media_buttons( + device_name: &str, + map: &Map, +) -> Vec { + use protocol::small_bedroom::portable_button_panel::Reading as R; + let action_reading_mapping = [ + ("play_pause", R::PlayPause), + ("track_next", R::TrackNext), + ("track_previous", R::TrackPrevious), + ("volume_up", R::VolumeUp), + ("volume_up_hold", R::VolumeUpHold), + ("volume_down", R::VolumeDown), + ("volume_down_hold", R::VolumeDownHold), + ("dots_1_initial_press", R::Dots1InitialPress), + ("dots_1_short_release", R::Dots1ShortRelease), + ("dots_1_double_press", R::Dots1DoublePress), + ("dots_1_long_press", R::Dots1LongPress), + ("dots_1_long_release", R::Dots1LongRelease), + ("dots_2_initial_press", R::Dots2InitialPress), + ("dots_2_short_release", R::Dots2ShortRelease), + ("dots_2_double_press", R::Dots2DoublePress), + ("dots_2_long_press", R::Dots2LongPress), + ("dots_2_long_release", R::Dots2LongRelease), + ]; + + if device_name == "small_bedroom:media_buttons" { + action_reading_mapping + .iter() + .filter(|(action, _)| map.contains_key(*action)) + .map(|(_, reading)| reading.clone()) + .map(small_bedroom::Reading::PortableButtonPanel) + .map(protocol::Reading::SmallBedroom) + .collect() + } else { + Vec::new() + } +} + +pub(crate) fn radiator_readings( device_name: &str, map: &Map, ) -> Result> { From 59f3648fcdf5da8bb3fd7ef4e79a86f5f6a77996 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 30 Dec 2024 10:32:52 +0100 Subject: [PATCH 531/687] fixes ikea symphonisk support --- crates/data-server/src/server/watch.rs | 3 ++ .../zigbee-bridge/src/cached_bridge/poll.rs | 7 ++-- crates/zigbee-bridge/src/parse.rs | 38 +++++++++++++------ 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/crates/data-server/src/server/watch.rs b/crates/data-server/src/server/watch.rs index 78652b75..634af13e 100644 --- a/crates/data-server/src/server/watch.rs +++ b/crates/data-server/src/server/watch.rs @@ -73,6 +73,9 @@ impl LastSeen { ) | Reading::SmallBedroom( small_bedroom::Reading::ButtonPanel(_), + ) + | Reading::SmallBedroom( + small_bedroom::Reading::PortableButtonPanel(_), ) => None, } .map(|reset_cmd| (reading, reset_cmd)) diff --git a/crates/zigbee-bridge/src/cached_bridge/poll.rs b/crates/zigbee-bridge/src/cached_bridge/poll.rs index b5713dc2..d9a47b3f 100644 --- a/crates/zigbee-bridge/src/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/cached_bridge/poll.rs @@ -111,12 +111,13 @@ fn parse_message(event: Event) -> Result { let changed = parse::properties(&device_name, map) .wrap_err("failed to parse device state") .with_note(|| format!("topic: {topic:?}"))?; - let readings = parse::radiator_readings(&device_name, map) + let mut readings = parse::radiator_readings(&device_name, map) .wrap_err("failed to parse device readings") .with_note(|| format!("topic: {topic:?}"))?; - let readings = parse::media_buttons(&device_name, map) - .wrap_err("failed to parse device readings") + let button_readings = parse::portable_button_panel(&device_name, map) + .wrap_err("failed to parse media buttons") .with_note(|| format!("topic: {topic:?}"))?; + readings.extend(button_readings); Ok(Message::Update { device_name, changed, diff --git a/crates/zigbee-bridge/src/parse.rs b/crates/zigbee-bridge/src/parse.rs index 9f3d60d5..7f13c3e3 100644 --- a/crates/zigbee-bridge/src/parse.rs +++ b/crates/zigbee-bridge/src/parse.rs @@ -24,10 +24,10 @@ pub(super) fn properties( } } -pub(crate) fn media_buttons( +pub(crate) fn portable_button_panel( device_name: &str, map: &Map, -) -> Vec { +) -> Result> { use protocol::small_bedroom::portable_button_panel::Reading as R; let action_reading_mapping = [ ("play_pause", R::PlayPause), @@ -49,16 +49,25 @@ pub(crate) fn media_buttons( ("dots_2_long_release", R::Dots2LongRelease), ]; - if device_name == "small_bedroom:media_buttons" { - action_reading_mapping - .iter() - .filter(|(action, _)| map.contains_key(*action)) - .map(|(_, reading)| reading.clone()) - .map(small_bedroom::Reading::PortableButtonPanel) - .map(protocol::Reading::SmallBedroom) - .collect() + if device_name == "small_bedroom:portable_button_panel" { + map.get("action") + .map(json_to_str) + .transpose()? + .map(|action| { + action_reading_mapping + .iter() + .find(|(a, _)| action == *a) + .map(|(_, reading)| reading.clone()) + .map(small_bedroom::Reading::PortableButtonPanel) + .map(protocol::Reading::SmallBedroom) + .ok_or_eyre( + "every action should have a corrosponding reading", + ) + .with_note(|| format!("action was: {action}")) + }) + .transpose() } else { - Vec::new() + Ok(None) } } @@ -245,6 +254,13 @@ fn json_to_f64(json: &Value) -> Result { .expect("Should be Some if not using arbitrary precision")) } +fn json_to_str(json: &Value) -> Result<&str> { + Ok(json + .as_str() + .ok_or_eyre("Must be a string") + .with_note(|| format!("got: {json:?}"))?) +} + fn json_to_f32(json: &Value) -> Result { json_to_f64(json).map(|v| v as f32) } From a945ee6c5b9d7d79f041e8944371909ae3f24df9 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 30 Dec 2024 10:59:14 +0100 Subject: [PATCH 532/687] fix symphonisk (do subscribe) + minor refactor --- Cargo.toml | 1 + crates/brain/Cargo.toml | 2 +- crates/data-server/Cargo.toml | 2 +- crates/data-store/Cargo.toml | 2 +- crates/log-store/Cargo.toml | 2 +- crates/protocol/src/small_bedroom/portable_button_panel.rs | 5 +++++ crates/radiator-bridge/Cargo.toml | 1 + crates/radiator-bridge/src/main.rs | 1 + crates/rpc/Cargo.toml | 4 ++-- crates/zigbee-bridge/src/cached_bridge.rs | 3 +++ crates/zigbee-bridge/src/cached_bridge/poll.rs | 7 ++++--- crates/zigbee-bridge/src/parse.rs | 4 ++-- 12 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 403cec44..64f39345 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ color-eyre = "0.6.3" tracing = "0.1.40" tracing-error = "0.2.0" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +futures = "0.3.31" futures-concurrency = "7.6.2" jiff = "0.1" clap = { version = "4", features = ["derive"]} diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 99834bb4..6641aac9 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -11,7 +11,7 @@ protocol = { workspace = true, features = ["alloc"] } data-server = { workspace = true } zigbee-bridge = { workspace = true } -futures = "0.3" +futures.workspace = true tokio = { workspace = true, features = ["full"] } serde.workspace = true diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index 990915c8..31787a51 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -21,7 +21,7 @@ rpc = { workspace = true } protocol = { workspace = true, features = ["alloc", "thiserror"] } tokio = { workspace = true, features = ["rt", "macros", "net", "sync", "io-util"] } thiserror.workspace = true -futures = "0.3.30" +futures.workspace = true tokio-serde = { version = "0.9.0", features = ["bincode"] } tokio-util = { version = "0.7.11", features = ["codec"] } serde.workspace = true diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index aec4d5d1..0a725e4c 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -29,7 +29,7 @@ tokio = { workspace = true, features = ["fs", "net", "rt-multi-thread", "sync"] futures-concurrency = { workspace = true } serde.workspace = true thiserror = { workspace = true } -futures = "0.3.30" +futures.workspace = true smallvec = "2.0.0-alpha.6" num = "0.4.3" ron = "0.8.1" diff --git a/crates/log-store/Cargo.toml b/crates/log-store/Cargo.toml index acbc3af4..1aac68f9 100644 --- a/crates/log-store/Cargo.toml +++ b/crates/log-store/Cargo.toml @@ -30,7 +30,7 @@ futures-concurrency = { workspace = true } serde.workspace = true bincode = "1.3.3" thiserror = { workspace = true } -futures = "0.3.30" +futures.workspace = true smallvec = "2.0.0-alpha.6" hdrhistogram = "7.5.4" derivative = "2.2.0" diff --git a/crates/protocol/src/small_bedroom/portable_button_panel.rs b/crates/protocol/src/small_bedroom/portable_button_panel.rs index 6f291a3e..b4bf6fef 100644 --- a/crates/protocol/src/small_bedroom/portable_button_panel.rs +++ b/crates/protocol/src/small_bedroom/portable_button_panel.rs @@ -56,6 +56,11 @@ impl Tree for Reading { }) } + fn name(&self) -> String { + let dbg_repr = format!("{self:?}"); + dbg_repr + } + #[must_use] fn branch_id(&self) -> crate::reading::tree::Id { ReadingDiscriminants::from(self) as crate::reading::tree::Id diff --git a/crates/radiator-bridge/Cargo.toml b/crates/radiator-bridge/Cargo.toml index 76b1ad20..ce7f00d3 100644 --- a/crates/radiator-bridge/Cargo.toml +++ b/crates/radiator-bridge/Cargo.toml @@ -15,5 +15,6 @@ tokio = { workspace = true } clap = { workspace = true } logger = { workspace = true } tracing = { workspace = true } +color-eyre.workspace = true futures-concurrency.workspace = true futures = "0.3.31" diff --git a/crates/radiator-bridge/src/main.rs b/crates/radiator-bridge/src/main.rs index dcf87e11..66da7d52 100644 --- a/crates/radiator-bridge/src/main.rs +++ b/crates/radiator-bridge/src/main.rs @@ -78,6 +78,7 @@ impl RadiatorState { #[tokio::main] async fn main() { let args = Opt::parse(); + color_eyre::install().unwrap(); logger::tracing::setup(); let mut data_subscriber = subscriber::ReconnectingClient::new( diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index 75606b97..d8834401 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -7,8 +7,8 @@ license.workspace = true authors.workspace = true [dependencies] -color-eyre = "0.6.3" -futures = "0.3.30" +color-eyre.workspace = true +futures.workspace = true governor.workspace = true tokio = { workspace = true, features = ["net", "rt", "sync", "time"] } tokio-util = { version = "0.7.11", features = ["codec"] } diff --git a/crates/zigbee-bridge/src/cached_bridge.rs b/crates/zigbee-bridge/src/cached_bridge.rs index 8e64f96d..3ff89fda 100644 --- a/crates/zigbee-bridge/src/cached_bridge.rs +++ b/crates/zigbee-bridge/src/cached_bridge.rs @@ -57,6 +57,9 @@ pub(super) async fn run( .unwrap(); mqtt.request_state(radiator).await; } + mqtt.subscribe("zigbee2mqtt/small_bedroom:portable_button_panel") + .await + .unwrap(); trace!("Starting main zigbee management loops"); let poll_mqtt = poll::poll_mqtt(eventloop, &known_states, reading_callback); diff --git a/crates/zigbee-bridge/src/cached_bridge/poll.rs b/crates/zigbee-bridge/src/cached_bridge/poll.rs index d9a47b3f..8f65c813 100644 --- a/crates/zigbee-bridge/src/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/cached_bridge/poll.rs @@ -114,9 +114,10 @@ fn parse_message(event: Event) -> Result { let mut readings = parse::radiator_readings(&device_name, map) .wrap_err("failed to parse device readings") .with_note(|| format!("topic: {topic:?}"))?; - let button_readings = parse::portable_button_panel(&device_name, map) - .wrap_err("failed to parse media buttons") - .with_note(|| format!("topic: {topic:?}"))?; + let button_readings = + parse::portable_button_panel(&device_name, map) + .wrap_err("failed to parse media buttons") + .with_note(|| format!("topic: {topic:?}"))?; readings.extend(button_readings); Ok(Message::Update { device_name, diff --git a/crates/zigbee-bridge/src/parse.rs b/crates/zigbee-bridge/src/parse.rs index 7f13c3e3..d63c7818 100644 --- a/crates/zigbee-bridge/src/parse.rs +++ b/crates/zigbee-bridge/src/parse.rs @@ -20,7 +20,7 @@ pub(super) fn properties( } else if RADIATOR_NAMES.contains(&device_name) { parse_radiator_properties(map) } else { - bail!("Unknown device name, could not parse properties"); + Ok(Vec::new()) } } @@ -30,7 +30,7 @@ pub(crate) fn portable_button_panel( ) -> Result> { use protocol::small_bedroom::portable_button_panel::Reading as R; let action_reading_mapping = [ - ("play_pause", R::PlayPause), + ("toggle", R::PlayPause), ("track_next", R::TrackNext), ("track_previous", R::TrackPrevious), ("volume_up", R::VolumeUp), From 77a7162978b86fadf699777e1ac609227eb41826 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 30 Dec 2024 12:49:15 +0100 Subject: [PATCH 533/687] Rename light_new in system to zigbee Better reflects expanded functionality --- crates/brain/src/controller/mod.rs | 18 +++++++++--------- crates/brain/src/system.rs | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 3ec03f2a..cb0e63b7 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -28,46 +28,46 @@ impl RestrictedSystem { bri: f64, ) { if self.allowed_lights.contains(&name) { - self.system.lights_new.set_color_temp(name, kelvin); - self.system.lights_new.set_brightness(name, bri); + self.system.zigbee.set_color_temp(name, kelvin); + self.system.zigbee.set_brightness(name, bri); } } async fn one_lamp_on(&mut self, name: &'static str) { if self.allowed_lights.contains(&name) { - self.system.lights_new.set_on(name); + self.system.zigbee.set_on(name); } } async fn one_lamp_off(&mut self, name: &'static str) { if self.allowed_lights.contains(&name) { - self.system.lights_new.set_off(name); + self.system.zigbee.set_off(name); } } async fn all_lamps_ct(&mut self, kelvin: usize, bri: f64) { for name in &self.allowed_lights { - self.system.lights_new.set_color_temp(name, kelvin); - self.system.lights_new.set_brightness(name, bri); + self.system.zigbee.set_color_temp(name, kelvin); + self.system.zigbee.set_brightness(name, bri); } } async fn all_lamps_off(&mut self) { for name in &self.allowed_lights { - self.system.lights_new.set_off(name); + self.system.zigbee.set_off(name); } } async fn all_lamps_on(&mut self) { for name in &self.allowed_lights { - self.system.lights_new.set_on(name); + self.system.zigbee.set_on(name); } } async fn all_lamps_but_one_off(&mut self, leave_this_on: &str) { for name in &self.allowed_lights { if *name != leave_this_on { - self.system.lights_new.set_off(name); + self.system.zigbee.set_off(name); } } } diff --git a/crates/brain/src/system.rs b/crates/brain/src/system.rs index b2e5488c..fc0d7e9e 100644 --- a/crates/brain/src/system.rs +++ b/crates/brain/src/system.rs @@ -10,7 +10,7 @@ use crate::input::jobs::Jobs; pub struct System { #[allow(dead_code)] pub jobs: Jobs, - pub lights_new: Controller, + pub zigbee: Controller, // pub mpd: Mpd, } @@ -18,7 +18,7 @@ impl System { pub fn init(mqtt_ip: IpAddr, jobs: Jobs) -> Self { Self { jobs, - lights_new: Controller::start_bridge(mqtt_ip, "brain"), + zigbee: Controller::start_bridge(mqtt_ip, "brain"), // mpd: Mpd, } } From b52f962541471ee4a583ad6779471c2a67dcb46b Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 30 Dec 2024 12:51:04 +0100 Subject: [PATCH 534/687] Add radiator setpoint control to small bedroom --- crates/brain/src/controller/mod.rs | 10 +++++++++ .../src/controller/rooms/small_bedroom.rs | 22 +++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index cb0e63b7..750c25e7 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -17,6 +17,7 @@ pub enum Event { #[derive(Clone)] pub(crate) struct RestrictedSystem { allowed_lights: Vec<&'static str>, + allowed_radiators: Vec<&'static str>, system: System, } @@ -71,6 +72,12 @@ impl RestrictedSystem { } } } + + async fn set_radiators_setpoint(&mut self, temperature: f64) { + for name in &self.allowed_radiators { + self.system.zigbee.set_radiator_setpoint(name, temperature); + } + } } pub fn start( @@ -91,6 +98,7 @@ pub fn start( "large_bedroom:wardrobe", "large_bedroom:bed", ], + allowed_radiators: vec!["large_bedroom:radiator"], }; tasks.spawn(rooms::large_bedroom::run(rx1, sender.clone(), restricted)); @@ -101,6 +109,7 @@ pub fn start( "small_bedroom:bureau", "small_bedroom:piano", ], + allowed_radiators: vec!["small_bedroom:radiator"], }; tasks.spawn(rooms::small_bedroom::run(rx2, sender.clone(), restricted)); @@ -113,6 +122,7 @@ pub fn start( "kitchen:fridge", "kitchen:hallway", ], + allowed_radiators: vec![], }; tasks.spawn(rooms::kitchen::run(rx3, sender, restricted)); diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 8523713d..f6430fa8 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -28,19 +28,23 @@ const fn time(hour: i8, minute: i8) -> f64 { } const T0_00: f64 = time(0, 0); const T8_00: f64 = time(8, 0); +const T8_30: f64 = time(8, 30); const T9_00: f64 = time(9, 0); +const T10_30: f64 = time(10, 30); +const T13_00: f64 = time(13, 0); const T16_00: f64 = time(16, 0); const T17_00: f64 = time(17, 0); const T18_00: f64 = time(18, 0); const T20_30: f64 = time(20, 30); +const T21_00: f64 = time(21, 0); const T21_30: f64 = time(21, 30); const T22_00: f64 = time(22, 0); -const T23_00: f64 = time(22, 0); +const T23_00: f64 = time(23, 0); pub async fn run( mut event_rx: broadcast::Receiver, event_tx: broadcast::Sender, - system: RestrictedSystem, + mut system: RestrictedSystem, ) { let mut room = Room::new(event_tx, system.clone()); let mut next_update = Instant::now() + UPDATE_INTERVAL; @@ -69,6 +73,7 @@ pub async fn run( } Trigger::Event(RelevantEvent::Wakeup) => room.to_wakeup().await, Trigger::ShouldUpdate => { + system.set_radiators_setpoint(goal_temp_now()).await; room.all_lights_daylight().await; next_update = Instant::now() + UPDATE_INTERVAL; } @@ -103,6 +108,19 @@ pub(super) fn is_nap_time() -> bool { && now < Time::new(20, 0, 0, 0).unwrap() } +pub(super) fn goal_temp_now() -> f64 { + let now = crate::time::now(); + + match time(now.hour(), now.minute()) { + T8_30..T10_30 => 19.5, + T10_30..T13_00 => 20.0, + T13_00..T21_00 => 21.0, + T21_00..T22_00 => 20.0, + T22_00.. | T0_00..T8_30 => 18.5, + _ => 18.5, + } +} + // TODO: move to jobs system and remove update trigger pub(super) fn daylight_now() -> (usize, f64) { let now = crate::time::now(); From f386aae30921f76df50ca37abd6099fd04c9e945 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 31 Dec 2024 10:00:36 +0100 Subject: [PATCH 535/687] fix reset cooldown + update embassy --- Cargo.toml | 2 +- crates/data-server/src/server/watch.rs | 2 +- sensor-nodes/Cargo.lock | 51 +++++++++++++------------ sensor-nodes/Cargo.toml | 28 +++++++------- sensor-nodes/bed-lb/src/network.rs | 7 +++- sensor-nodes/bed-lb/src/sensors/fast.rs | 2 +- 6 files changed, 48 insertions(+), 44 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 64f39345..8494f5e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ logger = { path = "crates/logger" } byteseries = { git = "https://github.com/dvdsk/byteseries", rev="325c7823aa2d04bba85d0346077fe999e789f3c9" } -serde = { version = "1", features = ["derive"] } +serde = { version = "1", features = ["derive"], default-features = false } tokio = { version = "1.38", features = ["rt-multi-thread"] } governor = "0.8" color-eyre = "0.6.3" diff --git a/crates/data-server/src/server/watch.rs b/crates/data-server/src/server/watch.rs index 634af13e..d8173d82 100644 --- a/crates/data-server/src/server/watch.rs +++ b/crates/data-server/src/server/watch.rs @@ -88,7 +88,7 @@ impl LastSeen { .map(|(_, at)| at) .copied(); !last_reset.is_some_and(|last_reset| { - last_reset.elapsed() < MIN_RESET_INTERVAL + last_reset.elapsed() > MIN_RESET_INTERVAL }) }) .map(|(reading, reset_cmd)| (reading.clone(), reset_cmd)) diff --git a/sensor-nodes/Cargo.lock b/sensor-nodes/Cargo.lock index 1c47f081..5b514baa 100644 --- a/sensor-nodes/Cargo.lock +++ b/sensor-nodes/Cargo.lock @@ -266,7 +266,7 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" +source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" dependencies = [ "defmt", "embassy-futures", @@ -282,22 +282,20 @@ dependencies = [ [[package]] name = "embassy-executor" -version = "0.6.3" -source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" +version = "0.7.0" +source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" dependencies = [ "cortex-m", "critical-section", "defmt", "document-features", "embassy-executor-macros", - "embassy-time-driver", - "embassy-time-queue-driver", ] [[package]] name = "embassy-executor-macros" version = "0.6.2" -source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" +source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" dependencies = [ "darling", "proc-macro2", @@ -308,12 +306,12 @@ dependencies = [ [[package]] name = "embassy-futures" version = "0.1.1" -source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" +source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" [[package]] name = "embassy-hal-internal" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" +source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" dependencies = [ "cortex-m", "critical-section", @@ -324,7 +322,7 @@ dependencies = [ [[package]] name = "embassy-net" version = "0.5.0" -source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" +source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" dependencies = [ "defmt", "document-features", @@ -341,7 +339,7 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" +source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" dependencies = [ "defmt", ] @@ -349,7 +347,7 @@ dependencies = [ [[package]] name = "embassy-net-driver-channel" version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" +source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" dependencies = [ "embassy-futures", "embassy-net-driver", @@ -359,7 +357,7 @@ dependencies = [ [[package]] name = "embassy-net-wiznet" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" +source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" dependencies = [ "defmt", "embassy-futures", @@ -372,7 +370,7 @@ dependencies = [ [[package]] name = "embassy-stm32" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" +source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" dependencies = [ "aligned", "bit_field", @@ -391,6 +389,7 @@ dependencies = [ "embassy-sync", "embassy-time", "embassy-time-driver", + "embassy-time-queue-utils", "embassy-usb-driver", "embassy-usb-synopsys-otg", "embedded-can", @@ -418,7 +417,7 @@ dependencies = [ [[package]] name = "embassy-sync" version = "0.6.1" -source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" +source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" dependencies = [ "cfg-if", "critical-section", @@ -431,39 +430,41 @@ dependencies = [ [[package]] name = "embassy-time" -version = "0.3.2" -source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" +version = "0.4.0" +source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" dependencies = [ "cfg-if", "critical-section", "defmt", "document-features", "embassy-time-driver", - "embassy-time-queue-driver", "embedded-hal 0.2.7", "embedded-hal 1.0.0", "embedded-hal-async", "futures-util", - "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "embassy-time-driver" -version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" dependencies = [ "document-features", ] [[package]] -name = "embassy-time-queue-driver" +name = "embassy-time-queue-utils" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" +source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +dependencies = [ + "embassy-executor", + "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "embassy-usb" version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" +source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" dependencies = [ "defmt", "embassy-futures", @@ -478,7 +479,7 @@ dependencies = [ [[package]] name = "embassy-usb-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" +source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" dependencies = [ "defmt", ] @@ -486,7 +487,7 @@ dependencies = [ [[package]] name = "embassy-usb-synopsys-otg" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=080900c#080900c8d11b25aaa9fdece4d03a73386ad622fd" +source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" dependencies = [ "critical-section", "defmt", diff --git a/sensor-nodes/Cargo.toml b/sensor-nodes/Cargo.toml index aaa90b94..2e8d333f 100644 --- a/sensor-nodes/Cargo.toml +++ b/sensor-nodes/Cargo.toml @@ -13,10 +13,10 @@ embassy-stm32 = { version = "0.1.0", features = [ "defmt", "stm32f401cc", embassy-net = { version = "0.5.0", features = ["defmt", "proto-ipv4", "tcp", "dhcpv4","medium-ethernet"] } embassy-net-wiznet = { version = "0.1.0", features = ["defmt"] } embassy-sync = { version = "0.6.1", features = ["defmt"] } -embassy-executor = { version = "0.6.3", features = ["arch-cortex-m", -"executor-thread", "defmt", "integrated-timers", "executor-interrupt"] } +embassy-executor = { version = "0.7", features = ["arch-cortex-m", +"executor-thread", "defmt", "executor-interrupt"] } embassy-embedded-hal = { version = "0.2.0" } -embassy-time = { version = "0.3.2", features = ["defmt", +embassy-time = { version = "0.4", features = ["defmt", "defmt-timestamp-uptime-ms", "tick-hz-32_768"] } embassy-futures = { version = "0.1.1"} @@ -31,17 +31,17 @@ defmt-rtt = "0.4" panic-probe = { version = "0.3", features = ["print-defmt"] } [patch.crates-io] -embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } -embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } -embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } -embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } -embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } -embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } -embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } -embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } -embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } -embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } -embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "080900c" } +embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } +embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } +embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } +embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } +embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } +embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } +embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } +embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } +embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } +# embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } +embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } [workspace.package] rust-version = "1.78" diff --git a/sensor-nodes/bed-lb/src/network.rs b/sensor-nodes/bed-lb/src/network.rs index e0121033..3edaa996 100644 --- a/sensor-nodes/bed-lb/src/network.rs +++ b/sensor-nodes/bed-lb/src/network.rs @@ -119,8 +119,8 @@ pub async fn handle( } } -fn affector_list() -> affector::ListMessage<5> { - let mut list = affector::ListMessage::<5>::empty(); +fn affector_list() -> affector::ListMessage<6> { + let mut list = affector::ListMessage::<6>::empty(); unwrap!(list.values.push(Affector::LargeBedroom( protocol::large_bedroom::Affector::Bed(bed::Affector::RgbLed { red: 0, @@ -144,6 +144,9 @@ fn affector_list() -> affector::ListMessage<5> { bed::Affector::Nau7802RightCalib ), ))); + unwrap!(list.values.push(Affector::LargeBedroom( + protocol::large_bedroom::Affector::Bed(bed::Affector::ResetNode) + ))); list } diff --git a/sensor-nodes/bed-lb/src/sensors/fast.rs b/sensor-nodes/bed-lb/src/sensors/fast.rs index 70f1a2b8..a1e288d7 100644 --- a/sensor-nodes/bed-lb/src/sensors/fast.rs +++ b/sensor-nodes/bed-lb/src/sensors/fast.rs @@ -18,7 +18,7 @@ fn sig_lux_diff(old: f32, new: f32) -> bool { fn sig_weight_diff(old: u32, new: u32) -> bool { let diff = new.abs_diff(old); - diff > 2000 + diff > 15 } async fn report_lux( From 7725c7b3cf8f4e3d4a2a07f3851738f78e1915ad Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 30 Dec 2024 13:51:19 +0100 Subject: [PATCH 536/687] Add light functionality to portable buttons --- .../src/controller/rooms/small_bedroom.rs | 29 +++++++++++++------ .../controller/rooms/small_bedroom/filter.rs | 3 +- .../controller/rooms/small_bedroom/state.rs | 7 ++++- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index f6430fa8..30be58a7 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -3,7 +3,7 @@ use std::time::Duration; use futures_concurrency::future::Race; use futures_util::FutureExt; use jiff::civil::Time; -use protocol::small_bedroom::ButtonPanel; +use protocol::small_bedroom::{portable_button_panel, ButtonPanel}; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; use tracing::trace; @@ -68,8 +68,11 @@ pub async fn run( let trigger = (get_event, tick).race().await; match trigger { - Trigger::Event(RelevantEvent::Button(button)) => { - handle_buttonpress(&mut room, button).await; + Trigger::Event( + event @ RelevantEvent::Button(_) + | event @ RelevantEvent::PortableButton(_), + ) => { + handle_buttonpress(&mut room, event).await; } Trigger::Event(RelevantEvent::Wakeup) => room.to_wakeup().await, Trigger::ShouldUpdate => { @@ -81,12 +84,20 @@ pub async fn run( } } -async fn handle_buttonpress(room: &mut Room, button: ButtonPanel) { - match button { - ButtonPanel::BottomLeft(_) => { - room.to_sleep().await; +async fn handle_buttonpress(room: &mut Room, event: RelevantEvent) { + use portable_button_panel::Reading as P; + use ButtonPanel as B; + use RelevantEvent as E; + + match event { + E::Button(B::BottomLeft(_)) => { + room.to_sleep_delayed().await; + } + E::PortableButton(P::Dots1InitialPress) => { + room.to_sleep_immediate().await } - ButtonPanel::BottomMiddle(_) => { + E::Button(B::BottomMiddle(_)) + | E::PortableButton(P::Dots2InitialPress) => { use crate::time; let now = time::now(); match time(now.hour(), now.minute()) { @@ -94,7 +105,7 @@ async fn handle_buttonpress(room: &mut Room, button: ButtonPanel) { _ => room.to_daylight().await, } } - ButtonPanel::BOttomRight(_) => { + E::Button(B::BOttomRight(_)) => { room.to_override().await; } _ => (), diff --git a/crates/brain/src/controller/rooms/small_bedroom/filter.rs b/crates/brain/src/controller/rooms/small_bedroom/filter.rs index 6db943da..be06073f 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/filter.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/filter.rs @@ -2,7 +2,7 @@ use tokio::sync::broadcast::{error::RecvError, Receiver}; use tracing::warn; use crate::controller::Event; -use protocol::{small_bedroom, Reading}; +use protocol::{small_bedroom::{self, portable_button_panel}, Reading}; #[derive(Debug)] pub(super) enum Trigger { @@ -13,6 +13,7 @@ pub(super) enum Trigger { #[derive(Debug)] pub(super) enum RelevantEvent { Button(small_bedroom::ButtonPanel), + PortableButton(portable_button_panel::Reading), Wakeup, } diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index f83d4ba8..e1a90b93 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -41,7 +41,12 @@ impl Room { } } - pub(super) async fn to_sleep(&mut self) { + pub(super) async fn to_sleep_immediate(&mut self) { + self.system.all_lamps_off().await; + self.to_state(State::Sleep).await; + } + + pub(super) async fn to_sleep_delayed(&mut self) { self.to_state_cancel_prev(State::DelayedOff).await; self.system.one_lamp_off("small_bedroom:bureau").await; From f39b21e2f25aef86bba1e5e2051fd6b3c6215b17 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 31 Dec 2024 12:15:14 +0100 Subject: [PATCH 537/687] Fix portablebuttons by adding to filter --- crates/brain/src/controller/rooms/small_bedroom/filter.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom/filter.rs b/crates/brain/src/controller/rooms/small_bedroom/filter.rs index be06073f..b1bfd50c 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/filter.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/filter.rs @@ -2,7 +2,10 @@ use tokio::sync::broadcast::{error::RecvError, Receiver}; use tracing::warn; use crate::controller::Event; -use protocol::{small_bedroom::{self, portable_button_panel}, Reading}; +use protocol::{ + small_bedroom::{self, portable_button_panel}, + Reading, +}; #[derive(Debug)] pub(super) enum Trigger { @@ -39,6 +42,9 @@ fn event_filter(event: Event) -> Option { Event::Sensor(Reading::SmallBedroom( small_bedroom::Reading::ButtonPanel(button), )) => Some(RelevantEvent::Button(button)), + Event::Sensor(Reading::SmallBedroom( + small_bedroom::Reading::PortableButtonPanel(button), + )) => Some(RelevantEvent::PortableButton(button)), Event::WakeupSB => Some(RelevantEvent::Wakeup), _ => None, } From 472c2769634f0cb5bf57d9f196bebd503b4355ef Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 31 Dec 2024 12:47:42 +0100 Subject: [PATCH 538/687] Add SetBy to radiator readings --- .../src/controller/rooms/small_bedroom.rs | 2 +- crates/protocol/src/large_bedroom/radiator.rs | 34 ++++++++++++++++++- crates/protocol/src/small_bedroom/radiator.rs | 34 ++++++++++++++++++- crates/zigbee-bridge/src/parse.rs | 21 ++++++++++++ 4 files changed, 88 insertions(+), 3 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 30be58a7..23769c4d 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -76,7 +76,7 @@ pub async fn run( } Trigger::Event(RelevantEvent::Wakeup) => room.to_wakeup().await, Trigger::ShouldUpdate => { - system.set_radiators_setpoint(goal_temp_now()).await; + // system.set_radiators_setpoint(goal_temp_now()).await; room.all_lights_daylight().await; next_update = Instant::now() + UPDATE_INTERVAL; } diff --git a/crates/protocol/src/large_bedroom/radiator.rs b/crates/protocol/src/large_bedroom/radiator.rs index 4d08127e..b21a2533 100644 --- a/crates/protocol/src/large_bedroom/radiator.rs +++ b/crates/protocol/src/large_bedroom/radiator.rs @@ -26,13 +26,34 @@ use crate::Unit; pub enum Reading { Temperature(f32) = 0, Heating(f32) = 1, + SetBy(Source) = 2, +} + +#[derive( + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, +)] +#[strum_discriminants(derive(Hash))] +#[repr(u8)] +pub enum Source { + Manual, + Schedule, + External, } impl crate::IsSameAs for Reading { fn is_same_as(&self, other: &Self) -> bool { match (self, other) { (Reading::Temperature(_), Reading::Temperature(_)) - | (Reading::Heating(_), Reading::Heating(_)) => true, + | (Reading::Heating(_), Reading::Heating(_)) + | (Reading::SetBy(_), Reading::SetBy(_)) => true, (_, _) => false, } } @@ -65,6 +86,17 @@ impl Tree for Reading { description: "Heating valve", branch_id: self.branch_id(), }, + Reading::SetBy(val) => Info { + val: *val as u8 as f32, + device: crate::Device::LargeBedroom(super::Device::Radiator( + Device, + )), + resolution: 1.0, + range: 0.0..3.0, + unit: Unit::None, + description: "Manual value set", + branch_id: self.branch_id(), + }, }; Item::Leaf(leaf) } diff --git a/crates/protocol/src/small_bedroom/radiator.rs b/crates/protocol/src/small_bedroom/radiator.rs index 583c417a..efb6a0af 100644 --- a/crates/protocol/src/small_bedroom/radiator.rs +++ b/crates/protocol/src/small_bedroom/radiator.rs @@ -26,13 +26,34 @@ use crate::Unit; pub enum Reading { Temperature(f32) = 0, Heating(f32) = 1, + SetBy(Source) = 2, +} + +#[derive( + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, +)] +#[strum_discriminants(derive(Hash))] +#[repr(u8)] +pub enum Source { + Manual, + Schedule, + External, } impl crate::IsSameAs for Reading { fn is_same_as(&self, other: &Self) -> bool { match (self, other) { (Reading::Temperature(_), Reading::Temperature(_)) - | (Reading::Heating(_), Reading::Heating(_)) => true, + | (Reading::Heating(_), Reading::Heating(_)) + | (Reading::SetBy(_), Reading::SetBy(_)) => true, (_, _) => false, } } @@ -65,6 +86,17 @@ impl Tree for Reading { description: "Heating valve", branch_id: self.branch_id(), }, + Reading::SetBy(val) => Info { + val: *val as u8 as f32, + device: crate::Device::SmallBedroom(super::Device::Radiator( + Device, + )), + resolution: 1.0, + range: 0.0..3.0, + unit: Unit::None, + description: "Manual value set", + branch_id: self.branch_id(), + }, }; Item::Leaf(leaf) } diff --git a/crates/zigbee-bridge/src/parse.rs b/crates/zigbee-bridge/src/parse.rs index d63c7818..79a999bd 100644 --- a/crates/zigbee-bridge/src/parse.rs +++ b/crates/zigbee-bridge/src/parse.rs @@ -97,6 +97,27 @@ pub(crate) fn radiator_readings( .map($protocol_module::Reading::Radiator) .map(Reading::$ReadingVariant), ) + .chain( + map.get("setpoint_change_source") + .map(json_to_usize) + .transpose()? + .map(|num| match num { + 0 => Ok($protocol_module::radiator::Source::Manual), + 1 => { + Ok($protocol_module::radiator::Source::Schedule) + } + 2 => { + Ok($protocol_module::radiator::Source::External) + } + _ => Err(color_eyre::eyre::eyre!( + "Unexpected change source {num}" + )), + }) + .transpose()? + .map($protocol_module::radiator::Reading::SetBy) + .map($protocol_module::Reading::Radiator) + .map(Reading::$ReadingVariant), + ) .collect()) }; } From bed8adaa5eca6bcaa981fd569a54803dd04e6197 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 2 Jan 2025 12:12:54 +0100 Subject: [PATCH 539/687] Fix radiator set method parsing --- crates/zigbee-bridge/src/parse.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/crates/zigbee-bridge/src/parse.rs b/crates/zigbee-bridge/src/parse.rs index 79a999bd..9032e0a3 100644 --- a/crates/zigbee-bridge/src/parse.rs +++ b/crates/zigbee-bridge/src/parse.rs @@ -99,18 +99,20 @@ pub(crate) fn radiator_readings( ) .chain( map.get("setpoint_change_source") - .map(json_to_usize) + .map(json_to_str) .transpose()? - .map(|num| match num { - 0 => Ok($protocol_module::radiator::Source::Manual), - 1 => { + .map(|val| match val.to_lowercase().as_str() { + "manual" => { + Ok($protocol_module::radiator::Source::Manual) + } + "schedule" => { Ok($protocol_module::radiator::Source::Schedule) } - 2 => { + "externally" => { Ok($protocol_module::radiator::Source::External) } _ => Err(color_eyre::eyre::eyre!( - "Unexpected change source {num}" + "Unexpected change source {val}" )), }) .transpose()? From 2a285ac9e19c9981604b2aaeae93f9005ef98e9d Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 2 Jan 2025 12:14:14 +0100 Subject: [PATCH 540/687] Add radiator manual override logic and debug --- .../src/controller/rooms/small_bedroom.rs | 17 +++++--- .../controller/rooms/small_bedroom/filter.rs | 15 ++++++- .../controller/rooms/small_bedroom/state.rs | 39 ++++++++++++++++++- crates/radiator-bridge/src/main.rs | 2 +- 4 files changed, 62 insertions(+), 11 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 23769c4d..ef634148 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -9,8 +9,8 @@ use tokio::time::{sleep_until, Instant}; use tracing::trace; use self::filter::{recv_filtered, RelevantEvent, Trigger}; -use self::state::Room; pub(crate) use self::state::State; +use self::state::Room; use crate::controller::{Event, RestrictedSystem}; use crate::input::jobs::Job; use crate::time; @@ -22,6 +22,7 @@ const UPDATE_INTERVAL: Duration = Duration::from_secs(5); const OFF_DELAY: Duration = Duration::from_secs(60); const WAKEUP_EXPIRATION: Duration = Duration::from_secs(60); const NAP_TIME: Duration = Duration::from_secs(30 * 60); +const RADIATOR_OVERRIDE_MINUTES: i32 = 60; const fn time(hour: i8, minute: i8) -> f64 { hour as f64 + minute as f64 / 60. @@ -31,6 +32,7 @@ const T8_00: f64 = time(8, 0); const T8_30: f64 = time(8, 30); const T9_00: f64 = time(9, 0); const T10_30: f64 = time(10, 30); +const T11_00: f64 = time(11, 0); const T13_00: f64 = time(13, 0); const T16_00: f64 = time(16, 0); const T17_00: f64 = time(17, 0); @@ -44,7 +46,7 @@ const T23_00: f64 = time(23, 0); pub async fn run( mut event_rx: broadcast::Receiver, event_tx: broadcast::Sender, - mut system: RestrictedSystem, + system: RestrictedSystem, ) { let mut room = Room::new(event_tx, system.clone()); let mut next_update = Instant::now() + UPDATE_INTERVAL; @@ -74,9 +76,13 @@ pub async fn run( ) => { handle_buttonpress(&mut room, event).await; } + Trigger::Event(RelevantEvent::RadiatorOverride) => { + trace!("Starting radiator override"); + room.start_radiator_override(); + } Trigger::Event(RelevantEvent::Wakeup) => room.to_wakeup().await, Trigger::ShouldUpdate => { - // system.set_radiators_setpoint(goal_temp_now()).await; + room.update_radiator().await; room.all_lights_daylight().await; next_update = Instant::now() + UPDATE_INTERVAL; } @@ -123,9 +129,8 @@ pub(super) fn goal_temp_now() -> f64 { let now = crate::time::now(); match time(now.hour(), now.minute()) { - T8_30..T10_30 => 19.5, - T10_30..T13_00 => 20.0, - T13_00..T21_00 => 21.0, + T8_30..T11_00 => 20.0, + T11_00..T21_00 => 21.0, T21_00..T22_00 => 20.0, T22_00.. | T0_00..T8_30 => 18.5, _ => 18.5, diff --git a/crates/brain/src/controller/rooms/small_bedroom/filter.rs b/crates/brain/src/controller/rooms/small_bedroom/filter.rs index b1bfd50c..3b0c6d37 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/filter.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/filter.rs @@ -1,9 +1,9 @@ use tokio::sync::broadcast::{error::RecvError, Receiver}; -use tracing::warn; +use tracing::{trace, warn}; use crate::controller::Event; use protocol::{ - small_bedroom::{self, portable_button_panel}, + small_bedroom::{self, portable_button_panel, radiator}, Reading, }; @@ -18,6 +18,7 @@ pub(super) enum RelevantEvent { Button(small_bedroom::ButtonPanel), PortableButton(portable_button_panel::Reading), Wakeup, + RadiatorOverride, } pub(super) async fn recv_filtered(event_rx: &mut Receiver) -> Trigger { @@ -45,6 +46,16 @@ fn event_filter(event: Event) -> Option { Event::Sensor(Reading::SmallBedroom( small_bedroom::Reading::PortableButtonPanel(button), )) => Some(RelevantEvent::PortableButton(button)), + Event::Sensor(Reading::SmallBedroom( + small_bedroom::Reading::Radiator(radiator::Reading::SetBy(source)), + )) => { + trace!("SB received radiator setby event"); + if source == radiator::Source::Manual { + Some(RelevantEvent::RadiatorOverride) + } else { + None + } + } Event::WakeupSB => Some(RelevantEvent::Wakeup), _ => None, } diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index e1a90b93..069c586f 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -1,13 +1,17 @@ use std::sync::Arc; use std::time::Duration; +use jiff::{ToSpan, Zoned}; use serde::{Deserialize, Serialize}; use tokio::sync::{broadcast, Mutex, RwLock}; use tokio::task::{self, JoinHandle}; use tokio::time::sleep; -use tracing::warn; +use tracing::{trace, warn}; -use super::{daylight_now, is_nap_time, NAP_TIME, OFF_DELAY}; +use super::{ + daylight_now, goal_temp_now, is_nap_time, NAP_TIME, OFF_DELAY, + RADIATOR_OVERRIDE_MINUTES, +}; use crate::controller::{Event, RestrictedSystem}; #[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)] @@ -23,6 +27,7 @@ pub(crate) enum State { #[derive(Clone)] pub(super) struct Room { state: Arc>, + radiator_override: Option, system: RestrictedSystem, event_tx: broadcast::Sender, task_handle: Arc>>>, @@ -35,12 +40,42 @@ impl Room { ) -> Self { Self { state: Arc::new(RwLock::new(State::Daylight)), + radiator_override: None, system, event_tx, task_handle: Arc::new(Mutex::new(None)), } } + pub(super) async fn update_radiator(&mut self) { + trace!("Updating radiator"); + trace!("Room radiator override state: {:?}", &self.radiator_override); + if let Some(override_time) = &self.radiator_override { + if crate::time::now() + <= override_time + .checked_add(RADIATOR_OVERRIDE_MINUTES.minute()) + .unwrap() + { + trace!("Override is set and not expired, do nothing"); + return; + } else { + warn!("Radiator override is expired, resetting"); + } + } + trace!("Override is either not set or expired, set to goal temp"); + self.system.set_radiators_setpoint(goal_temp_now()).await; + self.radiator_override = None; + } + + pub(crate) fn start_radiator_override(&mut self) { + // Don't set if the radiator resends the manual state + if self.radiator_override.is_none() { + warn!("Setting radiator override to now"); + let now = crate::time::now(); + self.radiator_override = Some(now); + } + } + pub(super) async fn to_sleep_immediate(&mut self) { self.system.all_lamps_off().await; self.to_state(State::Sleep).await; diff --git a/crates/radiator-bridge/src/main.rs b/crates/radiator-bridge/src/main.rs index 66da7d52..f86bd8c6 100644 --- a/crates/radiator-bridge/src/main.rs +++ b/crates/radiator-bridge/src/main.rs @@ -98,7 +98,7 @@ async fn main() { let (reading_tx, mut reading_rx) = tokio::sync::mpsc::channel(1024); let callback = move |reading| { reading_tx - .try_send(reading) + .try_send(dbg!(reading)) .expect("reading_rx should keep up and never drop") }; let controller = Controller::start_bridge_with_reading_callback( From 8095bde1084b4fbdc67cc141e9d33e1452841530 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 2 Jan 2025 12:20:40 +0100 Subject: [PATCH 541/687] remove dbg! in radbridge --- crates/radiator-bridge/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/radiator-bridge/src/main.rs b/crates/radiator-bridge/src/main.rs index f86bd8c6..66da7d52 100644 --- a/crates/radiator-bridge/src/main.rs +++ b/crates/radiator-bridge/src/main.rs @@ -98,7 +98,7 @@ async fn main() { let (reading_tx, mut reading_rx) = tokio::sync::mpsc::channel(1024); let callback = move |reading| { reading_tx - .try_send(dbg!(reading)) + .try_send(reading) .expect("reading_rx should keep up and never drop") }; let controller = Controller::start_bridge_with_reading_callback( From eb862e889a1c78d6f2b45e774a0bf4c0d8647f54 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 2 Jan 2025 15:28:49 +0100 Subject: [PATCH 542/687] fix missing affected_readings entry + improve error --- crates/data-store/src/main.rs | 1 + crates/data-store/src/server/db/series.rs | 36 +++++++++++++++---- crates/protocol/src/large_bedroom/radiator.rs | 2 +- crates/protocol/src/small_bedroom/radiator.rs | 2 +- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/crates/data-store/src/main.rs b/crates/data-store/src/main.rs index b0aaa5bf..e533a148 100644 --- a/crates/data-store/src/main.rs +++ b/crates/data-store/src/main.rs @@ -23,6 +23,7 @@ struct Cli { #[tokio::main] async fn main() -> Result<()> { logger::tracing::setup(); + color_eyre::install().unwrap(); let cli = Cli::parse(); tracing::info!("started data-server, args: {cli:?}"); diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index ae76f97a..dbe035a2 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf}; use std::time::{Duration, Instant}; use byteseries::{downsample, series, ByteSeries}; -use color_eyre::eyre::{eyre, WrapErr}; +use color_eyre::eyre::{eyre, OptionExt, WrapErr}; use color_eyre::{Result, Section}; use protocol::reading::tree::{Item, Tree}; use protocol::{reading, IsSameAs}; @@ -116,17 +116,14 @@ impl Series { #[instrument(skip(self))] fn append(&mut self, reading: &protocol::Reading) -> Result<()> { - let index = reading + let res = reading .device() .info() .affects_readings .iter() .map(|r| r.leaf().branch_id) - .position(|id_in_list| id_in_list == reading.leaf().branch_id) - .expect( - "reading.device.affected_readings() is a list that contains \ - reading.branch_id()", - ); + .position(|id_in_list| id_in_list == reading.leaf().branch_id); + let index = wrap_inder_err(res, reading)?; let meta = &mut self.meta_list[index]; if !reading.leaf().range.contains(&reading.leaf().val) { @@ -251,6 +248,31 @@ impl Series { } } +fn wrap_inder_err( + res: Option, + reading: &protocol::Reading, +) -> Result { + res.ok_or_eyre( + "Could not find reading index, branch id does not match + any in readings affected by the device", + ) + .suggestion("In protocol lib, is every reading variant in the affected readings list?") + .with_note(|| format!("reading: {reading:?}")) + .with_note(|| format!("reading branch id: {:?}", reading.leaf().branch_id)) + .with_note(|| { + format!( + "affected readings: {:?}", + reading + .device() + .info() + .affects_readings + .into_iter() + .map(|r| r.leaf()) + .collect::>() + ) + }) +} + fn meta_list_and_payload_size( readings: &[protocol::Reading], fields: &[bitspec::Field], diff --git a/crates/protocol/src/large_bedroom/radiator.rs b/crates/protocol/src/large_bedroom/radiator.rs index b21a2533..b7fe22f8 100644 --- a/crates/protocol/src/large_bedroom/radiator.rs +++ b/crates/protocol/src/large_bedroom/radiator.rs @@ -141,7 +141,7 @@ impl Device { pub const fn info(&self) -> crate::DeviceInfo { crate::DeviceInfo { name: "Radiator", - affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Heating(0.0)], + affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Heating(0.0), Reading::SetBy(Source::Manual)], temporal_resolution: Duration::from_secs(5), // unknown min_sample_interval: Duration::from_secs(5), // unknown max_sample_interval: Duration::MAX, diff --git a/crates/protocol/src/small_bedroom/radiator.rs b/crates/protocol/src/small_bedroom/radiator.rs index efb6a0af..37fa5bef 100644 --- a/crates/protocol/src/small_bedroom/radiator.rs +++ b/crates/protocol/src/small_bedroom/radiator.rs @@ -141,7 +141,7 @@ impl Device { pub const fn info(&self) -> crate::DeviceInfo { crate::DeviceInfo { name: "Radiator", - affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Heating(0.0)], + affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Heating(0.0), Reading::SetBy(Source::Manual)], temporal_resolution: Duration::from_secs(5), // unknown min_sample_interval: Duration::from_secs(5), // unknown max_sample_interval: Duration::MAX, From 432f26cc6714119a78bbae961215778e3e1b0fcf Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 4 Jan 2025 11:57:47 +0100 Subject: [PATCH 543/687] Tweak SB radiator values --- crates/brain/src/controller/rooms/small_bedroom.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index ef634148..5964b5d2 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -129,11 +129,12 @@ pub(super) fn goal_temp_now() -> f64 { let now = crate::time::now(); match time(now.hour(), now.minute()) { - T8_30..T11_00 => 20.0, - T11_00..T21_00 => 21.0, + T8_30..T11_00 => 19.0, + T11_00..T13_00 => 20.0, + T13_00..T21_00 => 21.0, T21_00..T22_00 => 20.0, - T22_00.. | T0_00..T8_30 => 18.5, - _ => 18.5, + T22_00.. | T0_00..T8_30 => 18.0, + _ => 18.0, } } From 1fa900420fa08412035a22a9981ab546a8880d16 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 2 Jan 2025 16:38:34 +0100 Subject: [PATCH 544/687] adds watchdog to bed-lb + flush network might solve issue where we get DEBUG failed to transmit IP: device exhausted https://github.com/embassy-rs/embassy/issues/3112 --- sensor-nodes/Cargo.toml | 1 - sensor-nodes/bed-lb/src/main.rs | 19 +++++++++++++------ sensor-nodes/bed-lb/src/network.rs | 6 ++++++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/sensor-nodes/Cargo.toml b/sensor-nodes/Cargo.toml index 2e8d333f..c9f7668d 100644 --- a/sensor-nodes/Cargo.toml +++ b/sensor-nodes/Cargo.toml @@ -40,7 +40,6 @@ embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "a4 embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } -# embassy-time-queue-driver = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } [workspace.package] diff --git a/sensor-nodes/bed-lb/src/main.rs b/sensor-nodes/bed-lb/src/main.rs index 9a5098ad..cd50afd7 100644 --- a/sensor-nodes/bed-lb/src/main.rs +++ b/sensor-nodes/bed-lb/src/main.rs @@ -2,7 +2,7 @@ #![no_main] use embassy_executor::Spawner; -use embassy_futures::select::{self, Either3}; +use embassy_futures::select::{self, Either4}; use embassy_net::{Ipv4Address, Ipv4Cidr, StackResources}; use embassy_net_wiznet::{chip::W5500, Device, Runner, State}; use embassy_stm32::exti::ExtiInput; @@ -96,6 +96,10 @@ fn config() -> Config { #[embassy_executor::main] async fn main(spawner: Spawner) { let p = embassy_stm32::init(config()); + let mut dog = IndependentWatchdog::new( + p.IWDG, 10_000_000, // microseconds + ); + dog.unleash(); let seed = rng::generate_seed_blocking(p.ADC1).await; defmt::info!("random seed: {}", seed); @@ -187,7 +191,7 @@ async fn main(spawner: Spawner) { let spi = unwrap!(ExclusiveDevice::new(spi, cs, Delay)); let w5500_int = ExtiInput::new(p.PB0, p.EXTI0, Pull::Up); - let w5500_reset = Output::new(p.PB1, Level::High, Speed::VeryHigh); + let w5500_reset = Output::new(p.PB1, Level::High, Speed::Medium); let mac_addr = [0x02, 234, 3, 4, 82, 231]; static STATE: StaticCell> = StaticCell::new(); @@ -238,17 +242,21 @@ async fn main(spawner: Spawner) { buttons, ); - let res = select::select3( + let res = select::select4( &mut handle_network, init_then_measure, led_controller.control(), + keep_dog_happy(dog), ) .await; let unrecoverable_err = match res { - Either3::First(()) | Either3::Third(()) | Either3::Second(Ok(())) => { + Either4::First(()) + | Either4::Third(()) + | Either4::Fourth(()) + | Either4::Second(Ok(())) => { defmt::unreachable!() } - Either3::Second(Err(err)) => err, + Either4::Second(Err(err)) => err, }; // at this point no other errors have occurred @@ -259,7 +267,6 @@ async fn main(spawner: Spawner) { async fn keep_dog_happy(mut dog: IndependentWatchdog<'_, IWDG>) { loop { - dog.unleash(); Timer::after_secs(8).await; trace!("petting dog"); dog.pet(); diff --git a/sensor-nodes/bed-lb/src/network.rs b/sensor-nodes/bed-lb/src/network.rs index 3edaa996..5e3e5b92 100644 --- a/sensor-nodes/bed-lb/src/network.rs +++ b/sensor-nodes/bed-lb/src/network.rs @@ -165,12 +165,18 @@ async fn send_messages( if let Err(e) = tcp.write_all(to_send).await { return e; } + if let Err(e) = tcp.flush().await { + return e; + } loop { let to_send = get_messages(publish, &mut buf).await; if let Err(e) = tcp.write_all(to_send).await { return e; } + if let Err(e) = tcp.flush().await { + return e; + } } } From 718da7511849344300bdbcf185fa4c8a88ef247b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 11 Jan 2025 00:23:34 +0100 Subject: [PATCH 545/687] reset node on repeated conn loss --- sensor-nodes/bed-lb/src/network.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sensor-nodes/bed-lb/src/network.rs b/sensor-nodes/bed-lb/src/network.rs index 5e3e5b92..f3d42769 100644 --- a/sensor-nodes/bed-lb/src/network.rs +++ b/sensor-nodes/bed-lb/src/network.rs @@ -88,15 +88,26 @@ pub async fn handle( let host_addr = Ipv4Address::new(192, 168, 1, 43); let host_port = 1234; + let mut sequential_errors = 0; + debug!("Configured socket and connecting"); loop { debug!("socket state: {:?}", socket.state()); if let Err(e) = socket.connect((host_addr, host_port)).await { + if sequential_errors > 3 { + defmt::info!("failing to reconnect, resetting node"); + defmt::flush(); + Timer::after_secs(1).await; + cortex_m::peripheral::SCB::sys_reset(); + } warn!("connect error: {}", e); + sequential_errors += 1; Timer::after_secs(5).await; continue; } + info!("(re-)connected"); + sequential_errors = 0; // Prevent out-dated data from being send publish.clear().await; @@ -213,7 +224,6 @@ async fn receive_orders( read = remaining; - #[allow(irrefutable_let_patterns)] // Will change in the future let Affector::LargeBedroom(large_bedroom::Affector::Bed(affector)) = item else { From feb275206b601031509f06ec407f9eae65cc5594 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 11 Jan 2025 00:29:38 +0100 Subject: [PATCH 546/687] add radiator Setpoint to reading --- crates/protocol/src/large_bedroom/radiator.rs | 15 ++++++++++++++- crates/protocol/src/small_bedroom/radiator.rs | 15 ++++++++++++++- crates/zigbee-bridge/src/parse.rs | 8 ++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/crates/protocol/src/large_bedroom/radiator.rs b/crates/protocol/src/large_bedroom/radiator.rs index b7fe22f8..d391469c 100644 --- a/crates/protocol/src/large_bedroom/radiator.rs +++ b/crates/protocol/src/large_bedroom/radiator.rs @@ -27,6 +27,7 @@ pub enum Reading { Temperature(f32) = 0, Heating(f32) = 1, SetBy(Source) = 2, + Setpoint(f32) = 3, } #[derive( @@ -54,6 +55,7 @@ impl crate::IsSameAs for Reading { (Reading::Temperature(_), Reading::Temperature(_)) | (Reading::Heating(_), Reading::Heating(_)) | (Reading::SetBy(_), Reading::SetBy(_)) => true, + (Reading::Setpoint(_), Reading::Setpoint(_)) => true, (_, _) => false, } } @@ -97,6 +99,17 @@ impl Tree for Reading { description: "Manual value set", branch_id: self.branch_id(), }, + Reading::Setpoint(val) => Info { + val: *val, + device: crate::Device::LargeBedroom(super::Device::Radiator( + Device, + )), + resolution: 0.5, + range: 0.0..30.0, + unit: Unit::C, + description: "Set point", + branch_id: self.branch_id(), + }, }; Item::Leaf(leaf) } @@ -141,7 +154,7 @@ impl Device { pub const fn info(&self) -> crate::DeviceInfo { crate::DeviceInfo { name: "Radiator", - affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Heating(0.0), Reading::SetBy(Source::Manual)], + affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Heating(0.0), Reading::SetBy(Source::Manual), Reading::Setpoint(0.0)], temporal_resolution: Duration::from_secs(5), // unknown min_sample_interval: Duration::from_secs(5), // unknown max_sample_interval: Duration::MAX, diff --git a/crates/protocol/src/small_bedroom/radiator.rs b/crates/protocol/src/small_bedroom/radiator.rs index 37fa5bef..365fde12 100644 --- a/crates/protocol/src/small_bedroom/radiator.rs +++ b/crates/protocol/src/small_bedroom/radiator.rs @@ -27,6 +27,7 @@ pub enum Reading { Temperature(f32) = 0, Heating(f32) = 1, SetBy(Source) = 2, + Setpoint(f32) = 3, } #[derive( @@ -54,6 +55,7 @@ impl crate::IsSameAs for Reading { (Reading::Temperature(_), Reading::Temperature(_)) | (Reading::Heating(_), Reading::Heating(_)) | (Reading::SetBy(_), Reading::SetBy(_)) => true, + (Reading::Setpoint(_), Reading::Setpoint(_)) => true, (_, _) => false, } } @@ -97,6 +99,17 @@ impl Tree for Reading { description: "Manual value set", branch_id: self.branch_id(), }, + Reading::Setpoint(val) => Info { + val: *val, + device: crate::Device::SmallBedroom(super::Device::Radiator( + Device, + )), + resolution: 0.5, + range: 0.0..30.0, + unit: Unit::C, + description: "Set point", + branch_id: self.branch_id(), + }, }; Item::Leaf(leaf) } @@ -141,7 +154,7 @@ impl Device { pub const fn info(&self) -> crate::DeviceInfo { crate::DeviceInfo { name: "Radiator", - affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Heating(0.0), Reading::SetBy(Source::Manual)], + affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Heating(0.0), Reading::SetBy(Source::Manual), Reading::Setpoint(0.0)], temporal_resolution: Duration::from_secs(5), // unknown min_sample_interval: Duration::from_secs(5), // unknown max_sample_interval: Duration::MAX, diff --git a/crates/zigbee-bridge/src/parse.rs b/crates/zigbee-bridge/src/parse.rs index 9032e0a3..1572c740 100644 --- a/crates/zigbee-bridge/src/parse.rs +++ b/crates/zigbee-bridge/src/parse.rs @@ -120,6 +120,14 @@ pub(crate) fn radiator_readings( .map($protocol_module::Reading::Radiator) .map(Reading::$ReadingVariant), ) + .chain( + map.get("occupied_heating_setpoint") + .map(json_to_f32) + .transpose()? + .map($protocol_module::radiator::Reading::Setpoint) + .map($protocol_module::Reading::Radiator) + .map(Reading::$ReadingVariant), + ) .collect()) }; } From df6c8ff0c16bdc9d1ab57bf08f58bfaebfdf4469 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 11 Jan 2025 14:12:17 +0100 Subject: [PATCH 547/687] rename sensor-tui -> ui --- crates/{sensor-tui => ui}/.gitignore | 0 crates/{sensor-tui => ui}/Cargo.lock | 0 crates/{sensor-tui => ui}/Cargo.toml | 2 +- .../{sensor-tui => ui}/examples/chart_gaps.rs | 0 crates/{sensor-tui => ui}/src/control.rs | 0 crates/{sensor-tui => ui}/src/fetch.rs | 0 crates/{sensor-tui => ui}/src/lib.rs | 0 crates/{sensor-tui => ui}/src/main.rs | 19 ++++++++----------- crates/{sensor-tui => ui}/src/populate.rs | 0 crates/{sensor-tui => ui}/src/receive.rs | 0 crates/{sensor-tui => ui}/src/time.rs | 0 crates/{sensor-tui => ui}/src/time/format.rs | 0 .../format/progressively_more_specified.rs | 0 crates/{sensor-tui => ui}/src/time/parse.rs | 0 crates/{sensor-tui => ui}/src/tui.rs | 0 .../{sensor-tui => ui}/src/tui/affectors.rs | 0 .../src/tui/affectors/handle_key.rs | 0 .../src/tui/affectors/render.rs | 0 crates/{sensor-tui => ui}/src/tui/readings.rs | 0 .../src/tui/readings/handle_key.rs | 0 .../src/tui/readings/plot_range.rs | 0 .../src/tui/readings/render.rs | 0 .../src/tui/readings/render/chart.rs | 0 .../src/tui/readings/render/chart/cursor.rs | 0 .../src/tui/readings/render/chart/labels.rs | 0 .../src/tui/readings/render/chart/split.rs | 0 .../src/tui/readings/render/logs.rs | 0 .../src/tui/readings/render/time.rs | 0 .../src/tui/readings/render/tree.rs | 0 .../src/tui/readings/sensor_info.rs | 0 .../src/tui/readings/sensor_info/logs.rs | 0 crates/{sensor-tui => ui}/src/tui/render.rs | 0 crates/{sensor-tui => ui}/src/tui/reports.rs | 0 33 files changed, 9 insertions(+), 12 deletions(-) rename crates/{sensor-tui => ui}/.gitignore (100%) rename crates/{sensor-tui => ui}/Cargo.lock (100%) rename crates/{sensor-tui => ui}/Cargo.toml (97%) rename crates/{sensor-tui => ui}/examples/chart_gaps.rs (100%) rename crates/{sensor-tui => ui}/src/control.rs (100%) rename crates/{sensor-tui => ui}/src/fetch.rs (100%) rename crates/{sensor-tui => ui}/src/lib.rs (100%) rename crates/{sensor-tui => ui}/src/main.rs (89%) rename crates/{sensor-tui => ui}/src/populate.rs (100%) rename crates/{sensor-tui => ui}/src/receive.rs (100%) rename crates/{sensor-tui => ui}/src/time.rs (100%) rename crates/{sensor-tui => ui}/src/time/format.rs (100%) rename crates/{sensor-tui => ui}/src/time/format/progressively_more_specified.rs (100%) rename crates/{sensor-tui => ui}/src/time/parse.rs (100%) rename crates/{sensor-tui => ui}/src/tui.rs (100%) rename crates/{sensor-tui => ui}/src/tui/affectors.rs (100%) rename crates/{sensor-tui => ui}/src/tui/affectors/handle_key.rs (100%) rename crates/{sensor-tui => ui}/src/tui/affectors/render.rs (100%) rename crates/{sensor-tui => ui}/src/tui/readings.rs (100%) rename crates/{sensor-tui => ui}/src/tui/readings/handle_key.rs (100%) rename crates/{sensor-tui => ui}/src/tui/readings/plot_range.rs (100%) rename crates/{sensor-tui => ui}/src/tui/readings/render.rs (100%) rename crates/{sensor-tui => ui}/src/tui/readings/render/chart.rs (100%) rename crates/{sensor-tui => ui}/src/tui/readings/render/chart/cursor.rs (100%) rename crates/{sensor-tui => ui}/src/tui/readings/render/chart/labels.rs (100%) rename crates/{sensor-tui => ui}/src/tui/readings/render/chart/split.rs (100%) rename crates/{sensor-tui => ui}/src/tui/readings/render/logs.rs (100%) rename crates/{sensor-tui => ui}/src/tui/readings/render/time.rs (100%) rename crates/{sensor-tui => ui}/src/tui/readings/render/tree.rs (100%) rename crates/{sensor-tui => ui}/src/tui/readings/sensor_info.rs (100%) rename crates/{sensor-tui => ui}/src/tui/readings/sensor_info/logs.rs (100%) rename crates/{sensor-tui => ui}/src/tui/render.rs (100%) rename crates/{sensor-tui => ui}/src/tui/reports.rs (100%) diff --git a/crates/sensor-tui/.gitignore b/crates/ui/.gitignore similarity index 100% rename from crates/sensor-tui/.gitignore rename to crates/ui/.gitignore diff --git a/crates/sensor-tui/Cargo.lock b/crates/ui/Cargo.lock similarity index 100% rename from crates/sensor-tui/Cargo.lock rename to crates/ui/Cargo.lock diff --git a/crates/sensor-tui/Cargo.toml b/crates/ui/Cargo.toml similarity index 97% rename from crates/sensor-tui/Cargo.toml rename to crates/ui/Cargo.toml index e0e1e646..4a3c54c9 100644 --- a/crates/sensor-tui/Cargo.toml +++ b/crates/ui/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "sensor-tui" +name = "ui" edition.workspace = true license.workspace = true authors.workspace = true diff --git a/crates/sensor-tui/examples/chart_gaps.rs b/crates/ui/examples/chart_gaps.rs similarity index 100% rename from crates/sensor-tui/examples/chart_gaps.rs rename to crates/ui/examples/chart_gaps.rs diff --git a/crates/sensor-tui/src/control.rs b/crates/ui/src/control.rs similarity index 100% rename from crates/sensor-tui/src/control.rs rename to crates/ui/src/control.rs diff --git a/crates/sensor-tui/src/fetch.rs b/crates/ui/src/fetch.rs similarity index 100% rename from crates/sensor-tui/src/fetch.rs rename to crates/ui/src/fetch.rs diff --git a/crates/sensor-tui/src/lib.rs b/crates/ui/src/lib.rs similarity index 100% rename from crates/sensor-tui/src/lib.rs rename to crates/ui/src/lib.rs diff --git a/crates/sensor-tui/src/main.rs b/crates/ui/src/main.rs similarity index 89% rename from crates/sensor-tui/src/main.rs rename to crates/ui/src/main.rs index 4ba7cfee..979d70cd 100644 --- a/crates/sensor-tui/src/main.rs +++ b/crates/ui/src/main.rs @@ -4,18 +4,16 @@ use std::thread; use clap::Parser; use color_eyre::Result; -use sensor_tui::control; -use sensor_tui::UserIntent; use tokio::task; +use ui::control; +use ui::UserIntent; -use sensor_tui::Fetch; -use sensor_tui::tui; -use sensor_tui::receive; -use sensor_tui::populate; - +use ui::populate; +use ui::receive; +use ui::Fetch; #[derive(Parser)] -#[command(name = "sensor tui")] +#[command(name = "home automation UI")] #[command(version = "1.0")] #[command(about = "View sensor values")] struct Cli { @@ -51,7 +49,7 @@ async fn main() -> Result<()> { let tx1_clone1 = tx1.clone(); let tx1_clone2 = tx1.clone(); - thread::spawn(move || tui::run(rx1, tx2, tx3, fetcher)); + thread::spawn(move || ui::tui::run(rx1, tx2, tx3, fetcher)); task::spawn(receive::receive_data(data_server, tx1_clone1)); task::spawn(populate::tree( data_server, @@ -65,9 +63,8 @@ async fn main() -> Result<()> { Ok(()) } - /// Similar to the `std::dbg!` macro, but generates `tracing` events rather -/// than printing to stdout. +/// than printing to standard output. /// /// By default, the verbosity level for the generated events is `DEBUG`, but /// this can be customized. diff --git a/crates/sensor-tui/src/populate.rs b/crates/ui/src/populate.rs similarity index 100% rename from crates/sensor-tui/src/populate.rs rename to crates/ui/src/populate.rs diff --git a/crates/sensor-tui/src/receive.rs b/crates/ui/src/receive.rs similarity index 100% rename from crates/sensor-tui/src/receive.rs rename to crates/ui/src/receive.rs diff --git a/crates/sensor-tui/src/time.rs b/crates/ui/src/time.rs similarity index 100% rename from crates/sensor-tui/src/time.rs rename to crates/ui/src/time.rs diff --git a/crates/sensor-tui/src/time/format.rs b/crates/ui/src/time/format.rs similarity index 100% rename from crates/sensor-tui/src/time/format.rs rename to crates/ui/src/time/format.rs diff --git a/crates/sensor-tui/src/time/format/progressively_more_specified.rs b/crates/ui/src/time/format/progressively_more_specified.rs similarity index 100% rename from crates/sensor-tui/src/time/format/progressively_more_specified.rs rename to crates/ui/src/time/format/progressively_more_specified.rs diff --git a/crates/sensor-tui/src/time/parse.rs b/crates/ui/src/time/parse.rs similarity index 100% rename from crates/sensor-tui/src/time/parse.rs rename to crates/ui/src/time/parse.rs diff --git a/crates/sensor-tui/src/tui.rs b/crates/ui/src/tui.rs similarity index 100% rename from crates/sensor-tui/src/tui.rs rename to crates/ui/src/tui.rs diff --git a/crates/sensor-tui/src/tui/affectors.rs b/crates/ui/src/tui/affectors.rs similarity index 100% rename from crates/sensor-tui/src/tui/affectors.rs rename to crates/ui/src/tui/affectors.rs diff --git a/crates/sensor-tui/src/tui/affectors/handle_key.rs b/crates/ui/src/tui/affectors/handle_key.rs similarity index 100% rename from crates/sensor-tui/src/tui/affectors/handle_key.rs rename to crates/ui/src/tui/affectors/handle_key.rs diff --git a/crates/sensor-tui/src/tui/affectors/render.rs b/crates/ui/src/tui/affectors/render.rs similarity index 100% rename from crates/sensor-tui/src/tui/affectors/render.rs rename to crates/ui/src/tui/affectors/render.rs diff --git a/crates/sensor-tui/src/tui/readings.rs b/crates/ui/src/tui/readings.rs similarity index 100% rename from crates/sensor-tui/src/tui/readings.rs rename to crates/ui/src/tui/readings.rs diff --git a/crates/sensor-tui/src/tui/readings/handle_key.rs b/crates/ui/src/tui/readings/handle_key.rs similarity index 100% rename from crates/sensor-tui/src/tui/readings/handle_key.rs rename to crates/ui/src/tui/readings/handle_key.rs diff --git a/crates/sensor-tui/src/tui/readings/plot_range.rs b/crates/ui/src/tui/readings/plot_range.rs similarity index 100% rename from crates/sensor-tui/src/tui/readings/plot_range.rs rename to crates/ui/src/tui/readings/plot_range.rs diff --git a/crates/sensor-tui/src/tui/readings/render.rs b/crates/ui/src/tui/readings/render.rs similarity index 100% rename from crates/sensor-tui/src/tui/readings/render.rs rename to crates/ui/src/tui/readings/render.rs diff --git a/crates/sensor-tui/src/tui/readings/render/chart.rs b/crates/ui/src/tui/readings/render/chart.rs similarity index 100% rename from crates/sensor-tui/src/tui/readings/render/chart.rs rename to crates/ui/src/tui/readings/render/chart.rs diff --git a/crates/sensor-tui/src/tui/readings/render/chart/cursor.rs b/crates/ui/src/tui/readings/render/chart/cursor.rs similarity index 100% rename from crates/sensor-tui/src/tui/readings/render/chart/cursor.rs rename to crates/ui/src/tui/readings/render/chart/cursor.rs diff --git a/crates/sensor-tui/src/tui/readings/render/chart/labels.rs b/crates/ui/src/tui/readings/render/chart/labels.rs similarity index 100% rename from crates/sensor-tui/src/tui/readings/render/chart/labels.rs rename to crates/ui/src/tui/readings/render/chart/labels.rs diff --git a/crates/sensor-tui/src/tui/readings/render/chart/split.rs b/crates/ui/src/tui/readings/render/chart/split.rs similarity index 100% rename from crates/sensor-tui/src/tui/readings/render/chart/split.rs rename to crates/ui/src/tui/readings/render/chart/split.rs diff --git a/crates/sensor-tui/src/tui/readings/render/logs.rs b/crates/ui/src/tui/readings/render/logs.rs similarity index 100% rename from crates/sensor-tui/src/tui/readings/render/logs.rs rename to crates/ui/src/tui/readings/render/logs.rs diff --git a/crates/sensor-tui/src/tui/readings/render/time.rs b/crates/ui/src/tui/readings/render/time.rs similarity index 100% rename from crates/sensor-tui/src/tui/readings/render/time.rs rename to crates/ui/src/tui/readings/render/time.rs diff --git a/crates/sensor-tui/src/tui/readings/render/tree.rs b/crates/ui/src/tui/readings/render/tree.rs similarity index 100% rename from crates/sensor-tui/src/tui/readings/render/tree.rs rename to crates/ui/src/tui/readings/render/tree.rs diff --git a/crates/sensor-tui/src/tui/readings/sensor_info.rs b/crates/ui/src/tui/readings/sensor_info.rs similarity index 100% rename from crates/sensor-tui/src/tui/readings/sensor_info.rs rename to crates/ui/src/tui/readings/sensor_info.rs diff --git a/crates/sensor-tui/src/tui/readings/sensor_info/logs.rs b/crates/ui/src/tui/readings/sensor_info/logs.rs similarity index 100% rename from crates/sensor-tui/src/tui/readings/sensor_info/logs.rs rename to crates/ui/src/tui/readings/sensor_info/logs.rs diff --git a/crates/sensor-tui/src/tui/render.rs b/crates/ui/src/tui/render.rs similarity index 100% rename from crates/sensor-tui/src/tui/render.rs rename to crates/ui/src/tui/render.rs diff --git a/crates/sensor-tui/src/tui/reports.rs b/crates/ui/src/tui/reports.rs similarity index 100% rename from crates/sensor-tui/src/tui/reports.rs rename to crates/ui/src/tui/reports.rs From 4ad9cc04ea818b72436110c8d049b0625a689f7a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 11 Jan 2025 14:19:02 +0100 Subject: [PATCH 548/687] tests compile again --- crates/ui/examples/chart_gaps.rs | 6 +++--- crates/zigbee-bridge/Cargo.toml | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/ui/examples/chart_gaps.rs b/crates/ui/examples/chart_gaps.rs index d8c747fa..7480964f 100644 --- a/crates/ui/examples/chart_gaps.rs +++ b/crates/ui/examples/chart_gaps.rs @@ -6,9 +6,9 @@ use crossterm::terminal::{ use crossterm::{event, ExecutableCommand}; use ratatui::backend::CrosstermBackend; use ratatui::{Frame, Terminal}; -use sensor_tui::tui::readings::render::chart; -use sensor_tui::tui::readings::sensor_info::ChartParts; -use sensor_tui::tui::readings::UiState; +use ui::tui::readings::render::chart; +use ui::tui::readings::sensor_info::ChartParts; +use ui::tui::readings::UiState; fn data_with_gap(buffer: &mut Vec<(f64, f64)>) -> ChartParts<'_> { buffer.extend((0..10).into_iter().map(|i| (i as f64, 2.0))); diff --git a/crates/zigbee-bridge/Cargo.toml b/crates/zigbee-bridge/Cargo.toml index 7000fe07..d85ae71e 100644 --- a/crates/zigbee-bridge/Cargo.toml +++ b/crates/zigbee-bridge/Cargo.toml @@ -20,3 +20,6 @@ strum = { version = "0.26.3", features = ["derive"] } color-eyre.workspace = true regex = "1.11.1" rand = "0.8.5" + +[dev-dependencies] +logger.workspace = true From d37b4ced42d495556500d821d5eb400de594b206 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 11 Jan 2025 14:24:01 +0100 Subject: [PATCH 549/687] fixes tests --- crates/data-server/tests/source_api.rs | 2 +- crates/data-store/src/server/db/series.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/data-server/tests/source_api.rs b/crates/data-server/tests/source_api.rs index eaf871e4..d53d98cc 100644 --- a/crates/data-server/tests/source_api.rs +++ b/crates/data-server/tests/source_api.rs @@ -45,7 +45,7 @@ async fn run_server( } async fn send_sensor_value(data_port: u16) -> Result { - tokio::time::sleep(Duration::from_millis(500)).await; + tokio::time::sleep(Duration::from_millis(400)).await; let mut list = protocol::affector::ListMessage::<50>::empty(); list.values diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/server/db/series.rs index dbe035a2..3079efa8 100644 --- a/crates/data-store/src/server/db/series.rs +++ b/crates/data-store/src/server/db/series.rs @@ -410,6 +410,7 @@ mod test { use protocol::{large_bedroom, Reading}; #[test] + #[should_panic(expected = "min sample interval may not be zero")] fn millis_to_minimal_representation_factor_is_not_zero() { let info = protocol::DeviceInfo { name: "test", From ae00ea1d941cf36b1f13d179e754010b1eeb9775 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 11 Jan 2025 14:41:59 +0100 Subject: [PATCH 550/687] update ui deps --- crates/ui/Cargo.toml | 6 +++--- crates/ui/src/tui/readings/render/logs.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/ui/Cargo.toml b/crates/ui/Cargo.toml index 4a3c54c9..c255e72e 100644 --- a/crates/ui/Cargo.toml +++ b/crates/ui/Cargo.toml @@ -10,8 +10,8 @@ authors.workspace = true color-eyre = { workspace = true } crossterm = "0.28" hdrhistogram = "7.5" -ratatui = "0.28" -tui-tree-widget = { version = "0.22.0", git = "https://github.com/dvdsk/tui-rs-tree-widget" } +ratatui = "0.29" +tui-tree-widget = { version = "0.23.0", git = "https://github.com/dvdsk/tui-rs-tree-widget" } clap = { workspace = true } tokio = { workspace = true, features = ["macros"] } @@ -26,7 +26,7 @@ data-store = { workspace = true } log-store = { workspace = true, features = ["api"] } jiff = { workspace = true } thiserror.workspace = true -itertools = "0.13.0" +itertools = "0.14.0" gethostname = "0.5.0" strip-ansi-escapes = "0.2.0" indextree = "4.7.2" diff --git a/crates/ui/src/tui/readings/render/logs.rs b/crates/ui/src/tui/readings/render/logs.rs index a8ff1f60..0b7fcc86 100644 --- a/crates/ui/src/tui/readings/render/logs.rs +++ b/crates/ui/src/tui/readings/render/logs.rs @@ -154,7 +154,7 @@ pub fn render_table( .header(header) .flex(Flex::SpaceAround) .column_spacing(1) - .highlight_style(selected_style) + .row_highlight_style(selected_style) .highlight_symbol(Text::from(vec![ "".into(), bar.into(), From 4a68b3a59bc204a6e8ecad945d23ca9da9493853 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 11 Jan 2025 20:13:33 +0100 Subject: [PATCH 551/687] implements label formatter for radiator and buttons + refactor protocol --- .../controller/rooms/small_bedroom/filter.rs | 2 +- crates/protocol/src/affector.rs | 27 ++++--- crates/protocol/src/button.rs | 25 ++++++- crates/protocol/src/device.rs | 13 +++- crates/protocol/src/large_bedroom.rs | 14 +++- crates/protocol/src/large_bedroom/bed.rs | 73 ++++++++++--------- crates/protocol/src/large_bedroom/desk.rs | 58 ++++++++++----- crates/protocol/src/large_bedroom/radiator.rs | 47 ++++-------- crates/protocol/src/lib.rs | 3 +- crates/protocol/src/msg.rs | 5 +- crates/protocol/src/msg/error.rs | 3 +- crates/protocol/src/msg/sensor.rs | 6 +- crates/protocol/src/reading.rs | 28 +++++++ crates/protocol/src/reading/tree.rs | 1 - crates/protocol/src/small_bedroom/bed.rs | 36 +++------ crates/protocol/src/small_bedroom/desk.rs | 55 +++++++++----- .../small_bedroom/portable_button_panel.rs | 3 + crates/protocol/src/small_bedroom/radiator.rs | 47 ++++-------- crates/protocol/src/usb.rs | 1 - crates/ui/examples/chart_gaps.rs | 21 ++++-- .../ui/src/tui/readings/render/chart/split.rs | 13 +++- crates/zigbee-bridge/src/parse.rs | 6 +- 22 files changed, 286 insertions(+), 201 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom/filter.rs b/crates/brain/src/controller/rooms/small_bedroom/filter.rs index 3b0c6d37..09e43531 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/filter.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/filter.rs @@ -50,7 +50,7 @@ fn event_filter(event: Event) -> Option { small_bedroom::Reading::Radiator(radiator::Reading::SetBy(source)), )) => { trace!("SB received radiator setby event"); - if source == radiator::Source::Manual { + if source == protocol::shared::radiator::Source::Manual { Some(RelevantEvent::RadiatorOverride) } else { None diff --git a/crates/protocol/src/affector.rs b/crates/protocol/src/affector.rs index f09c2844..5ffdac7d 100644 --- a/crates/protocol/src/affector.rs +++ b/crates/protocol/src/affector.rs @@ -59,8 +59,8 @@ pub struct Control<'a> { } impl Affector { - pub const ENCODED_SIZE: usize = - Affector::POSTCARD_MAX_SIZE + cobs_overhead(Affector::POSTCARD_MAX_SIZE); + pub const ENCODED_SIZE: usize = Affector::POSTCARD_MAX_SIZE + + cobs_overhead(Affector::POSTCARD_MAX_SIZE); #[cfg(feature = "alloc")] #[must_use] @@ -69,7 +69,8 @@ impl Affector { } pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { - postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeMsgError::CorruptEncoding) + postcard::from_bytes_cobs(bytes.as_mut()) + .map_err(DecodeMsgError::CorruptEncoding) } // Info() is explicitly not defined, use the tree impl to get at it @@ -109,7 +110,9 @@ impl Decoder { FeedResult::Consumed => break, FeedResult::OverFull(new_window) => new_window, FeedResult::DeserError(_) => return Err(DeserializeError), - FeedResult::Success { data, remaining } => return Ok(Some((data, remaining))), + FeedResult::Success { data, remaining } => { + return Ok(Some((data, remaining))) + } } } Ok(None) @@ -125,7 +128,8 @@ pub struct ListMessage { impl ListMessage { /// +2 is for the version /// +4 covers the length of the heapless list - pub const HALF_ENCODED_SIZE: usize = (MAX_ITEMS * Affector::POSTCARD_MAX_SIZE + 2 + 4); + pub const HALF_ENCODED_SIZE: usize = + (MAX_ITEMS * Affector::POSTCARD_MAX_SIZE + 2 + 4); /// cobs and postcard encoded pub const ENCODED_SIZE: usize = Self::HALF_ENCODED_SIZE + cobs_overhead(Self::HALF_ENCODED_SIZE); @@ -152,7 +156,8 @@ impl ListMessage { } pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { - postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeMsgError::CorruptEncoding) + postcard::from_bytes_cobs(bytes.as_mut()) + .map_err(DecodeMsgError::CorruptEncoding) } } @@ -163,16 +168,18 @@ mod test { #[test] fn decoder_decodes_encoded() { - let test_affector = - Affector::LargeBedroom(large_bedroom::Affector::Bed(bed::Affector::RgbLed { + let test_affector = Affector::LargeBedroom( + large_bedroom::Affector::Bed(bed::Affector::RgbLed { red: 0, green: 5, blue: 0, - })); + }), + ); let encoded = test_affector.encode(); let mut encoded_copy = encoded.clone(); - let decoded: Affector = postcard::from_bytes_cobs(encoded_copy.as_mut_slice()).unwrap(); + let decoded: Affector = + postcard::from_bytes_cobs(encoded_copy.as_mut_slice()).unwrap(); assert_eq!(decoded, test_affector); let mut decoder = Decoder::default(); diff --git a/crates/protocol/src/button.rs b/crates/protocol/src/button.rs index a498156a..c88fff95 100644 --- a/crates/protocol/src/button.rs +++ b/crates/protocol/src/button.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "alloc")] +use crate::reading::LabelFormatter; use serde::{Deserialize, Serialize}; // Duration of the press in milliseconds @@ -43,7 +45,7 @@ macro_rules! button_enum { Eq, )] $(#[$outer])* // docs - /// SAFETY: must be repr(u8) or id fn will create undefined behaviour + /// SAFETY: must be repr(u8) or id `fn` will create undefined behavior #[repr(u8)] pub enum $name { $($variant(crate::button::Press),)* @@ -84,6 +86,7 @@ macro_rules! button_enum { resolution: 1.0, unit: crate::Unit::None, branch_id: self.branch_id(), + label_formatter: Box::new(crate::button::ButtonLabelFormatter), }) } fn name(&self) -> String { @@ -111,3 +114,23 @@ macro_rules! button_enum { }; } pub(crate) use button_enum; + +#[cfg(feature = "alloc")] +#[derive(Debug)] +pub struct ButtonLabelFormatter; + +#[cfg(feature = "alloc")] +impl LabelFormatter for ButtonLabelFormatter { + fn format(&self, info: &crate::reading::Info) -> String { + match info.val { + 2.0 => "long press", + 1.0 => "short press", + 0.0 => "not pressed", + _ => "ButtonLabelFormatter error", + } + .to_string() + } + fn box_clone(&self) -> Box { + Box::new(Self) + } +} diff --git a/crates/protocol/src/device.rs b/crates/protocol/src/device.rs index 4c256584..9e915201 100644 --- a/crates/protocol/src/device.rs +++ b/crates/protocol/src/device.rs @@ -5,7 +5,17 @@ use serde::{Deserialize, Serialize}; use crate::{large_bedroom, small_bedroom, Affector, Reading}; -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, PartialEq, Eq, Hash)] +#[derive( + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, + Eq, + Hash, +)] pub enum Device { LargeBedroom(large_bedroom::Device), SmallBedroom(small_bedroom::Device), @@ -29,4 +39,3 @@ pub struct Info { pub max_sample_interval: Duration, pub temporal_resolution: Duration, } - diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index b86cbb74..ace580c8 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -2,7 +2,7 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; #[cfg(feature = "alloc")] -use crate::{reading, affector}; +use crate::{affector, reading}; pub mod bed; pub mod desk; @@ -65,7 +65,17 @@ impl core::fmt::Display for Error { } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq, Hash)] +#[derive( + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + Eq, + PartialEq, + Hash, +)] pub enum Device { Bed(bed::Device), Desk(desk::Device), diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 18cd7c78..87849655 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -7,7 +7,10 @@ use crate::button_enum; #[cfg(feature = "alloc")] use crate::reading::tree::{Id, Item, Tree}; #[cfg(feature = "alloc")] +use crate::reading::FloatLabelFormatter; +#[cfg(feature = "alloc")] use crate::reading::Info; +use crate::shared::impl_is_same_as; #[cfg(feature = "alloc")] use crate::{affector, Unit}; @@ -253,6 +256,7 @@ impl Tree for Reading { unit, description, branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), }) } @@ -262,35 +266,14 @@ impl Tree for Reading { } } -impl crate::IsSameAs for Reading { - #[must_use] - fn is_same_as(&self, other: &Self) -> bool { - match (self, other) { - (Self::Brightness(_), Self::Brightness(_)) - | (Self::Temperature(_), Self::Temperature(_)) - | (Self::Humidity(_), Self::Humidity(_)) - | (Self::GassResistance(_), Self::GassResistance(_)) - | (Self::Pressure(_), Self::Pressure(_)) - | (Self::Co2(_), Self::Co2(_)) - | (Self::WeightLeft(_), Self::WeightLeft(_)) - | (Self::WeightRight(_), Self::WeightRight(_)) - | (Self::MassPm1_0(_), Self::MassPm1_0(_)) - | (Self::MassPm2_5(_), Self::MassPm2_5(_)) - | (Self::MassPm4_0(_), Self::MassPm4_0(_)) - | (Self::MassPm10(_), Self::MassPm10(_)) - | (Self::NumberPm0_5(_), Self::NumberPm0_5(_)) - | (Self::NumberPm1_0(_), Self::NumberPm1_0(_)) - | (Self::NumberPm2_5(_), Self::NumberPm2_5(_)) - | (Self::NumberPm4_0(_), Self::NumberPm4_0(_)) - | (Self::NumberPm10(_), Self::NumberPm10(_)) - | (Self::TypicalParticleSize(_), Self::TypicalParticleSize(_)) => true, - (Self::Button(a), Self::Button(b)) => a.is_same_as(b), - _ => false, - } - } +impl_is_same_as! {Reading; Brightness, Temperature, Humidity, GassResistance, Pressure, + Co2, WeightLeft, WeightRight, MassPm1_0, MassPm2_5, MassPm4_0, MassPm10, + TypicalParticleSize; (Self::Button(a), Self::Button(b)) => a.is_same_as(b) } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +#[derive( + Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq, +)] pub enum Error { Running(SensorError), Setup(SensorError), @@ -302,8 +285,12 @@ impl Error { #[must_use] pub(crate) fn device(&self) -> Device { match self { - Self::Running(sensor_err) | Self::Setup(sensor_err) => sensor_err.device(), - Self::SetupTimedOut(device) | Self::Timeout(device) => device.clone(), + Self::Running(sensor_err) | Self::Setup(sensor_err) => { + sensor_err.device() + } + Self::SetupTimedOut(device) | Self::Timeout(device) => { + device.clone() + } } } } @@ -319,7 +306,9 @@ impl core::fmt::Display for Error { } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, Eq, PartialEq)] +#[derive( + Clone, Debug, defmt::Format, Serialize, Deserialize, Eq, PartialEq, +)] pub enum SensorError { Sht31(heapless::String<200>), Bme680(heapless::String<200>), @@ -366,7 +355,17 @@ impl SensorError { } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq, Hash)] +#[derive( + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + Eq, + PartialEq, + Hash, +)] pub enum Device { Sht31, Bme680, @@ -562,7 +561,9 @@ impl Affector { value: ControlValue::SetNum { valid_range: 0..255, value: *red as usize, - setter: Some(Box::new(|input: usize| *red = input as u8)), + setter: Some(Box::new(|input: usize| { + *red = input as u8 + })), }, }, Control { @@ -570,7 +571,9 @@ impl Affector { value: ControlValue::SetNum { valid_range: 0..255, value: *green as usize, - setter: Some(Box::new(|input: usize| *green = input as u8)), + setter: Some(Box::new(|input: usize| { + *green = input as u8 + })), }, }, Control { @@ -578,7 +581,9 @@ impl Affector { value: ControlValue::SetNum { valid_range: 0..255, value: *blue as usize, - setter: Some(Box::new(|input: usize| *blue = input as u8)), + setter: Some(Box::new(|input: usize| { + *blue = input as u8 + })), }, }, ], diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index 66f76bdd..afc60acb 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -7,9 +7,12 @@ use crate::button_enum; #[cfg(feature = "alloc")] use crate::reading::tree::{Item, Tree}; #[cfg(feature = "alloc")] -use crate::Unit; +use crate::reading::FloatLabelFormatter; #[cfg(feature = "alloc")] use crate::reading::Info; +use crate::shared::impl_is_same_as; +#[cfg(feature = "alloc")] +use crate::Unit; button_enum! { /// No these are not borg, these are buttons on a string of cat5. @@ -59,6 +62,7 @@ impl Tree for Reading { unit: Unit::C, description: "Temperature", branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), }, Reading::Humidity(val) => Info { val: *val, @@ -68,6 +72,7 @@ impl Tree for Reading { unit: Unit::RH, description: "Humidity", branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), }, Reading::Pressure(val) => Info { val: *val, @@ -77,6 +82,7 @@ impl Tree for Reading { unit: Unit::Pa, description: "Air pressure", branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), }, Reading::Button(val) => return Item::Node(val as &dyn Tree), }; @@ -89,20 +95,12 @@ impl Tree for Reading { } } -impl crate::IsSameAs for Reading { - #[must_use] - fn is_same_as(&self, other: &Self) -> bool { - match (self, other) { - (Reading::Temperature(_), Self::Temperature(_)) - | (Reading::Humidity(_), Self::Humidity(_)) - | (Reading::Pressure(_), Self::Pressure(_)) => true, - (Reading::Button(a), Self::Button(b)) => a.is_same_as(b), - _ => false, - } - } -} +impl_is_same_as! {Reading; Temperature, Humidity, Pressure; +(Reading::Button(a), Self::Button(b)) => a.is_same_as(b)} -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +#[derive( + Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq, +)] pub enum Error { Running(SensorError), Setup(SensorError), @@ -114,8 +112,12 @@ impl Error { #[must_use] pub fn device(&self) -> Device { match self { - Self::Running(sensor_err) | Self::Setup(sensor_err) => sensor_err.device(), - Self::SetupTimedOut(device) | Self::Timeout(device) => device.clone(), + Self::Running(sensor_err) | Self::Setup(sensor_err) => { + sensor_err.device() + } + Self::SetupTimedOut(device) | Self::Timeout(device) => { + device.clone() + } } } } @@ -123,15 +125,21 @@ impl Error { impl core::fmt::Display for Error { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - Error::Running(e) => write!(f, "{} ran into error: {e}", e.device()), - Error::Setup(e) => write!(f, "{} errored during setup: {e}", e.device()), + Error::Running(e) => { + write!(f, "{} ran into error: {e}", e.device()) + } + Error::Setup(e) => { + write!(f, "{} errored during setup: {e}", e.device()) + } Error::SetupTimedOut(d) => write!(f, "{d} timed out during setup"), Error::Timeout(d) => write!(f, "{d} timed out while running"), } } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, Eq, PartialEq)] +#[derive( + Clone, Debug, defmt::Format, Serialize, Deserialize, Eq, PartialEq, +)] pub enum SensorError { BmeError(heapless::String<200>), Gpio(heapless::String<200>), @@ -159,7 +167,17 @@ impl core::fmt::Display for SensorError { } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq, Hash)] +#[derive( + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + Eq, + PartialEq, + Hash, +)] pub enum Device { Bme280, Gpio, diff --git a/crates/protocol/src/large_bedroom/radiator.rs b/crates/protocol/src/large_bedroom/radiator.rs index d391469c..f90ec492 100644 --- a/crates/protocol/src/large_bedroom/radiator.rs +++ b/crates/protocol/src/large_bedroom/radiator.rs @@ -6,7 +6,10 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "alloc")] use crate::reading::tree::{Item, Tree}; #[cfg(feature = "alloc")] +use crate::reading::FloatLabelFormatter; +#[cfg(feature = "alloc")] use crate::reading::Info; +use crate::shared::{self, impl_is_same_as}; #[cfg(feature = "alloc")] use crate::Unit; @@ -26,40 +29,11 @@ use crate::Unit; pub enum Reading { Temperature(f32) = 0, Heating(f32) = 1, - SetBy(Source) = 2, + SetBy(shared::radiator::Source) = 2, Setpoint(f32) = 3, } -#[derive( - strum::EnumDiscriminants, - Clone, - Copy, - Debug, - defmt::Format, - Serialize, - Deserialize, - MaxSize, - PartialEq, -)] -#[strum_discriminants(derive(Hash))] -#[repr(u8)] -pub enum Source { - Manual, - Schedule, - External, -} - -impl crate::IsSameAs for Reading { - fn is_same_as(&self, other: &Self) -> bool { - match (self, other) { - (Reading::Temperature(_), Reading::Temperature(_)) - | (Reading::Heating(_), Reading::Heating(_)) - | (Reading::SetBy(_), Reading::SetBy(_)) => true, - (Reading::Setpoint(_), Reading::Setpoint(_)) => true, - (_, _) => false, - } - } -} +impl_is_same_as!{Reading; Temperature, Heating, SetBy, Setpoint} #[cfg(feature = "alloc")] impl Tree for Reading { @@ -76,6 +50,7 @@ impl Tree for Reading { unit: Unit::C, description: "Temperature", branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), }, Reading::Heating(val) => Info { val: *val, @@ -87,6 +62,7 @@ impl Tree for Reading { unit: Unit::RelativePower, description: "Heating valve", branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), }, Reading::SetBy(val) => Info { val: *val as u8 as f32, @@ -98,6 +74,9 @@ impl Tree for Reading { unit: Unit::None, description: "Manual value set", branch_id: self.branch_id(), + label_formatter: Box::new( + shared::radiator::SetByLabelFormatter, + ), }, Reading::Setpoint(val) => Info { val: *val, @@ -109,6 +88,7 @@ impl Tree for Reading { unit: Unit::C, description: "Set point", branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), }, }; Item::Leaf(leaf) @@ -154,7 +134,10 @@ impl Device { pub const fn info(&self) -> crate::DeviceInfo { crate::DeviceInfo { name: "Radiator", - affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Heating(0.0), Reading::SetBy(Source::Manual), Reading::Setpoint(0.0)], + affects_readings: &tree![ + Reading; Reading::Temperature(0.0), Reading::Heating(0.0), + Reading::SetBy(shared::radiator::Source::Manual), + Reading::Setpoint(0.0)], temporal_resolution: Duration::from_secs(5), // unknown min_sample_interval: Duration::from_secs(5), // unknown max_sample_interval: Duration::MAX, diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 6042306e..1f52c24f 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -8,6 +8,7 @@ pub(crate) use button::button_enum; pub mod large_bedroom; pub mod small_bedroom; +pub mod shared; pub mod affector; mod device; @@ -58,7 +59,7 @@ impl Display for Unit { } } -/// Is this the same variant as the other? +/// Is this the same variant as the other? /// Example: /// Temperature(5) is the same as Temperature(6) pub trait IsSameAs { diff --git a/crates/protocol/src/msg.rs b/crates/protocol/src/msg.rs index f135a3d2..9ef31481 100644 --- a/crates/protocol/src/msg.rs +++ b/crates/protocol/src/msg.rs @@ -100,7 +100,10 @@ impl Msg { #[derive(Debug, Clone, defmt::Format)] #[cfg_attr(feature = "thiserror", derive(thiserror::Error))] pub enum DecodeMsgError { - #[cfg_attr(feature = "thiserror", error("Could not decode SensorMessage: {0}"))] + #[cfg_attr( + feature = "thiserror", + error("Could not decode SensorMessage: {0}") + )] CorruptEncoding(postcard::Error), #[cfg_attr( feature = "thiserror", diff --git a/crates/protocol/src/msg/error.rs b/crates/protocol/src/msg/error.rs index 273e782e..c32f0b67 100644 --- a/crates/protocol/src/msg/error.rs +++ b/crates/protocol/src/msg/error.rs @@ -42,7 +42,8 @@ impl ErrorReport { } pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { - postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeMsgError::CorruptEncoding) + postcard::from_bytes_cobs(bytes.as_mut()) + .map_err(DecodeMsgError::CorruptEncoding) } } diff --git a/crates/protocol/src/msg/sensor.rs b/crates/protocol/src/msg/sensor.rs index e2716511..0ad51e3a 100644 --- a/crates/protocol/src/msg/sensor.rs +++ b/crates/protocol/src/msg/sensor.rs @@ -24,7 +24,8 @@ impl Default for SensorMessage { impl SensorMessage { /// +2 is for the version /// +4 covers the length of the heapless list - pub const HALF_ENCODED_SIZE: usize = (MAX_ITEMS * Reading::POSTCARD_MAX_SIZE + 2 + 4); + pub const HALF_ENCODED_SIZE: usize = + (MAX_ITEMS * Reading::POSTCARD_MAX_SIZE + 2 + 4); /// cobs and postcard encoded pub const ENCODED_SIZE: usize = @@ -49,7 +50,8 @@ impl SensorMessage { } pub fn decode(mut bytes: impl AsMut<[u8]>) -> Result { - postcard::from_bytes_cobs(bytes.as_mut()).map_err(DecodeMsgError::CorruptEncoding) + postcard::from_bytes_cobs(bytes.as_mut()) + .map_err(DecodeMsgError::CorruptEncoding) } #[must_use] diff --git a/crates/protocol/src/reading.rs b/crates/protocol/src/reading.rs index 5632fd16..097aadf4 100644 --- a/crates/protocol/src/reading.rs +++ b/crates/protocol/src/reading.rs @@ -60,6 +60,33 @@ impl Reading { } } +#[cfg(feature = "alloc")] +pub trait LabelFormatter: core::fmt::Debug { + fn format(&self, info: &Info) -> String; + fn box_clone(&self) -> Box; +} + +#[cfg(feature = "alloc")] +impl Clone for Box { + fn clone(&self) -> Self { + self.box_clone() + } +} + +#[cfg(feature = "alloc")] +#[derive(Debug)] +pub struct FloatLabelFormatter; + +#[cfg(feature = "alloc")] +impl LabelFormatter for FloatLabelFormatter { + fn format(&self, info: &Info) -> String { + format!("{0:.1$}", info.val, info.precision()) + } + fn box_clone(&self) -> Box { + Box::new(Self) + } +} + #[cfg(feature = "alloc")] #[derive(Debug, Clone)] pub struct Info { @@ -71,6 +98,7 @@ pub struct Info { pub unit: Unit, pub description: &'static str, pub branch_id: u8, + pub label_formatter: Box, } #[cfg(feature = "alloc")] diff --git a/crates/protocol/src/reading/tree.rs b/crates/protocol/src/reading/tree.rs index 29453d94..b0a9fb85 100644 --- a/crates/protocol/src/reading/tree.rs +++ b/crates/protocol/src/reading/tree.rs @@ -67,4 +67,3 @@ macro_rules! all_nodes { }; } pub(crate) use all_nodes; - diff --git a/crates/protocol/src/small_bedroom/bed.rs b/crates/protocol/src/small_bedroom/bed.rs index 7d09016d..c851e2f8 100644 --- a/crates/protocol/src/small_bedroom/bed.rs +++ b/crates/protocol/src/small_bedroom/bed.rs @@ -6,7 +6,10 @@ use crate::button::Press; #[cfg(feature = "alloc")] use crate::reading::tree::{Id, Item, Tree}; #[cfg(feature = "alloc")] +use crate::reading::FloatLabelFormatter; +#[cfg(feature = "alloc")] use crate::reading::Info; +use crate::shared::impl_is_same_as; #[cfg(feature = "alloc")] use crate::{affector, Unit}; @@ -234,6 +237,7 @@ impl Tree for Reading { unit, description, branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), }) } @@ -243,33 +247,11 @@ impl Tree for Reading { } } -impl crate::IsSameAs for Reading { - #[must_use] - fn is_same_as(&self, other: &Self) -> bool { - match (self, other) { - (Self::Brightness(_), Self::Brightness(_)) - | (Self::Temperature(_), Self::Temperature(_)) - | (Self::Humidity(_), Self::Humidity(_)) - | (Self::GassResistance(_), Self::GassResistance(_)) - | (Self::Pressure(_), Self::Pressure(_)) - | (Self::Co2(_), Self::Co2(_)) - | (Self::Weight(_), Self::Weight(_)) - | (Self::MassPm1_0(_), Self::MassPm1_0(_)) - | (Self::MassPm2_5(_), Self::MassPm2_5(_)) - | (Self::MassPm4_0(_), Self::MassPm4_0(_)) - | (Self::MassPm10(_), Self::MassPm10(_)) - | (Self::NumberPm0_5(_), Self::NumberPm0_5(_)) - | (Self::NumberPm1_0(_), Self::NumberPm1_0(_)) - | (Self::NumberPm2_5(_), Self::NumberPm2_5(_)) - | (Self::NumberPm4_0(_), Self::NumberPm4_0(_)) - | (Self::NumberPm10(_), Self::NumberPm10(_)) - | (Self::TypicalParticleSize(_), Self::TypicalParticleSize(_)) => { - true - } - (Self::Button(a), Self::Button(b)) => a.is_same_as(b), - _ => false, - } - } +impl_is_same_as! {Reading; + Brightness, Temperature, Humidity, GassResistance, Pressure, Co2, Weight, + MassPm1_0, MassPm2_5, MassPm4_0, MassPm10, NumberPm0_5, NumberPm1_0, + NumberPm2_5, NumberPm4_0, NumberPm10, TypicalParticleSize; + (Self::Button(a), Self::Button(b)) => a.is_same_as(b) } #[derive( diff --git a/crates/protocol/src/small_bedroom/desk.rs b/crates/protocol/src/small_bedroom/desk.rs index 1a8e4dc0..7d7badfa 100644 --- a/crates/protocol/src/small_bedroom/desk.rs +++ b/crates/protocol/src/small_bedroom/desk.rs @@ -6,7 +6,10 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "alloc")] use crate::reading::tree::{Item, Tree}; #[cfg(feature = "alloc")] +use crate::reading::FloatLabelFormatter; +#[cfg(feature = "alloc")] use crate::reading::Info; +use crate::shared::impl_is_same_as; #[cfg(feature = "alloc")] use crate::Unit; @@ -42,6 +45,7 @@ impl Tree for Reading { unit: Unit::C, description: "Temperature", branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), }, Reading::Humidity(val) => Info { val: *val, @@ -51,6 +55,7 @@ impl Tree for Reading { unit: Unit::RH, description: "Humidity", branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), }, Reading::Pressure(val) => Info { val: *val, @@ -60,6 +65,7 @@ impl Tree for Reading { unit: Unit::Pa, description: "Air pressure", branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), }, }; Item::Leaf(leaf) @@ -71,20 +77,11 @@ impl Tree for Reading { } } -impl crate::IsSameAs for Reading { - #[must_use] - fn is_same_as(&self, other: &Self) -> bool { - #[allow(clippy::match_like_matches_macro)] - match (self, other) { - (Reading::Temperature(_), Self::Temperature(_)) - | (Reading::Humidity(_), Self::Humidity(_)) - | (Reading::Pressure(_), Self::Pressure(_)) => true, - _ => false, - } - } -} +impl_is_same_as!(Reading; Temperature, Humidity, Pressure); -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq)] +#[derive( + Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq, +)] pub enum Error { Running(SensorError), Setup(SensorError), @@ -96,8 +93,12 @@ impl Error { #[must_use] pub fn device(&self) -> Device { match self { - Self::Running(sensor_err) | Self::Setup(sensor_err) => sensor_err.device(), - Self::SetupTimedOut(device) | Self::Timeout(device) => device.clone(), + Self::Running(sensor_err) | Self::Setup(sensor_err) => { + sensor_err.device() + } + Self::SetupTimedOut(device) | Self::Timeout(device) => { + device.clone() + } } } } @@ -105,15 +106,21 @@ impl Error { impl core::fmt::Display for Error { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - Error::Running(e) => write!(f, "{} ran into error: {e}", e.device()), - Error::Setup(e) => write!(f, "{} errored during setup: {e}", e.device()), + Error::Running(e) => { + write!(f, "{} ran into error: {e}", e.device()) + } + Error::Setup(e) => { + write!(f, "{} errored during setup: {e}", e.device()) + } Error::SetupTimedOut(d) => write!(f, "{d} timed out during setup"), Error::Timeout(d) => write!(f, "{d} timed out while running"), } } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, Eq, PartialEq)] +#[derive( + Clone, Debug, defmt::Format, Serialize, Deserialize, Eq, PartialEq, +)] pub enum SensorError { BmeError(heapless::String<200>), } @@ -139,7 +146,17 @@ impl core::fmt::Display for SensorError { } } -#[derive(Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq, Hash)] +#[derive( + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + Eq, + PartialEq, + Hash, +)] pub enum Device { Bme280, } diff --git a/crates/protocol/src/small_bedroom/portable_button_panel.rs b/crates/protocol/src/small_bedroom/portable_button_panel.rs index b4bf6fef..c3c3156d 100644 --- a/crates/protocol/src/small_bedroom/portable_button_panel.rs +++ b/crates/protocol/src/small_bedroom/portable_button_panel.rs @@ -5,6 +5,8 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "alloc")] use crate::reading::tree::{Item, Tree}; +#[cfg(feature = "alloc")] +use crate::reading::FloatLabelFormatter; use crate::IsSameAs; #[derive( @@ -53,6 +55,7 @@ impl Tree for Reading { resolution: 1.0, unit: crate::Unit::None, branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), }) } diff --git a/crates/protocol/src/small_bedroom/radiator.rs b/crates/protocol/src/small_bedroom/radiator.rs index 365fde12..5dfac2ed 100644 --- a/crates/protocol/src/small_bedroom/radiator.rs +++ b/crates/protocol/src/small_bedroom/radiator.rs @@ -6,7 +6,10 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "alloc")] use crate::reading::tree::{Item, Tree}; #[cfg(feature = "alloc")] +use crate::reading::FloatLabelFormatter; +#[cfg(feature = "alloc")] use crate::reading::Info; +use crate::shared::impl_is_same_as; #[cfg(feature = "alloc")] use crate::Unit; @@ -26,40 +29,11 @@ use crate::Unit; pub enum Reading { Temperature(f32) = 0, Heating(f32) = 1, - SetBy(Source) = 2, + SetBy(crate::shared::radiator::Source) = 2, Setpoint(f32) = 3, } -#[derive( - strum::EnumDiscriminants, - Clone, - Copy, - Debug, - defmt::Format, - Serialize, - Deserialize, - MaxSize, - PartialEq, -)] -#[strum_discriminants(derive(Hash))] -#[repr(u8)] -pub enum Source { - Manual, - Schedule, - External, -} - -impl crate::IsSameAs for Reading { - fn is_same_as(&self, other: &Self) -> bool { - match (self, other) { - (Reading::Temperature(_), Reading::Temperature(_)) - | (Reading::Heating(_), Reading::Heating(_)) - | (Reading::SetBy(_), Reading::SetBy(_)) => true, - (Reading::Setpoint(_), Reading::Setpoint(_)) => true, - (_, _) => false, - } - } -} +impl_is_same_as!(Reading; Temperature, Heating, SetBy, Setpoint); #[cfg(feature = "alloc")] impl Tree for Reading { @@ -76,6 +50,7 @@ impl Tree for Reading { unit: Unit::C, description: "Temperature", branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), }, Reading::Heating(val) => Info { val: *val, @@ -87,6 +62,7 @@ impl Tree for Reading { unit: Unit::RelativePower, description: "Heating valve", branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), }, Reading::SetBy(val) => Info { val: *val as u8 as f32, @@ -98,6 +74,9 @@ impl Tree for Reading { unit: Unit::None, description: "Manual value set", branch_id: self.branch_id(), + label_formatter: Box::new( + crate::shared::radiator::SetByLabelFormatter, + ), }, Reading::Setpoint(val) => Info { val: *val, @@ -109,6 +88,7 @@ impl Tree for Reading { unit: Unit::C, description: "Set point", branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), }, }; Item::Leaf(leaf) @@ -154,7 +134,10 @@ impl Device { pub const fn info(&self) -> crate::DeviceInfo { crate::DeviceInfo { name: "Radiator", - affects_readings: &tree![Reading; Reading::Temperature(0.0), Reading::Heating(0.0), Reading::SetBy(Source::Manual), Reading::Setpoint(0.0)], + affects_readings: &tree![Reading; + Reading::Temperature(0.0), Reading::Heating(0.0), + Reading::SetBy(crate::shared::radiator::Source::Manual), + Reading::Setpoint(0.0)], temporal_resolution: Duration::from_secs(5), // unknown min_sample_interval: Duration::from_secs(5), // unknown max_sample_interval: Duration::MAX, diff --git a/crates/protocol/src/usb.rs b/crates/protocol/src/usb.rs index cc0e625f..3801ef2e 100644 --- a/crates/protocol/src/usb.rs +++ b/crates/protocol/src/usb.rs @@ -1,4 +1,3 @@ - pub const GET_QUEUED_MESSAGES: u8 = 101; pub const AFFECTOR_ORDER: u8 = 100; pub const GET_AFFECTOR_LIST: u8 = 102; diff --git a/crates/ui/examples/chart_gaps.rs b/crates/ui/examples/chart_gaps.rs index 7480964f..d1cf27ec 100644 --- a/crates/ui/examples/chart_gaps.rs +++ b/crates/ui/examples/chart_gaps.rs @@ -1,9 +1,11 @@ use std::io::stdout; use crossterm::terminal::{ - disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen, + disable_raw_mode, enable_raw_mode, EnterAlternateScreen, + LeaveAlternateScreen, }; use crossterm::{event, ExecutableCommand}; +use protocol::reading::FloatLabelFormatter; use ratatui::backend::CrosstermBackend; use ratatui::{Frame, Terminal}; use ui::tui::readings::render::chart; @@ -17,22 +19,27 @@ fn data_with_gap(buffer: &mut Vec<(f64, f64)>) -> ChartParts<'_> { let info = protocol::reading::Info { val: 0.0, - device: protocol::Device::SmallBedroom(protocol::small_bedroom::Device::Bed( - protocol::small_bedroom::bed::Device::Bme680, - )), + device: protocol::Device::SmallBedroom( + protocol::small_bedroom::Device::Bed( + protocol::small_bedroom::bed::Device::Bme680, + ), + ), resolution: 1.0, range: 0.0..5.0, unit: protocol::Unit::Ohm, description: "test data with gaps", branch_id: 0, + label_formatter: Box::new(FloatLabelFormatter), }; ChartParts { info, data: buffer.as_mut_slice(), - reading: protocol::Reading::SmallBedroom(protocol::small_bedroom::Reading::Bed( - protocol::small_bedroom::bed::Reading::Temperature(0.0), - )), + reading: protocol::Reading::SmallBedroom( + protocol::small_bedroom::Reading::Bed( + protocol::small_bedroom::bed::Reading::Temperature(0.0), + ), + ), } } diff --git a/crates/ui/src/tui/readings/render/chart/split.rs b/crates/ui/src/tui/readings/render/chart/split.rs index accefb24..0b6e676e 100644 --- a/crates/ui/src/tui/readings/render/chart/split.rs +++ b/crates/ui/src/tui/readings/render/chart/split.rs @@ -20,7 +20,8 @@ pub(crate) fn split<'a>( chart: &'a ChartParts, chart_width: u16, ) -> impl Iterator { - let min_dist = chart.info.device.info().max_sample_interval.as_secs_f64() * 1.2; // 20% margin + let min_dist = + chart.info.device.info().max_sample_interval.as_secs_f64() * 1.2; // 20% margin let chart_resolution = chart .data @@ -53,6 +54,7 @@ pub(crate) fn split<'a>( #[cfg(test)] mod test { + use protocol::reading::FloatLabelFormatter; use protocol::{large_bedroom, Device}; use super::*; @@ -80,11 +82,14 @@ mod test { unit: protocol::Unit::C, description: "test", branch_id: 1, + label_formatter: Box::new(FloatLabelFormatter), }, data: &mut test_data, - reading: protocol::Reading::LargeBedroom(large_bedroom::Reading::Bed( - large_bedroom::bed::Reading::GassResistance(0.0), - )), + reading: protocol::Reading::LargeBedroom( + large_bedroom::Reading::Bed( + large_bedroom::bed::Reading::GassResistance(0.0), + ), + ), }; assert_eq!(split(&test_chart, 500).count(), 5); assert_eq!( diff --git a/crates/zigbee-bridge/src/parse.rs b/crates/zigbee-bridge/src/parse.rs index 1572c740..c1f86c3f 100644 --- a/crates/zigbee-bridge/src/parse.rs +++ b/crates/zigbee-bridge/src/parse.rs @@ -103,13 +103,13 @@ pub(crate) fn radiator_readings( .transpose()? .map(|val| match val.to_lowercase().as_str() { "manual" => { - Ok($protocol_module::radiator::Source::Manual) + Ok(protocol::shared::radiator::Source::Manual) } "schedule" => { - Ok($protocol_module::radiator::Source::Schedule) + Ok(protocol::shared::radiator::Source::Schedule) } "externally" => { - Ok($protocol_module::radiator::Source::External) + Ok(protocol::shared::radiator::Source::External) } _ => Err(color_eyre::eyre::eyre!( "Unexpected change source {val}" From ddfd83793ce2fc93f6974bf77818ae2eecfb68af Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 13 Jan 2025 18:09:26 +0100 Subject: [PATCH 552/687] formatter implemented for button --- crates/protocol/src/button.rs | 4 +-- crates/protocol/src/reading.rs | 15 +++++++-- .../src/tui/readings/render/chart/labels.rs | 32 +++++++++++++------ 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/crates/protocol/src/button.rs b/crates/protocol/src/button.rs index c88fff95..c40bca25 100644 --- a/crates/protocol/src/button.rs +++ b/crates/protocol/src/button.rs @@ -121,8 +121,8 @@ pub struct ButtonLabelFormatter; #[cfg(feature = "alloc")] impl LabelFormatter for ButtonLabelFormatter { - fn format(&self, info: &crate::reading::Info) -> String { - match info.val { + fn format(&self, value: f64, _: &crate::reading::Info) -> String { + match value { 2.0 => "long press", 1.0 => "short press", 0.0 => "not pressed", diff --git a/crates/protocol/src/reading.rs b/crates/protocol/src/reading.rs index 097aadf4..c2c13ec2 100644 --- a/crates/protocol/src/reading.rs +++ b/crates/protocol/src/reading.rs @@ -60,10 +60,19 @@ impl Reading { } } +// todo make axis fixed for some info's? +pub enum LabelPositions { + Flexible, + Fixed(&'static [f64]), +} + #[cfg(feature = "alloc")] pub trait LabelFormatter: core::fmt::Debug { - fn format(&self, info: &Info) -> String; + fn format(&self, value: f64, info: &Info) -> String; fn box_clone(&self) -> Box; + fn positions(&self) -> LabelPositions { + LabelPositions::Flexible + } } #[cfg(feature = "alloc")] @@ -79,8 +88,8 @@ pub struct FloatLabelFormatter; #[cfg(feature = "alloc")] impl LabelFormatter for FloatLabelFormatter { - fn format(&self, info: &Info) -> String { - format!("{0:.1$}", info.val, info.precision()) + fn format(&self, value: f64, info: &Info) -> String { + format!("{0:.1$}", value, info.precision()) } fn box_clone(&self) -> Box { Box::new(Self) diff --git a/crates/ui/src/tui/readings/render/chart/labels.rs b/crates/ui/src/tui/readings/render/chart/labels.rs index 0e0c9b85..a80b80de 100644 --- a/crates/ui/src/tui/readings/render/chart/labels.rs +++ b/crates/ui/src/tui/readings/render/chart/labels.rs @@ -34,19 +34,33 @@ pub fn y_and_title( (labels, title) } -fn y_labels(info: &reading::Info, layout: Rect, y_bounds: Bounds) -> Vec { +fn y_labels( + info: &reading::Info, + layout: Rect, + y_bounds: Bounds, +) -> Vec { + use reading::LabelPositions as L; // Characters are about twice as high as wide - evenly_spaced_ylabels( - layout.height / Y_LABEL_SPACING, - info.resolution as f64, - y_bounds, - ) - .map(|y| format!("{0:.1$}", y, info.precision())) - .collect() + match info.label_formatter.positions() { + L::Flexible => evenly_spaced_ylabels( + layout.height / Y_LABEL_SPACING, + info.resolution as f64, + y_bounds, + ) + .map(|y| info.label_formatter.format(y, &info)) + .collect(), + L::Fixed(at) => at + .into_iter() + .map(|y| info.label_formatter.format(*y, &info)) + .collect(), + } } type Labels = Vec>; -pub fn x_and_title(layout: Rect, plot_range: &PlotRange) -> (Labels, String, FmtScale) { +pub fn x_and_title( + layout: Rect, + plot_range: &PlotRange, +) -> (Labels, String, FmtScale) { // Characters are about twice as high as wide let max_labels = layout.width / Y_LABEL_SPACING / 2; let n_labels = max_labels.max(2); From 86bdaa8dc583cf9c9f610867ff97eb9023e841e0 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 13 Jan 2025 18:12:50 +0100 Subject: [PATCH 553/687] push missing files --- crates/protocol/src/shared.rs | 22 ++++++++++++ crates/protocol/src/shared/radiator.rs | 48 ++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 crates/protocol/src/shared.rs create mode 100644 crates/protocol/src/shared/radiator.rs diff --git a/crates/protocol/src/shared.rs b/crates/protocol/src/shared.rs new file mode 100644 index 00000000..40926b65 --- /dev/null +++ b/crates/protocol/src/shared.rs @@ -0,0 +1,22 @@ +pub mod radiator; + +/// implements the `IsSameAs` trait for enum `thing` with variants `variant` +/// example usage: +/// ```rust +/// impl_is_same_as!(Reading; Temperature, Heating, SetBy, Setpoint); +/// ``` +macro_rules! impl_is_same_as { + ($thing:ident; $($variant:ident),+$(; $extra:pat => $todo:expr);*) => { + impl crate::IsSameAs for $thing { + fn is_same_as(&self, other: &Self) -> bool { + match (self, other) { + $((Self::$variant(_), Self::$variant(_)))|+ => true, + $($extra => $todo,)* + _ => false, + } + } + } + }; +} + +pub(crate) use impl_is_same_as; diff --git a/crates/protocol/src/shared/radiator.rs b/crates/protocol/src/shared/radiator.rs new file mode 100644 index 00000000..13429838 --- /dev/null +++ b/crates/protocol/src/shared/radiator.rs @@ -0,0 +1,48 @@ +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "alloc")] +use crate::reading; +#[cfg(feature = "alloc")] +use crate::reading::LabelFormatter; + +#[derive( + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, +)] +#[strum_discriminants(derive(Hash))] +#[repr(u8)] +pub enum Source { + Manual = 0, + Schedule = 1, + External = 2, +} + +#[cfg(feature = "alloc")] +#[derive(Debug)] +pub struct SetByLabelFormatter; + +#[cfg(feature = "alloc")] +impl LabelFormatter for SetByLabelFormatter { + fn format(&self, value: f64, info: &reading::Info) -> String { + match value { + 0.0 => "Manual", + 1.0 => "Schedule", + 2.0 => "External", + _ => "SetpointLabelFormatterError", + } + .to_string() + } + + fn box_clone(&self) -> Box { + Box::new(Self) + } +} + From 7bf6b312d7085e472c121ccd4873f471811646ea Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 13 Jan 2025 18:49:30 +0100 Subject: [PATCH 554/687] Tweak lamp and radiator timings SB --- .../src/controller/rooms/small_bedroom.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 5964b5d2..03c0afd5 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -9,8 +9,8 @@ use tokio::time::{sleep_until, Instant}; use tracing::trace; use self::filter::{recv_filtered, RelevantEvent, Trigger}; -pub(crate) use self::state::State; use self::state::Room; +pub(crate) use self::state::State; use crate::controller::{Event, RestrictedSystem}; use crate::input::jobs::Job; use crate::time; @@ -37,6 +37,9 @@ const T13_00: f64 = time(13, 0); const T16_00: f64 = time(16, 0); const T17_00: f64 = time(17, 0); const T18_00: f64 = time(18, 0); +const T19_00: f64 = time(19, 0); +const T19_30: f64 = time(19, 30); +const T20_00: f64 = time(20, 0); const T20_30: f64 = time(20, 30); const T21_00: f64 = time(21, 0); const T21_30: f64 = time(21, 30); @@ -131,8 +134,8 @@ pub(super) fn goal_temp_now() -> f64 { match time(now.hour(), now.minute()) { T8_30..T11_00 => 19.0, T11_00..T13_00 => 20.0, - T13_00..T21_00 => 21.0, - T21_00..T22_00 => 20.0, + T13_00..T20_00 => 21.0, + T20_00..T22_00 => 20.0, T22_00.. | T0_00..T8_30 => 18.0, _ => 18.0, } @@ -144,11 +147,11 @@ pub(super) fn daylight_now() -> (usize, f64) { match time(now.hour(), now.minute()) { T8_00..T9_00 => (2000, 0.5), - T9_00..T16_00 => (4000, 1.0), - T16_00..T17_00 => (3500, 1.0), - T17_00..T18_00 => (2800, 1.0), - T18_00..T20_30 => (2300, 1.0), - T20_30..T21_30 => (2000, 0.7), + T9_00..T19_00 => (4000, 1.0), + T19_00..T19_30 => (3500, 1.0), + T20_00..T20_30 => (2800, 1.0), + T20_30..T21_00 => (2300, 1.0), + T21_00..T21_30 => (2000, 0.7), T21_30..T22_00 => (1900, 0.4), T22_00.. | T0_00..T8_00 => (1800, 0.1), _ => (2300, 1.0), From ca61fc7effff69a85de650832e9f6665a6bd79e6 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 14 Jan 2025 14:08:32 +0100 Subject: [PATCH 555/687] Add interpolation for color correction --- crates/zigbee-bridge/src/conversion.rs | 9 +-- crates/zigbee-bridge/src/lamp.rs | 6 +- crates/zigbee-bridge/src/lamp/model.rs | 77 ++++++++++++++++++-------- 3 files changed, 63 insertions(+), 29 deletions(-) diff --git a/crates/zigbee-bridge/src/conversion.rs b/crates/zigbee-bridge/src/conversion.rs index 849843e7..43f3283c 100644 --- a/crates/zigbee-bridge/src/conversion.rs +++ b/crates/zigbee-bridge/src/conversion.rs @@ -34,15 +34,16 @@ pub(super) fn times_100_int(reference: f64) -> usize { #[allow(clippy::doc_markdown)] /// 1000K < `color_temp` < 1_000_000K -pub(super) fn temp_to_xy(color_temp_k: usize) -> (f64, f64) { - // TODO: use table from black body deviation measurements +pub(super) fn temp_to_xy( + color_temp_k: usize, + color_deviation: f64, +) -> (f64, f64) { #[allow(clippy::cast_precision_loss)] - let cct = CCT::try_new(color_temp_k as f64, DUV_IKEA).unwrap(); + let cct = CCT::try_new(color_temp_k as f64, color_deviation).unwrap(); let xyz: XYZ = cct.try_into().unwrap(); let (x, y) = xyz_to_xy(xyz); (x.clamp(0.0, 1.0), y.clamp(0.0, 1.0)) - } fn xyz_to_xy(xyz: XYZ) -> (f64, f64) { diff --git a/crates/zigbee-bridge/src/lamp.rs b/crates/zigbee-bridge/src/lamp.rs index e3922847..80f1b5eb 100644 --- a/crates/zigbee-bridge/src/lamp.rs +++ b/crates/zigbee-bridge/src/lamp.rs @@ -18,8 +18,8 @@ enum Color { } impl Color { - fn xy_from_temp(temp: usize) -> Color { - Color::XY(temp_to_xy(temp)) + fn xy_from_temp(temp: usize, model: &Model) -> Color { + Color::XY(temp_to_xy(temp, model.color_deviation(temp))) } } @@ -97,7 +97,7 @@ impl Device for Lamp { LampProperty::ColorTempK(temp) => { // if we know the model, we know how to apply temp if self.model.supports_xy() { - self.color = Some(Color::xy_from_temp(temp)); + self.color = Some(Color::xy_from_temp(temp, &self.model)); } else { let range = self.model.temp_k_range(); let temp = temp.clamp(range.start, range.end); diff --git a/crates/zigbee-bridge/src/lamp/model.rs b/crates/zigbee-bridge/src/lamp/model.rs index 3b337cd6..29b73ce1 100644 --- a/crates/zigbee-bridge/src/lamp/model.rs +++ b/crates/zigbee-bridge/src/lamp/model.rs @@ -1,4 +1,7 @@ -use std::{collections::HashMap, ops::Range}; +use std::{ + collections::{BTreeMap, HashMap}, + ops::Range, +}; use tracing::warn; @@ -64,24 +67,21 @@ impl Model { } } - #[allow(unused)] - pub(super) fn color_deviation(&self, color_temp: usize) -> (usize, f64) { - match self { - Model::TradfriCandle => todo!(), - Model::TradfriE27 => todo!(), - Model::TradfriE14Color => todo!(), - Model::HueGen4 => todo!(), - Model::TradfriOther(_) => todo!(), - Model::HueOther(_) => todo!(), - Model::Other(_) => todo!(), - Model::TradfriGU10 => todo!(), - Model::TradfriE14White => todo!(), - } + pub(super) fn color_deviation(&self, color_temp: usize) -> f64 { + let temp = color_temp + self.temp_correction(color_temp) as usize; + self.blackbody_deviation(temp) + } + + fn temp_correction(&self, color_temp: usize) -> usize { + Model::interpolate(color_temp, self.temp_table()).round() as usize + } + + fn blackbody_deviation(&self, color_temp: usize) -> f64 { + Model::interpolate(color_temp, self.blackbody_table()) } - #[allow(unused)] // Value for actual color temp (after temp correction) - fn blackbody_table(&self) -> HashMap { + fn blackbody_table(&self) -> BTreeMap { match self { // 105.455.00 data Model::TradfriCandle => vec![ @@ -140,17 +140,24 @@ impl Model { .collect() } - #[allow(unused)] // Value to add to requested color temp - fn temp_table(&self) -> HashMap { + fn temp_table(&self) -> BTreeMap { match self { Model::TradfriCandle => { - vec![(2200, 30), (2700, 20), (4000, 50)] + vec![(2200, 30.), (2700, 20.), (4000, 50.)] + } + Model::TradfriE27 => vec![(2200, 110.), (2700, 30.), (4000, -110.)], + Model::TradfriE14Color => { + vec![(2200, 70.), (2700, -40.), (4000, 20.)] } - Model::TradfriE27 => vec![(2200, 110), (2700, 30), (4000, -110)], - Model::TradfriE14Color => vec![(2200, 70), (2700, -40), (4000, 20)], Model::HueGen4 | Model::HueOther(_) => { - vec![(2200, 2), (2700, 5), (4000, -10), (5500, 45), (6500, 5)] + vec![ + (2200, 2.), + (2700, 5.), + (4000, -10.), + (5500, 45.), + (6500, 5.), + ] } Model::TradfriOther(_) => todo!(), Model::Other(_) => todo!(), @@ -161,6 +168,32 @@ impl Model { .collect() } + fn interpolate(temp: usize, table: BTreeMap) -> f64 { + if let Some(val) = table.get(&temp) { + return *val; + } + + let larger = table + .iter() + .filter(|(k, _)| *k > &temp) + .min_by_key(|(k, _)| *k); + let smaller = table + .iter() + .filter(|(k, _)| *k < &temp) + .max_by_key(|(k, _)| *k); + + if let (Some(smaller), Some(larger)) = (smaller, larger) { + // Linear interpolation + return temp as f64 * (larger.1 - smaller.1) + / (*larger.0 as f64 - *smaller.0 as f64); + } + + match smaller.or(larger) { + Some(nearest) => *nearest.1, + None => 0.0, + } + } + pub(crate) fn is_hue(&self) -> bool { match self { Model::TradfriCandle From f76f177d97484e85d7d0294950e8673e7568412b Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 14 Jan 2025 14:12:33 +0100 Subject: [PATCH 556/687] Extract module color_correction --- crates/zigbee-bridge/src/lamp.rs | 1 + .../src/lamp/color_correction.rs | 125 +++++++++++++++++ crates/zigbee-bridge/src/lamp/model.rs | 131 +----------------- 3 files changed, 132 insertions(+), 125 deletions(-) create mode 100644 crates/zigbee-bridge/src/lamp/color_correction.rs diff --git a/crates/zigbee-bridge/src/lamp.rs b/crates/zigbee-bridge/src/lamp.rs index 80f1b5eb..6bce9ec0 100644 --- a/crates/zigbee-bridge/src/lamp.rs +++ b/crates/zigbee-bridge/src/lamp.rs @@ -10,6 +10,7 @@ pub(crate) use property::{LampProperty, LampPropertyDiscriminants}; mod model; mod property; +mod color_correction; #[derive(Clone, Copy, Debug)] enum Color { diff --git a/crates/zigbee-bridge/src/lamp/color_correction.rs b/crates/zigbee-bridge/src/lamp/color_correction.rs new file mode 100644 index 00000000..2d8b398a --- /dev/null +++ b/crates/zigbee-bridge/src/lamp/color_correction.rs @@ -0,0 +1,125 @@ +use std::collections::BTreeMap; + +use super::Model; + +pub(super) fn temp_correction(model: &Model, color_temp: usize) -> usize { + interpolate(color_temp, temp_table(model)).round() as usize +} + +pub(super) fn blackbody_deviation(model: &Model, color_temp: usize) -> f64 { + interpolate(color_temp, blackbody_table(model)) +} + +// Value for actual color temp (after temp correction) +fn blackbody_table(model: &Model) -> BTreeMap { + match model { + // 105.455.00 data + Model::TradfriCandle => vec![ + (2170, 0.0028), + (2391, 0.0018), + (2683, 0.0006), + (2990, 0.0006), + (3193, 0.0012), + (3590, 0.003), + (3791, 0.0036), + (3951, 0.0046), + ], + // 604.391.68 data + Model::TradfriE27 => vec![ + (1964, -0.003), + (2090, 0.0014), + (2668, 0.0015), + (3046, 0.001), + (3499, 0.0015), + (3605, -0.0011), + (4098, -0.0017), + (4110, -0.0009), + (4250, 0.0007), + ], + // 204.391.94 data + Model::TradfriE14Color => vec![ + (1841, -0.0032), + (2055, -0.0034), + (2120, 0.0012), + (2738, -0.0005), + (3070, 0.0004), + (3467, 0.0045), + (3555, 0.00), + (3981, 0.0009), + (4113, 0.0037), + ], + // A19 Color 9.5W data + Model::HueGen4 | Model::HueOther(_) => vec![ + (1998, 0.0005), + (2197, 0.00000), + (2519, -0.0004), + (2695, -0.0007), + (2849, -0.0011), + (3358, -0.0012), + (3864, -0.012), + (4010, -0.0009), + (5455, -0.0005), + (6495, 0.0014), + ], + Model::TradfriOther(_) => todo!(), + Model::Other(_) => todo!(), + Model::TradfriGU10 => todo!(), + Model::TradfriE14White => todo!(), + } + .into_iter() + .collect() +} + +// Value to add to requested color temp +fn temp_table(model: &Model) -> BTreeMap { + match model { + Model::TradfriCandle => { + vec![(2200, 30.), (2700, 20.), (4000, 50.)] + } + Model::TradfriE27 => vec![(2200, 110.), (2700, 30.), (4000, -110.)], + Model::TradfriE14Color => { + vec![(2200, 70.), (2700, -40.), (4000, 20.)] + } + Model::HueGen4 | Model::HueOther(_) => { + vec![ + (2200, 2.), + (2700, 5.), + (4000, -10.), + (5500, 45.), + (6500, 5.), + ] + } + Model::TradfriOther(_) => todo!(), + Model::Other(_) => todo!(), + Model::TradfriGU10 => todo!(), + Model::TradfriE14White => todo!(), + } + .into_iter() + .collect() +} + +fn interpolate(temp: usize, table: BTreeMap) -> f64 { + if let Some(val) = table.get(&temp) { + return *val; + } + + let larger = table + .iter() + .filter(|(k, _)| *k > &temp) + .min_by_key(|(k, _)| *k); + let smaller = table + .iter() + .filter(|(k, _)| *k < &temp) + .max_by_key(|(k, _)| *k); + + if let (Some(smaller), Some(larger)) = (smaller, larger) { + // Linear interpolation + return temp as f64 * (larger.1 - smaller.1) + / (*larger.0 as f64 - *smaller.0 as f64); + } + + match smaller.or(larger) { + Some(nearest) => *nearest.1, + None => 0.0, + } +} diff --git a/crates/zigbee-bridge/src/lamp/model.rs b/crates/zigbee-bridge/src/lamp/model.rs index 29b73ce1..48a3df1b 100644 --- a/crates/zigbee-bridge/src/lamp/model.rs +++ b/crates/zigbee-bridge/src/lamp/model.rs @@ -1,5 +1,5 @@ use std::{ - collections::{BTreeMap, HashMap}, + collections::HashMap, ops::Range, }; @@ -7,6 +7,8 @@ use tracing::warn; use crate::LIGHT_MODELS; +use super::color_correction; + #[derive(Debug, Clone, PartialEq, Eq)] pub(crate) enum Model { /// LED2107C4 TRADFRI bulb E14, white spectrum, candle, opal, 470 lm @@ -68,130 +70,9 @@ impl Model { } pub(super) fn color_deviation(&self, color_temp: usize) -> f64 { - let temp = color_temp + self.temp_correction(color_temp) as usize; - self.blackbody_deviation(temp) - } - - fn temp_correction(&self, color_temp: usize) -> usize { - Model::interpolate(color_temp, self.temp_table()).round() as usize - } - - fn blackbody_deviation(&self, color_temp: usize) -> f64 { - Model::interpolate(color_temp, self.blackbody_table()) - } - - // Value for actual color temp (after temp correction) - fn blackbody_table(&self) -> BTreeMap { - match self { - // 105.455.00 data - Model::TradfriCandle => vec![ - (2170, 0.0028), - (2391, 0.0018), - (2683, 0.0006), - (2990, 0.0006), - (3193, 0.0012), - (3590, 0.003), - (3791, 0.0036), - (3951, 0.0046), - ], - // 604.391.68 data - Model::TradfriE27 => vec![ - (1964, -0.003), - (2090, 0.0014), - (2668, 0.0015), - (3046, 0.001), - (3499, 0.0015), - (3605, -0.0011), - (4098, -0.0017), - (4110, -0.0009), - (4250, 0.0007), - ], - // 204.391.94 data - Model::TradfriE14Color => vec![ - (1841, -0.0032), - (2055, -0.0034), - (2120, 0.0012), - (2738, -0.0005), - (3070, 0.0004), - (3467, 0.0045), - (3555, 0.00), - (3981, 0.0009), - (4113, 0.0037), - ], - // A19 Color 9.5W data - Model::HueGen4 | Model::HueOther(_) => vec![ - (1998, 0.0005), - (2197, 0.00000), - (2519, -0.0004), - (2695, -0.0007), - (2849, -0.0011), - (3358, -0.0012), - (3864, -0.012), - (4010, -0.0009), - (5455, -0.0005), - (6495, 0.0014), - ], - Model::TradfriOther(_) => todo!(), - Model::Other(_) => todo!(), - Model::TradfriGU10 => todo!(), - Model::TradfriE14White => todo!(), - } - .into_iter() - .collect() - } - - // Value to add to requested color temp - fn temp_table(&self) -> BTreeMap { - match self { - Model::TradfriCandle => { - vec![(2200, 30.), (2700, 20.), (4000, 50.)] - } - Model::TradfriE27 => vec![(2200, 110.), (2700, 30.), (4000, -110.)], - Model::TradfriE14Color => { - vec![(2200, 70.), (2700, -40.), (4000, 20.)] - } - Model::HueGen4 | Model::HueOther(_) => { - vec![ - (2200, 2.), - (2700, 5.), - (4000, -10.), - (5500, 45.), - (6500, 5.), - ] - } - Model::TradfriOther(_) => todo!(), - Model::Other(_) => todo!(), - Model::TradfriGU10 => todo!(), - Model::TradfriE14White => todo!(), - } - .into_iter() - .collect() - } - - fn interpolate(temp: usize, table: BTreeMap) -> f64 { - if let Some(val) = table.get(&temp) { - return *val; - } - - let larger = table - .iter() - .filter(|(k, _)| *k > &temp) - .min_by_key(|(k, _)| *k); - let smaller = table - .iter() - .filter(|(k, _)| *k < &temp) - .max_by_key(|(k, _)| *k); - - if let (Some(smaller), Some(larger)) = (smaller, larger) { - // Linear interpolation - return temp as f64 * (larger.1 - smaller.1) - / (*larger.0 as f64 - *smaller.0 as f64); - } - - match smaller.or(larger) { - Some(nearest) => *nearest.1, - None => 0.0, - } + let temp = color_temp + + color_correction::temp_correction(&self, color_temp) as usize; + color_correction::blackbody_deviation(&self, temp) } pub(crate) fn is_hue(&self) -> bool { From 4ddaf49a9019be9fc123aa30f99191ec12bc21cb Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 14 Jan 2025 14:33:02 +0100 Subject: [PATCH 557/687] Complete color correction data --- .../src/lamp/color_correction.rs | 52 +++++++++++-------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/crates/zigbee-bridge/src/lamp/color_correction.rs b/crates/zigbee-bridge/src/lamp/color_correction.rs index 2d8b398a..ca9f91d7 100644 --- a/crates/zigbee-bridge/src/lamp/color_correction.rs +++ b/crates/zigbee-bridge/src/lamp/color_correction.rs @@ -1,5 +1,7 @@ use std::collections::BTreeMap; +use tracing::error; + use super::Model; pub(super) fn temp_correction(model: &Model, color_temp: usize) -> usize { @@ -13,19 +15,8 @@ pub(super) fn blackbody_deviation(model: &Model, color_temp: usize) -> f64 { // Value for actual color temp (after temp correction) fn blackbody_table(model: &Model) -> BTreeMap { match model { - // 105.455.00 data - Model::TradfriCandle => vec![ - (2170, 0.0028), - (2391, 0.0018), - (2683, 0.0006), - (2990, 0.0006), - (3193, 0.0012), - (3590, 0.003), - (3791, 0.0036), - (3951, 0.0046), - ], // 604.391.68 data - Model::TradfriE27 => vec![ + Model::TradfriE27 | Model::TradfriOther(_) => vec![ (1964, -0.003), (2090, 0.0014), (2668, 0.0015), @@ -61,10 +52,21 @@ fn blackbody_table(model: &Model) -> BTreeMap { (5455, -0.0005), (6495, 0.0014), ], - Model::TradfriOther(_) => todo!(), - Model::Other(_) => todo!(), - Model::TradfriGU10 => todo!(), - Model::TradfriE14White => todo!(), + Model::TradfriGU10 => vec![ + (2112, 0.0032), + (2354, 0.0003), + (2744, -0.0018), + (3109, -0.0023), + (3352, -0.002), + (3826, -0.0002), + (4035, 0.0005), + (4147, 0.0011), + ], + Model::Other(_) => vec![(2500, 0.)], + Model::TradfriCandle | Model::TradfriE14White => { + error!("Trying to color correct for non-color bulb {model:?}"); + vec![(2500, 0.)] + } } .into_iter() .collect() @@ -73,13 +75,15 @@ fn blackbody_table(model: &Model) -> BTreeMap { // Value to add to requested color temp fn temp_table(model: &Model) -> BTreeMap { match model { - Model::TradfriCandle => { - vec![(2200, 30.), (2700, 20.), (4000, 50.)] + // 604.391.68 data + Model::TradfriE27 | Model::TradfriOther(_) => { + vec![(2200, 110.), (2700, 30.), (4000, -110.)] } - Model::TradfriE27 => vec![(2200, 110.), (2700, 30.), (4000, -110.)], + // 204.391.94 data Model::TradfriE14Color => { vec![(2200, 70.), (2700, -40.), (4000, 20.)] } + // A19 Color 9.5W data Model::HueGen4 | Model::HueOther(_) => { vec![ (2200, 2.), @@ -89,10 +93,12 @@ fn temp_table(model: &Model) -> BTreeMap { (6500, 5.), ] } - Model::TradfriOther(_) => todo!(), - Model::Other(_) => todo!(), - Model::TradfriGU10 => todo!(), - Model::TradfriE14White => todo!(), + Model::TradfriGU10 => vec![(2200, -90.), (2700, 40.), (4000, 40.)], + Model::Other(_) => vec![(2500, 0.)], + Model::TradfriCandle | Model::TradfriE14White => { + error!("Trying to color correct for non-color bulb {model:?}"); + vec![(2500, 0.)] + } } .into_iter() .collect() From 8cac4e933324148b616eda5eac0af8d62ad23136 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 14 Jan 2025 15:48:30 +0100 Subject: [PATCH 558/687] Fix color correction --- .../src/lamp/color_correction.rs | 26 +++++++++++-------- crates/zigbee-bridge/src/lamp/model.rs | 25 +++++++++++------- crates/zigbee-bridge/src/lib.rs | 12 ++++----- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/crates/zigbee-bridge/src/lamp/color_correction.rs b/crates/zigbee-bridge/src/lamp/color_correction.rs index ca9f91d7..95c7528c 100644 --- a/crates/zigbee-bridge/src/lamp/color_correction.rs +++ b/crates/zigbee-bridge/src/lamp/color_correction.rs @@ -4,8 +4,8 @@ use tracing::error; use super::Model; -pub(super) fn temp_correction(model: &Model, color_temp: usize) -> usize { - interpolate(color_temp, temp_table(model)).round() as usize +pub(super) fn temp_correction(model: &Model, color_temp: usize) -> isize { + interpolate(color_temp, temp_table(model)).round() as isize } pub(super) fn blackbody_deviation(model: &Model, color_temp: usize) -> f64 { @@ -39,17 +39,20 @@ fn blackbody_table(model: &Model) -> BTreeMap { (3981, 0.0009), (4113, 0.0037), ], - // A19 Color 9.5W data - Model::HueGen4 | Model::HueOther(_) => vec![ + // LCA005 data + Model::HueGen1 | Model::HueGen2 | Model::HueOther(_) => vec![ (1998, 0.0005), (2197, 0.00000), (2519, -0.0004), (2695, -0.0007), - (2849, -0.0011), - (3358, -0.0012), - (3864, -0.012), + (2849, -0.001), + (2990, -0.0011), + (3155, -0.0012), + (3358, -0.0013), + (3633, -0.0012), + (3864, -0.0011), (4010, -0.0009), - (5455, -0.0005), + (5455, 0.0005), (6495, 0.0014), ], Model::TradfriGU10 => vec![ @@ -84,7 +87,7 @@ fn temp_table(model: &Model) -> BTreeMap { vec![(2200, 70.), (2700, -40.), (4000, 20.)] } // A19 Color 9.5W data - Model::HueGen4 | Model::HueOther(_) => { + Model::HueGen1 | Model::HueGen2 | Model::HueOther(_) => { vec![ (2200, 2.), (2700, 5.), @@ -120,8 +123,9 @@ fn interpolate(temp: usize, table: BTreeMap) -> f64 { if let (Some(smaller), Some(larger)) = (smaller, larger) { // Linear interpolation - return temp as f64 * (larger.1 - smaller.1) - / (*larger.0 as f64 - *smaller.0 as f64); + return smaller.1 + + (temp - smaller.0) as f64 * (larger.1 - smaller.1) + / (*larger.0 as f64 - *smaller.0 as f64); } match smaller.or(larger) { diff --git a/crates/zigbee-bridge/src/lamp/model.rs b/crates/zigbee-bridge/src/lamp/model.rs index 48a3df1b..ea26db5a 100644 --- a/crates/zigbee-bridge/src/lamp/model.rs +++ b/crates/zigbee-bridge/src/lamp/model.rs @@ -1,7 +1,4 @@ -use std::{ - collections::HashMap, - ops::Range, -}; +use std::{collections::HashMap, ops::Range}; use tracing::warn; @@ -22,7 +19,13 @@ pub(crate) enum Model { /// LED2101G4 TRADFRI bulb E12/E14, white spectrum, globe, opal, 450/470 lm TradfriE14White, /// 9290012573A Hue white and color ambiance E26/E27/E14 - HueGen4, + /// 600 lm + /// LCT001 + HueGen1, + /// 9290012573A Hue white and color ambiance E26/E27/E14 + /// 800 lm + /// LCT007 + HueGen2, #[allow(unused)] TradfriOther(String), #[allow(unused)] @@ -47,7 +50,8 @@ impl Model { match self { Model::TradfriE27 | Model::TradfriE14Color - | Model::HueGen4 + | Model::HueGen1 + | Model::HueGen2 | Model::TradfriGU10 => true, Model::TradfriCandle | Model::TradfriE14White => false, // We assume no so that things at least don't break @@ -62,7 +66,7 @@ impl Model { Model::TradfriCandle | Model::TradfriGU10 => 2200..4000, Model::TradfriE27 | Model::TradfriE14Color => 1780..4000, Model::TradfriE14White => 2000..4000, - Model::HueGen4 => 2000..6500, + Model::HueGen1 | Model::HueGen2 => 2000..6500, Model::TradfriOther(_) => 2200..4000, Model::HueOther(_) => 2200..6500, Model::Other(_) => 2200..4000, @@ -70,8 +74,9 @@ impl Model { } pub(super) fn color_deviation(&self, color_temp: usize) -> f64 { - let temp = color_temp - + color_correction::temp_correction(&self, color_temp) as usize; + let temp = color_temp.saturating_add_signed( + color_correction::temp_correction(&self, color_temp), + ); color_correction::blackbody_deviation(&self, temp) } @@ -83,7 +88,7 @@ impl Model { | Model::TradfriE14Color | Model::TradfriE14White | Model::TradfriOther(_) => false, - Model::HueGen4 | Model::HueOther(_) => true, + Model::HueGen1 | Model::HueGen2 | Model::HueOther(_) => true, // I guess we default to sending payloads separately Model::Other(_) => false, } diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 3ec19296..44308923 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -21,18 +21,18 @@ const LIGHT_MODELS: [(&str, Model); 16] = [ ("kitchen:hallway", Model::TradfriE27), ("kitchen:hood_left", Model::TradfriCandle), ("kitchen:hood_right", Model::TradfriCandle), - ("kitchen:ceiling", Model::HueGen4), + ("kitchen:ceiling", Model::HueGen1), ("large_bedroom:cabinet", Model::TradfriGU10), ("large_bedroom:ceiling", Model::TradfriE27), ("large_bedroom:desk", Model::TradfriE27), ("large_bedroom:wardrobe", Model::TradfriE27), ("large_bedroom:bed", Model::TradfriE14White), - ("small_bedroom:ceiling", Model::HueGen4), - ("small_bedroom:bureau", Model::HueGen4), - ("small_bedroom:piano", Model::HueGen4), - ("bathroom:ceiling", Model::HueGen4), + ("small_bedroom:ceiling", Model::HueGen1), + ("small_bedroom:bureau", Model::HueGen1), + ("small_bedroom:piano", Model::HueGen1), + ("bathroom:ceiling", Model::HueGen1), ("hallway:ceiling", Model::TradfriE27), - ("toilet:ceiling", Model::HueGen4), + ("toilet:ceiling", Model::HueGen1), ]; const RADIATOR_NAMES: [&str; 2] = ["small_bedroom:radiator", "large_bedroom:radiator"]; From 8a3cefaad131c0ecec62c83cfb58fa8d7811e40c Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 16 Jan 2025 13:01:16 +0100 Subject: [PATCH 559/687] Refactor daylight and temp for SB, tweak values --- .../src/controller/rooms/small_bedroom.rs | 70 +++++++++++++------ 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 03c0afd5..5af8158b 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeMap; +use std::fmt::Debug; use std::time::Duration; use futures_concurrency::future::Race; @@ -128,32 +130,54 @@ pub(super) fn is_nap_time() -> bool { && now < Time::new(20, 0, 0, 0).unwrap() } -pub(super) fn goal_temp_now() -> f64 { - let now = crate::time::now(); - - match time(now.hour(), now.minute()) { - T8_30..T11_00 => 19.0, - T11_00..T13_00 => 20.0, - T13_00..T20_00 => 21.0, - T20_00..T22_00 => 20.0, - T22_00.. | T0_00..T8_30 => 18.0, - _ => 18.0, - } +pub(crate) fn goal_temp_now() -> f64 { + let goals = BTreeMap::from([ + ((00, 00), 18.0), + ((08, 30), 19.0), + ((10, 00), 19.5), + ((11, 00), 20.0), + ((12, 00), 20.5), + ((13, 00), 21.0), + ((20, 00), 20.0), + ((22, 00), 18.0), + ]); + + goal_now(goals, 18.0) } // TODO: move to jobs system and remove update trigger pub(super) fn daylight_now() -> (usize, f64) { - let now = crate::time::now(); - - match time(now.hour(), now.minute()) { - T8_00..T9_00 => (2000, 0.5), - T9_00..T19_00 => (4000, 1.0), - T19_00..T19_30 => (3500, 1.0), - T20_00..T20_30 => (2800, 1.0), - T20_30..T21_00 => (2300, 1.0), - T21_00..T21_30 => (2000, 0.7), - T21_30..T22_00 => (1900, 0.4), - T22_00.. | T0_00..T8_00 => (1800, 0.1), - _ => (2300, 1.0), + let goals = BTreeMap::from([ + ((08, 00), (2000, 0.5)), + ((09, 00), (4000, 1.0)), + ((19, 00), (3800, 1.0)), + ((19, 30), (3600, 1.0)), + ((19, 45), (3300, 1.0)), + ((20, 00), (3000, 1.0)), + ((20, 15), (2500, 1.0)), + ((20, 30), (2000, 1.0)), + ((21, 30), (1900, 0.8)), + ((21, 00), (1800, 0.5)), + ]); + + goal_now(goals, (2300, 1.0)) +} + +fn goal_now(goals: BTreeMap<(i8, i8), T>, default: T) -> T { + let Some(first_goal) = goals.first_key_value() else { + return default; + }; + let mut prev_goal_val = first_goal.1.clone(); + + for ((h, m), goal_val) in goals { + let now = crate::time::now().datetime().time(); + let time = Time::new(h, m, 0, 0).unwrap(); + + if now < time { + return prev_goal_val.clone(); + } + prev_goal_val = goal_val } + + default } From 81ef0c24d694992225fc42e239f07dfcdca256a1 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 16 Jan 2025 13:20:52 +0100 Subject: [PATCH 560/687] Turn hallway lamp auto on and off --- crates/brain/src/controller/mod.rs | 8 +++++ crates/brain/src/controller/rooms/kitchen.rs | 30 ++++++++++++------- .../src/controller/rooms/small_bedroom.rs | 15 ---------- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 750c25e7..f412f0c2 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -73,6 +73,14 @@ impl RestrictedSystem { } } + async fn all_lamps_but_one_on(&mut self, leave_this_off: &str) { + for name in &self.allowed_lights { + if *name != leave_this_off { + self.system.zigbee.set_on(name); + } + } + } + async fn set_radiators_setpoint(&mut self, temperature: f64) { for name in &self.allowed_radiators { self.system.zigbee.set_radiator_setpoint(name, temperature); diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index 4bacdc4b..d3de8f1e 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -2,6 +2,7 @@ use std::time::Duration; use futures_concurrency::future::Race; use futures_util::FutureExt; +use jiff::civil::Time; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; use tracing::warn; @@ -12,6 +13,7 @@ use crate::controller::{Event, RestrictedSystem}; #[derive(PartialEq, Eq)] enum State { Sleep, + Morning, Daylight, } @@ -77,20 +79,24 @@ pub async fn run( match res { Res::Event(RelevantEvent::Sleep) => { state = State::Sleep; - if small_bedroom::is_nap_time() { - system.all_lamps_off().await; + system.all_lamps_off().await; + } + Res::Event(RelevantEvent::Daylight) => { + if is_late_morning() { + state = State::Daylight; + update(&mut system).await; + system.all_lamps_on().await; } else { - system.all_lamps_but_one_off("kitchen:hallway").await; + state = State::Morning; + update(&mut system).await; + system.all_lamps_but_one_on("kitchen:hallway").await; } } - Res::Event(RelevantEvent::Daylight) => { + Res::ShouldUpdate + if state == State::Daylight + || (state == State::Morning && is_late_morning()) => + { state = State::Daylight; - update(&mut system).await; - // TODO: only when LB also awake - // then turn all lamps off when SB sleep - system.all_lamps_on().await; - } - Res::ShouldUpdate if state == State::Daylight => { update(&mut system).await; system.all_lamps_on().await; next_update = Instant::now() + INTERVAL; @@ -100,6 +106,10 @@ pub async fn run( } } +fn is_late_morning() -> bool { + crate::time::now().datetime().time() > Time::new(10, 0, 0, 0).unwrap() +} + async fn update(system: &mut RestrictedSystem) { let (new_ct, new_bri) = small_bedroom::daylight_now(); // let (new_ct, new_bri) = _testing_ct_bri(); diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 5af8158b..9632945e 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -30,22 +30,7 @@ const fn time(hour: i8, minute: i8) -> f64 { hour as f64 + minute as f64 / 60. } const T0_00: f64 = time(0, 0); -const T8_00: f64 = time(8, 0); -const T8_30: f64 = time(8, 30); const T9_00: f64 = time(9, 0); -const T10_30: f64 = time(10, 30); -const T11_00: f64 = time(11, 0); -const T13_00: f64 = time(13, 0); -const T16_00: f64 = time(16, 0); -const T17_00: f64 = time(17, 0); -const T18_00: f64 = time(18, 0); -const T19_00: f64 = time(19, 0); -const T19_30: f64 = time(19, 30); -const T20_00: f64 = time(20, 0); -const T20_30: f64 = time(20, 30); -const T21_00: f64 = time(21, 0); -const T21_30: f64 = time(21, 30); -const T22_00: f64 = time(22, 0); const T23_00: f64 = time(23, 0); pub async fn run( From b5f5ffba5c782f1ff6069c008b7ddc9ad7f2df34 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 16 Jan 2025 21:32:39 +0100 Subject: [PATCH 561/687] hotfix: lamp color time swapped --- crates/brain/src/controller/rooms/small_bedroom.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 9632945e..8dfabb78 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -141,8 +141,8 @@ pub(super) fn daylight_now() -> (usize, f64) { ((20, 00), (3000, 1.0)), ((20, 15), (2500, 1.0)), ((20, 30), (2000, 1.0)), - ((21, 30), (1900, 0.8)), - ((21, 00), (1800, 0.5)), + ((21, 00), (1900, 0.8)), + ((21, 30), (1800, 0.5)), ]); goal_now(goals, (2300, 1.0)) From 047b32accc203db035316e2e6a80faef386c1795 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 17 Jan 2025 18:39:29 +0100 Subject: [PATCH 562/687] text-widget can handle multiple readings --- Cargo.toml | 2 + crates/protocol/src/large_bedroom/bed.rs | 5 +- crates/text-widget/Cargo.toml | 3 +- crates/text-widget/src/cache.rs | 20 ++- crates/text-widget/src/main.rs | 178 +++++++++++++++++------ crates/text-widget/src/resolve.rs | 72 ++++++--- crates/ui/Cargo.toml | 4 +- 7 files changed, 202 insertions(+), 82 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8494f5e6..18b46f88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,8 @@ byteseries = { git = "https://github.com/dvdsk/byteseries", rev="325c7823aa2d04b serde = { version = "1", features = ["derive"], default-features = false } tokio = { version = "1.38", features = ["rt-multi-thread"] } +itertools = { version = "0.14" } +gethostname = "0.5.0" governor = "0.8" color-eyre = "0.6.3" tracing = "0.1.40" diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 87849655..fae5f3c1 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -267,8 +267,9 @@ impl Tree for Reading { } impl_is_same_as! {Reading; Brightness, Temperature, Humidity, GassResistance, Pressure, - Co2, WeightLeft, WeightRight, MassPm1_0, MassPm2_5, MassPm4_0, MassPm10, - TypicalParticleSize; (Self::Button(a), Self::Button(b)) => a.is_same_as(b) + Co2, WeightLeft, WeightRight, MassPm1_0, MassPm2_5, MassPm4_0, MassPm10, NumberPm0_5, + NumberPm1_0, NumberPm2_5, NumberPm4_0, NumberPm10, TypicalParticleSize; + (Self::Button(a), Self::Button(b)) => a.is_same_as(b) } #[derive( diff --git a/crates/text-widget/Cargo.toml b/crates/text-widget/Cargo.toml index 10f8d896..f44a7d82 100644 --- a/crates/text-widget/Cargo.toml +++ b/crates/text-widget/Cargo.toml @@ -14,8 +14,9 @@ data-server = { workspace = true } data-store = { workspace = true } nucleo-matcher = "0.3.1" tokio = { workspace = true} -gethostname = "0.5.0" +gethostname.workspace = true +itertools.workspace = true logger.workspace = true tracing.workspace = true tracing-error.workspace = true diff --git a/crates/text-widget/src/cache.rs b/crates/text-widget/src/cache.rs index 207036a4..a6943135 100644 --- a/crates/text-widget/src/cache.rs +++ b/crates/text-widget/src/cache.rs @@ -7,15 +7,19 @@ use color_eyre::{Result, Section}; use protocol::Reading; use tokio::fs; -pub(crate) async fn store_to_file(reading: Reading, query: String) -> Result<()> { +pub(crate) async fn store_to_file( + fully_qualified: &[Reading], + queries: &[String], +) -> Result<()> { let mut entries = load_entries() .await .wrap_err("Could not load existing cache")? .unwrap_or_default(); - entries.insert(query, reading); - let serialized = - ron::to_string(&entries).wrap_err("Could not serialize query resolve result")?; + entries + .extend(queries.iter().cloned().zip(fully_qualified.iter().cloned())); + let serialized = ron::to_string(&entries) + .wrap_err("Could not serialize query resolve result")?; let path = path()?; fs::write(path, serialized.as_bytes()) @@ -48,10 +52,12 @@ pub(crate) async fn load_entries() -> Result>> { )) } -pub(crate) async fn load_from_file(query: &Query) -> Result> { +pub(crate) async fn load_from_file( + queries: &Vec, +) -> Result>> { let Some(mut entries) = load_entries().await? else { - return Ok(None); + return Ok(queries.iter().map(|_| None).collect()); }; - Ok(entries.remove(query)) + Ok(queries.iter().map(|q| entries.remove(q)).collect()) } diff --git a/crates/text-widget/src/main.rs b/crates/text-widget/src/main.rs index 0cf77d9e..a1c4fd39 100644 --- a/crates/text-widget/src/main.rs +++ b/crates/text-widget/src/main.rs @@ -1,13 +1,16 @@ use color_eyre::eyre::{eyre, Context}; use color_eyre::Result; use data_server::api::subscriber::SubMessage; -use data_server::api::subscriber::{ReconnectingClient, ReconnectingSubscribedClient}; +use data_server::api::subscriber::{ + ReconnectingClient, ReconnectingSubscribedClient, +}; use gethostname::gethostname; +use itertools::Itertools; use protocol::reading::tree::Tree; use protocol::{IsSameAs, Reading}; use std::net::SocketAddr; use std::time::Duration; -use tokio::time::timeout; +use tokio::time::{timeout_at, Instant}; use clap::Parser; @@ -25,44 +28,52 @@ struct Cli { #[arg(long, default_value_t = SocketAddr::from(([127,0,0,1], 1235)))] server: SocketAddr, - /// print json format: {"msg": "reading value"} + /// print json format: {"reading description passed in": "reading value"} #[arg(short, long)] json: bool, + /// print a custom separator between multiple printed values + #[arg(short, long, default_value_t = String::from(" "))] + separator: String, + /// String describing the reading. Something like temp can resolve to /// `large_bedroom desk temperature`. /// /// Run with RUST_LOG=debug to print the resolved string - reading: String, + readings: Vec, } -async fn wait_for_update(client: &mut ReconnectingSubscribedClient, needed: &Reading) -> Reading { +type Index = usize; +async fn wait_for_update( + client: &mut ReconnectingSubscribedClient, + needed: &[Reading], +) -> (Reading, Index) { loop { - let SubMessage::Reading(r) = client.next().await else { + let SubMessage::Reading(update) = client.next().await else { continue; }; - if r.is_same_as(needed) { - return r; + if let Some(idx) = + needed.iter().position(|watched| update.is_same_as(watched)) + { + return (update, idx); } } } -async fn setup(cli: &Cli, client: &mut ReconnectingSubscribedClient) -> Result { - let reading = match resolve::query(cli, client).await { - Ok(reading) => reading, - Err(e) => { - print(cli.json, "E"); - return Err(e); - } - }; - if promptly::prompt_default(format!("Is {reading:?} the correct sensor?"), false) - .wrap_err("Failed to read user confirmation")? - { - cache::store_to_file(reading.clone(), cli.reading.clone()).await?; - Ok(reading) - } else { - Err(eyre!("Exited, user indicated resolved sensor is incorrect")) +async fn setup( + cli: &Cli, + client: &mut ReconnectingSubscribedClient, +) -> Result> { + let available = resolve::available_readings(cli.store, client).await; + let mut fully_qualified = Vec::new(); + for query in &cli.readings { + let reading = resolve::query(&available, query) + .wrap_err("Could not resolve query to reading")?; + fully_qualified.push(reading); } + + cache::store_to_file(&fully_qualified, &cli.readings).await?; + Ok(fully_qualified) } #[tokio::main] @@ -72,45 +83,116 @@ async fn main() -> Result<()> { logger::tracing::setup(); let mut client = ReconnectingClient::new(cli.server, name()).subscribe(); - - let reading = match cache::load_from_file(&cli.reading).await { - Ok(Some(reading)) => reading, - Ok(None) => { - print(cli.json, "RunSetup"); + assert!( + !cli.readings.is_empty(), + "must provide at least one sensor to display" + ); + + let readings = match cache::load_from_file(&cli.readings).await { + Ok(readings) if readings.iter().any(Option::is_none) => { + println!("RunSetup"); setup(&cli, &mut client).await? } + Ok(readings) => readings.into_iter().map(Option::unwrap).collect(), Err(e) => { - print(cli.json, "Error"); - return Err(eyre!("Error, could not load resolved from file: {e:?}")); + println!("Error"); + return Err(eyre!( + "Error, could not load resolved from file: {e:?}" + )); } }; - tracing::debug!("Will be showing: {reading:?}"); - let timeout_dur = reading.leaf().device.info().max_sample_interval + Duration::from_secs(1); + tracing::debug!("Will be showing: {readings:?}"); + let mut next_timeout_at = + tokio::time::Instant::now() + Duration::from_secs(100); + let mut entries: Vec<_> = readings + .iter() + .map(|reading| Entry::new_for(reading)) + .collect(); loop { - let get_update = wait_for_update(&mut client, &reading); - let Ok(new) = timeout(timeout_dur, get_update).await else { - print(cli.json, "X"); - continue; - }; + let get_update = wait_for_update(&mut client, &readings); + if let Ok((new, idx)) = timeout_at(next_timeout_at, get_update).await { + entries[idx].curr_value = Some(new); + entries[idx].last_updated_at = Instant::now(); + } + + for entry in entries.iter_mut().filter(|e| e.curr_value.is_some()) { + if entry.last_updated_at.elapsed() > entry.timeout_interval { + entry.curr_value = None; + } + } - let info = new.leaf(); - let to_print = format!("{0:.1$} {2}", info.val, info.precision(), info.unit); - print(cli.json, &to_print); + if cli.json { + update_stdout_json(&entries, &cli.readings); + } else { + update_stdout(&entries, &cli.separator); + } + + next_timeout_at = Instant::now() + + entries + .iter() + .filter(|Entry { curr_value, .. }| curr_value.is_some()) + .map( + |Entry { + last_updated_at, + timeout_interval, + .. + }| { + timeout_interval + .saturating_sub(last_updated_at.elapsed()) + }, + ) + .min() + .unwrap_or(Duration::from_secs(100)); } } +#[derive(Debug)] +struct Entry { + curr_value: Option, + last_updated_at: Instant, + timeout_interval: Duration, +} + +impl Entry { + fn new_for(reading: &Reading) -> Self { + Self { + curr_value: None, + last_updated_at: Instant::now(), + timeout_interval: reading.leaf().device.info().max_sample_interval + + Duration::from_secs(1), + } + } + + fn format(&self) -> String { + if let Some(reading) = &self.curr_value { + let info = reading.leaf(); + format!("{0:.1$} {2}", info.val, info.precision(), info.unit) + } else { + "X".to_string() + } + } +} + +fn update_stdout_json(entries: &[Entry], used_queries: &[String]) { + let updates = entries.iter().map(|entry| entry.format()); + let json_body = used_queries + .iter() + .zip(updates) + .map(|(query, update)| format!("{query}: {update}")) + .join(", "); + println!("{{ {json_body} }}") +} + +fn update_stdout(entries: &[Entry], separator: &str) { + let mut updates = entries.iter().map(|entry| entry.format()); + let updates: String = updates.join(separator); + println!("{}", updates) +} + fn name() -> String { let host = gethostname(); let host = host.to_string_lossy(); format!("text-widget@{host}") } - -fn print(use_json: bool, msg: &str) { - if use_json { - println!("{{\"msg\": \"{msg}\"}}"); - } else { - println!("{msg}"); - } -} diff --git a/crates/text-widget/src/resolve.rs b/crates/text-widget/src/resolve.rs index fdfb122b..13159388 100644 --- a/crates/text-widget/src/resolve.rs +++ b/crates/text-widget/src/resolve.rs @@ -1,7 +1,9 @@ -use color_eyre::eyre::eyre; +use color_eyre::eyre::{eyre, Context}; use data_server::api::subscriber::ReconnectingSubscribedClient; +use itertools::Itertools; use nucleo_matcher::pattern::Pattern; use protocol::Reading; +use std::net::SocketAddr; use std::time::Duration; use tokio::time::timeout; @@ -9,31 +11,50 @@ use nucleo_matcher::pattern::{AtomKind, CaseMatching, Normalization}; mod fetch; -pub async fn query( - cli: &crate::Cli, +pub async fn available_readings( + store_addr: Option, client: &mut ReconnectingSubscribedClient, -) -> color_eyre::Result { - let mut list = if let Some(store_addr) = cli.store { +) -> Vec { + if let Some(store_addr) = store_addr { fetch::datalist_on_store(store_addr, crate::name()) .await .unwrap_or(Vec::new()) } else { - Vec::new() - }; - if list.is_empty() { + let mut list = Vec::new(); let _ignore_res = timeout( Duration::from_secs(7), fetch::datalist_from_updates(client, &mut list), ) .await; - }; + list + } +} +pub fn query( + list: &[Reading], + reading_query: &str, +) -> color_eyre::Result { tracing::trace!("{:?}", list); - let Some(reading) = resolve_argument(&cli.reading, &list) else { - return Err(eyre!("Could not resolve argument")); + let options = rank_options(&reading_query, &list); + if options.is_empty() { + return Err(eyre!("No idea whats meant by: {reading_query}")); }; - Ok(reading) + for reading in options.into_iter().take(3) { + let reading_path = to_path(&reading); + if promptly::prompt_default( + format!( + "Is {reading_path:?} what you meant with: {reading_query}?" + ), + false, + ) + .wrap_err("Failed to read user confirmation")? + { + return Ok(reading); + } + } + + Err(eyre!("Could not identify reading meant by user")) } fn to_path(reading: &Reading) -> String { @@ -44,33 +65,40 @@ fn to_path(reading: &Reading) -> String { path.replace('(', " ") } -fn resolve_argument(description: &str, options: &[Reading]) -> Option { +fn rank_options(query: &str, options: &[Reading]) -> Vec { + let query = query.replace("_", " ").replace("-", " "); + if options.is_empty() { - return None; + return Vec::new(); } - let mut matcher = nucleo_matcher::Matcher::new(nucleo_matcher::Config::DEFAULT); + let mut matcher = + nucleo_matcher::Matcher::new(nucleo_matcher::Config::DEFAULT); let pattern = Pattern::new( - description, + &query, CaseMatching::Ignore, Normalization::Smart, AtomKind::Fuzzy, ); let mut buf = Vec::new(); - let best_scored = options + options .iter() .map(|r| { ( pattern.score( - nucleo_matcher::Utf32Str::new(to_path(r).as_str(), &mut buf), + nucleo_matcher::Utf32Str::new( + to_path(r).as_str(), + &mut buf, + ), &mut matcher, ), r, ) }) - .max_by_key(|(score, _)| score.unwrap_or(0)) - .unwrap() - .1; - Some(best_scored.clone()) + .filter_map(|(score, reading)| score.zip(Some(reading))) + .sorted_unstable_by_key(|(score, _)| *score) + .rev() + .map(|(_, reading)| reading.clone()) + .collect() } diff --git a/crates/ui/Cargo.toml b/crates/ui/Cargo.toml index c255e72e..c35eddf5 100644 --- a/crates/ui/Cargo.toml +++ b/crates/ui/Cargo.toml @@ -26,8 +26,8 @@ data-store = { workspace = true } log-store = { workspace = true, features = ["api"] } jiff = { workspace = true } thiserror.workspace = true -itertools = "0.14.0" -gethostname = "0.5.0" +itertools.workspace = true +gethostname.workspace = true strip-ansi-escapes = "0.2.0" indextree = "4.7.2" derivative = "2.2.0" From ae56980f2ee3f17a15c8f280ad5f8190ce110eda Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 17 Jan 2025 19:04:41 +0100 Subject: [PATCH 563/687] adds units to json format, fixes json format --- crates/text-widget/src/main.rs | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/crates/text-widget/src/main.rs b/crates/text-widget/src/main.rs index a1c4fd39..b1858d92 100644 --- a/crates/text-widget/src/main.rs +++ b/crates/text-widget/src/main.rs @@ -28,10 +28,16 @@ struct Cli { #[arg(long, default_value_t = SocketAddr::from(([127,0,0,1], 1235)))] server: SocketAddr, - /// print json format: {"reading description passed in": "reading value"} + /// print json format where for each query passed in there are two key value pairs: + /// example for the query `temp`: + /// { "temp": 23.40, "temp-unit": "C" } #[arg(short, long)] json: bool, + /// wipe and redo setup + #[arg(short, long)] + setup: bool, + /// print a custom separator between multiple printed values #[arg(short, long, default_value_t = String::from(" "))] separator: String, @@ -176,11 +182,22 @@ impl Entry { } fn update_stdout_json(entries: &[Entry], used_queries: &[String]) { - let updates = entries.iter().map(|entry| entry.format()); let json_body = used_queries .iter() - .zip(updates) - .map(|(query, update)| format!("{query}: {update}")) + .zip(entries) + .map(|(query, Entry { curr_value, .. })| { + let value = curr_value + .as_ref() + .map(|r| r.leaf()) + .map(|info| format!("{0:.1$}", info.val, info.precision())) + .unwrap_or("X".to_string()); + let unit = curr_value + .as_ref() + .map(|r| r.leaf().unit) + .unwrap_or(protocol::Unit::None); + + format!("\"{query}\": {}, \"{query}-unit\": \"{}\"", value, unit) + }) .join(", "); println!("{{ {json_body} }}") } From ab1b09005d8331178085a4c0e229342b99345c13 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 17 Jan 2025 19:10:19 +0100 Subject: [PATCH 564/687] make it possible to clear resolve cache (re setup) --- crates/text-widget/src/cache.rs | 9 +++++++++ crates/text-widget/src/main.rs | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/crates/text-widget/src/cache.rs b/crates/text-widget/src/cache.rs index a6943135..bc66825e 100644 --- a/crates/text-widget/src/cache.rs +++ b/crates/text-widget/src/cache.rs @@ -61,3 +61,12 @@ pub(crate) async fn load_from_file( Ok(queries.iter().map(|q| entries.remove(q)).collect()) } + +pub(crate) async fn clear() -> Result<()> { + let path = path()?; + match fs::remove_file(path).await { + Ok(()) => Ok(()), + Err(e) if e.kind() == ErrorKind::NotFound => Ok(()), + Err(e) => Err(e).wrap_err("io error"), + } +} diff --git a/crates/text-widget/src/main.rs b/crates/text-widget/src/main.rs index b1858d92..1a166994 100644 --- a/crates/text-widget/src/main.rs +++ b/crates/text-widget/src/main.rs @@ -94,6 +94,10 @@ async fn main() -> Result<()> { "must provide at least one sensor to display" ); + if cli.setup { + cache::clear().await.wrap_err("Could not clear cache")?; + } + let readings = match cache::load_from_file(&cli.readings).await { Ok(readings) if readings.iter().any(Option::is_none) => { println!("RunSetup"); From 6a447b928448fb75fa17689dacb61cfd07bc681b Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 17 Jan 2025 21:39:18 +0100 Subject: [PATCH 565/687] Hotfix the hotfix --- crates/brain/src/controller/rooms/small_bedroom.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 8dfabb78..7850a010 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -119,10 +119,9 @@ pub(crate) fn goal_temp_now() -> f64 { let goals = BTreeMap::from([ ((00, 00), 18.0), ((08, 30), 19.0), - ((10, 00), 19.5), - ((11, 00), 20.0), - ((12, 00), 20.5), - ((13, 00), 21.0), + ((10, 00), 20.0), + ((11, 00), 20.5), + ((12, 00), 21.0), ((20, 00), 20.0), ((22, 00), 18.0), ]); @@ -133,6 +132,7 @@ pub(crate) fn goal_temp_now() -> f64 { // TODO: move to jobs system and remove update trigger pub(super) fn daylight_now() -> (usize, f64) { let goals = BTreeMap::from([ + ((00, 00), (1800, 0.5)), ((08, 00), (2000, 0.5)), ((09, 00), (4000, 1.0)), ((19, 00), (3800, 1.0)), @@ -152,6 +152,7 @@ fn goal_now(goals: BTreeMap<(i8, i8), T>, default: T) -> T { let Some(first_goal) = goals.first_key_value() else { return default; }; + let mut prev_goal_val = first_goal.1.clone(); for ((h, m), goal_val) in goals { @@ -164,5 +165,5 @@ fn goal_now(goals: BTreeMap<(i8, i8), T>, default: T) -> T { prev_goal_val = goal_val } - default + prev_goal_val } From b4a34cf42e1970517df7a407889d59f40f329203 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 18 Jan 2025 12:05:38 +0100 Subject: [PATCH 566/687] add export and import command to data-store --- crates/data-store/src/export.rs | 0 crates/data-store/src/lib.rs | 2 ++ crates/data-store/src/main.rs | 49 +++++++++++++++++++++++++++------ 3 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 crates/data-store/src/export.rs diff --git a/crates/data-store/src/export.rs b/crates/data-store/src/export.rs new file mode 100644 index 00000000..e69de29b diff --git a/crates/data-store/src/lib.rs b/crates/data-store/src/lib.rs index 3ca113c0..f5ca2f49 100644 --- a/crates/data-store/src/lib.rs +++ b/crates/data-store/src/lib.rs @@ -4,3 +4,5 @@ pub mod api; #[cfg(feature = "server")] pub mod server; +#[cfg(feature = "server")] +pub mod export; diff --git a/crates/data-store/src/main.rs b/crates/data-store/src/main.rs index e533a148..ffc5c725 100644 --- a/crates/data-store/src/main.rs +++ b/crates/data-store/src/main.rs @@ -7,19 +7,42 @@ use color_eyre::eyre::Result; #[derive(Parser, Debug)] #[command(name = "data server")] #[command(version = "1.0")] -#[command(about = "Receives sensor events and spreads those to subscribed services")] +#[command( + about = "Receives sensor events and spreads those to subscribed services" +)] struct Cli { - /// data server - #[arg(short, long)] - data_server: SocketAddr, - - #[arg(short, long)] - client_port: u16, + #[command(subcommand)] + command: Command, #[arg(long, default_value = ".")] data_dir: PathBuf, } +#[derive(clap::Subcommand, Debug)] +enum Command { + Run { + /// data server + #[arg(short, long)] + data_server: SocketAddr, + + #[arg(short, long)] + client_port: u16, + }, + Export { + /// export only one dataset + /// at this path this fails. + path: Option, + }, + Import { + /// which dataset to import + /// note a backup is made automatically and needs + /// to be manually removed if you do not want it. + /// + /// If the backup already exists this fails + path: Option, + }, +} + #[tokio::main] async fn main() -> Result<()> { logger::tracing::setup(); @@ -27,5 +50,15 @@ async fn main() -> Result<()> { let cli = Cli::parse(); tracing::info!("started data-server, args: {cli:?}"); - data_store::server::run(cli.data_server, cli.client_port, &cli.data_dir).await + match cli.command { + Command::Run { + data_server, + client_port, + } => { + data_store::server::run(data_server, client_port, &cli.data_dir) + .await + } + Command::Export { .. } => todo!(), + Command::Import { .. } => todo!(), + } } From 2604f186d9aee0f0f875575f39899f696d96a56a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 18 Jan 2025 15:08:38 +0100 Subject: [PATCH 567/687] move data from server/db to own root mod --- .gitignore | 1 - crates/data-store/src/data.rs | 71 +++++++++++++++++++ .../src/{server/db => data}/series.rs | 0 .../src/{server/db => data}/series/bitspec.rs | 0 .../db => data}/series/bitspec/compression.rs | 0 .../db => data}/series/bitspec/field.rs | 0 .../db => data}/series/bitspec/spec.rs | 0 .../{server/db => data}/series/resampler.rs | 0 crates/data-store/src/lib.rs | 2 + crates/data-store/src/server.rs | 14 ++-- crates/data-store/src/server/clients.rs | 2 +- crates/data-store/src/server/db.rs | 64 +---------------- 12 files changed, 83 insertions(+), 71 deletions(-) create mode 100644 crates/data-store/src/data.rs rename crates/data-store/src/{server/db => data}/series.rs (100%) rename crates/data-store/src/{server/db => data}/series/bitspec.rs (100%) rename crates/data-store/src/{server/db => data}/series/bitspec/compression.rs (100%) rename crates/data-store/src/{server/db => data}/series/bitspec/field.rs (100%) rename crates/data-store/src/{server/db => data}/series/bitspec/spec.rs (100%) rename crates/data-store/src/{server/db => data}/series/resampler.rs (100%) diff --git a/.gitignore b/.gitignore index e6d2e70d..9a1c1d59 100644 --- a/.gitignore +++ b/.gitignore @@ -64,7 +64,6 @@ __pycache__ debugToRemoteHost.sh hueBridgeLogin keys/ -data/ releaseToRemoteHost.sh specs/ userdb.hm diff --git a/crates/data-store/src/data.rs b/crates/data-store/src/data.rs new file mode 100644 index 00000000..c71f19a7 --- /dev/null +++ b/crates/data-store/src/data.rs @@ -0,0 +1,71 @@ +use std::collections::HashMap; +use std::net::SocketAddr; +use std::path::Path; +use std::sync::Arc; +use std::time::{Duration, Instant}; + +use color_eyre::{Result, Section}; +use tokio::sync::Mutex; + +pub mod series; +use series::Series; + +use crate::api; + +#[derive(Debug, Clone)] +pub(crate) struct Data( + pub(crate) Arc>>, +); + +impl Data { + pub(crate) async fn list(&self) -> Vec { + self.0 + .lock() + .await + .keys() + .flat_map(|dev| dev.info().affects_readings) + .cloned() + .collect() + } + pub(crate) async fn get( + &self, + reading: protocol::Reading, + start: jiff::Timestamp, + end: jiff::Timestamp, + n: usize, + ) -> Result { + use byteseries::seek::Error as Se; + use byteseries::series::Error as Be; + + let key = reading.device(); + let mut all_series = self.0.lock().await; + let series = all_series.get_mut(&key).ok_or_else(|| { + api::GetDataError::NotInStore { + reading: reading.clone(), + } + })?; + + let (time, mut data) = + series + .read(&[reading], start, end, n) + .map_err(|e| match e { + Be::InvalidRange(Se::NotFound) => { + api::GetDataError::NotFound + } + Be::InvalidRange(Se::EmptyFile) => { + api::GetDataError::EmptyFile + } + Be::InvalidRange(Se::StartAfterData { .. }) => { + api::GetDataError::StartAfterData + } + Be::InvalidRange(Se::StopBeforeData) => { + api::GetDataError::StopBeforeData + } + _ => api::GetDataError::ReadingFromStore(e.to_string()), + })?; + Ok(api::Data { + time, + values: data.pop().expect("one reading is put in so one comes out"), + }) + } +} diff --git a/crates/data-store/src/server/db/series.rs b/crates/data-store/src/data/series.rs similarity index 100% rename from crates/data-store/src/server/db/series.rs rename to crates/data-store/src/data/series.rs diff --git a/crates/data-store/src/server/db/series/bitspec.rs b/crates/data-store/src/data/series/bitspec.rs similarity index 100% rename from crates/data-store/src/server/db/series/bitspec.rs rename to crates/data-store/src/data/series/bitspec.rs diff --git a/crates/data-store/src/server/db/series/bitspec/compression.rs b/crates/data-store/src/data/series/bitspec/compression.rs similarity index 100% rename from crates/data-store/src/server/db/series/bitspec/compression.rs rename to crates/data-store/src/data/series/bitspec/compression.rs diff --git a/crates/data-store/src/server/db/series/bitspec/field.rs b/crates/data-store/src/data/series/bitspec/field.rs similarity index 100% rename from crates/data-store/src/server/db/series/bitspec/field.rs rename to crates/data-store/src/data/series/bitspec/field.rs diff --git a/crates/data-store/src/server/db/series/bitspec/spec.rs b/crates/data-store/src/data/series/bitspec/spec.rs similarity index 100% rename from crates/data-store/src/server/db/series/bitspec/spec.rs rename to crates/data-store/src/data/series/bitspec/spec.rs diff --git a/crates/data-store/src/server/db/series/resampler.rs b/crates/data-store/src/data/series/resampler.rs similarity index 100% rename from crates/data-store/src/server/db/series/resampler.rs rename to crates/data-store/src/data/series/resampler.rs diff --git a/crates/data-store/src/lib.rs b/crates/data-store/src/lib.rs index f5ca2f49..fb10b87d 100644 --- a/crates/data-store/src/lib.rs +++ b/crates/data-store/src/lib.rs @@ -6,3 +6,5 @@ pub mod api; pub mod server; #[cfg(feature = "server")] pub mod export; +#[cfg(feature = "server")] +pub mod data; diff --git a/crates/data-store/src/server.rs b/crates/data-store/src/server.rs index 88d0eb20..7901746f 100644 --- a/crates/data-store/src/server.rs +++ b/crates/data-store/src/server.rs @@ -10,15 +10,15 @@ mod clients; mod db; // used from main and tests -pub async fn run(data_server: SocketAddr, client_port: u16, data_dir: &Path) -> Result<()> { - let data = db::Data(Arc::new(Mutex::new(HashMap::new()))); +pub async fn run( + data_server: SocketAddr, + client_port: u16, + data_dir: &Path, +) -> Result<()> { + let data = crate::data::Data(Arc::new(Mutex::new(HashMap::new()))); let error = ( - db::run( - data_server, - data.clone(), - data_dir, - ), + db::run(data_server, data.clone(), data_dir), clients::handle(client_port, data), ) .race() diff --git a/crates/data-store/src/server/clients.rs b/crates/data-store/src/server/clients.rs index 8cc09f95..4d44b4a0 100644 --- a/crates/data-store/src/server/clients.rs +++ b/crates/data-store/src/server/clients.rs @@ -1,4 +1,4 @@ -use super::db::Data; +use crate::data::Data; use crate::api::{self, ServerError}; pub(crate) async fn handle(port: u16, data: Data) -> color_eyre::Result<()> { diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index c8f0c380..b0b3d419 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -10,10 +10,8 @@ use data_server::api::subscriber::SubMessage; use color_eyre::{Result, Section}; use tokio::sync::Mutex; -mod series; -use series::Series; - use crate::api; +use crate::data::Data; pub(crate) async fn run( data_server_addr: SocketAddr, @@ -31,7 +29,7 @@ pub(crate) async fn run( continue; }; - let res = series::store(&data, &reading, data_dir) + let res = crate::data::series::store(&data, &reading, data_dir) .await .with_note(|| format!("reading: {reading:?}")); @@ -48,61 +46,3 @@ pub(crate) async fn run( } } } - -#[derive(Debug, Clone)] -pub(crate) struct Data( - pub(crate) Arc>>, -); - -impl Data { - pub(crate) async fn list(&self) -> Vec { - self.0 - .lock() - .await - .keys() - .flat_map(|dev| dev.info().affects_readings) - .cloned() - .collect() - } - pub(crate) async fn get( - &self, - reading: protocol::Reading, - start: jiff::Timestamp, - end: jiff::Timestamp, - n: usize, - ) -> Result { - use byteseries::seek::Error as Se; - use byteseries::series::Error as Be; - - let key = reading.device(); - let mut all_series = self.0.lock().await; - let series = all_series.get_mut(&key).ok_or_else(|| { - api::GetDataError::NotInStore { - reading: reading.clone(), - } - })?; - - let (time, mut data) = - series - .read(&[reading], start, end, n) - .map_err(|e| match e { - Be::InvalidRange(Se::NotFound) => { - api::GetDataError::NotFound - } - Be::InvalidRange(Se::EmptyFile) => { - api::GetDataError::EmptyFile - } - Be::InvalidRange(Se::StartAfterData { .. }) => { - api::GetDataError::StartAfterData - } - Be::InvalidRange(Se::StopBeforeData) => { - api::GetDataError::StopBeforeData - } - _ => api::GetDataError::ReadingFromStore(e.to_string()), - })?; - Ok(api::Data { - time, - values: data.pop().expect("one reading is put in so one comes out"), - }) - } -} From c418768e3d8b906e678ab2820eb876ff91788a54 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 18 Jan 2025 15:09:37 +0100 Subject: [PATCH 568/687] fix warnings --- crates/data-store/src/data.rs | 5 +---- crates/data-store/src/data/series/resampler.rs | 2 +- crates/data-store/src/server/db.rs | 4 ---- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/crates/data-store/src/data.rs b/crates/data-store/src/data.rs index c71f19a7..d9e621c2 100644 --- a/crates/data-store/src/data.rs +++ b/crates/data-store/src/data.rs @@ -1,10 +1,7 @@ use std::collections::HashMap; -use std::net::SocketAddr; -use std::path::Path; use std::sync::Arc; -use std::time::{Duration, Instant}; -use color_eyre::{Result, Section}; +use color_eyre::Result; use tokio::sync::Mutex; pub mod series; diff --git a/crates/data-store/src/data/series/resampler.rs b/crates/data-store/src/data/series/resampler.rs index 328b4e3a..8aa0ede3 100644 --- a/crates/data-store/src/data/series/resampler.rs +++ b/crates/data-store/src/data/series/resampler.rs @@ -63,7 +63,7 @@ mod test { )); let readings = reading.device().info().affects_readings; - let specs = crate::server::db::series::to_speclist(readings); + let specs = crate::data::series::to_speclist(readings); let fields = bitspec::speclist_to_fields(specs); let payload_size = fields diff --git a/crates/data-store/src/server/db.rs b/crates/data-store/src/server/db.rs index b0b3d419..3526a2a9 100644 --- a/crates/data-store/src/server/db.rs +++ b/crates/data-store/src/server/db.rs @@ -1,16 +1,12 @@ -use std::collections::HashMap; use std::net::SocketAddr; use std::path::Path; -use std::sync::Arc; use std::time::{Duration, Instant}; use data_server::api::subscriber::ReconnectingClient; use data_server::api::subscriber::SubMessage; use color_eyre::{Result, Section}; -use tokio::sync::Mutex; -use crate::api; use crate::data::Data; pub(crate) async fn run( From 2299b4c3ea0f4d577f2843f10aa0beec54b553f1 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 18 Jan 2025 21:06:53 +0100 Subject: [PATCH 569/687] adds export functionality, writes csv --- crates/data-store/Cargo.toml | 4 +- crates/data-store/src/data.rs | 4 +- crates/data-store/src/data/series.rs | 14 +- .../data-store/src/data/series/resampler.rs | 16 +- crates/data-store/src/export.rs | 227 ++++++++++++++++++ crates/data-store/src/export/csv.rs | 42 ++++ crates/data-store/src/export/decoder.rs | 23 ++ crates/data-store/src/main.rs | 8 +- crates/data-store/src/server/clients.rs | 2 +- 9 files changed, 321 insertions(+), 19 deletions(-) create mode 100644 crates/data-store/src/export/csv.rs create mode 100644 crates/data-store/src/export/decoder.rs diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index 0a725e4c..14860c6e 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -9,7 +9,8 @@ authors.workspace = true [features] api = [] server = [] -default = ["api", "server"] +export = [] +default = ["api", "server", "export"] [dependencies] clap = { workspace = true } @@ -33,6 +34,7 @@ futures.workspace = true smallvec = "2.0.0-alpha.6" num = "0.4.3" ron = "0.8.1" +indicatif = "0.17.9" [dev-dependencies] futures-concurrency = { workspace = true } diff --git a/crates/data-store/src/data.rs b/crates/data-store/src/data.rs index d9e621c2..101a12c9 100644 --- a/crates/data-store/src/data.rs +++ b/crates/data-store/src/data.rs @@ -1,7 +1,6 @@ use std::collections::HashMap; use std::sync::Arc; -use color_eyre::Result; use tokio::sync::Mutex; pub mod series; @@ -15,7 +14,7 @@ pub(crate) struct Data( ); impl Data { - pub(crate) async fn list(&self) -> Vec { + pub(crate) async fn list_readings(&self) -> Vec { self.0 .lock() .await @@ -65,4 +64,5 @@ impl Data { values: data.pop().expect("one reading is put in so one comes out"), }) } + } diff --git a/crates/data-store/src/data/series.rs b/crates/data-store/src/data/series.rs index 3079efa8..6035c434 100644 --- a/crates/data-store/src/data/series.rs +++ b/crates/data-store/src/data/series.rs @@ -15,7 +15,7 @@ use byteseries::file::OpenError as FileOpenError; use series::data::OpenError as DataOpenError; use series::Error::Open; -mod bitspec; +pub mod bitspec; mod resampler; use self::resampler::Resampler; @@ -23,9 +23,9 @@ use self::resampler::Resampler; use super::Data; #[derive(Debug)] -struct Meta { +pub(crate) struct Meta { reading: protocol::Reading, - field: bitspec::Field, + pub(crate) field: bitspec::Field, set_at: Option, } @@ -38,9 +38,9 @@ pub(crate) struct Series { } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] -struct Header { - readings: Vec, - encoding: Vec>, +pub(crate) struct Header { + pub(crate) readings: Vec, + pub(crate) encoding: Vec>, } impl Header { @@ -273,7 +273,7 @@ fn wrap_inder_err( }) } -fn meta_list_and_payload_size( +pub(crate) fn meta_list_and_payload_size( readings: &[protocol::Reading], fields: &[bitspec::Field], ) -> (Vec, usize) { diff --git a/crates/data-store/src/data/series/resampler.rs b/crates/data-store/src/data/series/resampler.rs index 8aa0ede3..401a405a 100644 --- a/crates/data-store/src/data/series/resampler.rs +++ b/crates/data-store/src/data/series/resampler.rs @@ -8,7 +8,10 @@ pub(crate) struct Resampler { } impl Resampler { - pub(crate) fn from_fields(fields: Vec>, payload_size: usize) -> Self { + pub(crate) fn from_fields( + fields: Vec>, + payload_size: usize, + ) -> Self { Self { fields, payload_size, @@ -58,9 +61,11 @@ mod test { #[test] fn decoded_is_correct() { - let reading = protocol::Reading::LargeBedroom(protocol::large_bedroom::Reading::Bed( - protocol::large_bedroom::bed::Reading::Temperature(0.5), - )); + let reading = protocol::Reading::LargeBedroom( + protocol::large_bedroom::Reading::Bed( + protocol::large_bedroom::bed::Reading::Temperature(0.5), + ), + ); let readings = reading.device().info().affects_readings; let specs = crate::data::series::to_speclist(readings); @@ -71,7 +76,8 @@ mod test { .map(|spec| spec.length as usize) .sum::() .div_ceil(8); - let mut resampler = Resampler::from_fields(fields.clone(), payload_size); + let mut resampler = + Resampler::from_fields(fields.clone(), payload_size); let mut item: SmallVec = SmallVec::new(); item.push(0.5f32); item.push(0.5f32); diff --git a/crates/data-store/src/export.rs b/crates/data-store/src/export.rs index e69de29b..91305403 100644 --- a/crates/data-store/src/export.rs +++ b/crates/data-store/src/export.rs @@ -0,0 +1,227 @@ +use std::ffi::OsStr; +use std::fs; +use std::fs::DirEntry; +use std::io::{ErrorKind, Read}; +use std::path::{Path, PathBuf}; + +use byteseries::ByteSeries; +use color_eyre::eyre::{bail, Context, OptionExt, Result}; +use color_eyre::Section; +use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; + +use crate::data::series; + +mod csv; +use csv::Csv; +mod decoder; +use decoder::ExportDecoder; + +pub fn perform(data_dir: &Path, only: Option) -> Result<()> { + let list = files_to_export(data_dir)?; + let to_handle: Vec<_> = list + .into_iter() + .filter(|p| only.as_ref().is_none_or(|allowed| p.ends_with(allowed))) + .collect(); + + let bars = MultiProgress::new(); + let files_bar = + ProgressBar::new(to_handle.len() as u64).with_style(bar_style()); + let files_bar = bars.insert(0, files_bar); + files_bar.inc(0); // make the bar appear + + for path in to_handle { + handle_file(&path, bars.clone()) + .wrap_err("Failed to export data") + .with_note(|| format!("Input file: {}", path.display()))?; + files_bar.inc(1); + } + + Ok(()) +} + +pub fn handle_file(path: &Path, bars: MultiProgress) -> Result<()> { + let metadata = + read_metadata(path).wrap_err("Could not extract metadata")?; + let series::Header { readings, encoding } = + ron::from_str(&metadata).wrap_err("Could not deserialize metadata")?; + let (meta, payload_size) = + series::meta_list_and_payload_size(&readings, &encoding); + + let (input_series, _) = ByteSeries::builder() + .payload_size(payload_size) + .with_header(metadata.as_bytes().to_vec()) + .open(path) + .wrap_err("Could not open byteseries")?; + + let decoder = ExportDecoder::from_fields( + meta.iter().map(|m| m.field.clone()).collect(), + ); + let output = Csv::open(&readings, path.with_extension("csv")) + .wrap_err("Failed to open output csv") + .suggestion("If the file already exists remove it")?; + + let copy_bar = ProgressBar::new(input_series.len()) + .with_style(bar_style()) + .with_message(format!( + "{:?}", + path.file_name().expect("we only handle files with names") + )); + let copy_bar = bars.insert(1, copy_bar); + copy_over_content(input_series, decoder, output, copy_bar.clone()) + .wrap_err("Failed to copy over content")?; + bars.remove(©_bar); + Ok(()) +} + +fn copy_over_content( + mut input_series: ByteSeries, + mut decoder: ExportDecoder, + mut output: Csv, + copy_bar: ProgressBar, +) -> Result<()> { + let mut read_start = 0; + loop { + let mut timestamps = Vec::new(); + let mut data = Vec::new(); + + if let Err(byteseries::series::Error::InvalidRange( + byteseries::seek::Error::StartAfterData { .. }, + )) = input_series.read_first_n( + 100_000, + &mut decoder, + read_start.., + &mut timestamps, + &mut data, + ) { + copy_bar.finish(); + break Ok(()); + } + + let Some(last_ts) = timestamps.last() else { + break Ok(()); // all data consumed + }; + + read_start = *last_ts + 1; + for (ts, line) in timestamps.into_iter().zip(data.into_iter()) { + copy_bar.inc(1); + output + .write_line(ts, &line) + .wrap_err("failed to write line to csv")?; + } + } +} + +fn read_metadata(path: &Path) -> Result { + const HEADER_END: &'static str = "In the case the creator of this \ + file wanted to store metadata in it that\n follows now:"; + + let mut file = fs::File::open(path) + .wrap_err("Could not open file for reading metadata")?; + let mut buf = [0u8; 4000]; + file.read_exact(&mut buf) + .wrap_err("Could not read first 2x bytes")?; + let header = String::from_utf8_lossy(&buf); + let Some((_, metadata_and_rest)) = header.split_once(HEADER_END) else { + bail!("Could not find end of byteseries header") + }; + + let metadata = take_around_parenthesis(metadata_and_rest) + .wrap_err("Could not extract metadata around parenthesis")?; + + Ok(metadata.to_string()) +} + +/// reads till first parenthesis it sees then looks for +/// the corresponding closing one +fn take_around_parenthesis(input: &str) -> Result<&str> { + let start = input.find('(').ok_or_eyre("Missing starting parenthesis")?; + let input = &input[start..]; + + let mut end = None; + let mut depth = 0; + for (idx, char) in input.char_indices() { + match char { + '(' => { + depth += 1; + } + ')' => { + depth -= 1; + if depth == 0 { + end = Some(idx); + break; + } + } + _ => (), + } + } + + let end = end + .ok_or_eyre( + "Could not find matching closing parenthesis before end of input", + ) + .with_note(|| format!("meta was:```\n{}\n```", input))?; + + Ok(&input[..=end]) +} + +fn files_to_export( + data_dir: &Path, +) -> Result, color_eyre::eyre::Error> { + const HEADER_START: &'static str = "This is a byteseries 1 file, an embedded \ + timeseries file. Time may here may\n be whatever value as long as it is \ + monotonically increasing. The entries\n have a fixed length that \ + never changes."; + + let mut buf = [0u8; 300]; + let mut res = Vec::new(); + visit_dirs(data_dir, &mut |entry: &DirEntry| { + if entry.path().extension() == Some(OsStr::new("byteseries")) { + let mut file = + fs::File::open(entry.path()).wrap_err("Could not open file")?; + + match file.read_exact(&mut buf) { + Ok(()) => (), + Err(e) if e.kind() == ErrorKind::UnexpectedEof => return Ok(()), + other => other.wrap_err("Could not read first 300 bytes")?, + } + + let header = String::from_utf8_lossy(&buf); + if header.contains(HEADER_START) { + res.push(entry.path()); + } + } + Ok(()) + }) + .wrap_err("Could not search for byteseries files")?; + Ok(res) +} + +fn visit_dirs( + dir: &Path, + mut cb: &mut dyn FnMut(&DirEntry) -> Result<()>, +) -> Result<()> { + if dir.is_dir() { + for entry in fs::read_dir(dir).wrap_err("Could not read dir")? { + let entry = entry.wrap_err("Error walking dir")?; + let path = entry.path(); + if path.is_dir() { + visit_dirs(&path, &mut cb)?; + } else { + cb(&entry) + .wrap_err("Could not check file header") + .with_note(|| { + format!("file: {}", entry.path().display()) + })?; + } + } + } + Ok(()) +} + +fn bar_style() -> ProgressStyle { + ProgressStyle::with_template( + "[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg} [{eta}]", + ) + .unwrap() + .progress_chars("##-") +} diff --git a/crates/data-store/src/export/csv.rs b/crates/data-store/src/export/csv.rs new file mode 100644 index 00000000..80ae4559 --- /dev/null +++ b/crates/data-store/src/export/csv.rs @@ -0,0 +1,42 @@ +use color_eyre::eyre::Context; +use color_eyre::eyre::Result; + +use std::fs; +use std::io::BufWriter; +use std::io::Write; +use std::path::PathBuf; + +pub(crate) struct Csv { + pub(crate) file: BufWriter, +} + +impl Csv { + pub(crate) fn open( + readings: &[protocol::Reading], + path: PathBuf, + ) -> Result { + let file = fs::OpenOptions::new() + .create_new(true) + .write(true) + .open(path) + .wrap_err("Could not open output csv path")?; + let mut file = BufWriter::new(file); + write!(file, "ts").wrap_err("Could not write header")?; + for reading in readings { + write!(file, "{reading:?},").wrap_err("Could not write header")?; + } + + Ok(Self { file }) + } + + pub(crate) fn write_line(&mut self, ts: u64, line: &[f32]) -> Result<()> { + write!(self.file, "{ts}").wrap_err("Could not write ts to file")?; + for val in line { + write!(self.file, "{val}") + .wrap_err("Could not write float value to file")?; + } + write!(self.file, "\n").wrap_err("Could not write lineend to file")?; + + Ok(()) + } +} diff --git a/crates/data-store/src/export/decoder.rs b/crates/data-store/src/export/decoder.rs new file mode 100644 index 00000000..c0a169e8 --- /dev/null +++ b/crates/data-store/src/export/decoder.rs @@ -0,0 +1,23 @@ +use crate::data::series::bitspec; + +#[derive(Debug, Clone)] +pub(crate) struct ExportDecoder { + pub(crate) fields: Vec>, +} + +impl ExportDecoder { + pub(crate) fn from_fields(fields: Vec>) -> Self { + Self { fields } + } +} + +impl byteseries::Decoder for ExportDecoder { + type Item = smallvec::SmallVec; + + fn decode_payload(&mut self, payload: &[u8]) -> Self::Item { + self.fields + .iter() + .map(|field| field.decode(payload)) + .collect() + } +} diff --git a/crates/data-store/src/main.rs b/crates/data-store/src/main.rs index ffc5c725..0d5ac569 100644 --- a/crates/data-store/src/main.rs +++ b/crates/data-store/src/main.rs @@ -31,7 +31,8 @@ enum Command { Export { /// export only one dataset /// at this path this fails. - path: Option, + #[arg(short, long)] + only: Option, }, Import { /// which dataset to import @@ -39,7 +40,8 @@ enum Command { /// to be manually removed if you do not want it. /// /// If the backup already exists this fails - path: Option, + #[arg(short, long)] + only: Option, }, } @@ -58,7 +60,7 @@ async fn main() -> Result<()> { data_store::server::run(data_server, client_port, &cli.data_dir) .await } - Command::Export { .. } => todo!(), + Command::Export { only } => data_store::export::perform(&cli.data_dir, only), Command::Import { .. } => todo!(), } } diff --git a/crates/data-store/src/server/clients.rs b/crates/data-store/src/server/clients.rs index 4d44b4a0..4919d11a 100644 --- a/crates/data-store/src/server/clients.rs +++ b/crates/data-store/src/server/clients.rs @@ -24,7 +24,7 @@ async fn perform_request_inner( data: Data, ) -> Result { Ok(match request { - api::Request::ListData => api::Response::ListData(data.list().await), + api::Request::ListData => api::Response::ListData(data.list_readings().await), api::Request::GetData { reading, start, From e1aa260aa4e0baf66f113eb25207b180b43b2084 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 19 Jan 2025 16:16:55 +0100 Subject: [PATCH 570/687] add extensive description to bitspec::encode function --- .../src/data/series/bitspec/compression.rs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/crates/data-store/src/data/series/bitspec/compression.rs b/crates/data-store/src/data/series/bitspec/compression.rs index d92e2ddf..e3be2453 100644 --- a/crates/data-store/src/data/series/bitspec/compression.rs +++ b/crates/data-store/src/data/series/bitspec/compression.rs @@ -27,6 +27,62 @@ pub fn decode(line: &[u8], bit_offset: u8, length: u8) -> u32 { #[inline] #[allow(clippy::cast_possible_truncation)] +/// Encode the lower `length` bits of `to_encode` in a zero-ed byte slice +/// starting at the `bit_offset` bit. +/// +/// If `bit_offset` mod 8 is not zero this means we skip the that amount of +/// lower bits in the first byte used for encoding. Inversely +/// if `bit_offset` + `length` mod 8 is not zero that means we only use +/// that amount of lower bits of the last byte. +/// +/// # The first byte +/// Only using the free bits in the first byte is done by first bitmasking on +/// the lower 8 bits of `to_encode`. That mask when AND-ed makes the highest +/// bits zero. Specifically the `bit_offset` mod 8 highest bits are made zero. +/// +/// Then the remaining bits are shifted up such that they fill out the free +/// space in the highest bits of the first byte +/// +/// Example: store 8 bits starting at bit 4: +/// bit_offset: 4, used: 4 mod 8 = 4 +/// length: 8 +/// bits_in_first: 8 - (4 mod 8) = 4 +/// mask: 0b0000_1111 +/// shift: 4 up +/// +/// Example mask, store 4 bits starting at bit 5: +/// bit_offset: 5, used: 5 mod 8 = 5 +/// length: 4 +/// bits_in_first: 8 - (5 mod 8) = 3 +/// mask: 0b0000_0111 # Note how only 3 bits are selected +/// shift: 5 up +/// +/// # The last byte +/// We fit `bit_offest` mod 8 bits in the first byte, lets call that `bits_in_first`. +/// Then N * 8 more in the bytes in between the first and last byte used. This leaves +/// (`length` - `bits_in_first`) mod 8 bits to still encode. These are the highest +/// bits in `to_encode`. We again select them using a mask and AND. +/// +/// This mask is ones for the `bits_in_last` highest bits from `to_encode` and +/// zeros otherwise. Then the bits are shifted all the way down so they fit +/// the lower bits of the last byte in the slice used to store `to_encode`. +/// +/// Example: store 20 bits starting at bit 4 +/// bit_offset: 4 +/// length: 22 +/// bits_in_first: 4 +/// bits_in_last: (length - bits_in_first) mod 8 = 2 +/// mask: 0b0000_0000__0011_0000__0000_0000__0000_0000 +/// shift: 20 down +/// +/// Example: store 7 bits starting at bit 13 +/// bit_offset: 13 +/// length: 7 +/// bits_in_first: 8 - (5 mod 8) = 3 +/// bits_in_last: (length - bits_in_first) mod 8 = 4 +/// mask: 0b0000_0000__0000_0000__0000_0000__0111_1000 +/// shift: 7 down +/// pub fn encode(to_encode: u32, line: &mut [u8], bit_offset: u8, length: u8) { let start_mask = !0 >> (bit_offset % 8); From 20c12c8869377537ec8a3c3ef90625c3429514e0 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 23 Jan 2025 12:07:44 +0100 Subject: [PATCH 571/687] Tweak heating and wakeup SB --- crates/brain/src/controller/rooms/small_bedroom.rs | 5 +++-- crates/brain/src/controller/rooms/small_bedroom/state.rs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 7850a010..cc954c1a 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -122,8 +122,9 @@ pub(crate) fn goal_temp_now() -> f64 { ((10, 00), 20.0), ((11, 00), 20.5), ((12, 00), 21.0), - ((20, 00), 20.0), - ((22, 00), 18.0), + ((21, 00), 20.0), + ((22, 00), 19.0), + ((22, 30), 18.0), ]); goal_now(goals, 18.0) diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index 069c586f..fd5d3684 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -150,7 +150,7 @@ impl Room { } async fn run_wakeup_then_daylight(mut self) { - const LIGHT_NAME: &str = "small_bedroom:piano"; + const LIGHT_NAME: &str = "small_bedroom:ceiling"; const RUNTIME_MINS: i32 = 20; const STEP_SIZE_SECS: i32 = 30; const N_STEPS: i32 = RUNTIME_MINS * 60 / STEP_SIZE_SECS; From 62ecd482a9d9a6cc638658e89634090d51ec599a Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 23 Jan 2025 12:18:35 +0100 Subject: [PATCH 572/687] Add tcp control of air filtration box --- .../src/controller/rooms/small_bedroom.rs | 11 +++++++++++ .../controller/rooms/small_bedroom/state.rs | 18 +++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index cc954c1a..ddf8e01d 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -72,6 +72,7 @@ pub async fn run( } Trigger::Event(RelevantEvent::Wakeup) => room.to_wakeup().await, Trigger::ShouldUpdate => { + room.update_airbox().await; room.update_radiator().await; room.all_lights_daylight().await; next_update = Instant::now() + UPDATE_INTERVAL; @@ -130,6 +131,16 @@ pub(crate) fn goal_temp_now() -> f64 { goal_now(goals, 18.0) } +fn air_filtration_now() -> u16 { + let goals = BTreeMap::from([ + ((00, 00), 70), + ((18, 00), 100), + ((22, 30), 70), + ]); + + goal_now(goals, 80) +} + // TODO: move to jobs system and remove update trigger pub(super) fn daylight_now() -> (usize, f64) { let goals = BTreeMap::from([ diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index fd5d3684..9d301ebf 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -3,14 +3,16 @@ use std::time::Duration; use jiff::{ToSpan, Zoned}; use serde::{Deserialize, Serialize}; +use tokio::io::AsyncWriteExt; +use tokio::net::TcpStream; use tokio::sync::{broadcast, Mutex, RwLock}; use tokio::task::{self, JoinHandle}; use tokio::time::sleep; use tracing::{trace, warn}; use super::{ - daylight_now, goal_temp_now, is_nap_time, NAP_TIME, OFF_DELAY, - RADIATOR_OVERRIDE_MINUTES, + air_filtration_now, daylight_now, goal_temp_now, is_nap_time, NAP_TIME, + OFF_DELAY, RADIATOR_OVERRIDE_MINUTES, }; use crate::controller::{Event, RestrictedSystem}; @@ -49,7 +51,10 @@ impl Room { pub(super) async fn update_radiator(&mut self) { trace!("Updating radiator"); - trace!("Room radiator override state: {:?}", &self.radiator_override); + trace!( + "Room radiator override state: {:?}", + &self.radiator_override + ); if let Some(override_time) = &self.radiator_override { if crate::time::now() <= override_time @@ -196,4 +201,11 @@ impl Room { self.system.all_lamps_ct(new_ct, new_bri).await; } } + + pub(crate) async fn update_airbox(&self) { + if let Ok(mut stream) = TcpStream::connect("192.168.1.103:4444").await { + let message: u16 = 0xDD00 + air_filtration_now(); + let _ = stream.write(&message.to_le_bytes()).await; + } + } } From 7d5a480ef12260abf675e4c555a048923e8f1280 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 25 Jan 2025 13:15:16 +0100 Subject: [PATCH 573/687] Add pm2_5 logic to air filtration SB --- .../src/controller/rooms/small_bedroom.rs | 10 ++++---- .../controller/rooms/small_bedroom/filter.rs | 7 +++++- .../controller/rooms/small_bedroom/state.rs | 25 +++++++++++++++++-- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index ddf8e01d..8e61af55 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -71,6 +71,9 @@ pub async fn run( room.start_radiator_override(); } Trigger::Event(RelevantEvent::Wakeup) => room.to_wakeup().await, + Trigger::Event(RelevantEvent::Pm2_5(val)) => { + room.pm2_5 = Some((val, crate::time::now())) + } Trigger::ShouldUpdate => { room.update_airbox().await; room.update_radiator().await; @@ -132,11 +135,8 @@ pub(crate) fn goal_temp_now() -> f64 { } fn air_filtration_now() -> u16 { - let goals = BTreeMap::from([ - ((00, 00), 70), - ((18, 00), 100), - ((22, 30), 70), - ]); + let goals = + BTreeMap::from([((00, 00), 70), ((18, 00), 100), ((22, 30), 70)]); goal_now(goals, 80) } diff --git a/crates/brain/src/controller/rooms/small_bedroom/filter.rs b/crates/brain/src/controller/rooms/small_bedroom/filter.rs index 09e43531..dd613b6e 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/filter.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/filter.rs @@ -3,6 +3,7 @@ use tracing::{trace, warn}; use crate::controller::Event; use protocol::{ + large_bedroom, small_bedroom::{self, portable_button_panel, radiator}, Reading, }; @@ -19,6 +20,7 @@ pub(super) enum RelevantEvent { PortableButton(portable_button_panel::Reading), Wakeup, RadiatorOverride, + Pm2_5(f32), } pub(super) async fn recv_filtered(event_rx: &mut Receiver) -> Trigger { @@ -32,7 +34,7 @@ pub(super) async fn recv_filtered(event_rx: &mut Receiver) -> Trigger { Err(err) => panic!("{err}"), }; if let Some(relevant) = event_filter(event) { - warn!("SB received relevant event: {relevant:?}"); + trace!("SB received relevant event: {relevant:?}"); return Trigger::Event(relevant); } } @@ -56,6 +58,9 @@ fn event_filter(event: Event) -> Option { None } } + Event::Sensor(Reading::LargeBedroom(large_bedroom::Reading::Bed( + large_bedroom::bed::Reading::MassPm2_5(val), + ))) => Some(RelevantEvent::Pm2_5(val)), Event::WakeupSB => Some(RelevantEvent::Wakeup), _ => None, } diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index 9d301ebf..537922db 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use std::time::Duration; -use jiff::{ToSpan, Zoned}; +use jiff::{Span, ToSpan, Zoned}; use serde::{Deserialize, Serialize}; use tokio::io::AsyncWriteExt; use tokio::net::TcpStream; @@ -30,6 +30,7 @@ pub(crate) enum State { pub(super) struct Room { state: Arc>, radiator_override: Option, + pub(super) pm2_5: Option<(f32, Zoned)>, system: RestrictedSystem, event_tx: broadcast::Sender, task_handle: Arc>>>, @@ -43,6 +44,7 @@ impl Room { Self { state: Arc::new(RwLock::new(State::Daylight)), radiator_override: None, + pm2_5: None, system, event_tx, task_handle: Arc::new(Mutex::new(None)), @@ -203,8 +205,27 @@ impl Room { } pub(crate) async fn update_airbox(&self) { + let pm2_5_expiration = 10.minutes(); if let Ok(mut stream) = TcpStream::connect("192.168.1.103:4444").await { - let message: u16 = 0xDD00 + air_filtration_now(); + let setting = match &self.pm2_5 { + Some((pm2_5, measured_time)) => { + let is_expired = + measured_time.checked_add(pm2_5_expiration).unwrap() + < crate::time::now(); + + if is_expired { + air_filtration_now() + } else { + match pm2_5 { + 0.0..3.0 => 0, + 3.0..4.0 => return, + _ => air_filtration_now(), + } + } + } + None => air_filtration_now(), + }; + let message: u16 = 0xDD00 + setting; let _ = stream.write(&message.to_le_bytes()).await; } } From 58a98e47e94f9449c1e89cad79c6945f11a407ee Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 25 Jan 2025 13:25:47 +0100 Subject: [PATCH 574/687] Move air filtration logic together --- .../src/controller/rooms/small_bedroom.rs | 23 +++++++++++++++-- .../controller/rooms/small_bedroom/state.rs | 25 ++++--------------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 8e61af55..b26b46f1 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -5,6 +5,7 @@ use std::time::Duration; use futures_concurrency::future::Race; use futures_util::FutureExt; use jiff::civil::Time; +use jiff::{ToSpan, Zoned}; use protocol::small_bedroom::{portable_button_panel, ButtonPanel}; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; @@ -134,11 +135,29 @@ pub(crate) fn goal_temp_now() -> f64 { goal_now(goals, 18.0) } -fn air_filtration_now() -> u16 { +fn air_filtration_now(pm2_5_measurement: &Option<(f32, Zoned)>) -> Option { + let pm2_5_expiration = 10.minutes(); let goals = BTreeMap::from([((00, 00), 70), ((18, 00), 100), ((22, 30), 70)]); - goal_now(goals, 80) + let default = goal_now(goals, 80); + + let Some((pm2_5, measured_time)) = pm2_5_measurement else { + return Some(default); + }; + + let is_expired = measured_time.checked_add(pm2_5_expiration).unwrap() + < crate::time::now(); + if is_expired { + Some(default) + } else { + match pm2_5 { + 0.0..3.0 => Some(0), + // Don't change anything + 3.0..4.0 => None, + _ => Some(default), + } + } } // TODO: move to jobs system and remove update trigger diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index 537922db..615cb502 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use std::time::Duration; -use jiff::{Span, ToSpan, Zoned}; +use jiff::{ToSpan, Zoned}; use serde::{Deserialize, Serialize}; use tokio::io::AsyncWriteExt; use tokio::net::TcpStream; @@ -205,26 +205,11 @@ impl Room { } pub(crate) async fn update_airbox(&self) { - let pm2_5_expiration = 10.minutes(); + let Some(setting) = air_filtration_now(&self.pm2_5) else { + return; + }; + if let Ok(mut stream) = TcpStream::connect("192.168.1.103:4444").await { - let setting = match &self.pm2_5 { - Some((pm2_5, measured_time)) => { - let is_expired = - measured_time.checked_add(pm2_5_expiration).unwrap() - < crate::time::now(); - - if is_expired { - air_filtration_now() - } else { - match pm2_5 { - 0.0..3.0 => 0, - 3.0..4.0 => return, - _ => air_filtration_now(), - } - } - } - None => air_filtration_now(), - }; let message: u16 = 0xDD00 + setting; let _ = stream.write(&message.to_le_bytes()).await; } From d26ca5b6df67dd6c5bb56cda6c449c9e91bf86bf Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 1 Feb 2025 12:17:15 +0100 Subject: [PATCH 575/687] Tweak SB values --- crates/brain/src/controller/rooms/small_bedroom.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index b26b46f1..92332481 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -127,9 +127,11 @@ pub(crate) fn goal_temp_now() -> f64 { ((10, 00), 20.0), ((11, 00), 20.5), ((12, 00), 21.0), + ((14, 00), 21.5), + ((20, 30), 21.0), ((21, 00), 20.0), - ((22, 00), 19.0), - ((22, 30), 18.0), + ((21, 30), 19.0), + ((22, 00), 18.0), ]); goal_now(goals, 18.0) @@ -152,9 +154,9 @@ fn air_filtration_now(pm2_5_measurement: &Option<(f32, Zoned)>) -> Option { Some(default) } else { match pm2_5 { - 0.0..3.0 => Some(0), + 0.0..2.0 => Some(0), // Don't change anything - 3.0..4.0 => None, + 2.0..4.0 => None, _ => Some(default), } } From 3a4c44c65a728efe9b4366ccbdc51b9385b8622b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 2 Feb 2025 21:19:42 +0100 Subject: [PATCH 576/687] disable misbehaving radiator control + add logging to rad contrl --- crates/brain/src/controller/mod.rs | 6 +++--- crates/brain/src/controller/rooms/small_bedroom.rs | 3 ++- crates/brain/src/controller/rooms/small_bedroom/state.rs | 5 +++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index f412f0c2..fea3c925 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -82,9 +82,9 @@ impl RestrictedSystem { } async fn set_radiators_setpoint(&mut self, temperature: f64) { - for name in &self.allowed_radiators { - self.system.zigbee.set_radiator_setpoint(name, temperature); - } + // for name in &self.allowed_radiators { + // self.system.zigbee.set_radiator_setpoint(name, temperature); + // } } } diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 92332481..d2d33423 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -9,7 +9,7 @@ use jiff::{ToSpan, Zoned}; use protocol::small_bedroom::{portable_button_panel, ButtonPanel}; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; -use tracing::trace; +use tracing::{debug, trace}; use self::filter::{recv_filtered, RelevantEvent, Trigger}; use self::state::Room; @@ -102,6 +102,7 @@ async fn handle_buttonpress(room: &mut Room, event: RelevantEvent) { use crate::time; let now = time::now(); match time(now.hour(), now.minute()) { + // rust analyzer seems to think this illegal, its not T23_00.. | T0_00..T9_00 => room.to_nightlight().await, _ => room.to_daylight().await, } diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index 615cb502..25c956da 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -69,8 +69,9 @@ impl Room { warn!("Radiator override is expired, resetting"); } } - trace!("Override is either not set or expired, set to goal temp"); - self.system.set_radiators_setpoint(goal_temp_now()).await; + let goal_temp = goal_temp_now(); + trace!("Override is either not set or expired, set to goal temp: {goal_temp}"); + self.system.set_radiators_setpoint(goal_temp).await; self.radiator_override = None; } From 5f85a9ed0b37cf89e102ef71caccb31654364395 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 4 Feb 2025 14:29:23 +0100 Subject: [PATCH 577/687] Fix text-widget not compiling because of clap arg --- crates/text-widget/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/text-widget/src/main.rs b/crates/text-widget/src/main.rs index 1a166994..ad824016 100644 --- a/crates/text-widget/src/main.rs +++ b/crates/text-widget/src/main.rs @@ -39,7 +39,7 @@ struct Cli { setup: bool, /// print a custom separator between multiple printed values - #[arg(short, long, default_value_t = String::from(" "))] + #[arg(short = 'd', long, default_value_t = String::from(" "))] separator: String, /// String describing the reading. Something like temp can resolve to From 67775e52b67bcfb262bfd458f24fbabb2a4547a3 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 4 Feb 2025 14:33:11 +0100 Subject: [PATCH 578/687] Fix parse error for portable button panel Z2M sends null sometimes for some reason --- crates/zigbee-bridge/src/parse.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/zigbee-bridge/src/parse.rs b/crates/zigbee-bridge/src/parse.rs index c1f86c3f..5728fecb 100644 --- a/crates/zigbee-bridge/src/parse.rs +++ b/crates/zigbee-bridge/src/parse.rs @@ -50,7 +50,12 @@ pub(crate) fn portable_button_panel( ]; if device_name == "small_bedroom:portable_button_panel" { - map.get("action") + let action = map.get("action"); + // Ignore when it is Null for some reason + if action == Some(&Value::Null) { + return Ok(None); + } + action .map(json_to_str) .transpose()? .map(|action| { From baa84110c719a54c65ead8b116e4a24cd8fe6564 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 4 Feb 2025 14:33:41 +0100 Subject: [PATCH 579/687] Disable radiator override and re-enable setting --- crates/brain/src/controller/mod.rs | 6 ++-- .../src/controller/rooms/small_bedroom.rs | 6 ++-- .../controller/rooms/small_bedroom/state.rs | 34 +++++++++---------- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index fea3c925..f412f0c2 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -82,9 +82,9 @@ impl RestrictedSystem { } async fn set_radiators_setpoint(&mut self, temperature: f64) { - // for name in &self.allowed_radiators { - // self.system.zigbee.set_radiator_setpoint(name, temperature); - // } + for name in &self.allowed_radiators { + self.system.zigbee.set_radiator_setpoint(name, temperature); + } } } diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index d2d33423..104c0440 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -68,8 +68,8 @@ pub async fn run( handle_buttonpress(&mut room, event).await; } Trigger::Event(RelevantEvent::RadiatorOverride) => { - trace!("Starting radiator override"); - room.start_radiator_override(); + // trace!("Starting radiator override"); + // room.start_radiator_override(); } Trigger::Event(RelevantEvent::Wakeup) => room.to_wakeup().await, Trigger::Event(RelevantEvent::Pm2_5(val)) => { @@ -128,8 +128,6 @@ pub(crate) fn goal_temp_now() -> f64 { ((10, 00), 20.0), ((11, 00), 20.5), ((12, 00), 21.0), - ((14, 00), 21.5), - ((20, 30), 21.0), ((21, 00), 20.0), ((21, 30), 19.0), ((22, 00), 18.0), diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index 25c956da..ca1b51bb 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -53,24 +53,24 @@ impl Room { pub(super) async fn update_radiator(&mut self) { trace!("Updating radiator"); - trace!( - "Room radiator override state: {:?}", - &self.radiator_override - ); - if let Some(override_time) = &self.radiator_override { - if crate::time::now() - <= override_time - .checked_add(RADIATOR_OVERRIDE_MINUTES.minute()) - .unwrap() - { - trace!("Override is set and not expired, do nothing"); - return; - } else { - warn!("Radiator override is expired, resetting"); - } - } + // trace!( + // "Room radiator override state: {:?}", + // &self.radiator_override + // ); + // if let Some(override_time) = &self.radiator_override { + // if crate::time::now() + // <= override_time + // .checked_add(RADIATOR_OVERRIDE_MINUTES.minute()) + // .unwrap() + // { + // trace!("Override is set and not expired, do nothing"); + // return; + // } else { + // warn!("Radiator override is expired, resetting"); + // } + // } let goal_temp = goal_temp_now(); - trace!("Override is either not set or expired, set to goal temp: {goal_temp}"); + // trace!("Override is either not set or expired, set to goal temp: {goal_temp}"); self.system.set_radiators_setpoint(goal_temp).await; self.radiator_override = None; } From 08032af689dc49063bb51f088730ec619c9d5f31 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 6 Feb 2025 18:47:11 +0100 Subject: [PATCH 580/687] Fix log errors originating from portable buttons --- crates/zigbee-bridge/src/cached_bridge/poll.rs | 4 +++- crates/zigbee-bridge/src/parse.rs | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/zigbee-bridge/src/cached_bridge/poll.rs b/crates/zigbee-bridge/src/cached_bridge/poll.rs index 8f65c813..0d465e24 100644 --- a/crates/zigbee-bridge/src/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/cached_bridge/poll.rs @@ -61,7 +61,9 @@ async fn update_state( ) { let mut known_states = known_states.write().await; let Some(current_device) = known_states.get_mut(device_name) else { - error!("Trying to update state for unknown device {device_name}, ignoring!"); + if device_name != "small_bedroom:portable_button_panel" { + error!("Trying to update state for unknown device {device_name}, ignoring!"); + } return; }; trace!("applying properties"); diff --git a/crates/zigbee-bridge/src/parse.rs b/crates/zigbee-bridge/src/parse.rs index 5728fecb..f435383c 100644 --- a/crates/zigbee-bridge/src/parse.rs +++ b/crates/zigbee-bridge/src/parse.rs @@ -52,7 +52,10 @@ pub(crate) fn portable_button_panel( if device_name == "small_bedroom:portable_button_panel" { let action = map.get("action"); // Ignore when it is Null for some reason - if action == Some(&Value::Null) { + // or an empty string...... + if action == Some(&Value::Null) + || action == Some(&Value::String("".to_string())) + { return Ok(None); } action From 4fa09f906d922cc0b703eb1fc4d856595c09e72d Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 7 Feb 2025 12:05:04 +0100 Subject: [PATCH 581/687] Fix another portable button error --- crates/zigbee-bridge/src/cached_bridge/poll.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/zigbee-bridge/src/cached_bridge/poll.rs b/crates/zigbee-bridge/src/cached_bridge/poll.rs index 0d465e24..59df0080 100644 --- a/crates/zigbee-bridge/src/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/cached_bridge/poll.rs @@ -198,7 +198,9 @@ fn online_message(device_name: String, is_online: bool) -> Message { readings: Vec::new(), } } else { - error!("Unknown device name {device_name}, could not parse log"); + if device_name != "small_bedroom:portable_button_panel" { + error!("Unknown device name {device_name}, could not parse log"); + } Message::Irrelevant } } From 5ae6fc7f4de4980a54d43ad8440d014e26fa993e Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 11 Feb 2025 14:56:36 +0100 Subject: [PATCH 582/687] Send all z2m set commands twice --- crates/zigbee-bridge/src/cached_bridge/mqtt.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/zigbee-bridge/src/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/cached_bridge/mqtt.rs index 1b699c85..ea15c562 100644 --- a/crates/zigbee-bridge/src/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/cached_bridge/mqtt.rs @@ -109,6 +109,9 @@ impl Mqtt { self.set(device_name, payload.to_string()).await?; } else { for change in due_changes { + // Send twice because... issues + self.set(device_name, change.payload().to_string()).await?; + sleep(MIN_TIME_BETWEEN_SENDS).await; self.set(device_name, change.payload().to_string()).await?; sleep(MIN_TIME_BETWEEN_SENDS).await; } From 859d3afb501140115fa5ca795ab4a81d51a2edff Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 14 Feb 2025 17:27:40 +0100 Subject: [PATCH 583/687] piano lamp replaced with tradfri --- crates/zigbee-bridge/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 44308923..34a3cb43 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -29,7 +29,7 @@ const LIGHT_MODELS: [(&str, Model); 16] = [ ("large_bedroom:bed", Model::TradfriE14White), ("small_bedroom:ceiling", Model::HueGen1), ("small_bedroom:bureau", Model::HueGen1), - ("small_bedroom:piano", Model::HueGen1), + ("small_bedroom:piano", Model::TradfriE27), ("bathroom:ceiling", Model::HueGen1), ("hallway:ceiling", Model::TradfriE27), ("toilet:ceiling", Model::HueGen1), From 5bce0bf9fd1a21ba8a74e634d914530a4ad4b79f Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 15 Feb 2025 12:16:02 +0100 Subject: [PATCH 584/687] Add info to error --- crates/zigbee-bridge/src/parse.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/zigbee-bridge/src/parse.rs b/crates/zigbee-bridge/src/parse.rs index f435383c..617c4255 100644 --- a/crates/zigbee-bridge/src/parse.rs +++ b/crates/zigbee-bridge/src/parse.rs @@ -182,6 +182,7 @@ fn parse_radiator_properties( .map(|s| { s.as_str() .ok_or_eyre("Setpoint change source not a string") + .with_note(|| format!("Received: {s}")) .map(|s| s.parse().unwrap()) }) .transpose()? From c6f449e275364b347d1367266907e65649cc6783 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 17 Feb 2025 16:05:05 +0100 Subject: [PATCH 585/687] Add wakeup override to SB --- .../src/controller/rooms/small_bedroom.rs | 19 +++++++++++-------- .../controller/rooms/small_bedroom/state.rs | 16 +++++++++++++--- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 104c0440..3155d448 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -90,15 +90,18 @@ async fn handle_buttonpress(room: &mut Room, event: RelevantEvent) { use ButtonPanel as B; use RelevantEvent as E; + // Dots1 short: to sleep -> lights off + // Dots1 long: to nightlight always -> one lamp on + // + // Dots2 short: to nightlight at night, otherwise daylight -> lamp(s) on + // Dots2 long: to sleep, wakeup off -> lights off match event { - E::Button(B::BottomLeft(_)) => { - room.to_sleep_delayed().await; - } - E::PortableButton(P::Dots1InitialPress) => { + E::Button(B::BottomLeft(_)) => room.to_sleep_delayed().await, + E::PortableButton(P::Dots1ShortRelease) => { room.to_sleep_immediate().await } E::Button(B::BottomMiddle(_)) - | E::PortableButton(P::Dots2InitialPress) => { + | E::PortableButton(P::Dots2ShortRelease) => { use crate::time; let now = time::now(); match time(now.hour(), now.minute()) { @@ -107,9 +110,9 @@ async fn handle_buttonpress(room: &mut Room, event: RelevantEvent) { _ => room.to_daylight().await, } } - E::Button(B::BOttomRight(_)) => { - room.to_override().await; - } + E::Button(B::BOttomRight(_)) => room.to_override().await, + E::PortableButton(P::Dots2LongRelease) => room.to_sleep_no_wakeup().await, + E::PortableButton(P::Dots1LongRelease) => room.to_nightlight().await, _ => (), } } diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index ca1b51bb..3480e2b5 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use std::time::Duration; -use jiff::{ToSpan, Zoned}; +use jiff::Zoned; use serde::{Deserialize, Serialize}; use tokio::io::AsyncWriteExt; use tokio::net::TcpStream; @@ -12,13 +12,14 @@ use tracing::{trace, warn}; use super::{ air_filtration_now, daylight_now, goal_temp_now, is_nap_time, NAP_TIME, - OFF_DELAY, RADIATOR_OVERRIDE_MINUTES, + OFF_DELAY, }; use crate::controller::{Event, RestrictedSystem}; #[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)] pub(crate) enum State { Sleep, + SleepNoWakeup, Wakeup, Daylight, Override, @@ -86,7 +87,12 @@ impl Room { pub(super) async fn to_sleep_immediate(&mut self) { self.system.all_lamps_off().await; - self.to_state(State::Sleep).await; + self.to_state_cancel_prev(State::Sleep).await; + } + + pub(super) async fn to_sleep_no_wakeup(&mut self) { + self.system.all_lamps_off().await; + self.to_state_cancel_prev(State::SleepNoWakeup).await; } pub(super) async fn to_sleep_delayed(&mut self) { @@ -100,6 +106,10 @@ impl Room { } pub(super) async fn to_wakeup(&mut self) { + if *self.state.read().await == State::SleepNoWakeup { + warn!("Ignoring wakeup because of override"); + return; + } warn!("Starting wakeup"); self.to_state_cancel_prev(State::Wakeup).await; From 030feee8def9f19acddfef2029a8f428013b357d Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 17 Feb 2025 16:07:29 +0100 Subject: [PATCH 586/687] Add simple daylight behaviour room for entrance --- crates/brain/src/controller/mod.rs | 19 +++++++---- crates/brain/src/controller/rooms.rs | 1 + crates/brain/src/controller/rooms/entrance.rs | 34 +++++++++++++++++++ 3 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 crates/brain/src/controller/rooms/entrance.rs diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index f412f0c2..3c885647 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -89,13 +89,13 @@ impl RestrictedSystem { } pub fn start( - subscribed: [broadcast::Receiver; 3], + subscribed: [broadcast::Receiver; 4], sender: broadcast::Sender, system: System, ) -> JoinSet<()> { tracing::info!("starting"); let mut tasks = JoinSet::new(); - let [rx1, rx2, rx3] = subscribed; + let [rx1, rx2, rx3, rx4] = subscribed; let restricted = RestrictedSystem { system: system.clone(), @@ -132,11 +132,18 @@ pub fn start( ], allowed_radiators: vec![], }; - tasks.spawn(rooms::kitchen::run(rx3, sender, restricted)); + tasks.spawn(rooms::kitchen::run(rx3, sender.clone(), restricted)); - // "hallway:ceiling" - // "bathroom:ceiling" - // "toilet:ceiling" + let restricted = RestrictedSystem { + system: system.clone(), + allowed_lights: vec![ + "hallway:ceiling", + "bathroom:ceiling", + "toilet:ceiling", + ], + allowed_radiators: vec![], + }; + tasks.spawn(rooms::entrance::run(rx4, sender, restricted)); tasks } diff --git a/crates/brain/src/controller/rooms.rs b/crates/brain/src/controller/rooms.rs index b45791b7..0375837a 100644 --- a/crates/brain/src/controller/rooms.rs +++ b/crates/brain/src/controller/rooms.rs @@ -1,3 +1,4 @@ pub mod large_bedroom; pub mod small_bedroom; pub mod kitchen; +pub mod entrance; diff --git a/crates/brain/src/controller/rooms/entrance.rs b/crates/brain/src/controller/rooms/entrance.rs new file mode 100644 index 00000000..4568077c --- /dev/null +++ b/crates/brain/src/controller/rooms/entrance.rs @@ -0,0 +1,34 @@ +use std::time::Duration; + +use tokio::sync::broadcast; +use tokio::time::{sleep_until, Instant}; + +use crate::controller::rooms::small_bedroom; +use crate::controller::{Event, RestrictedSystem}; + +const INTERVAL: Duration = Duration::from_secs(5); + +pub async fn run( + mut _event_rx: broadcast::Receiver, + // todo if state change message everyone using this + _event_tx: broadcast::Sender, + mut system: RestrictedSystem, +) { + + let mut next_update = Instant::now() + INTERVAL; + loop { + sleep_until(next_update).await; + + update(&mut system).await; + system.all_lamps_on().await; + + next_update = Instant::now() + INTERVAL; + } +} + +async fn update(system: &mut RestrictedSystem) { + let (new_ct, new_bri) = small_bedroom::daylight_now(); + let new_bri = new_bri.clamp(0.8, 1.0); + system.all_lamps_ct(new_ct, new_bri).await; + tracing::trace!("updated lamps"); +} From 793392b4b8b5cd8b8589ec7a06aa075aafa1c816 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 17 Feb 2025 16:11:08 +0100 Subject: [PATCH 587/687] Update lamp models --- crates/zigbee-bridge/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index 44308923..b68dc33b 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -21,7 +21,7 @@ const LIGHT_MODELS: [(&str, Model); 16] = [ ("kitchen:hallway", Model::TradfriE27), ("kitchen:hood_left", Model::TradfriCandle), ("kitchen:hood_right", Model::TradfriCandle), - ("kitchen:ceiling", Model::HueGen1), + ("kitchen:ceiling", Model::TradfriE27), ("large_bedroom:cabinet", Model::TradfriGU10), ("large_bedroom:ceiling", Model::TradfriE27), ("large_bedroom:desk", Model::TradfriE27), @@ -29,10 +29,10 @@ const LIGHT_MODELS: [(&str, Model); 16] = [ ("large_bedroom:bed", Model::TradfriE14White), ("small_bedroom:ceiling", Model::HueGen1), ("small_bedroom:bureau", Model::HueGen1), - ("small_bedroom:piano", Model::HueGen1), + ("small_bedroom:piano", Model::TradfriE27), ("bathroom:ceiling", Model::HueGen1), ("hallway:ceiling", Model::TradfriE27), - ("toilet:ceiling", Model::HueGen1), + ("toilet:ceiling", Model::HueGen2), ]; const RADIATOR_NAMES: [&str; 2] = ["small_bedroom:radiator", "large_bedroom:radiator"]; From 22347a296c02d9fd81a47a8c5316b528fa2c5437 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 20 Feb 2025 14:31:04 +0100 Subject: [PATCH 588/687] Add Sleep behaviour to entrance --- crates/brain/src/controller/rooms/entrance.rs | 81 +++++++++++++++++-- crates/brain/src/controller/rooms/kitchen.rs | 4 +- 2 files changed, 78 insertions(+), 7 deletions(-) diff --git a/crates/brain/src/controller/rooms/entrance.rs b/crates/brain/src/controller/rooms/entrance.rs index 4568077c..8b3fdcc3 100644 --- a/crates/brain/src/controller/rooms/entrance.rs +++ b/crates/brain/src/controller/rooms/entrance.rs @@ -1,5 +1,7 @@ use std::time::Duration; +use futures::FutureExt; +use futures_concurrency::future::Race; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; @@ -8,21 +10,90 @@ use crate::controller::{Event, RestrictedSystem}; const INTERVAL: Duration = Duration::from_secs(5); +#[derive(PartialEq, Eq)] +enum State { + Sleep, + Daylight, +} + +// TODO: deduplicate filter code with kitchen +trait RecvFiltered { + async fn recv_filter_mapped( + &mut self, + filter_map: impl Fn(Event) -> Option, + ) -> T; +} + +impl RecvFiltered for broadcast::Receiver { + async fn recv_filter_mapped( + &mut self, + filter_map: impl Fn(Event) -> Option, + ) -> T { + loop { + let event = self.recv().await.unwrap(); + if let Some(relevant) = filter_map(event) { + return relevant; + } + } + } +} + +#[derive(Debug)] +enum RelevantEvent { + Sleep, + Daylight, +} + +fn filter(event: Event) -> Option { + match event { + Event::StateChangeSB(small_bedroom::State::Sleep) => { + Some(RelevantEvent::Sleep) + } + Event::StateChangeSB(small_bedroom::State::Daylight) => { + Some(RelevantEvent::Daylight) + } + _ => None, + } +} + pub async fn run( - mut _event_rx: broadcast::Receiver, + mut event_rx: broadcast::Receiver, // todo if state change message everyone using this _event_tx: broadcast::Sender, mut system: RestrictedSystem, ) { + enum Res { + Event(RelevantEvent), + ShouldUpdate, + } + let mut state = State::Daylight; let mut next_update = Instant::now() + INTERVAL; loop { - sleep_until(next_update).await; + let get_event = event_rx.recv_filter_mapped(filter).map(Res::Event); + let tick = sleep_until(next_update).map(|_| Res::ShouldUpdate); + + let res = (get_event, tick).race().await; + match res { + Res::Event(RelevantEvent::Sleep) => { + state = State::Sleep; + system.one_lamp_off("hallway:ceiling").await; + } + Res::Event(RelevantEvent::Daylight) => { + state = State::Daylight; - update(&mut system).await; - system.all_lamps_on().await; + update(&mut system).await; + system.all_lamps_on().await; + } + Res::ShouldUpdate => { + if state == State::Daylight { + update(&mut system).await; + system.all_lamps_on().await; - next_update = Instant::now() + INTERVAL; + next_update = Instant::now() + INTERVAL; + } + } + } } } diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index d3de8f1e..b64f903b 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -10,6 +10,8 @@ use tracing::warn; use crate::controller::rooms::small_bedroom; use crate::controller::{Event, RestrictedSystem}; +const INTERVAL: Duration = Duration::from_secs(5); + #[derive(PartialEq, Eq)] enum State { Sleep, @@ -17,8 +19,6 @@ enum State { Daylight, } -const INTERVAL: Duration = Duration::from_secs(5); - trait RecvFiltered { async fn recv_filter_mapped( &mut self, From 8ebd24a7b6a0a9fd9f374a87bce0c3d09e4818d6 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 28 Feb 2025 11:42:09 +0100 Subject: [PATCH 589/687] Tweak lights and SB temperature --- crates/brain/src/controller/rooms/small_bedroom.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 3155d448..8f278e31 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -131,6 +131,7 @@ pub(crate) fn goal_temp_now() -> f64 { ((10, 00), 20.0), ((11, 00), 20.5), ((12, 00), 21.0), + ((20, 00), 20.5), ((21, 00), 20.0), ((21, 30), 19.0), ((22, 00), 18.0), @@ -169,11 +170,11 @@ pub(super) fn daylight_now() -> (usize, f64) { let goals = BTreeMap::from([ ((00, 00), (1800, 0.5)), ((08, 00), (2000, 0.5)), - ((09, 00), (4000, 1.0)), - ((19, 00), (3800, 1.0)), - ((19, 30), (3600, 1.0)), - ((19, 45), (3300, 1.0)), - ((20, 00), (3000, 1.0)), + ((09, 00), (3800, 1.0)), + ((19, 00), (3600, 1.0)), + ((19, 30), (3300, 1.0)), + ((19, 45), (3000, 1.0)), + ((20, 00), (2800, 1.0)), ((20, 15), (2500, 1.0)), ((20, 30), (2000, 1.0)), ((21, 00), (1900, 0.8)), From 6f24776110dee19e8b6bfac053c8c2628b5c67ea Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 8 Mar 2025 11:59:41 +0100 Subject: [PATCH 590/687] Tweak airbox speed and decouple from LB sensor --- crates/brain/src/controller/rooms/small_bedroom.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 8f278e31..81ccf453 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -143,7 +143,7 @@ pub(crate) fn goal_temp_now() -> f64 { fn air_filtration_now(pm2_5_measurement: &Option<(f32, Zoned)>) -> Option { let pm2_5_expiration = 10.minutes(); let goals = - BTreeMap::from([((00, 00), 70), ((18, 00), 100), ((22, 30), 70)]); + BTreeMap::from([((00, 00), 80), ((18, 00), 100), ((22, 30), 80)]); let default = goal_now(goals, 80); @@ -157,9 +157,9 @@ fn air_filtration_now(pm2_5_measurement: &Option<(f32, Zoned)>) -> Option { Some(default) } else { match pm2_5 { - 0.0..2.0 => Some(0), - // Don't change anything - 2.0..4.0 => None, + // 0.0..2.0 => Some(0), + // // Don't change anything + // 2.0..4.0 => None, _ => Some(default), } } From c14de313631e8f1e6ea734eef565788dde3c3b1c Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 8 Mar 2025 12:03:24 +0100 Subject: [PATCH 591/687] Add 1h delay to wakeup on Sunday --- crates/brain/src/controller/rooms/small_bedroom/state.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index 3480e2b5..0489ea9d 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use std::time::Duration; +use jiff::civil::Weekday; use jiff::Zoned; use serde::{Deserialize, Serialize}; use tokio::io::AsyncWriteExt; @@ -182,6 +183,10 @@ impl Room { let ct_growth = (END_CT as f64 / START_CT as f64).powf(1. / N_STEPS as f64); + if crate::time::now().weekday() == Weekday::Sunday { + // On Sunday, delay wakeup one hour + sleep(Duration::from_secs(60 * 60)).await; + } self.system .one_lamp_ct(LIGHT_NAME, START_CT, START_BRI) .await; From 134a946a9d47f53db935772153bab93bef381429 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 14 Feb 2025 17:28:18 +0100 Subject: [PATCH 592/687] better docs / refactor (broken) --- .../src/data/series/bitspec/compression.rs | 68 +++++++++++++++---- 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/crates/data-store/src/data/series/bitspec/compression.rs b/crates/data-store/src/data/series/bitspec/compression.rs index e3be2453..9cb6ba84 100644 --- a/crates/data-store/src/data/series/bitspec/compression.rs +++ b/crates/data-store/src/data/series/bitspec/compression.rs @@ -1,17 +1,33 @@ +/// ```txt +/// array's with bytes in them follow Little Endian byte order +/// (not relevant) to the algo but might be nice to know. It can +/// get a little confusing given the lowest bit is printed right most +/// given these strange bit 1 is next to bit 16 situations. See diagram: +/// +/// byte 1 byte 2 byte 3 +/// [ 8|7|6|5|4|3|2|1, 16|15|14|13|12|11|10|9, 24|23|22|21|20|19|18|17 ] +/// |____________________________________________| +/// |________| encoded B +/// encoded lower part of B higher part of B +/// value stored in lower part stored in higher +/// A of byte 1 part of byte 3 +/// ``` + #[inline] #[allow(clippy::cast_possible_truncation)] +/// Decodes `length` bytes starting at `bit_offset` from `line`. pub fn decode(line: &[u8], bit_offset: u8, length: u8) -> u32 { let start_byte = (bit_offset / 8) as usize; - let stop_byte = ((bit_offset + length) / 8) as usize; + // build mask to get lowest bits of first byte let start_mask: u8 = !0 >> (bit_offset % 8); - let used_bits = bit_offset + length - stop_byte as u8 * 8; - let stop_mask = !(!0 >> used_bits); //decode first bit (never needs shifting (lowest part is used)) let mut decoded: u32 = u32::from(line[start_byte] & start_mask); let mut bits_read = 8 - (bit_offset % 8); + //if we have more bits + let stop_byte = ((bit_offset + length) / 8) as usize; if length > 8 { //decode middle bits, no masking needed for byte in &line[start_byte + 1..stop_byte] { @@ -19,8 +35,15 @@ pub fn decode(line: &[u8], bit_offset: u8, length: u8) -> u32 { bits_read += 8; } } - let stop_byte = ((bit_offset + length).div_ceil(8) - 1) as usize; //starts at 0 - decoded |= u32::from(line[stop_byte] & stop_mask) << (bits_read - (8 - used_bits)); + + // build mask to get highest bits of last byte + let bits_still_needed = length - bits_read; + let stop_mask = !(!0 >> bits_still_needed); + + let stop_byte2 = ((bit_offset + length).div_ceil(8) - 1) as usize; //starts at 0 + assert_eq!(stop_byte2, stop_byte, "{bit_offset}, {length}"); + decoded |= + u32::from(line[stop_byte2] & stop_mask) << (bits_read - (8 - bits_still_needed)); decoded } @@ -31,14 +54,15 @@ pub fn decode(line: &[u8], bit_offset: u8, length: u8) -> u32 { /// starting at the `bit_offset` bit. /// /// If `bit_offset` mod 8 is not zero this means we skip the that amount of -/// lower bits in the first byte used for encoding. Inversely +/// higher bits in the first byte used for encoding. Inversely /// if `bit_offset` + `length` mod 8 is not zero that means we only use /// that amount of lower bits of the last byte. /// /// # The first byte -/// Only using the free bits in the first byte is done by first bitmasking on -/// the lower 8 bits of `to_encode`. That mask when AND-ed makes the highest -/// bits zero. Specifically the `bit_offset` mod 8 highest bits are made zero. +/// Only using the free lower bits in the first byte is done by masking off +/// the higher part of the lower 8 bits of `to_encode`. That mask when AND-ed +/// makes the highest bits zero. Specifically the `bit_offset` mod 8 highest +/// bits are made zero. /// /// Then the remaining bits are shifted up such that they fill out the free /// space in the highest bits of the first byte @@ -104,7 +128,8 @@ pub fn encode(to_encode: u32, line: &mut [u8], bit_offset: u8, length: u8) { let used_bits = bit_offset + length - stop_byte as u8 * 8; let stop_mask = !(!0 >> used_bits); let stop_byte = (bit_offset + length).div_ceil(8) as usize; //starts at 0 - line[stop_byte - 1] |= (to_encode >> (bits_written - (8 - used_bits))) as u8 & stop_mask; + line[stop_byte - 1] |= + (to_encode >> (bits_written - (8 - used_bits))) as u8 & stop_mask; } #[cfg(test)] @@ -193,11 +218,23 @@ mod tests { let mut array = vec![0; 12]; let test_numb1 = 2f32.powf(power1) as u32; let test_numb2 = 2f32.powf(power2) as u32; - encode(test_numb1, array.as_mut_slice(), offset, length); - encode(test_numb2, array.as_mut_slice(), offset + length, length); + encode( + test_numb1, + array.as_mut_slice(), + offset, + length, + ); + encode( + test_numb2, + array.as_mut_slice(), + offset + length, + length, + ); - let decoded_test_numb1 = decode(array.as_slice(), offset, length); - let decoded_test_numb2 = decode(array.as_slice(), offset + length, length); + let decoded_test_numb1 = + decode(array.as_slice(), offset, length); + let decoded_test_numb2 = + decode(array.as_slice(), offset + length, length); assert_eq!( test_numb1, decoded_test_numb1, "\n##### numb:1, \noffset: {},\nlength: {}, \nvalue1: {}, \nvalue2: {}", @@ -237,7 +274,8 @@ mod tests { let test_numb = 2f32.powf(power) as u32; encode(test_numb, array.as_mut_slice(), offset, length); - let decoded_test_numb = decode(array.as_slice(), offset, length); + let decoded_test_numb = + decode(array.as_slice(), offset, length); assert_eq!( test_numb, decoded_test_numb, From 63c469234fc4a3e8a26b53aaa2e63ea7ef9d2f4b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 19 Feb 2025 17:55:12 +0100 Subject: [PATCH 593/687] renames, better export error handling --- crates/data-store/Cargo.toml | 1 + .../src/data/series/bitspec/compression.rs | 43 +++++++++++-------- crates/data-store/src/export.rs | 40 +++++++++++++++-- crates/data-store/src/export/csv.rs | 6 ++- 4 files changed, 66 insertions(+), 24 deletions(-) diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index 14860c6e..9e09ed90 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -35,6 +35,7 @@ smallvec = "2.0.0-alpha.6" num = "0.4.3" ron = "0.8.1" indicatif = "0.17.9" +itertools.workspace = true [dev-dependencies] futures-concurrency = { workspace = true } diff --git a/crates/data-store/src/data/series/bitspec/compression.rs b/crates/data-store/src/data/series/bitspec/compression.rs index 9cb6ba84..04c7ffa0 100644 --- a/crates/data-store/src/data/series/bitspec/compression.rs +++ b/crates/data-store/src/data/series/bitspec/compression.rs @@ -17,20 +17,20 @@ #[allow(clippy::cast_possible_truncation)] /// Decodes `length` bytes starting at `bit_offset` from `line`. pub fn decode(line: &[u8], bit_offset: u8, length: u8) -> u32 { - let start_byte = (bit_offset / 8) as usize; + let first_byte = (bit_offset / 8) as usize; // build mask to get lowest bits of first byte let start_mask: u8 = !0 >> (bit_offset % 8); //decode first bit (never needs shifting (lowest part is used)) - let mut decoded: u32 = u32::from(line[start_byte] & start_mask); + let mut decoded: u32 = u32::from(line[first_byte] & start_mask); let mut bits_read = 8 - (bit_offset % 8); - //if we have more bits - let stop_byte = ((bit_offset + length) / 8) as usize; + let last_byte_new = ((bit_offset + length).div_ceil(8)) as usize; + let last_byte_idx = last_byte_new - 1; if length > 8 { //decode middle bits, no masking needed - for byte in &line[start_byte + 1..stop_byte] { + for byte in &line[first_byte + 1..last_byte_idx] { decoded |= u32::from(*byte) << bits_read; bits_read += 8; } @@ -38,12 +38,15 @@ pub fn decode(line: &[u8], bit_offset: u8, length: u8) -> u32 { // build mask to get highest bits of last byte let bits_still_needed = length - bits_read; - let stop_mask = !(!0 >> bits_still_needed); + // shifting 8 bits to get mask 0b1111_1111 panics with `u8` + let end_mask = if bits_still_needed == 8 { + 0b1111_1111 + } else { + !(!0 >> bits_still_needed) + }; - let stop_byte2 = ((bit_offset + length).div_ceil(8) - 1) as usize; //starts at 0 - assert_eq!(stop_byte2, stop_byte, "{bit_offset}, {length}"); - decoded |= - u32::from(line[stop_byte2] & stop_mask) << (bits_read - (8 - bits_still_needed)); + decoded |= u32::from(line[last_byte_idx] & end_mask) + << (bits_read - (8 - bits_still_needed)); decoded } @@ -110,26 +113,28 @@ pub fn decode(line: &[u8], bit_offset: u8, length: u8) -> u32 { pub fn encode(to_encode: u32, line: &mut [u8], bit_offset: u8, length: u8) { let start_mask = !0 >> (bit_offset % 8); - let start_byte = (bit_offset / 8) as usize; - let stop_byte = ((bit_offset + length) / 8) as usize; + let first_byte = (bit_offset / 8) as usize; //encode first bit (never needs shifting (lowest part is used)) - line[start_byte] |= (to_encode as u8) & start_mask; + line[first_byte] |= (to_encode as u8) & start_mask; let mut bits_written = 8 - (bit_offset % 8); + // this writes the last bit too when the offset + length is a multiple of 8 + // that is okay since then the byte is full used so no masking is needed. + let last_byte = ((bit_offset + length) / 8) as usize; if length > 8 { //decode middle bits, no masking needed - for byte in &mut line[start_byte + 1..stop_byte] { + for byte in &mut line[first_byte + 1..last_byte] { *byte |= (to_encode >> bits_written) as u8; bits_written += 8; } } - let used_bits = bit_offset + length - stop_byte as u8 * 8; - let stop_mask = !(!0 >> used_bits); - let stop_byte = (bit_offset + length).div_ceil(8) as usize; //starts at 0 - line[stop_byte - 1] |= - (to_encode >> (bits_written - (8 - used_bits))) as u8 & stop_mask; + let used_bits = bit_offset + length - last_byte as u8 * 8; + let end_mask = !(!0 >> used_bits); + let last_byte = (bit_offset + length).div_ceil(8) as usize; //starts at 0 + line[last_byte - 1] |= + (to_encode >> (bits_written - (8 - used_bits))) as u8 & end_mask; } #[cfg(test)] diff --git a/crates/data-store/src/export.rs b/crates/data-store/src/export.rs index 91305403..9a0a2cdb 100644 --- a/crates/data-store/src/export.rs +++ b/crates/data-store/src/export.rs @@ -6,8 +6,9 @@ use std::path::{Path, PathBuf}; use byteseries::ByteSeries; use color_eyre::eyre::{bail, Context, OptionExt, Result}; -use color_eyre::Section; +use color_eyre::{Report, Section}; use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; +use itertools::Itertools; use crate::data::series; @@ -18,11 +19,23 @@ use decoder::ExportDecoder; pub fn perform(data_dir: &Path, only: Option) -> Result<()> { let list = files_to_export(data_dir)?; + if list.is_empty() { + bail!("No files left to export") + } + let to_handle: Vec<_> = list - .into_iter() - .filter(|p| only.as_ref().is_none_or(|allowed| p.ends_with(allowed))) + .iter() + .filter(|p| { + only.as_ref().is_none_or(|allowed| { + p.ends_with(allowed) || p.with_extension("").ends_with(allowed) + }) + }) .collect(); + if to_handle.is_empty() { + return no_filter_match_err(list, only); + } + let bars = MultiProgress::new(); let files_bar = ProgressBar::new(to_handle.len() as u64).with_style(bar_style()); @@ -39,6 +52,27 @@ pub fn perform(data_dir: &Path, only: Option) -> Result<()> { Ok(()) } +fn no_filter_match_err( + list: Vec, + only: Option, +) -> Result<(), Report> { + return Err(Report::msg( + "None of the paths ended with required argument", + )) + .with_note(|| { + format!("filter argument (--only) {}", only.unwrap().display()) + }) + .with_note(|| { + format!( + "examples of files: \n\t- {}", + list.iter() + .map(|p| p.display().to_string()) + .take(5) + .join("\n\t- ") + ) + }); +} + pub fn handle_file(path: &Path, bars: MultiProgress) -> Result<()> { let metadata = read_metadata(path).wrap_err("Could not extract metadata")?; diff --git a/crates/data-store/src/export/csv.rs b/crates/data-store/src/export/csv.rs index 80ae4559..71b5a90e 100644 --- a/crates/data-store/src/export/csv.rs +++ b/crates/data-store/src/export/csv.rs @@ -1,5 +1,6 @@ use color_eyre::eyre::Context; use color_eyre::eyre::Result; +use color_eyre::Section; use std::fs; use std::io::BufWriter; @@ -18,8 +19,9 @@ impl Csv { let file = fs::OpenOptions::new() .create_new(true) .write(true) - .open(path) - .wrap_err("Could not open output csv path")?; + .open(&path) + .wrap_err("Could not open output csv path") + .with_note(|| format!("csv path: {}", path.display()))?; let mut file = BufWriter::new(file); write!(file, "ts").wrap_err("Could not write header")?; for reading in readings { From 95a0c4a0d2e40fa45d7877cd446e786523ea9e81 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 19 Feb 2025 17:55:27 +0100 Subject: [PATCH 594/687] adds test script for reproducing bug --- crates/data-store/test.sh | 2 ++ 1 file changed, 2 insertions(+) create mode 100755 crates/data-store/test.sh diff --git a/crates/data-store/test.sh b/crates/data-store/test.sh new file mode 100755 index 00000000..7e8a294e --- /dev/null +++ b/crates/data-store/test.sh @@ -0,0 +1,2 @@ +rm data/smallbedroom/radiator/radiator.csv +cargo r -- --data-dir data export --only smallbedroom/radiator/radiator From 572d46246d508cab90a3081474db160083d35ab2 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 5 Mar 2025 15:24:24 +0100 Subject: [PATCH 595/687] fixes compression algorithm for lengths < 8bits --- crates/data-store/Cargo.toml | 4 +- crates/data-store/src/data/series.rs | 1 + .../src/data/series/bitspec/compression.rs | 125 ++++++++++-------- crates/data-store/src/export.rs | 9 +- crates/data-store/test.sh | 4 + 5 files changed, 85 insertions(+), 58 deletions(-) diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index 9e09ed90..92b8c72b 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -25,7 +25,8 @@ rpc = { workspace = true } protocol = { workspace = true, features = ["alloc", "thiserror"] } data-server = { workspace = true } -byteseries = { workspace = true } +# byteseries = { workspace = true } +byteseries = { path = "/home/david/Documents/byteseries" } tokio = { workspace = true, features = ["fs", "net", "rt-multi-thread", "sync"] } futures-concurrency = { workspace = true } serde.workspace = true @@ -36,6 +37,7 @@ num = "0.4.3" ron = "0.8.1" indicatif = "0.17.9" itertools.workspace = true +rstest = "0.24.0" [dev-dependencies] futures-concurrency = { workspace = true } diff --git a/crates/data-store/src/data/series.rs b/crates/data-store/src/data/series.rs index 6035c434..c8cc9fe8 100644 --- a/crates/data-store/src/data/series.rs +++ b/crates/data-store/src/data/series.rs @@ -221,6 +221,7 @@ impl Series { &mut resampler, &mut timestamps, &mut interleaved_data, + false, )?; let time = timestamps diff --git a/crates/data-store/src/data/series/bitspec/compression.rs b/crates/data-store/src/data/series/bitspec/compression.rs index 04c7ffa0..12d0e5bb 100644 --- a/crates/data-store/src/data/series/bitspec/compression.rs +++ b/crates/data-store/src/data/series/bitspec/compression.rs @@ -11,6 +11,8 @@ /// encoded lower part of B higher part of B /// value stored in lower part stored in higher /// A of byte 1 part of byte 3 +/// +/// B: length = 16, offest = 4, at byte 3 bits read = 12 /// ``` #[inline] @@ -21,10 +23,16 @@ pub fn decode(line: &[u8], bit_offset: u8, length: u8) -> u32 { // build mask to get lowest bits of first byte let start_mask: u8 = !0 >> (bit_offset % 8); + // second mask for sources with length smaller then 8 bits + let start_mask = if length < (bit_offset % 8) { + start_mask & !(!0 << length) + } else { + start_mask + }; //decode first bit (never needs shifting (lowest part is used)) let mut decoded: u32 = u32::from(line[first_byte] & start_mask); - let mut bits_read = 8 - (bit_offset % 8); + let mut bits_read = (8 - (bit_offset % 8)).min(length); let last_byte_new = ((bit_offset + length).div_ceil(8)) as usize; let last_byte_idx = last_byte_new - 1; @@ -45,8 +53,12 @@ pub fn decode(line: &[u8], bit_offset: u8, length: u8) -> u32 { !(!0 >> bits_still_needed) }; - decoded |= u32::from(line[last_byte_idx] & end_mask) - << (bits_read - (8 - bits_still_needed)); + // let bits_in_last_byte = bits_still_needed; + let shift_back = 8 - bits_still_needed; + let shift_in_position = bits_read; + + decoded |= u32::from(line[last_byte_idx] & end_mask) >> shift_back + << shift_in_position; decoded } @@ -117,7 +129,7 @@ pub fn encode(to_encode: u32, line: &mut [u8], bit_offset: u8, length: u8) { //encode first bit (never needs shifting (lowest part is used)) line[first_byte] |= (to_encode as u8) & start_mask; - let mut bits_written = 8 - (bit_offset % 8); + let mut bits_written = (8 - (bit_offset % 8)).min(length); // this writes the last bit too when the offset + length is a multiple of 8 // that is okay since then the byte is full used so no masking is needed. @@ -133,12 +145,34 @@ pub fn encode(to_encode: u32, line: &mut [u8], bit_offset: u8, length: u8) { let used_bits = bit_offset + length - last_byte as u8 * 8; let end_mask = !(!0 >> used_bits); let last_byte = (bit_offset + length).div_ceil(8) as usize; //starts at 0 - line[last_byte - 1] |= - (to_encode >> (bits_written - (8 - used_bits))) as u8 & end_mask; + + if bits_written < length { + // lets say to_encode is: 1100_0000_0000 + // and that 11 still needs to be encoded (bits written = 10, length = 12) + // then we should shift them all the way down (shift 10) and then up into + // the place where they are stored in the last byte. In this case the upper + // 2 bits. So shift back up 6. Total shift is 4 down/right or: + // + // bits_written 10 - (8 - bits to use in last byte) + // + // now if we encode is: 11 + // and only the left most (higher) 1 still needs to be encoded. But it + // will need to be encoded in the highest bit in the next byte. So it + // must be shifted 7 up/left. + let to_shift = bits_written as i16 - (8 - used_bits as i16); + if to_shift > 0 { + line[last_byte - 1] |= (to_encode >> to_shift) as u8 & end_mask; + } else { + line[last_byte - 1] |= + (to_encode << to_shift.abs()) as u8 & end_mask; + } + } } #[cfg(test)] mod tests { + use rstest::rstest; + use super::*; #[test] @@ -211,52 +245,21 @@ mod tests { assert_eq!(decoded1, test_case); } - #[test] - #[ignore = "takes 10 secs to run"] - fn encode_and_decode_multiple() { - for length in 8..33 { - for offset in 0..16 { - for _power1 in 0..length as u16 * 10 { - for _power2 in 0..length as u16 * 10 { - let power1 = _power1 as f32 * 0.1; - let power2 = _power2 as f32 * 0.1; - let mut array = vec![0; 12]; - let test_numb1 = 2f32.powf(power1) as u32; - let test_numb2 = 2f32.powf(power2) as u32; - encode( - test_numb1, - array.as_mut_slice(), - offset, - length, - ); - encode( - test_numb2, - array.as_mut_slice(), - offset + length, - length, - ); - - let decoded_test_numb1 = - decode(array.as_slice(), offset, length); - let decoded_test_numb2 = - decode(array.as_slice(), offset + length, length); - assert_eq!( - test_numb1, decoded_test_numb1, - "\n##### numb:1, \noffset: {},\nlength: {}, \nvalue1: {}, \nvalue2: {}", - offset, length, test_numb1, test_numb2 - ); - assert_eq!( - test_numb2, - decoded_test_numb2, - "\n##### numb:2, \noffset: {},\nlength: {}, \nvalue1: {}, \nvalue2: {}", - offset + length, - length, - test_numb1, - test_numb2 - ); - } - } - } + #[rstest] + fn encode_and_decode_max( + #[values(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)] + length: u8, + ) { + // > 2 bytes + for offset in 0..=16 { + let max_we_can_store = 2u32.pow(length as u32 - 1); + + let mut array = vec![0; 12]; + encode(max_we_can_store, array.as_mut_slice(), offset, length); + let decoded = decode(array.as_slice(), offset, length); + + assert_eq!(max_we_can_store, decoded, "should decode {max_we_can_store}, got {decoded}, \noffset: {offset},\nlength: {length}" + ); } } @@ -270,7 +273,7 @@ mod tests { } #[test] - fn encode_and_decode() { + fn encode_and_decode_various_numbers() { for length in 8..32 { for offset in 0..16 { for _power in 0..length as u16 * 10 { @@ -293,4 +296,20 @@ mod tests { } } } + + #[test] + fn edge_case_1() { + let line = [206, 84, 2, 0]; + let offset = 13; + let length = 7; + decode(&line, offset, length); + } + + #[test] + fn edge_case_2() { + let line = [206, 84, 2, 0]; + let offset = 20; + let length = 2; + decode(&line, offset, length); + } } diff --git a/crates/data-store/src/export.rs b/crates/data-store/src/export.rs index 9a0a2cdb..a597ec1c 100644 --- a/crates/data-store/src/export.rs +++ b/crates/data-store/src/export.rs @@ -149,11 +149,12 @@ fn read_metadata(path: &Path) -> Result { const HEADER_END: &'static str = "In the case the creator of this \ file wanted to store metadata in it that\n follows now:"; - let mut file = fs::File::open(path) + let file = fs::File::open(path) .wrap_err("Could not open file for reading metadata")?; - let mut buf = [0u8; 4000]; - file.read_exact(&mut buf) - .wrap_err("Could not read first 2x bytes")?; + let mut buf = Vec::with_capacity(12_000); + file.take(12_000) + .read_to_end(&mut buf) + .wrap_err("Could not read first 12_000 bytes or end")?; let header = String::from_utf8_lossy(&buf); let Some((_, metadata_and_rest)) = header.split_once(HEADER_END) else { bail!("Could not find end of byteseries header") diff --git a/crates/data-store/test.sh b/crates/data-store/test.sh index 7e8a294e..0e3c6fba 100755 --- a/crates/data-store/test.sh +++ b/crates/data-store/test.sh @@ -1,2 +1,6 @@ rm data/smallbedroom/radiator/radiator.csv cargo r -- --data-dir data export --only smallbedroom/radiator/radiator + + +# rm data/smallbedroom/radiator/radiator.csv +# cargo r -- --data-dir data export --only smallbedroom/radiator/radiator From 97545ab4ceb9689efe5b04e14b965b3ea2c26cee Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 17 Mar 2025 15:45:04 +0100 Subject: [PATCH 596/687] adds import command --- crates/data-store/src/data/series.rs | 6 +- crates/data-store/src/export.rs | 114 ++++++------ crates/data-store/src/export/csv.rs | 19 +- crates/data-store/src/import.rs | 260 +++++++++++++++++++++++++++ crates/data-store/src/lib.rs | 65 ++++++- crates/data-store/src/main.rs | 22 ++- 6 files changed, 406 insertions(+), 80 deletions(-) create mode 100644 crates/data-store/src/import.rs diff --git a/crates/data-store/src/data/series.rs b/crates/data-store/src/data/series.rs index c8cc9fe8..976252a4 100644 --- a/crates/data-store/src/data/series.rs +++ b/crates/data-store/src/data/series.rs @@ -24,7 +24,7 @@ use super::Data; #[derive(Debug)] pub(crate) struct Meta { - reading: protocol::Reading, + pub(crate) reading: protocol::Reading, pub(crate) field: bitspec::Field, set_at: Option, } @@ -44,7 +44,7 @@ pub(crate) struct Header { } impl Header { - fn serialized(&self) -> Result> { + pub(crate) fn serialized(&self) -> Result> { let config = ron::ser::PrettyConfig::new(); ron::ser::to_string_pretty(self, config) .map(|s| s.into_bytes()) @@ -351,7 +351,7 @@ pub(crate) async fn store( Ok(()) } -fn to_speclist(readings: &[protocol::Reading]) -> Vec { +pub(crate) fn to_speclist(readings: &[protocol::Reading]) -> Vec { readings .iter() .map(|r| bitspec::RangeWithRes { diff --git a/crates/data-store/src/export.rs b/crates/data-store/src/export.rs index a597ec1c..ff59ee41 100644 --- a/crates/data-store/src/export.rs +++ b/crates/data-store/src/export.rs @@ -3,12 +3,17 @@ use std::fs; use std::fs::DirEntry; use std::io::{ErrorKind, Read}; use std::path::{Path, PathBuf}; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; use byteseries::ByteSeries; use color_eyre::eyre::{bail, Context, OptionExt, Result}; -use color_eyre::{Report, Section}; -use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; +use color_eyre::Section; +use indicatif::{MultiProgress, ProgressBar}; use itertools::Itertools; +use protocol::reading::tree::Tree; +use protocol::Reading; +use tracing::warn; use crate::data::series; @@ -33,44 +38,30 @@ pub fn perform(data_dir: &Path, only: Option) -> Result<()> { .collect(); if to_handle.is_empty() { - return no_filter_match_err(list, only); + return crate::no_filter_match_err(list, only); } let bars = MultiProgress::new(); let files_bar = - ProgressBar::new(to_handle.len() as u64).with_style(bar_style()); + ProgressBar::new(to_handle.len() as u64).with_style(crate::bar_style()); let files_bar = bars.insert(0, files_bar); files_bar.inc(0); // make the bar appear - for path in to_handle { + for path in &to_handle { handle_file(&path, bars.clone()) .wrap_err("Failed to export data") .with_note(|| format!("Input file: {}", path.display()))?; files_bar.inc(1); } - Ok(()) -} + drop(bars); + tracing::info!( + "Done, exported {} files to {}", + to_handle.len(), + data_dir.display() + ); -fn no_filter_match_err( - list: Vec, - only: Option, -) -> Result<(), Report> { - return Err(Report::msg( - "None of the paths ended with required argument", - )) - .with_note(|| { - format!("filter argument (--only) {}", only.unwrap().display()) - }) - .with_note(|| { - format!( - "examples of files: \n\t- {}", - list.iter() - .map(|p| p.display().to_string()) - .take(5) - .join("\n\t- ") - ) - }); + Ok(()) } pub fn handle_file(path: &Path, bars: MultiProgress) -> Result<()> { @@ -81,9 +72,18 @@ pub fn handle_file(path: &Path, bars: MultiProgress) -> Result<()> { let (meta, payload_size) = series::meta_list_and_payload_size(&readings, &encoding); + let corrupt_sections_skipped = Arc::new(AtomicUsize::new(0)); + let callback = { + let corrupt_sections_skipped = corrupt_sections_skipped.clone(); + Box::new(move || { + corrupt_sections_skipped.fetch_add(1, Ordering::Relaxed); + true + }) + }; let (input_series, _) = ByteSeries::builder() .payload_size(payload_size) .with_header(metadata.as_bytes().to_vec()) + .with_callback_on_recoverable_corruption(callback) .open(path) .wrap_err("Could not open byteseries")?; @@ -95,25 +95,47 @@ pub fn handle_file(path: &Path, bars: MultiProgress) -> Result<()> { .suggestion("If the file already exists remove it")?; let copy_bar = ProgressBar::new(input_series.len()) - .with_style(bar_style()) + .with_style(crate::bar_style()) .with_message(format!( "{:?}", path.file_name().expect("we only handle files with names") )); let copy_bar = bars.insert(1, copy_bar); - copy_over_content(input_series, decoder, output, copy_bar.clone()) - .wrap_err("Failed to copy over content")?; + copy_over_content( + input_series, + decoder, + readings, + output, + copy_bar.clone(), + ) + .wrap_err("Failed to copy over content")?; bars.remove(©_bar); + + let skipped = corrupt_sections_skipped.load(Ordering::Relaxed); + if skipped > 0 { + bars.suspend(|| { + warn!( + "Skipped {skipped} corrupt meta data sections and data from \ + that section until the next intact metadata section" + ) + }) + } Ok(()) } fn copy_over_content( mut input_series: ByteSeries, mut decoder: ExportDecoder, + readings: Vec, mut output: Csv, copy_bar: ProgressBar, ) -> Result<()> { let mut read_start = 0; + let precisions = readings + .into_iter() + .map(|r| r.leaf().precision()) + .collect_vec(); + loop { let mut timestamps = Vec::new(); let mut data = Vec::new(); @@ -139,7 +161,7 @@ fn copy_over_content( for (ts, line) in timestamps.into_iter().zip(data.into_iter()) { copy_bar.inc(1); output - .write_line(ts, &line) + .write_line(ts, &line, &precisions) .wrap_err("failed to write line to csv")?; } } @@ -209,7 +231,7 @@ fn files_to_export( let mut buf = [0u8; 300]; let mut res = Vec::new(); - visit_dirs(data_dir, &mut |entry: &DirEntry| { + crate::visit_dirs(data_dir, &mut |entry: &DirEntry| { if entry.path().extension() == Some(OsStr::new("byteseries")) { let mut file = fs::File::open(entry.path()).wrap_err("Could not open file")?; @@ -230,33 +252,3 @@ fn files_to_export( .wrap_err("Could not search for byteseries files")?; Ok(res) } - -fn visit_dirs( - dir: &Path, - mut cb: &mut dyn FnMut(&DirEntry) -> Result<()>, -) -> Result<()> { - if dir.is_dir() { - for entry in fs::read_dir(dir).wrap_err("Could not read dir")? { - let entry = entry.wrap_err("Error walking dir")?; - let path = entry.path(); - if path.is_dir() { - visit_dirs(&path, &mut cb)?; - } else { - cb(&entry) - .wrap_err("Could not check file header") - .with_note(|| { - format!("file: {}", entry.path().display()) - })?; - } - } - } - Ok(()) -} - -fn bar_style() -> ProgressStyle { - ProgressStyle::with_template( - "[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg} [{eta}]", - ) - .unwrap() - .progress_chars("##-") -} diff --git a/crates/data-store/src/export/csv.rs b/crates/data-store/src/export/csv.rs index 71b5a90e..5748df9a 100644 --- a/crates/data-store/src/export/csv.rs +++ b/crates/data-store/src/export/csv.rs @@ -7,6 +7,7 @@ use std::io::BufWriter; use std::io::Write; use std::path::PathBuf; +/// https://www.rfc-editor.org/rfc/rfc4180 pub(crate) struct Csv { pub(crate) file: BufWriter, } @@ -25,19 +26,27 @@ impl Csv { let mut file = BufWriter::new(file); write!(file, "ts").wrap_err("Could not write header")?; for reading in readings { - write!(file, "{reading:?},").wrap_err("Could not write header")?; + let encoded = ron::to_string(reading).expect("can be encoded"); + write!(file, ",{encoded}").wrap_err("Could not write header")?; } + write!(file, "\r\n").wrap_err("Could not write header")?; Ok(Self { file }) } - pub(crate) fn write_line(&mut self, ts: u64, line: &[f32]) -> Result<()> { + pub(crate) fn write_line( + &mut self, + ts: u64, + line: &[f32], + precisions: &[usize], + ) -> Result<()> { write!(self.file, "{ts}").wrap_err("Could not write ts to file")?; - for val in line { - write!(self.file, "{val}") + for (val, precision) in line.into_iter().zip(precisions) { + write!(self.file, ",{0:.1$}", val, precision) .wrap_err("Could not write float value to file")?; } - write!(self.file, "\n").wrap_err("Could not write lineend to file")?; + write!(self.file, "\r\n") + .wrap_err("Could not write lineend to file")?; Ok(()) } diff --git a/crates/data-store/src/import.rs b/crates/data-store/src/import.rs new file mode 100644 index 00000000..a3ffcb1d --- /dev/null +++ b/crates/data-store/src/import.rs @@ -0,0 +1,260 @@ +use byteseries::ByteSeries; +use color_eyre::eyre::{bail, Context, OptionExt}; +use color_eyre::{Result, Section}; +use indicatif::{MultiProgress, ProgressBar}; +use std::ffi::OsStr; +use std::fs::{self, DirEntry}; +use std::io::{BufRead, BufReader, ErrorKind, Read}; +use std::path::{Path, PathBuf}; +use tracing::warn; + +use crate::data::series::Meta; + +pub fn perform( + data_dir: &Path, + only: Option, + allow_corrupt: bool, +) -> Result<()> { + let list = files_to_export(data_dir)?; + if list.is_empty() { + bail!("No files left to export") + } + + let to_handle: Vec<_> = list + .iter() + .filter(|p| { + only.as_ref().is_none_or(|allowed| { + p.ends_with(allowed) || p.with_extension("").ends_with(allowed) + }) + }) + .collect(); + + if to_handle.is_empty() { + return crate::no_filter_match_err(list, only); + } + + let bars = MultiProgress::new(); + let files_bar = + ProgressBar::new(to_handle.len() as u64).with_style(crate::bar_style()); + let files_bar = bars.insert(0, files_bar); + files_bar.inc(0); // make the bar appear + + for path in &to_handle { + handle_file(&path, bars.clone(), allow_corrupt) + .wrap_err("Failed to export data") + .with_note(|| format!("Input file: {}", path.display()))?; + files_bar.inc(1); + } + + drop(bars); + tracing::info!( + "Done, exported {} files to {}", + to_handle.len(), + data_dir.display() + ); + + Ok(()) +} + +fn files_to_export( + data_dir: &Path, +) -> Result, color_eyre::eyre::Error> { + let mut buf = [0u8; 3]; + let mut res = Vec::new(); + + crate::visit_dirs(data_dir, &mut |entry: &DirEntry| { + if entry.path().extension() == Some(OsStr::new("csv")) { + let mut file = + fs::File::open(entry.path()).wrap_err("Could not open file")?; + + match file.read_exact(&mut buf) { + Ok(()) => (), + Err(e) if e.kind() == ErrorKind::UnexpectedEof => return Ok(()), + other => other.wrap_err("Could not read first 3 bytes")?, + } + + let header = String::from_utf8_lossy(&buf); + if header.contains("ts,") { + res.push(entry.path()); + } + } + Ok(()) + }) + .wrap_err("Could not search for csv files")?; + Ok(res) +} + +fn resolve_readings( + csv: &mut BufReader, +) -> color_eyre::Result<(Vec, usize)> { + let mut csv_header = String::new(); + let header_len = csv + .read_line(&mut csv_header) + .wrap_err("Could not read csv header")?; + let readings = csv_header + .trim() + .strip_prefix("ts,") + .ok_or_eyre("Csv header is missing the timestamp column header: 'ts,'") + .with_note(|| format!("header is: {csv_header}"))? + .split(',') + .map(|s| { + ron::from_str::(s) + .wrap_err("Could not decode Reading from string") + .with_note(|| format!("string was: {s}")) + }) + .collect::>>()?; + Ok((readings, header_len)) +} + +/// must be called after `resolve_readings` +/// this is a guess since some lines are longer some shorter. +fn number_of_lines( + csv: &mut BufReader, + header_len: usize, +) -> color_eyre::Result { + let file = csv.get_mut(); + let data_length = file + .metadata() + .wrap_err("Could not get file metadata")? + .len() + - header_len as u64; + let _ = file; + + if data_length == 0 { + return Ok(0); + } + + let mut line = String::new(); + let line_size = csv + .read_line(&mut line) + .wrap_err("Could not read data line from csv")?; + csv.seek_relative(-(line_size as i64)) + .wrap_err("Could not seek back to start of csv data")?; + + Ok(data_length / line_size as u64) +} + +fn handle_file( + path: &Path, + bars: MultiProgress, + allow_corrupt: bool, +) -> Result<()> { + let input_csv = fs::File::open(path).wrap_err("Could not open file")?; + let mut input_csv = BufReader::new(input_csv); + let (readings, header_len) = resolve_readings(&mut input_csv)?; + let lines = number_of_lines(&mut input_csv, header_len)?; + + let specs = crate::data::series::to_speclist(&readings); + let fields = crate::data::series::bitspec::speclist_to_fields(specs); + let (meta_list, payload_size) = + crate::data::series::meta_list_and_payload_size(&readings, &fields); + for (Meta { reading, .. }, in_csv) in meta_list.iter().zip(&readings) { + assert_eq!(reading, in_csv); + } + + let header = crate::data::series::Header { + readings: readings.to_vec(), + encoding: fields.clone(), + } + .serialized()?; + + let (bs, _) = byteseries::ByteSeries::builder() + .payload_size(payload_size) + .with_header(header) + .create_new(true) + .open(path.with_extension("byteseries")) + .wrap_err("Could not open output series")?; + + let copy_bar = ProgressBar::new(lines) + .with_style(crate::bar_style()) + .with_message(format!( + "{:?}", + path.file_name().expect("we only handle files with names") + )); + let copy_bar = bars.insert(1, copy_bar); + + let mut skipped_sections = 0; + let mut last_correct_before_corrupt = 0; + if allow_corrupt { + copy_over_content( + input_csv, + bs, + meta_list, + copy_bar.clone(), + |_, prev| { + if prev != last_correct_before_corrupt { + skipped_sections += 1; + } else { + last_correct_before_corrupt = prev; + } + true + }, + ) + .wrap_err("Failed to copy over content")?; + } else { + copy_over_content( + input_csv, + bs, + meta_list, + copy_bar.clone(), + |_, _| false, + ) + .wrap_err("Failed to copy over content")?; + } + + if skipped_sections > 0 { + bars.suspend(|| { + warn!( + "skipped {skipped_sections} sections of data due to \ + corrupt full meta ts" + ); + }) + } + + bars.remove(©_bar); + + Ok(()) +} + +fn copy_over_content( + input_csv: BufReader, + mut bs: ByteSeries, + meta_list: Vec, + copy_bar: ProgressBar, + mut on_invalid_ts: impl FnMut(u64, u64) -> bool, +) -> color_eyre::Result<()> { + use byteseries::series::Error as BsError; + + let mut encoded_line = vec![0; bs.payload_size()]; + for (i, line) in input_csv.lines().enumerate() { + let line = line.wrap_err("Could not read line from csv")?; + let (ts, line) = + line.split_once(',').ok_or_eyre("Empty line in csv")?; + let ts: u64 = ts + .parse() + .wrap_err("Could not parse timestamp as integer") + .with_note(|| format!("timestamp: {ts}"))?; + + for (value, Meta { field, .. }) in line.split(',').zip(&meta_list) { + let value: f32 = + value.parse().wrap_err("Could not parse field as f32")?; + field.encode(value, &mut encoded_line); + } + + match bs.push_line(ts, &encoded_line) { + Ok(()) => (), + Err(BsError::TimeNotAfterLast { new, prev }) + if on_invalid_ts(new, prev) => + { + () + } + Err(other) => Err(other) + .wrap_err("Could not push line to output") + .with_note(|| format!("line {} in file", i + 1))?, + }; + + copy_bar.inc(1); + } + + Ok(()) +} diff --git a/crates/data-store/src/lib.rs b/crates/data-store/src/lib.rs index fb10b87d..a0518314 100644 --- a/crates/data-store/src/lib.rs +++ b/crates/data-store/src/lib.rs @@ -1,10 +1,71 @@ #![allow(clippy::missing_errors_doc, clippy::missing_panics_doc)] +use std::fs::DirEntry; +use std::path::{Path, PathBuf}; + +use color_eyre::eyre::Context; +use color_eyre::Section; +use indicatif::ProgressStyle; +use itertools::Itertools; + #[cfg(feature = "api")] pub mod api; #[cfg(feature = "server")] -pub mod server; +pub mod data; #[cfg(feature = "server")] pub mod export; #[cfg(feature = "server")] -pub mod data; +pub mod import; +#[cfg(feature = "server")] +pub mod server; + +pub(crate) fn visit_dirs( + dir: &Path, + mut cb: &mut dyn FnMut(&DirEntry) -> color_eyre::Result<()>, +) -> color_eyre::Result<()> { + if dir.is_dir() { + for entry in std::fs::read_dir(dir).wrap_err("Could not read dir")? { + let entry = entry.wrap_err("Error walking dir")?; + let path = entry.path(); + if path.is_dir() { + visit_dirs(&path, &mut cb)?; + } else { + cb(&entry) + .wrap_err("Could not check file header") + .with_note(|| { + format!("file: {}", entry.path().display()) + })?; + } + } + } + Ok(()) +} + +pub(crate) fn no_filter_match_err( + list: Vec, + only: Option, +) -> color_eyre::Result<()> { + return Err(color_eyre::Report::msg( + "None of the paths ended with required argument", + )) + .with_note(|| { + format!("filter argument (--only) {}", only.unwrap().display()) + }) + .with_note(|| { + format!( + "examples of files: \n\t- {}", + list.iter() + .map(|p| p.display().to_string()) + .take(5) + .join("\n\t- ") + ) + }); +} + +fn bar_style() -> ProgressStyle { + ProgressStyle::with_template( + "[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg} [{eta}]", + ) + .unwrap() + .progress_chars("##-") +} diff --git a/crates/data-store/src/main.rs b/crates/data-store/src/main.rs index 0d5ac569..02e532d3 100644 --- a/crates/data-store/src/main.rs +++ b/crates/data-store/src/main.rs @@ -29,19 +29,19 @@ enum Command { client_port: u16, }, Export { - /// export only one dataset - /// at this path this fails. + /// export only one dataset at this path + /// `largebedroom/bed/nau7802right` #[arg(short, long)] only: Option, }, Import { - /// which dataset to import - /// note a backup is made automatically and needs - /// to be manually removed if you do not want it. - /// - /// If the backup already exists this fails + /// import a dataset at this path for example: + /// `largebedroom/bed/nau7802right` #[arg(short, long)] only: Option, + /// skip data that is out of order, this is useful as it fixes an + /// issue caused by a bug in Byteseries. + skip_corrupt: bool, }, } @@ -60,7 +60,11 @@ async fn main() -> Result<()> { data_store::server::run(data_server, client_port, &cli.data_dir) .await } - Command::Export { only } => data_store::export::perform(&cli.data_dir, only), - Command::Import { .. } => todo!(), + Command::Export { only } => { + data_store::export::perform(&cli.data_dir, only) + } + Command::Import { only, skip_corrupt } => { + data_store::import::perform(&cli.data_dir, only, skip_corrupt) + } } } From 1e3a6af6705f9b8136682901f3e2f92bc95d0376 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 17 Mar 2025 18:47:29 +0100 Subject: [PATCH 597/687] fix typos --- crates/data-store/src/import.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/data-store/src/import.rs b/crates/data-store/src/import.rs index a3ffcb1d..aeb35a10 100644 --- a/crates/data-store/src/import.rs +++ b/crates/data-store/src/import.rs @@ -15,9 +15,9 @@ pub fn perform( only: Option, allow_corrupt: bool, ) -> Result<()> { - let list = files_to_export(data_dir)?; + let list = files_to_import(data_dir)?; if list.is_empty() { - bail!("No files left to export") + bail!("No files left to import") } let to_handle: Vec<_> = list @@ -41,14 +41,14 @@ pub fn perform( for path in &to_handle { handle_file(&path, bars.clone(), allow_corrupt) - .wrap_err("Failed to export data") + .wrap_err("Failed to import data") .with_note(|| format!("Input file: {}", path.display()))?; files_bar.inc(1); } drop(bars); tracing::info!( - "Done, exported {} files to {}", + "Done, imported {} files to {}", to_handle.len(), data_dir.display() ); @@ -56,7 +56,7 @@ pub fn perform( Ok(()) } -fn files_to_export( +fn files_to_import( data_dir: &Path, ) -> Result, color_eyre::eyre::Error> { let mut buf = [0u8; 3]; From cd466160e0893bf79b5ba9c1ad05e19c5cb66839 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 17 Mar 2025 18:47:53 +0100 Subject: [PATCH 598/687] script to update data --- crates/data-store/update_data.sh | 62 ++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100755 crates/data-store/update_data.sh diff --git a/crates/data-store/update_data.sh b/crates/data-store/update_data.sh new file mode 100755 index 00000000..00c2c228 --- /dev/null +++ b/crates/data-store/update_data.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash + +set -e + +if [ ! -d data ]; then + ssh sgc -q << ENDSSH +set -e +sudo systemctl stop data-store +cd /home/ha +sudo tar -czf data.tar.gz data +ENDSSH + + rsync sgc:/home/david/data.tar.gz . + tar -xzf data.tar.gz +else + echo "data directory already exists, skipping fetch data from server" +fi + +if [ ! -d data_updated ]; then + cargo r --release -- --data-dir data export + cp -r data data_updated + rm $(find data_updated | grep '.byteseries') +else + echo "data_updated.tar.gz already exists skipping exporting" +fi + +if [ ! -f data_updated.tar.gz ]; then + cargo r --release -- --data-dir data_updated import + rm $(find data_updated | grep '.csv') + tar -czf data_updated.tar.gz data_updated +else + echo "data_updated.tar.gz already exists skipping importing" +fi + +rsync $(pwd)/data_updated.tar.gz sgc:/home/david/ + +result=$(ssh sgc -q << ENDSSH +set -e +if [ -d /home/ha/data ]; then + sudo mv /home/ha/data{,_backup} +fi +sudo tar -xzf data_updated.tar.gz -C /home/ha +sudo mv /home/ha/data{_updated,} +sudo chown -R ha:ha /home/ha/data +echo success +ENDSSH +) + +if [[ $result != *success ]]; then + echo "Error, unpacking failed on server." + echo "$result" + exit +fi + +ssh sgc -q << ENDSSH +sudo systemctl start data-store +ENDSSH + +sleep 5 +ssh sgc -q << ENDSSH +sudo systemctl status data-store +ENDSSH From d6e5e56d05b3ff860e30fdb2c4e011f125e387b8 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 17 Mar 2025 18:49:26 +0100 Subject: [PATCH 599/687] switch to latest upstream byteseries --- Cargo.toml | 2 +- crates/data-store/Cargo.toml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 18b46f88..4e3fcbe1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ zigbee-bridge = { path = "crates/zigbee-bridge" } rpc = { path = "crates/rpc" } logger = { path = "crates/logger" } -byteseries = { git = "https://github.com/dvdsk/byteseries", rev="325c7823aa2d04bba85d0346077fe999e789f3c9" } +byteseries = { git = "https://github.com/dvdsk/byteseries", rev="a9da72e9585e5f5a8cc3cf543d6ca2561ad7007a" } serde = { version = "1", features = ["derive"], default-features = false } tokio = { version = "1.38", features = ["rt-multi-thread"] } diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index 92b8c72b..393fe6f7 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -25,8 +25,7 @@ rpc = { workspace = true } protocol = { workspace = true, features = ["alloc", "thiserror"] } data-server = { workspace = true } -# byteseries = { workspace = true } -byteseries = { path = "/home/david/Documents/byteseries" } +byteseries = { workspace = true } tokio = { workspace = true, features = ["fs", "net", "rt-multi-thread", "sync"] } futures-concurrency = { workspace = true } serde.workspace = true From 9f4aff2ca4cd843691328293825878c1a549fbc4 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 18 Mar 2025 01:26:18 +0100 Subject: [PATCH 600/687] fix import not zero-ing line --- crates/data-store/src/import.rs | 1 + crates/protocol/src/shared/radiator.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/data-store/src/import.rs b/crates/data-store/src/import.rs index aeb35a10..3fb2086f 100644 --- a/crates/data-store/src/import.rs +++ b/crates/data-store/src/import.rs @@ -235,6 +235,7 @@ fn copy_over_content( .wrap_err("Could not parse timestamp as integer") .with_note(|| format!("timestamp: {ts}"))?; + encoded_line.fill(0); for (value, Meta { field, .. }) in line.split(',').zip(&meta_list) { let value: f32 = value.parse().wrap_err("Could not parse field as f32")?; diff --git a/crates/protocol/src/shared/radiator.rs b/crates/protocol/src/shared/radiator.rs index 13429838..38dc2bb1 100644 --- a/crates/protocol/src/shared/radiator.rs +++ b/crates/protocol/src/shared/radiator.rs @@ -31,7 +31,7 @@ pub struct SetByLabelFormatter; #[cfg(feature = "alloc")] impl LabelFormatter for SetByLabelFormatter { - fn format(&self, value: f64, info: &reading::Info) -> String { + fn format(&self, value: f64, _info: &reading::Info) -> String { match value { 0.0 => "Manual", 1.0 => "Schedule", From 8a8f469d3c2989873ef0d8ddd3a709fcc9da4801 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 18 Mar 2025 14:58:50 +0100 Subject: [PATCH 601/687] add import/export test --- crates/data-store/test_import_export.sh | 18 ++++++++++++++++++ crates/data-store/update_data.sh | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100755 crates/data-store/test_import_export.sh diff --git a/crates/data-store/test_import_export.sh b/crates/data-store/test_import_export.sh new file mode 100755 index 00000000..21c4bfb0 --- /dev/null +++ b/crates/data-store/test_import_export.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +# restore test file +cp data_updated/largebedroom/desk/bme280.csv{2,} + +rm data_updated/largebedroom/desk/bme280.byteseries +rm data_updated/largebedroom/desk/bme280.byteseries_index +cargo r --release -- --data-dir data_updated import --only largebedroom/desk/bme280 + +rm data_updated/largebedroom/desk/bme280.csv +cargo r --release -- --data-dir data_updated export --only largebedroom/desk/bme280 + +diff -q data_updated/largebedroom/desk/bme280.csv{2,} + +echo "Tail of input/correct file" +tail -n 2 data_updated/largebedroom/desk/bme280.csv2 +echo "Tail of output" +tail -n 2 data_updated/largebedroom/desk/bme280.csv diff --git a/crates/data-store/update_data.sh b/crates/data-store/update_data.sh index 00c2c228..8cfb034c 100755 --- a/crates/data-store/update_data.sh +++ b/crates/data-store/update_data.sh @@ -21,7 +21,7 @@ if [ ! -d data_updated ]; then cp -r data data_updated rm $(find data_updated | grep '.byteseries') else - echo "data_updated.tar.gz already exists skipping exporting" + echo "data_updated directory already exists skipping exporting" fi if [ ! -f data_updated.tar.gz ]; then From 105f72249d01e860bdc0c4324ff7d586a005a3ba Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 18 Mar 2025 15:03:16 +0100 Subject: [PATCH 602/687] rename sensor-nodes -> nodes --- {sensor-nodes => nodes}/Cargo.lock | 0 {sensor-nodes => nodes}/Cargo.toml | 0 {sensor-nodes => nodes}/bed-lb/.cargo/config.toml | 0 {sensor-nodes => nodes}/bed-lb/Cargo.lock | 0 {sensor-nodes => nodes}/bed-lb/Cargo.toml | 0 {sensor-nodes => nodes}/bed-lb/build.rs | 0 {sensor-nodes => nodes}/bed-lb/output.txt | 0 {sensor-nodes => nodes}/bed-lb/rust-toolchain.toml | 0 {sensor-nodes => nodes}/bed-lb/src/channel.rs | 0 {sensor-nodes => nodes}/bed-lb/src/main.rs | 0 {sensor-nodes => nodes}/bed-lb/src/network.rs | 0 {sensor-nodes => nodes}/bed-lb/src/rgb_led.rs | 0 {sensor-nodes => nodes}/bed-lb/src/rng.rs | 0 {sensor-nodes => nodes}/bed-lb/src/sensors.rs | 0 {sensor-nodes => nodes}/bed-lb/src/sensors/fast.rs | 0 {sensor-nodes => nodes}/bed-lb/src/sensors/slow.rs | 0 {sensor-nodes => nodes}/bed-lb/stm32f401.svd | 0 {sensor-nodes => nodes}/bed-sb/.cargo/config.toml | 0 {sensor-nodes => nodes}/bed-sb/Cargo.lock | 0 {sensor-nodes => nodes}/bed-sb/Cargo.toml | 0 {sensor-nodes => nodes}/bed-sb/build.rs | 0 {sensor-nodes => nodes}/bed-sb/output.txt | 0 {sensor-nodes => nodes}/bed-sb/rust-toolchain.toml | 0 {sensor-nodes => nodes}/bed-sb/src/channel.rs | 0 {sensor-nodes => nodes}/bed-sb/src/comms.rs | 0 {sensor-nodes => nodes}/bed-sb/src/main.rs | 0 {sensor-nodes => nodes}/bed-sb/src/sensors.rs | 0 {sensor-nodes => nodes}/bed-sb/src/sensors/fast.rs | 0 {sensor-nodes => nodes}/bed-sb/src/sensors/slow.rs | 0 {sensor-nodes => nodes}/bed-sb/src/usb_wrapper.rs | 0 {sensor-nodes => nodes}/bed-sb/stm32f401.svd | 0 {sensor-nodes => nodes}/sensors/Cargo.toml | 0 {sensor-nodes => nodes}/sensors/src/drivers.rs | 0 {sensor-nodes => nodes}/sensors/src/drivers/driver_impl_bme680.rs | 0 .../sensors/src/drivers/driver_impl_max44009.rs | 0 .../sensors/src/drivers/driver_impl_nau7802.rs | 0 {sensor-nodes => nodes}/sensors/src/drivers/driver_impl_sht31.rs | 0 {sensor-nodes => nodes}/sensors/src/drivers/i2c_wrapper.rs | 0 {sensor-nodes => nodes}/sensors/src/drivers/reinit_on_error.rs | 0 {sensor-nodes => nodes}/sensors/src/drivers/wrap_mhz.rs | 0 {sensor-nodes => nodes}/sensors/src/drivers/wrap_sps30.rs | 0 {sensor-nodes => nodes}/sensors/src/errors.rs | 0 {sensor-nodes => nodes}/sensors/src/lib.rs | 0 {sensor-nodes => nodes}/sensors/src/measurements.rs | 0 {sensor-nodes => nodes}/setup.sh | 0 45 files changed, 0 insertions(+), 0 deletions(-) rename {sensor-nodes => nodes}/Cargo.lock (100%) rename {sensor-nodes => nodes}/Cargo.toml (100%) rename {sensor-nodes => nodes}/bed-lb/.cargo/config.toml (100%) rename {sensor-nodes => nodes}/bed-lb/Cargo.lock (100%) rename {sensor-nodes => nodes}/bed-lb/Cargo.toml (100%) rename {sensor-nodes => nodes}/bed-lb/build.rs (100%) rename {sensor-nodes => nodes}/bed-lb/output.txt (100%) rename {sensor-nodes => nodes}/bed-lb/rust-toolchain.toml (100%) rename {sensor-nodes => nodes}/bed-lb/src/channel.rs (100%) rename {sensor-nodes => nodes}/bed-lb/src/main.rs (100%) rename {sensor-nodes => nodes}/bed-lb/src/network.rs (100%) rename {sensor-nodes => nodes}/bed-lb/src/rgb_led.rs (100%) rename {sensor-nodes => nodes}/bed-lb/src/rng.rs (100%) rename {sensor-nodes => nodes}/bed-lb/src/sensors.rs (100%) rename {sensor-nodes => nodes}/bed-lb/src/sensors/fast.rs (100%) rename {sensor-nodes => nodes}/bed-lb/src/sensors/slow.rs (100%) rename {sensor-nodes => nodes}/bed-lb/stm32f401.svd (100%) rename {sensor-nodes => nodes}/bed-sb/.cargo/config.toml (100%) rename {sensor-nodes => nodes}/bed-sb/Cargo.lock (100%) rename {sensor-nodes => nodes}/bed-sb/Cargo.toml (100%) rename {sensor-nodes => nodes}/bed-sb/build.rs (100%) rename {sensor-nodes => nodes}/bed-sb/output.txt (100%) rename {sensor-nodes => nodes}/bed-sb/rust-toolchain.toml (100%) rename {sensor-nodes => nodes}/bed-sb/src/channel.rs (100%) rename {sensor-nodes => nodes}/bed-sb/src/comms.rs (100%) rename {sensor-nodes => nodes}/bed-sb/src/main.rs (100%) rename {sensor-nodes => nodes}/bed-sb/src/sensors.rs (100%) rename {sensor-nodes => nodes}/bed-sb/src/sensors/fast.rs (100%) rename {sensor-nodes => nodes}/bed-sb/src/sensors/slow.rs (100%) rename {sensor-nodes => nodes}/bed-sb/src/usb_wrapper.rs (100%) rename {sensor-nodes => nodes}/bed-sb/stm32f401.svd (100%) rename {sensor-nodes => nodes}/sensors/Cargo.toml (100%) rename {sensor-nodes => nodes}/sensors/src/drivers.rs (100%) rename {sensor-nodes => nodes}/sensors/src/drivers/driver_impl_bme680.rs (100%) rename {sensor-nodes => nodes}/sensors/src/drivers/driver_impl_max44009.rs (100%) rename {sensor-nodes => nodes}/sensors/src/drivers/driver_impl_nau7802.rs (100%) rename {sensor-nodes => nodes}/sensors/src/drivers/driver_impl_sht31.rs (100%) rename {sensor-nodes => nodes}/sensors/src/drivers/i2c_wrapper.rs (100%) rename {sensor-nodes => nodes}/sensors/src/drivers/reinit_on_error.rs (100%) rename {sensor-nodes => nodes}/sensors/src/drivers/wrap_mhz.rs (100%) rename {sensor-nodes => nodes}/sensors/src/drivers/wrap_sps30.rs (100%) rename {sensor-nodes => nodes}/sensors/src/errors.rs (100%) rename {sensor-nodes => nodes}/sensors/src/lib.rs (100%) rename {sensor-nodes => nodes}/sensors/src/measurements.rs (100%) rename {sensor-nodes => nodes}/setup.sh (100%) diff --git a/sensor-nodes/Cargo.lock b/nodes/Cargo.lock similarity index 100% rename from sensor-nodes/Cargo.lock rename to nodes/Cargo.lock diff --git a/sensor-nodes/Cargo.toml b/nodes/Cargo.toml similarity index 100% rename from sensor-nodes/Cargo.toml rename to nodes/Cargo.toml diff --git a/sensor-nodes/bed-lb/.cargo/config.toml b/nodes/bed-lb/.cargo/config.toml similarity index 100% rename from sensor-nodes/bed-lb/.cargo/config.toml rename to nodes/bed-lb/.cargo/config.toml diff --git a/sensor-nodes/bed-lb/Cargo.lock b/nodes/bed-lb/Cargo.lock similarity index 100% rename from sensor-nodes/bed-lb/Cargo.lock rename to nodes/bed-lb/Cargo.lock diff --git a/sensor-nodes/bed-lb/Cargo.toml b/nodes/bed-lb/Cargo.toml similarity index 100% rename from sensor-nodes/bed-lb/Cargo.toml rename to nodes/bed-lb/Cargo.toml diff --git a/sensor-nodes/bed-lb/build.rs b/nodes/bed-lb/build.rs similarity index 100% rename from sensor-nodes/bed-lb/build.rs rename to nodes/bed-lb/build.rs diff --git a/sensor-nodes/bed-lb/output.txt b/nodes/bed-lb/output.txt similarity index 100% rename from sensor-nodes/bed-lb/output.txt rename to nodes/bed-lb/output.txt diff --git a/sensor-nodes/bed-lb/rust-toolchain.toml b/nodes/bed-lb/rust-toolchain.toml similarity index 100% rename from sensor-nodes/bed-lb/rust-toolchain.toml rename to nodes/bed-lb/rust-toolchain.toml diff --git a/sensor-nodes/bed-lb/src/channel.rs b/nodes/bed-lb/src/channel.rs similarity index 100% rename from sensor-nodes/bed-lb/src/channel.rs rename to nodes/bed-lb/src/channel.rs diff --git a/sensor-nodes/bed-lb/src/main.rs b/nodes/bed-lb/src/main.rs similarity index 100% rename from sensor-nodes/bed-lb/src/main.rs rename to nodes/bed-lb/src/main.rs diff --git a/sensor-nodes/bed-lb/src/network.rs b/nodes/bed-lb/src/network.rs similarity index 100% rename from sensor-nodes/bed-lb/src/network.rs rename to nodes/bed-lb/src/network.rs diff --git a/sensor-nodes/bed-lb/src/rgb_led.rs b/nodes/bed-lb/src/rgb_led.rs similarity index 100% rename from sensor-nodes/bed-lb/src/rgb_led.rs rename to nodes/bed-lb/src/rgb_led.rs diff --git a/sensor-nodes/bed-lb/src/rng.rs b/nodes/bed-lb/src/rng.rs similarity index 100% rename from sensor-nodes/bed-lb/src/rng.rs rename to nodes/bed-lb/src/rng.rs diff --git a/sensor-nodes/bed-lb/src/sensors.rs b/nodes/bed-lb/src/sensors.rs similarity index 100% rename from sensor-nodes/bed-lb/src/sensors.rs rename to nodes/bed-lb/src/sensors.rs diff --git a/sensor-nodes/bed-lb/src/sensors/fast.rs b/nodes/bed-lb/src/sensors/fast.rs similarity index 100% rename from sensor-nodes/bed-lb/src/sensors/fast.rs rename to nodes/bed-lb/src/sensors/fast.rs diff --git a/sensor-nodes/bed-lb/src/sensors/slow.rs b/nodes/bed-lb/src/sensors/slow.rs similarity index 100% rename from sensor-nodes/bed-lb/src/sensors/slow.rs rename to nodes/bed-lb/src/sensors/slow.rs diff --git a/sensor-nodes/bed-lb/stm32f401.svd b/nodes/bed-lb/stm32f401.svd similarity index 100% rename from sensor-nodes/bed-lb/stm32f401.svd rename to nodes/bed-lb/stm32f401.svd diff --git a/sensor-nodes/bed-sb/.cargo/config.toml b/nodes/bed-sb/.cargo/config.toml similarity index 100% rename from sensor-nodes/bed-sb/.cargo/config.toml rename to nodes/bed-sb/.cargo/config.toml diff --git a/sensor-nodes/bed-sb/Cargo.lock b/nodes/bed-sb/Cargo.lock similarity index 100% rename from sensor-nodes/bed-sb/Cargo.lock rename to nodes/bed-sb/Cargo.lock diff --git a/sensor-nodes/bed-sb/Cargo.toml b/nodes/bed-sb/Cargo.toml similarity index 100% rename from sensor-nodes/bed-sb/Cargo.toml rename to nodes/bed-sb/Cargo.toml diff --git a/sensor-nodes/bed-sb/build.rs b/nodes/bed-sb/build.rs similarity index 100% rename from sensor-nodes/bed-sb/build.rs rename to nodes/bed-sb/build.rs diff --git a/sensor-nodes/bed-sb/output.txt b/nodes/bed-sb/output.txt similarity index 100% rename from sensor-nodes/bed-sb/output.txt rename to nodes/bed-sb/output.txt diff --git a/sensor-nodes/bed-sb/rust-toolchain.toml b/nodes/bed-sb/rust-toolchain.toml similarity index 100% rename from sensor-nodes/bed-sb/rust-toolchain.toml rename to nodes/bed-sb/rust-toolchain.toml diff --git a/sensor-nodes/bed-sb/src/channel.rs b/nodes/bed-sb/src/channel.rs similarity index 100% rename from sensor-nodes/bed-sb/src/channel.rs rename to nodes/bed-sb/src/channel.rs diff --git a/sensor-nodes/bed-sb/src/comms.rs b/nodes/bed-sb/src/comms.rs similarity index 100% rename from sensor-nodes/bed-sb/src/comms.rs rename to nodes/bed-sb/src/comms.rs diff --git a/sensor-nodes/bed-sb/src/main.rs b/nodes/bed-sb/src/main.rs similarity index 100% rename from sensor-nodes/bed-sb/src/main.rs rename to nodes/bed-sb/src/main.rs diff --git a/sensor-nodes/bed-sb/src/sensors.rs b/nodes/bed-sb/src/sensors.rs similarity index 100% rename from sensor-nodes/bed-sb/src/sensors.rs rename to nodes/bed-sb/src/sensors.rs diff --git a/sensor-nodes/bed-sb/src/sensors/fast.rs b/nodes/bed-sb/src/sensors/fast.rs similarity index 100% rename from sensor-nodes/bed-sb/src/sensors/fast.rs rename to nodes/bed-sb/src/sensors/fast.rs diff --git a/sensor-nodes/bed-sb/src/sensors/slow.rs b/nodes/bed-sb/src/sensors/slow.rs similarity index 100% rename from sensor-nodes/bed-sb/src/sensors/slow.rs rename to nodes/bed-sb/src/sensors/slow.rs diff --git a/sensor-nodes/bed-sb/src/usb_wrapper.rs b/nodes/bed-sb/src/usb_wrapper.rs similarity index 100% rename from sensor-nodes/bed-sb/src/usb_wrapper.rs rename to nodes/bed-sb/src/usb_wrapper.rs diff --git a/sensor-nodes/bed-sb/stm32f401.svd b/nodes/bed-sb/stm32f401.svd similarity index 100% rename from sensor-nodes/bed-sb/stm32f401.svd rename to nodes/bed-sb/stm32f401.svd diff --git a/sensor-nodes/sensors/Cargo.toml b/nodes/sensors/Cargo.toml similarity index 100% rename from sensor-nodes/sensors/Cargo.toml rename to nodes/sensors/Cargo.toml diff --git a/sensor-nodes/sensors/src/drivers.rs b/nodes/sensors/src/drivers.rs similarity index 100% rename from sensor-nodes/sensors/src/drivers.rs rename to nodes/sensors/src/drivers.rs diff --git a/sensor-nodes/sensors/src/drivers/driver_impl_bme680.rs b/nodes/sensors/src/drivers/driver_impl_bme680.rs similarity index 100% rename from sensor-nodes/sensors/src/drivers/driver_impl_bme680.rs rename to nodes/sensors/src/drivers/driver_impl_bme680.rs diff --git a/sensor-nodes/sensors/src/drivers/driver_impl_max44009.rs b/nodes/sensors/src/drivers/driver_impl_max44009.rs similarity index 100% rename from sensor-nodes/sensors/src/drivers/driver_impl_max44009.rs rename to nodes/sensors/src/drivers/driver_impl_max44009.rs diff --git a/sensor-nodes/sensors/src/drivers/driver_impl_nau7802.rs b/nodes/sensors/src/drivers/driver_impl_nau7802.rs similarity index 100% rename from sensor-nodes/sensors/src/drivers/driver_impl_nau7802.rs rename to nodes/sensors/src/drivers/driver_impl_nau7802.rs diff --git a/sensor-nodes/sensors/src/drivers/driver_impl_sht31.rs b/nodes/sensors/src/drivers/driver_impl_sht31.rs similarity index 100% rename from sensor-nodes/sensors/src/drivers/driver_impl_sht31.rs rename to nodes/sensors/src/drivers/driver_impl_sht31.rs diff --git a/sensor-nodes/sensors/src/drivers/i2c_wrapper.rs b/nodes/sensors/src/drivers/i2c_wrapper.rs similarity index 100% rename from sensor-nodes/sensors/src/drivers/i2c_wrapper.rs rename to nodes/sensors/src/drivers/i2c_wrapper.rs diff --git a/sensor-nodes/sensors/src/drivers/reinit_on_error.rs b/nodes/sensors/src/drivers/reinit_on_error.rs similarity index 100% rename from sensor-nodes/sensors/src/drivers/reinit_on_error.rs rename to nodes/sensors/src/drivers/reinit_on_error.rs diff --git a/sensor-nodes/sensors/src/drivers/wrap_mhz.rs b/nodes/sensors/src/drivers/wrap_mhz.rs similarity index 100% rename from sensor-nodes/sensors/src/drivers/wrap_mhz.rs rename to nodes/sensors/src/drivers/wrap_mhz.rs diff --git a/sensor-nodes/sensors/src/drivers/wrap_sps30.rs b/nodes/sensors/src/drivers/wrap_sps30.rs similarity index 100% rename from sensor-nodes/sensors/src/drivers/wrap_sps30.rs rename to nodes/sensors/src/drivers/wrap_sps30.rs diff --git a/sensor-nodes/sensors/src/errors.rs b/nodes/sensors/src/errors.rs similarity index 100% rename from sensor-nodes/sensors/src/errors.rs rename to nodes/sensors/src/errors.rs diff --git a/sensor-nodes/sensors/src/lib.rs b/nodes/sensors/src/lib.rs similarity index 100% rename from sensor-nodes/sensors/src/lib.rs rename to nodes/sensors/src/lib.rs diff --git a/sensor-nodes/sensors/src/measurements.rs b/nodes/sensors/src/measurements.rs similarity index 100% rename from sensor-nodes/sensors/src/measurements.rs rename to nodes/sensors/src/measurements.rs diff --git a/sensor-nodes/setup.sh b/nodes/setup.sh similarity index 100% rename from sensor-nodes/setup.sh rename to nodes/setup.sh From aabcdde95b6344cfd6bbf4e61efc071f03df2706 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 18 Mar 2025 19:29:02 +0100 Subject: [PATCH 603/687] adds Airbox to protocol --- crates/protocol/src/large_bedroom.rs | 13 +- crates/protocol/src/large_bedroom/airbox.rs | 275 ++++++++++++++++++++ 2 files changed, 286 insertions(+), 2 deletions(-) create mode 100644 crates/protocol/src/large_bedroom/airbox.rs diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index ace580c8..08ad4a87 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -7,6 +7,7 @@ use crate::{affector, reading}; pub mod bed; pub mod desk; pub mod radiator; +pub mod airbox; #[derive( strum::EnumDiscriminants, @@ -25,10 +26,11 @@ pub enum Reading { Bed(bed::Reading) = 0, Desk(desk::Reading) = 1, Radiator(radiator::Reading) = 2, + Airbox(airbox::Reading) = 3, } #[cfg(feature = "alloc")] -reading::tree::all_nodes! {Reading; ReadingDiscriminants; Bed, Desk, Radiator} +reading::tree::all_nodes! {Reading; ReadingDiscriminants; Bed, Desk, Radiator, Airbox} #[derive( strum::EnumDiscriminants, @@ -44,6 +46,7 @@ reading::tree::all_nodes! {Reading; ReadingDiscriminants; Bed, Desk, Radiator} pub enum Error { Bed(bed::Error), Desk(desk::Error), + Airbox(airbox::Error), } impl Error { @@ -52,6 +55,7 @@ impl Error { match self { Error::Bed(error) => Device::Bed(error.device()), Error::Desk(error) => Device::Desk(error.device()), + Error::Airbox(error) => Device::Airbox(error.device()), } } } @@ -61,6 +65,7 @@ impl core::fmt::Display for Error { match self { Error::Bed(error) => write!(f, "{error}"), Error::Desk(error) => write!(f, "{error}"), + Error::Airbox(error) => write!(f, "{error}"), } } } @@ -80,6 +85,7 @@ pub enum Device { Bed(bed::Device), Desk(desk::Device), Radiator(radiator::Device), + Airbox(airbox::Device), } impl Device { @@ -89,6 +95,7 @@ impl Device { Self::Bed(dev) => dev.info(), Self::Desk(dev) => dev.info(), Self::Radiator(dev) => dev.info(), + Self::Airbox(dev) => dev.info(), } } } @@ -109,15 +116,17 @@ impl Device { #[strum_discriminants(derive(Hash))] pub enum Affector { Bed(bed::Affector), + Airbox(airbox::Affector), } impl Affector { #[cfg(feature = "alloc")] pub(crate) fn controls(&mut self) -> Vec { match self { Affector::Bed(a) => a.controls(), + Affector::Airbox(a) => a.controls(), } } } #[cfg(feature = "alloc")] -affector::tree::all_nodes! {Affector; AffectorDiscriminants; Bed} +affector::tree::all_nodes! {Affector; AffectorDiscriminants; Bed, Airbox} diff --git a/crates/protocol/src/large_bedroom/airbox.rs b/crates/protocol/src/large_bedroom/airbox.rs new file mode 100644 index 00000000..7dc5b9bd --- /dev/null +++ b/crates/protocol/src/large_bedroom/airbox.rs @@ -0,0 +1,275 @@ +use core::time::Duration; + +#[cfg(feature = "alloc")] +use crate::affector::{self, Control, ControlValue}; +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "alloc")] +use crate::reading::tree::{Item, Tree}; +#[cfg(feature = "alloc")] +use crate::reading::FloatLabelFormatter; +#[cfg(feature = "alloc")] +use crate::reading::Info; +use crate::shared::impl_is_same_as; +#[cfg(feature = "alloc")] +use crate::Unit; + +#[derive( + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, +)] +#[strum_discriminants(derive(Hash))] +#[repr(u8)] +pub enum Reading { + Temperature(f32) = 0, + Pressure(f32) = 1, + FanPower(f32) = 2, +} + +impl_is_same_as! {Reading; Temperature, Pressure} + +#[cfg(feature = "alloc")] +impl Tree for Reading { + #[must_use] + fn inner(&self) -> Item<'_> { + let leaf = match self { + Reading::Temperature(val) => Info { + val: *val, + device: Device::Bme280.rooted(), + resolution: 0.01, + range: -10.0..45.0, + unit: Unit::C, + description: "Temperature", + branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), + }, + Reading::Pressure(val) => Info { + val: *val, + device: Device::Bme280.rooted(), + range: 87_000.0..108_100.0, + resolution: 0.18, + unit: Unit::Pa, + description: "Air pressure", + branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), + }, + Reading::FanPower(val) => Info { + val: *val as u8 as f32, + device: crate::Device::LargeBedroom(super::Device::Airbox( + Device::Fans, + )), + resolution: 1.0, + range: 0.0..100.0, + unit: Unit::RelativePower, + description: "Fan power", + branch_id: self.branch_id(), + label_formatter: Box::new(FloatLabelFormatter), + }, + }; + Item::Leaf(leaf) + } + + #[must_use] + fn branch_id(&self) -> crate::reading::tree::Id { + ReadingDiscriminants::from(self) as crate::reading::tree::Id + } +} + +#[derive( + Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq, +)] +pub enum Error { + Running(SensorError), + Setup(SensorError), + SetupTimedOut(Device), + Timeout(Device), +} + +impl Error { + pub fn device(&self) -> Device { + match self { + Self::Running(sensor_err) | Self::Setup(sensor_err) => { + sensor_err.device() + } + Self::SetupTimedOut(device) | Self::Timeout(device) => { + device.clone() + } + } + } +} + +impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Error::Running(e) => { + write!(f, "{} ran into error: {e}", e.device()) + } + Error::Setup(e) => { + write!(f, "{} errored during setup: {e}", e.device()) + } + Error::SetupTimedOut(d) => write!(f, "{d} timed out during setup"), + Error::Timeout(d) => write!(f, "{d} timed out while running"), + } + } +} + +#[derive( + Clone, Debug, defmt::Format, Serialize, Deserialize, Eq, PartialEq, +)] +pub enum SensorError { + BmeError(heapless::String<200>), +} + +impl SensorError { + fn device(&self) -> Device { + Device::Bme280 + } +} + +impl core::fmt::Display for SensorError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + SensorError::BmeError(e) => write!(f, "{e}"), + } + } +} + +impl MaxSize for SensorError { + const POSTCARD_MAX_SIZE: usize = 200 + 1; +} + +#[derive( + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + Eq, + PartialEq, + Hash, +)] +pub enum Device { + Bme280, + Fans, +} + +impl core::fmt::Display for Device { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.info().name) + } +} + +macro_rules! tree { + [$thing:ident; $($item:expr),+] => { + [$(crate::$thing::LargeBedroom( + crate::large_bedroom::$thing::Airbox($item), + )),+] + }; +} + +impl Device { + #[must_use] + pub fn rooted(self) -> crate::Device { + crate::Device::LargeBedroom(crate::large_bedroom::Device::Airbox(self)) + } + + /// Note the order in which the `affects_readings` occur is the order in which + /// they will be stored, do not change it! + #[must_use] + pub const fn info(&self) -> crate::DeviceInfo { + match self { + Device::Bme280 => crate::DeviceInfo { + name: "Bme280", + affects_readings: &tree![ + Reading; Reading::Temperature(0.0), Reading::Pressure(0.0)], + temporal_resolution: Duration::from_secs(5), // unknown + min_sample_interval: Duration::from_secs(5), // unknown + max_sample_interval: Duration::MAX, + affectors: &[], + }, + Device::Fans => crate::DeviceInfo { + name: "Fans", + affects_readings: &tree![Reading; Reading::FanPower(0.0) ], + temporal_resolution: Duration::from_secs(5), // unknown + min_sample_interval: Duration::from_secs(5), // unknown + max_sample_interval: Duration::MAX, + affectors: &[], + }, + } + } +} + +#[derive( + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, + Eq, + Hash, +)] +#[strum_discriminants(derive(Hash))] +pub enum Affector { + FanPower { power: u8 }, + ResetNode, +} + +impl crate::IsSameAs for Affector { + #[must_use] + fn is_same_as(&self, other: &Self) -> bool { + match (self, other) { + (Affector::FanPower { .. }, Affector::FanPower { .. }) => true, + (Affector::ResetNode, Affector::ResetNode) => true, + _ => false, + } + } +} + +impl Affector { + #[cfg(feature = "alloc")] + pub fn controls(&mut self) -> Vec { + match self { + Affector::FanPower { power } => vec![Control { + name: "red", + value: ControlValue::SetNum { + valid_range: 0..100, + value: *power as usize, + setter: Some(Box::new(|input: usize| *power = input as u8)), + }, + }], + Affector::ResetNode => vec![Control { + name: "reset the node", + value: ControlValue::Trigger, + }], + } + } +} + +#[cfg(feature = "alloc")] +impl affector::tree::Tree for Affector { + fn inner(&self) -> affector::tree::Item<'_> { + let description = match self { + Affector::FanPower { .. } => "Set the power of the fans", + Affector::ResetNode => "Reset the node, this might fix errors such as I2c getting stuck after Arbitration Error", + }; + + affector::tree::Item::Leaf(affector::Info { description }) + } + + fn branch_id(&self) -> affector::tree::Id { + AffectorDiscriminants::from(self) as affector::tree::Id + } +} From 2796c05e442aae49307b0ce8fdecb8a95a4f7c87 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 19 Mar 2025 16:42:07 +0100 Subject: [PATCH 604/687] reorder nodes into embassy and esp32 linking issue if they are in the same workspace :( --- Cargo.toml | 3 ++- nodes/Readme.md | 1 + nodes/{ => embassy}/Cargo.lock | 0 nodes/{ => embassy}/Cargo.toml | 0 nodes/{ => embassy}/bed-lb/.cargo/config.toml | 0 nodes/{ => embassy}/bed-lb/Cargo.lock | 0 nodes/{ => embassy}/bed-lb/Cargo.toml | 0 nodes/{ => embassy}/bed-lb/build.rs | 0 nodes/{ => embassy}/bed-lb/output.txt | 0 nodes/{ => embassy}/bed-lb/rust-toolchain.toml | 0 nodes/{ => embassy}/bed-lb/src/channel.rs | 0 nodes/{ => embassy}/bed-lb/src/main.rs | 0 nodes/{ => embassy}/bed-lb/src/network.rs | 0 nodes/{ => embassy}/bed-lb/src/rgb_led.rs | 0 nodes/{ => embassy}/bed-lb/src/rng.rs | 0 nodes/{ => embassy}/bed-lb/src/sensors.rs | 0 nodes/{ => embassy}/bed-lb/src/sensors/fast.rs | 0 nodes/{ => embassy}/bed-lb/src/sensors/slow.rs | 0 nodes/{ => embassy}/bed-lb/stm32f401.svd | 0 nodes/{ => embassy}/bed-sb/.cargo/config.toml | 0 nodes/{ => embassy}/bed-sb/Cargo.lock | 0 nodes/{ => embassy}/bed-sb/Cargo.toml | 0 nodes/{ => embassy}/bed-sb/build.rs | 0 nodes/{ => embassy}/bed-sb/output.txt | 0 nodes/{ => embassy}/bed-sb/rust-toolchain.toml | 0 nodes/{ => embassy}/bed-sb/src/channel.rs | 0 nodes/{ => embassy}/bed-sb/src/comms.rs | 0 nodes/{ => embassy}/bed-sb/src/main.rs | 0 nodes/{ => embassy}/bed-sb/src/sensors.rs | 0 nodes/{ => embassy}/bed-sb/src/sensors/fast.rs | 0 nodes/{ => embassy}/bed-sb/src/sensors/slow.rs | 0 nodes/{ => embassy}/bed-sb/src/usb_wrapper.rs | 0 nodes/{ => embassy}/bed-sb/stm32f401.svd | 0 nodes/{ => embassy}/sensors/Cargo.toml | 0 nodes/{ => embassy}/sensors/src/drivers.rs | 0 nodes/{ => embassy}/sensors/src/drivers/driver_impl_bme680.rs | 0 .../{ => embassy}/sensors/src/drivers/driver_impl_max44009.rs | 0 nodes/{ => embassy}/sensors/src/drivers/driver_impl_nau7802.rs | 0 nodes/{ => embassy}/sensors/src/drivers/driver_impl_sht31.rs | 0 nodes/{ => embassy}/sensors/src/drivers/i2c_wrapper.rs | 0 nodes/{ => embassy}/sensors/src/drivers/reinit_on_error.rs | 0 nodes/{ => embassy}/sensors/src/drivers/wrap_mhz.rs | 0 nodes/{ => embassy}/sensors/src/drivers/wrap_sps30.rs | 0 nodes/{ => embassy}/sensors/src/errors.rs | 0 nodes/{ => embassy}/sensors/src/lib.rs | 0 nodes/{ => embassy}/sensors/src/measurements.rs | 0 nodes/{ => embassy}/setup.sh | 0 47 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 nodes/Readme.md rename nodes/{ => embassy}/Cargo.lock (100%) rename nodes/{ => embassy}/Cargo.toml (100%) rename nodes/{ => embassy}/bed-lb/.cargo/config.toml (100%) rename nodes/{ => embassy}/bed-lb/Cargo.lock (100%) rename nodes/{ => embassy}/bed-lb/Cargo.toml (100%) rename nodes/{ => embassy}/bed-lb/build.rs (100%) rename nodes/{ => embassy}/bed-lb/output.txt (100%) rename nodes/{ => embassy}/bed-lb/rust-toolchain.toml (100%) rename nodes/{ => embassy}/bed-lb/src/channel.rs (100%) rename nodes/{ => embassy}/bed-lb/src/main.rs (100%) rename nodes/{ => embassy}/bed-lb/src/network.rs (100%) rename nodes/{ => embassy}/bed-lb/src/rgb_led.rs (100%) rename nodes/{ => embassy}/bed-lb/src/rng.rs (100%) rename nodes/{ => embassy}/bed-lb/src/sensors.rs (100%) rename nodes/{ => embassy}/bed-lb/src/sensors/fast.rs (100%) rename nodes/{ => embassy}/bed-lb/src/sensors/slow.rs (100%) rename nodes/{ => embassy}/bed-lb/stm32f401.svd (100%) rename nodes/{ => embassy}/bed-sb/.cargo/config.toml (100%) rename nodes/{ => embassy}/bed-sb/Cargo.lock (100%) rename nodes/{ => embassy}/bed-sb/Cargo.toml (100%) rename nodes/{ => embassy}/bed-sb/build.rs (100%) rename nodes/{ => embassy}/bed-sb/output.txt (100%) rename nodes/{ => embassy}/bed-sb/rust-toolchain.toml (100%) rename nodes/{ => embassy}/bed-sb/src/channel.rs (100%) rename nodes/{ => embassy}/bed-sb/src/comms.rs (100%) rename nodes/{ => embassy}/bed-sb/src/main.rs (100%) rename nodes/{ => embassy}/bed-sb/src/sensors.rs (100%) rename nodes/{ => embassy}/bed-sb/src/sensors/fast.rs (100%) rename nodes/{ => embassy}/bed-sb/src/sensors/slow.rs (100%) rename nodes/{ => embassy}/bed-sb/src/usb_wrapper.rs (100%) rename nodes/{ => embassy}/bed-sb/stm32f401.svd (100%) rename nodes/{ => embassy}/sensors/Cargo.toml (100%) rename nodes/{ => embassy}/sensors/src/drivers.rs (100%) rename nodes/{ => embassy}/sensors/src/drivers/driver_impl_bme680.rs (100%) rename nodes/{ => embassy}/sensors/src/drivers/driver_impl_max44009.rs (100%) rename nodes/{ => embassy}/sensors/src/drivers/driver_impl_nau7802.rs (100%) rename nodes/{ => embassy}/sensors/src/drivers/driver_impl_sht31.rs (100%) rename nodes/{ => embassy}/sensors/src/drivers/i2c_wrapper.rs (100%) rename nodes/{ => embassy}/sensors/src/drivers/reinit_on_error.rs (100%) rename nodes/{ => embassy}/sensors/src/drivers/wrap_mhz.rs (100%) rename nodes/{ => embassy}/sensors/src/drivers/wrap_sps30.rs (100%) rename nodes/{ => embassy}/sensors/src/errors.rs (100%) rename nodes/{ => embassy}/sensors/src/lib.rs (100%) rename nodes/{ => embassy}/sensors/src/measurements.rs (100%) rename nodes/{ => embassy}/setup.sh (100%) diff --git a/Cargo.toml b/Cargo.toml index 4e3fcbe1..e8e0a51d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,8 @@ [workspace] resolver = "2" members = ["crates/*"] -exclude = ["sensor-nodes/bed-lb", "sensor-nodes/bed-sb"] +exclude = ["nodes/embassy/bed-lb", "nodes/embassy/bed-sb", +"nodes/esp32/airbox"] [workspace.dependencies] data-server = { path = "crates/data-server" } diff --git a/nodes/Readme.md b/nodes/Readme.md new file mode 100644 index 00000000..015602fc --- /dev/null +++ b/nodes/Readme.md @@ -0,0 +1 @@ +While esp32 nodes use embassy they need a different time driver which causes linking issues if they are in the same workspace diff --git a/nodes/Cargo.lock b/nodes/embassy/Cargo.lock similarity index 100% rename from nodes/Cargo.lock rename to nodes/embassy/Cargo.lock diff --git a/nodes/Cargo.toml b/nodes/embassy/Cargo.toml similarity index 100% rename from nodes/Cargo.toml rename to nodes/embassy/Cargo.toml diff --git a/nodes/bed-lb/.cargo/config.toml b/nodes/embassy/bed-lb/.cargo/config.toml similarity index 100% rename from nodes/bed-lb/.cargo/config.toml rename to nodes/embassy/bed-lb/.cargo/config.toml diff --git a/nodes/bed-lb/Cargo.lock b/nodes/embassy/bed-lb/Cargo.lock similarity index 100% rename from nodes/bed-lb/Cargo.lock rename to nodes/embassy/bed-lb/Cargo.lock diff --git a/nodes/bed-lb/Cargo.toml b/nodes/embassy/bed-lb/Cargo.toml similarity index 100% rename from nodes/bed-lb/Cargo.toml rename to nodes/embassy/bed-lb/Cargo.toml diff --git a/nodes/bed-lb/build.rs b/nodes/embassy/bed-lb/build.rs similarity index 100% rename from nodes/bed-lb/build.rs rename to nodes/embassy/bed-lb/build.rs diff --git a/nodes/bed-lb/output.txt b/nodes/embassy/bed-lb/output.txt similarity index 100% rename from nodes/bed-lb/output.txt rename to nodes/embassy/bed-lb/output.txt diff --git a/nodes/bed-lb/rust-toolchain.toml b/nodes/embassy/bed-lb/rust-toolchain.toml similarity index 100% rename from nodes/bed-lb/rust-toolchain.toml rename to nodes/embassy/bed-lb/rust-toolchain.toml diff --git a/nodes/bed-lb/src/channel.rs b/nodes/embassy/bed-lb/src/channel.rs similarity index 100% rename from nodes/bed-lb/src/channel.rs rename to nodes/embassy/bed-lb/src/channel.rs diff --git a/nodes/bed-lb/src/main.rs b/nodes/embassy/bed-lb/src/main.rs similarity index 100% rename from nodes/bed-lb/src/main.rs rename to nodes/embassy/bed-lb/src/main.rs diff --git a/nodes/bed-lb/src/network.rs b/nodes/embassy/bed-lb/src/network.rs similarity index 100% rename from nodes/bed-lb/src/network.rs rename to nodes/embassy/bed-lb/src/network.rs diff --git a/nodes/bed-lb/src/rgb_led.rs b/nodes/embassy/bed-lb/src/rgb_led.rs similarity index 100% rename from nodes/bed-lb/src/rgb_led.rs rename to nodes/embassy/bed-lb/src/rgb_led.rs diff --git a/nodes/bed-lb/src/rng.rs b/nodes/embassy/bed-lb/src/rng.rs similarity index 100% rename from nodes/bed-lb/src/rng.rs rename to nodes/embassy/bed-lb/src/rng.rs diff --git a/nodes/bed-lb/src/sensors.rs b/nodes/embassy/bed-lb/src/sensors.rs similarity index 100% rename from nodes/bed-lb/src/sensors.rs rename to nodes/embassy/bed-lb/src/sensors.rs diff --git a/nodes/bed-lb/src/sensors/fast.rs b/nodes/embassy/bed-lb/src/sensors/fast.rs similarity index 100% rename from nodes/bed-lb/src/sensors/fast.rs rename to nodes/embassy/bed-lb/src/sensors/fast.rs diff --git a/nodes/bed-lb/src/sensors/slow.rs b/nodes/embassy/bed-lb/src/sensors/slow.rs similarity index 100% rename from nodes/bed-lb/src/sensors/slow.rs rename to nodes/embassy/bed-lb/src/sensors/slow.rs diff --git a/nodes/bed-lb/stm32f401.svd b/nodes/embassy/bed-lb/stm32f401.svd similarity index 100% rename from nodes/bed-lb/stm32f401.svd rename to nodes/embassy/bed-lb/stm32f401.svd diff --git a/nodes/bed-sb/.cargo/config.toml b/nodes/embassy/bed-sb/.cargo/config.toml similarity index 100% rename from nodes/bed-sb/.cargo/config.toml rename to nodes/embassy/bed-sb/.cargo/config.toml diff --git a/nodes/bed-sb/Cargo.lock b/nodes/embassy/bed-sb/Cargo.lock similarity index 100% rename from nodes/bed-sb/Cargo.lock rename to nodes/embassy/bed-sb/Cargo.lock diff --git a/nodes/bed-sb/Cargo.toml b/nodes/embassy/bed-sb/Cargo.toml similarity index 100% rename from nodes/bed-sb/Cargo.toml rename to nodes/embassy/bed-sb/Cargo.toml diff --git a/nodes/bed-sb/build.rs b/nodes/embassy/bed-sb/build.rs similarity index 100% rename from nodes/bed-sb/build.rs rename to nodes/embassy/bed-sb/build.rs diff --git a/nodes/bed-sb/output.txt b/nodes/embassy/bed-sb/output.txt similarity index 100% rename from nodes/bed-sb/output.txt rename to nodes/embassy/bed-sb/output.txt diff --git a/nodes/bed-sb/rust-toolchain.toml b/nodes/embassy/bed-sb/rust-toolchain.toml similarity index 100% rename from nodes/bed-sb/rust-toolchain.toml rename to nodes/embassy/bed-sb/rust-toolchain.toml diff --git a/nodes/bed-sb/src/channel.rs b/nodes/embassy/bed-sb/src/channel.rs similarity index 100% rename from nodes/bed-sb/src/channel.rs rename to nodes/embassy/bed-sb/src/channel.rs diff --git a/nodes/bed-sb/src/comms.rs b/nodes/embassy/bed-sb/src/comms.rs similarity index 100% rename from nodes/bed-sb/src/comms.rs rename to nodes/embassy/bed-sb/src/comms.rs diff --git a/nodes/bed-sb/src/main.rs b/nodes/embassy/bed-sb/src/main.rs similarity index 100% rename from nodes/bed-sb/src/main.rs rename to nodes/embassy/bed-sb/src/main.rs diff --git a/nodes/bed-sb/src/sensors.rs b/nodes/embassy/bed-sb/src/sensors.rs similarity index 100% rename from nodes/bed-sb/src/sensors.rs rename to nodes/embassy/bed-sb/src/sensors.rs diff --git a/nodes/bed-sb/src/sensors/fast.rs b/nodes/embassy/bed-sb/src/sensors/fast.rs similarity index 100% rename from nodes/bed-sb/src/sensors/fast.rs rename to nodes/embassy/bed-sb/src/sensors/fast.rs diff --git a/nodes/bed-sb/src/sensors/slow.rs b/nodes/embassy/bed-sb/src/sensors/slow.rs similarity index 100% rename from nodes/bed-sb/src/sensors/slow.rs rename to nodes/embassy/bed-sb/src/sensors/slow.rs diff --git a/nodes/bed-sb/src/usb_wrapper.rs b/nodes/embassy/bed-sb/src/usb_wrapper.rs similarity index 100% rename from nodes/bed-sb/src/usb_wrapper.rs rename to nodes/embassy/bed-sb/src/usb_wrapper.rs diff --git a/nodes/bed-sb/stm32f401.svd b/nodes/embassy/bed-sb/stm32f401.svd similarity index 100% rename from nodes/bed-sb/stm32f401.svd rename to nodes/embassy/bed-sb/stm32f401.svd diff --git a/nodes/sensors/Cargo.toml b/nodes/embassy/sensors/Cargo.toml similarity index 100% rename from nodes/sensors/Cargo.toml rename to nodes/embassy/sensors/Cargo.toml diff --git a/nodes/sensors/src/drivers.rs b/nodes/embassy/sensors/src/drivers.rs similarity index 100% rename from nodes/sensors/src/drivers.rs rename to nodes/embassy/sensors/src/drivers.rs diff --git a/nodes/sensors/src/drivers/driver_impl_bme680.rs b/nodes/embassy/sensors/src/drivers/driver_impl_bme680.rs similarity index 100% rename from nodes/sensors/src/drivers/driver_impl_bme680.rs rename to nodes/embassy/sensors/src/drivers/driver_impl_bme680.rs diff --git a/nodes/sensors/src/drivers/driver_impl_max44009.rs b/nodes/embassy/sensors/src/drivers/driver_impl_max44009.rs similarity index 100% rename from nodes/sensors/src/drivers/driver_impl_max44009.rs rename to nodes/embassy/sensors/src/drivers/driver_impl_max44009.rs diff --git a/nodes/sensors/src/drivers/driver_impl_nau7802.rs b/nodes/embassy/sensors/src/drivers/driver_impl_nau7802.rs similarity index 100% rename from nodes/sensors/src/drivers/driver_impl_nau7802.rs rename to nodes/embassy/sensors/src/drivers/driver_impl_nau7802.rs diff --git a/nodes/sensors/src/drivers/driver_impl_sht31.rs b/nodes/embassy/sensors/src/drivers/driver_impl_sht31.rs similarity index 100% rename from nodes/sensors/src/drivers/driver_impl_sht31.rs rename to nodes/embassy/sensors/src/drivers/driver_impl_sht31.rs diff --git a/nodes/sensors/src/drivers/i2c_wrapper.rs b/nodes/embassy/sensors/src/drivers/i2c_wrapper.rs similarity index 100% rename from nodes/sensors/src/drivers/i2c_wrapper.rs rename to nodes/embassy/sensors/src/drivers/i2c_wrapper.rs diff --git a/nodes/sensors/src/drivers/reinit_on_error.rs b/nodes/embassy/sensors/src/drivers/reinit_on_error.rs similarity index 100% rename from nodes/sensors/src/drivers/reinit_on_error.rs rename to nodes/embassy/sensors/src/drivers/reinit_on_error.rs diff --git a/nodes/sensors/src/drivers/wrap_mhz.rs b/nodes/embassy/sensors/src/drivers/wrap_mhz.rs similarity index 100% rename from nodes/sensors/src/drivers/wrap_mhz.rs rename to nodes/embassy/sensors/src/drivers/wrap_mhz.rs diff --git a/nodes/sensors/src/drivers/wrap_sps30.rs b/nodes/embassy/sensors/src/drivers/wrap_sps30.rs similarity index 100% rename from nodes/sensors/src/drivers/wrap_sps30.rs rename to nodes/embassy/sensors/src/drivers/wrap_sps30.rs diff --git a/nodes/sensors/src/errors.rs b/nodes/embassy/sensors/src/errors.rs similarity index 100% rename from nodes/sensors/src/errors.rs rename to nodes/embassy/sensors/src/errors.rs diff --git a/nodes/sensors/src/lib.rs b/nodes/embassy/sensors/src/lib.rs similarity index 100% rename from nodes/sensors/src/lib.rs rename to nodes/embassy/sensors/src/lib.rs diff --git a/nodes/sensors/src/measurements.rs b/nodes/embassy/sensors/src/measurements.rs similarity index 100% rename from nodes/sensors/src/measurements.rs rename to nodes/embassy/sensors/src/measurements.rs diff --git a/nodes/setup.sh b/nodes/embassy/setup.sh similarity index 100% rename from nodes/setup.sh rename to nodes/embassy/setup.sh From 754d19b5a8e8dba3e94e3c94080ee96d320abc34 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 19 Mar 2025 16:42:46 +0100 Subject: [PATCH 605/687] adds airbox firmware --- crates/data-server/src/server/watch.rs | 7 + crates/protocol/src/large_bedroom/airbox.rs | 39 +- nodes/esp32/airbox/.cargo/config.toml | 17 + nodes/esp32/airbox/.gitignore | 17 + nodes/esp32/airbox/Cargo.lock | 1622 +++++++++++++++++++ nodes/esp32/airbox/Cargo.toml | 78 + nodes/esp32/airbox/build.rs | 41 + nodes/esp32/airbox/rust-toolchain.toml | 4 + nodes/esp32/airbox/src/fans.rs | 76 + nodes/esp32/airbox/src/main.rs | 105 ++ nodes/esp32/airbox/src/network.rs | 221 +++ nodes/esp32/airbox/src/sensor.rs | 71 + nodes/esp32/airbox/template.yaml | 149 ++ 13 files changed, 2440 insertions(+), 7 deletions(-) create mode 100644 nodes/esp32/airbox/.cargo/config.toml create mode 100644 nodes/esp32/airbox/.gitignore create mode 100644 nodes/esp32/airbox/Cargo.lock create mode 100644 nodes/esp32/airbox/Cargo.toml create mode 100644 nodes/esp32/airbox/build.rs create mode 100644 nodes/esp32/airbox/rust-toolchain.toml create mode 100644 nodes/esp32/airbox/src/fans.rs create mode 100644 nodes/esp32/airbox/src/main.rs create mode 100644 nodes/esp32/airbox/src/network.rs create mode 100644 nodes/esp32/airbox/src/sensor.rs create mode 100644 nodes/esp32/airbox/template.yaml diff --git a/crates/data-server/src/server/watch.rs b/crates/data-server/src/server/watch.rs index d8173d82..a73cb492 100644 --- a/crates/data-server/src/server/watch.rs +++ b/crates/data-server/src/server/watch.rs @@ -63,6 +63,13 @@ impl LastSeen { ), )) } + Reading::LargeBedroom(large_bedroom::Reading::Airbox( + _, + )) => Some(Affector::LargeBedroom( + large_bedroom::Affector::Airbox( + large_bedroom::airbox::Affector::ResetNode, + ), + )), Reading::LargeBedroom(large_bedroom::Reading::Desk(_)) | Reading::LargeBedroom( large_bedroom::Reading::Radiator(_), diff --git a/crates/protocol/src/large_bedroom/airbox.rs b/crates/protocol/src/large_bedroom/airbox.rs index 7dc5b9bd..60e961f3 100644 --- a/crates/protocol/src/large_bedroom/airbox.rs +++ b/crates/protocol/src/large_bedroom/airbox.rs @@ -2,6 +2,7 @@ use core::time::Duration; #[cfg(feature = "alloc")] use crate::affector::{self, Control, ControlValue}; +use crate::button::Press; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; @@ -32,6 +33,7 @@ pub enum Reading { Temperature(f32) = 0, Pressure(f32) = 1, FanPower(f32) = 2, + Button(Press) = 3, } impl_is_same_as! {Reading; Temperature, Pressure} @@ -73,6 +75,18 @@ impl Tree for Reading { branch_id: self.branch_id(), label_formatter: Box::new(FloatLabelFormatter), }, + Reading::Button(press) => Info { + val: if press.is_long() { 2.0 } else { 1.0 }, + device: crate::Device::LargeBedroom(super::Device::Airbox( + Device::Gpio, + )), + description: "button", + range: 0.0..3.0, + resolution: 1.0, + unit: crate::Unit::None, + branch_id: self.branch_id(), + label_formatter: Box::new(crate::button::ButtonLabelFormatter), + }, }; Item::Leaf(leaf) } @@ -87,8 +101,8 @@ impl Tree for Reading { Clone, Debug, defmt::Format, Serialize, Deserialize, MaxSize, Eq, PartialEq, )] pub enum Error { - Running(SensorError), - Setup(SensorError), + Running(DeviceError), + Setup(DeviceError), SetupTimedOut(Device), Timeout(Device), } @@ -124,25 +138,27 @@ impl core::fmt::Display for Error { #[derive( Clone, Debug, defmt::Format, Serialize, Deserialize, Eq, PartialEq, )] -pub enum SensorError { +pub enum DeviceError { BmeError(heapless::String<200>), + Pwm(heapless::String<200>), } -impl SensorError { +impl DeviceError { fn device(&self) -> Device { Device::Bme280 } } -impl core::fmt::Display for SensorError { +impl core::fmt::Display for DeviceError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - SensorError::BmeError(e) => write!(f, "{e}"), + DeviceError::BmeError(e) => write!(f, "Bme error: {e}"), + DeviceError::Pwm(e) => write!(f, "Pwm error: {e}"), } } } -impl MaxSize for SensorError { +impl MaxSize for DeviceError { const POSTCARD_MAX_SIZE: usize = 200 + 1; } @@ -160,6 +176,7 @@ impl MaxSize for SensorError { pub enum Device { Bme280, Fans, + Gpio, } impl core::fmt::Display for Device { @@ -204,6 +221,14 @@ impl Device { max_sample_interval: Duration::MAX, affectors: &[], }, + Self::Gpio => crate::DeviceInfo { + name: "Gpio", + affects_readings: &tree![Reading; Reading::Button(Press(0)) ], + temporal_resolution: Duration::from_millis(50), // unknown + min_sample_interval: Duration::from_millis(50), // unknown + max_sample_interval: Duration::MAX, + affectors: &[], + }, } } } diff --git a/nodes/esp32/airbox/.cargo/config.toml b/nodes/esp32/airbox/.cargo/config.toml new file mode 100644 index 00000000..ae85381c --- /dev/null +++ b/nodes/esp32/airbox/.cargo/config.toml @@ -0,0 +1,17 @@ +[target.riscv32imc-unknown-none-elf] +runner = "espflash flash --monitor --chip esp32c3 --log-format defmt" + +[env] +DEFMT_LOG="info" + +[build] +rustflags = [ + # Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.) + # NOTE: May negatively impact performance of produced code + "-C", "force-frame-pointers", +] + +target = "riscv32imc-unknown-none-elf" + +[unstable] +build-std = ["alloc", "core"] diff --git a/nodes/esp32/airbox/.gitignore b/nodes/esp32/airbox/.gitignore new file mode 100644 index 00000000..6e771f81 --- /dev/null +++ b/nodes/esp32/airbox/.gitignore @@ -0,0 +1,17 @@ +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + +# RustRover +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ diff --git a/nodes/esp32/airbox/Cargo.lock b/nodes/esp32/airbox/Cargo.lock new file mode 100644 index 00000000..d42ac8dc --- /dev/null +++ b/nodes/esp32/airbox/Cargo.lock @@ -0,0 +1,1622 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "airbox" +version = "0.1.0" +dependencies = [ + "bme280-rs", + "critical-section", + "defmt", + "embassy-executor", + "embassy-futures", + "embassy-net", + "embassy-sync", + "embassy-time", + "embedded-io", + "embedded-io-async", + "esp-alloc", + "esp-backtrace", + "esp-hal", + "esp-hal-embassy", + "esp-println", + "esp-wifi", + "heapless 0.8.0", + "protocol", + "smoltcp", + "static_cell", + "toml-cfg", +] + +[[package]] +name = "anyhow" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "basic-toml" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" +dependencies = [ + "serde", +] + +[[package]] +name = "bitfield" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7e6caee68becd795bfd65f1a026e4d00d8f0c2bc9be5eb568e1015f9ce3c34" +dependencies = [ + "bitfield-macros", +] + +[[package]] +name = "bitfield-macros" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "331afbb18ce7b644c0b428726d369c5dd37ca0b815d72a459fcc2896c3c8ad32" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" + +[[package]] +name = "bme280-rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b9c5f8cda3fc2c518da006efb17147d2814349adf209911141168838ea5b54" +dependencies = [ + "embedded-hal 1.0.0", + "embedded-hal-async", + "log", +] + +[[package]] +name = "bt-hci" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f377753756ec12e76b52d2dd657437be0448cc9736402ffadd0b8b8b9602c8a1" +dependencies = [ + "defmt", + "embassy-sync", + "embedded-io", + "embedded-io-async", + "futures-intrusive", + "heapless 0.8.0", +] + +[[package]] +name = "bytemuck" +version = "1.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" +dependencies = [ + "num-traits", +] + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.100", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "defmt" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f6162c53f659f65d00619fe31f14556a6e9f8752ccc4a41bd177ffcf3d6130" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d135dd939bad62d7490b0002602d35b358dce5fd9233a709d3c1ef467d4bde6" +dependencies = [ + "defmt-parser", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "defmt-parser" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3983b127f13995e68c1e29071e5d115cd96f215ccb5e6812e3728cd6f92653b3" +dependencies = [ + "thiserror", +] + +[[package]] +name = "delegate" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297806318ef30ad066b15792a8372858020ae3ca2e414ee6c2133b1eb9e9e945" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "document-features" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" +dependencies = [ + "litrs", +] + +[[package]] +name = "embassy-embedded-hal" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fea5ef5bed4d3468dfd44f5c9fa4cda8f54c86d4fb4ae683eacf9d39e2ea12" +dependencies = [ + "embassy-futures", + "embassy-sync", + "embassy-time", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-storage", + "embedded-storage-async", + "nb 1.1.0", +] + +[[package]] +name = "embassy-executor" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90327bcc66333a507f89ecc4e2d911b265c45f5c9bc241f98eee076752d35ac6" +dependencies = [ + "critical-section", + "defmt", + "document-features", + "embassy-executor-macros", +] + +[[package]] +name = "embassy-executor-macros" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3577b1e9446f61381179a330fc5324b01d511624c55f25e3c66c9e3c626dbecf" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "embassy-futures" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f878075b9794c1e4ac788c95b728f26aa6366d32eeb10c7051389f898f7d067" +dependencies = [ + "defmt", +] + +[[package]] +name = "embassy-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed041cc19a603d657124fddefdcbe5ef8bd60e77d972793ebb57de93394f5949" +dependencies = [ + "defmt", + "document-features", + "embassy-net-driver", + "embassy-sync", + "embassy-time", + "embedded-io-async", + "embedded-nal-async", + "heapless 0.8.0", + "managed", + "smoltcp", +] + +[[package]] +name = "embassy-net-driver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d" +dependencies = [ + "defmt", +] + +[[package]] +name = "embassy-sync" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d2c8cdff05a7a51ba0087489ea44b0b1d97a296ca6b1d6d1a33ea7423d34049" +dependencies = [ + "cfg-if", + "critical-section", + "defmt", + "embedded-io-async", + "futures-sink", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f820157f198ada183ad62e0a66f554c610cdcd1a9f27d4b316358103ced7a1f8" +dependencies = [ + "cfg-if", + "critical-section", + "document-features", + "embassy-time-driver", + "embassy-time-queue-utils", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "futures-util", +] + +[[package]] +name = "embassy-time-driver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d45f5d833b6d98bd2aab0c2de70b18bfaa10faf661a1578fd8e5dfb15eb7eba" +dependencies = [ + "document-features", +] + +[[package]] +name = "embassy-time-queue-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc55c748d16908a65b166d09ce976575fb8852cf60ccd06174092b41064d8f83" +dependencies = [ + "embassy-executor", + "heapless 0.8.0", +] + +[[package]] +name = "embedded-can" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-io-async" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" +dependencies = [ + "defmt", + "embedded-io", +] + +[[package]] +name = "embedded-nal" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56a28be191a992f28f178ec338a0bf02f63d7803244add736d026a471e6ed77" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "embedded-nal-async" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76959917cd2b86f40a98c28dd5624eddd1fa69d746241c8257eac428d83cb211" +dependencies = [ + "embedded-io-async", + "embedded-nal", +] + +[[package]] +name = "embedded-storage" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" + +[[package]] +name = "embedded-storage-async" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc" +dependencies = [ + "embedded-storage", +] + +[[package]] +name = "enum-as-inner" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "enumset" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a4b049558765cef5f0c1a273c3fc57084d768b44d2f98127aef4cceb17293" +dependencies = [ + "enumset_derive", +] + +[[package]] +name = "enumset_derive" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "esp-alloc" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a78132d362cbf62ce22a1466eb9e98424f6b2d1e476e7a3cb46ca9063c5833f7" +dependencies = [ + "cfg-if", + "critical-section", + "document-features", + "enumset", + "linked_list_allocator", +] + +[[package]] +name = "esp-backtrace" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4cd70abe47945c9116972781b5c05277ad855a5f5569fe2afd3e2e61a103cc0" +dependencies = [ + "defmt", + "esp-build", + "esp-println", +] + +[[package]] +name = "esp-build" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8aa1c8f9954c9506699cf1ca10a2adcc226ff10b6ae3cb9e875cf2c6a0b9a372" +dependencies = [ + "quote", + "syn 2.0.100", + "termcolor", +] + +[[package]] +name = "esp-config" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "158dba334d3a2acd8d93873c0ae723ca1037cc78eefe5d6b4c5919b0ca28e38e" +dependencies = [ + "document-features", +] + +[[package]] +name = "esp-hal" +version = "1.0.0-beta.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9efaa9c1324ca20a22086aba2ce47a9bdc5bd65969af8b0cd5e879603b57bef" +dependencies = [ + "basic-toml", + "bitfield", + "bitflags 2.9.0", + "bytemuck", + "cfg-if", + "chrono", + "critical-section", + "defmt", + "delegate", + "document-features", + "embassy-embedded-hal", + "embassy-futures", + "embassy-sync", + "embedded-can", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-io", + "embedded-io-async", + "enumset", + "esp-build", + "esp-config", + "esp-hal-procmacros", + "esp-metadata", + "esp-riscv-rt", + "esp32", + "esp32c2", + "esp32c3", + "esp32c6", + "esp32h2", + "esp32s2", + "esp32s3", + "fugit", + "instability", + "nb 1.1.0", + "paste", + "portable-atomic", + "rand_core", + "riscv", + "serde", + "strum 0.27.1", + "ufmt-write", + "void", + "xtensa-lx", + "xtensa-lx-rt", +] + +[[package]] +name = "esp-hal-embassy" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b27f41110117a9bf2be385b42535c686b301c8ce3b5ea0a07567e200a63a2239" +dependencies = [ + "critical-section", + "document-features", + "embassy-executor", + "embassy-sync", + "embassy-time", + "embassy-time-driver", + "embassy-time-queue-utils", + "esp-build", + "esp-config", + "esp-hal", + "esp-hal-procmacros", + "esp-metadata", + "portable-atomic", + "static_cell", +] + +[[package]] +name = "esp-hal-procmacros" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd340a20a7d546570af58fd9e2aae17466a42572680d8e70d35fc7c475c4ed8" +dependencies = [ + "darling", + "document-features", + "litrs", + "proc-macro-crate", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "esp-metadata" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b4bffc22b7b1222c9467f0cb90eb49dcb63de810ecb3300e4b3bbc4ac2423e" +dependencies = [ + "anyhow", + "basic-toml", + "serde", + "strum 0.26.3", +] + +[[package]] +name = "esp-println" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960703930f9f3c899ddedd122ea27a09d6a612c22323157e524af5b18876448e" +dependencies = [ + "critical-section", + "defmt", + "esp-build", + "log", + "portable-atomic", +] + +[[package]] +name = "esp-riscv-rt" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec69987b3d7c48b65f8fb829220832a101478d766c518ae836720d040608d5dd" +dependencies = [ + "document-features", + "riscv", + "riscv-rt-macros", +] + +[[package]] +name = "esp-wifi" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7d7ea0e2c374343a375758861e13cf618db619436bcb386dfe5529ef31e9d5" +dependencies = [ + "bt-hci", + "cfg-if", + "critical-section", + "defmt", + "document-features", + "embassy-net-driver", + "embassy-sync", + "embedded-io", + "embedded-io-async", + "enumset", + "esp-alloc", + "esp-build", + "esp-config", + "esp-hal", + "esp-metadata", + "esp-wifi-sys", + "heapless 0.8.0", + "libm", + "num-derive", + "num-traits", + "portable-atomic", + "portable_atomic_enum", + "rand_core", + "smoltcp", +] + +[[package]] +name = "esp-wifi-sys" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6b5438361891c431970194a733415006fb3d00b6eb70b3dcb66fd58f04d9b39" +dependencies = [ + "anyhow", + "defmt", +] + +[[package]] +name = "esp32" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d9b774d7a2c96550a5c25016c2abd33370ebac60e534484b7bca344ecb8a3d6" +dependencies = [ + "critical-section", + "defmt", + "vcell", +] + +[[package]] +name = "esp32c2" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f7037cfa7c93574b0891062f980a75ae97e9d6c93dcaff3e060b37cf1281c59" +dependencies = [ + "critical-section", + "defmt", + "vcell", +] + +[[package]] +name = "esp32c3" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1bbcfa3ab2979171263db80804dabc38bdd45450c7eb775ee3f81d552cf0ba" +dependencies = [ + "critical-section", + "defmt", + "vcell", +] + +[[package]] +name = "esp32c6" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ff2a4e1d1b0cb2517af20766004b8e8fb4612043f0b0569703cc90d1880ede4" +dependencies = [ + "critical-section", + "defmt", + "vcell", +] + +[[package]] +name = "esp32h2" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee7512ae8da61338545804a76c5bc9816a9122abbf2f23d1195e3d45fab79af" +dependencies = [ + "critical-section", + "defmt", + "vcell", +] + +[[package]] +name = "esp32s2" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a22733ee6f4bb08e3113df6651b2c350f37c44314017476e354ec951a55465e9" +dependencies = [ + "critical-section", + "defmt", + "vcell", +] + +[[package]] +name = "esp32s3" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6d20f119410092abfbc65e46f9362015a7110023528f0dbe855cab80c38ca8" +dependencies = [ + "critical-section", + "defmt", + "vcell", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "fugit" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17186ad64927d5ac8f02c1e77ccefa08ccd9eaa314d5a4772278aa204a22f7e7" +dependencies = [ + "defmt", + "gcd", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "gcd" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version", + "serde", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "defmt", + "hash32 0.3.1", + "portable-atomic", + "serde", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "indoc" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" + +[[package]] +name = "instability" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf9fed6d91cfb734e7476a06bde8300a1b94e217e1b523b6f0cd1a01998c71d" +dependencies = [ + "darling", + "indoc", + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + +[[package]] +name = "linked_list_allocator" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286" + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" + +[[package]] +name = "managed" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minijinja" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e36f1329330bb1614c94b78632b9ce45dd7d761f3304a1bed07b2990a7c5097" +dependencies = [ + "serde", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "portable-atomic" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" + +[[package]] +name = "portable_atomic_enum" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d48f60c43e0120bb2bb48589a16d4bed2f4b911be41e299f2d0fc0e0e20885" +dependencies = [ + "portable-atomic", + "portable_atomic_enum_macros", +] + +[[package]] +name = "portable_atomic_enum_macros" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33fa6ec7f2047f572d49317cca19c87195de99c6e5b6ee492da701cfe02b053" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "postcard" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8" +dependencies = [ + "cobs", + "defmt", + "heapless 0.7.17", + "postcard-derive", + "serde", +] + +[[package]] +name = "postcard-derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0239fa9c1d225d4b7eb69925c25c5e082307a141e470573fbbe3a817ce6a7a37" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "protocol" +version = "0.1.0" +dependencies = [ + "defmt", + "heapless 0.8.0", + "postcard", + "serde", + "strum 0.26.3", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r0" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211" + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "riscv" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea8ff73d3720bdd0a97925f0bf79ad2744b6da8ff36be3840c48ac81191d7a7" +dependencies = [ + "critical-section", + "embedded-hal 1.0.0", + "paste", + "riscv-macros", + "riscv-pac", +] + +[[package]] +name = "riscv-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f265be5d634272320a7de94cea15c22a3bfdd4eb42eb43edc528415f066a1f25" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "riscv-pac" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" + +[[package]] +name = "riscv-rt-macros" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc71814687c45ba4cd1e47a54e03a2dbc62ca3667098fbae9cc6b423956758fa" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "smoltcp" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad095989c1533c1c266d9b1e8d70a1329dd3723c3edac6d03bbd67e7bf6f4bb" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "cfg-if", + "defmt", + "heapless 0.8.0", + "managed", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_cell" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89b0684884a883431282db1e4343f34afc2ff6996fe1f4a1664519b66e14c1e" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros 0.26.4", +] + +[[package]] +name = "strum" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" +dependencies = [ + "strum_macros 0.27.1", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.100", +] + +[[package]] +name = "strum_macros" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.100", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "toml" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml-cfg" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68c587298ddd135c156e92e8c3eae69614d6eecea8e2d8a09daab011e5e6a21d" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "serde", + "syn 2.0.100", + "toml", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "ufmt-write" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" +dependencies = [ + "memchr", +] + +[[package]] +name = "xtensa-lx" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51cbb46c78cfd284c9378070ab90bae9d14d38b3766cb853a97c0a137f736d5b" +dependencies = [ + "critical-section", + "document-features", +] + +[[package]] +name = "xtensa-lx-rt" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "689c2ef159d9cd4fc9503603e9999968a84a30db9bde0f0f880d0cceea0190a9" +dependencies = [ + "anyhow", + "document-features", + "enum-as-inner", + "minijinja", + "r0", + "serde", + "strum 0.26.3", + "toml", + "xtensa-lx", + "xtensa-lx-rt-proc-macros", +] + +[[package]] +name = "xtensa-lx-rt-proc-macros" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11277b1e4cbb7ffe44678c668518b249c843c81df249b8f096701757bc50d7ee" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.100", +] diff --git a/nodes/esp32/airbox/Cargo.toml b/nodes/esp32/airbox/Cargo.toml new file mode 100644 index 00000000..7610df6a --- /dev/null +++ b/nodes/esp32/airbox/Cargo.toml @@ -0,0 +1,78 @@ +[package] +edition = "2024" +name = "airbox" +version = "0.1.0" + +[dependencies] +defmt = "0.3.10" +embassy-net = { version = "0.6.0", features = [ + "dhcpv4", + "medium-ethernet", + "tcp", + "udp", + "defmt", +] } +embedded-io = "0.6.1" +embedded-io-async = "0.6.1" +esp-alloc = "0.7.0" +esp-backtrace = { version = "0.15.1", features = [ + "defmt", + "esp32c3", + "exception-handler", + "panic-handler", +] } +esp-hal = { version = "1.0.0-beta.0", features = [ + "defmt", + "esp32c3", + "unstable", +] } +esp-println = { version = "0.13.0", features = ["defmt-espflash", "esp32c3"] } +smoltcp = { version = "0.12.0", default-features = false, features = [ + "medium-ethernet", + "multicast", + "proto-dhcpv4", + "proto-dns", + "proto-ipv4", + "socket-dns", + "socket-icmp", + "socket-raw", + "socket-tcp", + "socket-udp", +] } +# for more networking protocol support see https://crates.io/crates/edge-net +critical-section = "1.2.0" +embassy-executor = { version = "0.7.0", features = [ + "defmt", + "task-arena-size-20480", +] } +embassy-time = { version = "0.4.0", features = ["generic-queue-8"] } +embassy-sync = { version = "0.6.2" } +embassy-futures = { version = "0.1.1" } +esp-hal-embassy = { version = "0.7.0", features = ["esp32c3"] } +esp-wifi = { version = "0.13.0", features = [ + "builtin-scheduler", + "defmt", + "esp-alloc", + "esp32c3", + "wifi", +] } +heapless = { version = "0.8.0", default-features = false } +static_cell = { version = "2.1.0", features = ["nightly"] } + +toml-cfg = "0.2" +protocol = { path = "../../../crates/protocol" } +bme280-rs = { version = "0.3.0", features = ["async"] } + +[profile.dev] +# Rust debug is too slow. +# For debug builds always builds with some optimization +opt-level = "s" + +[profile.release] +codegen-units = 1 # LLVM can perform better optimizations using a single thread +debug = 2 +debug-assertions = false +incremental = false +lto = 'fat' +opt-level = 's' +overflow-checks = false diff --git a/nodes/esp32/airbox/build.rs b/nodes/esp32/airbox/build.rs new file mode 100644 index 00000000..e0ec8f61 --- /dev/null +++ b/nodes/esp32/airbox/build.rs @@ -0,0 +1,41 @@ +fn main() { + linker_be_nice(); + println!("cargo:rustc-link-arg=-Tdefmt.x"); + // make sure linkall.x is the last linker script (otherwise might cause problems with flip-link) + println!("cargo:rustc-link-arg=-Tlinkall.x"); +} + +fn linker_be_nice() { + let args: Vec = std::env::args().collect(); + if args.len() > 1 { + let kind = &args[1]; + let what = &args[2]; + + match kind.as_str() { + "undefined-symbol" => match what.as_str() { + "_defmt_timestamp" => { + eprintln!(); + eprintln!("💡 `defmt` not found - make sure `defmt.x` is added as a linker script and you have included `use defmt_rtt as _;`"); + eprintln!(); + } + "_stack_start" => { + eprintln!(); + eprintln!("💡 Is the linker script `linkall.x` missing?"); + eprintln!(); + } + _ => (), + }, + // we don't have anything helpful for "missing-lib" yet + _ => { + std::process::exit(1); + } + } + + std::process::exit(0); + } + + println!( + "cargo:rustc-link-arg=--error-handling-script={}", + std::env::current_exe().unwrap().display() + ); +} diff --git a/nodes/esp32/airbox/rust-toolchain.toml b/nodes/esp32/airbox/rust-toolchain.toml new file mode 100644 index 00000000..30c6884b --- /dev/null +++ b/nodes/esp32/airbox/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "stable" +components = ["rust-src"] +targets = ["riscv32imc-unknown-none-elf"] diff --git a/nodes/esp32/airbox/src/fans.rs b/nodes/esp32/airbox/src/fans.rs new file mode 100644 index 00000000..1f01a655 --- /dev/null +++ b/nodes/esp32/airbox/src/fans.rs @@ -0,0 +1,76 @@ +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::mutex::Mutex; +use embassy_time::Instant; +use esp_hal::gpio::GpioPin; +use esp_hal::ledc::channel::{Channel, ChannelIFace, Number}; +use esp_hal::ledc::{LSGlobalClkSource, Ledc, LowSpeed}; +use esp_hal::peripherals::LEDC; +use protocol::large_bedroom::airbox::{DeviceError, Error}; +use protocol::make_error_string; + +use crate::wrap_error; + +pub struct Fans { + fan_channel: Channel<'static, LowSpeed>, + _control: Ledc<'static>, + transition: Mutex, +} + +struct Transition { + transition_started: Instant, + power_pre_transition: u8, + power_target: u8, +} + +impl Transition { + fn current_power(&self) -> u8 { + let target_change = + self.power_pre_transition as i8 - self.power_target as i8; + let progress = + self.transition_started.elapsed().as_millis() as f32 / 1000.0; + let progress = if progress > 1.0 { 1.0 } else { progress }; + + self.power_pre_transition + (progress * target_change as f32) as u8 + } + fn store_new_to(&mut self, target: u8) { + self.power_pre_transition = self.current_power(); + self.power_target = target; + self.transition_started = Instant::now(); + } +} + +impl Fans { + pub fn new(led_controller: LEDC, pwm_pin: GpioPin<3>) -> Self { + let mut control = Ledc::new(led_controller); + control.set_global_slow_clock(LSGlobalClkSource::APBClk); + let fan_channel = control.channel(Number::Channel0, pwm_pin); + let transition = Mutex::new(Transition { + transition_started: Instant::now(), + power_pre_transition: 0, + power_target: 0, + }); + Self { + _control: control, + fan_channel, + transition, + } + } + + pub async fn current_power(&self) -> u8 { + self.transition.lock().await.current_power() + } + + pub async fn set_power(&self, power: u8) -> Result<(), protocol::Error> { + if let Err(e) = self.fan_channel.start_duty_fade( + self.current_power().await, + power, + 1000, + ) { + return Err(wrap_error(Error::Running(DeviceError::Pwm( + make_error_string(e), + )))); + } + self.transition.lock().await.store_new_to(power); + Ok(()) + } +} diff --git a/nodes/esp32/airbox/src/main.rs b/nodes/esp32/airbox/src/main.rs new file mode 100644 index 00000000..f76efaea --- /dev/null +++ b/nodes/esp32/airbox/src/main.rs @@ -0,0 +1,105 @@ +#![no_std] +#![no_main] + +use embassy_futures::join::join3; +use embassy_net::StackResources; +use esp_hal::clock::CpuClock; +use esp_hal::rng::Rng; +use esp_hal::timer::systimer::SystemTimer; +use esp_hal::timer::timg::TimerGroup; + +use defmt::info; +use esp_println as _; + +use embassy_executor::Spawner; + +use esp_backtrace as _; +use esp_wifi::EspWifiController; + +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::channel::Channel; +use protocol::large_bedroom::airbox::Error; + +extern crate alloc; + +mod fans; +mod network; +mod sensor; + +#[toml_cfg::toml_config] +pub struct Config { + #[default("")] + wifi_ssid: &'static str, + #[default("")] + wifi_psk: &'static str, +} + +// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html +macro_rules! mk_static { + ($t:ty,$val:expr) => {{ + static STATIC_CELL: static_cell::StaticCell<$t> = + static_cell::StaticCell::new(); + #[deny(unused_attributes)] + let x = STATIC_CELL.uninit().write(($val)); + x + }}; +} + +type Queue = + Channel, 20>; + +#[esp_hal_embassy::main] +async fn main(spawner: Spawner) { + let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); + let peripherals = esp_hal::init(config); + let fans = fans::Fans::new(peripherals.LEDC, peripherals.GPIO3); + + esp_alloc::heap_allocator!(size: 72 * 1024); + + let timer0 = SystemTimer::new(peripherals.SYSTIMER); + esp_hal_embassy::init(timer0.alarm0); + + info!("Embassy initialized!"); + + let timg0 = TimerGroup::new(peripherals.TIMG0); + let mut rng = Rng::new(peripherals.RNG); + + let esp_wifi_ctrl = &*mk_static!( + EspWifiController<'static>, + esp_wifi::init(timg0.timer0, rng, peripherals.RADIO_CLK).unwrap() + ); + + let (controller, interfaces) = + esp_wifi::wifi::new(esp_wifi_ctrl, peripherals.WIFI).unwrap(); + let wifi_interface = interfaces.sta; + + let timg1 = TimerGroup::new(peripherals.TIMG1); + esp_hal_embassy::init(timg1.timer0); + + let config = embassy_net::Config::dhcpv4(Default::default()); + + let seed = ((rng.random() as u64) << 32) | rng.random() as u64; + + // Init network stack + let (stack, runner) = embassy_net::new( + wifi_interface, + config, + mk_static!(StackResources<3>, StackResources::<3>::new()), + seed, + ); + + spawner.spawn(network::connection(controller)).ok(); + spawner.spawn(network::net_task(runner)).ok(); + + let queue = Channel::new(); + join3( + network::handle(&stack, &queue, &fans), + sensor::button(peripherals.GPIO10, &queue, &fans), + sensor::measure(peripherals.I2C0, &queue), + ) + .await; +} + +fn wrap_error(error: Error) -> protocol::Error { + protocol::Error::LargeBedroom(protocol::large_bedroom::Error::Airbox(error)) +} diff --git a/nodes/esp32/airbox/src/network.rs b/nodes/esp32/airbox/src/network.rs new file mode 100644 index 00000000..dce9f30f --- /dev/null +++ b/nodes/esp32/airbox/src/network.rs @@ -0,0 +1,221 @@ +use defmt::{debug, info, unwrap, warn}; +use embassy_futures::select::{self, select}; +use embassy_net::tcp::{TcpReader, TcpSocket, TcpWriter}; +use embassy_net::{Ipv4Address, Runner}; +use embassy_time::{Duration, Timer}; +use embedded_io_async::Write; +use esp_wifi::wifi::{ + ClientConfiguration, Configuration, WifiController, WifiDevice, WifiEvent, + WifiState, +}; +use protocol::affector::DeserializeError; +use protocol::large_bedroom::airbox; +use protocol::{Affector, ErrorReport, affector}; + +use crate::fans::Fans; +use crate::{CONFIG, Queue}; +type SensMsg = protocol::SensorMessage<10>; + +const fn max(a: usize, b: usize) -> usize { + [a, b][(a < b) as usize] +} + +pub async fn handle( + stack: &embassy_net::Stack<'_>, + publish: &Queue, + fans: &Fans, +) { + let mut rx_buffer = [0; 1024]; + let mut tx_buffer = + [0; max(SensMsg::ENCODED_SIZE, protocol::ErrorReport::ENCODED_SIZE) + * 2]; + + let mut socket = TcpSocket::new(*stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(Duration::from_secs(5))); + socket.set_keep_alive(Some(Duration::from_secs(1))); + let host_addr = Ipv4Address::new(192, 168, 1, 43); + let host_port = 1234; + + debug!("Configured socket and connecting"); + loop { + debug!("socket state: {:?}", socket.state()); + if let Err(e) = socket.connect((host_addr, host_port)).await { + warn!("connect error: {}", e); + Timer::after_secs(5).await; + continue; + } + + info!("(re-)connected"); + // Prevent out-dated data from being send + publish.clear(); + + let (reader, writer) = socket.split(); + match select( + send_messages(writer, publish), + receive_orders(reader, fans, publish), + ) + .await + { + select::Either::First(e) => { + warn!("Error while sending messages: {}", e) + } + select::Either::Second(e) => warn!("Error receiving orders: {}", e), + }; + // Or the socket will hang for a while waiting to close this makes sure + // we can reconnect instantly + socket.abort(); + Timer::after_secs(60).await; // Experiment: does this help? + } +} + +async fn send_messages( + mut tcp: TcpWriter<'_>, + publish: &Queue, +) -> embassy_net::tcp::Error { + let mut buf = [0; 1 + max( + max(SensMsg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE), + affector::ListMessage::<5>::ENCODED_SIZE, + )]; + let encoded_len = affector_list().encode_slice(&mut buf[1..]).len(); + buf[0] = protocol::Msg::<5>::AFFECTOR_LIST; + let to_send = &buf[..=encoded_len]; + if let Err(e) = tcp.write_all(to_send).await { + return e; + } + if let Err(e) = tcp.flush().await { + return e; + } + + loop { + let to_send = match publish.receive().await { + Ok(reading) => { + let mut msg = SensMsg::default(); + defmt::unwrap!(msg.values.push(reading)); + let encoded_len = msg.encode_slice(&mut buf[1..]).len(); + buf[0] = protocol::Msg::<0>::READINGS; + &buf[..=encoded_len] + } + Err(error) => { + let encoded_len = + ErrorReport::new(error).encode_slice(&mut buf[1..]).len(); + buf[0] = protocol::Msg::<0>::ERROR_REPORT; + &buf[..=encoded_len] + } + }; + + if let Err(e) = tcp.write_all(to_send).await { + return e; + } + if let Err(e) = tcp.flush().await { + return e; + } + } +} + +#[derive(defmt::Format)] +enum ReadError { + ConnectionClosed, + TcpError(embassy_net::tcp::Error), + Deserialize(DeserializeError), +} + +async fn receive_orders( + mut tcp: TcpReader<'_>, + fans: &Fans, + publish: &Queue, +) -> ReadError { + defmt::debug!("ready to receive orders"); + let mut decoder = protocol::affector::Decoder::default(); + let mut buf = [0u8; 100]; + loop { + let res = tcp.read(&mut buf).await; + let n_read = match res { + Ok(0) => return ReadError::ConnectionClosed, + Ok(n_read) => n_read, + Err(e) => return ReadError::TcpError(e), + }; + let mut read = &buf[..n_read]; + + loop { + let (item, remaining) = match decoder.feed(read) { + Ok(Some((item, remaining))) => (item, remaining), + Ok(None) => break, + Err(e) => return ReadError::Deserialize(e), + }; + + read = remaining; + + let protocol::Affector::LargeBedroom( + protocol::large_bedroom::Affector::Airbox(affector), + ) = item + else { + defmt::error!("Got affector for other node"); + continue; + }; + + defmt::info!("got affector order: {:?}", affector); + match affector { + protocol::large_bedroom::airbox::Affector::FanPower { + power, + } => { + if let Err(e) = fans.set_power(power).await { + publish.send(Err(e)).await; + } + } + protocol::large_bedroom::airbox::Affector::ResetNode => todo!(), + } + } + } +} + +#[embassy_executor::task] +pub async fn net_task(mut runner: Runner<'static, WifiDevice<'static>>) { + runner.run().await +} + +#[embassy_executor::task] +pub async fn connection(mut controller: WifiController<'static>) { + defmt::info!("start connection task"); + loop { + if esp_wifi::wifi::wifi_state() == WifiState::StaConnected { + // Wait until we're no longer connected + controller.wait_for_event(WifiEvent::StaDisconnected).await; + Timer::after(Duration::from_millis(5000)).await + } + if !matches!(controller.is_started(), Ok(true)) { + let client_config = Configuration::Client(ClientConfiguration { + // The constant `CONFIG` is auto-generated by `toml_config`. + ssid: CONFIG.wifi_ssid.try_into().unwrap(), + password: CONFIG.wifi_psk.try_into().unwrap(), + ..Default::default() + }); + controller.set_configuration(&client_config).unwrap(); + defmt::info!("Starting wifi"); + controller.start_async().await.unwrap(); + defmt::info!("Wifi started!"); + } + defmt::info!("About to connect..."); + + match controller.connect_async().await { + Ok(_) => defmt::info!("Wifi connected!"), + Err(e) => { + defmt::info!("Failed to connect to wifi: {}", e); + Timer::after(Duration::from_millis(5000)).await + } + } + } +} + +fn affector_list() -> affector::ListMessage<2> { + let mut list = affector::ListMessage::<2>::empty(); + unwrap!(list.values.push(Affector::LargeBedroom( + protocol::large_bedroom::Affector::Airbox(airbox::Affector::FanPower { + power: 0, + }), + ))); + unwrap!(list.values.push(Affector::LargeBedroom( + protocol::large_bedroom::Affector::Airbox(airbox::Affector::ResetNode) + ))); + + list +} diff --git a/nodes/esp32/airbox/src/sensor.rs b/nodes/esp32/airbox/src/sensor.rs new file mode 100644 index 00000000..7eb718c3 --- /dev/null +++ b/nodes/esp32/airbox/src/sensor.rs @@ -0,0 +1,71 @@ +use bme280_rs::{AsyncBme280, Sample}; +use embassy_time::{Delay, Timer}; +use esp_hal::gpio::{GpioPin, Input, InputConfig, Pull}; +use esp_hal::i2c::master::{Config, I2c}; +use esp_hal::peripherals::I2C0; +use protocol::button::Press; +use protocol::large_bedroom::airbox::{DeviceError, Error, Reading}; +use protocol::{large_bedroom, make_error_string}; + +use crate::fans::Fans; +use crate::{Queue, wrap_error}; + +fn wrap_reading(reading: Reading) -> protocol::Reading { + protocol::Reading::LargeBedroom(large_bedroom::Reading::Airbox(reading)) +} + +pub async fn button(pin: GpioPin<10>, queue: &Queue, fans: &Fans) { + let mut input = Input::new(pin, InputConfig::default().with_pull(Pull::Up)); + + loop { + // TODO measure press time, deduplicate with bed_lb & bed_sb + input.wait_for_low().await; + queue + .send(Ok(wrap_reading(Reading::Button(Press(1))))) + .await; + + let next_power = (fans.current_power().await + 20).next_multiple_of(20); + let next_power = if next_power > 100 { 0 } else { next_power }; + + if let Err(e) = fans.set_power(next_power).await { + queue.send(Err(e)).await; + } + + Timer::after_millis(100).await; + } +} + +pub async fn measure(i2c: I2C0, queue: &Queue) { + let i2c = match I2c::new(i2c, Config::default()) { + Ok(i2c) => i2c, + Err(e) => { + let report = + Error::Setup(DeviceError::BmeError(make_error_string(e))); + queue.send(Err(wrap_error(report))).await; + return; + } + } + .into_async(); + let mut bme = AsyncBme280::new(i2c, Delay); + + loop { + match bme.read_sample().await { + Ok(Sample { + pressure: Some(p), + temperature: Some(t), + .. + }) => { + queue.send(Ok(wrap_reading(Reading::Temperature(t)))).await; + queue.send(Ok(wrap_reading(Reading::Pressure(p)))).await; + } + Ok(_) => { + defmt::unreachable!("pressure and temperature are enabled") + } + Err(e) => { + let report = + Error::Running(DeviceError::BmeError(make_error_string(e))); + queue.send(Err(wrap_error(report))).await; + } + } + } +} diff --git a/nodes/esp32/airbox/template.yaml b/nodes/esp32/airbox/template.yaml new file mode 100644 index 00000000..990c8aa1 --- /dev/null +++ b/nodes/esp32/airbox/template.yaml @@ -0,0 +1,149 @@ +options: + - !Option + name: unstable-hal + display_name: Enable unstable HAL features. + help: "This configuration enables unstable esp-hal features. + These come with no stability guarantees, and could be changed or removed at any time." + + - !Option + name: alloc + display_name: Enable allocations via the esp-alloc crate. + help: esp-alloc comes with no stability guarantees at this time. + + - !Option + name: wifi + display_name: Enable Wi-Fi via the esp-wifi crate. + help: esp-wifi comes with no stability guarantees at this time. + requires: + - alloc + - unstable-hal + chips: + - esp32 + - esp32c2 + - esp32c3 + - esp32c6 + - esp32s2 + - esp32s3 + + - !Option + name: ble + display_name: Enable BLE via the esp-wifi crate. + help: esp-wifi comes with no stability guarantees at this time. + requires: + - alloc + - unstable-hal + chips: + - esp32 + - esp32c2 + - esp32c3 + - esp32c6 + - esp32h2 + - esp32s3 + + - !Option + name: embassy + display_name: Add embassy framework support. + help: esp-hal-embassy comes with no stability guarantees at this time. + requires: + - unstable-hal + + - !Option + name: probe-rs + display_name: Use probe-rs to flash and monitor instead of espflash. + help: probe-rs is a debugger that connects to the chips over JTAG. It can be used to flash and + monitor, and it can also be used to interactively debug an application, or run tests on the + hardware. Semihosting or RTT-based technologies like defmt-rtt require probe-rs. + chips: + - esp32c6 + - esp32h2 + - esp32s3 + + - !Option + name: probe-rs + display_name: Use probe-rs to flash and monitor instead of espflash. + help: probe-rs is a debugger that connects to the chips over JTAG. It can be used to flash and + monitor, and it can also be used to interactively debug an application, or run tests on the + hardware. Semihosting or RTT-based technologies like defmt-rtt require probe-rs. + + probe-rs requires a debug probe like esp-prog, and will not work with USB-UART adapters that + often come on development boards. + chips: + - esp32 + - esp32s2 + - esp32c2 + - esp32c3 + + - !Category + name: flashing-probe-rs + display_name: Flashing, logging and debugging (probe-rs) + requires: + - probe-rs + options: + - !Option + name: defmt + display_name: Use defmt to print messages. + selection_group: log-frontend + - !Option + name: panic-rtt-target + display_name: Use panic-rtt-target as the panic handler. + selection_group: panic-handler + requires: + - probe-rs + + - !Category + name: flashing-espflash + display_name: Flashing, logging and debugging (espflash) + requires: + - "!probe-rs" + options: + - !Option + name: log + display_name: Use the log crate to print messages. + selection_group: log-frontend + requires: + - "!probe-rs" + - !Option + name: defmt + display_name: Use defmt to print messages. + selection_group: log-frontend + - !Option + name: esp-backtrace + display_name: Use esp-backtrace as the panic handler. + selection_group: panic-handler + requires: + - "!probe-rs" + + - !Category + name: optional + display_name: Options + options: + - !Option + name: wokwi + display_name: Add support for Wokwi simulation using VS Code Wokwi extension. + chips: + - esp32 + - esp32c3 + - esp32c6 + - esp32h2 + - esp32s2 + - esp32s3 + + - !Option + name: dev-container + display_name: Add support for VS Code Dev Containers and GitHub Codespaces. + + - !Option + name: ci + display_name: Add GitHub Actions support with some basic checks. + + - !Category + name: editor + display_name: Optional editor config files for rust-analyzer + options: + - !Option + name: helix + display_name: Add rust-analyzer settings for Helix Editor + + - !Option + name: vscode + display_name: Add rust-analyzer settings for Visual Studio Code From 43774ce5f38468764694d869a56faed33c5e8261 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 19 Mar 2025 17:48:27 +0100 Subject: [PATCH 606/687] fix esp main setup --- nodes/esp32/airbox/src/main.rs | 11 +++-------- nodes/esp32/airbox/src/network.rs | 1 + 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/nodes/esp32/airbox/src/main.rs b/nodes/esp32/airbox/src/main.rs index f76efaea..1404ae08 100644 --- a/nodes/esp32/airbox/src/main.rs +++ b/nodes/esp32/airbox/src/main.rs @@ -8,7 +8,6 @@ use esp_hal::rng::Rng; use esp_hal::timer::systimer::SystemTimer; use esp_hal::timer::timg::TimerGroup; -use defmt::info; use esp_println as _; use embassy_executor::Spawner; @@ -50,17 +49,13 @@ type Queue = #[esp_hal_embassy::main] async fn main(spawner: Spawner) { + defmt::warn!("started"); let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); let peripherals = esp_hal::init(config); let fans = fans::Fans::new(peripherals.LEDC, peripherals.GPIO3); esp_alloc::heap_allocator!(size: 72 * 1024); - let timer0 = SystemTimer::new(peripherals.SYSTIMER); - esp_hal_embassy::init(timer0.alarm0); - - info!("Embassy initialized!"); - let timg0 = TimerGroup::new(peripherals.TIMG0); let mut rng = Rng::new(peripherals.RNG); @@ -73,8 +68,8 @@ async fn main(spawner: Spawner) { esp_wifi::wifi::new(esp_wifi_ctrl, peripherals.WIFI).unwrap(); let wifi_interface = interfaces.sta; - let timg1 = TimerGroup::new(peripherals.TIMG1); - esp_hal_embassy::init(timg1.timer0); + let systimer = SystemTimer::new(peripherals.SYSTIMER); + esp_hal_embassy::init(systimer.alarm0); let config = embassy_net::Config::dhcpv4(Default::default()); diff --git a/nodes/esp32/airbox/src/network.rs b/nodes/esp32/airbox/src/network.rs index dce9f30f..02f1a067 100644 --- a/nodes/esp32/airbox/src/network.rs +++ b/nodes/esp32/airbox/src/network.rs @@ -195,6 +195,7 @@ pub async fn connection(mut controller: WifiController<'static>) { defmt::info!("Wifi started!"); } defmt::info!("About to connect..."); + defmt::info!("{}, {}", CONFIG.wifi_ssid, CONFIG.wifi_psk); match controller.connect_async().await { Ok(_) => defmt::info!("Wifi connected!"), From 3e65c7cded02d6312d0b88573a5b6cee7f05064f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 19 Mar 2025 19:10:11 +0100 Subject: [PATCH 607/687] fix broken is_same_as for airbox --- crates/protocol/src/large_bedroom/airbox.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/protocol/src/large_bedroom/airbox.rs b/crates/protocol/src/large_bedroom/airbox.rs index 60e961f3..91257cca 100644 --- a/crates/protocol/src/large_bedroom/airbox.rs +++ b/crates/protocol/src/large_bedroom/airbox.rs @@ -36,7 +36,7 @@ pub enum Reading { Button(Press) = 3, } -impl_is_same_as! {Reading; Temperature, Pressure} +impl_is_same_as! {Reading; Temperature, Pressure, FanPower, Button} #[cfg(feature = "alloc")] impl Tree for Reading { @@ -153,7 +153,7 @@ impl core::fmt::Display for DeviceError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { DeviceError::BmeError(e) => write!(f, "Bme error: {e}"), - DeviceError::Pwm(e) => write!(f, "Pwm error: {e}"), + DeviceError::Pwm(e) => write!(f, "Pwm error:{e}"), } } } From 5d4dd217fada4cc1db20f1cedb988c10c36eaa54 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 20 Mar 2025 18:56:26 +0100 Subject: [PATCH 608/687] fixes to fan button --- nodes/esp32/airbox/.cargo/config.toml | 1 + nodes/esp32/airbox/src/fans.rs | 65 +++++++++++---- nodes/esp32/airbox/src/main.rs | 71 +++++++++------- nodes/esp32/airbox/src/network.rs | 14 +++- nodes/esp32/airbox/src/sensor.rs | 114 +++++++++++++++++++++----- 5 files changed, 195 insertions(+), 70 deletions(-) diff --git a/nodes/esp32/airbox/.cargo/config.toml b/nodes/esp32/airbox/.cargo/config.toml index ae85381c..624f450e 100644 --- a/nodes/esp32/airbox/.cargo/config.toml +++ b/nodes/esp32/airbox/.cargo/config.toml @@ -3,6 +3,7 @@ runner = "espflash flash --monitor --chip esp32c3 --log-format defmt" [env] DEFMT_LOG="info" +ESP_WIFI_COUNTRY_CODE = "NL" [build] rustflags = [ diff --git a/nodes/esp32/airbox/src/fans.rs b/nodes/esp32/airbox/src/fans.rs index 1f01a655..bbfd9892 100644 --- a/nodes/esp32/airbox/src/fans.rs +++ b/nodes/esp32/airbox/src/fans.rs @@ -2,17 +2,24 @@ use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; use embassy_time::Instant; use esp_hal::gpio::GpioPin; -use esp_hal::ledc::channel::{Channel, ChannelIFace, Number}; -use esp_hal::ledc::{LSGlobalClkSource, Ledc, LowSpeed}; +use esp_hal::ledc::channel::{self, Channel, ChannelIFace, Number}; +use esp_hal::ledc::timer::{Timer, TimerIFace}; +use esp_hal::ledc::{LSGlobalClkSource, Ledc, LowSpeed, timer}; use esp_hal::peripherals::LEDC; +use esp_hal::time::Rate; use protocol::large_bedroom::airbox::{DeviceError, Error}; use protocol::make_error_string; use crate::wrap_error; -pub struct Fans { - fan_channel: Channel<'static, LowSpeed>, - _control: Ledc<'static>, +/// stack allocated parts of Fans +pub struct FanStack { + control: Ledc<'static>, + timer: Timer<'static, LowSpeed>, +} + +pub struct Fans<'a> { + fan_channel: Channel<'a, LowSpeed>, transition: Mutex, } @@ -23,14 +30,22 @@ struct Transition { } impl Transition { + fn fade_time(&self, target: u8) -> u16 { + const RATE: u16 = 2000 / 100; + let target_change = target as i8 - self.current_power() as i8; + let target_change = target_change.abs() as u16; + target_change * RATE + } fn current_power(&self) -> u8 { let target_change = - self.power_pre_transition as i8 - self.power_target as i8; + self.power_target as i8 - self.power_pre_transition as i8; let progress = self.transition_started.elapsed().as_millis() as f32 / 1000.0; let progress = if progress > 1.0 { 1.0 } else { progress }; - self.power_pre_transition + (progress * target_change as f32) as u8 + let curr = self.power_pre_transition as i8 + + (progress * target_change as f32) as i8; + curr as u8 } fn store_new_to(&mut self, target: u8) { self.power_pre_transition = self.current_power(); @@ -39,18 +54,34 @@ impl Transition { } } -impl Fans { - pub fn new(led_controller: LEDC, pwm_pin: GpioPin<3>) -> Self { +impl FanStack { + pub fn new(led_controller: LEDC) -> Self { let mut control = Ledc::new(led_controller); control.set_global_slow_clock(LSGlobalClkSource::APBClk); - let fan_channel = control.channel(Number::Channel0, pwm_pin); + let mut timer = control.timer(timer::Number::Timer0); + defmt::unwrap!(timer.configure(timer::config::Config { + duty: timer::config::Duty::Duty10Bit, + clock_source: timer::LSClockSource::APBClk, + frequency: Rate::from_khz(24), + })); + FanStack { control, timer } + } +} + +impl<'a> Fans<'a> { + pub fn new(stack: &'a FanStack, pwm_pin: GpioPin<3>) -> Self { + let mut fan_channel = stack.control.channel(Number::Channel0, pwm_pin); + defmt::unwrap!(fan_channel.configure(channel::config::Config { + timer: &stack.timer, + duty_pct: 10, + pin_config: channel::config::PinConfig::PushPull, + })); let transition = Mutex::new(Transition { transition_started: Instant::now(), power_pre_transition: 0, power_target: 0, }); Self { - _control: control, fan_channel, transition, } @@ -60,17 +91,21 @@ impl Fans { self.transition.lock().await.current_power() } - pub async fn set_power(&self, power: u8) -> Result<(), protocol::Error> { + pub async fn fade_time(&self, target: u8) -> u16 { + self.transition.lock().await.fade_time(target) + } + + pub async fn set_power(&self, target: u8) -> Result<(), protocol::Error> { if let Err(e) = self.fan_channel.start_duty_fade( self.current_power().await, - power, - 1000, + target, + self.fade_time(target).await, ) { return Err(wrap_error(Error::Running(DeviceError::Pwm( make_error_string(e), )))); } - self.transition.lock().await.store_new_to(power); + self.transition.lock().await.store_new_to(target); Ok(()) } } diff --git a/nodes/esp32/airbox/src/main.rs b/nodes/esp32/airbox/src/main.rs index 1404ae08..51e38f13 100644 --- a/nodes/esp32/airbox/src/main.rs +++ b/nodes/esp32/airbox/src/main.rs @@ -1,8 +1,10 @@ #![no_std] #![no_main] -use embassy_futures::join::join3; -use embassy_net::StackResources; +use core::net::Ipv4Addr; + +use embassy_futures::join::{self, join3}; +use embassy_net::{Ipv4Cidr, StackResources}; use esp_hal::clock::CpuClock; use esp_hal::rng::Rng; use esp_hal::timer::systimer::SystemTimer; @@ -50,49 +52,60 @@ type Queue = #[esp_hal_embassy::main] async fn main(spawner: Spawner) { defmt::warn!("started"); - let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); + let config = esp_hal::Config::default().with_cpu_clock(CpuClock::default()); let peripherals = esp_hal::init(config); - let fans = fans::Fans::new(peripherals.LEDC, peripherals.GPIO3); esp_alloc::heap_allocator!(size: 72 * 1024); - let timg0 = TimerGroup::new(peripherals.TIMG0); - let mut rng = Rng::new(peripherals.RNG); + // let timg0 = TimerGroup::new(peripherals.TIMG0); + // let mut rng = Rng::new(peripherals.RNG); - let esp_wifi_ctrl = &*mk_static!( - EspWifiController<'static>, - esp_wifi::init(timg0.timer0, rng, peripherals.RADIO_CLK).unwrap() - ); + // let esp_wifi_ctrl = &*mk_static!( + // EspWifiController<'static>, + // esp_wifi::init(timg0.timer0, rng, peripherals.RADIO_CLK).unwrap() + // ); - let (controller, interfaces) = - esp_wifi::wifi::new(esp_wifi_ctrl, peripherals.WIFI).unwrap(); - let wifi_interface = interfaces.sta; + // let (controller, interfaces) = + // esp_wifi::wifi::new(esp_wifi_ctrl, peripherals.WIFI).unwrap(); + // let wifi_interface = interfaces.sta; let systimer = SystemTimer::new(peripherals.SYSTIMER); esp_hal_embassy::init(systimer.alarm0); - let config = embassy_net::Config::dhcpv4(Default::default()); - - let seed = ((rng.random() as u64) << 32) | rng.random() as u64; - - // Init network stack - let (stack, runner) = embassy_net::new( - wifi_interface, - config, - mk_static!(StackResources<3>, StackResources::<3>::new()), - seed, - ); - - spawner.spawn(network::connection(controller)).ok(); - spawner.spawn(network::net_task(runner)).ok(); + // let config = + // embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { + // address: Ipv4Cidr::new(Ipv4Addr::new(192, 168, 1, 8), 24), + // gateway: Some(Ipv4Addr::new(192, 168, 1, 1)), + // dns_servers: heapless::Vec::new(), + // }); + // + // let seed = ((rng.random() as u64) << 32) | rng.random() as u64; + + // // Init network stack + // let (stack, runner) = embassy_net::new( + // wifi_interface, + // config, + // mk_static!(StackResources<3>, StackResources::<3>::new()), + // seed, + // ); + + // spawner.spawn(network::connection(controller)).ok(); + // spawner.spawn(network::net_task(runner)).ok(); let queue = Channel::new(); - join3( - network::handle(&stack, &queue, &fans), + let fan_stack = fans::FanStack::new(peripherals.LEDC); + let fans = fans::Fans::new(&fan_stack, peripherals.GPIO3); + join::join( sensor::button(peripherals.GPIO10, &queue, &fans), sensor::measure(peripherals.I2C0, &queue), ) .await; + // join3( + // network::handle(&stack, &queue, &fans), + // sensor::button(peripherals.GPIO10, &queue, &fans), + // sensor::measure(peripherals.I2C0, &queue), + // ) + // .await; } fn wrap_error(error: Error) -> protocol::Error { diff --git a/nodes/esp32/airbox/src/network.rs b/nodes/esp32/airbox/src/network.rs index 02f1a067..282f05fa 100644 --- a/nodes/esp32/airbox/src/network.rs +++ b/nodes/esp32/airbox/src/network.rs @@ -23,7 +23,7 @@ const fn max(a: usize, b: usize) -> usize { pub async fn handle( stack: &embassy_net::Stack<'_>, publish: &Queue, - fans: &Fans, + fans: &Fans<'_>, ) { let mut rx_buffer = [0; 1024]; let mut tx_buffer = @@ -38,6 +38,7 @@ pub async fn handle( debug!("Configured socket and connecting"); loop { + info!("ip: {}", stack.config_v4().map(|config| config.address)); debug!("socket state: {:?}", socket.state()); if let Err(e) = socket.connect((host_addr, host_port)).await { warn!("connect error: {}", e); @@ -121,7 +122,7 @@ enum ReadError { async fn receive_orders( mut tcp: TcpReader<'_>, - fans: &Fans, + fans: &Fans<'_>, publish: &Queue, ) -> ReadError { defmt::debug!("ready to receive orders"); @@ -159,7 +160,8 @@ async fn receive_orders( power, } => { if let Err(e) = fans.set_power(power).await { - publish.send(Err(e)).await; + defmt::error!("could not set fan power: {}", e); + let _ignore_err = publish.try_send(Err(e)); } } protocol::large_bedroom::airbox::Affector::ResetNode => todo!(), @@ -198,9 +200,13 @@ pub async fn connection(mut controller: WifiController<'static>) { defmt::info!("{}, {}", CONFIG.wifi_ssid, CONFIG.wifi_psk); match controller.connect_async().await { - Ok(_) => defmt::info!("Wifi connected!"), + Ok(()) => { + defmt::info!("Wifi connected!") + } Err(e) => { defmt::info!("Failed to connect to wifi: {}", e); + let scan_res = controller.scan_n_async::<12>().await; + defmt::info!("Scan results: {}", scan_res); Timer::after(Duration::from_millis(5000)).await } } diff --git a/nodes/esp32/airbox/src/sensor.rs b/nodes/esp32/airbox/src/sensor.rs index 7eb718c3..120f241b 100644 --- a/nodes/esp32/airbox/src/sensor.rs +++ b/nodes/esp32/airbox/src/sensor.rs @@ -1,10 +1,11 @@ use bme280_rs::{AsyncBme280, Sample}; -use embassy_time::{Delay, Timer}; +use embassy_time::{Delay, Duration, TimeoutError, Timer, WithTimeout}; use esp_hal::gpio::{GpioPin, Input, InputConfig, Pull}; use esp_hal::i2c::master::{Config, I2c}; use esp_hal::peripherals::I2C0; +use esp_hal::time::Rate; use protocol::button::Press; -use protocol::large_bedroom::airbox::{DeviceError, Error, Reading}; +use protocol::large_bedroom::airbox::{Device, DeviceError, Error, Reading}; use protocol::{large_bedroom, make_error_string}; use crate::fans::Fans; @@ -14,58 +15,127 @@ fn wrap_reading(reading: Reading) -> protocol::Reading { protocol::Reading::LargeBedroom(large_bedroom::Reading::Airbox(reading)) } -pub async fn button(pin: GpioPin<10>, queue: &Queue, fans: &Fans) { +fn next_fan_power(current: u8) -> u8 { + let next = match current { + ..15 => 20, + 15..35 => 40, + 35..55 => 60, + 55..75 => 80, + 75..95 => 100, + 95.. => 0, + }; + defmt::info!("current: {}, next_power: {}", current, next); + next +} + +pub async fn button(pin: GpioPin<10>, queue: &Queue, fans: &Fans<'_>) { let mut input = Input::new(pin, InputConfig::default().with_pull(Pull::Up)); loop { // TODO measure press time, deduplicate with bed_lb & bed_sb input.wait_for_low().await; - queue - .send(Ok(wrap_reading(Reading::Button(Press(1))))) - .await; + Timer::after_millis(50).await; + if input.is_high() { + continue + } - let next_power = (fans.current_power().await + 20).next_multiple_of(20); - let next_power = if next_power > 100 { 0 } else { next_power }; + let _ignore_err = + queue.try_send(Ok(wrap_reading(Reading::Button(Press(1))))); - if let Err(e) = fans.set_power(next_power).await { - queue.send(Err(e)).await; + let next = next_fan_power(fans.current_power().await); + if let Err(e) = fans.set_power(next).await { + defmt::error!("error setting fan power: {}", e); + let _ignore_err = queue.try_send(Err(e)); } - Timer::after_millis(100).await; + Timer::after_millis(500).await; } } pub async fn measure(i2c: I2C0, queue: &Queue) { - let i2c = match I2c::new(i2c, Config::default()) { + defmt::info!("HOI"); + let i2c = match I2c::new( + i2c, + Config::default().with_frequency(Rate::from_khz(4)), + ) { Ok(i2c) => i2c, Err(e) => { + defmt::error!("Could not start i2c"); let report = Error::Setup(DeviceError::BmeError(make_error_string(e))); - queue.send(Err(wrap_error(report))).await; + let _ignore_err = queue.try_send(Err(wrap_error(report))); return; } } .into_async(); - let mut bme = AsyncBme280::new(i2c, Delay); + let mut i2c = Some(i2c); loop { - match bme.read_sample().await { - Ok(Sample { + let mut bme = AsyncBme280::new(defmt::unwrap!(i2c.take()), Delay); + match bme.init().with_timeout(Duration::from_millis(200)).await { + Ok(Ok(())) => (), + Ok(Err(e)) => { + defmt::error!("Could not init bme280: {}", e); + let report = + Error::Setup(DeviceError::BmeError(make_error_string(e))); + let _ignore_err = queue.try_send(Err(wrap_error(report))); + i2c = Some(bme.release()); + continue; + } + Err(TimeoutError) => { + defmt::error!("Could not init bme280, timeout"); + let report = Error::SetupTimedOut(Device::Bme280); + let _ignore_err = queue.try_send(Err(wrap_error(report))); + i2c = Some(bme.release()); + continue; + } + } + + read_every_5_seconds_until_error(queue, &mut bme).await; + i2c = Some(bme.release()); + Timer::after_secs(5).await; + } +} + +async fn read_every_5_seconds_until_error( + queue: &Queue, + bme: &mut AsyncBme280, Delay>, +) { + loop { + defmt::info!("loop start"); + match bme + .read_sample() + .with_timeout(Duration::from_millis(200)) + .await + { + Ok(Ok(Sample { pressure: Some(p), temperature: Some(t), .. - }) => { - queue.send(Ok(wrap_reading(Reading::Temperature(t)))).await; - queue.send(Ok(wrap_reading(Reading::Pressure(p)))).await; + })) => { + defmt::info!("pressure: {}, temperature: {}", p, t); + let _ignore_err = + queue.try_send(Ok(wrap_reading(Reading::Temperature(t)))); + let _ignore_err = + queue.try_send(Ok(wrap_reading(Reading::Pressure(p)))); } - Ok(_) => { + Ok(Ok(_)) => { defmt::unreachable!("pressure and temperature are enabled") } - Err(e) => { + Ok(Err(e)) => { + defmt::error!("Could not read bme280"); let report = Error::Running(DeviceError::BmeError(make_error_string(e))); - queue.send(Err(wrap_error(report))).await; + let _ignore_err = queue.try_send(Err(wrap_error(report))); + return; + } + Err(TimeoutError) => { + defmt::error!("Could not read bme280, timeout"); + let report = Error::Timeout(Device::Bme280); + let _ignore_err = queue.try_send(Err(wrap_error(report))); + return; } } + Timer::after_secs(5).await; } } From c657bf2c06595cd80f58b21096ee5599f2579002 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 20 Mar 2025 19:13:55 +0100 Subject: [PATCH 609/687] update embassy to latest version --- nodes/embassy/Cargo.lock | 51 +++++++++++++++++---------------- nodes/embassy/Cargo.toml | 32 ++++++++++----------- nodes/embassy/bed-sb/Cargo.toml | 2 +- 3 files changed, 43 insertions(+), 42 deletions(-) diff --git a/nodes/embassy/Cargo.lock b/nodes/embassy/Cargo.lock index 5b514baa..024eba42 100644 --- a/nodes/embassy/Cargo.lock +++ b/nodes/embassy/Cargo.lock @@ -265,11 +265,12 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" -version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +version = "0.3.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", "embassy-futures", + "embassy-hal-internal", "embassy-sync", "embassy-time", "embedded-hal 0.2.7", @@ -283,7 +284,7 @@ dependencies = [ [[package]] name = "embassy-executor" version = "0.7.0" -source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "cortex-m", "critical-section", @@ -295,7 +296,7 @@ dependencies = [ [[package]] name = "embassy-executor-macros" version = "0.6.2" -source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "darling", "proc-macro2", @@ -306,12 +307,12 @@ dependencies = [ [[package]] name = "embassy-futures" version = "0.1.1" -source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" [[package]] name = "embassy-hal-internal" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "cortex-m", "critical-section", @@ -321,8 +322,8 @@ dependencies = [ [[package]] name = "embassy-net" -version = "0.5.0" -source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +version = "0.7.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", "document-features", @@ -339,7 +340,7 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", ] @@ -347,7 +348,7 @@ dependencies = [ [[package]] name = "embassy-net-driver-channel" version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "embassy-futures", "embassy-net-driver", @@ -356,8 +357,8 @@ dependencies = [ [[package]] name = "embassy-net-wiznet" -version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", "embassy-futures", @@ -369,8 +370,8 @@ dependencies = [ [[package]] name = "embassy-stm32" -version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "aligned", "bit_field", @@ -416,8 +417,8 @@ dependencies = [ [[package]] name = "embassy-sync" -version = "0.6.1" -source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +version = "0.6.2" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "cfg-if", "critical-section", @@ -431,7 +432,7 @@ dependencies = [ [[package]] name = "embassy-time" version = "0.4.0" -source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "cfg-if", "critical-section", @@ -447,7 +448,7 @@ dependencies = [ [[package]] name = "embassy-time-driver" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "document-features", ] @@ -455,7 +456,7 @@ dependencies = [ [[package]] name = "embassy-time-queue-utils" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "embassy-executor", "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -463,8 +464,8 @@ dependencies = [ [[package]] name = "embassy-usb" -version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +version = "0.4.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", "embassy-futures", @@ -479,7 +480,7 @@ dependencies = [ [[package]] name = "embassy-usb-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", ] @@ -487,7 +488,7 @@ dependencies = [ [[package]] name = "embassy-usb-synopsys-otg" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=a4f8fdd#a4f8fddd696ca2e3705827ba4b3806cbadcb3134" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "critical-section", "defmt", @@ -1216,8 +1217,8 @@ dependencies = [ [[package]] name = "stm32-metapac" -version = "15.0.0" -source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-ddb0e7abab14bf3e1399875767b8834442382988#15c2d08f1b0e5877c787bddb1f35a49cbe180f36" +version = "16.0.0" +source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-4a964af03b298de30ff9f84fcfa890bcab4ce609#aee345990e1a14efd018877b52aff1d63e16bb7f" dependencies = [ "cortex-m", "cortex-m-rt", diff --git a/nodes/embassy/Cargo.toml b/nodes/embassy/Cargo.toml index c9f7668d..723311b7 100644 --- a/nodes/embassy/Cargo.toml +++ b/nodes/embassy/Cargo.toml @@ -3,19 +3,19 @@ resolver = "2" members = ["bed-sb", "bed-lb", "sensors"] [workspace.dependencies] -protocol = { path = "../crates/protocol" } +protocol = { path = "../../crates/protocol" } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" -embassy-stm32 = { version = "0.1.0", features = [ "defmt", "stm32f401cc", +embassy-stm32 = { version = "0.2.0", features = [ "defmt", "stm32f401cc", "unstable-pac", "memory-x", "time-driver-tim9", "time", "exti" ] } -embassy-net = { version = "0.5.0", features = ["defmt", "proto-ipv4", "tcp", "dhcpv4","medium-ethernet"] } -embassy-net-wiznet = { version = "0.1.0", features = ["defmt"] } -embassy-sync = { version = "0.6.1", features = ["defmt"] } +embassy-net = { version = "0.7.0", features = ["defmt", "proto-ipv4", "tcp", "dhcpv4","medium-ethernet"] } +embassy-net-wiznet = { version = "0.2.0", features = ["defmt"] } +embassy-sync = { version = "0.6.2", features = ["defmt"] } embassy-executor = { version = "0.7", features = ["arch-cortex-m", "executor-thread", "defmt", "executor-interrupt"] } -embassy-embedded-hal = { version = "0.2.0" } +embassy-embedded-hal = { version = "0.3.0" } embassy-time = { version = "0.4", features = ["defmt", "defmt-timestamp-uptime-ms", "tick-hz-32_768"] } embassy-futures = { version = "0.1.1"} @@ -31,16 +31,16 @@ defmt-rtt = "0.4" panic-probe = { version = "0.3", features = ["print-defmt"] } [patch.crates-io] -embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } -embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } -embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } -embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } -embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } -embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } -embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } -embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } -embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } -embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "a4f8fdd" } +embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } [workspace.package] rust-version = "1.78" diff --git a/nodes/embassy/bed-sb/Cargo.toml b/nodes/embassy/bed-sb/Cargo.toml index 43549399..73e12bf2 100644 --- a/nodes/embassy/bed-sb/Cargo.toml +++ b/nodes/embassy/bed-sb/Cargo.toml @@ -16,7 +16,7 @@ embassy-executor.workspace = true embassy-embedded-hal.workspace = true embassy-time.workspace = true embassy-futures.workspace = true -embassy-usb = { version = "0.3.0", features = ["defmt"] } +embassy-usb = { version = "0.4.0", features = ["defmt"] } defmt.workspace = true defmt-rtt.workspace = true From fd6ce40a978fd5ca0163df1f65fc94f566c0b246 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 23 Mar 2025 15:13:36 +0100 Subject: [PATCH 610/687] refactors bed-lb to use more tasks instead of select --- nodes/embassy/bed-lb/.cargo/config.toml | 2 +- nodes/embassy/bed-lb/src/channel.rs | 22 ++++-- nodes/embassy/bed-lb/src/main.rs | 49 +++++-------- nodes/embassy/bed-lb/src/network.rs | 16 +++-- nodes/embassy/bed-lb/src/rgb_led.rs | 82 ++++++++++----------- nodes/embassy/bed-lb/src/sensors.rs | 16 ++--- nodes/embassy/bed-lb/src/sensors/fast.rs | 52 ++++++-------- nodes/embassy/bed-lb/src/sensors/slow.rs | 92 ++++++++++-------------- 8 files changed, 146 insertions(+), 185 deletions(-) diff --git a/nodes/embassy/bed-lb/.cargo/config.toml b/nodes/embassy/bed-lb/.cargo/config.toml index 161b3118..1c28d62e 100644 --- a/nodes/embassy/bed-lb/.cargo/config.toml +++ b/nodes/embassy/bed-lb/.cargo/config.toml @@ -1,7 +1,7 @@ [target.'cfg(all(target_arch = "arm", target_os = "none"))'] # replace STM32F103C8 with your chip as listed in `probe-rs chip list` # runner = "probe-rs run --chip STM32F103C8" -runner = "probe-rs run --chip STM32F401CCUx" +runner = "probe-rs run --chip STM32F401CCUx --host ws://192.168.1.43:3000 --token secret_token_redacted --probe c251:f001:202108120001" linker = "flip-link" [build] diff --git a/nodes/embassy/bed-lb/src/channel.rs b/nodes/embassy/bed-lb/src/channel.rs index 2f7fe5ae..c30eb5d5 100644 --- a/nodes/embassy/bed-lb/src/channel.rs +++ b/nodes/embassy/bed-lb/src/channel.rs @@ -1,5 +1,5 @@ use embassy_futures::select::{self, Either}; -use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; use embassy_sync::channel::Channel; use embassy_sync::mutex::Mutex; use embassy_sync::priority_channel::{self, PriorityChannel}; @@ -8,9 +8,14 @@ use heapless::HistoryBuffer; use protocol::large_bedroom::bed::Reading; pub struct Queues { - sensor_queue: PriorityChannel, - error_queue: Channel, - recent_errors: Mutex>, + sensor_queue: PriorityChannel< + ThreadModeRawMutex, + PriorityValue, + priority_channel::Max, + 20, + >, + error_queue: Channel, + recent_errors: Mutex>, recent_is_since: Instant, } @@ -20,12 +25,12 @@ pub enum QueueItem { } impl Queues { - pub fn new() -> Self { + pub const fn new() -> Self { Self { sensor_queue: PriorityChannel::new(), error_queue: Channel::new(), recent_errors: Mutex::new(HistoryBuffer::new()), - recent_is_since: Instant::now(), + recent_is_since: Instant::MIN, // time since CPU start } } @@ -39,7 +44,10 @@ impl Queues { return QueueItem::Reading(val); } - let race = select::select(self.sensor_queue.receive(), self.error_queue.receive()); + let race = select::select( + self.sensor_queue.receive(), + self.error_queue.receive(), + ); match race.await { Either::First(reading) => QueueItem::Reading(reading), Either::Second(error) => QueueItem::Error(error), diff --git a/nodes/embassy/bed-lb/src/main.rs b/nodes/embassy/bed-lb/src/main.rs index cd50afd7..8d2b7340 100644 --- a/nodes/embassy/bed-lb/src/main.rs +++ b/nodes/embassy/bed-lb/src/main.rs @@ -2,7 +2,6 @@ #![no_main] use embassy_executor::Spawner; -use embassy_futures::select::{self, Either4}; use embassy_net::{Ipv4Address, Ipv4Cidr, StackResources}; use embassy_net_wiznet::{chip::W5500, Device, Runner, State}; use embassy_stm32::exti::ExtiInput; @@ -15,18 +14,18 @@ use embassy_stm32::time::Hertz; use embassy_stm32::usart::{self, DataBits, Parity, StopBits, Uart}; use embassy_stm32::wdg::IndependentWatchdog; use embassy_stm32::Config; -use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::blocking_mutex::raw::{NoopRawMutex, ThreadModeRawMutex}; use embassy_sync::channel::Channel; use embassy_sync::mutex::Mutex; use embassy_time::{Delay, Timer}; use embedded_hal_bus::spi::ExclusiveDevice; -use futures::pin_mut; use heapless::Vec; +use rgb_led::{control_leds, LedHandle}; use sensors::fast::ButtonInputs; use sensors::slow; use static_cell::StaticCell; -use defmt::{error, trace, unwrap}; +use defmt::{trace, unwrap}; use {defmt_rtt as _, panic_probe as _}; mod channel; @@ -66,6 +65,8 @@ async fn net_task( runner.run().await } +static PUBLISH: Queues = Queues::new(); + // 84 Mhz clock stm32f401 fn config() -> Config { use embassy_stm32::rcc::{ @@ -220,19 +221,17 @@ async fn main(spawner: Spawner) { // Launch network task unwrap!(spawner.spawn(net_task(runner))); - let comms = Channel::new(); - let (mut led_controller, led_handle) = - rgb_led::controller_and_handle(p.TIM1, p.PB14, p.PB13, p.PB15, &comms); + static LED_COMMS: Channel = + Channel::new(); + let control_leds = control_leds(p.TIM1, p.PB14, p.PB13, p.PB15, &LED_COMMS); + let led_handle = LedHandle::new(&LED_COMMS); - let driver_orderers = slow::DriverOrderers::new(); - let publish = Queues::new(); + static DRIVER_ORDERERS: slow::DriverOrderers = slow::DriverOrderers::new(); let handle_network = - network::handle(&stack, &publish, led_handle.clone(), &driver_orderers); - pin_mut!(handle_network); + network::handle(stack, &PUBLISH, led_handle.clone(), &DRIVER_ORDERERS); let init_then_measure = sensors::init_then_measure( - &publish, - &driver_orderers, + &DRIVER_ORDERERS, led_handle, i2c_1, i2c_2, @@ -242,27 +241,11 @@ async fn main(spawner: Spawner) { buttons, ); - let res = select::select4( - &mut handle_network, - init_then_measure, - led_controller.control(), - keep_dog_happy(dog), - ) - .await; - let unrecoverable_err = match res { - Either4::First(()) - | Either4::Third(()) - | Either4::Fourth(()) - | Either4::Second(Ok(())) => { - defmt::unreachable!() - } - Either4::Second(Err(err)) => err, - }; + spawner.must_spawn(init_then_measure); + spawner.must_spawn(handle_network); + spawner.must_spawn(control_leds); - // at this point no other errors have occurred - error!("unrecoverable error, resetting: {}", unrecoverable_err); - publish.queue_error(unrecoverable_err); - handle_network.await; // if this takes too long the dog will get us + keep_dog_happy(dog).await; } async fn keep_dog_happy(mut dog: IndependentWatchdog<'_, IWDG>) { diff --git a/nodes/embassy/bed-lb/src/network.rs b/nodes/embassy/bed-lb/src/network.rs index f3d42769..6228cff3 100644 --- a/nodes/embassy/bed-lb/src/network.rs +++ b/nodes/embassy/bed-lb/src/network.rs @@ -1,4 +1,5 @@ use defmt::{debug, info, unwrap, warn}; +use embassy_executor::task; use embassy_futures::select::{self, select}; use embassy_net::tcp::{TcpReader, TcpSocket, TcpWriter}; use embassy_net::{Ipv4Address, Stack}; @@ -72,17 +73,18 @@ const fn max(a: usize, b: usize) -> usize { [a, b][(a < b) as usize] } +#[task] pub async fn handle( - stack: &Stack<'_>, - publish: &Queues, - led: LedHandle<'_>, - driver_orderers: &slow::DriverOrderers, + stack: Stack<'static>, + publish: &'static Queues, + led: LedHandle, + driver_orderers: &'static slow::DriverOrderers, ) { let mut rx_buffer = [0; 1024]; let mut tx_buffer = [0; max(SensMsg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE) * 2]; - let mut socket = TcpSocket::new(*stack, &mut rx_buffer, &mut tx_buffer); + let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); socket.set_timeout(Some(Duration::from_secs(5))); socket.set_keep_alive(Some(Duration::from_secs(1))); let host_addr = Ipv4Address::new(192, 168, 1, 43); @@ -114,7 +116,7 @@ pub async fn handle( let (reader, writer) = socket.split(); match select( send_messages(writer, publish), - receive_orders(reader, &led, &driver_orderers), + receive_orders(reader, &led, driver_orderers), ) .await { @@ -200,7 +202,7 @@ enum ReadError { async fn receive_orders( mut tcp: TcpReader<'_>, - led: &LedHandle<'_>, + led: &LedHandle, driver_orderers: &slow::DriverOrderers, ) -> ReadError { defmt::debug!("ready to receive orders"); diff --git a/nodes/embassy/bed-lb/src/rgb_led.rs b/nodes/embassy/bed-lb/src/rgb_led.rs index 5361186e..735ca4a3 100644 --- a/nodes/embassy/bed-lb/src/rgb_led.rs +++ b/nodes/embassy/bed-lb/src/rgb_led.rs @@ -1,9 +1,12 @@ +use embassy_executor::task; use embassy_stm32::gpio::OutputType; use embassy_stm32::peripherals::{PB13, PB14, PB15, TIM1}; use embassy_stm32::time::khz; use embassy_stm32::timer; -use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; -use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_stm32::timer::complementary_pwm::{ + ComplementaryPwm, ComplementaryPwmPin, +}; +use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; use embassy_sync::channel::Channel; struct RgbLed { @@ -84,17 +87,22 @@ pub(crate) enum Event { } #[derive(Clone)] -pub struct LedHandle<'a> { - sender: &'a Channel, +pub struct LedHandle { + led_comms: &'static Channel, } -impl<'a> LedHandle<'a> { +impl LedHandle { + pub const fn new( + led_comms: &'static Channel, + ) -> Self { + Self { led_comms } + } pub async fn set_color(&self, r: f32, g: f32, b: f32) { - self.sender.send(Event::SetColor { r, g, b }).await + self.led_comms.send(Event::SetColor { r, g, b }).await } pub async fn update_lux(&self, lux: f32) { - self.sender.send(Event::LuxChanged(lux)).await + self.led_comms.send(Event::LuxChanged(lux)).await } } @@ -117,46 +125,30 @@ fn lookup_bri(lux: f32) -> f32 { .unwrap_or(0.6) } -pub(crate) struct LedController<'a> { - orders: &'a Channel, - led: RgbLed, -} - -impl<'a> LedController<'a> { - pub(crate) async fn control(&mut self) { - let mut bri = 0.01; // Start with minimal bri - - loop { - let order = self.orders.receive().await; - match order { - Event::SetColor { r, g, b } => { - self.led.r = r; - self.led.g = g; - self.led.b = b; - } - Event::LuxChanged(new) => { - bri = lookup_bri(new); - } - } - - self.led.update(bri); - } - } -} - -pub fn controller_and_handle<'a>( +#[task] +pub(crate) async fn control_leds( timer: TIM1, r: PB14, g: PB13, b: PB15, - channel: &'a Channel, -) -> (LedController<'a>, LedHandle<'a>) { - let led = RgbLed::new(timer, b, r, g); - ( - LedController { - led, - orders: channel, - }, - LedHandle { sender: channel }, - ) + led_comms: &'static Channel, +) { + let mut led = RgbLed::new(timer, b, r, g); + let mut bri = 0.01; // Start with minimal bri + + loop { + let order = led_comms.receive().await; + match order { + Event::SetColor { r, g, b } => { + led.r = r; + led.g = g; + led.b = b; + } + Event::LuxChanged(new) => { + bri = lookup_bri(new); + } + } + + led.update(bri); + } } diff --git a/nodes/embassy/bed-lb/src/sensors.rs b/nodes/embassy/bed-lb/src/sensors.rs index 0d1c51a9..833770ca 100644 --- a/nodes/embassy/bed-lb/src/sensors.rs +++ b/nodes/embassy/bed-lb/src/sensors.rs @@ -1,4 +1,5 @@ use defmt::info; +use embassy_executor::task; use embassy_futures::join; use embassy_stm32::i2c::I2c; use embassy_stm32::mode::{Async, Blocking}; @@ -8,9 +9,8 @@ use embassy_sync::mutex::Mutex; use fast::ButtonInputs; use protocol::large_bedroom::bed::Device; -use crate::channel::Queues; use crate::rgb_led; -use sensors::{Error, I2cWrapper, Nau7802DriverBlocking, SPS30_UART_BUF_SIZE}; +use sensors::{I2cWrapper, Nau7802DriverBlocking, SPS30_UART_BUF_SIZE}; pub mod fast; pub mod slow; @@ -23,17 +23,17 @@ fn local_dev(dev: protocol::large_bedroom::bed::Device) -> protocol::Device { protocol::Device::LargeBedroom(protocol::large_bedroom::Device::Bed(dev)) } +#[task] pub async fn init_then_measure( - publish: &Queues, - orderers: &slow::DriverOrderers, - rgb_led: rgb_led::LedHandle<'_>, + orderers: &'static slow::DriverOrderers, + rgb_led: rgb_led::LedHandle, i2c_1: Mutex>, i2c_2: Mutex>, i2c_3: Mutex>, usart_mhz: Uart<'static, Async>, usart_sps: Uart<'static, Async>, buttons: ButtonInputs, -) -> Result<(), Error> { +) -> ! { info!("initializing sensors"); let bme = Bme680Driver::new(&i2c_3, local_dev(Device::Bme680)); let max44009 = Max44Driver::new(&i2c_1, local_dev(Device::Max44)); @@ -54,14 +54,14 @@ pub async fn init_then_measure( let sps30 = Sps30Driver::init(tx, rx, local_dev(Device::Sps30)); let sensors_fast = - fast::read(max44009, nau_right, nau_left, buttons, publish, rgb_led); + fast::read(max44009, nau_right, nau_left, buttons, rgb_led); let drivers = slow::Drivers { sht, bme, mhz, sps: sps30, }; - let sensors_slow = slow::read(drivers, orderers, publish); + let sensors_slow = slow::read(drivers, orderers); join::join(sensors_fast, sensors_slow).await; defmt::unreachable!(); diff --git a/nodes/embassy/bed-lb/src/sensors/fast.rs b/nodes/embassy/bed-lb/src/sensors/fast.rs index a1e288d7..865f6fa3 100644 --- a/nodes/embassy/bed-lb/src/sensors/fast.rs +++ b/nodes/embassy/bed-lb/src/sensors/fast.rs @@ -7,7 +7,7 @@ use embassy_time::{Duration, Instant, Timer}; use protocol::large_bedroom::{bed::Button, bed::Reading}; -use crate::{channel::Queues, rgb_led}; +use crate::{rgb_led, PUBLISH}; use sensors::{Max44Driver, Nau7802Driver, Nau7802DriverBlocking}; fn sig_lux_diff(old: f32, new: f32) -> bool { @@ -23,8 +23,7 @@ fn sig_weight_diff(old: u32, new: u32) -> bool { async fn report_lux( mut max44: Max44Driver<'_>, - publish: &Queues, - rgb_led: rgb_led::LedHandle<'_>, + rgb_led: rgb_led::LedHandle, ) { const MAX_INTERVAL: Duration = Duration::from_secs(5); @@ -36,17 +35,17 @@ async fn report_lux( let lux = match max44.try_measure().await { Ok(lux) => lux, Err(err) if last_lux.elapsed() > MAX_INTERVAL => { - publish.queue_error(err); + PUBLISH.queue_error(err); continue; } Err(_) => continue, }; if sig_lux_diff(prev_lux, lux) { - publish.send_p2(Reading::Brightness(lux)); + PUBLISH.send_p2(Reading::Brightness(lux)); rgb_led.update_lux(lux).await; } else if last_lux.elapsed() > MAX_INTERVAL { - publish.send_p1(Reading::Brightness(lux)); + PUBLISH.send_p1(Reading::Brightness(lux)); } else { yield_now().await; continue; @@ -82,7 +81,6 @@ async fn report_weight( mut nau: impl Nau, wrap_reading: impl Fn(u32) -> Reading, position: Position, - publish: &Queues, ) { const MAX_INTERVAL: Duration = Duration::from_secs(5); @@ -99,16 +97,16 @@ async fn report_weight( } else { err // default is left }; - publish.queue_error(err); + PUBLISH.queue_error(err); continue; } Err(_) => continue, }; if sig_weight_diff(prev_weight, weight) { - publish.send_p2(wrap_reading(weight)); + PUBLISH.send_p2(wrap_reading(weight)); } else if reported_at.elapsed() > MAX_INTERVAL { - publish.send_p1(wrap_reading(weight)); + PUBLISH.send_p1(wrap_reading(weight)); } else { yield_now().await; continue; @@ -122,7 +120,6 @@ async fn report_weight( async fn watch_button( mut input: ExtiInput<'static>, event: impl Fn(protocol::button::Press) -> Button, - channel: &Queues, ) { use sensors::{errors::PressTooLong, errors::SensorError, Error}; @@ -134,13 +131,13 @@ async fn watch_button( let Ok(press) = press.as_millis().try_into() else { let event_for_printing = (event)(protocol::button::Press(0)); let name = event_for_printing.variant_name(); - channel.queue_error(Error::Running(SensorError::Button( + PUBLISH.queue_error(Error::Running(SensorError::Button( PressTooLong { button: name }, ))); continue; }; let event = (event)(protocol::button::Press(press)); - channel.send_p2(Reading::Button(event)); + PUBLISH.send_p2(Reading::Button(event)); } else { input.wait_for_high().await; Timer::after(Duration::from_millis(20)).await; @@ -174,33 +171,28 @@ pub(crate) async fn read( nau_right: Nau7802DriverBlocking<'_>, nau_left: Nau7802Driver<'_>, inputs: ButtonInputs, - publish: &Queues, - rgb_led: rgb_led::LedHandle<'_>, + rgb_led: rgb_led::LedHandle, ) { use protocol::large_bedroom::bed::Button; let watch_buttons_1 = join4( - watch_button(inputs.top, Button::Top, publish), - watch_button(inputs.middle_inner, Button::MiddleInner, publish), - watch_button(inputs.middle_center, Button::MiddleCenter, publish), - watch_button(inputs.middle_outer, Button::MiddleOuter, publish), + watch_button(inputs.top, Button::Top), + watch_button(inputs.middle_inner, Button::MiddleInner), + watch_button(inputs.middle_center, Button::MiddleCenter), + watch_button(inputs.middle_outer, Button::MiddleOuter), ); let watch_buttons_2 = join3( - watch_button(inputs.lower_inner, Button::LowerInner, publish), - watch_button(inputs.lower_center, Button::LowerCenter, publish), - watch_button(inputs.lower_outer, Button::LowerOuter, publish), + watch_button(inputs.lower_inner, Button::LowerInner), + watch_button(inputs.lower_center, Button::LowerCenter), + watch_button(inputs.lower_outer, Button::LowerOuter), ); - let watch_lux = report_lux(max44, publish, rgb_led); - let report_right_weight = report_weight( - nau_right, - Reading::WeightRight, - Position::Right, - publish, - ); + let watch_lux = report_lux(max44, rgb_led); + let report_right_weight = + report_weight(nau_right, Reading::WeightRight, Position::Right); let report_left_weight = - report_weight(nau_left, Reading::WeightLeft, Position::Left, publish); + report_weight(nau_left, Reading::WeightLeft, Position::Left); join::join5( report_left_weight, diff --git a/nodes/embassy/bed-lb/src/sensors/slow.rs b/nodes/embassy/bed-lb/src/sensors/slow.rs index e556c937..a6d80462 100644 --- a/nodes/embassy/bed-lb/src/sensors/slow.rs +++ b/nodes/embassy/bed-lb/src/sensors/slow.rs @@ -1,31 +1,31 @@ use defmt::unwrap; use embassy_futures::join::join5; use embassy_futures::select; -use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; use embassy_sync::channel::Channel; use embassy_time::Timer; use embassy_time::{with_timeout, Duration}; use protocol::large_bedroom::bed::Reading; -use crate::channel::Queues; +use crate::PUBLISH; use sensors::measurements; use sensors::{Bme680Driver, Driver, Sht31Driver, Sps30Driver}; use sensors::{Error, MhzDriver}; -type Signal = embassy_sync::signal::Signal; +type Signal = embassy_sync::signal::Signal; /// Measure when signal is received or control the device's /// affector when it is ordered #[inline(always)] async fn measure_and_control( mut driver: D, - order: &Channel, + order: &Channel, send: F, signal: &Signal, ) where D: Driver, - F: Fn(Result) -> (), + F: Fn(Result), { let timeout = Duration::from_secs(15); loop { @@ -68,13 +68,13 @@ pub(crate) struct Drivers<'a> { } pub(crate) struct DriverOrderers { - pub sht: Channel, - pub bme: Channel, - pub mhz: Channel, - pub sps: Channel, + pub sht: Channel, + pub bme: Channel, + pub mhz: Channel, + pub sps: Channel, } impl DriverOrderers { - pub(crate) fn new() -> Self { + pub(crate) const fn new() -> Self { Self { sht: Channel::new(), bme: Channel::new(), @@ -85,11 +85,7 @@ impl DriverOrderers { } #[inline(always)] -pub async fn read( - drivers: Drivers<'_>, - orderers: &DriverOrderers, - publish: &'_ Queues, -) { +pub async fn read(drivers: Drivers<'_>, orderers: &DriverOrderers) { let signals = [const { Signal::new() }; 4]; join5( @@ -97,35 +93,32 @@ pub async fn read( measure_and_control( drivers.sht, &orderers.sht, - |res| publish_sht_result(res, &publish), + publish_sht_result, &signals[0], ), measure_and_control( drivers.bme, &orderers.bme, - |res| publish_bme_result(res, &publish), + publish_bme_result, &signals[1], ), measure_and_control( drivers.mhz, &orderers.mhz, - |res| publish_mhz_result(res, &publish), + publish_mhz_result, &signals[2], ), measure_and_control( drivers.sps, &orderers.sps, - |res| publish_sps_result(res, &publish), + publish_sps_result, &signals[3], ), ) .await; } -fn publish_sps_result( - sps_res: Result, - publish: &Queues, -) { +fn publish_sps_result(sps_res: Result) { match sps_res { Ok(measurements::Sps30 { mass_pm1_0, @@ -140,56 +133,47 @@ fn publish_sps_result( typical_particle_size, .. }) => { - publish.send_p0(Reading::MassPm1_0(mass_pm1_0)); - publish.send_p0(Reading::MassPm2_5(mass_pm2_5)); - publish.send_p0(Reading::MassPm4_0(mass_pm4_0)); - publish.send_p0(Reading::MassPm10(mass_pm10)); - publish.send_p0(Reading::NumberPm0_5(number_pm0_5)); - publish.send_p0(Reading::NumberPm1_0(number_pm1_0)); - publish.send_p0(Reading::NumberPm2_5(number_pm2_5)); - publish.send_p0(Reading::NumberPm4_0(number_pm4_0)); - publish.send_p0(Reading::NumberPm10(number_pm10)); - publish + PUBLISH.send_p0(Reading::MassPm1_0(mass_pm1_0)); + PUBLISH.send_p0(Reading::MassPm2_5(mass_pm2_5)); + PUBLISH.send_p0(Reading::MassPm4_0(mass_pm4_0)); + PUBLISH.send_p0(Reading::MassPm10(mass_pm10)); + PUBLISH.send_p0(Reading::NumberPm0_5(number_pm0_5)); + PUBLISH.send_p0(Reading::NumberPm1_0(number_pm1_0)); + PUBLISH.send_p0(Reading::NumberPm2_5(number_pm2_5)); + PUBLISH.send_p0(Reading::NumberPm4_0(number_pm4_0)); + PUBLISH.send_p0(Reading::NumberPm10(number_pm10)); + PUBLISH .send_p0(Reading::TypicalParticleSize(typical_particle_size)); } - Err(err) => publish.queue_error(err), + Err(err) => PUBLISH.queue_error(err), } } -fn publish_mhz_result( - mhz_res: Result, - publish: &Queues, -) { +fn publish_mhz_result(mhz_res: Result) { match mhz_res { Ok(measurements::Mhz { co2, .. }) => { - publish.send_p0(Reading::Co2(co2)); + PUBLISH.send_p0(Reading::Co2(co2)); } Err(err) => { - publish.queue_error(err); + PUBLISH.queue_error(err); } } } -fn publish_sht_result( - sht_res: Result, - publish: &Queues, -) { +fn publish_sht_result(sht_res: Result) { match sht_res { Ok(measurements::Sht31 { temperature, humidity, }) => { - publish.send_p0(Reading::Temperature(temperature)); - publish.send_p0(Reading::Humidity(humidity)); + PUBLISH.send_p0(Reading::Temperature(temperature)); + PUBLISH.send_p0(Reading::Humidity(humidity)); } - Err(err) => publish.queue_error(err), + Err(err) => PUBLISH.queue_error(err), } } -fn publish_bme_result( - bme_res: Result, - publish: &Queues, -) { +fn publish_bme_result(bme_res: Result) { match bme_res { Ok(measurements::Bme { pressure, @@ -197,9 +181,9 @@ fn publish_bme_result( .. }) => { let gas_resistance = unwrap!(gas_resistance); // sensor is on - publish.send_p0(Reading::GassResistance(gas_resistance)); - publish.send_p0(Reading::Pressure(pressure)); + PUBLISH.send_p0(Reading::GassResistance(gas_resistance)); + PUBLISH.send_p0(Reading::Pressure(pressure)); } - Err(err) => publish.queue_error(err), + Err(err) => PUBLISH.queue_error(err), } } From e861b490716752bca1e296ef2c9522cd7bc3684c Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 23 Mar 2025 22:53:50 +0100 Subject: [PATCH 611/687] fix log store returning error if range is past last error --- crates/log-store/src/server/db/log.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/crates/log-store/src/server/db/log.rs b/crates/log-store/src/server/db/log.rs index b5daa606..5c612d92 100644 --- a/crates/log-store/src/server/db/log.rs +++ b/crates/log-store/src/server/db/log.rs @@ -196,7 +196,9 @@ impl Log { &mut self, range: RangeInclusive, ) -> GetLogResponse { - use byteseries::seek::Error::{EmptyFile, StopBeforeData}; + use byteseries::seek::Error::{ + EmptyFile, StartAfterData, StopBeforeData, + }; use byteseries::series::Error::InvalidRange; const MAX_IN_ONE_READ: usize = 200; @@ -226,10 +228,11 @@ impl Log { &mut data, ) { Ok(()) => (), - Err(InvalidRange(StopBeforeData | EmptyFile)) => { - return GetLogResponse::All(current.collect()) - } + Err(InvalidRange( + StopBeforeData | StartAfterData { .. } | EmptyFile, + )) => return GetLogResponse::All(current.collect()), Err(other) => { + dbg!(&other); let report = color_eyre::eyre::Report::new(other) .wrap_err("Could not read log events from disk"); let report = format!("{report:?}"); From 559aa232b18d47b839e80f3fab87bb17ed9d94e5 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 23 Mar 2025 22:54:22 +0100 Subject: [PATCH 612/687] ui error reports no longer cutting off location, no longer printing error over ui --- crates/log-store/src/api/client.rs | 2 +- crates/ui/src/tui/reports.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/log-store/src/api/client.rs b/crates/log-store/src/api/client.rs index cb167680..60c7e766 100644 --- a/crates/log-store/src/api/client.rs +++ b/crates/log-store/src/api/client.rs @@ -50,7 +50,7 @@ impl Client { } } - #[instrument(err, skip(self))] + #[instrument(skip(self))] pub async fn get_logs( &mut self, device: protocol::Device, diff --git a/crates/ui/src/tui/reports.rs b/crates/ui/src/tui/reports.rs index d7887db5..0a7fd7ab 100644 --- a/crates/ui/src/tui/reports.rs +++ b/crates/ui/src/tui/reports.rs @@ -19,7 +19,7 @@ impl From for Report { let detailed = format!("{value:?}"); let mut detailed = strip_ansi_escapes::strip_str(&detailed); let last_paragraph = detailed - .find("Location:") + .rfind("Location:") .expect("Detailed report always lists a location"); let backtrace_start = detailed[last_paragraph..] .find("\n\n") @@ -100,7 +100,7 @@ impl Reports { let current = self.current.as_ref()?; Some(if self.show_details { - 1 + current.detailed.lines().count() as u16 + 2 + current.detailed.lines().count() as u16 } else { 1 + current.short.lines().count() as u16 }) From 3e69ca0e9dd593471dc3ca25ac87ed21e60a2e63 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 26 Mar 2025 17:37:35 +0100 Subject: [PATCH 613/687] extracts usb logic to its own lib --- nodes/embassy/Cargo.toml | 3 ++ nodes/embassy/bed-sb/Cargo.toml | 7 +-- nodes/embassy/bed-sb/src/comms.rs | 2 +- nodes/embassy/bed-sb/src/main.rs | 7 ++- nodes/embassy/usb-bridge-client/Cargo.toml | 15 ++++++ .../src/lib.rs} | 52 ++++++++++++------- 6 files changed, 59 insertions(+), 27 deletions(-) create mode 100644 nodes/embassy/usb-bridge-client/Cargo.toml rename nodes/embassy/{bed-sb/src/usb_wrapper.rs => usb-bridge-client/src/lib.rs} (86%) diff --git a/nodes/embassy/Cargo.toml b/nodes/embassy/Cargo.toml index 723311b7..edd82923 100644 --- a/nodes/embassy/Cargo.toml +++ b/nodes/embassy/Cargo.toml @@ -19,6 +19,7 @@ embassy-embedded-hal = { version = "0.3.0" } embassy-time = { version = "0.4", features = ["defmt", "defmt-timestamp-uptime-ms", "tick-hz-32_768"] } embassy-futures = { version = "0.1.1"} +embassy-usb = { version = "0.4.0", features = ["defmt"] } embedded-hal = "1.0.0" embedded-hal-async = "1.0" @@ -26,6 +27,8 @@ embedded-hal-bus = { version = "0.2", features = ["async", "defmt-03"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } futures = { version = "0.3.31", default-features = false, features = ["async-await"] } +heapless = { git = "https://github.com/rust-embedded/heapless", version = "0.8", rev = "0ebca23", default-features = false } + defmt = "0.3" defmt-rtt = "0.4" panic-probe = { version = "0.3", features = ["print-defmt"] } diff --git a/nodes/embassy/bed-sb/Cargo.toml b/nodes/embassy/bed-sb/Cargo.toml index 73e12bf2..eb546799 100644 --- a/nodes/embassy/bed-sb/Cargo.toml +++ b/nodes/embassy/bed-sb/Cargo.toml @@ -16,7 +16,7 @@ embassy-executor.workspace = true embassy-embedded-hal.workspace = true embassy-time.workspace = true embassy-futures.workspace = true -embassy-usb = { version = "0.4.0", features = ["defmt"] } +embassy-usb.workspace = true defmt.workspace = true defmt-rtt.workspace = true @@ -28,10 +28,11 @@ embedded-io-async.workspace = true panic-probe.workspace = true futures.workspace = true -heapless = { git = "https://github.com/rust-embedded/heapless", version = "0.8", rev = "0ebca23", default-features = false } +heapless.workspace = true # sensors sensors = { path = "../sensors" } # encoding -protocol = { workspace = true } +protocol.workspace = true +usb-bridge-client = { path = "../usb-bridge-client" } diff --git a/nodes/embassy/bed-sb/src/comms.rs b/nodes/embassy/bed-sb/src/comms.rs index e650383c..a2a07972 100644 --- a/nodes/embassy/bed-sb/src/comms.rs +++ b/nodes/embassy/bed-sb/src/comms.rs @@ -7,7 +7,7 @@ use protocol::{affector, Affector, ErrorReport, SensorMessage}; use crate::channel::{PriorityValue, QueueItem, Queues}; use crate::sensors::slow; -use crate::usb_wrapper::{NoSpaceInQueue, UsbHandle, UsbReceiver, UsbSender}; +use usb_bridge_client::{NoSpaceInQueue, UsbHandle, UsbReceiver, UsbSender}; pub(crate) type SensMsg = SensorMessage<10>; type IsLowPrio = bool; diff --git a/nodes/embassy/bed-sb/src/main.rs b/nodes/embassy/bed-sb/src/main.rs index 6b846727..4eb569cc 100644 --- a/nodes/embassy/bed-sb/src/main.rs +++ b/nodes/embassy/bed-sb/src/main.rs @@ -26,7 +26,6 @@ use {defmt_rtt as _, panic_probe as _}; mod channel; mod comms; mod sensors; -mod usb_wrapper; use crate::channel::Queues; embassy_stm32::bind_interrupts!(struct Irqs { @@ -153,9 +152,9 @@ async fn main(_spawner: Spawner) { ); let affector_list = comms::affector_list(); - let stack_a = usb_wrapper::StackA::new(); - let mut stack_b = usb_wrapper::StackB::new(&stack_a, &affector_list); - let (mut usb_bus, usb_handle) = usb_wrapper::new(&stack_a, &mut stack_b, usb_driver); + let stack_a = usb_bridge_client::StackA::new(); + let mut stack_b = usb_bridge_client::StackB::new(&stack_a, &affector_list); + let (mut usb_bus, usb_handle) = usb_bridge_client::new(&stack_a, &mut stack_b, usb_driver); let driver_orderers = slow::DriverOrderers::new(); let publish = Queues::new(); diff --git a/nodes/embassy/usb-bridge-client/Cargo.toml b/nodes/embassy/usb-bridge-client/Cargo.toml new file mode 100644 index 00000000..1e3a1b71 --- /dev/null +++ b/nodes/embassy/usb-bridge-client/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "usb-bridge-client" +version = "0.1.0" +rust-version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true + +[dependencies] +embassy-sync.workspace = true +embassy-usb.workspace = true +defmt.workspace = true +heapless.workspace = true + +protocol.workspace = true diff --git a/nodes/embassy/bed-sb/src/usb_wrapper.rs b/nodes/embassy/usb-bridge-client/src/lib.rs similarity index 86% rename from nodes/embassy/bed-sb/src/usb_wrapper.rs rename to nodes/embassy/usb-bridge-client/src/lib.rs index d621d9cb..2a49e724 100644 --- a/nodes/embassy/bed-sb/src/usb_wrapper.rs +++ b/nodes/embassy/usb-bridge-client/src/lib.rs @@ -1,3 +1,5 @@ +#![no_std] + use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::channel::Channel; use embassy_sync::mutex::Mutex; @@ -10,7 +12,8 @@ use protocol::{affector, usb}; const MAX_RECV_ITEM_SIZE: usize = 1 + affector::Affector::ENCODED_SIZE; pub(crate) type RecvItem = heapless::Vec; -type SendQueue = Mutex>; +type SendQueue = + Mutex>; pub struct UsbControlHandler<'a> { pub if_num: Option, @@ -44,8 +47,11 @@ impl embassy_usb::Handler for UsbControlHandler<'_> { } // Accept affector orders only. - if req.request == usb::AFFECTOR_ORDER && data.len() <= MAX_RECV_ITEM_SIZE { - let data = heapless::Vec::from_slice(data).expect("checked length above"); + if req.request == usb::AFFECTOR_ORDER + && data.len() <= MAX_RECV_ITEM_SIZE + { + let data = + heapless::Vec::from_slice(data).expect("checked length above"); if self.receive_queue.try_send(data).is_err() { Some(OutResponse::Rejected) } else { @@ -100,7 +106,8 @@ impl embassy_usb::Handler for UsbControlHandler<'_> { impl UsbControlHandler<'_> { fn send_affector_list(&mut self, buf: &mut [u8]) { buf[0] = protocol::Msg::<5>::AFFECTOR_LIST; - buf[1..1 + self.affector_list.len()].copy_from_slice(self.affector_list); + buf[1..1 + self.affector_list.len()] + .copy_from_slice(self.affector_list); buf[1 + self.affector_list.len()..].fill(0); } @@ -124,11 +131,12 @@ impl UsbControlHandler<'_> { pub struct UsbHandle<'a> { send_queue: &'a SendQueue, ready_to_send: &'a Signal, - receive_queue: &'a Channel, 2>, + receive_queue: + &'a Channel, 2>, } impl<'a> UsbHandle<'a> { - pub(crate) fn split(&self) -> (UsbSender<'a>, UsbReceiver<'a>) { + pub fn split(&self) -> (UsbSender<'a>, UsbReceiver<'a>) { ( UsbSender { send_queue: self.send_queue, @@ -149,7 +157,7 @@ pub struct UsbSender<'a> { pub struct NoSpaceInQueue; impl UsbSender<'_> { - pub(crate) async fn send( + pub async fn send( &self, to_send: &[u8], is_low_prio: bool, @@ -181,7 +189,7 @@ impl UsbSender<'_> { Ok(()) } - pub(crate) async fn wait_till_queue_free(&self) { + pub async fn wait_till_queue_free(&self) { let wait_for_ready = self.ready_to_send.wait(); if !self.send_queue.lock().await.is_full() { return; @@ -191,11 +199,14 @@ impl UsbSender<'_> { } } +#[allow(dead_code)] pub struct UsbReceiver<'a> { - receive_queue: &'a Channel, 2>, + receive_queue: + &'a Channel, 2>, } +#[allow(dead_code)] impl UsbReceiver<'_> { - pub(crate) async fn recv(&self) -> RecvItem { + pub async fn recv(&self) -> RecvItem { self.receive_queue.receive().await } } @@ -204,7 +215,7 @@ pub fn config() -> embassy_usb::Config<'static> { let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); config.manufacturer = Some("Vid"); config.product = Some(concat!("sensor node ", env!("CARGO_PKG_NAME"))); - config.serial_number = Some("2139874"); // random, host driver finds device using this + config.serial_number = Some("2139874"); // Random, host driver finds device using this // Required for windows compatibility. // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help @@ -219,11 +230,12 @@ pub fn config() -> embassy_usb::Config<'static> { pub struct StackA { send_queue: SendQueue, ready_to_send: Signal, - receive_queue: Channel, 2>, + receive_queue: + Channel, 2>, } impl StackA { - pub(crate) fn new() -> Self { + pub fn new() -> Self { Self { send_queue: Mutex::new(heapless::Deque::new()), receive_queue: Channel::new(), @@ -241,7 +253,7 @@ pub struct StackB<'a> { } impl<'a> StackB<'a> { - pub(crate) fn new(stack_a: &'a StackA, affector_list: &'a [u8]) -> Self { + pub fn new(stack_a: &'a StackA, affector_list: &'a [u8]) -> Self { Self { config_descriptor: [0u8; 256], bos_descriptor: [0u8; 256], @@ -267,7 +279,7 @@ impl<'a, D: embassy_usb::driver::Driver<'a>> Usb<'a, D> { } } -pub(crate) fn new<'a, D: embassy_usb::driver::Driver<'a>>( +pub fn new<'a, D: embassy_usb::driver::Driver<'a>>( stack_a: &'a StackA, stack_b: &'a mut StackB<'a>, driver: D, @@ -292,18 +304,20 @@ pub(crate) fn new<'a, D: embassy_usb::driver::Driver<'a>>( ); // Add the Microsoft OS Descriptor (MSOS/MOD) descriptor. - // We tell Windows that this entire device is compatible with the "WINUSB" feature, - // which causes it to use the built-in WinUSB driver automatically, which in turn + // We tell Windows that this entire device is compatible with the "WINUSB" feature. + // This causes it to use the built-in WInUSB driver automatically, which in turn // can be used by libusb/rusb software without needing a custom driver or INF file. // In principle you might want to call msos_feature() just on a specific function, // if your device also has other functions that still use standard class drivers. builder.msos_descriptor(windows_version::WIN8_1, 0); - builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); + builder + .msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); // Randomly generated UUID because Windows requires you provide one to use WinUSB. // In principle WinUSB-using software could find this device (or a specific interface // on it) by its GUID instead of using the VID/PID, but in practice that seems unhelpful. - const DEVICE_INTERFACE_GUIDS: &[&str] = &["{DAC2087C-63FA-458D-A55D-827C0762DEC7}"]; + const DEVICE_INTERFACE_GUIDS: &[&str] = + &["{DAC2087C-63FA-458D-A55D-827C0762DEC7}"]; builder.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( "DeviceInterfaceGUIDs", From f31fb29c032d74f948b6703cc10425b694fc8a32 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 26 Mar 2025 17:39:07 +0100 Subject: [PATCH 614/687] fix button panel name --- crates/brain/src/controller/rooms/small_bedroom.rs | 2 +- crates/protocol/src/small_bedroom.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 81ccf453..c1bd9a83 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -110,7 +110,7 @@ async fn handle_buttonpress(room: &mut Room, event: RelevantEvent) { _ => room.to_daylight().await, } } - E::Button(B::BOttomRight(_)) => room.to_override().await, + E::Button(B::BottomRight(_)) => room.to_override().await, E::PortableButton(P::Dots2LongRelease) => room.to_sleep_no_wakeup().await, E::PortableButton(P::Dots1LongRelease) => room.to_nightlight().await, _ => (), diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index c7b41e59..228e3abc 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -24,7 +24,7 @@ crate::button_enum! { TopRight, BottomLeft, BottomMiddle, - BOttomRight, + BottomRight, } crate::Device::SmallBedroom(crate::small_bedroom::Device::Gpio); } @@ -128,7 +128,7 @@ impl Device { ButtonPanel::TopRight(Press(0)), ButtonPanel::BottomLeft(Press(0)), ButtonPanel::BottomMiddle(Press(0)), - ButtonPanel::BOttomRight(Press(0)) + ButtonPanel::BottomRight(Press(0)) ], affectors: &[], temporal_resolution: Duration::from_millis(1), From 90495d2b2480d2b041c5c1e4e3b96786b0102ba5 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 26 Mar 2025 17:40:09 +0100 Subject: [PATCH 615/687] adds button pannel, port of evavh buttonpanel --- nodes/embassy/Cargo.lock | 128 +- nodes/embassy/Cargo.toml | 2 +- nodes/embassy/bed-lb/Cargo.toml | 4 +- nodes/embassy/button-panel/.cargo/config.toml | 18 + nodes/embassy/button-panel/Cargo.toml | 36 + nodes/embassy/button-panel/build.rs | 5 + .../embassy/button-panel/rust-toolchain.toml | 6 + nodes/embassy/button-panel/src/buttons.rs | 71 + .../embassy/button-panel/src/buttons/fast.rs | 38 + .../embassy/button-panel/src/buttons/slow.rs | 205 + nodes/embassy/button-panel/src/comms.rs | 67 + nodes/embassy/button-panel/src/main.rs | 139 + nodes/embassy/button-panel/src/usb_wrapper.rs | 0 nodes/embassy/button-panel/stm32f401.svd | 35196 ++++++++++++++++ 14 files changed, 35867 insertions(+), 48 deletions(-) create mode 100644 nodes/embassy/button-panel/.cargo/config.toml create mode 100644 nodes/embassy/button-panel/Cargo.toml create mode 100644 nodes/embassy/button-panel/build.rs create mode 100644 nodes/embassy/button-panel/rust-toolchain.toml create mode 100644 nodes/embassy/button-panel/src/buttons.rs create mode 100644 nodes/embassy/button-panel/src/buttons/fast.rs create mode 100644 nodes/embassy/button-panel/src/buttons/slow.rs create mode 100644 nodes/embassy/button-panel/src/comms.rs create mode 100644 nodes/embassy/button-panel/src/main.rs create mode 100644 nodes/embassy/button-panel/src/usb_wrapper.rs create mode 100644 nodes/embassy/button-panel/stm32f401.svd diff --git a/nodes/embassy/Cargo.lock b/nodes/embassy/Cargo.lock index 024eba42..9eb7ad6d 100644 --- a/nodes/embassy/Cargo.lock +++ b/nodes/embassy/Cargo.lock @@ -82,9 +82,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "block-device-driver" @@ -105,6 +105,32 @@ dependencies = [ "embedded-hal-async", ] +[[package]] +name = "button-panel" +version = "0.2.0" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "defmt", + "defmt-rtt", + "embassy-embedded-hal", + "embassy-executor", + "embassy-futures", + "embassy-stm32", + "embassy-sync", + "embassy-time", + "embassy-usb", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-bus", + "embedded-io-async", + "futures", + "heapless 0.8.0 (git+https://github.com/rust-embedded/heapless?rev=0ebca23)", + "panic-probe", + "protocol", + "usb-bridge-client", +] + [[package]] name = "byteorder" version = "1.5.0" @@ -153,7 +179,7 @@ checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] @@ -198,7 +224,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] @@ -209,7 +235,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] @@ -232,7 +258,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] @@ -256,9 +282,9 @@ dependencies = [ [[package]] name = "document-features" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" +checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" dependencies = [ "litrs", ] @@ -301,7 +327,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] @@ -375,7 +401,7 @@ source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953 dependencies = [ "aligned", "bit_field", - "bitflags 2.6.0", + "bitflags 2.9.0", "block-device-driver", "cfg-if", "cortex-m", @@ -666,7 +692,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] @@ -816,9 +842,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "managed" @@ -883,9 +909,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.2" +version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" [[package]] name = "panic-probe" @@ -899,9 +925,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -911,9 +937,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "portable-atomic" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" [[package]] name = "postcard" @@ -958,14 +984,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] @@ -983,9 +1009,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.37" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] @@ -1020,14 +1046,14 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver 1.0.23", + "semver 1.0.26", ] [[package]] name = "rustversion" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" [[package]] name = "scopeguard" @@ -1052,9 +1078,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "semver-parser" @@ -1084,22 +1110,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.215" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] @@ -1137,6 +1163,7 @@ dependencies = [ "panic-probe", "protocol", "sensors", + "usb-bridge-client", ] [[package]] @@ -1249,7 +1276,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] @@ -1265,9 +1292,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.90" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -1276,29 +1303,40 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.6" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec2a1820ebd077e2b90c4df007bebf344cd394098a13c563957d0afc83ea47" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.6" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d65750cab40f4ff1929fb1ba509e9914eb756131cef4210da8d5d700d26f6312" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "usb-bridge-client" +version = "0.1.0" +dependencies = [ + "defmt", + "embassy-sync", + "embassy-usb", + "heapless 0.8.0 (git+https://github.com/rust-embedded/heapless?rev=0ebca23)", + "protocol", +] [[package]] name = "usb-device" @@ -1391,5 +1429,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.100", ] diff --git a/nodes/embassy/Cargo.toml b/nodes/embassy/Cargo.toml index edd82923..5d4be4b6 100644 --- a/nodes/embassy/Cargo.toml +++ b/nodes/embassy/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "2" -members = ["bed-sb", "bed-lb", "sensors"] +members = ["bed-sb", "bed-lb", "button-panel", "sensors", "usb-bridge-client"] [workspace.dependencies] protocol = { path = "../../crates/protocol" } diff --git a/nodes/embassy/bed-lb/Cargo.toml b/nodes/embassy/bed-lb/Cargo.toml index ccbde18d..ac595b85 100644 --- a/nodes/embassy/bed-lb/Cargo.toml +++ b/nodes/embassy/bed-lb/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "large-bedroom-sensor-node" version = "0.2.0" -rust-version = "1.78" -edition = "2021" +rust-version.workspace = true +edition.workspace = true license = "GPLv3" authors = ["David Kleingeld & Eva van Houten"] diff --git a/nodes/embassy/button-panel/.cargo/config.toml b/nodes/embassy/button-panel/.cargo/config.toml new file mode 100644 index 00000000..f00aaa5f --- /dev/null +++ b/nodes/embassy/button-panel/.cargo/config.toml @@ -0,0 +1,18 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +# replace STM32F103C8 with your chip as listed in `probe-rs chip list` +# runner = "probe-rs run --chip STM32F103C8" +runner = "probe-rs run --chip STM32F401CCUx" +# runner = "probe-rs run --chip STM32F401CCUx --host ws://192.168.1.43:3000 --token secret_token_redacted --probe c251:f001:202108120001" +linker = "flip-link" + +[build] +# target = "thumbv7m-none-eabi" for f103 +target = "thumbv7em-none-eabihf" + +[env] +DEFMT_LOG = "debug,sps30_async=warn,bosch_bme680=info" +EMBASSY_EXECUTOR_TASK_ARENA_SIZE="10900" + +# [unstable] +# build-std = ["core"] +# build-std-features = ["panic_immediate_abort"] diff --git a/nodes/embassy/button-panel/Cargo.toml b/nodes/embassy/button-panel/Cargo.toml new file mode 100644 index 00000000..87502de6 --- /dev/null +++ b/nodes/embassy/button-panel/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "button-panel" +version = "0.2.0" +rust-version = "1.85" +edition = "2024" +license = "GPLv3" +authors = ["David Kleingeld & Eva van Houten"] + +[dependencies] +cortex-m.workspace = true +cortex-m-rt.workspace = true + +embassy-stm32.workspace = true +embassy-sync.workspace = true +embassy-executor.workspace = true +embassy-embedded-hal.workspace = true +embassy-time.workspace = true +embassy-futures.workspace = true +embassy-usb.workspace = true + +defmt.workspace = true +defmt-rtt.workspace = true + +embedded-hal.workspace = true +embedded-hal-async.workspace = true +embedded-hal-bus.workspace = true +embedded-io-async.workspace = true + +panic-probe.workspace = true +futures.workspace = true +heapless.workspace = true + +# encoding +protocol = { workspace = true } + +usb-bridge-client = { path = "../usb-bridge-client" } diff --git a/nodes/embassy/button-panel/build.rs b/nodes/embassy/button-panel/build.rs new file mode 100644 index 00000000..8cd32d7e --- /dev/null +++ b/nodes/embassy/button-panel/build.rs @@ -0,0 +1,5 @@ +fn main() { + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tlink.x"); + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); +} diff --git a/nodes/embassy/button-panel/rust-toolchain.toml b/nodes/embassy/button-panel/rust-toolchain.toml new file mode 100644 index 00000000..c17f644e --- /dev/null +++ b/nodes/embassy/button-panel/rust-toolchain.toml @@ -0,0 +1,6 @@ +[toolchain] +channel = "stable" +components = [ "rust-src", "rustfmt", "llvm-tools" ] +targets = [ + "thumbv7em-none-eabihf", +] diff --git a/nodes/embassy/button-panel/src/buttons.rs b/nodes/embassy/button-panel/src/buttons.rs new file mode 100644 index 00000000..84d1599f --- /dev/null +++ b/nodes/embassy/button-panel/src/buttons.rs @@ -0,0 +1,71 @@ +use embassy_futures::join; +use embassy_stm32::exti::ExtiInput; +use fast::watch_button; + +pub mod fast; + +pub struct Inputs { + pub bottom_left: ExtiInput<'static>, + pub bottom_middle: ExtiInput<'static>, + pub bottom_right: ExtiInput<'static>, + pub top_left: ExtiInput<'static>, + pub top_middle: ExtiInput<'static>, + pub top_right: ExtiInput<'static>, +} + +macro_rules! on_ok { + ($pos:ident) => { + |press| { + crate::PUBLISH.send(protocol::Reading::SmallBedroom( + protocol::small_bedroom::Reading::ButtonPanel( + protocol::small_bedroom::ButtonPanel::$pos(press), + ), + )) + } + }; +} + +macro_rules! on_err { + ($pos:ident) => { + || { + let event_for_printing = + (protocol::small_bedroom::ButtonPanel::$pos)( + protocol::button::Press(0), + ); + let name = event_for_printing.variant_name(); + defmt::error!("Button pressed too long: {}", name); + } + }; +} + +pub async fn init_then_measure(inputs: Inputs) { + join::join( + join::join3( + watch_button( + inputs.bottom_left, + on_ok!(BottomLeft), + on_err!(BottomLeft), + ), + watch_button( + inputs.bottom_middle, + on_ok!(BottomMiddle), + on_err!(BottomMiddle), + ), + watch_button( + inputs.bottom_right, + on_ok!(BottomRight), + on_err!(BottomRight), + ), + ), + join::join3( + watch_button(inputs.top_left, on_ok!(TopLeft), on_err!(TopLeft)), + watch_button( + inputs.top_middle, + on_ok!(TopMiddle), + on_err!(TopMiddle), + ), + watch_button(inputs.top_right, on_ok!(TopRight), on_err!(TopRight)), + ), + ) + .await; +} diff --git a/nodes/embassy/button-panel/src/buttons/fast.rs b/nodes/embassy/button-panel/src/buttons/fast.rs new file mode 100644 index 00000000..1abd6918 --- /dev/null +++ b/nodes/embassy/button-panel/src/buttons/fast.rs @@ -0,0 +1,38 @@ +use embassy_stm32::exti::ExtiInput; +use embassy_time::{Duration, Instant, Timer}; + +use protocol::button; + +pub async fn watch_button( + mut input: ExtiInput<'static>, + on_ok_press: impl AsyncFn(protocol::button::Press), + on_err_press: impl Fn(), +) { + let mut went_high_at: Option = None; + loop { + if let Some(went_high_at) = went_high_at.take() { + input.wait_for_low().await; + let press = went_high_at.elapsed(); + let Ok(press) = press.as_millis().try_into().map(button::Press) + else { + on_err_press(); + continue; + }; + on_ok_press(press).await; + } else { + input.wait_for_high().await; + Timer::after(Duration::from_millis(20)).await; + if input.is_low() { + continue; + } + Timer::after(Duration::from_millis(20)).await; + if input.is_low() { + continue; + } + Timer::after(Duration::from_millis(10)).await; + if input.is_high() { + went_high_at = Some(Instant::now()); + } + } + } +} diff --git a/nodes/embassy/button-panel/src/buttons/slow.rs b/nodes/embassy/button-panel/src/buttons/slow.rs new file mode 100644 index 00000000..f1d1a973 --- /dev/null +++ b/nodes/embassy/button-panel/src/buttons/slow.rs @@ -0,0 +1,205 @@ +use defmt::unwrap; +use embassy_futures::join::join5; +use embassy_futures::select; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::channel::Channel; +use embassy_time::Timer; +use embassy_time::{with_timeout, Duration}; + +use protocol::small_bedroom::bed::Reading; + +use crate::channel::Queues; +use sensors::measurements; +use sensors::{Bme680Driver, Driver, Sht31Driver, Sps30Driver}; +use sensors::{Error, MhzDriver}; + +type Signal = embassy_sync::signal::Signal; + +/// Measure when signal is received or control the device's +/// affector when it is ordered +#[inline(always)] +async fn measure_and_control( + mut driver: D, + order: &Channel, + send: F, + signal: &Signal, +) where + D: Driver, + F: Fn(Result) -> (), +{ + let timeout = Duration::from_secs(15); + loop { + match select::select(signal.wait(), order.receive()).await { + select::Either::First(_) => { + let try_measure = Driver::try_measure(&mut driver); + let res = match with_timeout(timeout, try_measure).await { + Ok(res) => res, + Err(_) => Err(Error::Timeout(driver.device())), + }; + send(res); + } + select::Either::Second(order) => { + let affect = Driver::affect(&mut driver, order); + let res = match with_timeout(timeout, affect).await { + Ok(Ok(_)) => continue, + Ok(Err(e)) => Err(e), + Err(_) => Err(Error::Timeout(driver.device())), + }; + send(res); + } + } + } +} + +async fn order_measurements_every_period(signals: &[Signal]) { + loop { + for signal in signals { + signal.signal(()); + } + Timer::after_secs(5).await; + } +} + +pub(crate) struct Drivers<'a> { + pub sht: Sht31Driver<'a>, + pub bme: Bme680Driver<'a>, + pub mhz: MhzDriver<'a>, + pub sps: Sps30Driver<'a>, +} + +pub(crate) struct DriverOrderers { + pub sht: Channel, + pub bme: Channel, + pub mhz: Channel, + pub sps: Channel, +} +impl DriverOrderers { + pub(crate) fn new() -> Self { + Self { + sht: Channel::new(), + bme: Channel::new(), + mhz: Channel::new(), + sps: Channel::new(), + } + } +} + +#[inline(always)] +pub async fn read( + drivers: Drivers<'_>, + orderers: &DriverOrderers, + publish: &'_ Queues, +) { + let signals = [const { Signal::new() }; 4]; + + join5( + order_measurements_every_period(&signals), + measure_and_control( + drivers.sht, + &orderers.sht, + |res| publish_sht_result(res, &publish), + &signals[0], + ), + measure_and_control( + drivers.bme, + &orderers.bme, + |res| publish_bme_result(res, &publish), + &signals[1], + ), + measure_and_control( + drivers.mhz, + &orderers.mhz, + |res| publish_mhz_result(res, &publish), + &signals[2], + ), + measure_and_control( + drivers.sps, + &orderers.sps, + |res| publish_sps_result(res, &publish), + &signals[3], + ), + ) + .await; +} + +fn publish_sps_result( + sps_res: Result, + publish: &Queues, +) { + match sps_res { + Ok(measurements::Sps30 { + mass_pm1_0, + mass_pm2_5, + mass_pm4_0, + mass_pm10, + number_pm0_5, + number_pm1_0, + number_pm2_5, + number_pm4_0, + number_pm10, + typical_particle_size, + .. + }) => { + publish.send_p0(Reading::MassPm1_0(mass_pm1_0)); + publish.send_p0(Reading::MassPm2_5(mass_pm2_5)); + publish.send_p0(Reading::MassPm4_0(mass_pm4_0)); + publish.send_p0(Reading::MassPm10(mass_pm10)); + publish.send_p0(Reading::NumberPm0_5(number_pm0_5)); + publish.send_p0(Reading::NumberPm1_0(number_pm1_0)); + publish.send_p0(Reading::NumberPm2_5(number_pm2_5)); + publish.send_p0(Reading::NumberPm4_0(number_pm4_0)); + publish.send_p0(Reading::NumberPm10(number_pm10)); + publish + .send_p0(Reading::TypicalParticleSize(typical_particle_size)); + } + Err(err) => publish.queue_error(err), + } +} + +fn publish_mhz_result( + mhz_res: Result, + publish: &Queues, +) { + match mhz_res { + Ok(measurements::Mhz { co2, .. }) => { + publish.send_p0(Reading::Co2(co2)); + } + Err(err) => { + publish.queue_error(err); + } + } +} + +fn publish_sht_result( + sht_res: Result, + publish: &Queues, +) { + match sht_res { + Ok(measurements::Sht31 { + temperature, + humidity, + }) => { + publish.send_p0(Reading::Temperature(temperature)); + publish.send_p0(Reading::Humidity(humidity)); + } + Err(err) => publish.queue_error(err), + } +} + +fn publish_bme_result( + bme_res: Result, + publish: &Queues, +) { + match bme_res { + Ok(measurements::Bme { + pressure, + gas_resistance, + .. + }) => { + let gas_resistance = unwrap!(gas_resistance); // sensor is on + publish.send_p0(Reading::GassResistance(gas_resistance)); + publish.send_p0(Reading::Pressure(pressure)); + } + Err(err) => publish.queue_error(err), + } +} diff --git a/nodes/embassy/button-panel/src/comms.rs b/nodes/embassy/button-panel/src/comms.rs new file mode 100644 index 00000000..64de4ef0 --- /dev/null +++ b/nodes/embassy/button-panel/src/comms.rs @@ -0,0 +1,67 @@ +use defmt::warn; +use embassy_time::{Duration, Instant}; +use heapless::HistoryBuffer; +use protocol::{SensorMessage, affector}; +use usb_bridge_client::{NoSpaceInQueue, UsbHandle, UsbSender}; + +pub async fn handle(usb: UsbHandle<'_>) -> ! { + const MIN_BETWEEN_COMM_ERRS: Duration = Duration::from_secs(30); + let mut last_errors_at: HistoryBuffer<_, 5> = HistoryBuffer::new(); + + loop { + crate::PUBLISH.clear(); + + let (writer, _) = usb.split(); + send_messages(writer).await; + warn!("Error while sending messages"); + + let mut error_after = Instant::now(); + if last_errors_at.oldest_ordered().rev().copied().all( + |error: Instant| { + let is_recent = + error_after.duration_since(error) < MIN_BETWEEN_COMM_ERRS; + error_after = error; + is_recent + }, + ) { + defmt::error!( + "Something is terribly wrong with the connection, \ + 5 errors occured each within 30 seconds of the previous. \ + Resetting entire node" + ); + cortex_m::peripheral::SCB::sys_reset(); + } else { + last_errors_at.write(Instant::now()); + } + } +} + +const AFFECTOR_LIST_MAX_SIZE: usize = protocol::Msg::<5>::max_size(); +pub fn affector_list() -> heapless::Vec { + let list = affector::ListMessage::<5>::empty(); + let mut buf = heapless::Vec::new(); + defmt::unwrap!(buf.resize_default(AFFECTOR_LIST_MAX_SIZE)); + let encoded_len = list.encode_slice(&mut buf).len(); + buf.truncate(encoded_len); + buf +} + +async fn collect_msg() -> SensorMessage<10> { + let mut msg = SensorMessage::<10>::default(); + let reading = crate::PUBLISH.receive().await; + defmt::unwrap!(msg.values.push(reading)); + msg +} + +async fn send_messages(usb: UsbSender<'_>) { + let mut buf = [0; protocol::Msg::<5>::max_size()]; + loop { + let msg = collect_msg().await; + let encoded_len = msg.encode_slice(&mut buf[1..]).len(); + buf[0] = protocol::Msg::<0>::READINGS; + let to_send = &buf[..=encoded_len]; + while let Err(NoSpaceInQueue) = usb.send(to_send, true).await { + usb.wait_till_queue_free().await; + } + } +} diff --git a/nodes/embassy/button-panel/src/main.rs b/nodes/embassy/button-panel/src/main.rs new file mode 100644 index 00000000..00c6260d --- /dev/null +++ b/nodes/embassy/button-panel/src/main.rs @@ -0,0 +1,139 @@ +#![no_std] +#![no_main] + +use core::time::Duration; + +use embassy_executor::Spawner; +use embassy_futures::join; +use embassy_stm32::exti::ExtiInput; +use embassy_stm32::gpio::Pull; +use embassy_stm32::peripherals::IWDG; +use embassy_stm32::time::Hertz; +use embassy_stm32::wdg::IndependentWatchdog; +use embassy_stm32::{Config, usb}; +use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; +use embassy_sync::channel::Channel; +use embassy_time::Timer; +use futures::pin_mut; + +use defmt::trace; +use {defmt_rtt as _, panic_probe as _}; + +mod buttons; +mod comms; + +embassy_stm32::bind_interrupts!(struct Irqs { + OTG_FS => embassy_stm32::usb::InterruptHandler; +}); + +static PUBLISH: Channel = + Channel::new(); + +// 84 Mhz clock stm32f401 +// 48 Mhz clock for usb +fn config() -> Config { + use embassy_stm32::rcc::mux; + use embassy_stm32::rcc::{ + AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, + PllPreDiv, PllQDiv, PllSource, Sysclk, + }; + + let mut config = Config::default(); + config.rcc.hse = Some(Hse { + freq: Hertz(25_000_000), + mode: HseMode::Oscillator, + }); + config.rcc.pll_src = PllSource::HSE; + config.rcc.pll = Some(Pll { + prediv: PllPreDiv::DIV25, + mul: PllMul::MUL336, + divp: Some(PllPDiv::DIV4), // 25mhz / 25 * 336 / 4 = 84Mhz. + divq: Some(PllQDiv::DIV7), // 25mhz / 25 * 336 / 7 = 48Mhz. + divr: None, + }); + config.rcc.ahb_pre = AHBPrescaler::DIV1; + config.rcc.apb1_pre = APBPrescaler::DIV2; + config.rcc.apb2_pre = APBPrescaler::DIV1; + config.rcc.sys = Sysclk::PLL1_P; + config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q; + config +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_stm32::init(config()); + let dog = IndependentWatchdog::new( + p.IWDG, + Duration::from_secs(5).as_micros() as u32, + ); + + let buttons = buttons::Inputs { + bottom_left: ExtiInput::new(p.PC15, p.EXTI15, Pull::Down), + bottom_middle: ExtiInput::new(p.PB0, p.EXTI0, Pull::Down), + bottom_right: ExtiInput::new(p.PC14, p.EXTI14, Pull::Down), + top_left: ExtiInput::new(p.PB12, p.EXTI12, Pull::Down), + top_middle: ExtiInput::new(p.PB13, p.EXTI13, Pull::Down), + top_right: ExtiInput::new(p.PB1, p.EXTI1, Pull::Down), + }; + + let mut usb_driver_config = embassy_stm32::usb::Config::default(); + // Do not enable vbus_detection. This is a safe default that works in all + // boards. However, if your USB device is self-powered (can stay powered on + // if USB is unplugged), you need to enable vbus_detection to comply with + // the USB spec. If you enable it, the board + usb_driver_config.vbus_detection = false; + + let mut ep_out_buffer = [0u8; 256]; + let usb_driver = usb::Driver::new_fs( + p.USB_OTG_FS, + Irqs, + p.PA12, + p.PA11, + &mut ep_out_buffer, + usb_driver_config, + ); + + let affector_list = comms::affector_list(); + let stack_a = usb_bridge_client::StackA::new(); + let mut stack_b = usb_bridge_client::StackB::new(&stack_a, &affector_list); + let (mut usb_bus, usb_handle) = + usb_bridge_client::new(&stack_a, &mut stack_b, usb_driver); + + let handle_network = comms::handle(usb_handle); + pin_mut!(handle_network); + + let init_then_measure = buttons::init_then_measure(buttons); + + join::join4( + &mut handle_network, + init_then_measure, + usb_bus.run(), + keep_dog_happy(dog), + ) + .await; +} + +pub fn usb_config() -> embassy_usb::Config<'static> { + // Create embassy-usb Config + let mut config = embassy_usb::Config::new(0x16c0, 0x27DD); + config.manufacturer = Some("Vid"); + config.product = Some("Sensor node"); + config.serial_number = Some("2478437"); + + // Required for windows compatibility. + // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help + config.device_class = 0xEF; + config.device_sub_class = 0x02; + config.device_protocol = 0x01; + config.composite_with_iads = true; + + config +} + +async fn keep_dog_happy(mut dog: IndependentWatchdog<'_, IWDG>) -> ! { + loop { + Timer::after_secs(1).await; + trace!("petting dog"); + dog.pet(); + } +} diff --git a/nodes/embassy/button-panel/src/usb_wrapper.rs b/nodes/embassy/button-panel/src/usb_wrapper.rs new file mode 100644 index 00000000..e69de29b diff --git a/nodes/embassy/button-panel/stm32f401.svd b/nodes/embassy/button-panel/stm32f401.svd new file mode 100644 index 00000000..b9353d01 --- /dev/null +++ b/nodes/embassy/button-panel/stm32f401.svd @@ -0,0 +1,35196 @@ + + + STM32F401 + 1.1 + STM32F401 + + CM4 + r1p0 + little + false + false + 4 + false + + 8 + 32 + 0x20 + 0x00000000 + 0xFFFFFFFF + + + ADC_Common + ADC common registers + ADC_Common + 0x40012300 + + 0x0 + 0x9 + registers + + + FPU + FPU interrupt + 81 + + + + CCR + CCR + ADC common control register + 0x4 + 0x20 + read-write + 0x00000000 + + + TSVREFE + Temperature sensor and VREFINT + enable + 23 + 1 + + TSVREFE + read-write + + Disabled + Temperature sensor and V_REFINT channel disabled + 0 + + + Enabled + Temperature sensor and V_REFINT channel enabled + 1 + + + + + VBATE + VBAT enable + 22 + 1 + + VBATE + read-write + + Disabled + V_BAT channel disabled + 0 + + + Enabled + V_BAT channel enabled + 1 + + + + + ADCPRE + ADC prescaler + 16 + 2 + + ADCPRE + read-write + + Div2 + PCLK2 divided by 2 + 0 + + + Div4 + PCLK2 divided by 4 + 1 + + + Div6 + PCLK2 divided by 6 + 2 + + + Div8 + PCLK2 divided by 8 + 3 + + + + + + + + + ADC1 + Analog-to-digital converter + ADC + 0x40012000 + + 0x0 + 0x51 + registers + + + ADC + ADC1 global interrupt + 18 + + + + SR + SR + status register + 0x0 + 0x20 + read-write + 0x00000000 + + + OVR + Overrun + 5 + 1 + zeroToClear + + OVRR + read + + NoOverrun + No overrun occurred + 0 + + + Overrun + Overrun occurred + 1 + + + + OVRW + write + + Clear + Clear flag + 0 + + + + + STRT + Regular channel start flag + 4 + 1 + zeroToClear + + STRTR + read + + NotStarted + No regular channel conversion started + 0 + + + Started + Regular channel conversion has started + 1 + + + + STRTW + write + + Clear + Clear flag + 0 + + + + + JSTRT + Injected channel start + flag + 3 + 1 + zeroToClear + + JSTRTR + read + + NotStarted + No injected channel conversion started + 0 + + + Started + Injected channel conversion has started + 1 + + + + JSTRTW + write + + Clear + Clear flag + 0 + + + + + JEOC + Injected channel end of + conversion + 2 + 1 + zeroToClear + + JEOCR + read + + NotComplete + Conversion is not complete + 0 + + + Complete + Conversion complete + 1 + + + + JEOCW + write + + Clear + Clear flag + 0 + + + + + EOC + Regular channel end of + conversion + 1 + 1 + zeroToClear + + EOCR + read + + NotComplete + Conversion is not complete + 0 + + + Complete + Conversion complete + 1 + + + + EOCW + write + + Clear + Clear flag + 0 + + + + + AWD + Analog watchdog flag + 0 + 1 + zeroToClear + + AWDR + read + + NoEvent + No analog watchdog event occurred + 0 + + + Event + Analog watchdog event occurred + 1 + + + + AWDW + write + + Clear + Clear flag + 0 + + + + + + + CR1 + CR1 + control register 1 + 0x4 + 0x20 + read-write + 0x00000000 + + + OVRIE + Overrun interrupt enable + 26 + 1 + + OVRIE + read-write + + Disabled + Overrun interrupt disabled + 0 + + + Enabled + Overrun interrupt enabled + 1 + + + + + RES + Resolution + 24 + 2 + + RES + read-write + + TwelveBit + 12-bit (15 ADCCLK cycles) + 0 + + + TenBit + 10-bit (13 ADCCLK cycles) + 1 + + + EightBit + 8-bit (11 ADCCLK cycles) + 2 + + + SixBit + 6-bit (9 ADCCLK cycles) + 3 + + + + + AWDEN + Analog watchdog enable on regular + channels + 23 + 1 + + AWDEN + read-write + + Disabled + Analog watchdog disabled on regular channels + 0 + + + Enabled + Analog watchdog enabled on regular channels + 1 + + + + + JAWDEN + Analog watchdog enable on injected + channels + 22 + 1 + + JAWDEN + read-write + + Disabled + Analog watchdog disabled on injected channels + 0 + + + Enabled + Analog watchdog enabled on injected channels + 1 + + + + + DISCNUM + Discontinuous mode channel + count + 13 + 3 + + + 0 + 7 + + + + + JDISCEN + Discontinuous mode on injected + channels + 12 + 1 + + JDISCEN + read-write + + Disabled + Discontinuous mode on injected channels disabled + 0 + + + Enabled + Discontinuous mode on injected channels enabled + 1 + + + + + DISCEN + Discontinuous mode on regular + channels + 11 + 1 + + DISCEN + read-write + + Disabled + Discontinuous mode on regular channels disabled + 0 + + + Enabled + Discontinuous mode on regular channels enabled + 1 + + + + + JAUTO + Automatic injected group + conversion + 10 + 1 + + JAUTO + read-write + + Disabled + Automatic injected group conversion disabled + 0 + + + Enabled + Automatic injected group conversion enabled + 1 + + + + + AWDSGL + Enable the watchdog on a single channel + in scan mode + 9 + 1 + + AWDSGL + read-write + + AllChannels + Analog watchdog enabled on all channels + 0 + + + SingleChannel + Analog watchdog enabled on a single channel + 1 + + + + + SCAN + Scan mode + 8 + 1 + + SCAN + read-write + + Disabled + Scan mode disabled + 0 + + + Enabled + Scan mode enabled + 1 + + + + + JEOCIE + Interrupt enable for injected + channels + 7 + 1 + + JEOCIE + read-write + + Disabled + JEOC interrupt disabled + 0 + + + Enabled + JEOC interrupt enabled + 1 + + + + + AWDIE + Analog watchdog interrupt + enable + 6 + 1 + + AWDIE + read-write + + Disabled + Analogue watchdog interrupt disabled + 0 + + + Enabled + Analogue watchdog interrupt enabled + 1 + + + + + EOCIE + Interrupt enable for EOC + 5 + 1 + + EOCIE + read-write + + Disabled + EOC interrupt disabled + 0 + + + Enabled + EOC interrupt enabled + 1 + + + + + AWDCH + Analog watchdog channel select + bits + 0 + 5 + + + 0 + 18 + + + + + + + CR2 + CR2 + control register 2 + 0x8 + 0x20 + read-write + 0x00000000 + + + SWSTART + Start conversion of regular + channels + 30 + 1 + + SWSTARTW + write + + Start + Starts conversion of regular channels + 1 + + + + + EXTEN + External trigger enable for regular + channels + 28 + 2 + + EXTEN + read-write + + Disabled + Trigger detection disabled + 0 + + + RisingEdge + Trigger detection on the rising edge + 1 + + + FallingEdge + Trigger detection on the falling edge + 2 + + + BothEdges + Trigger detection on both the rising and falling edges + 3 + + + + + EXTSEL + External event select for regular + group + 24 + 4 + + EXTSEL + read-write + + TIM1CC1 + Timer 1 CC1 event + 0 + + + TIM1CC2 + Timer 1 CC2 event + 1 + + + TIM1CC3 + Timer 1 CC3 event + 2 + + + TIM2CC2 + Timer 2 CC2 event + 3 + + + TIM2CC3 + Timer 2 CC3 event + 4 + + + TIM2CC4 + Timer 2 CC4 event + 5 + + + TIM2TRGO + Timer 2 TRGO event + 6 + + + TIM3CC1 + Timer 3 CC1 event + 7 + + + TIM3TRGO + Timer 3 TRGO event + 8 + + + TIM4CC4 + Timer 4 CC4 event + 9 + + + TIM5CC1 + Timer 5 CC1 event + 10 + + + TIM5CC2 + Timer 5 CC2 event + 11 + + + TIM5CC3 + Timer 5 CC3 event + 12 + + + EXTI11 + EXTI line 11 + 15 + + + + + JSWSTART + Start conversion of injected + channels + 22 + 1 + + JSWSTARTW + write + + Start + Starts conversion of injected channels + 1 + + + + + JEXTEN + External trigger enable for injected + channels + 20 + 2 + + JEXTEN + read-write + + Disabled + Trigger detection disabled + 0 + + + RisingEdge + Trigger detection on the rising edge + 1 + + + FallingEdge + Trigger detection on the falling edge + 2 + + + BothEdges + Trigger detection on both the rising and falling edges + 3 + + + + + JEXTSEL + External event select for injected + group + 16 + 4 + + JEXTSEL + read-write + + TIM1CC4 + Timer 1 CC4 event + 0 + + + TIM1TRGO + Timer 1 TRGO event + 1 + + + TIM2CC1 + Timer 2 CC1 event + 2 + + + TIM2TRGO + Timer 2 TRGO event + 3 + + + TIM3CC2 + Timer 3 CC2 event + 4 + + + TIM3CC4 + Timer 3 CC4 event + 5 + + + TIM4CC1 + Timer 4 CC1 event + 6 + + + TIM4CC2 + Timer 4 CC2 event + 7 + + + TIM4CC3 + Timer 4 CC3 event + 8 + + + TIM4TRGO + Timer 4 TRGO event + 9 + + + TIM5CC4 + Timer 5 CC4 event + 10 + + + TIM5TRGO + Timer 5 TRGO event + 11 + + + EXTI15 + EXTI line 15 + 15 + + + + + ALIGN + Data alignment + 11 + 1 + + ALIGN + read-write + + Right + Right alignment + 0 + + + Left + Left alignment + 1 + + + + + EOCS + End of conversion + selection + 10 + 1 + + EOCS + read-write + + EachSequence + The EOC bit is set at the end of each sequence of regular conversions + 0 + + + EachConversion + The EOC bit is set at the end of each regular conversion + 1 + + + + + DDS + DMA disable selection (for single ADC + mode) + 9 + 1 + + DDS + read-write + + Single + No new DMA request is issued after the last transfer + 0 + + + Continuous + DMA requests are issued as long as data are converted and DMA=1 + 1 + + + + + DMA + Direct memory access mode (for single + ADC mode) + 8 + 1 + + DMA + read-write + + Disabled + DMA mode disabled + 0 + + + Enabled + DMA mode enabled + 1 + + + + + CONT + Continuous conversion + 1 + 1 + + CONT + read-write + + Single + Single conversion mode + 0 + + + Continuous + Continuous conversion mode + 1 + + + + + ADON + A/D Converter ON / OFF + 0 + 1 + + ADON + read-write + + Disabled + Disable ADC conversion and go to power down mode + 0 + + + Enabled + Enable ADC + 1 + + + + + + + SMPR1 + SMPR1 + sample time register 1 + 0xC + 0x20 + read-write + 0x00000000 + + + SMP18 + Channel 18 sampling time selection + 24 + 3 + + + + SMP17 + Channel 17 sampling time selection + 21 + 3 + + + + SMP16 + Channel 16 sampling time selection + 18 + 3 + + + + SMP15 + Channel 15 sampling time selection + 15 + 3 + + + + SMP14 + Channel 14 sampling time selection + 12 + 3 + + + + SMP13 + Channel 13 sampling time selection + 9 + 3 + + + + SMP12 + Channel 12 sampling time selection + 6 + 3 + + + + SMP11 + Channel 11 sampling time selection + 3 + 3 + + + + SMP10 + Channel 10 sampling time selection + 0 + 3 + + SMP10 + read-write + + Cycles3 + 3 cycles + 0 + + + Cycles15 + 15 cycles + 1 + + + Cycles28 + 28 cycles + 2 + + + Cycles56 + 56 cycles + 3 + + + Cycles84 + 84 cycles + 4 + + + Cycles112 + 112 cycles + 5 + + + Cycles144 + 144 cycles + 6 + + + Cycles480 + 480 cycles + 7 + + + + + + + SMPR2 + SMPR2 + sample time register 2 + 0x10 + 0x20 + read-write + 0x00000000 + + + SMP9 + Channel 9 sampling time selection + 27 + 3 + + + + SMP8 + Channel 8 sampling time selection + 24 + 3 + + + + SMP7 + Channel 7 sampling time selection + 21 + 3 + + + + SMP6 + Channel 6 sampling time selection + 18 + 3 + + + + SMP5 + Channel 5 sampling time selection + 15 + 3 + + + + SMP4 + Channel 4 sampling time selection + 12 + 3 + + + + SMP3 + Channel 3 sampling time selection + 9 + 3 + + + + SMP2 + Channel 2 sampling time selection + 6 + 3 + + + + SMP1 + Channel 1 sampling time selection + 3 + 3 + + + + SMP0 + Channel 0 sampling time selection + 0 + 3 + + SMP0 + read-write + + Cycles3 + 3 cycles + 0 + + + Cycles15 + 15 cycles + 1 + + + Cycles28 + 28 cycles + 2 + + + Cycles56 + 56 cycles + 3 + + + Cycles84 + 84 cycles + 4 + + + Cycles112 + 112 cycles + 5 + + + Cycles144 + 144 cycles + 6 + + + Cycles480 + 480 cycles + 7 + + + + + + + 4 + 0x4 + 1-4 + JOFR%s + JOFR1 + injected channel data offset register + x + 0x14 + 0x20 + read-write + 0x00000000 + + + JOFFSET + Data offset for injected channel + x + 0 + 12 + + + 0 + 4095 + + + + + + + HTR + HTR + watchdog higher threshold + register + 0x24 + 0x20 + read-write + 0x00000FFF + + + HT + Analog watchdog higher + threshold + 0 + 12 + + + 0 + 4095 + + + + + + + LTR + LTR + watchdog lower threshold + register + 0x28 + 0x20 + read-write + 0x00000000 + + + LT + Analog watchdog lower + threshold + 0 + 12 + + + 0 + 4095 + + + + + + + SQR1 + SQR1 + regular sequence register 1 + 0x2C + 0x20 + read-write + 0x00000000 + + + L + Regular channel sequence + length + 20 + 4 + + + 0 + 15 + + + + + SQ16 + 16th conversion in regular + sequence + 15 + 5 + + + 0 + 18 + + + + + SQ15 + 15th conversion in regular + sequence + 10 + 5 + + + 0 + 18 + + + + + SQ14 + 14th conversion in regular + sequence + 5 + 5 + + + 0 + 18 + + + + + SQ13 + 13th conversion in regular + sequence + 0 + 5 + + + 0 + 18 + + + + + + + SQR2 + SQR2 + regular sequence register 2 + 0x30 + 0x20 + read-write + 0x00000000 + + + SQ12 + 12th conversion in regular + sequence + 25 + 5 + + + 0 + 18 + + + + + SQ11 + 11th conversion in regular + sequence + 20 + 5 + + + 0 + 18 + + + + + SQ10 + 10th conversion in regular + sequence + 15 + 5 + + + 0 + 18 + + + + + SQ9 + 9th conversion in regular + sequence + 10 + 5 + + + 0 + 18 + + + + + SQ8 + 8th conversion in regular + sequence + 5 + 5 + + + 0 + 18 + + + + + SQ7 + 7th conversion in regular + sequence + 0 + 5 + + + 0 + 18 + + + + + + + SQR3 + SQR3 + regular sequence register 3 + 0x34 + 0x20 + read-write + 0x00000000 + + + SQ6 + 6th conversion in regular + sequence + 25 + 5 + + + 0 + 18 + + + + + SQ5 + 5th conversion in regular + sequence + 20 + 5 + + + 0 + 18 + + + + + SQ4 + 4th conversion in regular + sequence + 15 + 5 + + + 0 + 18 + + + + + SQ3 + 3rd conversion in regular + sequence + 10 + 5 + + + 0 + 18 + + + + + SQ2 + 2nd conversion in regular + sequence + 5 + 5 + + + 0 + 18 + + + + + SQ1 + 1st conversion in regular + sequence + 0 + 5 + + + 0 + 18 + + + + + + + JSQR + JSQR + injected sequence register + 0x38 + 0x20 + read-write + 0x00000000 + + + JL + Injected sequence length + 20 + 2 + + + 0 + 3 + + + + + JSQ4 + 4th conversion in injected + sequence + 15 + 5 + + + 0 + 18 + + + + + JSQ3 + 3rd conversion in injected + sequence + 10 + 5 + + + 0 + 18 + + + + + JSQ2 + 2nd conversion in injected + sequence + 5 + 5 + + + 0 + 18 + + + + + JSQ1 + 1st conversion in injected + sequence + 0 + 5 + + + 0 + 18 + + + + + + + 4 + 0x4 + 1-4 + JDR%s + JDR1 + injected data register x + 0x3C + 0x20 + read-only + 0x00000000 + + + JDATA + Injected data + 0 + 16 + + + + + DR + DR + regular data register + 0x4C + 0x20 + read-only + 0x00000000 + + + DATA + Regular data + 0 + 16 + + + + + + + CRC + Cryptographic processor + CRC + 0x40023000 + + 0x0 + 0x400 + registers + + + + DR + DR + Data register + 0x0 + 0x20 + read-write + 0xFFFFFFFF + + + DR + Data Register + 0 + 32 + + + 0 + 4294967295 + + + + + + + IDR + IDR + Independent Data register + 0x4 + 0x20 + read-write + 0x00000000 + + + IDR + Independent Data register + 0 + 8 + + + 0 + 255 + + + + + + + CR + CR + Control register + 0x8 + 0x20 + write-only + 0x00000000 + + + RESET + Control regidter + 0 + 1 + + RESETW + write + + Reset + Resets the CRC calculation unit and sets the data register to 0xFFFF FFFF + 1 + + + + + + + + + DBGMCU + Debug support + DBG + 0xE0042000 + + 0x0 + 0x400 + registers + + + + IDCODE + IDCODE + IDCODE + 0x0 + 0x20 + read-only + 0x10006411 + + + DEV_ID + DEV_ID + 0 + 12 + + + REV_ID + REV_ID + 16 + 16 + + + + + CR + CR + Control Register + 0x4 + 0x20 + read-write + 0x00000000 + + + DBG_SLEEP + DBG_SLEEP + 0 + 1 + + + DBG_STOP + DBG_STOP + 1 + 1 + + + DBG_STANDBY + DBG_STANDBY + 2 + 1 + + + TRACE_IOEN + TRACE_IOEN + 5 + 1 + + + TRACE_MODE + TRACE_MODE + 6 + 2 + + + + + APB1_FZ + APB1_FZ + Debug MCU APB1 Freeze registe + 0x8 + 0x20 + read-write + 0x00000000 + + + DBG_TIM2_STOP + DBG_TIM2_STOP + 0 + 1 + + + DBG_TIM3_STOP + DBG_TIM3 _STOP + 1 + 1 + + + DBG_TIM4_STOP + DBG_TIM4_STOP + 2 + 1 + + + DBG_TIM5_STOP + DBG_TIM5_STOP + 3 + 1 + + + DBG_RTC_Stop + RTC stopped when Core is + halted + 10 + 1 + + + DBG_WWDG_STOP + DBG_WWDG_STOP + 11 + 1 + + + DBG_IWDG_STOP + DBG_IWDEG_STOP + 12 + 1 + + + DBG_I2C1_SMBUS_TIMEOUT + DBG_J2C1_SMBUS_TIMEOUT + 21 + 1 + + + DBG_I2C2_SMBUS_TIMEOUT + DBG_J2C2_SMBUS_TIMEOUT + 22 + 1 + + + DBG_I2C3SMBUS_TIMEOUT + DBG_J2C3SMBUS_TIMEOUT + 23 + 1 + + + + + APB2_FZ + APB2_FZ + Debug MCU APB2 Freeze registe + 0xC + 0x20 + read-write + 0x00000000 + + + DBG_TIM1_STOP + TIM1 counter stopped when core is + halted + 0 + 1 + + + DBG_TIM9_STOP + TIM9 counter stopped when core is + halted + 16 + 1 + + + DBG_TIM10_STOP + TIM10 counter stopped when core is + halted + 17 + 1 + + + DBG_TIM11_STOP + TIM11 counter stopped when core is + halted + 18 + 1 + + + + + + + EXTI + External interrupt/event + controller + EXTI + 0x40013C00 + + 0x0 + 0x400 + registers + + + TAMP_STAMP + Tamper and TimeStamp interrupts through the + EXTI line + 2 + + + EXTI0 + EXTI Line0 interrupt + 6 + + + EXTI1 + EXTI Line1 interrupt + 7 + + + EXTI2 + EXTI Line2 interrupt + 8 + + + EXTI3 + EXTI Line3 interrupt + 9 + + + EXTI4 + EXTI Line4 interrupt + 10 + + + EXTI9_5 + EXTI Line[9:5] interrupts + 23 + + + EXTI15_10 + EXTI Line[15:10] interrupts + 40 + + + + IMR + IMR + Interrupt mask register + (EXTI_IMR) + 0x0 + 0x20 + read-write + 0x00000000 + + + MR0 + Interrupt Mask on line 0 + 0 + 1 + + MR0 + read-write + + Masked + Interrupt request line is masked + 0 + + + Unmasked + Interrupt request line is unmasked + 1 + + + + + MR1 + Interrupt Mask on line 1 + 1 + 1 + + + + MR2 + Interrupt Mask on line 2 + 2 + 1 + + + + MR3 + Interrupt Mask on line 3 + 3 + 1 + + + + MR4 + Interrupt Mask on line 4 + 4 + 1 + + + + MR5 + Interrupt Mask on line 5 + 5 + 1 + + + + MR6 + Interrupt Mask on line 6 + 6 + 1 + + + + MR7 + Interrupt Mask on line 7 + 7 + 1 + + + + MR8 + Interrupt Mask on line 8 + 8 + 1 + + + + MR9 + Interrupt Mask on line 9 + 9 + 1 + + + + MR10 + Interrupt Mask on line 10 + 10 + 1 + + + + MR11 + Interrupt Mask on line 11 + 11 + 1 + + + + MR12 + Interrupt Mask on line 12 + 12 + 1 + + + + MR13 + Interrupt Mask on line 13 + 13 + 1 + + + + MR14 + Interrupt Mask on line 14 + 14 + 1 + + + + MR15 + Interrupt Mask on line 15 + 15 + 1 + + + + MR16 + Interrupt Mask on line 16 + 16 + 1 + + + + MR17 + Interrupt Mask on line 17 + 17 + 1 + + + + MR18 + Interrupt Mask on line 18 + 18 + 1 + + + + MR19 + Interrupt Mask on line 19 + 19 + 1 + + + + MR20 + Interrupt Mask on line 20 + 20 + 1 + + + + MR21 + Interrupt Mask on line 21 + 21 + 1 + + + + MR22 + Interrupt Mask on line 22 + 22 + 1 + + + + + + EMR + EMR + Event mask register (EXTI_EMR) + 0x4 + 0x20 + read-write + 0x00000000 + + + MR0 + Event Mask on line 0 + 0 + 1 + + MR0 + read-write + + Masked + Interrupt request line is masked + 0 + + + Unmasked + Interrupt request line is unmasked + 1 + + + + + MR1 + Event Mask on line 1 + 1 + 1 + + + + MR2 + Event Mask on line 2 + 2 + 1 + + + + MR3 + Event Mask on line 3 + 3 + 1 + + + + MR4 + Event Mask on line 4 + 4 + 1 + + + + MR5 + Event Mask on line 5 + 5 + 1 + + + + MR6 + Event Mask on line 6 + 6 + 1 + + + + MR7 + Event Mask on line 7 + 7 + 1 + + + + MR8 + Event Mask on line 8 + 8 + 1 + + + + MR9 + Event Mask on line 9 + 9 + 1 + + + + MR10 + Event Mask on line 10 + 10 + 1 + + + + MR11 + Event Mask on line 11 + 11 + 1 + + + + MR12 + Event Mask on line 12 + 12 + 1 + + + + MR13 + Event Mask on line 13 + 13 + 1 + + + + MR14 + Event Mask on line 14 + 14 + 1 + + + + MR15 + Event Mask on line 15 + 15 + 1 + + + + MR16 + Event Mask on line 16 + 16 + 1 + + + + MR17 + Event Mask on line 17 + 17 + 1 + + + + MR18 + Event Mask on line 18 + 18 + 1 + + + + MR19 + Event Mask on line 19 + 19 + 1 + + + + MR20 + Event Mask on line 20 + 20 + 1 + + + + MR21 + Event Mask on line 21 + 21 + 1 + + + + MR22 + Event Mask on line 22 + 22 + 1 + + + + + + RTSR + RTSR + Rising Trigger selection register + (EXTI_RTSR) + 0x8 + 0x20 + read-write + 0x00000000 + + + TR0 + Rising trigger event configuration of + line 0 + 0 + 1 + + TR0 + read-write + + Disabled + Rising edge trigger is disabled + 0 + + + Enabled + Rising edge trigger is enabled + 1 + + + + + TR1 + Rising trigger event configuration of + line 1 + 1 + 1 + + + + TR2 + Rising trigger event configuration of + line 2 + 2 + 1 + + + + TR3 + Rising trigger event configuration of + line 3 + 3 + 1 + + + + TR4 + Rising trigger event configuration of + line 4 + 4 + 1 + + + + TR5 + Rising trigger event configuration of + line 5 + 5 + 1 + + + + TR6 + Rising trigger event configuration of + line 6 + 6 + 1 + + + + TR7 + Rising trigger event configuration of + line 7 + 7 + 1 + + + + TR8 + Rising trigger event configuration of + line 8 + 8 + 1 + + + + TR9 + Rising trigger event configuration of + line 9 + 9 + 1 + + + + TR10 + Rising trigger event configuration of + line 10 + 10 + 1 + + + + TR11 + Rising trigger event configuration of + line 11 + 11 + 1 + + + + TR12 + Rising trigger event configuration of + line 12 + 12 + 1 + + + + TR13 + Rising trigger event configuration of + line 13 + 13 + 1 + + + + TR14 + Rising trigger event configuration of + line 14 + 14 + 1 + + + + TR15 + Rising trigger event configuration of + line 15 + 15 + 1 + + + + TR16 + Rising trigger event configuration of + line 16 + 16 + 1 + + + + TR17 + Rising trigger event configuration of + line 17 + 17 + 1 + + + + TR18 + Rising trigger event configuration of + line 18 + 18 + 1 + + + + TR19 + Rising trigger event configuration of + line 19 + 19 + 1 + + + + TR20 + Rising trigger event configuration of + line 20 + 20 + 1 + + + + TR21 + Rising trigger event configuration of + line 21 + 21 + 1 + + + + TR22 + Rising trigger event configuration of + line 22 + 22 + 1 + + + + + + FTSR + FTSR + Falling Trigger selection register + (EXTI_FTSR) + 0xC + 0x20 + read-write + 0x00000000 + + + TR0 + Falling trigger event configuration of + line 0 + 0 + 1 + + TR0 + read-write + + Disabled + Falling edge trigger is disabled + 0 + + + Enabled + Falling edge trigger is enabled + 1 + + + + + TR1 + Falling trigger event configuration of + line 1 + 1 + 1 + + + + TR2 + Falling trigger event configuration of + line 2 + 2 + 1 + + + + TR3 + Falling trigger event configuration of + line 3 + 3 + 1 + + + + TR4 + Falling trigger event configuration of + line 4 + 4 + 1 + + + + TR5 + Falling trigger event configuration of + line 5 + 5 + 1 + + + + TR6 + Falling trigger event configuration of + line 6 + 6 + 1 + + + + TR7 + Falling trigger event configuration of + line 7 + 7 + 1 + + + + TR8 + Falling trigger event configuration of + line 8 + 8 + 1 + + + + TR9 + Falling trigger event configuration of + line 9 + 9 + 1 + + + + TR10 + Falling trigger event configuration of + line 10 + 10 + 1 + + + + TR11 + Falling trigger event configuration of + line 11 + 11 + 1 + + + + TR12 + Falling trigger event configuration of + line 12 + 12 + 1 + + + + TR13 + Falling trigger event configuration of + line 13 + 13 + 1 + + + + TR14 + Falling trigger event configuration of + line 14 + 14 + 1 + + + + TR15 + Falling trigger event configuration of + line 15 + 15 + 1 + + + + TR16 + Falling trigger event configuration of + line 16 + 16 + 1 + + + + TR17 + Falling trigger event configuration of + line 17 + 17 + 1 + + + + TR18 + Falling trigger event configuration of + line 18 + 18 + 1 + + + + TR19 + Falling trigger event configuration of + line 19 + 19 + 1 + + + + TR20 + Falling trigger event configuration of + line 20 + 20 + 1 + + + + TR21 + Falling trigger event configuration of + line 21 + 21 + 1 + + + + TR22 + Falling trigger event configuration of + line 22 + 22 + 1 + + + + + + SWIER + SWIER + Software interrupt event register + (EXTI_SWIER) + 0x10 + 0x20 + read-write + 0x00000000 + + + SWIER0 + Software Interrupt on line + 0 + 0 + 1 + + SWIER0W + write + + Pend + Generates an interrupt request + 1 + + + + + SWIER1 + Software Interrupt on line + 1 + 1 + 1 + + + + SWIER2 + Software Interrupt on line + 2 + 2 + 1 + + + + SWIER3 + Software Interrupt on line + 3 + 3 + 1 + + + + SWIER4 + Software Interrupt on line + 4 + 4 + 1 + + + + SWIER5 + Software Interrupt on line + 5 + 5 + 1 + + + + SWIER6 + Software Interrupt on line + 6 + 6 + 1 + + + + SWIER7 + Software Interrupt on line + 7 + 7 + 1 + + + + SWIER8 + Software Interrupt on line + 8 + 8 + 1 + + + + SWIER9 + Software Interrupt on line + 9 + 9 + 1 + + + + SWIER10 + Software Interrupt on line + 10 + 10 + 1 + + + + SWIER11 + Software Interrupt on line + 11 + 11 + 1 + + + + SWIER12 + Software Interrupt on line + 12 + 12 + 1 + + + + SWIER13 + Software Interrupt on line + 13 + 13 + 1 + + + + SWIER14 + Software Interrupt on line + 14 + 14 + 1 + + + + SWIER15 + Software Interrupt on line + 15 + 15 + 1 + + + + SWIER16 + Software Interrupt on line + 16 + 16 + 1 + + + + SWIER17 + Software Interrupt on line + 17 + 17 + 1 + + + + SWIER18 + Software Interrupt on line + 18 + 18 + 1 + + + + SWIER19 + Software Interrupt on line + 19 + 19 + 1 + + + + SWIER20 + Software Interrupt on line + 20 + 20 + 1 + + + + SWIER21 + Software Interrupt on line + 21 + 21 + 1 + + + + SWIER22 + Software Interrupt on line + 22 + 22 + 1 + + + + + + PR + PR + Pending register (EXTI_PR) + 0x14 + 0x20 + read-write + 0x00000000 + + + PR0 + Pending bit 0 + 0 + 1 + oneToClear + + PR0R + read + + NotPending + No trigger request occurred + 0 + + + Pending + Selected trigger request occurred + 1 + + + + PR0W + write + + Clear + Clears pending bit + 1 + + + + + PR1 + Pending bit 1 + 1 + 1 + oneToClear + + read + + + write + + + + PR2 + Pending bit 2 + 2 + 1 + oneToClear + + read + + + write + + + + PR3 + Pending bit 3 + 3 + 1 + oneToClear + + read + + + write + + + + PR4 + Pending bit 4 + 4 + 1 + oneToClear + + read + + + write + + + + PR5 + Pending bit 5 + 5 + 1 + oneToClear + + read + + + write + + + + PR6 + Pending bit 6 + 6 + 1 + oneToClear + + read + + + write + + + + PR7 + Pending bit 7 + 7 + 1 + oneToClear + + read + + + write + + + + PR8 + Pending bit 8 + 8 + 1 + oneToClear + + read + + + write + + + + PR9 + Pending bit 9 + 9 + 1 + oneToClear + + read + + + write + + + + PR10 + Pending bit 10 + 10 + 1 + oneToClear + + read + + + write + + + + PR11 + Pending bit 11 + 11 + 1 + oneToClear + + read + + + write + + + + PR12 + Pending bit 12 + 12 + 1 + oneToClear + + read + + + write + + + + PR13 + Pending bit 13 + 13 + 1 + oneToClear + + read + + + write + + + + PR14 + Pending bit 14 + 14 + 1 + oneToClear + + read + + + write + + + + PR15 + Pending bit 15 + 15 + 1 + oneToClear + + read + + + write + + + + PR16 + Pending bit 16 + 16 + 1 + oneToClear + + read + + + write + + + + PR17 + Pending bit 17 + 17 + 1 + oneToClear + + read + + + write + + + + PR18 + Pending bit 18 + 18 + 1 + oneToClear + + read + + + write + + + + PR19 + Pending bit 19 + 19 + 1 + oneToClear + + read + + + write + + + + PR20 + Pending bit 20 + 20 + 1 + oneToClear + + read + + + write + + + + PR21 + Pending bit 21 + 21 + 1 + oneToClear + + read + + + write + + + + PR22 + Pending bit 22 + 22 + 1 + oneToClear + + read + + + write + + + + + + + + FLASH + FLASH + FLASH + 0x40023C00 + + 0x0 + 0x400 + registers + + + FLASH + FLASH global interrupt + 4 + + + + ACR + ACR + Flash access control register + 0x0 + 0x20 + 0x00000000 + + + LATENCY + Latency + 0 + 4 + read-write + + LATENCY + read-write + + WS0 + 0 wait states + 0 + + + WS1 + 1 wait states + 1 + + + WS2 + 2 wait states + 2 + + + WS3 + 3 wait states + 3 + + + WS4 + 4 wait states + 4 + + + WS5 + 5 wait states + 5 + + + WS6 + 6 wait states + 6 + + + WS7 + 7 wait states + 7 + + + WS8 + 8 wait states + 8 + + + WS9 + 9 wait states + 9 + + + WS10 + 10 wait states + 10 + + + WS11 + 11 wait states + 11 + + + WS12 + 12 wait states + 12 + + + WS13 + 13 wait states + 13 + + + WS14 + 14 wait states + 14 + + + WS15 + 15 wait states + 15 + + + + + PRFTEN + Prefetch enable + 8 + 1 + read-write + + PRFTEN + read-write + + Disabled + Prefetch is disabled + 0 + + + Enabled + Prefetch is enabled + 1 + + + + + ICEN + Instruction cache enable + 9 + 1 + read-write + + ICEN + read-write + + Disabled + Instruction cache is disabled + 0 + + + Enabled + Instruction cache is enabled + 1 + + + + + DCEN + Data cache enable + 10 + 1 + read-write + + DCEN + read-write + + Disabled + Data cache is disabled + 0 + + + Enabled + Data cache is enabled + 1 + + + + + ICRST + Instruction cache reset + 11 + 1 + write-only + + ICRST + write + + NotReset + Instruction cache is not reset + 0 + + + Reset + Instruction cache is reset + 1 + + + + + DCRST + Data cache reset + 12 + 1 + read-write + + DCRST + read-write + + NotReset + Data cache is not reset + 0 + + + Reset + Data cache is reset + 1 + + + + + + + KEYR + KEYR + Flash key register + 0x4 + 0x20 + write-only + 0x00000000 + + + KEY + FPEC key + 0 + 32 + + + 0 + 4294967295 + + + + + + + OPTKEYR + OPTKEYR + Flash option key register + 0x8 + 0x20 + write-only + 0x00000000 + + + OPTKEY + Option byte key + 0 + 32 + + + 0 + 4294967295 + + + + + + + SR + SR + Status register + 0xC + 0x20 + 0x00000000 + + + EOP + End of operation + 0 + 1 + read-write + oneToClear + + EOPW + write + + Clear + Clear error flag + 1 + + + + + OPERR + Operation error + 1 + 1 + read-write + oneToClear + + OPERRW + write + + Clear + Clear error flag + 1 + + + + + WRPERR + Write protection error + 4 + 1 + read-write + oneToClear + + WRPERRW + write + + Clear + Clear error flag + 1 + + + + + PGAERR + Programming alignment + error + 5 + 1 + read-write + oneToClear + + PGAERRW + write + + Clear + Clear error flag + 1 + + + + + PGPERR + Programming parallelism + error + 6 + 1 + read-write + oneToClear + + PGPERRW + write + + Clear + Clear error flag + 1 + + + + + PGSERR + Programming sequence error + 7 + 1 + read-write + oneToClear + + PGSERRW + write + + Clear + Clear error flag + 1 + + + + + BSY + Busy + 16 + 1 + read-only + + BSYR + read + + NotBusy + no Flash memory operation ongoing + 0 + + + Busy + Flash memory operation ongoing + 1 + + + + + + + CR + CR + Control register + 0x10 + 0x20 + read-write + 0x80000000 + + + PG + Programming + 0 + 1 + + PG + read-write + + Program + Flash programming activated + 1 + + + + + SER + Sector Erase + 1 + 1 + + SER + read-write + + SectorErase + Erase activated for selected sector + 1 + + + + + MER + Mass Erase + 2 + 1 + + MER + read-write + + MassErase + Erase activated for all user sectors + 1 + + + + + SNB + Sector number + 3 + 4 + + + 0 + 11 + + + + + PSIZE + Program size + 8 + 2 + + PSIZE + read-write + + PSIZE8 + Program x8 + 0 + + + PSIZE16 + Program x16 + 1 + + + PSIZE32 + Program x32 + 2 + + + PSIZE64 + Program x64 + 3 + + + + + STRT + Start + 16 + 1 + + STRT + read-write + + Start + Trigger an erase operation + 1 + + + + + EOPIE + End of operation interrupt + enable + 24 + 1 + + EOPIE + read-write + + Disabled + End of operation interrupt disabled + 0 + + + Enabled + End of operation interrupt enabled + 1 + + + + + ERRIE + Error interrupt enable + 25 + 1 + + ERRIE + read-write + + Disabled + Error interrupt generation disabled + 0 + + + Enabled + Error interrupt generation enabled + 1 + + + + + LOCK + Lock + 31 + 1 + + LOCK + read-write + + Unlocked + FLASH_CR register is unlocked + 0 + + + Locked + FLASH_CR register is locked + 1 + + + + + + + OPTCR + OPTCR + Flash option control register + 0x14 + 0x20 + read-write + 0x00000014 + + + OPTLOCK + Option lock + 0 + 1 + + + OPTSTRT + Option start + 1 + 1 + + + BOR_LEV + BOR reset Level + 2 + 2 + + + WDG_SW + WDG_SW User option bytes + 5 + 1 + + + nRST_STOP + nRST_STOP User option + bytes + 6 + 1 + + + nRST_STDBY + nRST_STDBY User option + bytes + 7 + 1 + + + RDP + Read protect + 8 + 8 + + + nWRP + Not write protect + 16 + 12 + + + + + + + IWDG + Independent watchdog + IWDG + 0x40003000 + + 0x0 + 0x400 + registers + + + + KR + KR + Key register + 0x0 + 0x20 + write-only + 0x00000000 + + + KEY + Key value + 0 + 16 + + KEY + write + + Enable + Enable access to PR, RLR and WINR registers (0x5555) + 21845 + + + Reset + Reset the watchdog value (0xAAAA) + 43690 + + + Start + Start the watchdog (0xCCCC) + 52428 + + + + + + + PR + PR + Prescaler register + 0x4 + 0x20 + read-write + 0x00000000 + + + PR + Prescaler divider + 0 + 3 + + PR + read-write + + DivideBy4 + Divider /4 + 0 + + + DivideBy8 + Divider /8 + 1 + + + DivideBy16 + Divider /16 + 2 + + + DivideBy32 + Divider /32 + 3 + + + DivideBy64 + Divider /64 + 4 + + + DivideBy128 + Divider /128 + 5 + + + DivideBy256 + Divider /256 + 6 + + + DivideBy256bis + Divider /256 + 7 + + + + + + + RLR + RLR + Reload register + 0x8 + 0x20 + read-write + 0x00000FFF + + + RL + Watchdog counter reload + value + 0 + 12 + + + 0 + 4095 + + + + + + + SR + SR + Status register + 0xC + 0x20 + read-only + 0x00000000 + + + RVU + Watchdog counter reload value + update + 1 + 1 + + + PVU + Watchdog prescaler value + update + 0 + 1 + + + + + + + OTG_FS_DEVICE + USB on the go full speed + USB_OTG_FS + 0x50000800 + + 0x0 + 0x400 + registers + + + + DCFG + DCFG + OTG_FS device configuration register + (OTG_FS_DCFG) + 0x0 + 0x20 + read-write + 0x02200000 + + + DSPD + Device speed + 0 + 2 + + + NZLSOHSK + Non-zero-length status OUT + handshake + 2 + 1 + + + DAD + Device address + 4 + 7 + + + PFIVL + Periodic frame interval + 11 + 2 + + + + + DCTL + DCTL + OTG_FS device control register + (OTG_FS_DCTL) + 0x4 + 0x20 + 0x00000000 + + + RWUSIG + Remote wakeup signaling + 0 + 1 + read-write + + + SDIS + Soft disconnect + 1 + 1 + read-write + + + GINSTS + Global IN NAK status + 2 + 1 + read-only + + + GONSTS + Global OUT NAK status + 3 + 1 + read-only + + + TCTL + Test control + 4 + 3 + read-write + + + SGINAK + Set global IN NAK + 7 + 1 + read-write + + + CGINAK + Clear global IN NAK + 8 + 1 + read-write + + + SGONAK + Set global OUT NAK + 9 + 1 + read-write + + + CGONAK + Clear global OUT NAK + 10 + 1 + read-write + + + POPRGDNE + Power-on programming done + 11 + 1 + read-write + + + + + DSTS + DSTS + OTG_FS device status register + (OTG_FS_DSTS) + 0x8 + 0x20 + read-only + 0x00000010 + + + SUSPSTS + Suspend status + 0 + 1 + + + ENUMSPD + Enumerated speed + 1 + 2 + + + EERR + Erratic error + 3 + 1 + + + FNSOF + Frame number of the received + SOF + 8 + 14 + + + + + DIEPMSK + DIEPMSK + OTG_FS device IN endpoint common interrupt + mask register (OTG_FS_DIEPMSK) + 0x10 + 0x20 + read-write + 0x00000000 + + + XFRCM + Transfer completed interrupt + mask + 0 + 1 + + + EPDM + Endpoint disabled interrupt + mask + 1 + 1 + + + TOM + Timeout condition mask (Non-isochronous + endpoints) + 3 + 1 + + + ITTXFEMSK + IN token received when TxFIFO empty + mask + 4 + 1 + + + INEPNMM + IN token received with EP mismatch + mask + 5 + 1 + + + INEPNEM + IN endpoint NAK effective + mask + 6 + 1 + + + + + DOEPMSK + DOEPMSK + OTG_FS device OUT endpoint common interrupt + mask register (OTG_FS_DOEPMSK) + 0x14 + 0x20 + read-write + 0x00000000 + + + XFRCM + Transfer completed interrupt + mask + 0 + 1 + + + EPDM + Endpoint disabled interrupt + mask + 1 + 1 + + + STUPM + SETUP phase done mask + 3 + 1 + + + OTEPDM + OUT token received when endpoint + disabled mask + 4 + 1 + + + + + DAINT + DAINT + OTG_FS device all endpoints interrupt + register (OTG_FS_DAINT) + 0x18 + 0x20 + read-only + 0x00000000 + + + IEPINT + IN endpoint interrupt bits + 0 + 16 + + + OEPINT + OUT endpoint interrupt + bits + 16 + 16 + + + + + DAINTMSK + DAINTMSK + OTG_FS all endpoints interrupt mask register + (OTG_FS_DAINTMSK) + 0x1C + 0x20 + read-write + 0x00000000 + + + IEPM + IN EP interrupt mask bits + 0 + 16 + + + OEPM + OUT EP interrupt mask bits + 16 + 16 + + + + + DVBUSDIS + DVBUSDIS + OTG_FS device VBUS discharge time + register + 0x28 + 0x20 + read-write + 0x000017D7 + + + VBUSDT + Device VBUS discharge time + 0 + 16 + + + + + DVBUSPULSE + DVBUSPULSE + OTG_FS device VBUS pulsing time + register + 0x2C + 0x20 + read-write + 0x000005B8 + + + DVBUSP + Device VBUS pulsing time + 0 + 12 + + + + + DIEPEMPMSK + DIEPEMPMSK + OTG_FS device IN endpoint FIFO empty + interrupt mask register + 0x34 + 0x20 + read-write + 0x00000000 + + + INEPTXFEM + IN EP Tx FIFO empty interrupt mask + bits + 0 + 16 + + + + + DIEP0 + Device IN endpoint 0 + 0x100 + + CTL + DIEPCTL0 + OTG_FS device control IN endpoint 0 control + register (OTG_FS_DIEPCTL0) + 0x0 + 0x20 + 0x00000000 + + + MPSIZ + Maximum packet size + 0 + 2 + read-write + + + USBAEP + USB active endpoint + 15 + 1 + read-only + + + NAKSTS + NAK status + 17 + 1 + read-only + + + EPTYP + Endpoint type + 18 + 2 + read-only + + + STALL + STALL handshake + 21 + 1 + read-write + + + TXFNUM + TxFIFO number + 22 + 4 + read-write + + + CNAK + Clear NAK + 26 + 1 + write-only + + + SNAK + Set NAK + 27 + 1 + write-only + + + EPDIS + Endpoint disable + 30 + 1 + read-only + + + EPENA + Endpoint enable + 31 + 1 + read-write + + + + + INT + DIEPINT0 + device endpoint-x interrupt + register + 0x8 + 0x20 + 0x00000080 + + + TXFE + TXFE + 7 + 1 + read-only + + + INEPNE + INEPNE + 6 + 1 + read-write + + + ITTXFE + ITTXFE + 4 + 1 + read-write + + + TOC + TOC + 3 + 1 + read-write + + + EPDISD + EPDISD + 1 + 1 + read-write + + + XFRC + XFRC + 0 + 1 + read-write + + + + + TSIZ + DIEPTSIZ0 + device endpoint-0 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + PKTCNT + Packet count + 19 + 2 + + + XFRSIZ + Transfer size + 0 + 7 + + + + + TXFSTS + DTXFSTS0 + OTG_FS device IN endpoint transmit FIFO + status register + 0x18 + 0x20 + read-only + 0x00000000 + + + INEPTFSAV + IN endpoint TxFIFO space + available + 0 + 16 + + + + + + 3 + 0x20 + 1-3 + DIEP%s + Device IN endpoint X + 0x120 + + CTL + DIEPCTL1 + OTG device endpoint-1 control + register + 0x0 + 0x20 + 0x00000000 + + + EPENA + EPENA + 31 + 1 + read-write + + + EPDIS + EPDIS + 30 + 1 + read-write + + + SODDFRM_SD1PID + SODDFRM/SD1PID + 29 + 1 + write-only + + + SD0PID_SEVNFRM + SD0PID/SEVNFRM + 28 + 1 + write-only + + + SNAK + SNAK + 27 + 1 + write-only + + + CNAK + CNAK + 26 + 1 + write-only + + + TXFNUM + TXFNUM + 22 + 4 + read-write + + + STALL + STALL handshake + 21 + 1 + read-write + + + EPTYP + EPTYP + 18 + 2 + read-write + + + NAKSTS + NAKSTS + 17 + 1 + read-only + + + EONUM_DPID + EONUM/DPID + 16 + 1 + read-only + + + USBAEP + USBAEP + 15 + 1 + read-write + + + MPSIZ + MPSIZ + 0 + 11 + read-write + + + + + INT + DIEPINT1 + device endpoint-1 interrupt + register + 0x8 + 0x20 + 0x00000080 + + + TXFE + TXFE + 7 + 1 + read-only + + + INEPNE + INEPNE + 6 + 1 + read-write + + + ITTXFE + ITTXFE + 4 + 1 + read-write + + + TOC + TOC + 3 + 1 + read-write + + + EPDISD + EPDISD + 1 + 1 + read-write + + + XFRC + XFRC + 0 + 1 + read-write + + + + + TSIZ + DIEPTSIZ1 + device endpoint-1 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + MCNT + Multi count + 29 + 2 + + + PKTCNT + Packet count + 19 + 10 + + + XFRSIZ + Transfer size + 0 + 19 + + + + + TXFSTS + DTXFSTS1 + OTG_FS device IN endpoint transmit FIFO + status register + 0x18 + 0x20 + read-only + 0x00000000 + + + INEPTFSAV + IN endpoint TxFIFO space + available + 0 + 16 + + + + + + DOEP0 + Device OUT endpoint 0 + 0x300 + + CTL + DOEPCTL0 + device endpoint-0 control + register + 0x0 + 0x20 + 0x00008000 + + + EPENA + EPENA + 31 + 1 + read-write + + + EPDIS + EPDIS + 30 + 1 + read-only + + + SNAK + SNAK + 27 + 1 + write-only + + + CNAK + CNAK + 26 + 1 + write-only + + + STALL + STALL handshake + 21 + 1 + read-write + + + SNPM + SNPM + 20 + 1 + read-write + + + EPTYP + EPTYP + 18 + 2 + read-only + + + NAKSTS + NAKSTS + 17 + 1 + read-only + + + USBAEP + USBAEP + 15 + 1 + read-only + + + MPSIZ + MPSIZ + 0 + 2 + read-only + + + + + INT + DOEPINT0 + device endpoint-0 interrupt + register + 0x8 + 0x20 + read-write + 0x00000080 + + + B2BSTUP + B2BSTUP + 6 + 1 + + + OTEPDIS + OTEPDIS + 4 + 1 + + + STUP + STUP + 3 + 1 + + + EPDISD + EPDISD + 1 + 1 + + + XFRC + XFRC + 0 + 1 + + + + + TSIZ + DOEPTSIZ0 + device OUT endpoint-0 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + STUPCNT + SETUP packet count + 29 + 2 + + + PKTCNT + Packet count + 19 + 1 + + + XFRSIZ + Transfer size + 0 + 7 + + + + + + 3 + 0x20 + 1-3 + DOEP%s + Device IN endpoint X + 0x320 + + CTL + DOEPCTL1 + device endpoint-1 control + register + 0x0 + 0x20 + 0x00000000 + + + EPENA + EPENA + 31 + 1 + read-write + + + EPDIS + EPDIS + 30 + 1 + read-write + + + SODDFRM + SODDFRM + 29 + 1 + write-only + + + SD0PID_SEVNFRM + SD0PID/SEVNFRM + 28 + 1 + write-only + + + SNAK + SNAK + 27 + 1 + write-only + + + CNAK + CNAK + 26 + 1 + write-only + + + STALL + STALL handshake + 21 + 1 + read-write + + + SNPM + SNPM + 20 + 1 + read-write + + + EPTYP + EPTYP + 18 + 2 + read-write + + + NAKSTS + NAKSTS + 17 + 1 + read-only + + + EONUM_DPID + EONUM/DPID + 16 + 1 + read-only + + + USBAEP + USBAEP + 15 + 1 + read-write + + + MPSIZ + MPSIZ + 0 + 11 + read-write + + + + + INT + DOEPINT1 + device endpoint-1 interrupt + register + 0x8 + 0x20 + read-write + 0x00000080 + + + B2BSTUP + B2BSTUP + 6 + 1 + + + OTEPDIS + OTEPDIS + 4 + 1 + + + STUP + STUP + 3 + 1 + + + EPDISD + EPDISD + 1 + 1 + + + XFRC + XFRC + 0 + 1 + + + + + TSIZ + DOEPTSIZ1 + device OUT endpoint-1 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + RXDPID_STUPCNT + Received data PID/SETUP packet + count + 29 + 2 + + + PKTCNT + Packet count + 19 + 10 + + + XFRSIZ + Transfer size + 0 + 19 + + + + + + + + OTG_FS_GLOBAL + USB on the go full speed + USB_OTG_FS + 0x50000000 + + 0x0 + 0x400 + registers + + + + GOTGCTL + GOTGCTL + OTG_FS control and status register + (OTG_FS_GOTGCTL) + 0x0 + 0x20 + 0x00000800 + + + SRQSCS + Session request success + 0 + 1 + read-only + + + SRQ + Session request + 1 + 1 + read-write + + + HNGSCS + Host negotiation success + 8 + 1 + read-only + + + HNPRQ + HNP request + 9 + 1 + read-write + + + HSHNPEN + Host set HNP enable + 10 + 1 + read-write + + + DHNPEN + Device HNP enabled + 11 + 1 + read-write + + + CIDSTS + Connector ID status + 16 + 1 + read-only + + + DBCT + Long/short debounce time + 17 + 1 + read-only + + + ASVLD + A-session valid + 18 + 1 + read-only + + + BSVLD + B-session valid + 19 + 1 + read-only + + + + + GOTGINT + GOTGINT + OTG_FS interrupt register + (OTG_FS_GOTGINT) + 0x4 + 0x20 + read-write + 0x00000000 + + + SEDET + Session end detected + 2 + 1 + + + SRSSCHG + Session request success status + change + 8 + 1 + + + HNSSCHG + Host negotiation success status + change + 9 + 1 + + + HNGDET + Host negotiation detected + 17 + 1 + + + ADTOCHG + A-device timeout change + 18 + 1 + + + DBCDNE + Debounce done + 19 + 1 + + + + + GAHBCFG + GAHBCFG + OTG_FS AHB configuration register + (OTG_FS_GAHBCFG) + 0x8 + 0x20 + read-write + 0x00000000 + + + GINT + Global interrupt mask + 0 + 1 + + + TXFELVL + TxFIFO empty level + 7 + 1 + + + PTXFELVL + Periodic TxFIFO empty + level + 8 + 1 + + + + + GUSBCFG + GUSBCFG + OTG_FS USB configuration register + (OTG_FS_GUSBCFG) + 0xC + 0x20 + 0x00000A00 + + + TOCAL + FS timeout calibration + 0 + 3 + read-write + + + PHYSEL + Full Speed serial transceiver + select + 6 + 1 + write-only + + + SRPCAP + SRP-capable + 8 + 1 + read-write + + + HNPCAP + HNP-capable + 9 + 1 + read-write + + + TRDT + USB turnaround time + 10 + 4 + read-write + + + FHMOD + Force host mode + 29 + 1 + read-write + + + FDMOD + Force device mode + 30 + 1 + read-write + + + CTXPKT + Corrupt Tx packet + 31 + 1 + read-write + + + + + GRSTCTL + GRSTCTL + OTG_FS reset register + (OTG_FS_GRSTCTL) + 0x10 + 0x20 + 0x20000000 + + + CSRST + Core soft reset + 0 + 1 + read-write + + + HSRST + HCLK soft reset + 1 + 1 + read-write + + + FCRST + Host frame counter reset + 2 + 1 + read-write + + + RXFFLSH + RxFIFO flush + 4 + 1 + read-write + + + TXFFLSH + TxFIFO flush + 5 + 1 + read-write + + + TXFNUM + TxFIFO number + 6 + 5 + read-write + + + AHBIDL + AHB master idle + 31 + 1 + read-only + + + + + GINTSTS + GINTSTS + OTG_FS core interrupt register + (OTG_FS_GINTSTS) + 0x14 + 0x20 + 0x04000020 + + + CMOD + Current mode of operation + 0 + 1 + read-only + + + MMIS + Mode mismatch interrupt + 1 + 1 + read-write + + + OTGINT + OTG interrupt + 2 + 1 + read-only + + + SOF + Start of frame + 3 + 1 + read-write + + + RXFLVL + RxFIFO non-empty + 4 + 1 + read-only + + + NPTXFE + Non-periodic TxFIFO empty + 5 + 1 + read-only + + + GINAKEFF + Global IN non-periodic NAK + effective + 6 + 1 + read-only + + + GOUTNAKEFF + Global OUT NAK effective + 7 + 1 + read-only + + + ESUSP + Early suspend + 10 + 1 + read-write + + + USBSUSP + USB suspend + 11 + 1 + read-write + + + USBRST + USB reset + 12 + 1 + read-write + + + ENUMDNE + Enumeration done + 13 + 1 + read-write + + + ISOODRP + Isochronous OUT packet dropped + interrupt + 14 + 1 + read-write + + + EOPF + End of periodic frame + interrupt + 15 + 1 + read-write + + + IEPINT + IN endpoint interrupt + 18 + 1 + read-only + + + OEPINT + OUT endpoint interrupt + 19 + 1 + read-only + + + IISOIXFR + Incomplete isochronous IN + transfer + 20 + 1 + read-write + + + IPXFR_INCOMPISOOUT + Incomplete periodic transfer(Host + mode)/Incomplete isochronous OUT transfer(Device + mode) + 21 + 1 + read-write + + + HPRTINT + Host port interrupt + 24 + 1 + read-only + + + HCINT + Host channels interrupt + 25 + 1 + read-only + + + PTXFE + Periodic TxFIFO empty + 26 + 1 + read-only + + + CIDSCHG + Connector ID status change + 28 + 1 + read-write + + + DISCINT + Disconnect detected + interrupt + 29 + 1 + read-write + + + SRQINT + Session request/new session detected + interrupt + 30 + 1 + read-write + + + WKUPINT + Resume/remote wakeup detected + interrupt + 31 + 1 + read-write + + + + + GINTMSK + GINTMSK + OTG_FS interrupt mask register + (OTG_FS_GINTMSK) + 0x18 + 0x20 + 0x00000000 + + + MMISM + Mode mismatch interrupt + mask + 1 + 1 + read-write + + + OTGINT + OTG interrupt mask + 2 + 1 + read-write + + + SOFM + Start of frame mask + 3 + 1 + read-write + + + RXFLVLM + Receive FIFO non-empty + mask + 4 + 1 + read-write + + + NPTXFEM + Non-periodic TxFIFO empty + mask + 5 + 1 + read-write + + + GINAKEFFM + Global non-periodic IN NAK effective + mask + 6 + 1 + read-write + + + GONAKEFFM + Global OUT NAK effective + mask + 7 + 1 + read-write + + + ESUSPM + Early suspend mask + 10 + 1 + read-write + + + USBSUSPM + USB suspend mask + 11 + 1 + read-write + + + USBRST + USB reset mask + 12 + 1 + read-write + + + ENUMDNEM + Enumeration done mask + 13 + 1 + read-write + + + ISOODRPM + Isochronous OUT packet dropped interrupt + mask + 14 + 1 + read-write + + + EOPFM + End of periodic frame interrupt + mask + 15 + 1 + read-write + + + EPMISM + Endpoint mismatch interrupt + mask + 17 + 1 + read-write + + + IEPINT + IN endpoints interrupt + mask + 18 + 1 + read-write + + + OEPINT + OUT endpoints interrupt + mask + 19 + 1 + read-write + + + IISOIXFRM + Incomplete isochronous IN transfer + mask + 20 + 1 + read-write + + + IPXFRM_IISOOXFRM + Incomplete periodic transfer mask(Host + mode)/Incomplete isochronous OUT transfer mask(Device + mode) + 21 + 1 + read-write + + + PRTIM + Host port interrupt mask + 24 + 1 + read-write + + + HCIM + Host channels interrupt + mask + 25 + 1 + read-write + + + PTXFEM + Periodic TxFIFO empty mask + 26 + 1 + read-write + + + CIDSCHGM + Connector ID status change + mask + 28 + 1 + read-write + + + DISCINT + Disconnect detected interrupt + mask + 29 + 1 + read-write + + + SRQIM + Session request/new session detected + interrupt mask + 30 + 1 + read-write + + + WUIM + Resume/remote wakeup detected interrupt + mask + 31 + 1 + read-write + + + + + GRXSTSR_Device + GRXSTSR_Device + OTG_FS Receive status debug read(Device + mode) + 0x1C + 0x20 + read-only + 0x00000000 + + + EPNUM + Endpoint number + 0 + 4 + + + BCNT + Byte count + 4 + 11 + + + DPID + Data PID + 15 + 2 + + + PKTSTS + Packet status + 17 + 4 + + + FRMNUM + Frame number + 21 + 4 + + + + + GRXSTSR_Host + GRXSTSR_Host + OTG status debug read (host mode) + GRXSTSR_Device + 0x1C + 0x20 + read-only + 0x00000000 + + + CHNUM + Channel number + 0 + 4 + + + BCNT + Byte count + 4 + 11 + + + DPID + Data PID + 15 + 2 + + + PKTSTS + Packet status + 17 + 4 + + + + + GRXFSIZ + GRXFSIZ + OTG_FS Receive FIFO size register + (OTG_FS_GRXFSIZ) + 0x24 + 0x20 + read-write + 0x00000200 + + + RXFD + RxFIFO depth + 0 + 16 + + + + + DIEPTXF0 + DIEPTXF0 + OTG_FS non-periodic transmit FIFO size + register (Device mode) + 0x28 + 0x20 + read-write + 0x00000200 + + + TX0FSA + Endpoint 0 transmit RAM start + address + 0 + 16 + + + TX0FD + Endpoint 0 TxFIFO depth + 16 + 16 + + + + + HNPTXFSIZ + HNPTXFSIZ + OTG_FS non-periodic transmit FIFO size + register (Host mode) + DIEPTXF0 + 0x28 + 0x20 + read-write + 0x00000200 + + + NPTXFSA + Non-periodic transmit RAM start + address + 0 + 16 + + + NPTXFD + Non-periodic TxFIFO depth + 16 + 16 + + + + + GNPTXSTS + GNPTXSTS + OTG_FS non-periodic transmit FIFO/queue + status register (OTG_FS_GNPTXSTS) + 0x2C + 0x20 + read-only + 0x00080200 + + + NPTXFSAV + Non-periodic TxFIFO space + available + 0 + 16 + + + NPTQXSAV + Non-periodic transmit request queue + space available + 16 + 8 + + + NPTXQTOP + Top of the non-periodic transmit request + queue + 24 + 7 + + + + + GCCFG + GCCFG + OTG_FS general core configuration register + (OTG_FS_GCCFG) + 0x38 + 0x20 + read-write + 0x00000000 + + + PWRDWN + Power down + 16 + 1 + + + VBUSASEN + Enable the VBUS sensing + device + 18 + 1 + + + VBUSBSEN + Enable the VBUS sensing + device + 19 + 1 + + + SOFOUTEN + SOF output enable + 20 + 1 + + + NOVBUSSENS + Vbus sensing disable option + 21 + 1 + + + + + CID + CID + core ID register + 0x3C + 0x20 + read-write + 0x00001000 + + + PRODUCT_ID + Product ID field + 0 + 32 + + + + + HPTXFSIZ + HPTXFSIZ + OTG_FS Host periodic transmit FIFO size + register (OTG_FS_HPTXFSIZ) + 0x100 + 0x20 + read-write + 0x02000600 + + + PTXSA + Host periodic TxFIFO start + address + 0 + 16 + + + PTXFSIZ + Host periodic TxFIFO depth + 16 + 16 + + + + + 3 + 0x4 + 1-3 + DIEPTXF%s + DIEPTXF1 + OTF_FS device IN endpoint transmit FIFO size register + 0x104 + 0x20 + read-write + 0x02000400 + + + INEPTXSA + IN endpoint FIFO2 transmit RAM start + address + 0 + 16 + + + INEPTXFD + IN endpoint TxFIFO depth + 16 + 16 + + + + + GRXSTSP_Device + OTG status read and pop (device mode) + 0x20 + 0x20 + read-only + 0x00000000 + + + FRMNUM + Frame number + 21 + 4 + + + PKTSTS + Packet status + 17 + 4 + + + DPID + Data PID + 15 + 2 + + + BCNT + Byte count + 4 + 11 + + + EPNUM + Endpoint number + 0 + 4 + + + + + GRXSTSP_Host + OTG status read and pop (host mode) + GRXSTSP_Device + 0x20 + 0x20 + read-only + 0x00000000 + + + PKTSTS + Packet status + 17 + 4 + + + DPID + Data PID + 15 + 2 + + + BCNT + Byte count + 4 + 11 + + + CHNUM + Channel number + 0 + 4 + + + + + + + OTG_FS_HOST + USB on the go full speed + USB_OTG_FS + 0x50000400 + + 0x0 + 0x400 + registers + + + + HCFG + HCFG + OTG_FS host configuration register + (OTG_FS_HCFG) + 0x0 + 0x20 + 0x00000000 + + + FSLSPCS + FS/LS PHY clock select + 0 + 2 + read-write + + + FSLSS + FS- and LS-only support + 2 + 1 + read-write + + + + + HFIR + HFIR + OTG_FS Host frame interval + register + 0x4 + 0x20 + read-write + 0x0000EA60 + + + FRIVL + Frame interval + 0 + 16 + + + + + HFNUM + HFNUM + OTG_FS host frame number/frame time + remaining register (OTG_FS_HFNUM) + 0x8 + 0x20 + read-only + 0x00003FFF + + + FRNUM + Frame number + 0 + 16 + + + FTREM + Frame time remaining + 16 + 16 + + + + + HPTXSTS + HPTXSTS + OTG_FS_Host periodic transmit FIFO/queue + status register (OTG_FS_HPTXSTS) + 0x10 + 0x20 + 0x00080100 + + + PTXFSAVL + Periodic transmit data FIFO space + available + 0 + 16 + read-write + + + PTXQSAV + Periodic transmit request queue space + available + 16 + 8 + read-only + + + PTXQTOP + Top of the periodic transmit request + queue + 24 + 8 + read-only + + + + + HAINT + HAINT + OTG_FS Host all channels interrupt + register + 0x14 + 0x20 + read-only + 0x00000000 + + + HAINT + Channel interrupts + 0 + 16 + + + + + HAINTMSK + HAINTMSK + OTG_FS host all channels interrupt mask + register + 0x18 + 0x20 + read-write + 0x00000000 + + + HAINTM + Channel interrupt mask + 0 + 16 + + + + + HPRT + HPRT + OTG_FS host port control and status register + (OTG_FS_HPRT) + 0x40 + 0x20 + 0x00000000 + + + PCSTS + Port connect status + 0 + 1 + read-only + + + PCDET + Port connect detected + 1 + 1 + read-write + + + PENA + Port enable + 2 + 1 + read-write + + + PENCHNG + Port enable/disable change + 3 + 1 + read-write + + + POCA + Port overcurrent active + 4 + 1 + read-only + + + POCCHNG + Port overcurrent change + 5 + 1 + read-write + + + PRES + Port resume + 6 + 1 + read-write + + + PSUSP + Port suspend + 7 + 1 + read-write + + + PRST + Port reset + 8 + 1 + read-write + + + PLSTS + Port line status + 10 + 2 + read-only + + + PPWR + Port power + 12 + 1 + read-write + + + PTCTL + Port test control + 13 + 4 + read-write + + + PSPD + Port speed + 17 + 2 + read-only + + + + + 8 + 0x20 + 0-7 + HC%s + Host channel + 0x100 + + CHAR + HCCHAR0 + OTG_FS host channel-0 characteristics + register (OTG_FS_HCCHAR0) + 0x0 + 0x20 + read-write + 0x00000000 + + + MPSIZ + Maximum packet size + 0 + 11 + + + EPNUM + Endpoint number + 11 + 4 + + + EPDIR + Endpoint direction + 15 + 1 + + + LSDEV + Low-speed device + 17 + 1 + + + EPTYP + Endpoint type + 18 + 2 + + + MCNT + Multicount + 20 + 2 + + + DAD + Device address + 22 + 7 + + + ODDFRM + Odd frame + 29 + 1 + + + CHDIS + Channel disable + 30 + 1 + + + CHENA + Channel enable + 31 + 1 + + + + + INT + HCINT0 + OTG_FS host channel-0 interrupt register + (OTG_FS_HCINT0) + 0x8 + 0x20 + read-write + 0x00000000 + + + XFRC + Transfer completed + 0 + 1 + + + CHH + Channel halted + 1 + 1 + + + STALL + STALL response received + interrupt + 3 + 1 + + + NAK + NAK response received + interrupt + 4 + 1 + + + ACK + ACK response received/transmitted + interrupt + 5 + 1 + + + TXERR + Transaction error + 7 + 1 + + + BBERR + Babble error + 8 + 1 + + + FRMOR + Frame overrun + 9 + 1 + + + DTERR + Data toggle error + 10 + 1 + + + + + INTMSK + HCINTMSK0 + OTG_FS host channel-0 mask register + (OTG_FS_HCINTMSK0) + 0xC + 0x20 + read-write + 0x00000000 + + + XFRCM + Transfer completed mask + 0 + 1 + + + CHHM + Channel halted mask + 1 + 1 + + + STALLM + STALL response received interrupt + mask + 3 + 1 + + + NAKM + NAK response received interrupt + mask + 4 + 1 + + + ACKM + ACK response received/transmitted + interrupt mask + 5 + 1 + + + NYET + response received interrupt + mask + 6 + 1 + + + TXERRM + Transaction error mask + 7 + 1 + + + BBERRM + Babble error mask + 8 + 1 + + + FRMORM + Frame overrun mask + 9 + 1 + + + DTERRM + Data toggle error mask + 10 + 1 + + + + + TSIZ + HCTSIZ0 + OTG_FS host channel-0 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + XFRSIZ + Transfer size + 0 + 19 + + + PKTCNT + Packet count + 19 + 10 + + + DPID + Data PID + 29 + 2 + + + + + + + + OTG_FS_PWRCLK + USB on the go full speed + USB_OTG_FS + 0x50000E00 + + 0x0 + 0x400 + registers + + + + PCGCCTL + PCGCCTL + OTG_FS power and clock gating control + register + 0x0 + 0x20 + read-write + 0x00000000 + + + STPPCLK + Stop PHY clock + 0 + 1 + + + GATEHCLK + Gate HCLK + 1 + 1 + + + PHYSUSP + PHY Suspended + 4 + 1 + + + + + + + PWR + Power control + PWR + 0x40007000 + + 0x0 + 0x400 + registers + + + + CR + CR + power control register + 0x0 + 0x20 + read-write + 0x00000000 + + + VOS + Regulator voltage scaling output + selection + 14 + 2 + + + ADCDC1 + ADCDC1 + 13 + 1 + + + FPDS + Flash power down in Stop + mode + 9 + 1 + + + DBP + Disable backup domain write + protection + 8 + 1 + + + PLS + PVD level selection + 5 + 3 + + + PVDE + Power voltage detector + enable + 4 + 1 + + + CSBF + Clear standby flag + 3 + 1 + + + CWUF + Clear wakeup flag + 2 + 1 + + + PDDS + Power down deepsleep + 1 + 1 + + + LPDS + Low-power deep sleep + 0 + 1 + + + + + CSR + CSR + power control/status register + 0x4 + 0x20 + 0x00000000 + + + WUF + Wakeup flag + 0 + 1 + read-only + + + SBF + Standby flag + 1 + 1 + read-only + + + PVDO + PVD output + 2 + 1 + read-only + + + BRR + Backup regulator ready + 3 + 1 + read-only + + + EWUP + Enable WKUP pin + 8 + 1 + read-write + + + BRE + Backup regulator enable + 9 + 1 + read-write + + + VOSRDY + Regulator voltage scaling output + selection ready bit + 14 + 1 + read-write + + + + + + + RCC + Reset and clock control + RCC + 0x40023800 + + 0x0 + 0x400 + registers + + + I2C1_EV + I2C1 event interrupt + 31 + + + I2C1_ER + I2C1 error interrupt + 32 + + + + CR + CR + clock control register + 0x0 + 0x20 + 0x00000083 + + + PLLI2SRDY + PLLI2S clock ready flag + 27 + 1 + read-only + + + + PLLI2SON + PLLI2S enable + 26 + 1 + read-write + + + + PLLRDY + Main PLL (PLL) clock ready + flag + 25 + 1 + read-only + + + + PLLON + Main PLL (PLL) enable + 24 + 1 + read-write + + + + CSSON + Clock security system + enable + 19 + 1 + read-write + + CSSON + read-write + + Off + Clock security system disabled (clock detector OFF) + 0 + + + On + Clock security system enable (clock detector ON if the HSE is ready, OFF if not) + 1 + + + + + HSEBYP + HSE clock bypass + 18 + 1 + read-write + + HSEBYP + read-write + + NotBypassed + HSE crystal oscillator not bypassed + 0 + + + Bypassed + HSE crystal oscillator bypassed with external clock + 1 + + + + + HSERDY + HSE clock ready flag + 17 + 1 + read-only + + + + HSEON + HSE clock enable + 16 + 1 + read-write + + + + HSICAL + Internal high-speed clock + calibration + 8 + 8 + read-only + + + 0 + 255 + + + + + HSITRIM + Internal high-speed clock + trimming + 3 + 5 + read-write + + + 0 + 31 + + + + + HSIRDY + Internal high-speed clock ready + flag + 1 + 1 + read-only + + HSIRDYR + read + + NotReady + Clock not ready + 0 + + + Ready + Clock ready + 1 + + + + + HSION + Internal high-speed clock + enable + 0 + 1 + read-write + + HSION + read-write + + Off + Clock Off + 0 + + + On + Clock On + 1 + + + + + + + PLLCFGR + PLLCFGR + PLL configuration register + 0x4 + 0x20 + read-write + 0x24003010 + + + PLLSRC + Main PLL(PLL) and audio PLL (PLLI2S) + entry clock source + 22 + 1 + + PLLSRC + read-write + + HSI + HSI clock selected as PLL and PLLI2S clock entry + 0 + + + HSE + HSE oscillator clock selected as PLL and PLLI2S clock entry + 1 + + + + + PLLM + Division factor for the main PLL (PLL) + and audio PLL (PLLI2S) input clock + 0 + 6 + + + 2 + 63 + + + + + PLLN + Main PLL (PLL) multiplication factor for + VCO + 6 + 9 + + + 50 + 432 + + + + + PLLP + Main PLL (PLL) division factor for main + system clock + 16 + 2 + + PLLP + read-write + + Div2 + PLLP=2 + 0 + + + Div4 + PLLP=4 + 1 + + + Div6 + PLLP=6 + 2 + + + Div8 + PLLP=8 + 3 + + + + + PLLQ + Main PLL (PLL) division factor for USB + OTG FS, SDIO and random number generator + clocks + 24 + 4 + + + 2 + 15 + + + + + + + CFGR + CFGR + clock configuration register + 0x8 + 0x20 + 0x00000000 + + + MCO2 + Microcontroller clock output + 2 + 30 + 2 + read-write + + MCO2 + read-write + + SYSCLK + System clock (SYSCLK) selected + 0 + + + PLLI2S + PLLI2S clock selected + 1 + + + HSE + HSE oscillator clock selected + 2 + + + PLL + PLL clock selected + 3 + + + + + MCO2PRE + MCO2 prescaler + 27 + 3 + read-write + + + + MCO1PRE + MCO1 prescaler + 24 + 3 + read-write + + MCO1PRE + read-write + + Div1 + No division + 0 + + + Div2 + Division by 2 + 4 + + + Div3 + Division by 3 + 5 + + + Div4 + Division by 4 + 6 + + + Div5 + Division by 5 + 7 + + + + + I2SSRC + I2S clock selection + 23 + 1 + read-write + + I2SSRC + read-write + + PLLI2S + PLLI2S clock used as I2S clock source + 0 + + + CKIN + External clock mapped on the I2S_CKIN pin used as I2S clock source + 1 + + + + + MCO1 + Microcontroller clock output + 1 + 21 + 2 + read-write + + MCO1 + read-write + + HSI + HSI clock selected + 0 + + + LSE + LSE oscillator selected + 1 + + + HSE + HSE oscillator clock selected + 2 + + + PLL + PLL clock selected + 3 + + + + + RTCPRE + HSE division factor for RTC + clock + 16 + 5 + read-write + + + 0 + 31 + + + + + PPRE2 + APB high-speed prescaler + (APB2) + 13 + 3 + read-write + + + + PPRE1 + APB Low speed prescaler + (APB1) + 10 + 3 + read-write + + PPRE1 + read-write + + Div1 + HCLK not divided + 0 + + + Div2 + HCLK divided by 2 + 4 + + + Div4 + HCLK divided by 4 + 5 + + + Div8 + HCLK divided by 8 + 6 + + + Div16 + HCLK divided by 16 + 7 + + + + + HPRE + AHB prescaler + 4 + 4 + read-write + + HPRE + read-write + + Div1 + SYSCLK not divided + 0 + + + Div2 + SYSCLK divided by 2 + 8 + + + Div4 + SYSCLK divided by 4 + 9 + + + Div8 + SYSCLK divided by 8 + 10 + + + Div16 + SYSCLK divided by 16 + 11 + + + Div64 + SYSCLK divided by 64 + 12 + + + Div128 + SYSCLK divided by 128 + 13 + + + Div256 + SYSCLK divided by 256 + 14 + + + Div512 + SYSCLK divided by 512 + 15 + + + + + SW + System clock switch + 0 + 2 + + SW + read-write + + HSI + HSI selected as system clock + 0 + + + HSE + HSE selected as system clock + 1 + + + PLL + PLL selected as system clock + 2 + + + + + SWS + System clock switch status + 2 + 2 + + SWSR + read + + HSI + HSI oscillator used as system clock + 0 + + + HSE + HSE oscillator used as system clock + 1 + + + PLL + PLL used as system clock + 2 + + + + + + + CIR + CIR + clock interrupt register + 0xC + 0x20 + 0x00000000 + + + CSSC + Clock security system interrupt + clear + 23 + 1 + write-only + + CSSCW + write + + Clear + Clear CSSF flag + 1 + + + + + PLLI2SRDYC + PLLI2S ready interrupt + clear + 21 + 1 + write-only + + + + PLLRDYC + Main PLL(PLL) ready interrupt + clear + 20 + 1 + write-only + + + + HSERDYC + HSE ready interrupt clear + 19 + 1 + write-only + + + + HSIRDYC + HSI ready interrupt clear + 18 + 1 + write-only + + + + LSERDYC + LSE ready interrupt clear + 17 + 1 + write-only + + + + LSIRDYC + LSI ready interrupt clear + 16 + 1 + write-only + + LSIRDYCW + write + + Clear + Clear interrupt flag + 1 + + + + + PLLI2SRDYIE + PLLI2S ready interrupt + enable + 13 + 1 + read-write + + + + PLLRDYIE + Main PLL (PLL) ready interrupt + enable + 12 + 1 + read-write + + + + HSERDYIE + HSE ready interrupt enable + 11 + 1 + read-write + + + + HSIRDYIE + HSI ready interrupt enable + 10 + 1 + read-write + + + + LSERDYIE + LSE ready interrupt enable + 9 + 1 + read-write + + + + LSIRDYIE + LSI ready interrupt enable + 8 + 1 + read-write + + LSIRDYIE + read-write + + Disabled + Interrupt disabled + 0 + + + Enabled + Interrupt enabled + 1 + + + + + CSSF + Clock security system interrupt + flag + 7 + 1 + read-only + + CSSFR + read + + NotInterrupted + No clock security interrupt caused by HSE clock failure + 0 + + + Interrupted + Clock security interrupt caused by HSE clock failure + 1 + + + + + PLLI2SRDYF + PLLI2S ready interrupt + flag + 5 + 1 + read-only + + + + PLLRDYF + Main PLL (PLL) ready interrupt + flag + 4 + 1 + read-only + + + + HSERDYF + HSE ready interrupt flag + 3 + 1 + read-only + + + + HSIRDYF + HSI ready interrupt flag + 2 + 1 + read-only + + + + LSERDYF + LSE ready interrupt flag + 1 + 1 + read-only + + + + LSIRDYF + LSI ready interrupt flag + 0 + 1 + read-only + + LSIRDYFR + read + + NotInterrupted + No clock ready interrupt + 0 + + + Interrupted + Clock ready interrupt + 1 + + + + + + + AHB1RSTR + AHB1RSTR + AHB1 peripheral reset register + 0x10 + 0x20 + read-write + 0x00000000 + + + DMA2RST + DMA2 reset + 22 + 1 + + + + DMA1RST + DMA2 reset + 21 + 1 + + + + CRCRST + CRC reset + 12 + 1 + + + + GPIOHRST + IO port H reset + 7 + 1 + + + + GPIOERST + IO port E reset + 4 + 1 + + + + GPIODRST + IO port D reset + 3 + 1 + + + + GPIOCRST + IO port C reset + 2 + 1 + + + + GPIOBRST + IO port B reset + 1 + 1 + + + + GPIOARST + IO port A reset + 0 + 1 + + GPIOARST + read-write + + Reset + Reset the selected module + 1 + + + + + + + AHB2RSTR + AHB2RSTR + AHB2 peripheral reset register + 0x14 + 0x20 + read-write + 0x00000000 + + + OTGFSRST + USB OTG FS module reset + 7 + 1 + + OTGFSRST + read-write + + Reset + Reset the selected module + 1 + + + + + + + APB1RSTR + APB1RSTR + APB1 peripheral reset register + 0x20 + 0x20 + read-write + 0x00000000 + + + PWRRST + Power interface reset + 28 + 1 + + + + I2C3RST + I2C3 reset + 23 + 1 + + + + I2C2RST + I2C 2 reset + 22 + 1 + + + + I2C1RST + I2C 1 reset + 21 + 1 + + + + USART2RST + USART 2 reset + 17 + 1 + + + + SPI3RST + SPI 3 reset + 15 + 1 + + + + SPI2RST + SPI 2 reset + 14 + 1 + + + + WWDGRST + Window watchdog reset + 11 + 1 + + + + TIM5RST + TIM5 reset + 3 + 1 + + + + TIM4RST + TIM4 reset + 2 + 1 + + + + TIM3RST + TIM3 reset + 1 + 1 + + + + TIM2RST + TIM2 reset + 0 + 1 + + TIM2RST + read-write + + Reset + Reset the selected module + 1 + + + + + + + APB2RSTR + APB2RSTR + APB2 peripheral reset register + 0x24 + 0x20 + read-write + 0x00000000 + + + TIM11RST + TIM11 reset + 18 + 1 + + + + TIM10RST + TIM10 reset + 17 + 1 + + + + TIM9RST + TIM9 reset + 16 + 1 + + + + SYSCFGRST + System configuration controller + reset + 14 + 1 + + + + SPI1RST + SPI 1 reset + 12 + 1 + + + + SDIORST + SDIO reset + 11 + 1 + + + + ADCRST + ADC interface reset (common to all + ADCs) + 8 + 1 + + + + USART6RST + USART6 reset + 5 + 1 + + + + USART1RST + USART1 reset + 4 + 1 + + + + TIM1RST + TIM1 reset + 0 + 1 + + TIM1RST + read-write + + Reset + Reset the selected module + 1 + + + + + SPI4RST + SPI4 reset + 13 + 1 + + + + + + AHB1ENR + AHB1ENR + AHB1 peripheral clock register + 0x30 + 0x20 + read-write + 0x00100000 + + + DMA2EN + DMA2 clock enable + 22 + 1 + + + + DMA1EN + DMA1 clock enable + 21 + 1 + + + + CRCEN + CRC clock enable + 12 + 1 + + + + GPIOHEN + IO port H clock enable + 7 + 1 + + + + GPIOEEN + IO port E clock enable + 4 + 1 + + + + GPIODEN + IO port D clock enable + 3 + 1 + + + + GPIOCEN + IO port C clock enable + 2 + 1 + + + + GPIOBEN + IO port B clock enable + 1 + 1 + + + + GPIOAEN + IO port A clock enable + 0 + 1 + + GPIOAEN + read-write + + Disabled + The selected clock is disabled + 0 + + + Enabled + The selected clock is enabled + 1 + + + + + + + AHB2ENR + AHB2ENR + AHB2 peripheral clock enable + register + 0x34 + 0x20 + read-write + 0x00000000 + + + OTGFSEN + USB OTG FS clock enable + 7 + 1 + + OTGFSEN + read-write + + Disabled + The selected clock is disabled + 0 + + + Enabled + The selected clock is enabled + 1 + + + + + + + APB1ENR + APB1ENR + APB1 peripheral clock enable + register + 0x40 + 0x20 + read-write + 0x00000000 + + + PWREN + Power interface clock + enable + 28 + 1 + + + + I2C3EN + I2C3 clock enable + 23 + 1 + + + + I2C2EN + I2C2 clock enable + 22 + 1 + + + + I2C1EN + I2C1 clock enable + 21 + 1 + + + + USART2EN + USART 2 clock enable + 17 + 1 + + + + SPI3EN + SPI3 clock enable + 15 + 1 + + + + SPI2EN + SPI2 clock enable + 14 + 1 + + + + WWDGEN + Window watchdog clock + enable + 11 + 1 + + + + TIM5EN + TIM5 clock enable + 3 + 1 + + + + TIM4EN + TIM4 clock enable + 2 + 1 + + + + TIM3EN + TIM3 clock enable + 1 + 1 + + + + TIM2EN + TIM2 clock enable + 0 + 1 + + TIM2EN + read-write + + Disabled + The selected clock is disabled + 0 + + + Enabled + The selected clock is enabled + 1 + + + + + + + APB2ENR + APB2ENR + APB2 peripheral clock enable + register + 0x44 + 0x20 + read-write + 0x00000000 + + + TIM11EN + TIM11 clock enable + 18 + 1 + + + + TIM10EN + TIM10 clock enable + 17 + 1 + + + + TIM9EN + TIM9 clock enable + 16 + 1 + + + + SYSCFGEN + System configuration controller clock + enable + 14 + 1 + + + + SPI1EN + SPI1 clock enable + 12 + 1 + + + + SDIOEN + SDIO clock enable + 11 + 1 + + + + ADC1EN + ADC1 clock enable + 8 + 1 + + + + USART6EN + USART6 clock enable + 5 + 1 + + + + USART1EN + USART1 clock enable + 4 + 1 + + + + TIM1EN + TIM1 clock enable + 0 + 1 + + TIM1EN + read-write + + Disabled + The selected clock is disabled + 0 + + + Enabled + The selected clock is enabled + 1 + + + + + SPI4EN + SPI4 clock enable + 13 + 1 + + + + + + AHB1LPENR + AHB1LPENR + AHB1 peripheral clock enable in low power + mode register + 0x50 + 0x20 + read-write + 0x7E6791FF + + + DMA2LPEN + DMA2 clock enable during Sleep + mode + 22 + 1 + + + + DMA1LPEN + DMA1 clock enable during Sleep + mode + 21 + 1 + + + + SRAM1LPEN + SRAM 1interface clock enable during + Sleep mode + 16 + 1 + + + + FLITFLPEN + Flash interface clock enable during + Sleep mode + 15 + 1 + + + + CRCLPEN + CRC clock enable during Sleep + mode + 12 + 1 + + + + GPIOHLPEN + IO port H clock enable during Sleep + mode + 7 + 1 + + + + GPIOELPEN + IO port E clock enable during Sleep + mode + 4 + 1 + + + + GPIODLPEN + IO port D clock enable during Sleep + mode + 3 + 1 + + + + GPIOCLPEN + IO port C clock enable during Sleep + mode + 2 + 1 + + + + GPIOBLPEN + IO port B clock enable during Sleep + mode + 1 + 1 + + + + GPIOALPEN + IO port A clock enable during sleep + mode + 0 + 1 + + GPIOALPEN + read-write + + DisabledInSleep + Selected module is disabled during Sleep mode + 0 + + + EnabledInSleep + Selected module is enabled during Sleep mode + 1 + + + + + + + AHB2LPENR + AHB2LPENR + AHB2 peripheral clock enable in low power + mode register + 0x54 + 0x20 + read-write + 0x000000F1 + + + OTGFSLPEN + USB OTG FS clock enable during Sleep + mode + 7 + 1 + + OTGFSLPEN + read-write + + DisabledInSleep + Selected module is disabled during Sleep mode + 0 + + + EnabledInSleep + Selected module is enabled during Sleep mode + 1 + + + + + + + APB1LPENR + APB1LPENR + APB1 peripheral clock enable in low power + mode register + 0x60 + 0x20 + read-write + 0x36FEC9FF + + + PWRLPEN + Power interface clock enable during + Sleep mode + 28 + 1 + + + + I2C3LPEN + I2C3 clock enable during Sleep + mode + 23 + 1 + + + + I2C2LPEN + I2C2 clock enable during Sleep + mode + 22 + 1 + + + + I2C1LPEN + I2C1 clock enable during Sleep + mode + 21 + 1 + + + + USART2LPEN + USART2 clock enable during Sleep + mode + 17 + 1 + + + + SPI3LPEN + SPI3 clock enable during Sleep + mode + 15 + 1 + + + + SPI2LPEN + SPI2 clock enable during Sleep + mode + 14 + 1 + + + + WWDGLPEN + Window watchdog clock enable during + Sleep mode + 11 + 1 + + + + TIM5LPEN + TIM5 clock enable during Sleep + mode + 3 + 1 + + + + TIM4LPEN + TIM4 clock enable during Sleep + mode + 2 + 1 + + + + TIM3LPEN + TIM3 clock enable during Sleep + mode + 1 + 1 + + + + TIM2LPEN + TIM2 clock enable during Sleep + mode + 0 + 1 + + TIM2LPEN + read-write + + DisabledInSleep + Selected module is disabled during Sleep mode + 0 + + + EnabledInSleep + Selected module is enabled during Sleep mode + 1 + + + + + + + APB2LPENR + APB2LPENR + APB2 peripheral clock enabled in low power + mode register + 0x64 + 0x20 + read-write + 0x00075F33 + + + TIM11LPEN + TIM11 clock enable during Sleep + mode + 18 + 1 + + + + TIM10LPEN + TIM10 clock enable during Sleep + mode + 17 + 1 + + + + TIM9LPEN + TIM9 clock enable during sleep + mode + 16 + 1 + + + + SYSCFGLPEN + System configuration controller clock + enable during Sleep mode + 14 + 1 + + + + SPI1LPEN + SPI 1 clock enable during Sleep + mode + 12 + 1 + + + + SDIOLPEN + SDIO clock enable during Sleep + mode + 11 + 1 + + + + ADC1LPEN + ADC1 clock enable during Sleep + mode + 8 + 1 + + + + USART6LPEN + USART6 clock enable during Sleep + mode + 5 + 1 + + + + USART1LPEN + USART1 clock enable during Sleep + mode + 4 + 1 + + + + TIM1LPEN + TIM1 clock enable during Sleep + mode + 0 + 1 + + TIM1LPEN + read-write + + DisabledInSleep + Selected module is disabled during Sleep mode + 0 + + + EnabledInSleep + Selected module is enabled during Sleep mode + 1 + + + + + SPI4LPEN + SPI4 clock enable during Sleep mode + 13 + 1 + + + + + + BDCR + BDCR + Backup domain control register + 0x70 + 0x20 + 0x00000000 + + + BDRST + Backup domain software + reset + 16 + 1 + read-write + + BDRST + read-write + + Disabled + Reset not activated + 0 + + + Enabled + Reset the entire RTC domain + 1 + + + + + RTCEN + RTC clock enable + 15 + 1 + read-write + + RTCEN + read-write + + Disabled + RTC clock disabled + 0 + + + Enabled + RTC clock enabled + 1 + + + + + LSEBYP + External low-speed oscillator + bypass + 2 + 1 + read-write + + LSEBYP + read-write + + NotBypassed + LSE crystal oscillator not bypassed + 0 + + + Bypassed + LSE crystal oscillator bypassed with external clock + 1 + + + + + LSERDY + External low-speed oscillator + ready + 1 + 1 + read-only + + LSERDYR + read + + NotReady + LSE oscillator not ready + 0 + + + Ready + LSE oscillator ready + 1 + + + + + LSEON + External low-speed oscillator + enable + 0 + 1 + read-write + + LSEON + read-write + + Off + LSE oscillator Off + 0 + + + On + LSE oscillator On + 1 + + + + + RTCSEL + RTC clock source selection + 8 + 2 + + RTCSEL + read-write + + NoClock + No clock + 0 + + + LSE + LSE oscillator clock used as RTC clock + 1 + + + LSI + LSI oscillator clock used as RTC clock + 2 + + + HSE + HSE oscillator clock divided by a prescaler used as RTC clock + 3 + + + + + + + CSR + CSR + clock control & status + register + 0x74 + 0x20 + 0x0E000000 + + + LPWRRSTF + Low-power reset flag + 31 + 1 + read-write + + + + WWDGRSTF + Window watchdog reset flag + 30 + 1 + read-write + + + + WDGRSTF + Independent watchdog reset + flag + 29 + 1 + read-write + + + + SFTRSTF + Software reset flag + 28 + 1 + read-write + + + + PORRSTF + POR/PDR reset flag + 27 + 1 + read-write + + + + PADRSTF + PIN reset flag + 26 + 1 + read-write + + + + BORRSTF + BOR reset flag + 25 + 1 + read-write + + BORRSTFR + read + + NoReset + No reset has occured + 0 + + + Reset + A reset has occured + 1 + + + + + RMVF + Remove reset flag + 24 + 1 + read-write + + RMVFW + write + + Clear + Clears the reset flag + 1 + + + + + LSIRDY + Internal low-speed oscillator + ready + 1 + 1 + read-only + + LSIRDYR + read + + NotReady + LSI oscillator not ready + 0 + + + Ready + LSI oscillator ready + 1 + + + + + LSION + Internal low-speed oscillator + enable + 0 + 1 + read-write + + LSION + read-write + + Off + LSI oscillator Off + 0 + + + On + LSI oscillator On + 1 + + + + + + + SSCGR + SSCGR + spread spectrum clock generation + register + 0x80 + 0x20 + read-write + 0x00000000 + + + SSCGEN + Spread spectrum modulation + enable + 31 + 1 + + SSCGEN + read-write + + Disabled + Spread spectrum modulation disabled + 0 + + + Enabled + Spread spectrum modulation enabled + 1 + + + + + SPREADSEL + Spread Select + 30 + 1 + + SPREADSEL + read-write + + Center + Center spread + 0 + + + Down + Down spread + 1 + + + + + INCSTEP + Incrementation step + 13 + 15 + + + 0 + 32767 + + + + + MODPER + Modulation period + 0 + 13 + + + 0 + 8191 + + + + + + + PLLI2SCFGR + PLLI2SCFGR + PLLI2S configuration register + 0x84 + 0x20 + read-write + 0x20003000 + + + PLLI2SR + PLLI2S division factor for I2S + clocks + 28 + 3 + + + 2 + 7 + + + + + PLLI2SN + PLLI2S multiplication factor for + VCO + 6 + 9 + + + 50 + 432 + + + + + + + DCKCFGR + RCC Dedicated Clock Configuration Register + 0x8C + 0x20 + read-write + 0x00000000 + + + TIMPRE + Timers clocks prescalers selection + 24 + 1 + + TIMPRE + read-write + + Mul1Or2 + If the APB prescaler is configured 1, TIMxCLK = PCLKx. Otherwise, TIMxCLK = 2xPCLKx + 0 + + + Mul1Or4 + If the APB prescaler is configured 1, 2 or 4, TIMxCLK = HCLK. Otherwise, TIMxCLK = 4xPCLKx + 1 + + + + + + + + + RTC + Real-time clock + RTC + 0x40002800 + + 0x0 + 0x400 + registers + + + I2C2_EV + I2C2 event interrupt + 33 + + + I2C2_ER + I2C2 error interrupt + 34 + + + + TR + TR + time register + 0x0 + 0x20 + read-write + 0x00000000 + + + PM + AM/PM notation + 22 + 1 + + PM + read-write + + AM + AM or 24-hour format + 0 + + + PM + PM + 1 + + + + + HT + Hour tens in BCD format + 20 + 2 + + + 0 + 3 + + + + + HU + Hour units in BCD format + 16 + 4 + + + 0 + 15 + + + + + MNT + Minute tens in BCD format + 12 + 3 + + + 0 + 7 + + + + + MNU + Minute units in BCD format + 8 + 4 + + + 0 + 15 + + + + + ST + Second tens in BCD format + 4 + 3 + + + 0 + 7 + + + + + SU + Second units in BCD format + 0 + 4 + + + 0 + 15 + + + + + + + DR + DR + date register + 0x4 + 0x20 + read-write + 0x00002101 + + + YT + Year tens in BCD format + 20 + 4 + + + 0 + 15 + + + + + YU + Year units in BCD format + 16 + 4 + + + 0 + 15 + + + + + WDU + Week day units + 13 + 3 + + + 1 + 7 + + + + + MT + Month tens in BCD format + 12 + 1 + + MT + read-write + + Zero + Month tens is 0 + 0 + + + One + Month tens is 1 + 1 + + + + + MU + Month units in BCD format + 8 + 4 + + + 0 + 15 + + + + + DT + Date tens in BCD format + 4 + 2 + + + 0 + 3 + + + + + DU + Date units in BCD format + 0 + 4 + + + 0 + 15 + + + + + + + CR + CR + control register + 0x8 + 0x20 + read-write + 0x00000000 + + + COE + Calibration output enable + 23 + 1 + + COE + read-write + + Disabled + Calibration output disabled + 0 + + + Enabled + Calibration output enabled + 1 + + + + + OSEL + Output selection + 21 + 2 + + OSEL + read-write + + Disabled + Output disabled + 0 + + + AlarmA + Alarm A output enabled + 1 + + + AlarmB + Alarm B output enabled + 2 + + + Wakeup + Wakeup output enabled + 3 + + + + + POL + Output polarity + 20 + 1 + + POL + read-write + + High + The pin is high when ALRAF/ALRBF/WUTF is asserted (depending on OSEL[1:0]) + 0 + + + Low + The pin is low when ALRAF/ALRBF/WUTF is asserted (depending on OSEL[1:0]) + 1 + + + + + COSEL + Calibration Output + selection + 19 + 1 + + COSEL + read-write + + CalFreq_512Hz + Calibration output is 512 Hz (with default prescaler setting) + 0 + + + CalFreq_1Hz + Calibration output is 1 Hz (with default prescaler setting) + 1 + + + + + BKP + Backup + 18 + 1 + + BKP + read-write + + DST_Not_Changed + Daylight Saving Time change has not been performed + 0 + + + DST_Changed + Daylight Saving Time change has been performed + 1 + + + + + SUB1H + Subtract 1 hour (winter time + change) + 17 + 1 + + SUB1HW + write + + Sub1 + Subtracts 1 hour to the current time. This can be used for winter time change outside initialization mode + 1 + + + + + ADD1H + Add 1 hour (summer time + change) + 16 + 1 + + ADD1HW + write + + Add1 + Adds 1 hour to the current time. This can be used for summer time change outside initialization mode + 1 + + + + + TSIE + Time-stamp interrupt + enable + 15 + 1 + + TSIE + read-write + + Disabled + Time-stamp Interrupt disabled + 0 + + + Enabled + Time-stamp Interrupt enabled + 1 + + + + + WUTIE + Wakeup timer interrupt + enable + 14 + 1 + + WUTIE + read-write + + Disabled + Wakeup timer interrupt disabled + 0 + + + Enabled + Wakeup timer interrupt enabled + 1 + + + + + ALRBIE + Alarm B interrupt enable + 13 + 1 + + ALRBIE + read-write + + Disabled + Alarm B Interrupt disabled + 0 + + + Enabled + Alarm B Interrupt enabled + 1 + + + + + ALRAIE + Alarm A interrupt enable + 12 + 1 + + ALRAIE + read-write + + Disabled + Alarm A interrupt disabled + 0 + + + Enabled + Alarm A interrupt enabled + 1 + + + + + TSE + Time stamp enable + 11 + 1 + + TSE + read-write + + Disabled + Timestamp disabled + 0 + + + Enabled + Timestamp enabled + 1 + + + + + WUTE + Wakeup timer enable + 10 + 1 + + WUTE + read-write + + Disabled + Wakeup timer disabled + 0 + + + Enabled + Wakeup timer enabled + 1 + + + + + ALRBE + Alarm B enable + 9 + 1 + + ALRBE + read-write + + Disabled + Alarm B disabled + 0 + + + Enabled + Alarm B enabled + 1 + + + + + ALRAE + Alarm A enable + 8 + 1 + + ALRAE + read-write + + Disabled + Alarm A disabled + 0 + + + Enabled + Alarm A enabled + 1 + + + + + DCE + Coarse digital calibration + enable + 7 + 1 + + + FMT + Hour format + 6 + 1 + + FMT + read-write + + Twenty_Four_Hour + 24 hour/day format + 0 + + + AM_PM + AM/PM hour format + 1 + + + + + BYPSHAD + Bypass the shadow + registers + 5 + 1 + + BYPSHAD + read-write + + ShadowReg + Calendar values (when reading from RTC_SSR, RTC_TR, and RTC_DR) are taken from the shadow registers, which are updated once every two RTCCLK cycles + 0 + + + BypassShadowReg + Calendar values (when reading from RTC_SSR, RTC_TR, and RTC_DR) are taken directly from the calendar counters + 1 + + + + + REFCKON + Reference clock detection enable (50 or + 60 Hz) + 4 + 1 + + REFCKON + read-write + + Disabled + RTC_REFIN detection disabled + 0 + + + Enabled + RTC_REFIN detection enabled + 1 + + + + + TSEDGE + Time-stamp event active + edge + 3 + 1 + + TSEDGE + read-write + + RisingEdge + RTC_TS input rising edge generates a time-stamp event + 0 + + + FallingEdge + RTC_TS input falling edge generates a time-stamp event + 1 + + + + + WUCKSEL + Wakeup clock selection + 0 + 3 + + WUCKSEL + read-write + + Div16 + RTC/16 clock is selected + 0 + + + Div8 + RTC/8 clock is selected + 1 + + + Div4 + RTC/4 clock is selected + 2 + + + Div2 + RTC/2 clock is selected + 3 + + + ClockSpare + ck_spre (usually 1 Hz) clock is selected + 4 + + + ClockSpareWithOffset + ck_spre (usually 1 Hz) clock is selected and 2^16 is added to the WUT counter value + 6 + + + + + + + ISR + ISR + initialization and status + register + 0xC + 0x20 + 0x00000007 + + + ALRAWF + Alarm A write flag + 0 + 1 + read-only + + ALRAWFR + read + + UpdateNotAllowed + Alarm update not allowed + 0 + + + UpdateAllowed + Alarm update allowed + 1 + + + + + ALRBWF + Alarm B write flag + 1 + 1 + read-only + + + + WUTWF + Wakeup timer write flag + 2 + 1 + read-only + + WUTWFR + read + + UpdateNotAllowed + Wakeup timer configuration update not allowed + 0 + + + UpdateAllowed + Wakeup timer configuration update allowed + 1 + + + + + SHPF + Shift operation pending + 3 + 1 + read-write + + SHPFR + read + + NoShiftPending + No shift operation is pending + 0 + + + ShiftPending + A shift operation is pending + 1 + + + + + INITS + Initialization status flag + 4 + 1 + read-only + + INITSR + read + + NotInitalized + Calendar has not been initialized + 0 + + + Initalized + Calendar has been initialized + 1 + + + + + RSF + Registers synchronization + flag + 5 + 1 + read-write + zeroToClear + + RSFR + read + + NotSynced + Calendar shadow registers not yet synchronized + 0 + + + Synced + Calendar shadow registers synchronized + 1 + + + + RSFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + INITF + Initialization flag + 6 + 1 + read-only + + INITFR + read + + NotAllowed + Calendar registers update is not allowed + 0 + + + Allowed + Calendar registers update is allowed + 1 + + + + + INIT + Initialization mode + 7 + 1 + read-write + + INIT + read-write + + FreeRunningMode + Free running mode + 0 + + + InitMode + Initialization mode used to program time and date register (RTC_TR and RTC_DR), and prescaler register (RTC_PRER). Counters are stopped and start counting from the new value when INIT is reset. + 1 + + + + + ALRAF + Alarm A flag + 8 + 1 + read-write + zeroToClear + + ALRAFR + read + + Match + This flag is set by hardware when the time/date registers (RTC_TR and RTC_DR) match the Alarm A register (RTC_ALRMAR) + 1 + + + + ALRAFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + ALRBF + Alarm B flag + 9 + 1 + read-write + zeroToClear + + ALRBFR + read + + Match + This flag is set by hardware when the time/date registers (RTC_TR and RTC_DR) match the Alarm B register (RTC_ALRMBR) + 1 + + + + ALRBFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + WUTF + Wakeup timer flag + 10 + 1 + read-write + zeroToClear + + WUTFR + read + + Zero + This flag is set by hardware when the wakeup auto-reload counter reaches 0 + 1 + + + + WUTFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + TSF + Time-stamp flag + 11 + 1 + read-write + zeroToClear + + TSFR + read + + TimestampEvent + This flag is set by hardware when a time-stamp event occurs + 1 + + + + TSFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + TSOVF + Time-stamp overflow flag + 12 + 1 + read-write + zeroToClear + + TSOVFR + read + + Overflow + This flag is set by hardware when a time-stamp event occurs while TSF is already set + 1 + + + + TSOVFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + TAMP1F + Tamper detection flag + 13 + 1 + read-write + zeroToClear + + TAMP1FR + read + + Tampered + This flag is set by hardware when a tamper detection event is detected on the RTC_TAMPx input + 1 + + + + TAMP1FW + write + + Clear + Flag cleared by software writing 0 + 0 + + + + + TAMP2F + TAMPER2 detection flag + 14 + 1 + read-write + zeroToClear + + read + + + write + + + + RECALPF + Recalibration pending Flag + 16 + 1 + read-only + + RECALPFR + read + + Pending + The RECALPF status flag is automatically set to 1 when software writes to the RTC_CALR register, indicating that the RTC_CALR register is blocked. When the new calibration settings are taken into account, this bit returns to 0 + 1 + + + + + + + PRER + PRER + prescaler register + 0x10 + 0x20 + read-write + 0x007F00FF + + + PREDIV_A + Asynchronous prescaler + factor + 16 + 7 + + + 0 + 127 + + + + + PREDIV_S + Synchronous prescaler + factor + 0 + 15 + + + 0 + 32767 + + + + + + + WUTR + WUTR + wakeup timer register + 0x14 + 0x20 + read-write + 0x0000FFFF + + + WUT + Wakeup auto-reload value + bits + 0 + 16 + + + 0 + 65535 + + + + + + + CALIBR + CALIBR + calibration register + 0x18 + 0x20 + read-write + 0x00000000 + + + DCS + Digital calibration sign + 7 + 1 + + + DC + Digital calibration + 0 + 5 + + + + + 2 + 0x4 + A,B + ALRM%sR + ALRMAR + Alarm register + 0x1C + 0x20 + read-write + 0x00000000 + + + MSK4 + Alarm date mask + 31 + 1 + + + + WDSEL + Week day selection + 30 + 1 + + WDSEL + read-write + + DateUnits + DU[3:0] represents the date units + 0 + + + WeekDay + DU[3:0] represents the week day. DT[1:0] is don’t care. + 1 + + + + + DT + Date tens in BCD format + 28 + 2 + + + 0 + 3 + + + + + DU + Date units or day in BCD format + 24 + 4 + + + 0 + 15 + + + + + MSK3 + Alarm hours mask + 23 + 1 + + + + PM + AM/PM notation + 22 + 1 + + PM + read-write + + AM + AM or 24-hour format + 0 + + + PM + PM + 1 + + + + + HT + Hour tens in BCD format + 20 + 2 + + + 0 + 3 + + + + + HU + Hour units in BCD format + 16 + 4 + + + 0 + 15 + + + + + MSK2 + Alarm minutes mask + 15 + 1 + + + + MNT + Minute tens in BCD format + 12 + 3 + + + 0 + 7 + + + + + MNU + Minute units in BCD format + 8 + 4 + + + 0 + 15 + + + + + MSK1 + Alarm seconds mask + 7 + 1 + + MSK1 + read-write + + Mask + Alarm set if the date/day match + 0 + + + NotMask + Date/day don’t care in Alarm comparison + 1 + + + + + ST + Second tens in BCD format + 4 + 3 + + + 0 + 7 + + + + + SU + Second units in BCD format + 0 + 4 + + + 0 + 15 + + + + + + + WPR + WPR + write protection register + 0x24 + 0x20 + write-only + 0x00000000 + + + KEY + Write protection key + 0 + 8 + + + 0 + 255 + + + + + + + SSR + SSR + sub second register + 0x28 + 0x20 + read-only + 0x00000000 + + + SS + Sub second value + 0 + 16 + + + 0 + 65535 + + + + + + + SHIFTR + SHIFTR + shift control register + 0x2C + 0x20 + write-only + 0x00000000 + + + ADD1S + Add one second + 31 + 1 + + ADD1SW + write + + Add1 + Add one second to the clock/calendar + 1 + + + + + SUBFS + Subtract a fraction of a + second + 0 + 15 + + + 0 + 32767 + + + + + + + TSTR + TSTR + time stamp time register + 0x30 + + + TSDR + TSDR + time stamp date register + 0x34 + + + TSSSR + TSSSR + timestamp sub second register + 0x38 + + + CALR + CALR + calibration register + 0x3C + 0x20 + read-write + 0x00000000 + + + CALP + Increase frequency of RTC by 488.5 + ppm + 15 + 1 + + CALP + read-write + + NoChange + No RTCCLK pulses are added + 0 + + + IncreaseFreq + One RTCCLK pulse is effectively inserted every 2^11 pulses (frequency increased by 488.5 ppm) + 1 + + + + + CALW8 + Use an 8-second calibration cycle + period + 14 + 1 + + CALW8 + read-write + + Eight_Second + When CALW8 is set to ‘1’, the 8-second calibration cycle period is selected + 1 + + + + + CALW16 + Use a 16-second calibration cycle + period + 13 + 1 + + CALW16 + read-write + + Sixteen_Second + When CALW16 is set to ‘1’, the 16-second calibration cycle period is selected.This bit must not be set to ‘1’ if CALW8=1 + 1 + + + + + CALM + Calibration minus + 0 + 9 + + + 0 + 511 + + + + + + + TAFCR + TAFCR + tamper and alternate function configuration + register + 0x40 + 0x20 + read-write + 0x00000000 + + + ALARMOUTTYPE + AFO_ALARM output type + 18 + 1 + + + TSINSEL + TIMESTAMP mapping + 17 + 1 + + + TAMP1INSEL + TAMPER1 mapping + 16 + 1 + + + TAMPPUDIS + TAMPER pull-up disable + 15 + 1 + + + TAMPPRCH + Tamper precharge duration + 13 + 2 + + + TAMPFLT + Tamper filter count + 11 + 2 + + + TAMPFREQ + Tamper sampling frequency + 8 + 3 + + + TAMPTS + Activate timestamp on tamper detection + event + 7 + 1 + + + TAMP2TRG + Active level for tamper 2 + 4 + 1 + + + TAMP2E + Tamper 2 detection enable + 3 + 1 + + + TAMPIE + Tamper interrupt enable + 2 + 1 + + + TAMP1TRG + Active level for tamper 1 + 1 + 1 + + + TAMP1E + Tamper 1 detection enable + 0 + 1 + + + + + 2 + 0x4 + A,B + ALRM%sSSR + ALRMASSR + Alarm sub-second register + 0x44 + 0x20 + read-write + 0x00000000 + + + MASKSS + Mask the most-significant bits starting + at this bit + 24 + 4 + + + 0 + 15 + + + + + SS + Sub seconds value + 0 + 15 + + + 0 + 32767 + + + + + + + 20 + 0x4 + 0-19 + BKP%sR + BKP0R + backup register + 0x50 + 0x20 + read-write + 0x00000000 + + + BKP + BKP + 0 + 32 + + + 0 + 4294967295 + + + + + + + + + SDIO + Secure digital input/output + interface + SDIO + 0x40012C00 + + 0x0 + 0x400 + registers + + + I2C3_EV + I2C3 event interrupt + 72 + + + I2C3_ER + I2C3 error interrupt + 73 + + + + POWER + POWER + power control register + 0x0 + 0x20 + read-write + 0x00000000 + + + PWRCTRL + PWRCTRL + 0 + 2 + + PWRCTRL + read-write + + PowerOff + Power off + 0 + + + PowerOn + Power on + 3 + + + + + + + CLKCR + CLKCR + SDI clock control register + 0x4 + 0x20 + read-write + 0x00000000 + + + HWFC_EN + HW Flow Control enable + 14 + 1 + + HWFC_EN + read-write + + Disabled + HW Flow Control is disabled + 0 + + + Enabled + HW Flow Control is enabled + 1 + + + + + NEGEDGE + SDIO_CK dephasing selection + bit + 13 + 1 + + NEGEDGE + read-write + + Rising + SDIO_CK generated on the rising edge + 0 + + + Falling + SDIO_CK generated on the falling edge + 1 + + + + + WIDBUS + Wide bus mode enable bit + 11 + 2 + + WIDBUS + read-write + + BusWidth1 + 1 lane wide bus + 0 + + + BusWidth4 + 4 lane wide bus + 1 + + + BusWidth8 + 8 lane wide bus + 2 + + + + + BYPASS + Clock divider bypass enable + bit + 10 + 1 + + BYPASS + read-write + + Disabled + SDIOCLK is divided according to the CLKDIV value before driving the SDIO_CK output signal. + 0 + + + Enabled + SDIOCLK directly drives the SDIO_CK output signal + 1 + + + + + PWRSAV + Power saving configuration + bit + 9 + 1 + + PWRSAV + read-write + + Enabled + SDIO_CK clock is always enabled + 0 + + + Disabled + SDIO_CK is only enabled when the bus is active + 1 + + + + + CLKEN + Clock enable bit + 8 + 1 + + CLKEN + read-write + + Disabled + Disable clock + 0 + + + Enabled + Enable clock + 1 + + + + + CLKDIV + Clock divide factor + 0 + 8 + + + 0 + 255 + + + + + + + ARG + ARG + argument register + 0x8 + 0x20 + read-write + 0x00000000 + + + CMDARG + Command argument + 0 + 32 + + + 0 + 4294967295 + + + + + + + CMD + CMD + command register + 0xC + 0x20 + read-write + 0x00000000 + + + CE_ATACMD + CE-ATA command + 14 + 1 + + CE_ATACMD + read-write + + Disabled + CE-ATA command disabled + 0 + + + Enabled + CE-ATA command enabled + 1 + + + + + nIEN + not Interrupt Enable + 13 + 1 + + nIEN + read-write + + Disabled + Interrupts to the CE-ATA not disabled + 0 + + + Enabled + Interrupt to the CE-ATA are disabled + 1 + + + + + ENCMDcompl + Enable CMD completion + 12 + 1 + + ENCMDcompl + read-write + + Disabled + Command complete signal disabled + 0 + + + Enabled + Command complete signal enabled + 1 + + + + + SDIOSuspend + SD I/O suspend command + 11 + 1 + + SDIOSuspend + read-write + + Disabled + Next command is not a SDIO suspend command + 0 + + + Enabled + Next command send is a SDIO suspend command + 1 + + + + + CPSMEN + Command path state machine (CPSM) Enable + bit + 10 + 1 + + CPSMEN + read-write + + Disabled + Command path state machine disabled + 0 + + + Enabled + Command path state machine enabled + 1 + + + + + WAITPEND + CPSM Waits for ends of data transfer + (CmdPend internal signal). + 9 + 1 + + WAITPEND + read-write + + Disabled + Don't wait for data end + 0 + + + Enabled + Wait for end of data transfer signal before sending command + 1 + + + + + WAITINT + CPSM waits for interrupt + request + 8 + 1 + + WAITINT + read-write + + Disabled + Don't wait for interrupt request + 0 + + + Enabled + Wait for interrupt request + 1 + + + + + WAITRESP + Wait for response bits + 6 + 2 + + WAITRESP + read-write + + NoResponse + No response + 0 + + + ShortResponse + Short response + 1 + + + NoResponse2 + No reponse + 2 + + + LongResponse + Long reponse + 3 + + + + + CMDINDEX + Command index + 0 + 6 + + + 0 + 63 + + + + + + + RESPCMD + RESPCMD + command response register + 0x10 + 0x20 + read-only + 0x00000000 + + + RESPCMD + Response command index + 0 + 6 + + + 0 + 63 + + + + + + + RESP1 + RESP1 + response 1..4 register + 0x14 + 0x20 + read-only + 0x00000000 + + + CARDSTATUS1 + Card Status + 0 + 32 + + + 0 + 4294967295 + + + + + + + RESP2 + RESP2 + response 1..4 register + 0x18 + 0x20 + read-only + 0x00000000 + + + CARDSTATUS2 + Card Status + 0 + 32 + + + 0 + 4294967295 + + + + + + + RESP3 + RESP3 + response 1..4 register + 0x1C + 0x20 + read-only + 0x00000000 + + + CARDSTATUS3 + Card Status + 0 + 32 + + + 0 + 4294967295 + + + + + + + RESP4 + RESP4 + response 1..4 register + 0x20 + 0x20 + read-only + 0x00000000 + + + CARDSTATUS4 + Card Status + 0 + 32 + + + 0 + 4294967295 + + + + + + + DTIMER + DTIMER + data timer register + 0x24 + 0x20 + read-write + 0x00000000 + + + DATATIME + Data timeout period + 0 + 32 + + + 0 + 4294967295 + + + + + + + DLEN + DLEN + data length register + 0x28 + 0x20 + read-write + 0x00000000 + + + DATALENGTH + Data length value + 0 + 25 + + + 0 + 33554431 + + + + + + + DCTRL + DCTRL + data control register + 0x2C + 0x20 + read-write + 0x00000000 + + + SDIOEN + SD I/O enable functions + 11 + 1 + + SDIOEN + read-write + + Disabled + SDIO operations disabled + 0 + + + Enabled + SDIO operations enabled + 1 + + + + + RWMOD + Read wait mode + 10 + 1 + + RWMOD + read-write + + D2 + Read wait control stopping using SDIO_D2 + 0 + + + Ck + Read wait control using SDIO_CK + 1 + + + + + RWSTOP + Read wait stop + 9 + 1 + + RWSTOP + read-write + + Disabled + Read wait in progress if RWSTART is enabled + 0 + + + Enabled + Enable for read wait stop if RWSTART is enabled + 1 + + + + + RWSTART + Read wait start + 8 + 1 + + RWSTART + read-write + + Disabled + Don't start read wait operation + 0 + + + Enabled + Read wait operation starts + 1 + + + + + DBLOCKSIZE + Data block size + 4 + 4 + + + 0 + 15 + + + + + DMAEN + DMA enable bit + 3 + 1 + + DMAEN + read-write + + Disabled + Dma disabled + 0 + + + Enabled + Dma enabled + 1 + + + + + DTMODE + Data transfer mode selection 1: Stream + or SDIO multibyte data transfer. + 2 + 1 + + DTMODE + read-write + + BlockMode + Bloack data transfer + 0 + + + StreamMode + Stream or SDIO multibyte data transfer + 1 + + + + + DTDIR + Data transfer direction + selection + 1 + 1 + + DTDIR + read-write + + ControllerToCard + From controller to card + 0 + + + CardToController + From card to controller + 1 + + + + + DTEN + DTEN + 0 + 1 + + DTEN + read-write + + Disabled + Disabled + 0 + + + Enabled + Start transfer + 1 + + + + + + + DCOUNT + DCOUNT + data counter register + 0x30 + 0x20 + read-only + 0x00000000 + + + DATACOUNT + Data count value + 0 + 25 + + + 0 + 33554431 + + + + + + + STA + STA + status register + 0x34 + 0x20 + read-only + 0x00000000 + + + CEATAEND + CE-ATA command completion signal + received for CMD61 + 23 + 1 + + CEATAEND + read + + NotReceived + Completion signal not received + 0 + + + Received + CE-ATA command completion signal received for CMD61 + 1 + + + + + SDIOIT + SDIO interrupt received + 22 + 1 + + SDIOIT + read + + NotReceived + SDIO interrupt not receieved + 0 + + + Received + SDIO interrupt received + 1 + + + + + RXDAVL + Data available in receive + FIFO + 21 + 1 + + RXDAVL + read + + NotAvailable + Data not available in receive FIFO + 0 + + + Available + Data available in receive FIFO + 1 + + + + + TXDAVL + Data available in transmit + FIFO + 20 + 1 + + TXDAVL + read + + NotAvailable + Data not available in transmit FIFO + 0 + + + Available + Data available in transmit FIFO + 1 + + + + + RXFIFOE + Receive FIFO empty + 19 + 1 + + RXFIFOE + read + + NotEmpty + Receive FIFO not empty + 0 + + + Empty + Receive FIFO empty + 1 + + + + + TXFIFOE + Transmit FIFO empty + 18 + 1 + + TXFIFOE + read + + NotEmpty + Transmit FIFO not empty + 0 + + + Empty + Transmit FIFO empty. When HW Flow Control is enabled, TXFIFOE signals becomes activated when the FIFO contains 2 words. + 1 + + + + + RXFIFOF + Receive FIFO full + 17 + 1 + + RXFIFOF + read + + NotFull + Transmit FIFO not full + 0 + + + Full + Receive FIFO full. When HW Flow Control is enabled, RXFIFOF signals becomes activated 2 words before the FIFO is full. + 1 + + + + + TXFIFOF + Transmit FIFO full + 16 + 1 + + TXFIFOF + read + + NotFull + Transmit FIFO not full + 0 + + + Full + Transmit FIFO full + 1 + + + + + RXFIFOHF + Receive FIFO half full: there are at + least 8 words in the FIFO + 15 + 1 + + RXFIFOHF + read + + NotHalfFull + Receive FIFO not half full + 0 + + + HalfFull + Receive FIFO half full. At least 8 words in the FIFO + 1 + + + + + TXFIFOHE + Transmit FIFO half empty: at least 8 + words can be written into the FIFO + 14 + 1 + + TXFIFOHE + read + + NotHalfEmpty + Transmit FIFO not half empty + 0 + + + HalfEmpty + Transmit FIFO half empty. At least 8 words can be written into the FIFO + 1 + + + + + RXACT + Data receive in progress + 13 + 1 + + RXACT + read + + NotInProgress + Data receive not in progress + 0 + + + InProgress + Data receive in progress + 1 + + + + + TXACT + Data transmit in progress + 12 + 1 + + TXACT + read + + NotInProgress + Data transmit is not in progress + 0 + + + InProgress + Data transmit in progress + 1 + + + + + CMDACT + Command transfer in + progress + 11 + 1 + + CMDACT + read + + NotInProgress + Command transfer not in progress + 0 + + + InProgress + Command tranfer in progress + 1 + + + + + DBCKEND + Data block sent/received (CRC check + passed) + 10 + 1 + + DBCKEND + read + + NotTransferred + Data block not sent/received (CRC check failed) + 0 + + + Transferred + Data block sent/received (CRC check passed) + 1 + + + + + STBITERR + Start bit not detected on all data + signals in wide bus mode + 9 + 1 + + STBITERR + read + + Detected + No start bit detected error + 0 + + + NotDetected + Start bit not detected error + 1 + + + + + DATAEND + Data end (data counter, SDIDCOUNT, is + zero) + 8 + 1 + + DATAEND + read + + NotDone + Not done + 0 + + + Done + Data end (DCOUNT, is zero) + 1 + + + + + CMDSENT + Command sent (no response + required) + 7 + 1 + + CMDSENT + read + + NotSent + Command not sent + 0 + + + Sent + Command sent (no response required) + 1 + + + + + CMDREND + Command response received (CRC check + passed) + 6 + 1 + + CMDREND + read + + NotDone + Command not done + 0 + + + Done + Command response received (CRC check passed) + 1 + + + + + RXOVERR + Received FIFO overrun + error + 5 + 1 + + RXOVERR + read + + NoOverrun + No FIFO overrun error + 0 + + + Overrun + Receive FIFO overrun error + 1 + + + + + TXUNDERR + Transmit FIFO underrun + error + 4 + 1 + + TXUNDERR + read + + NoUnderrun + No transmit FIFO underrun error + 0 + + + Underrun + Transmit FIFO underrun error + 1 + + + + + DTIMEOUT + Data timeout + 3 + 1 + + DTIMEOUT + read + + NoTimeout + No data timeout + 0 + + + Timeout + Data timeout + 1 + + + + + CTIMEOUT + Command response timeout + 2 + 1 + + CTIMEOUT + read + + NoTimeout + No Command timeout + 0 + + + Timeout + Command timeout + 1 + + + + + DCRCFAIL + Data block sent/received (CRC check + failed) + 1 + 1 + + DCRCFAIL + read + + NotFailed + No Data block sent/received crc check fail + 0 + + + Failed + Data block sent/received crc failed + 1 + + + + + CCRCFAIL + Command response received (CRC check + failed) + 0 + 1 + + CCRCFAIL + read + + NotFailed + Command response received, crc check passed + 0 + + + Failed + Command response received, crc check failed + 1 + + + + + + + ICR + ICR + interrupt clear register + 0x38 + 0x20 + read-write + 0x00000000 + + + CEATAENDC + CEATAEND flag clear bit + 23 + 1 + + + + SDIOITC + SDIOIT flag clear bit + 22 + 1 + + + + DBCKENDC + DBCKEND flag clear bit + 10 + 1 + + + + STBITERRC + STBITERR flag clear bit + 9 + 1 + + + + DATAENDC + DATAEND flag clear bit + 8 + 1 + + + + CMDSENTC + CMDSENT flag clear bit + 7 + 1 + + + + CMDRENDC + CMDREND flag clear bit + 6 + 1 + + + + RXOVERRC + RXOVERR flag clear bit + 5 + 1 + + + + TXUNDERRC + TXUNDERR flag clear bit + 4 + 1 + + + + DTIMEOUTC + DTIMEOUT flag clear bit + 3 + 1 + + + + CTIMEOUTC + CTIMEOUT flag clear bit + 2 + 1 + + + + DCRCFAILC + DCRCFAIL flag clear bit + 1 + 1 + + + + CCRCFAILC + CCRCFAIL flag clear bit + 0 + 1 + + CCRCFAILCW + write + + Clear + Clear flag + 1 + + + + + + + MASK + MASK + mask register + 0x3C + 0x20 + read-write + 0x00000000 + + + CEATAENDIE + CE-ATA command completion signal + received interrupt enable + 23 + 1 + + + + SDIOITIE + SDIO mode interrupt received interrupt + enable + 22 + 1 + + + + RXDAVLIE + Data available in Rx FIFO interrupt + enable + 21 + 1 + + + + TXDAVLIE + Data available in Tx FIFO interrupt + enable + 20 + 1 + + + + RXFIFOEIE + Rx FIFO empty interrupt + enable + 19 + 1 + + + + TXFIFOEIE + Tx FIFO empty interrupt + enable + 18 + 1 + + + + RXFIFOFIE + Rx FIFO full interrupt + enable + 17 + 1 + + + + TXFIFOFIE + Tx FIFO full interrupt + enable + 16 + 1 + + + + RXFIFOHFIE + Rx FIFO half full interrupt + enable + 15 + 1 + + + + TXFIFOHEIE + Tx FIFO half empty interrupt + enable + 14 + 1 + + + + RXACTIE + Data receive acting interrupt + enable + 13 + 1 + + + + TXACTIE + Data transmit acting interrupt + enable + 12 + 1 + + + + CMDACTIE + Command acting interrupt + enable + 11 + 1 + + + + DBCKENDIE + Data block end interrupt + enable + 10 + 1 + + + + STBITERRIE + Start bit error interrupt + enable + 9 + 1 + + + + DATAENDIE + Data end interrupt enable + 8 + 1 + + + + CMDSENTIE + Command sent interrupt + enable + 7 + 1 + + + + CMDRENDIE + Command response received interrupt + enable + 6 + 1 + + + + RXOVERRIE + Rx FIFO overrun error interrupt + enable + 5 + 1 + + + + TXUNDERRIE + Tx FIFO underrun error interrupt + enable + 4 + 1 + + + + DTIMEOUTIE + Data timeout interrupt + enable + 3 + 1 + + + + CTIMEOUTIE + Command timeout interrupt + enable + 2 + 1 + + + + DCRCFAILIE + Data CRC fail interrupt + enable + 1 + 1 + + + + CCRCFAILIE + Command CRC fail interrupt + enable + 0 + 1 + + CCRCFAILIE + read-write + + Disabled + Interrupt disabled + 0 + + + Enabled + Interrupt enabled + 1 + + + + + + + FIFOCNT + FIFOCNT + FIFO counter register + 0x48 + 0x20 + read-only + 0x00000000 + + + FIFOCOUNT + Remaining number of words to be written + to or read from the FIFO. + 0 + 24 + + + 0 + 16777215 + + + + + + + FIFO + FIFO + data FIFO register + 0x80 + 0x20 + read-write + 0x00000000 + + + FIFOData + Receive and transmit FIFO + data + 0 + 32 + + + 0 + 4294967295 + + + + + + + + + SYSCFG + System configuration controller + SYSCFG + 0x40013800 + + 0x0 + 0x400 + registers + + + + MEMRM + MEMRM + memory remap register + 0x0 + 0x20 + read-write + 0x00000000 + + + MEM_MODE + MEM_MODE + 0 + 2 + + + + + PMC + PMC + peripheral mode configuration + register + 0x4 + 0x20 + read-write + 0x00000000 + + + ADC1DC2 + ADC1DC2 + 16 + 1 + + + + + EXTICR1 + EXTICR1 + external interrupt configuration register + 1 + 0x8 + 0x20 + read-write + 0x00000000 + + + EXTI3 + EXTI x configuration (x = 0 to + 3) + 12 + 4 + + + EXTI2 + EXTI x configuration (x = 0 to + 3) + 8 + 4 + + + EXTI1 + EXTI x configuration (x = 0 to + 3) + 4 + 4 + + + EXTI0 + EXTI x configuration (x = 0 to + 3) + 0 + 4 + + + + + EXTICR2 + EXTICR2 + external interrupt configuration register + 2 + 0xC + 0x20 + read-write + 0x00000000 + + + EXTI7 + EXTI x configuration (x = 4 to + 7) + 12 + 4 + + + EXTI6 + EXTI x configuration (x = 4 to + 7) + 8 + 4 + + + EXTI5 + EXTI x configuration (x = 4 to + 7) + 4 + 4 + + + EXTI4 + EXTI x configuration (x = 4 to + 7) + 0 + 4 + + + + + EXTICR3 + EXTICR3 + external interrupt configuration register + 3 + 0x10 + 0x20 + read-write + 0x00000000 + + + EXTI11 + EXTI x configuration (x = 8 to + 11) + 12 + 4 + + + EXTI10 + EXTI10 + 8 + 4 + + + EXTI9 + EXTI x configuration (x = 8 to + 11) + 4 + 4 + + + EXTI8 + EXTI x configuration (x = 8 to + 11) + 0 + 4 + + + + + EXTICR4 + EXTICR4 + external interrupt configuration register + 4 + 0x14 + 0x20 + read-write + 0x00000000 + + + EXTI15 + EXTI x configuration (x = 12 to + 15) + 12 + 4 + + + EXTI14 + EXTI x configuration (x = 12 to + 15) + 8 + 4 + + + EXTI13 + EXTI x configuration (x = 12 to + 15) + 4 + 4 + + + EXTI12 + EXTI x configuration (x = 12 to + 15) + 0 + 4 + + + + + CMPCR + CMPCR + Compensation cell control + register + 0x20 + 0x20 + read-only + 0x00000000 + + + READY + READY + 8 + 1 + + + CMP_PD + Compensation cell + power-down + 0 + 1 + + + + + + + TIM1 + Advanced-timers + TIM + 0x40010000 + + 0x0 + 0x400 + registers + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + CMS + Center-aligned mode + selection + 5 + 2 + + CMS + read-write + + EdgeAligned + The counter counts up or down depending on the direction bit + 0 + + + CenterAligned1 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting down. + 1 + + + CenterAligned2 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting up. + 2 + + + CenterAligned3 + The counter counts up and down alternatively. Output compare interrupt flags are set both when the counter is counting up or down. + 3 + + + + + DIR + Direction + 4 + 1 + + DIR + read-write + + Up + Counter used as upcounter + 0 + + + Down + Counter used as downcounter + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + OIS4 + Output Idle state 4 + 14 + 1 + + + + OIS3N + Output Idle state 3 + 13 + 1 + + + + OIS3 + Output Idle state 3 + 12 + 1 + + + + OIS2N + Output Idle state 2 + 11 + 1 + + + + OIS2 + Output Idle state 2 + 10 + 1 + + + + OIS1N + Output Idle state 1 + 9 + 1 + + OIS1N + read-write + + Reset + OCxN=0 after a dead-time when MOE=0 + 0 + + + Set + OCxN=1 after a dead-time when MOE=0 + 1 + + + + + OIS1 + Output Idle state 1 + 8 + 1 + + OIS1 + read-write + + Reset + OCx=0 (after a dead-time if OCx(N) is implemented) when MOE=0 + 0 + + + Set + OCx=1 (after a dead-time if OCx(N) is implemented) when MOE=0 + 1 + + + + + TI1S + TI1 selection + 7 + 1 + + TI1S + read-write + + Normal + The TIMx_CH1 pin is connected to TI1 input + 0 + + + XOR + The TIMx_CH1, CH2, CH3 pins are connected to TI1 input + 1 + + + + + MMS + Master mode selection + 4 + 3 + + MMS + read-write + + Reset + The UG bit from the TIMx_EGR register is used as trigger output + 0 + + + Enable + The counter enable signal, CNT_EN, is used as trigger output + 1 + + + Update + The update event is selected as trigger output + 2 + + + ComparePulse + The trigger output send a positive pulse when the CC1IF flag it to be set, as soon as a capture or a compare match occurred + 3 + + + CompareOC1 + OC1REF signal is used as trigger output + 4 + + + CompareOC2 + OC2REF signal is used as trigger output + 5 + + + CompareOC3 + OC3REF signal is used as trigger output + 6 + + + CompareOC4 + OC4REF signal is used as trigger output + 7 + + + + + CCDS + Capture/compare DMA + selection + 3 + 1 + + CCDS + read-write + + OnCompare + CCx DMA request sent when CCx event occurs + 0 + + + OnUpdate + CCx DMA request sent when update event occurs + 1 + + + + + CCUS + Capture/compare control update + selection + 2 + 1 + + + CCPC + Capture/compare preloaded + control + 0 + 1 + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + ETP + External trigger polarity + 15 + 1 + + ETP + read-write + + NotInverted + ETR is noninverted, active at high level or rising edge + 0 + + + Inverted + ETR is inverted, active at low level or falling edge + 1 + + + + + ECE + External clock enable + 14 + 1 + + ECE + read-write + + Disabled + External clock mode 2 disabled + 0 + + + Enabled + External clock mode 2 enabled. The counter is clocked by any active edge on the ETRF signal. + 1 + + + + + ETPS + External trigger prescaler + 12 + 2 + + ETPS + read-write + + Div1 + Prescaler OFF + 0 + + + Div2 + ETRP frequency divided by 2 + 1 + + + Div4 + ETRP frequency divided by 4 + 2 + + + Div8 + ETRP frequency divided by 8 + 3 + + + + + ETF + External trigger filter + 8 + 4 + + ETF + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + MSM + Master/Slave mode + 7 + 1 + + MSM + read-write + + NoSync + No action + 0 + + + Sync + The effect of an event on the trigger input (TRGI) is delayed to allow a perfect synchronization between the current timer and its slaves (through TRGO). It is useful if we want to synchronize several timers on a single external event. + 1 + + + + + TS + Trigger selection + 4 + 3 + + TS + read-write + + ITR0 + Internal Trigger 0 (ITR0) + 0 + + + ITR1 + Internal Trigger 1 (ITR1) + 1 + + + ITR2 + Internal Trigger 2 (ITR2) + 2 + + + TI1F_ED + TI1 Edge Detector (TI1F_ED) + 4 + + + TI1FP1 + Filtered Timer Input 1 (TI1FP1) + 5 + + + TI2FP2 + Filtered Timer Input 2 (TI2FP2) + 6 + + + ETRF + External Trigger input (ETRF) + 7 + + + + + SMS + Slave mode selection + 0 + 3 + + SMS + read-write + + Disabled + Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal clock. + 0 + + + Encoder_Mode_1 + Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending on TI1FP2 level. + 1 + + + Encoder_Mode_2 + Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level. + 2 + + + Encoder_Mode_3 + Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. + 3 + + + Reset_Mode + Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and generates an update of the registers. + 4 + + + Gated_Mode + Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of the counter are controlled. + 5 + + + Trigger_Mode + Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not reset). Only the start of the counter is controlled. + 6 + + + Ext_Clock_Mode + External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter. + 7 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TDE + Trigger DMA request enable + 14 + 1 + + TDE + read-write + + Disabled + Trigger DMA request disabled + 0 + + + Enabled + Trigger DMA request enabled + 1 + + + + + COMDE + COM DMA request enable + 13 + 1 + + + CC4DE + Capture/Compare 4 DMA request + enable + 12 + 1 + + + + CC3DE + Capture/Compare 3 DMA request + enable + 11 + 1 + + + + CC2DE + Capture/Compare 2 DMA request + enable + 10 + 1 + + + + CC1DE + Capture/Compare 1 DMA request + enable + 9 + 1 + + CC1DE + read-write + + Disabled + CCx DMA request disabled + 0 + + + Enabled + CCx DMA request enabled + 1 + + + + + UDE + Update DMA request enable + 8 + 1 + + UDE + read-write + + Disabled + Update DMA request disabled + 0 + + + Enabled + Update DMA request enabled + 1 + + + + + BIE + Break interrupt enable + 7 + 1 + + + TIE + Trigger interrupt enable + 6 + 1 + + TIE + read-write + + Disabled + Trigger interrupt disabled + 0 + + + Enabled + Trigger interrupt enabled + 1 + + + + + COMIE + COM interrupt enable + 5 + 1 + + + CC4IE + Capture/Compare 4 interrupt + enable + 4 + 1 + + + + CC3IE + Capture/Compare 3 interrupt + enable + 3 + 1 + + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + CC1IE + read-write + + Disabled + CCx interrupt disabled + 0 + + + Enabled + CCx interrupt enabled + 1 + + + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC4OF + Capture/Compare 4 overcapture + flag + 12 + 1 + zeroToClear + + read + + + write + + + + CC3OF + Capture/Compare 3 overcapture + flag + 11 + 1 + zeroToClear + + read + + + write + + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + zeroToClear + + read + + + write + + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + zeroToClear + + CC1OFR + read + + Overcapture + The counter value has been captured in TIMx_CCRx register while CCxIF flag was already set + 1 + + + + CC1OFW + write + + Clear + Clear flag + 0 + + + + + BIF + Break interrupt flag + 7 + 1 + + + TIF + Trigger interrupt flag + 6 + 1 + zeroToClear + + TIFR + read + + NoTrigger + No trigger event occurred + 0 + + + Trigger + Trigger interrupt pending + 1 + + + + TIFW + write + + Clear + Clear flag + 0 + + + + + COMIF + COM interrupt flag + 5 + 1 + + + CC4IF + Capture/Compare 4 interrupt + flag + 4 + 1 + zeroToClear + + read + + + write + + + + CC3IF + Capture/Compare 3 interrupt + flag + 3 + 1 + zeroToClear + + read + + + write + + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + zeroToClear + + read + + + write + + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + zeroToClear + + CC1IFR + read + + Match + If CC1 is an output: The content of the counter TIMx_CNT matches the content of the TIMx_CCR1 register. If CC1 is an input: The counter value has been captured in TIMx_CCR1 register. + 1 + + + + CC1IFW + write + + Clear + Clear flag + 0 + + + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + BG + Break generation + 7 + 1 + + + TG + Trigger generation + 6 + 1 + + TGW + write + + Trigger + The TIF flag is set in TIMx_SR register. Related interrupt or DMA transfer can occur if enabled. + 1 + + + + + COMG + Capture/Compare control update + generation + 5 + 1 + + + CC4G + Capture/compare 4 + generation + 4 + 1 + + + + CC3G + Capture/compare 3 + generation + 3 + 1 + + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + CC1GW + write + + Trigger + If CC1 is an output: CC1IF flag is set, Corresponding interrupt or DMA request is sent if enabled. If CC1 is an input: The current value of the counter is captured in TIMx_CCR1 register. + 1 + + + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2CE + Output Compare 2 clear + enable + 15 + 1 + + + OC2M + Output Compare 2 mode + 12 + 3 + + + + OC2PE + Output Compare 2 preload + enable + 11 + 1 + + OC2PE + read-write + + Disabled + Preload register on CCR2 disabled. New values written to CCR2 are taken into account immediately + 0 + + + Enabled + Preload register on CCR2 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC2FE + Output Compare 2 fast + enable + 10 + 1 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + Output + CC2 channel is configured as output + 0 + + + + + OC1CE + Output Compare 1 clear + enable + 7 + 1 + + + OC1M + Output Compare 1 mode + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + Output Compare 1 preload + enable + 3 + 1 + + OC1PE + read-write + + Disabled + Preload register on CCR1 disabled. New values written to CCR1 are taken into account immediately + 0 + + + Enabled + Preload register on CCR1 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC1FE + Output Compare 1 fast + enable + 2 + 1 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + Output + CC1 channel is configured as output + 0 + + + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 4 + + + 0 + 15 + + + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + TI2 + CC2 channel is configured as input, IC2 is mapped on TI2 + 1 + + + TI1 + CC2 channel is configured as input, IC2 is mapped on TI1 + 2 + + + TRC + CC2 channel is configured as input, IC2 is mapped on TRC + 3 + + + + + IC1F + Input capture 1 filter + 4 + 4 + + IC1F + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + TI1 + CC1 channel is configured as input, IC1 is mapped on TI1 + 1 + + + TI2 + CC1 channel is configured as input, IC1 is mapped on TI2 + 2 + + + TRC + CC1 channel is configured as input, IC1 is mapped on TRC + 3 + + + + + + + CCMR2_Output + CCMR2_Output + capture/compare mode register 2 (output + mode) + 0x1C + 0x20 + read-write + 0x00000000 + + + OC4CE + Output compare 4 clear + enable + 15 + 1 + + + OC4M + Output compare 4 mode + 12 + 3 + + + + OC4PE + Output compare 4 preload + enable + 11 + 1 + + OC4PE + read-write + + Disabled + Preload register on CCR4 disabled. New values written to CCR4 are taken into account immediately + 0 + + + Enabled + Preload register on CCR4 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC4FE + Output compare 4 fast + enable + 10 + 1 + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + Output + CC4 channel is configured as output + 0 + + + + + OC3CE + Output compare 3 clear + enable + 7 + 1 + + + OC3M + Output compare 3 mode + 4 + 3 + + OC3M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC3PE + Output compare 3 preload + enable + 3 + 1 + + OC3PE + read-write + + Disabled + Preload register on CCR3 disabled. New values written to CCR3 are taken into account immediately + 0 + + + Enabled + Preload register on CCR3 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC3FE + Output compare 3 fast + enable + 2 + 1 + + + CC3S + Capture/Compare 3 + selection + 0 + 2 + + CC3S + read-write + + Output + CC3 channel is configured as output + 0 + + + + + + + CCMR2_Input + CCMR2_Input + capture/compare mode register 2 (input + mode) + CCMR2_Output + 0x1C + 0x20 + read-write + 0x00000000 + + + IC4F + Input capture 4 filter + 12 + 4 + + + 0 + 15 + + + + + IC4PSC + Input capture 4 prescaler + 10 + 2 + + + 0 + 3 + + + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + TI4 + CC4 channel is configured as input, IC4 is mapped on TI4 + 1 + + + TI3 + CC4 channel is configured as input, IC4 is mapped on TI3 + 2 + + + TRC + CC4 channel is configured as input, IC4 is mapped on TRC + 3 + + + + + IC3F + Input capture 3 filter + 4 + 4 + + + 0 + 15 + + + + + IC3PSC + Input capture 3 prescaler + 2 + 2 + + + 0 + 3 + + + + + CC3S + Capture/compare 3 + selection + 0 + 2 + + CC3S + read-write + + TI3 + CC3 channel is configured as input, IC3 is mapped on TI3 + 1 + + + TI4 + CC3 channel is configured as input, IC3 is mapped on TI4 + 2 + + + TRC + CC3 channel is configured as input, IC3 is mapped on TRC + 3 + + + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC4P + Capture/Compare 3 output + Polarity + 13 + 1 + + + CC4E + Capture/Compare 4 output + enable + 12 + 1 + + + CC3NP + Capture/Compare 3 output + Polarity + 11 + 1 + + + CC3NE + Capture/Compare 3 complementary output + enable + 10 + 1 + + + CC3P + Capture/Compare 3 output + Polarity + 9 + 1 + + + CC3E + Capture/Compare 3 output + enable + 8 + 1 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2NE + Capture/Compare 2 complementary output + enable + 6 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1NE + Capture/Compare 1 complementary output + enable + 2 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + counter value + 0 + 16 + + + 0 + 65535 + + + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + 0 + 65535 + + + + + + + 4 + 0x4 + 1-4 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + 0 + 65535 + + + + + + + DCR + DCR + DMA control register + 0x48 + 0x20 + read-write + 0x00000000 + + + DBL + DMA burst length + 8 + 5 + + + 0 + 18 + + + + + DBA + DMA base address + 0 + 5 + + + 0 + 31 + + + + + + + DMAR + DMAR + DMA address for full transfer + 0x4C + 0x20 + read-write + 0x00000000 + + + DMAB + DMA register for burst + accesses + 0 + 16 + + + + + RCR + RCR + repetition counter register + 0x30 + 0x20 + read-write + 0x00000000 + + + REP + Repetition counter value + 0 + 8 + + + + + BDTR + BDTR + break and dead-time register + 0x44 + 0x20 + read-write + 0x00000000 + + + MOE + Main output enable + 15 + 1 + + MOE + read-write + + DisabledIdle + OC/OCN are disabled or forced idle depending on OSSI + 0 + + + Enabled + OC/OCN are enabled if CCxE/CCxNE are set + 1 + + + + + AOE + Automatic output enable + 14 + 1 + + AOE + read-write + + Manual + MOE can be set only by software + 0 + + + Automatic + MOE can be set by software or automatically at the next update event (if none of the break inputs BRK and BRK2 is active) + 1 + + + + + BKP + Break polarity + 13 + 1 + + BKP + read-write + + ActiveLow + Break input BRKx is active low + 0 + + + ActiveHigh + Break input BRKx is active high + 1 + + + + + BKE + Break enable + 12 + 1 + + BKE + read-write + + Disabled + Break function x disabled + 0 + + + Enabled + Break function x disabled + 1 + + + + + OSSR + Off-state selection for Run + mode + 11 + 1 + + OSSR + read-write + + Disabled + When inactive, OC/OCN outputs are disabled + 0 + + + IdleLevel + When inactive, OC/OCN outputs are enabled with their inactive level + 1 + + + + + OSSI + Off-state selection for Idle + mode + 10 + 1 + + OSSI + read-write + + Disabled + When inactive, OC/OCN outputs are disabled + 0 + + + IdleLevel + When inactive, OC/OCN outputs are forced to idle level + 1 + + + + + LOCK + Lock configuration + 8 + 2 + + LOCK + read-write + + Off + No bit is write protected + 0 + + + Level1 + Any bits except MOE, OSSR, OSSI and LOCK in TIMx_BDTR register, OISx and OISxN bits in TIMx_CR2 register can no longer be written + 1 + + + Level2 + LOCK Level 1 + CC Polarity bits (CCxP/CCxNP bits in TIMx_CCER register, as long as the related channel is configured in output through the CCxS bits) as well as OSSR and OSSI bits can no longer be written + 2 + + + Level3 + LOCK Level 2 + CC Control bits (OCxM and OCxPE bits in TIMx_CCMRx registers, as long as the related channel is configured in output through the CCxS bits) can no longer be written + 3 + + + + + DTG + Dead-time generator setup + 0 + 8 + + + 0 + 255 + + + + + + + + + TIM10 + General-purpose-timers + TIM + 0x40014400 + + 0x0 + 0x400 + registers + + + SPI1 + SPI1 global interrupt + 35 + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC1M + Output Compare 1 mode + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + Output Compare 1 preload + enable + 3 + 1 + + + OC1FE + Output Compare 1 fast + enable + 2 + 1 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC1F + Input capture 1 filter + 4 + 4 + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + counter value + 0 + 16 + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + + + 1 + 0x0 + 1-1 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + + + + + TIM11 + General-purpose-timers + TIM + 0x40014800 + + 0x0 + 0x400 + registers + + + SPI2 + SPI2 global interrupt + 36 + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC1M + Output Compare 1 mode + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + Output Compare 1 preload + enable + 3 + 1 + + + OC1FE + Output Compare 1 fast + enable + 2 + 1 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC1F + Input capture 1 filter + 4 + 4 + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + counter value + 0 + 16 + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + + + 1 + 0x0 + 1-1 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + + + OR + OR + option register + 0x50 + 0x20 + read-write + 0x00000000 + + + RMP + Input 1 remapping + capability + 0 + 2 + + + + + + + TIM2 + General purpose timers + TIM + 0x40000000 + + 0x0 + 0x400 + registers + + + SPI3 + SPI3 global interrupt + 51 + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + CMS + Center-aligned mode + selection + 5 + 2 + + CMS + read-write + + EdgeAligned + The counter counts up or down depending on the direction bit + 0 + + + CenterAligned1 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting down. + 1 + + + CenterAligned2 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting up. + 2 + + + CenterAligned3 + The counter counts up and down alternatively. Output compare interrupt flags are set both when the counter is counting up or down. + 3 + + + + + DIR + Direction + 4 + 1 + + DIR + read-write + + Up + Counter used as upcounter + 0 + + + Down + Counter used as downcounter + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + TI1S + TI1 selection + 7 + 1 + + TI1S + read-write + + Normal + The TIMx_CH1 pin is connected to TI1 input + 0 + + + XOR + The TIMx_CH1, CH2, CH3 pins are connected to TI1 input + 1 + + + + + MMS + Master mode selection + 4 + 3 + + MMS + read-write + + Reset + The UG bit from the TIMx_EGR register is used as trigger output + 0 + + + Enable + The counter enable signal, CNT_EN, is used as trigger output + 1 + + + Update + The update event is selected as trigger output + 2 + + + ComparePulse + The trigger output send a positive pulse when the CC1IF flag it to be set, as soon as a capture or a compare match occurred + 3 + + + CompareOC1 + OC1REF signal is used as trigger output + 4 + + + CompareOC2 + OC2REF signal is used as trigger output + 5 + + + CompareOC3 + OC3REF signal is used as trigger output + 6 + + + CompareOC4 + OC4REF signal is used as trigger output + 7 + + + + + CCDS + Capture/compare DMA + selection + 3 + 1 + + CCDS + read-write + + OnCompare + CCx DMA request sent when CCx event occurs + 0 + + + OnUpdate + CCx DMA request sent when update event occurs + 1 + + + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + ETP + External trigger polarity + 15 + 1 + + ETP + read-write + + NotInverted + ETR is noninverted, active at high level or rising edge + 0 + + + Inverted + ETR is inverted, active at low level or falling edge + 1 + + + + + ECE + External clock enable + 14 + 1 + + ECE + read-write + + Disabled + External clock mode 2 disabled + 0 + + + Enabled + External clock mode 2 enabled. The counter is clocked by any active edge on the ETRF signal. + 1 + + + + + ETPS + External trigger prescaler + 12 + 2 + + ETPS + read-write + + Div1 + Prescaler OFF + 0 + + + Div2 + ETRP frequency divided by 2 + 1 + + + Div4 + ETRP frequency divided by 4 + 2 + + + Div8 + ETRP frequency divided by 8 + 3 + + + + + ETF + External trigger filter + 8 + 4 + + ETF + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + MSM + Master/Slave mode + 7 + 1 + + MSM + read-write + + NoSync + No action + 0 + + + Sync + The effect of an event on the trigger input (TRGI) is delayed to allow a perfect synchronization between the current timer and its slaves (through TRGO). It is useful if we want to synchronize several timers on a single external event. + 1 + + + + + TS + Trigger selection + 4 + 3 + + TS + read-write + + ITR0 + Internal Trigger 0 (ITR0) + 0 + + + ITR1 + Internal Trigger 1 (ITR1) + 1 + + + ITR2 + Internal Trigger 2 (ITR2) + 2 + + + TI1F_ED + TI1 Edge Detector (TI1F_ED) + 4 + + + TI1FP1 + Filtered Timer Input 1 (TI1FP1) + 5 + + + TI2FP2 + Filtered Timer Input 2 (TI2FP2) + 6 + + + ETRF + External Trigger input (ETRF) + 7 + + + + + SMS + Slave mode selection + 0 + 3 + + SMS + read-write + + Disabled + Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal clock. + 0 + + + Encoder_Mode_1 + Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending on TI1FP2 level. + 1 + + + Encoder_Mode_2 + Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level. + 2 + + + Encoder_Mode_3 + Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. + 3 + + + Reset_Mode + Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and generates an update of the registers. + 4 + + + Gated_Mode + Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of the counter are controlled. + 5 + + + Trigger_Mode + Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not reset). Only the start of the counter is controlled. + 6 + + + Ext_Clock_Mode + External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter. + 7 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TDE + Trigger DMA request enable + 14 + 1 + + TDE + read-write + + Disabled + Trigger DMA request disabled + 0 + + + Enabled + Trigger DMA request enabled + 1 + + + + + CC4DE + Capture/Compare 4 DMA request + enable + 12 + 1 + + + + CC3DE + Capture/Compare 3 DMA request + enable + 11 + 1 + + + + CC2DE + Capture/Compare 2 DMA request + enable + 10 + 1 + + + + CC1DE + Capture/Compare 1 DMA request + enable + 9 + 1 + + CC1DE + read-write + + Disabled + CCx DMA request disabled + 0 + + + Enabled + CCx DMA request enabled + 1 + + + + + UDE + Update DMA request enable + 8 + 1 + + UDE + read-write + + Disabled + Update DMA request disabled + 0 + + + Enabled + Update DMA request enabled + 1 + + + + + TIE + Trigger interrupt enable + 6 + 1 + + TIE + read-write + + Disabled + Trigger interrupt disabled + 0 + + + Enabled + Trigger interrupt enabled + 1 + + + + + CC4IE + Capture/Compare 4 interrupt + enable + 4 + 1 + + + + CC3IE + Capture/Compare 3 interrupt + enable + 3 + 1 + + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + CC1IE + read-write + + Disabled + CCx interrupt disabled + 0 + + + Enabled + CCx interrupt enabled + 1 + + + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC4OF + Capture/Compare 4 overcapture + flag + 12 + 1 + zeroToClear + + read + + + write + + + + CC3OF + Capture/Compare 3 overcapture + flag + 11 + 1 + zeroToClear + + read + + + write + + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + zeroToClear + + read + + + write + + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + zeroToClear + + CC1OFR + read + + Overcapture + The counter value has been captured in TIMx_CCRx register while CCxIF flag was already set + 1 + + + + CC1OFW + write + + Clear + Clear flag + 0 + + + + + TIF + Trigger interrupt flag + 6 + 1 + zeroToClear + + TIFR + read + + NoTrigger + No trigger event occurred + 0 + + + Trigger + Trigger interrupt pending + 1 + + + + TIFW + write + + Clear + Clear flag + 0 + + + + + CC4IF + Capture/Compare 4 interrupt + flag + 4 + 1 + zeroToClear + + read + + + write + + + + CC3IF + Capture/Compare 3 interrupt + flag + 3 + 1 + zeroToClear + + read + + + write + + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + zeroToClear + + read + + + write + + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + zeroToClear + + CC1IFR + read + + Match + If CC1 is an output: The content of the counter TIMx_CNT matches the content of the TIMx_CCR1 register. If CC1 is an input: The counter value has been captured in TIMx_CCR1 register. + 1 + + + + CC1IFW + write + + Clear + Clear flag + 0 + + + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + TG + Trigger generation + 6 + 1 + + TGW + write + + Trigger + The TIF flag is set in TIMx_SR register. Related interrupt or DMA transfer can occur if enabled. + 1 + + + + + CC4G + Capture/compare 4 + generation + 4 + 1 + + + + CC3G + Capture/compare 3 + generation + 3 + 1 + + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + CC1GW + write + + Trigger + If CC1 is an output: CC1IF flag is set, Corresponding interrupt or DMA request is sent if enabled. If CC1 is an input: The current value of the counter is captured in TIMx_CCR1 register. + 1 + + + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2CE + OC2CE + 15 + 1 + + + OC2M + OC2M + 12 + 3 + + + + OC2PE + OC2PE + 11 + 1 + + OC2PE + read-write + + Disabled + Preload register on CCR2 disabled. New values written to CCR2 are taken into account immediately + 0 + + + Enabled + Preload register on CCR2 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC2FE + OC2FE + 10 + 1 + + + CC2S + CC2S + 8 + 2 + + CC2S + read-write + + Output + CC2 channel is configured as output + 0 + + + + + OC1CE + OC1CE + 7 + 1 + + + OC1M + OC1M + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + OC1PE + 3 + 1 + + OC1PE + read-write + + Disabled + Preload register on CCR1 disabled. New values written to CCR1 are taken into account immediately + 0 + + + Enabled + Preload register on CCR1 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC1FE + OC1FE + 2 + 1 + + + CC1S + CC1S + 0 + 2 + + CC1S + read-write + + Output + CC1 channel is configured as output + 0 + + + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 4 + + + 0 + 15 + + + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + TI2 + CC2 channel is configured as input, IC2 is mapped on TI2 + 1 + + + TI1 + CC2 channel is configured as input, IC2 is mapped on TI1 + 2 + + + TRC + CC2 channel is configured as input, IC2 is mapped on TRC + 3 + + + + + IC1F + Input capture 1 filter + 4 + 4 + + IC1F + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + TI1 + CC1 channel is configured as input, IC1 is mapped on TI1 + 1 + + + TI2 + CC1 channel is configured as input, IC1 is mapped on TI2 + 2 + + + TRC + CC1 channel is configured as input, IC1 is mapped on TRC + 3 + + + + + + + CCMR2_Output + CCMR2_Output + capture/compare mode register 2 (output + mode) + 0x1C + 0x20 + read-write + 0x00000000 + + + OC4CE + O24CE + 15 + 1 + + + OC4M + OC4M + 12 + 3 + + + + OC4PE + OC4PE + 11 + 1 + + OC4PE + read-write + + Disabled + Preload register on CCR4 disabled. New values written to CCR4 are taken into account immediately + 0 + + + Enabled + Preload register on CCR4 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC4FE + OC4FE + 10 + 1 + + + CC4S + CC4S + 8 + 2 + + CC4S + read-write + + Output + CC4 channel is configured as output + 0 + + + + + OC3CE + OC3CE + 7 + 1 + + + OC3M + OC3M + 4 + 3 + + OC3M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC3PE + OC3PE + 3 + 1 + + OC3PE + read-write + + Disabled + Preload register on CCR3 disabled. New values written to CCR3 are taken into account immediately + 0 + + + Enabled + Preload register on CCR3 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC3FE + OC3FE + 2 + 1 + + + CC3S + CC3S + 0 + 2 + + CC3S + read-write + + Output + CC3 channel is configured as output + 0 + + + + + + + CCMR2_Input + CCMR2_Input + capture/compare mode register 2 (input + mode) + CCMR2_Output + 0x1C + 0x20 + read-write + 0x00000000 + + + IC4F + Input capture 4 filter + 12 + 4 + + + 0 + 15 + + + + + IC4PSC + Input capture 4 prescaler + 10 + 2 + + + 0 + 3 + + + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + TI4 + CC4 channel is configured as input, IC4 is mapped on TI4 + 1 + + + TI3 + CC4 channel is configured as input, IC4 is mapped on TI3 + 2 + + + TRC + CC4 channel is configured as input, IC4 is mapped on TRC + 3 + + + + + IC3F + Input capture 3 filter + 4 + 4 + + + 0 + 15 + + + + + IC3PSC + Input capture 3 prescaler + 2 + 2 + + + 0 + 3 + + + + + CC3S + Capture/compare 3 + selection + 0 + 2 + + CC3S + read-write + + TI3 + CC3 channel is configured as input, IC3 is mapped on TI3 + 1 + + + TI4 + CC3 channel is configured as input, IC3 is mapped on TI4 + 2 + + + TRC + CC3 channel is configured as input, IC3 is mapped on TRC + 3 + + + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC4NP + Capture/Compare 4 output + Polarity + 15 + 1 + + + CC4P + Capture/Compare 3 output + Polarity + 13 + 1 + + + CC4E + Capture/Compare 4 output + enable + 12 + 1 + + + CC3NP + Capture/Compare 3 output + Polarity + 11 + 1 + + + CC3P + Capture/Compare 3 output + Polarity + 9 + 1 + + + CC3E + Capture/Compare 3 output + enable + 8 + 1 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + Counter value + 0 + 32 + + + 0 + 4294967295 + + + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 32 + + + 0 + 4294967295 + + + + + + + 4 + 0x4 + 1-4 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 32 + + + 0 + 4294967295 + + + + + + + DCR + DCR + DMA control register + 0x48 + 0x20 + read-write + 0x00000000 + + + DBL + DMA burst length + 8 + 5 + + + 0 + 18 + + + + + DBA + DMA base address + 0 + 5 + + + 0 + 31 + + + + + + + DMAR + DMAR + DMA address for full transfer + 0x4C + 0x20 + read-write + 0x00000000 + + + DMAB + DMA register for burst + accesses + 0 + 16 + + + + + OR + OR + TIM5 option register + 0x50 + 0x20 + read-write + 0x00000000 + + + ITR1_RMP + Timer Input 4 remap + 10 + 2 + + + + + + + TIM3 + General purpose timers + TIM + 0x40000400 + + 0x0 + 0x400 + registers + + + SPI4 + SPI4 global interrupt + 84 + + + TIM4 + TIM4 global interrupt + 30 + + + TIM5 + TIM5 global interrupt + 50 + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + CMS + Center-aligned mode + selection + 5 + 2 + + CMS + read-write + + EdgeAligned + The counter counts up or down depending on the direction bit + 0 + + + CenterAligned1 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting down. + 1 + + + CenterAligned2 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting up. + 2 + + + CenterAligned3 + The counter counts up and down alternatively. Output compare interrupt flags are set both when the counter is counting up or down. + 3 + + + + + DIR + Direction + 4 + 1 + + DIR + read-write + + Up + Counter used as upcounter + 0 + + + Down + Counter used as downcounter + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + TI1S + TI1 selection + 7 + 1 + + TI1S + read-write + + Normal + The TIMx_CH1 pin is connected to TI1 input + 0 + + + XOR + The TIMx_CH1, CH2, CH3 pins are connected to TI1 input + 1 + + + + + MMS + Master mode selection + 4 + 3 + + MMS + read-write + + Reset + The UG bit from the TIMx_EGR register is used as trigger output + 0 + + + Enable + The counter enable signal, CNT_EN, is used as trigger output + 1 + + + Update + The update event is selected as trigger output + 2 + + + ComparePulse + The trigger output send a positive pulse when the CC1IF flag it to be set, as soon as a capture or a compare match occurred + 3 + + + CompareOC1 + OC1REF signal is used as trigger output + 4 + + + CompareOC2 + OC2REF signal is used as trigger output + 5 + + + CompareOC3 + OC3REF signal is used as trigger output + 6 + + + CompareOC4 + OC4REF signal is used as trigger output + 7 + + + + + CCDS + Capture/compare DMA + selection + 3 + 1 + + CCDS + read-write + + OnCompare + CCx DMA request sent when CCx event occurs + 0 + + + OnUpdate + CCx DMA request sent when update event occurs + 1 + + + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + ETP + External trigger polarity + 15 + 1 + + ETP + read-write + + NotInverted + ETR is noninverted, active at high level or rising edge + 0 + + + Inverted + ETR is inverted, active at low level or falling edge + 1 + + + + + ECE + External clock enable + 14 + 1 + + ECE + read-write + + Disabled + External clock mode 2 disabled + 0 + + + Enabled + External clock mode 2 enabled. The counter is clocked by any active edge on the ETRF signal. + 1 + + + + + ETPS + External trigger prescaler + 12 + 2 + + ETPS + read-write + + Div1 + Prescaler OFF + 0 + + + Div2 + ETRP frequency divided by 2 + 1 + + + Div4 + ETRP frequency divided by 4 + 2 + + + Div8 + ETRP frequency divided by 8 + 3 + + + + + ETF + External trigger filter + 8 + 4 + + ETF + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + MSM + Master/Slave mode + 7 + 1 + + MSM + read-write + + NoSync + No action + 0 + + + Sync + The effect of an event on the trigger input (TRGI) is delayed to allow a perfect synchronization between the current timer and its slaves (through TRGO). It is useful if we want to synchronize several timers on a single external event. + 1 + + + + + TS + Trigger selection + 4 + 3 + + TS + read-write + + ITR0 + Internal Trigger 0 (ITR0) + 0 + + + ITR1 + Internal Trigger 1 (ITR1) + 1 + + + ITR2 + Internal Trigger 2 (ITR2) + 2 + + + TI1F_ED + TI1 Edge Detector (TI1F_ED) + 4 + + + TI1FP1 + Filtered Timer Input 1 (TI1FP1) + 5 + + + TI2FP2 + Filtered Timer Input 2 (TI2FP2) + 6 + + + ETRF + External Trigger input (ETRF) + 7 + + + + + SMS + Slave mode selection + 0 + 3 + + SMS + read-write + + Disabled + Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal clock. + 0 + + + Encoder_Mode_1 + Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending on TI1FP2 level. + 1 + + + Encoder_Mode_2 + Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level. + 2 + + + Encoder_Mode_3 + Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. + 3 + + + Reset_Mode + Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and generates an update of the registers. + 4 + + + Gated_Mode + Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of the counter are controlled. + 5 + + + Trigger_Mode + Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not reset). Only the start of the counter is controlled. + 6 + + + Ext_Clock_Mode + External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter. + 7 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TDE + Trigger DMA request enable + 14 + 1 + + TDE + read-write + + Disabled + Trigger DMA request disabled + 0 + + + Enabled + Trigger DMA request enabled + 1 + + + + + CC4DE + Capture/Compare 4 DMA request + enable + 12 + 1 + + + + CC3DE + Capture/Compare 3 DMA request + enable + 11 + 1 + + + + CC2DE + Capture/Compare 2 DMA request + enable + 10 + 1 + + + + CC1DE + Capture/Compare 1 DMA request + enable + 9 + 1 + + CC1DE + read-write + + Disabled + CCx DMA request disabled + 0 + + + Enabled + CCx DMA request enabled + 1 + + + + + UDE + Update DMA request enable + 8 + 1 + + UDE + read-write + + Disabled + Update DMA request disabled + 0 + + + Enabled + Update DMA request enabled + 1 + + + + + TIE + Trigger interrupt enable + 6 + 1 + + TIE + read-write + + Disabled + Trigger interrupt disabled + 0 + + + Enabled + Trigger interrupt enabled + 1 + + + + + CC4IE + Capture/Compare 4 interrupt + enable + 4 + 1 + + + + CC3IE + Capture/Compare 3 interrupt + enable + 3 + 1 + + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + CC1IE + read-write + + Disabled + CCx interrupt disabled + 0 + + + Enabled + CCx interrupt enabled + 1 + + + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC4OF + Capture/Compare 4 overcapture + flag + 12 + 1 + zeroToClear + + read + + + write + + + + CC3OF + Capture/Compare 3 overcapture + flag + 11 + 1 + zeroToClear + + read + + + write + + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + zeroToClear + + read + + + write + + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + zeroToClear + + CC1OFR + read + + Overcapture + The counter value has been captured in TIMx_CCRx register while CCxIF flag was already set + 1 + + + + CC1OFW + write + + Clear + Clear flag + 0 + + + + + TIF + Trigger interrupt flag + 6 + 1 + zeroToClear + + TIFR + read + + NoTrigger + No trigger event occurred + 0 + + + Trigger + Trigger interrupt pending + 1 + + + + TIFW + write + + Clear + Clear flag + 0 + + + + + CC4IF + Capture/Compare 4 interrupt + flag + 4 + 1 + zeroToClear + + read + + + write + + + + CC3IF + Capture/Compare 3 interrupt + flag + 3 + 1 + zeroToClear + + read + + + write + + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + zeroToClear + + read + + + write + + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + zeroToClear + + CC1IFR + read + + Match + If CC1 is an output: The content of the counter TIMx_CNT matches the content of the TIMx_CCR1 register. If CC1 is an input: The counter value has been captured in TIMx_CCR1 register. + 1 + + + + CC1IFW + write + + Clear + Clear flag + 0 + + + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + TG + Trigger generation + 6 + 1 + + TGW + write + + Trigger + The TIF flag is set in TIMx_SR register. Related interrupt or DMA transfer can occur if enabled. + 1 + + + + + CC4G + Capture/compare 4 + generation + 4 + 1 + + + + CC3G + Capture/compare 3 + generation + 3 + 1 + + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + CC1GW + write + + Trigger + If CC1 is an output: CC1IF flag is set, Corresponding interrupt or DMA request is sent if enabled. If CC1 is an input: The current value of the counter is captured in TIMx_CCR1 register. + 1 + + + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2CE + OC2CE + 15 + 1 + + + OC2M + OC2M + 12 + 3 + + + + OC2PE + OC2PE + 11 + 1 + + OC2PE + read-write + + Disabled + Preload register on CCR2 disabled. New values written to CCR2 are taken into account immediately + 0 + + + Enabled + Preload register on CCR2 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC2FE + OC2FE + 10 + 1 + + + CC2S + CC2S + 8 + 2 + + CC2S + read-write + + Output + CC2 channel is configured as output + 0 + + + + + OC1CE + OC1CE + 7 + 1 + + + OC1M + OC1M + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + OC1PE + 3 + 1 + + OC1PE + read-write + + Disabled + Preload register on CCR1 disabled. New values written to CCR1 are taken into account immediately + 0 + + + Enabled + Preload register on CCR1 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC1FE + OC1FE + 2 + 1 + + + CC1S + CC1S + 0 + 2 + + CC1S + read-write + + Output + CC1 channel is configured as output + 0 + + + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 4 + + + 0 + 15 + + + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + TI2 + CC2 channel is configured as input, IC2 is mapped on TI2 + 1 + + + TI1 + CC2 channel is configured as input, IC2 is mapped on TI1 + 2 + + + TRC + CC2 channel is configured as input, IC2 is mapped on TRC + 3 + + + + + IC1F + Input capture 1 filter + 4 + 4 + + IC1F + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + TI1 + CC1 channel is configured as input, IC1 is mapped on TI1 + 1 + + + TI2 + CC1 channel is configured as input, IC1 is mapped on TI2 + 2 + + + TRC + CC1 channel is configured as input, IC1 is mapped on TRC + 3 + + + + + + + CCMR2_Output + CCMR2_Output + capture/compare mode register 2 (output + mode) + 0x1C + 0x20 + read-write + 0x00000000 + + + OC4CE + O24CE + 15 + 1 + + + OC4M + OC4M + 12 + 3 + + + + OC4PE + OC4PE + 11 + 1 + + OC4PE + read-write + + Disabled + Preload register on CCR4 disabled. New values written to CCR4 are taken into account immediately + 0 + + + Enabled + Preload register on CCR4 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC4FE + OC4FE + 10 + 1 + + + CC4S + CC4S + 8 + 2 + + CC4S + read-write + + Output + CC4 channel is configured as output + 0 + + + + + OC3CE + OC3CE + 7 + 1 + + + OC3M + OC3M + 4 + 3 + + OC3M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC3PE + OC3PE + 3 + 1 + + OC3PE + read-write + + Disabled + Preload register on CCR3 disabled. New values written to CCR3 are taken into account immediately + 0 + + + Enabled + Preload register on CCR3 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC3FE + OC3FE + 2 + 1 + + + CC3S + CC3S + 0 + 2 + + CC3S + read-write + + Output + CC3 channel is configured as output + 0 + + + + + + + CCMR2_Input + CCMR2_Input + capture/compare mode register 2 (input + mode) + CCMR2_Output + 0x1C + 0x20 + read-write + 0x00000000 + + + IC4F + Input capture 4 filter + 12 + 4 + + + 0 + 15 + + + + + IC4PSC + Input capture 4 prescaler + 10 + 2 + + + 0 + 3 + + + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + TI4 + CC4 channel is configured as input, IC4 is mapped on TI4 + 1 + + + TI3 + CC4 channel is configured as input, IC4 is mapped on TI3 + 2 + + + TRC + CC4 channel is configured as input, IC4 is mapped on TRC + 3 + + + + + IC3F + Input capture 3 filter + 4 + 4 + + + 0 + 15 + + + + + IC3PSC + Input capture 3 prescaler + 2 + 2 + + + 0 + 3 + + + + + CC3S + Capture/compare 3 + selection + 0 + 2 + + CC3S + read-write + + TI3 + CC3 channel is configured as input, IC3 is mapped on TI3 + 1 + + + TI4 + CC3 channel is configured as input, IC3 is mapped on TI4 + 2 + + + TRC + CC3 channel is configured as input, IC3 is mapped on TRC + 3 + + + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC4NP + Capture/Compare 4 output + Polarity + 15 + 1 + + + CC4P + Capture/Compare 3 output + Polarity + 13 + 1 + + + CC4E + Capture/Compare 4 output + enable + 12 + 1 + + + CC3NP + Capture/Compare 3 output + Polarity + 11 + 1 + + + CC3P + Capture/Compare 3 output + Polarity + 9 + 1 + + + CC3E + Capture/Compare 3 output + enable + 8 + 1 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + Counter value + 0 + 16 + + + 0 + 65535 + + + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + 0 + 65535 + + + + + + + 4 + 0x4 + 1-4 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + 0 + 65535 + + + + + + + DCR + DCR + DMA control register + 0x48 + 0x20 + read-write + 0x00000000 + + + DBL + DMA burst length + 8 + 5 + + + 0 + 18 + + + + + DBA + DMA base address + 0 + 5 + + + 0 + 31 + + + + + + + DMAR + DMAR + DMA address for full transfer + 0x4C + 0x20 + read-write + 0x00000000 + + + DMAB + DMA register for burst + accesses + 0 + 16 + + + + + + + TIM4 + TIM + 0x40000800 + + + TIM5 + General-purpose-timers + TIM + 0x40000C00 + + 0x0 + 0x400 + registers + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + CMS + Center-aligned mode + selection + 5 + 2 + + CMS + read-write + + EdgeAligned + The counter counts up or down depending on the direction bit + 0 + + + CenterAligned1 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting down. + 1 + + + CenterAligned2 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting up. + 2 + + + CenterAligned3 + The counter counts up and down alternatively. Output compare interrupt flags are set both when the counter is counting up or down. + 3 + + + + + DIR + Direction + 4 + 1 + + DIR + read-write + + Up + Counter used as upcounter + 0 + + + Down + Counter used as downcounter + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + TI1S + TI1 selection + 7 + 1 + + TI1S + read-write + + Normal + The TIMx_CH1 pin is connected to TI1 input + 0 + + + XOR + The TIMx_CH1, CH2, CH3 pins are connected to TI1 input + 1 + + + + + MMS + Master mode selection + 4 + 3 + + MMS + read-write + + Reset + The UG bit from the TIMx_EGR register is used as trigger output + 0 + + + Enable + The counter enable signal, CNT_EN, is used as trigger output + 1 + + + Update + The update event is selected as trigger output + 2 + + + ComparePulse + The trigger output send a positive pulse when the CC1IF flag it to be set, as soon as a capture or a compare match occurred + 3 + + + CompareOC1 + OC1REF signal is used as trigger output + 4 + + + CompareOC2 + OC2REF signal is used as trigger output + 5 + + + CompareOC3 + OC3REF signal is used as trigger output + 6 + + + CompareOC4 + OC4REF signal is used as trigger output + 7 + + + + + CCDS + Capture/compare DMA + selection + 3 + 1 + + CCDS + read-write + + OnCompare + CCx DMA request sent when CCx event occurs + 0 + + + OnUpdate + CCx DMA request sent when update event occurs + 1 + + + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + ETP + External trigger polarity + 15 + 1 + + ETP + read-write + + NotInverted + ETR is noninverted, active at high level or rising edge + 0 + + + Inverted + ETR is inverted, active at low level or falling edge + 1 + + + + + ECE + External clock enable + 14 + 1 + + ECE + read-write + + Disabled + External clock mode 2 disabled + 0 + + + Enabled + External clock mode 2 enabled. The counter is clocked by any active edge on the ETRF signal. + 1 + + + + + ETPS + External trigger prescaler + 12 + 2 + + ETPS + read-write + + Div1 + Prescaler OFF + 0 + + + Div2 + ETRP frequency divided by 2 + 1 + + + Div4 + ETRP frequency divided by 4 + 2 + + + Div8 + ETRP frequency divided by 8 + 3 + + + + + ETF + External trigger filter + 8 + 4 + + ETF + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + MSM + Master/Slave mode + 7 + 1 + + MSM + read-write + + NoSync + No action + 0 + + + Sync + The effect of an event on the trigger input (TRGI) is delayed to allow a perfect synchronization between the current timer and its slaves (through TRGO). It is useful if we want to synchronize several timers on a single external event. + 1 + + + + + TS + Trigger selection + 4 + 3 + + TS + read-write + + ITR0 + Internal Trigger 0 (ITR0) + 0 + + + ITR1 + Internal Trigger 1 (ITR1) + 1 + + + ITR2 + Internal Trigger 2 (ITR2) + 2 + + + TI1F_ED + TI1 Edge Detector (TI1F_ED) + 4 + + + TI1FP1 + Filtered Timer Input 1 (TI1FP1) + 5 + + + TI2FP2 + Filtered Timer Input 2 (TI2FP2) + 6 + + + ETRF + External Trigger input (ETRF) + 7 + + + + + SMS + Slave mode selection + 0 + 3 + + SMS + read-write + + Disabled + Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal clock. + 0 + + + Encoder_Mode_1 + Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending on TI1FP2 level. + 1 + + + Encoder_Mode_2 + Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level. + 2 + + + Encoder_Mode_3 + Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. + 3 + + + Reset_Mode + Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and generates an update of the registers. + 4 + + + Gated_Mode + Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of the counter are controlled. + 5 + + + Trigger_Mode + Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not reset). Only the start of the counter is controlled. + 6 + + + Ext_Clock_Mode + External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter. + 7 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TDE + Trigger DMA request enable + 14 + 1 + + TDE + read-write + + Disabled + Trigger DMA request disabled + 0 + + + Enabled + Trigger DMA request enabled + 1 + + + + + CC4DE + Capture/Compare 4 DMA request + enable + 12 + 1 + + + + CC3DE + Capture/Compare 3 DMA request + enable + 11 + 1 + + + + CC2DE + Capture/Compare 2 DMA request + enable + 10 + 1 + + + + CC1DE + Capture/Compare 1 DMA request + enable + 9 + 1 + + CC1DE + read-write + + Disabled + CCx DMA request disabled + 0 + + + Enabled + CCx DMA request enabled + 1 + + + + + UDE + Update DMA request enable + 8 + 1 + + UDE + read-write + + Disabled + Update DMA request disabled + 0 + + + Enabled + Update DMA request enabled + 1 + + + + + TIE + Trigger interrupt enable + 6 + 1 + + TIE + read-write + + Disabled + Trigger interrupt disabled + 0 + + + Enabled + Trigger interrupt enabled + 1 + + + + + CC4IE + Capture/Compare 4 interrupt + enable + 4 + 1 + + + + CC3IE + Capture/Compare 3 interrupt + enable + 3 + 1 + + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + CC1IE + read-write + + Disabled + CCx interrupt disabled + 0 + + + Enabled + CCx interrupt enabled + 1 + + + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC4OF + Capture/Compare 4 overcapture + flag + 12 + 1 + zeroToClear + + read + + + write + + + + CC3OF + Capture/Compare 3 overcapture + flag + 11 + 1 + zeroToClear + + read + + + write + + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + zeroToClear + + read + + + write + + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + zeroToClear + + CC1OFR + read + + Overcapture + The counter value has been captured in TIMx_CCRx register while CCxIF flag was already set + 1 + + + + CC1OFW + write + + Clear + Clear flag + 0 + + + + + TIF + Trigger interrupt flag + 6 + 1 + zeroToClear + + TIFR + read + + NoTrigger + No trigger event occurred + 0 + + + Trigger + Trigger interrupt pending + 1 + + + + TIFW + write + + Clear + Clear flag + 0 + + + + + CC4IF + Capture/Compare 4 interrupt + flag + 4 + 1 + zeroToClear + + read + + + write + + + + CC3IF + Capture/Compare 3 interrupt + flag + 3 + 1 + zeroToClear + + read + + + write + + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + zeroToClear + + read + + + write + + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + zeroToClear + + CC1IFR + read + + Match + If CC1 is an output: The content of the counter TIMx_CNT matches the content of the TIMx_CCR1 register. If CC1 is an input: The counter value has been captured in TIMx_CCR1 register. + 1 + + + + CC1IFW + write + + Clear + Clear flag + 0 + + + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + TG + Trigger generation + 6 + 1 + + TGW + write + + Trigger + The TIF flag is set in TIMx_SR register. Related interrupt or DMA transfer can occur if enabled. + 1 + + + + + CC4G + Capture/compare 4 + generation + 4 + 1 + + + + CC3G + Capture/compare 3 + generation + 3 + 1 + + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + CC1GW + write + + Trigger + If CC1 is an output: CC1IF flag is set, Corresponding interrupt or DMA request is sent if enabled. If CC1 is an input: The current value of the counter is captured in TIMx_CCR1 register. + 1 + + + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2CE + OC2CE + 15 + 1 + + + OC2M + OC2M + 12 + 3 + + + + OC2PE + OC2PE + 11 + 1 + + OC2PE + read-write + + Disabled + Preload register on CCR2 disabled. New values written to CCR2 are taken into account immediately + 0 + + + Enabled + Preload register on CCR2 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC2FE + OC2FE + 10 + 1 + + + CC2S + CC2S + 8 + 2 + + CC2S + read-write + + Output + CC2 channel is configured as output + 0 + + + + + OC1CE + OC1CE + 7 + 1 + + + OC1M + OC1M + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + OC1PE + 3 + 1 + + OC1PE + read-write + + Disabled + Preload register on CCR1 disabled. New values written to CCR1 are taken into account immediately + 0 + + + Enabled + Preload register on CCR1 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC1FE + OC1FE + 2 + 1 + + + CC1S + CC1S + 0 + 2 + + CC1S + read-write + + Output + CC1 channel is configured as output + 0 + + + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 4 + + + 0 + 15 + + + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + TI2 + CC2 channel is configured as input, IC2 is mapped on TI2 + 1 + + + TI1 + CC2 channel is configured as input, IC2 is mapped on TI1 + 2 + + + TRC + CC2 channel is configured as input, IC2 is mapped on TRC + 3 + + + + + IC1F + Input capture 1 filter + 4 + 4 + + IC1F + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + TI1 + CC1 channel is configured as input, IC1 is mapped on TI1 + 1 + + + TI2 + CC1 channel is configured as input, IC1 is mapped on TI2 + 2 + + + TRC + CC1 channel is configured as input, IC1 is mapped on TRC + 3 + + + + + + + CCMR2_Output + CCMR2_Output + capture/compare mode register 2 (output + mode) + 0x1C + 0x20 + read-write + 0x00000000 + + + OC4CE + O24CE + 15 + 1 + + + OC4M + OC4M + 12 + 3 + + + + OC4PE + OC4PE + 11 + 1 + + OC4PE + read-write + + Disabled + Preload register on CCR4 disabled. New values written to CCR4 are taken into account immediately + 0 + + + Enabled + Preload register on CCR4 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC4FE + OC4FE + 10 + 1 + + + CC4S + CC4S + 8 + 2 + + CC4S + read-write + + Output + CC4 channel is configured as output + 0 + + + + + OC3CE + OC3CE + 7 + 1 + + + OC3M + OC3M + 4 + 3 + + OC3M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC3PE + OC3PE + 3 + 1 + + OC3PE + read-write + + Disabled + Preload register on CCR3 disabled. New values written to CCR3 are taken into account immediately + 0 + + + Enabled + Preload register on CCR3 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC3FE + OC3FE + 2 + 1 + + + CC3S + CC3S + 0 + 2 + + CC3S + read-write + + Output + CC3 channel is configured as output + 0 + + + + + + + CCMR2_Input + CCMR2_Input + capture/compare mode register 2 (input + mode) + CCMR2_Output + 0x1C + 0x20 + read-write + 0x00000000 + + + IC4F + Input capture 4 filter + 12 + 4 + + + 0 + 15 + + + + + IC4PSC + Input capture 4 prescaler + 10 + 2 + + + 0 + 3 + + + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + TI4 + CC4 channel is configured as input, IC4 is mapped on TI4 + 1 + + + TI3 + CC4 channel is configured as input, IC4 is mapped on TI3 + 2 + + + TRC + CC4 channel is configured as input, IC4 is mapped on TRC + 3 + + + + + IC3F + Input capture 3 filter + 4 + 4 + + + 0 + 15 + + + + + IC3PSC + Input capture 3 prescaler + 2 + 2 + + + 0 + 3 + + + + + CC3S + Capture/compare 3 + selection + 0 + 2 + + CC3S + read-write + + TI3 + CC3 channel is configured as input, IC3 is mapped on TI3 + 1 + + + TI4 + CC3 channel is configured as input, IC3 is mapped on TI4 + 2 + + + TRC + CC3 channel is configured as input, IC3 is mapped on TRC + 3 + + + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC4NP + Capture/Compare 4 output + Polarity + 15 + 1 + + + CC4P + Capture/Compare 3 output + Polarity + 13 + 1 + + + CC4E + Capture/Compare 4 output + enable + 12 + 1 + + + CC3NP + Capture/Compare 3 output + Polarity + 11 + 1 + + + CC3P + Capture/Compare 3 output + Polarity + 9 + 1 + + + CC3E + Capture/Compare 3 output + enable + 8 + 1 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + Counter value + 0 + 32 + + + 0 + 4294967295 + + + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 32 + + + 0 + 4294967295 + + + + + + + 4 + 0x4 + 1-4 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 32 + + + 0 + 4294967295 + + + + + + + DCR + DCR + DMA control register + 0x48 + 0x20 + read-write + 0x00000000 + + + DBL + DMA burst length + 8 + 5 + + + 0 + 18 + + + + + DBA + DMA base address + 0 + 5 + + + 0 + 31 + + + + + + + DMAR + DMAR + DMA address for full transfer + 0x4C + 0x20 + read-write + 0x00000000 + + + DMAB + DMA register for burst + accesses + 0 + 16 + + + + + OR + OR + TIM5 option register + 0x50 + 0x20 + read-write + 0x00000000 + + + IT4_RMP + Timer Input 4 remap + 6 + 2 + + + + + + + TIM9 + General purpose timers + TIM + 0x40014000 + + 0x0 + 0x400 + registers + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + MMS + Master mode selection + 4 + 3 + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + MSM + Master/Slave mode + 7 + 1 + + + TS + Trigger selection + 4 + 3 + + + SMS + Slave mode selection + 0 + 3 + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TIE + Trigger interrupt enable + 6 + 1 + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + + + TIF + Trigger interrupt flag + 6 + 1 + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + TG + Trigger generation + 6 + 1 + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2M + Output Compare 2 mode + 12 + 3 + + + + OC2PE + Output Compare 2 preload + enable + 11 + 1 + + + OC2FE + Output Compare 2 fast + enable + 10 + 1 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + + OC1M + Output Compare 1 mode + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + Output Compare 1 preload + enable + 3 + 1 + + + OC1FE + Output Compare 1 fast + enable + 2 + 1 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 3 + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + + IC1F + Input capture 1 filter + 4 + 3 + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + counter value + 0 + 16 + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + + + 2 + 0x4 + 1-2 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + + + + + USART1 + Universal synchronous asynchronous receiver + transmitter + USART + 0x40011000 + + 0x0 + 0x400 + registers + + + OTG_FS_WKUP + USB On-The-Go FS Wakeup through EXTI line + interrupt + 42 + + + OTG_FS + USB On The Go FS global + interrupt + 67 + + + USART1 + USART1 global interrupt + 37 + + + USART2 + USART2 global interrupt + 38 + + + USART6 + USART6 global interrupt + 71 + + + + SR + SR + Status register + 0x0 + 0x20 + 0x00C00000 + + + CTS + CTS flag + 9 + 1 + read-write + + + LBD + LIN break detection flag + 8 + 1 + read-write + + + TXE + Transmit data register + empty + 7 + 1 + read-only + + + TC + Transmission complete + 6 + 1 + read-write + + + RXNE + Read data register not + empty + 5 + 1 + read-write + + + IDLE + IDLE line detected + 4 + 1 + read-only + + + ORE + Overrun error + 3 + 1 + read-only + + + NF + Noise detected flag + 2 + 1 + read-only + + + FE + Framing error + 1 + 1 + read-only + + + PE + Parity error + 0 + 1 + read-only + + + + + DR + DR + Data register + 0x4 + 0x20 + read-write + 0x00000000 + + + DR + Data value + 0 + 9 + + + 0 + 511 + + + + + + + BRR + BRR + Baud rate register + 0x8 + 0x20 + read-write + 0x00000000 + + + DIV_Mantissa + mantissa of USARTDIV + 4 + 12 + + + 0 + 4095 + + + + + DIV_Fraction + fraction of USARTDIV + 0 + 4 + + + 0 + 15 + + + + + + + CR1 + CR1 + Control register 1 + 0xC + 0x20 + read-write + 0x00000000 + + + OVER8 + Oversampling mode + 15 + 1 + + OVER8 + read-write + + Oversample16 + Oversampling by 16 + 0 + + + Oversample8 + Oversampling by 8 + 1 + + + + + UE + USART enable + 13 + 1 + + UE + read-write + + Disabled + USART prescaler and outputs disabled + 0 + + + Enabled + USART enabled + 1 + + + + + M + Word length + 12 + 1 + + M + read-write + + M8 + 8 data bits + 0 + + + M9 + 9 data bits + 1 + + + + + WAKE + Wakeup method + 11 + 1 + + WAKE + read-write + + IdleLine + USART wakeup on idle line + 0 + + + AddressMark + USART wakeup on address mark + 1 + + + + + PCE + Parity control enable + 10 + 1 + + PCE + read-write + + Disabled + Parity control disabled + 0 + + + Enabled + Parity control enabled + 1 + + + + + PS + Parity selection + 9 + 1 + + PS + read-write + + Even + Even parity + 0 + + + Odd + Odd parity + 1 + + + + + PEIE + PE interrupt enable + 8 + 1 + + PEIE + read-write + + Disabled + PE interrupt disabled + 0 + + + Enabled + PE interrupt enabled + 1 + + + + + TXEIE + TXE interrupt enable + 7 + 1 + + TXEIE + read-write + + Disabled + TXE interrupt disabled + 0 + + + Enabled + TXE interrupt enabled + 1 + + + + + TCIE + Transmission complete interrupt + enable + 6 + 1 + + TCIE + read-write + + Disabled + TC interrupt disabled + 0 + + + Enabled + TC interrupt enabled + 1 + + + + + RXNEIE + RXNE interrupt enable + 5 + 1 + + RXNEIE + read-write + + Disabled + RXNE interrupt disabled + 0 + + + Enabled + RXNE interrupt enabled + 1 + + + + + IDLEIE + IDLE interrupt enable + 4 + 1 + + IDLEIE + read-write + + Disabled + IDLE interrupt disabled + 0 + + + Enabled + IDLE interrupt enabled + 1 + + + + + TE + Transmitter enable + 3 + 1 + + TE + read-write + + Disabled + Transmitter disabled + 0 + + + Enabled + Transmitter enabled + 1 + + + + + RE + Receiver enable + 2 + 1 + + RE + read-write + + Disabled + Receiver disabled + 0 + + + Enabled + Receiver enabled + 1 + + + + + RWU + Receiver wakeup + 1 + 1 + + RWU + read-write + + Active + Receiver in active mode + 0 + + + Mute + Receiver in mute mode + 1 + + + + + SBK + Send break + 0 + 1 + + SBK + read-write + + NoBreak + No break character is transmitted + 0 + + + Break + Break character transmitted + 1 + + + + + + + CR2 + CR2 + Control register 2 + 0x10 + 0x20 + read-write + 0x00000000 + + + LINEN + LIN mode enable + 14 + 1 + + LINEN + read-write + + Disabled + LIN mode disabled + 0 + + + Enabled + LIN mode enabled + 1 + + + + + STOP + STOP bits + 12 + 2 + + STOP + read-write + + Stop1 + 1 stop bit + 0 + + + Stop0p5 + 0.5 stop bits + 1 + + + Stop2 + 2 stop bits + 2 + + + Stop1p5 + 1.5 stop bits + 3 + + + + + CLKEN + Clock enable + 11 + 1 + + CLKEN + read-write + + Disabled + CK pin disabled + 0 + + + Enabled + CK pin enabled + 1 + + + + + CPOL + Clock polarity + 10 + 1 + + CPOL + read-write + + Low + Steady low value on CK pin outside transmission window + 0 + + + High + Steady high value on CK pin outside transmission window + 1 + + + + + CPHA + Clock phase + 9 + 1 + + CPHA + read-write + + First + The first clock transition is the first data capture edge + 0 + + + Second + The second clock transition is the first data capture edge + 1 + + + + + LBCL + Last bit clock pulse + 8 + 1 + + + LBDIE + LIN break detection interrupt + enable + 6 + 1 + + LBDIE + read-write + + Disabled + LIN break detection interrupt disabled + 0 + + + Enabled + LIN break detection interrupt enabled + 1 + + + + + LBDL + lin break detection length + 5 + 1 + + LBDL + read-write + + LBDL10 + 10-bit break detection + 0 + + + LBDL11 + 11-bit break detection + 1 + + + + + ADD + Address of the USART node + 0 + 4 + + + 0 + 15 + + + + + + + CR3 + CR3 + Control register 3 + 0x14 + 0x20 + read-write + 0x00000000 + + + ONEBIT + One sample bit method + enable + 11 + 1 + + ONEBIT + read-write + + Sample3 + Three sample bit method + 0 + + + Sample1 + One sample bit method + 1 + + + + + CTSIE + CTS interrupt enable + 10 + 1 + + CTSIE + read-write + + Disabled + CTS interrupt disabled + 0 + + + Enabled + CTS interrupt enabled + 1 + + + + + CTSE + CTS enable + 9 + 1 + + CTSE + read-write + + Disabled + CTS hardware flow control disabled + 0 + + + Enabled + CTS hardware flow control enabled + 1 + + + + + RTSE + RTS enable + 8 + 1 + + RTSE + read-write + + Disabled + RTS hardware flow control disabled + 0 + + + Enabled + RTS hardware flow control enabled + 1 + + + + + DMAT + DMA enable transmitter + 7 + 1 + + DMAT + read-write + + Disabled + DMA mode is disabled for transmission + 0 + + + Enabled + DMA mode is enabled for transmission + 1 + + + + + DMAR + DMA enable receiver + 6 + 1 + + DMAR + read-write + + Disabled + DMA mode is disabled for reception + 0 + + + Enabled + DMA mode is enabled for reception + 1 + + + + + SCEN + Smartcard mode enable + 5 + 1 + + SCEN + read-write + + Disabled + Smartcard mode disabled + 0 + + + Enabled + Smartcard mode enabled + 1 + + + + + NACK + Smartcard NACK enable + 4 + 1 + + NACK + read-write + + Disabled + NACK transmission in case of parity error is disabled + 0 + + + Enabled + NACK transmission during parity error is enabled + 1 + + + + + HDSEL + Half-duplex selection + 3 + 1 + + HDSEL + read-write + + FullDuplex + Half duplex mode is not selected + 0 + + + HalfDuplex + Half duplex mode is selected + 1 + + + + + IRLP + IrDA low-power + 2 + 1 + + IRLP + read-write + + Normal + Normal mode + 0 + + + LowPower + Low-power mode + 1 + + + + + IREN + IrDA mode enable + 1 + 1 + + IREN + read-write + + Disabled + IrDA disabled + 0 + + + Enabled + IrDA enabled + 1 + + + + + EIE + Error interrupt enable + 0 + 1 + + EIE + read-write + + Disabled + Error interrupt disabled + 0 + + + Enabled + Error interrupt enabled + 1 + + + + + + + GTPR + GTPR + Guard time and prescaler + register + 0x18 + 0x20 + read-write + 0x00000000 + + + GT + Guard time value + 8 + 8 + + + PSC + Prescaler value + 0 + 8 + + + + + + + USART2 + 0x40004400 + + + USART6 + 0x40011400 + + + WWDG + Window watchdog + WWDG + 0x40002C00 + + 0x0 + 0x400 + registers + + + PVD + PVD through EXTI line detection + interrupt + 1 + + + + CR + CR + Control register + 0x0 + 0x20 + read-write + 0x0000007F + + + WDGA + Activation bit + 7 + 1 + + WDGA + read-write + + Disabled + Watchdog disabled + 0 + + + Enabled + Watchdog enabled + 1 + + + + + T + 7-bit counter (MSB to LSB) + 0 + 7 + + + 0 + 127 + + + + + + + CFR + CFR + Configuration register + 0x4 + 0x20 + read-write + 0x0000007F + + + EWI + Early wakeup interrupt + 9 + 1 + + EWIW + write + + Enable + interrupt occurs whenever the counter reaches the value 0x40 + 1 + + + + + W + 7-bit window value + 0 + 7 + + + 0 + 127 + + + + + WDGTB + Timer base + 7 + 2 + + WDGTB + read-write + + Div1 + Counter clock (PCLK1 div 4096) div 1 + 0 + + + Div2 + Counter clock (PCLK1 div 4096) div 2 + 1 + + + Div4 + Counter clock (PCLK1 div 4096) div 4 + 2 + + + Div8 + Counter clock (PCLK1 div 4096) div 8 + 3 + + + + + + + SR + SR + Status register + 0x8 + 0x20 + read-write + 0x00000000 + + + EWIF + Early wakeup interrupt + flag + 0 + 1 + zeroToClear + + EWIFR + read + + Finished + The EWI Interrupt Service Routine has been serviced + 0 + + + Pending + The EWI Interrupt Service Routine has been triggered + 1 + + + + EWIFW + write + + Finished + The EWI Interrupt Service Routine has been serviced + 0 + + + + + + + + + DMA2 + DMA controller + DMA + 0x40026400 + + 0x0 + 0x400 + registers + + + RCC + RCC global interrupt + 5 + + + DMA1_STREAM0 + DMA1_STREAM0 global interrupt + 11 + + + DMA1_STREAM1 + DMA1_STREAM1 global interrupt + 12 + + + DMA1_STREAM2 + DMA1_STREAM2 global interrupt + 13 + + + DMA1_STREAM3 + DMA1_STREAM3 global interrupt + 14 + + + DMA1_STREAM4 + DMA1_STREAM4 global interrupt + 15 + + + DMA1_STREAM5 + DMA1_STREAM5 global interrupt + 16 + + + DMA1_STREAM6 + DMA1_STREAM6 global interrupt + 17 + + + DMA1_STREAM7 + DMA1_STREAM7 global interrupt + 47 + + + DMA2_STREAM0 + DMA2_STREAM0 global interrupt + 56 + + + DMA2_STREAM1 + DMA2_STREAM1 global interrupt + 57 + + + DMA2_STREAM2 + DMA2_STREAM2 global interrupt + 58 + + + DMA2_STREAM3 + DMA2_STREAM3 global interrupt + 59 + + + DMA2_STREAM4 + DMA2_STREAM4 global interrupt + 60 + + + DMA2_STREAM5 + DMA2_STREAM5 global interrupt + 68 + + + DMA2_STREAM6 + DMA2_STREAM6 global interrupt + 69 + + + DMA2_STREAM7 + DMA2_STREAM7 global interrupt + 70 + + + + LISR + LISR + low interrupt status register + 0x0 + 0x20 + read-only + 0x00000000 + + + TCIF3 + Stream x transfer complete interrupt + flag (x = 3..0) + 27 + 1 + + + + HTIF3 + Stream x half transfer interrupt flag + (x=3..0) + 26 + 1 + + + + TEIF3 + Stream x transfer error interrupt flag + (x=3..0) + 25 + 1 + + + + DMEIF3 + Stream x direct mode error interrupt + flag (x=3..0) + 24 + 1 + + + + FEIF3 + Stream x FIFO error interrupt flag + (x=3..0) + 22 + 1 + + + + TCIF2 + Stream x transfer complete interrupt + flag (x = 3..0) + 21 + 1 + + + + HTIF2 + Stream x half transfer interrupt flag + (x=3..0) + 20 + 1 + + + + TEIF2 + Stream x transfer error interrupt flag + (x=3..0) + 19 + 1 + + + + DMEIF2 + Stream x direct mode error interrupt + flag (x=3..0) + 18 + 1 + + + + FEIF2 + Stream x FIFO error interrupt flag + (x=3..0) + 16 + 1 + + + + TCIF1 + Stream x transfer complete interrupt + flag (x = 3..0) + 11 + 1 + + + + HTIF1 + Stream x half transfer interrupt flag + (x=3..0) + 10 + 1 + + + + TEIF1 + Stream x transfer error interrupt flag + (x=3..0) + 9 + 1 + + + + DMEIF1 + Stream x direct mode error interrupt + flag (x=3..0) + 8 + 1 + + + + FEIF1 + Stream x FIFO error interrupt flag + (x=3..0) + 6 + 1 + + + + TCIF0 + Stream x transfer complete interrupt + flag (x = 3..0) + 5 + 1 + + TCIF0 + read + + NotComplete + No transfer complete event on stream x + 0 + + + Complete + A transfer complete event occurred on stream x + 1 + + + + + HTIF0 + Stream x half transfer interrupt flag + (x=3..0) + 4 + 1 + + HTIF0 + read + + NotHalf + No half transfer event on stream x + 0 + + + Half + A half transfer event occurred on stream x + 1 + + + + + TEIF0 + Stream x transfer error interrupt flag + (x=3..0) + 3 + 1 + + TEIF0 + read + + NoError + No transfer error on stream x + 0 + + + Error + A transfer error occurred on stream x + 1 + + + + + DMEIF0 + Stream x direct mode error interrupt + flag (x=3..0) + 2 + 1 + + DMEIF0 + read + + NoError + No Direct Mode error on stream x + 0 + + + Error + A Direct Mode error occurred on stream x + 1 + + + + + FEIF0 + Stream x FIFO error interrupt flag + (x=3..0) + 0 + 1 + + FEIF0 + read + + NoError + No FIFO error event on stream x + 0 + + + Error + A FIFO error event occurred on stream x + 1 + + + + + + + HISR + HISR + high interrupt status register + 0x4 + 0x20 + read-only + 0x00000000 + + + TCIF7 + Stream x transfer complete interrupt + flag (x=7..4) + 27 + 1 + + + + HTIF7 + Stream x half transfer interrupt flag + (x=7..4) + 26 + 1 + + + + TEIF7 + Stream x transfer error interrupt flag + (x=7..4) + 25 + 1 + + + + DMEIF7 + Stream x direct mode error interrupt + flag (x=7..4) + 24 + 1 + + + + FEIF7 + Stream x FIFO error interrupt flag + (x=7..4) + 22 + 1 + + + + TCIF6 + Stream x transfer complete interrupt + flag (x=7..4) + 21 + 1 + + + + HTIF6 + Stream x half transfer interrupt flag + (x=7..4) + 20 + 1 + + + + TEIF6 + Stream x transfer error interrupt flag + (x=7..4) + 19 + 1 + + + + DMEIF6 + Stream x direct mode error interrupt + flag (x=7..4) + 18 + 1 + + + + FEIF6 + Stream x FIFO error interrupt flag + (x=7..4) + 16 + 1 + + + + TCIF5 + Stream x transfer complete interrupt + flag (x=7..4) + 11 + 1 + + + + HTIF5 + Stream x half transfer interrupt flag + (x=7..4) + 10 + 1 + + + + TEIF5 + Stream x transfer error interrupt flag + (x=7..4) + 9 + 1 + + + + DMEIF5 + Stream x direct mode error interrupt + flag (x=7..4) + 8 + 1 + + + + FEIF5 + Stream x FIFO error interrupt flag + (x=7..4) + 6 + 1 + + + + TCIF4 + Stream x transfer complete interrupt + flag (x=7..4) + 5 + 1 + + TCIF4 + read + + NotComplete + No transfer complete event on stream x + 0 + + + Complete + A transfer complete event occurred on stream x + 1 + + + + + HTIF4 + Stream x half transfer interrupt flag + (x=7..4) + 4 + 1 + + HTIF4 + read + + NotHalf + No half transfer event on stream x + 0 + + + Half + A half transfer event occurred on stream x + 1 + + + + + TEIF4 + Stream x transfer error interrupt flag + (x=7..4) + 3 + 1 + + TEIF4 + read + + NoError + No transfer error on stream x + 0 + + + Error + A transfer error occurred on stream x + 1 + + + + + DMEIF4 + Stream x direct mode error interrupt + flag (x=7..4) + 2 + 1 + + DMEIF4 + read + + NoError + No Direct Mode error on stream x + 0 + + + Error + A Direct Mode error occurred on stream x + 1 + + + + + FEIF4 + Stream x FIFO error interrupt flag + (x=7..4) + 0 + 1 + + FEIF4 + read + + NoError + No FIFO error event on stream x + 0 + + + Error + A FIFO error event occurred on stream x + 1 + + + + + + + LIFCR + LIFCR + low interrupt flag clear + register + 0x8 + 0x20 + write-only + 0x00000000 + + + CTCIF3 + Stream x clear transfer complete + interrupt flag (x = 3..0) + 27 + 1 + + + + CHTIF3 + Stream x clear half transfer interrupt + flag (x = 3..0) + 26 + 1 + + + + CTEIF3 + Stream x clear transfer error interrupt + flag (x = 3..0) + 25 + 1 + + + + CDMEIF3 + Stream x clear direct mode error + interrupt flag (x = 3..0) + 24 + 1 + + + + CFEIF3 + Stream x clear FIFO error interrupt flag + (x = 3..0) + 22 + 1 + + + + CTCIF2 + Stream x clear transfer complete + interrupt flag (x = 3..0) + 21 + 1 + + + + CHTIF2 + Stream x clear half transfer interrupt + flag (x = 3..0) + 20 + 1 + + + + CTEIF2 + Stream x clear transfer error interrupt + flag (x = 3..0) + 19 + 1 + + + + CDMEIF2 + Stream x clear direct mode error + interrupt flag (x = 3..0) + 18 + 1 + + + + CFEIF2 + Stream x clear FIFO error interrupt flag + (x = 3..0) + 16 + 1 + + + + CTCIF1 + Stream x clear transfer complete + interrupt flag (x = 3..0) + 11 + 1 + + + + CHTIF1 + Stream x clear half transfer interrupt + flag (x = 3..0) + 10 + 1 + + + + CTEIF1 + Stream x clear transfer error interrupt + flag (x = 3..0) + 9 + 1 + + + + CDMEIF1 + Stream x clear direct mode error + interrupt flag (x = 3..0) + 8 + 1 + + + + CFEIF1 + Stream x clear FIFO error interrupt flag + (x = 3..0) + 6 + 1 + + + + CTCIF0 + Stream x clear transfer complete + interrupt flag (x = 3..0) + 5 + 1 + + CTCIF0 + write + + Clear + Clear the corresponding TCIFx flag + 1 + + + + + CHTIF0 + Stream x clear half transfer interrupt + flag (x = 3..0) + 4 + 1 + + CHTIF0 + write + + Clear + Clear the corresponding HTIFx flag + 1 + + + + + CTEIF0 + Stream x clear transfer error interrupt + flag (x = 3..0) + 3 + 1 + + CTEIF0 + write + + Clear + Clear the corresponding TEIFx flag + 1 + + + + + CDMEIF0 + Stream x clear direct mode error + interrupt flag (x = 3..0) + 2 + 1 + + CDMEIF0 + write + + Clear + Clear the corresponding DMEIFx flag + 1 + + + + + CFEIF0 + Stream x clear FIFO error interrupt flag + (x = 3..0) + 0 + 1 + + CFEIF0 + write + + Clear + Clear the corresponding CFEIFx flag + 1 + + + + + + + HIFCR + HIFCR + high interrupt flag clear + register + 0xC + 0x20 + write-only + 0x00000000 + + + CTCIF7 + Stream x clear transfer complete + interrupt flag (x = 7..4) + 27 + 1 + + + + CHTIF7 + Stream x clear half transfer interrupt + flag (x = 7..4) + 26 + 1 + + + + CTEIF7 + Stream x clear transfer error interrupt + flag (x = 7..4) + 25 + 1 + + + + CDMEIF7 + Stream x clear direct mode error + interrupt flag (x = 7..4) + 24 + 1 + + + + CFEIF7 + Stream x clear FIFO error interrupt flag + (x = 7..4) + 22 + 1 + + + + CTCIF6 + Stream x clear transfer complete + interrupt flag (x = 7..4) + 21 + 1 + + + + CHTIF6 + Stream x clear half transfer interrupt + flag (x = 7..4) + 20 + 1 + + + + CTEIF6 + Stream x clear transfer error interrupt + flag (x = 7..4) + 19 + 1 + + + + CDMEIF6 + Stream x clear direct mode error + interrupt flag (x = 7..4) + 18 + 1 + + + + CFEIF6 + Stream x clear FIFO error interrupt flag + (x = 7..4) + 16 + 1 + + + + CTCIF5 + Stream x clear transfer complete + interrupt flag (x = 7..4) + 11 + 1 + + + + CHTIF5 + Stream x clear half transfer interrupt + flag (x = 7..4) + 10 + 1 + + + + CTEIF5 + Stream x clear transfer error interrupt + flag (x = 7..4) + 9 + 1 + + + + CDMEIF5 + Stream x clear direct mode error + interrupt flag (x = 7..4) + 8 + 1 + + + + CFEIF5 + Stream x clear FIFO error interrupt flag + (x = 7..4) + 6 + 1 + + + + CTCIF4 + Stream x clear transfer complete + interrupt flag (x = 7..4) + 5 + 1 + + CTCIF4 + write + + Clear + Clear the corresponding TCIFx flag + 1 + + + + + CHTIF4 + Stream x clear half transfer interrupt + flag (x = 7..4) + 4 + 1 + + CHTIF4 + write + + Clear + Clear the corresponding HTIFx flag + 1 + + + + + CTEIF4 + Stream x clear transfer error interrupt + flag (x = 7..4) + 3 + 1 + + CTEIF4 + write + + Clear + Clear the corresponding TEIFx flag + 1 + + + + + CDMEIF4 + Stream x clear direct mode error + interrupt flag (x = 7..4) + 2 + 1 + + CDMEIF4 + write + + Clear + Clear the corresponding DMEIFx flag + 1 + + + + + CFEIF4 + Stream x clear FIFO error interrupt flag + (x = 7..4) + 0 + 1 + + CFEIF4 + write + + Clear + Clear the corresponding CFEIFx flag + 1 + + + + + + + 8 + 0x18 + 0-7 + ST%s + Stream cluster: S?CR, S?NDTR, S?M0AR, S?M1AR and S?FCR registers + 0x10 + + CR + S0CR + stream x configuration + register + 0x0 + 0x20 + read-write + 0x00000000 + + + CHSEL + Channel selection + 25 + 3 + + + 0 + 7 + + + + + MBURST + Memory burst transfer + configuration + 23 + 2 + + + + PBURST + Peripheral burst transfer + configuration + 21 + 2 + + PBURST + read-write + + Single + Single transfer + 0 + + + INCR4 + Incremental burst of 4 beats + 1 + + + INCR8 + Incremental burst of 8 beats + 2 + + + INCR16 + Incremental burst of 16 beats + 3 + + + + + CT + Current target (only in double buffer + mode) + 19 + 1 + + CT + read-write + + Memory0 + The current target memory is Memory 0 + 0 + + + Memory1 + The current target memory is Memory 1 + 1 + + + + + DBM + Double buffer mode + 18 + 1 + + DBM + read-write + + Disabled + No buffer switching at the end of transfer + 0 + + + Enabled + Memory target switched at the end of the DMA transfer + 1 + + + + + PL + Priority level + 16 + 2 + + PL + read-write + + Low + Low + 0 + + + Medium + Medium + 1 + + + High + High + 2 + + + VeryHigh + Very high + 3 + + + + + PINCOS + Peripheral increment offset + size + 15 + 1 + + PINCOS + read-write + + PSIZE + The offset size for the peripheral address calculation is linked to the PSIZE + 0 + + + Fixed4 + The offset size for the peripheral address calculation is fixed to 4 (32-bit alignment) + 1 + + + + + MSIZE + Memory data size + 13 + 2 + + + + PSIZE + Peripheral data size + 11 + 2 + + PSIZE + read-write + + Bits8 + Byte (8-bit) + 0 + + + Bits16 + Half-word (16-bit) + 1 + + + Bits32 + Word (32-bit) + 2 + + + + + MINC + Memory increment mode + 10 + 1 + + + + PINC + Peripheral increment mode + 9 + 1 + + PINC + read-write + + Fixed + Address pointer is fixed + 0 + + + Incremented + Address pointer is incremented after each data transfer + 1 + + + + + CIRC + Circular mode + 8 + 1 + + CIRC + read-write + + Disabled + Circular mode disabled + 0 + + + Enabled + Circular mode enabled + 1 + + + + + DIR + Data transfer direction + 6 + 2 + + DIR + read-write + + PeripheralToMemory + Peripheral-to-memory + 0 + + + MemoryToPeripheral + Memory-to-peripheral + 1 + + + MemoryToMemory + Memory-to-memory + 2 + + + + + PFCTRL + Peripheral flow controller + 5 + 1 + + PFCTRL + read-write + + DMA + The DMA is the flow controller + 0 + + + Peripheral + The peripheral is the flow controller + 1 + + + + + TCIE + Transfer complete interrupt + enable + 4 + 1 + + TCIE + read-write + + Disabled + TC interrupt disabled + 0 + + + Enabled + TC interrupt enabled + 1 + + + + + HTIE + Half transfer interrupt + enable + 3 + 1 + + HTIE + read-write + + Disabled + HT interrupt disabled + 0 + + + Enabled + HT interrupt enabled + 1 + + + + + TEIE + Transfer error interrupt + enable + 2 + 1 + + TEIE + read-write + + Disabled + TE interrupt disabled + 0 + + + Enabled + TE interrupt enabled + 1 + + + + + DMEIE + Direct mode error interrupt + enable + 1 + 1 + + DMEIE + read-write + + Disabled + DME interrupt disabled + 0 + + + Enabled + DME interrupt enabled + 1 + + + + + EN + Stream enable / flag stream ready when + read low + 0 + 1 + + EN + read-write + + Disabled + Stream disabled + 0 + + + Enabled + Stream enabled + 1 + + + + + + + NDTR + S0NDTR + stream x number of data + register + 0x4 + 0x20 + read-write + 0x00000000 + + + NDT + Number of data items to + transfer + 0 + 16 + + + 0 + 65535 + + + + + + + PAR + S0PAR + stream x peripheral address + register + 0x8 + 0x20 + read-write + 0x00000000 + + + PA + Peripheral address + 0 + 32 + + + + + M0AR + S0M0AR + stream x memory 0 address + register + 0xC + 0x20 + read-write + 0x00000000 + + + M0A + Memory 0 address + 0 + 32 + + + + + M1AR + S0M1AR + stream x memory 1 address + register + 0x10 + 0x20 + read-write + 0x00000000 + + + M1A + Memory 1 address (used in case of Double + buffer mode) + 0 + 32 + + + + + FCR + S0FCR + stream x FIFO control register + 0x14 + 0x20 + 0x00000021 + + + FEIE + FIFO error interrupt + enable + 7 + 1 + read-write + + FEIE + read-write + + Disabled + FE interrupt disabled + 0 + + + Enabled + FE interrupt enabled + 1 + + + + + FS + FIFO status + 3 + 3 + read-only + + FS + read + + Quarter1 + 0 < fifo_level < 1/4 + 0 + + + Quarter2 + 1/4 <= fifo_level < 1/2 + 1 + + + Quarter3 + 1/2 <= fifo_level < 3/4 + 2 + + + Quarter4 + 3/4 <= fifo_level < full + 3 + + + Empty + FIFO is empty + 4 + + + Full + FIFO is full + 5 + + + + + DMDIS + Direct mode disable + 2 + 1 + read-write + + DMDIS + read-write + + Enabled + Direct mode is enabled + 0 + + + Disabled + Direct mode is disabled + 1 + + + + + FTH + FIFO threshold selection + 0 + 2 + read-write + + FTH + read-write + + Quarter + 1/4 full FIFO + 0 + + + Half + 1/2 full FIFO + 1 + + + ThreeQuarters + 3/4 full FIFO + 2 + + + Full + Full FIFO + 3 + + + + + + + + + + DMA1 + 0x40026000 + + RTC_WKUP + RTC Wakeup interrupt through the EXTI + line + 3 + + + RTC_Alarm + RTC Alarms (A and B) through EXTI line + interrupt + 41 + + + + GPIOH + General-purpose I/Os + GPIO + 0x40021C00 + + 0x0 + 0x400 + registers + + + SDIO + SDIO global interrupt + 49 + + + + MODER + MODER + GPIO port mode register + 0x0 + 0x20 + read-write + 0x00000000 + + + MODER15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + MODER14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + MODER13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + MODER12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + MODER11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + MODER10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + MODER9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + MODER8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + MODER7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + MODER6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + MODER5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + MODER4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + MODER3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + MODER2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + MODER1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + MODER0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + MODER0 + read-write + + Input + Input mode (reset state) + 0 + + + Output + General purpose output mode + 1 + + + Alternate + Alternate function mode + 2 + + + Analog + Analog mode + 3 + + + + + + + OTYPER + OTYPER + GPIO port output type register + 0x4 + 0x20 + read-write + 0x00000000 + + + OT15 + Port x configuration bits (y = + 0..15) + 15 + 1 + + + + OT14 + Port x configuration bits (y = + 0..15) + 14 + 1 + + + + OT13 + Port x configuration bits (y = + 0..15) + 13 + 1 + + + + OT12 + Port x configuration bits (y = + 0..15) + 12 + 1 + + + + OT11 + Port x configuration bits (y = + 0..15) + 11 + 1 + + + + OT10 + Port x configuration bits (y = + 0..15) + 10 + 1 + + + + OT9 + Port x configuration bits (y = + 0..15) + 9 + 1 + + + + OT8 + Port x configuration bits (y = + 0..15) + 8 + 1 + + + + OT7 + Port x configuration bits (y = + 0..15) + 7 + 1 + + + + OT6 + Port x configuration bits (y = + 0..15) + 6 + 1 + + + + OT5 + Port x configuration bits (y = + 0..15) + 5 + 1 + + + + OT4 + Port x configuration bits (y = + 0..15) + 4 + 1 + + + + OT3 + Port x configuration bits (y = + 0..15) + 3 + 1 + + + + OT2 + Port x configuration bits (y = + 0..15) + 2 + 1 + + + + OT1 + Port x configuration bits (y = + 0..15) + 1 + 1 + + + + OT0 + Port x configuration bits (y = + 0..15) + 0 + 1 + + OT0 + read-write + + PushPull + Output push-pull (reset state) + 0 + + + OpenDrain + Output open-drain + 1 + + + + + + + OSPEEDR + OSPEEDR + GPIO port output speed + register + 0x8 + 0x20 + read-write + 0x00000000 + + + OSPEEDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + OSPEEDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + OSPEEDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + OSPEEDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + OSPEEDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + OSPEEDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + OSPEEDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + OSPEEDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + OSPEEDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + OSPEEDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + OSPEEDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + OSPEEDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + OSPEEDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + OSPEEDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + OSPEEDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + OSPEEDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + OSPEEDR0 + read-write + + LowSpeed + Low speed + 0 + + + MediumSpeed + Medium speed + 1 + + + HighSpeed + High speed + 2 + + + VeryHighSpeed + Very high speed + 3 + + + + + + + PUPDR + PUPDR + GPIO port pull-up/pull-down + register + 0xC + 0x20 + read-write + 0x00000000 + + + PUPDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + PUPDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + PUPDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + PUPDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + PUPDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + PUPDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + PUPDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + PUPDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + PUPDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + PUPDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + PUPDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + PUPDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + PUPDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + PUPDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + PUPDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + PUPDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + PUPDR0 + read-write + + Floating + No pull-up, pull-down + 0 + + + PullUp + Pull-up + 1 + + + PullDown + Pull-down + 2 + + + + + + + IDR + IDR + GPIO port input data register + 0x10 + 0x20 + read-only + 0x00000000 + + + IDR15 + Port input data (y = + 0..15) + 15 + 1 + + + + IDR14 + Port input data (y = + 0..15) + 14 + 1 + + + + IDR13 + Port input data (y = + 0..15) + 13 + 1 + + + + IDR12 + Port input data (y = + 0..15) + 12 + 1 + + + + IDR11 + Port input data (y = + 0..15) + 11 + 1 + + + + IDR10 + Port input data (y = + 0..15) + 10 + 1 + + + + IDR9 + Port input data (y = + 0..15) + 9 + 1 + + + + IDR8 + Port input data (y = + 0..15) + 8 + 1 + + + + IDR7 + Port input data (y = + 0..15) + 7 + 1 + + + + IDR6 + Port input data (y = + 0..15) + 6 + 1 + + + + IDR5 + Port input data (y = + 0..15) + 5 + 1 + + + + IDR4 + Port input data (y = + 0..15) + 4 + 1 + + + + IDR3 + Port input data (y = + 0..15) + 3 + 1 + + + + IDR2 + Port input data (y = + 0..15) + 2 + 1 + + + + IDR1 + Port input data (y = + 0..15) + 1 + 1 + + + + IDR0 + Port input data (y = + 0..15) + 0 + 1 + + IDR0 + read + + Low + Input is logic low + 0 + + + High + Input is logic high + 1 + + + + + + + ODR + ODR + GPIO port output data register + 0x14 + 0x20 + read-write + 0x00000000 + + + ODR15 + Port output data (y = + 0..15) + 15 + 1 + + + + ODR14 + Port output data (y = + 0..15) + 14 + 1 + + + + ODR13 + Port output data (y = + 0..15) + 13 + 1 + + + + ODR12 + Port output data (y = + 0..15) + 12 + 1 + + + + ODR11 + Port output data (y = + 0..15) + 11 + 1 + + + + ODR10 + Port output data (y = + 0..15) + 10 + 1 + + + + ODR9 + Port output data (y = + 0..15) + 9 + 1 + + + + ODR8 + Port output data (y = + 0..15) + 8 + 1 + + + + ODR7 + Port output data (y = + 0..15) + 7 + 1 + + + + ODR6 + Port output data (y = + 0..15) + 6 + 1 + + + + ODR5 + Port output data (y = + 0..15) + 5 + 1 + + + + ODR4 + Port output data (y = + 0..15) + 4 + 1 + + + + ODR3 + Port output data (y = + 0..15) + 3 + 1 + + + + ODR2 + Port output data (y = + 0..15) + 2 + 1 + + + + ODR1 + Port output data (y = + 0..15) + 1 + 1 + + + + ODR0 + Port output data (y = + 0..15) + 0 + 1 + + ODR0 + read-write + + Low + Set output to logic low + 0 + + + High + Set output to logic high + 1 + + + + + + + BSRR + BSRR + GPIO port bit set/reset + register + 0x18 + 0x20 + write-only + 0x00000000 + + + BR15 + Port x reset bit y (y = + 0..15) + 31 + 1 + + + + BR14 + Port x reset bit y (y = + 0..15) + 30 + 1 + + + + BR13 + Port x reset bit y (y = + 0..15) + 29 + 1 + + + + BR12 + Port x reset bit y (y = + 0..15) + 28 + 1 + + + + BR11 + Port x reset bit y (y = + 0..15) + 27 + 1 + + + + BR10 + Port x reset bit y (y = + 0..15) + 26 + 1 + + + + BR9 + Port x reset bit y (y = + 0..15) + 25 + 1 + + + + BR8 + Port x reset bit y (y = + 0..15) + 24 + 1 + + + + BR7 + Port x reset bit y (y = + 0..15) + 23 + 1 + + + + BR6 + Port x reset bit y (y = + 0..15) + 22 + 1 + + + + BR5 + Port x reset bit y (y = + 0..15) + 21 + 1 + + + + BR4 + Port x reset bit y (y = + 0..15) + 20 + 1 + + + + BR3 + Port x reset bit y (y = + 0..15) + 19 + 1 + + + + BR2 + Port x reset bit y (y = + 0..15) + 18 + 1 + + + + BR1 + Port x reset bit y (y = + 0..15) + 17 + 1 + + + + BR0 + Port x set bit y (y= + 0..15) + 16 + 1 + + BR0W + write + + Reset + Resets the corresponding ODRx bit + 1 + + + + + BS15 + Port x set bit y (y= + 0..15) + 15 + 1 + + + + BS14 + Port x set bit y (y= + 0..15) + 14 + 1 + + + + BS13 + Port x set bit y (y= + 0..15) + 13 + 1 + + + + BS12 + Port x set bit y (y= + 0..15) + 12 + 1 + + + + BS11 + Port x set bit y (y= + 0..15) + 11 + 1 + + + + BS10 + Port x set bit y (y= + 0..15) + 10 + 1 + + + + BS9 + Port x set bit y (y= + 0..15) + 9 + 1 + + + + BS8 + Port x set bit y (y= + 0..15) + 8 + 1 + + + + BS7 + Port x set bit y (y= + 0..15) + 7 + 1 + + + + BS6 + Port x set bit y (y= + 0..15) + 6 + 1 + + + + BS5 + Port x set bit y (y= + 0..15) + 5 + 1 + + + + BS4 + Port x set bit y (y= + 0..15) + 4 + 1 + + + + BS3 + Port x set bit y (y= + 0..15) + 3 + 1 + + + + BS2 + Port x set bit y (y= + 0..15) + 2 + 1 + + + + BS1 + Port x set bit y (y= + 0..15) + 1 + 1 + + + + BS0 + Port x set bit y (y= + 0..15) + 0 + 1 + + BS0W + write + + Set + Sets the corresponding ODRx bit + 1 + + + + + + + LCKR + LCKR + GPIO port configuration lock + register + 0x1C + 0x20 + read-write + 0x00000000 + + + LCKK + Port x lock bit y (y= + 0..15) + 16 + 1 + + LCKK + read-write + + NotActive + Port configuration lock key not active + 0 + + + Active + Port configuration lock key active + 1 + + + + + LCK15 + Port x lock bit y (y= + 0..15) + 15 + 1 + + + + LCK14 + Port x lock bit y (y= + 0..15) + 14 + 1 + + + + LCK13 + Port x lock bit y (y= + 0..15) + 13 + 1 + + + + LCK12 + Port x lock bit y (y= + 0..15) + 12 + 1 + + + + LCK11 + Port x lock bit y (y= + 0..15) + 11 + 1 + + + + LCK10 + Port x lock bit y (y= + 0..15) + 10 + 1 + + + + LCK9 + Port x lock bit y (y= + 0..15) + 9 + 1 + + + + LCK8 + Port x lock bit y (y= + 0..15) + 8 + 1 + + + + LCK7 + Port x lock bit y (y= + 0..15) + 7 + 1 + + + + LCK6 + Port x lock bit y (y= + 0..15) + 6 + 1 + + + + LCK5 + Port x lock bit y (y= + 0..15) + 5 + 1 + + + + LCK4 + Port x lock bit y (y= + 0..15) + 4 + 1 + + + + LCK3 + Port x lock bit y (y= + 0..15) + 3 + 1 + + + + LCK2 + Port x lock bit y (y= + 0..15) + 2 + 1 + + + + LCK1 + Port x lock bit y (y= + 0..15) + 1 + 1 + + + + LCK0 + Port x lock bit y (y= + 0..15) + 0 + 1 + + LCK0 + read-write + + Unlocked + Port configuration not locked + 0 + + + Locked + Port configuration locked + 1 + + + + + + + AFRL + AFRL + GPIO alternate function low + register + 0x20 + 0x20 + read-write + 0x00000000 + + + AFRL7 + Alternate function selection for port x + bit y (y = 0..7) + 28 + 4 + + + + AFRL6 + Alternate function selection for port x + bit y (y = 0..7) + 24 + 4 + + + + AFRL5 + Alternate function selection for port x + bit y (y = 0..7) + 20 + 4 + + + + AFRL4 + Alternate function selection for port x + bit y (y = 0..7) + 16 + 4 + + + + AFRL3 + Alternate function selection for port x + bit y (y = 0..7) + 12 + 4 + + + + AFRL2 + Alternate function selection for port x + bit y (y = 0..7) + 8 + 4 + + + + AFRL1 + Alternate function selection for port x + bit y (y = 0..7) + 4 + 4 + + + + AFRL0 + Alternate function selection for port x + bit y (y = 0..7) + 0 + 4 + + AFRL0 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + AFRH + AFRH + GPIO alternate function high + register + 0x24 + 0x20 + read-write + 0x00000000 + + + AFRH15 + Alternate function selection for port x + bit y (y = 8..15) + 28 + 4 + + + + AFRH14 + Alternate function selection for port x + bit y (y = 8..15) + 24 + 4 + + + + AFRH13 + Alternate function selection for port x + bit y (y = 8..15) + 20 + 4 + + + + AFRH12 + Alternate function selection for port x + bit y (y = 8..15) + 16 + 4 + + + + AFRH11 + Alternate function selection for port x + bit y (y = 8..15) + 12 + 4 + + + + AFRH10 + Alternate function selection for port x + bit y (y = 8..15) + 8 + 4 + + + + AFRH9 + Alternate function selection for port x + bit y (y = 8..15) + 4 + 4 + + + + AFRH8 + Alternate function selection for port x + bit y (y = 8..15) + 0 + 4 + + AFRH8 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + + + GPIOE + 0x40021000 + + + GPIOD + 0x40020C00 + + TIM1_BRK_TIM9 + TIM1 Break interrupt and TIM9 global + interrupt + 24 + + + TIM1_UP_TIM10 + TIM1 Update interrupt and TIM10 global + interrupt + 25 + + + TIM1_TRG_COM_TIM11 + TIM1 Trigger and Commutation interrupts and + TIM11 global interrupt + 26 + + + TIM1_CC + TIM1 Capture Compare interrupt + 27 + + + + GPIOC + 0x40020800 + + TIM1_UP_TIM10 + TIM1 Update interrupt and TIM10 global + interrupt + 25 + + + + GPIOB + General-purpose I/Os + GPIO + 0x40020400 + + 0x0 + 0x400 + registers + + + TIM1_TRG_COM_TIM11 + TIM1 Trigger and Commutation interrupts and + TIM11 global interrupt + 26 + + + + MODER + MODER + GPIO port mode register + 0x0 + 0x20 + read-write + 0x00000280 + + + MODER15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + MODER14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + MODER13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + MODER12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + MODER11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + MODER10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + MODER9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + MODER8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + MODER7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + MODER6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + MODER5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + MODER4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + MODER3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + MODER2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + MODER1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + MODER0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + MODER0 + read-write + + Input + Input mode (reset state) + 0 + + + Output + General purpose output mode + 1 + + + Alternate + Alternate function mode + 2 + + + Analog + Analog mode + 3 + + + + + + + OTYPER + OTYPER + GPIO port output type register + 0x4 + 0x20 + read-write + 0x00000000 + + + OT15 + Port x configuration bits (y = + 0..15) + 15 + 1 + + + + OT14 + Port x configuration bits (y = + 0..15) + 14 + 1 + + + + OT13 + Port x configuration bits (y = + 0..15) + 13 + 1 + + + + OT12 + Port x configuration bits (y = + 0..15) + 12 + 1 + + + + OT11 + Port x configuration bits (y = + 0..15) + 11 + 1 + + + + OT10 + Port x configuration bits (y = + 0..15) + 10 + 1 + + + + OT9 + Port x configuration bits (y = + 0..15) + 9 + 1 + + + + OT8 + Port x configuration bits (y = + 0..15) + 8 + 1 + + + + OT7 + Port x configuration bits (y = + 0..15) + 7 + 1 + + + + OT6 + Port x configuration bits (y = + 0..15) + 6 + 1 + + + + OT5 + Port x configuration bits (y = + 0..15) + 5 + 1 + + + + OT4 + Port x configuration bits (y = + 0..15) + 4 + 1 + + + + OT3 + Port x configuration bits (y = + 0..15) + 3 + 1 + + + + OT2 + Port x configuration bits (y = + 0..15) + 2 + 1 + + + + OT1 + Port x configuration bits (y = + 0..15) + 1 + 1 + + + + OT0 + Port x configuration bits (y = + 0..15) + 0 + 1 + + OT0 + read-write + + PushPull + Output push-pull (reset state) + 0 + + + OpenDrain + Output open-drain + 1 + + + + + + + OSPEEDR + OSPEEDR + GPIO port output speed + register + 0x8 + 0x20 + read-write + 0x000000C0 + + + OSPEEDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + OSPEEDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + OSPEEDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + OSPEEDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + OSPEEDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + OSPEEDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + OSPEEDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + OSPEEDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + OSPEEDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + OSPEEDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + OSPEEDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + OSPEEDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + OSPEEDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + OSPEEDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + OSPEEDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + OSPEEDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + OSPEEDR0 + read-write + + LowSpeed + Low speed + 0 + + + MediumSpeed + Medium speed + 1 + + + HighSpeed + High speed + 2 + + + VeryHighSpeed + Very high speed + 3 + + + + + + + PUPDR + PUPDR + GPIO port pull-up/pull-down + register + 0xC + 0x20 + read-write + 0x00000100 + + + PUPDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + PUPDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + PUPDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + PUPDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + PUPDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + PUPDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + PUPDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + PUPDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + PUPDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + PUPDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + PUPDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + PUPDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + PUPDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + PUPDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + PUPDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + PUPDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + PUPDR0 + read-write + + Floating + No pull-up, pull-down + 0 + + + PullUp + Pull-up + 1 + + + PullDown + Pull-down + 2 + + + + + + + IDR + IDR + GPIO port input data register + 0x10 + 0x20 + read-only + 0x00000000 + + + IDR15 + Port input data (y = + 0..15) + 15 + 1 + + + + IDR14 + Port input data (y = + 0..15) + 14 + 1 + + + + IDR13 + Port input data (y = + 0..15) + 13 + 1 + + + + IDR12 + Port input data (y = + 0..15) + 12 + 1 + + + + IDR11 + Port input data (y = + 0..15) + 11 + 1 + + + + IDR10 + Port input data (y = + 0..15) + 10 + 1 + + + + IDR9 + Port input data (y = + 0..15) + 9 + 1 + + + + IDR8 + Port input data (y = + 0..15) + 8 + 1 + + + + IDR7 + Port input data (y = + 0..15) + 7 + 1 + + + + IDR6 + Port input data (y = + 0..15) + 6 + 1 + + + + IDR5 + Port input data (y = + 0..15) + 5 + 1 + + + + IDR4 + Port input data (y = + 0..15) + 4 + 1 + + + + IDR3 + Port input data (y = + 0..15) + 3 + 1 + + + + IDR2 + Port input data (y = + 0..15) + 2 + 1 + + + + IDR1 + Port input data (y = + 0..15) + 1 + 1 + + + + IDR0 + Port input data (y = + 0..15) + 0 + 1 + + IDR0 + read + + Low + Input is logic low + 0 + + + High + Input is logic high + 1 + + + + + + + ODR + ODR + GPIO port output data register + 0x14 + 0x20 + read-write + 0x00000000 + + + ODR15 + Port output data (y = + 0..15) + 15 + 1 + + + + ODR14 + Port output data (y = + 0..15) + 14 + 1 + + + + ODR13 + Port output data (y = + 0..15) + 13 + 1 + + + + ODR12 + Port output data (y = + 0..15) + 12 + 1 + + + + ODR11 + Port output data (y = + 0..15) + 11 + 1 + + + + ODR10 + Port output data (y = + 0..15) + 10 + 1 + + + + ODR9 + Port output data (y = + 0..15) + 9 + 1 + + + + ODR8 + Port output data (y = + 0..15) + 8 + 1 + + + + ODR7 + Port output data (y = + 0..15) + 7 + 1 + + + + ODR6 + Port output data (y = + 0..15) + 6 + 1 + + + + ODR5 + Port output data (y = + 0..15) + 5 + 1 + + + + ODR4 + Port output data (y = + 0..15) + 4 + 1 + + + + ODR3 + Port output data (y = + 0..15) + 3 + 1 + + + + ODR2 + Port output data (y = + 0..15) + 2 + 1 + + + + ODR1 + Port output data (y = + 0..15) + 1 + 1 + + + + ODR0 + Port output data (y = + 0..15) + 0 + 1 + + ODR0 + read-write + + Low + Set output to logic low + 0 + + + High + Set output to logic high + 1 + + + + + + + BSRR + BSRR + GPIO port bit set/reset + register + 0x18 + 0x20 + write-only + 0x00000000 + + + BR15 + Port x reset bit y (y = + 0..15) + 31 + 1 + + + + BR14 + Port x reset bit y (y = + 0..15) + 30 + 1 + + + + BR13 + Port x reset bit y (y = + 0..15) + 29 + 1 + + + + BR12 + Port x reset bit y (y = + 0..15) + 28 + 1 + + + + BR11 + Port x reset bit y (y = + 0..15) + 27 + 1 + + + + BR10 + Port x reset bit y (y = + 0..15) + 26 + 1 + + + + BR9 + Port x reset bit y (y = + 0..15) + 25 + 1 + + + + BR8 + Port x reset bit y (y = + 0..15) + 24 + 1 + + + + BR7 + Port x reset bit y (y = + 0..15) + 23 + 1 + + + + BR6 + Port x reset bit y (y = + 0..15) + 22 + 1 + + + + BR5 + Port x reset bit y (y = + 0..15) + 21 + 1 + + + + BR4 + Port x reset bit y (y = + 0..15) + 20 + 1 + + + + BR3 + Port x reset bit y (y = + 0..15) + 19 + 1 + + + + BR2 + Port x reset bit y (y = + 0..15) + 18 + 1 + + + + BR1 + Port x reset bit y (y = + 0..15) + 17 + 1 + + + + BR0 + Port x set bit y (y= + 0..15) + 16 + 1 + + BR0W + write + + Reset + Resets the corresponding ODRx bit + 1 + + + + + BS15 + Port x set bit y (y= + 0..15) + 15 + 1 + + + + BS14 + Port x set bit y (y= + 0..15) + 14 + 1 + + + + BS13 + Port x set bit y (y= + 0..15) + 13 + 1 + + + + BS12 + Port x set bit y (y= + 0..15) + 12 + 1 + + + + BS11 + Port x set bit y (y= + 0..15) + 11 + 1 + + + + BS10 + Port x set bit y (y= + 0..15) + 10 + 1 + + + + BS9 + Port x set bit y (y= + 0..15) + 9 + 1 + + + + BS8 + Port x set bit y (y= + 0..15) + 8 + 1 + + + + BS7 + Port x set bit y (y= + 0..15) + 7 + 1 + + + + BS6 + Port x set bit y (y= + 0..15) + 6 + 1 + + + + BS5 + Port x set bit y (y= + 0..15) + 5 + 1 + + + + BS4 + Port x set bit y (y= + 0..15) + 4 + 1 + + + + BS3 + Port x set bit y (y= + 0..15) + 3 + 1 + + + + BS2 + Port x set bit y (y= + 0..15) + 2 + 1 + + + + BS1 + Port x set bit y (y= + 0..15) + 1 + 1 + + + + BS0 + Port x set bit y (y= + 0..15) + 0 + 1 + + BS0W + write + + Set + Sets the corresponding ODRx bit + 1 + + + + + + + LCKR + LCKR + GPIO port configuration lock + register + 0x1C + 0x20 + read-write + 0x00000000 + + + LCKK + Port x lock bit y (y= + 0..15) + 16 + 1 + + LCKK + read-write + + NotActive + Port configuration lock key not active + 0 + + + Active + Port configuration lock key active + 1 + + + + + LCK15 + Port x lock bit y (y= + 0..15) + 15 + 1 + + + + LCK14 + Port x lock bit y (y= + 0..15) + 14 + 1 + + + + LCK13 + Port x lock bit y (y= + 0..15) + 13 + 1 + + + + LCK12 + Port x lock bit y (y= + 0..15) + 12 + 1 + + + + LCK11 + Port x lock bit y (y= + 0..15) + 11 + 1 + + + + LCK10 + Port x lock bit y (y= + 0..15) + 10 + 1 + + + + LCK9 + Port x lock bit y (y= + 0..15) + 9 + 1 + + + + LCK8 + Port x lock bit y (y= + 0..15) + 8 + 1 + + + + LCK7 + Port x lock bit y (y= + 0..15) + 7 + 1 + + + + LCK6 + Port x lock bit y (y= + 0..15) + 6 + 1 + + + + LCK5 + Port x lock bit y (y= + 0..15) + 5 + 1 + + + + LCK4 + Port x lock bit y (y= + 0..15) + 4 + 1 + + + + LCK3 + Port x lock bit y (y= + 0..15) + 3 + 1 + + + + LCK2 + Port x lock bit y (y= + 0..15) + 2 + 1 + + + + LCK1 + Port x lock bit y (y= + 0..15) + 1 + 1 + + + + LCK0 + Port x lock bit y (y= + 0..15) + 0 + 1 + + LCK0 + read-write + + Unlocked + Port configuration not locked + 0 + + + Locked + Port configuration locked + 1 + + + + + + + AFRL + AFRL + GPIO alternate function low + register + 0x20 + 0x20 + read-write + 0x00000000 + + + AFRL7 + Alternate function selection for port x + bit y (y = 0..7) + 28 + 4 + + + + AFRL6 + Alternate function selection for port x + bit y (y = 0..7) + 24 + 4 + + + + AFRL5 + Alternate function selection for port x + bit y (y = 0..7) + 20 + 4 + + + + AFRL4 + Alternate function selection for port x + bit y (y = 0..7) + 16 + 4 + + + + AFRL3 + Alternate function selection for port x + bit y (y = 0..7) + 12 + 4 + + + + AFRL2 + Alternate function selection for port x + bit y (y = 0..7) + 8 + 4 + + + + AFRL1 + Alternate function selection for port x + bit y (y = 0..7) + 4 + 4 + + + + AFRL0 + Alternate function selection for port x + bit y (y = 0..7) + 0 + 4 + + AFRL0 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + AFRH + AFRH + GPIO alternate function high + register + 0x24 + 0x20 + read-write + 0x00000000 + + + AFRH15 + Alternate function selection for port x + bit y (y = 8..15) + 28 + 4 + + + + AFRH14 + Alternate function selection for port x + bit y (y = 8..15) + 24 + 4 + + + + AFRH13 + Alternate function selection for port x + bit y (y = 8..15) + 20 + 4 + + + + AFRH12 + Alternate function selection for port x + bit y (y = 8..15) + 16 + 4 + + + + AFRH11 + Alternate function selection for port x + bit y (y = 8..15) + 12 + 4 + + + + AFRH10 + Alternate function selection for port x + bit y (y = 8..15) + 8 + 4 + + + + AFRH9 + Alternate function selection for port x + bit y (y = 8..15) + 4 + 4 + + + + AFRH8 + Alternate function selection for port x + bit y (y = 8..15) + 0 + 4 + + AFRH8 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + + + GPIOA + General-purpose I/Os + GPIO + 0x40020000 + + 0x0 + 0x400 + registers + + + TIM2 + TIM2 global interrupt + 28 + + + + MODER + MODER + GPIO port mode register + 0x0 + 0x20 + read-write + 0xA8000000 + + + MODER15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + MODER14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + MODER13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + MODER12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + MODER11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + MODER10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + MODER9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + MODER8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + MODER7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + MODER6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + MODER5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + MODER4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + MODER3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + MODER2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + MODER1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + MODER0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + MODER0 + read-write + + Input + Input mode (reset state) + 0 + + + Output + General purpose output mode + 1 + + + Alternate + Alternate function mode + 2 + + + Analog + Analog mode + 3 + + + + + + + OTYPER + OTYPER + GPIO port output type register + 0x4 + 0x20 + read-write + 0x00000000 + + + OT15 + Port x configuration bits (y = + 0..15) + 15 + 1 + + + + OT14 + Port x configuration bits (y = + 0..15) + 14 + 1 + + + + OT13 + Port x configuration bits (y = + 0..15) + 13 + 1 + + + + OT12 + Port x configuration bits (y = + 0..15) + 12 + 1 + + + + OT11 + Port x configuration bits (y = + 0..15) + 11 + 1 + + + + OT10 + Port x configuration bits (y = + 0..15) + 10 + 1 + + + + OT9 + Port x configuration bits (y = + 0..15) + 9 + 1 + + + + OT8 + Port x configuration bits (y = + 0..15) + 8 + 1 + + + + OT7 + Port x configuration bits (y = + 0..15) + 7 + 1 + + + + OT6 + Port x configuration bits (y = + 0..15) + 6 + 1 + + + + OT5 + Port x configuration bits (y = + 0..15) + 5 + 1 + + + + OT4 + Port x configuration bits (y = + 0..15) + 4 + 1 + + + + OT3 + Port x configuration bits (y = + 0..15) + 3 + 1 + + + + OT2 + Port x configuration bits (y = + 0..15) + 2 + 1 + + + + OT1 + Port x configuration bits (y = + 0..15) + 1 + 1 + + + + OT0 + Port x configuration bits (y = + 0..15) + 0 + 1 + + OT0 + read-write + + PushPull + Output push-pull (reset state) + 0 + + + OpenDrain + Output open-drain + 1 + + + + + + + OSPEEDR + OSPEEDR + GPIO port output speed + register + 0x8 + 0x20 + read-write + 0x00000000 + + + OSPEEDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + OSPEEDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + OSPEEDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + OSPEEDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + OSPEEDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + OSPEEDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + OSPEEDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + OSPEEDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + OSPEEDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + OSPEEDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + OSPEEDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + OSPEEDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + OSPEEDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + OSPEEDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + OSPEEDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + OSPEEDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + OSPEEDR0 + read-write + + LowSpeed + Low speed + 0 + + + MediumSpeed + Medium speed + 1 + + + HighSpeed + High speed + 2 + + + VeryHighSpeed + Very high speed + 3 + + + + + + + PUPDR + PUPDR + GPIO port pull-up/pull-down + register + 0xC + 0x20 + read-write + 0x64000000 + + + PUPDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + PUPDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + PUPDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + PUPDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + PUPDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + PUPDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + PUPDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + PUPDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + PUPDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + PUPDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + PUPDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + PUPDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + PUPDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + PUPDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + PUPDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + PUPDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + PUPDR0 + read-write + + Floating + No pull-up, pull-down + 0 + + + PullUp + Pull-up + 1 + + + PullDown + Pull-down + 2 + + + + + + + IDR + IDR + GPIO port input data register + 0x10 + 0x20 + read-only + 0x00000000 + + + IDR15 + Port input data (y = + 0..15) + 15 + 1 + + + + IDR14 + Port input data (y = + 0..15) + 14 + 1 + + + + IDR13 + Port input data (y = + 0..15) + 13 + 1 + + + + IDR12 + Port input data (y = + 0..15) + 12 + 1 + + + + IDR11 + Port input data (y = + 0..15) + 11 + 1 + + + + IDR10 + Port input data (y = + 0..15) + 10 + 1 + + + + IDR9 + Port input data (y = + 0..15) + 9 + 1 + + + + IDR8 + Port input data (y = + 0..15) + 8 + 1 + + + + IDR7 + Port input data (y = + 0..15) + 7 + 1 + + + + IDR6 + Port input data (y = + 0..15) + 6 + 1 + + + + IDR5 + Port input data (y = + 0..15) + 5 + 1 + + + + IDR4 + Port input data (y = + 0..15) + 4 + 1 + + + + IDR3 + Port input data (y = + 0..15) + 3 + 1 + + + + IDR2 + Port input data (y = + 0..15) + 2 + 1 + + + + IDR1 + Port input data (y = + 0..15) + 1 + 1 + + + + IDR0 + Port input data (y = + 0..15) + 0 + 1 + + IDR0 + read + + Low + Input is logic low + 0 + + + High + Input is logic high + 1 + + + + + + + ODR + ODR + GPIO port output data register + 0x14 + 0x20 + read-write + 0x00000000 + + + ODR15 + Port output data (y = + 0..15) + 15 + 1 + + + + ODR14 + Port output data (y = + 0..15) + 14 + 1 + + + + ODR13 + Port output data (y = + 0..15) + 13 + 1 + + + + ODR12 + Port output data (y = + 0..15) + 12 + 1 + + + + ODR11 + Port output data (y = + 0..15) + 11 + 1 + + + + ODR10 + Port output data (y = + 0..15) + 10 + 1 + + + + ODR9 + Port output data (y = + 0..15) + 9 + 1 + + + + ODR8 + Port output data (y = + 0..15) + 8 + 1 + + + + ODR7 + Port output data (y = + 0..15) + 7 + 1 + + + + ODR6 + Port output data (y = + 0..15) + 6 + 1 + + + + ODR5 + Port output data (y = + 0..15) + 5 + 1 + + + + ODR4 + Port output data (y = + 0..15) + 4 + 1 + + + + ODR3 + Port output data (y = + 0..15) + 3 + 1 + + + + ODR2 + Port output data (y = + 0..15) + 2 + 1 + + + + ODR1 + Port output data (y = + 0..15) + 1 + 1 + + + + ODR0 + Port output data (y = + 0..15) + 0 + 1 + + ODR0 + read-write + + Low + Set output to logic low + 0 + + + High + Set output to logic high + 1 + + + + + + + BSRR + BSRR + GPIO port bit set/reset + register + 0x18 + 0x20 + write-only + 0x00000000 + + + BR15 + Port x reset bit y (y = + 0..15) + 31 + 1 + + + + BR14 + Port x reset bit y (y = + 0..15) + 30 + 1 + + + + BR13 + Port x reset bit y (y = + 0..15) + 29 + 1 + + + + BR12 + Port x reset bit y (y = + 0..15) + 28 + 1 + + + + BR11 + Port x reset bit y (y = + 0..15) + 27 + 1 + + + + BR10 + Port x reset bit y (y = + 0..15) + 26 + 1 + + + + BR9 + Port x reset bit y (y = + 0..15) + 25 + 1 + + + + BR8 + Port x reset bit y (y = + 0..15) + 24 + 1 + + + + BR7 + Port x reset bit y (y = + 0..15) + 23 + 1 + + + + BR6 + Port x reset bit y (y = + 0..15) + 22 + 1 + + + + BR5 + Port x reset bit y (y = + 0..15) + 21 + 1 + + + + BR4 + Port x reset bit y (y = + 0..15) + 20 + 1 + + + + BR3 + Port x reset bit y (y = + 0..15) + 19 + 1 + + + + BR2 + Port x reset bit y (y = + 0..15) + 18 + 1 + + + + BR1 + Port x reset bit y (y = + 0..15) + 17 + 1 + + + + BR0 + Port x set bit y (y= + 0..15) + 16 + 1 + + BR0W + write + + Reset + Resets the corresponding ODRx bit + 1 + + + + + BS15 + Port x set bit y (y= + 0..15) + 15 + 1 + + + + BS14 + Port x set bit y (y= + 0..15) + 14 + 1 + + + + BS13 + Port x set bit y (y= + 0..15) + 13 + 1 + + + + BS12 + Port x set bit y (y= + 0..15) + 12 + 1 + + + + BS11 + Port x set bit y (y= + 0..15) + 11 + 1 + + + + BS10 + Port x set bit y (y= + 0..15) + 10 + 1 + + + + BS9 + Port x set bit y (y= + 0..15) + 9 + 1 + + + + BS8 + Port x set bit y (y= + 0..15) + 8 + 1 + + + + BS7 + Port x set bit y (y= + 0..15) + 7 + 1 + + + + BS6 + Port x set bit y (y= + 0..15) + 6 + 1 + + + + BS5 + Port x set bit y (y= + 0..15) + 5 + 1 + + + + BS4 + Port x set bit y (y= + 0..15) + 4 + 1 + + + + BS3 + Port x set bit y (y= + 0..15) + 3 + 1 + + + + BS2 + Port x set bit y (y= + 0..15) + 2 + 1 + + + + BS1 + Port x set bit y (y= + 0..15) + 1 + 1 + + + + BS0 + Port x set bit y (y= + 0..15) + 0 + 1 + + BS0W + write + + Set + Sets the corresponding ODRx bit + 1 + + + + + + + LCKR + LCKR + GPIO port configuration lock + register + 0x1C + 0x20 + read-write + 0x00000000 + + + LCKK + Port x lock bit y (y= + 0..15) + 16 + 1 + + LCKK + read-write + + NotActive + Port configuration lock key not active + 0 + + + Active + Port configuration lock key active + 1 + + + + + LCK15 + Port x lock bit y (y= + 0..15) + 15 + 1 + + + + LCK14 + Port x lock bit y (y= + 0..15) + 14 + 1 + + + + LCK13 + Port x lock bit y (y= + 0..15) + 13 + 1 + + + + LCK12 + Port x lock bit y (y= + 0..15) + 12 + 1 + + + + LCK11 + Port x lock bit y (y= + 0..15) + 11 + 1 + + + + LCK10 + Port x lock bit y (y= + 0..15) + 10 + 1 + + + + LCK9 + Port x lock bit y (y= + 0..15) + 9 + 1 + + + + LCK8 + Port x lock bit y (y= + 0..15) + 8 + 1 + + + + LCK7 + Port x lock bit y (y= + 0..15) + 7 + 1 + + + + LCK6 + Port x lock bit y (y= + 0..15) + 6 + 1 + + + + LCK5 + Port x lock bit y (y= + 0..15) + 5 + 1 + + + + LCK4 + Port x lock bit y (y= + 0..15) + 4 + 1 + + + + LCK3 + Port x lock bit y (y= + 0..15) + 3 + 1 + + + + LCK2 + Port x lock bit y (y= + 0..15) + 2 + 1 + + + + LCK1 + Port x lock bit y (y= + 0..15) + 1 + 1 + + + + LCK0 + Port x lock bit y (y= + 0..15) + 0 + 1 + + LCK0 + read-write + + Unlocked + Port configuration not locked + 0 + + + Locked + Port configuration locked + 1 + + + + + + + AFRL + AFRL + GPIO alternate function low + register + 0x20 + 0x20 + read-write + 0x00000000 + + + AFRL7 + Alternate function selection for port x + bit y (y = 0..7) + 28 + 4 + + + + AFRL6 + Alternate function selection for port x + bit y (y = 0..7) + 24 + 4 + + + + AFRL5 + Alternate function selection for port x + bit y (y = 0..7) + 20 + 4 + + + + AFRL4 + Alternate function selection for port x + bit y (y = 0..7) + 16 + 4 + + + + AFRL3 + Alternate function selection for port x + bit y (y = 0..7) + 12 + 4 + + + + AFRL2 + Alternate function selection for port x + bit y (y = 0..7) + 8 + 4 + + + + AFRL1 + Alternate function selection for port x + bit y (y = 0..7) + 4 + 4 + + + + AFRL0 + Alternate function selection for port x + bit y (y = 0..7) + 0 + 4 + + AFRL0 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + AFRH + AFRH + GPIO alternate function high + register + 0x24 + 0x20 + read-write + 0x00000000 + + + AFRH15 + Alternate function selection for port x + bit y (y = 8..15) + 28 + 4 + + + + AFRH14 + Alternate function selection for port x + bit y (y = 8..15) + 24 + 4 + + + + AFRH13 + Alternate function selection for port x + bit y (y = 8..15) + 20 + 4 + + + + AFRH12 + Alternate function selection for port x + bit y (y = 8..15) + 16 + 4 + + + + AFRH11 + Alternate function selection for port x + bit y (y = 8..15) + 12 + 4 + + + + AFRH10 + Alternate function selection for port x + bit y (y = 8..15) + 8 + 4 + + + + AFRH9 + Alternate function selection for port x + bit y (y = 8..15) + 4 + 4 + + + + AFRH8 + Alternate function selection for port x + bit y (y = 8..15) + 0 + 4 + + AFRH8 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + + + I2C3 + 0x40005C00 + + TIM3 + TIM3 global interrupt + 29 + + + + I2C2 + 0x40005800 + + I2C3_EV + I2C3 event interrupt + 72 + + + I2C3_ER + I2C3 error interrupt + 73 + + + + I2C1 + Inter-integrated circuit + I2C + 0x40005400 + + 0x0 + 0x400 + registers + + + I2C2_EV + I2C2 event interrupt + 33 + + + I2C2_ER + I2C2 error interrupt + 34 + + + + CR1 + CR1 + Control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + SWRST + Software reset + 15 + 1 + + SWRST + read-write + + NotReset + I2C peripheral not under reset + 0 + + + Reset + I2C peripheral under reset + 1 + + + + + ALERT + SMBus alert + 13 + 1 + + ALERT + read-write + + Release + SMBA pin released high + 0 + + + Drive + SMBA pin driven low + 1 + + + + + PEC + Packet error checking + 12 + 1 + + PEC + read-write + + Disabled + No PEC transfer + 0 + + + Enabled + PEC transfer + 1 + + + + + POS + Acknowledge/PEC Position (for data + reception) + 11 + 1 + + POS + read-write + + Current + ACK bit controls the (N)ACK of the current byte being received + 0 + + + Next + ACK bit controls the (N)ACK of the next byte to be received + 1 + + + + + ACK + Acknowledge enable + 10 + 1 + + ACK + read-write + + NAK + No acknowledge returned + 0 + + + ACK + Acknowledge returned after a byte is received + 1 + + + + + STOP + Stop generation + 9 + 1 + + STOP + read-write + + NoStop + No Stop generation + 0 + + + Stop + In master mode: stop generation after current byte/start, in slave mode: release SCL and SDA after current byte + 1 + + + + + START + Start generation + 8 + 1 + + START + read-write + + NoStart + No Start generation + 0 + + + Start + In master mode: repeated start generation, in slave mode: start generation when bus is free + 1 + + + + + NOSTRETCH + Clock stretching disable (Slave + mode) + 7 + 1 + + NOSTRETCH + read-write + + Enabled + Clock stretching enabled + 0 + + + Disabled + Clock stretching disabled + 1 + + + + + ENGC + General call enable + 6 + 1 + + ENGC + read-write + + Disabled + General call disabled + 0 + + + Enabled + General call enabled + 1 + + + + + ENPEC + PEC enable + 5 + 1 + + ENPEC + read-write + + Disabled + PEC calculation disabled + 0 + + + Enabled + PEC calculation enabled + 1 + + + + + ENARP + ARP enable + 4 + 1 + + ENARP + read-write + + Disabled + ARP disabled + 0 + + + Enabled + ARP enabled + 1 + + + + + SMBTYPE + SMBus type + 3 + 1 + + SMBTYPE + read-write + + Device + SMBus Device + 0 + + + Host + SMBus Host + 1 + + + + + SMBUS + SMBus mode + 1 + 1 + + SMBUS + read-write + + I2C + I2C Mode + 0 + + + SMBus + SMBus + 1 + + + + + PE + Peripheral enable + 0 + 1 + + PE + read-write + + Disabled + Peripheral disabled + 0 + + + Enabled + Peripheral enabled + 1 + + + + + + + CR2 + CR2 + Control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + LAST + DMA last transfer + 12 + 1 + + LAST + read-write + + NotLast + Next DMA EOT is not the last transfer + 0 + + + Last + Next DMA EOT is the last transfer + 1 + + + + + DMAEN + DMA requests enable + 11 + 1 + + DMAEN + read-write + + Disabled + DMA requests disabled + 0 + + + Enabled + DMA request enabled when TxE=1 or RxNE=1 + 1 + + + + + ITBUFEN + Buffer interrupt enable + 10 + 1 + + ITBUFEN + read-write + + Disabled + TxE=1 or RxNE=1 does not generate any interrupt + 0 + + + Enabled + TxE=1 or RxNE=1 generates Event interrupt + 1 + + + + + ITEVTEN + Event interrupt enable + 9 + 1 + + ITEVTEN + read-write + + Disabled + Event interrupt disabled + 0 + + + Enabled + Event interrupt enabled + 1 + + + + + ITERREN + Error interrupt enable + 8 + 1 + + ITERREN + read-write + + Disabled + Error interrupt disabled + 0 + + + Enabled + Error interrupt enabled + 1 + + + + + FREQ + Peripheral clock frequency + 0 + 6 + + + 2 + 50 + + + + + + + OAR1 + OAR1 + Own address register 1 + 0x8 + 0x20 + read-write + 0x00000000 + + + ADDMODE + Addressing mode (slave + mode) + 15 + 1 + + ADDMODE + read-write + + ADD7 + 7-bit slave address + 0 + + + ADD10 + 10-bit slave address + 1 + + + + + ADD + Interface address + 0 + 10 + + + 0 + 1023 + + + + + + + OAR2 + OAR2 + Own address register 2 + 0xC + 0x20 + read-write + 0x00000000 + + + ADD2 + Interface address + 1 + 7 + + + 0 + 127 + + + + + ENDUAL + Dual addressing mode + enable + 0 + 1 + + ENDUAL + read-write + + Single + Single addressing mode + 0 + + + Dual + Dual addressing mode + 1 + + + + + + + DR + DR + Data register + 0x10 + 0x20 + read-write + 0x00000000 + + + DR + 8-bit data register + 0 + 8 + + + 0 + 255 + + + + + + + SR1 + SR1 + Status register 1 + 0x14 + 0x20 + 0x00000000 + + + SMBALERT + SMBus alert + 15 + 1 + read-write + zeroToClear + + SMBALERTR + read + + NoAlert + No SMBALERT occured + 0 + + + Alert + SMBALERT occurred + 1 + + + + SMBALERTW + write + + Clear + Clear flag + 0 + + + + + TIMEOUT + Timeout or Tlow error + 14 + 1 + read-write + zeroToClear + + TIMEOUTR + read + + NoTimeout + No Timeout error + 0 + + + Timeout + SCL remained LOW for 25 ms + 1 + + + + TIMEOUTW + write + + Clear + Clear flag + 0 + + + + + PECERR + PEC Error in reception + 12 + 1 + read-write + zeroToClear + + PECERRR + read + + NoError + no PEC error: receiver returns ACK after PEC reception (if ACK=1) + 0 + + + Error + PEC error: receiver returns NACK after PEC reception (whatever ACK) + 1 + + + + PECERRW + write + + Clear + Clear flag + 0 + + + + + OVR + Overrun/Underrun + 11 + 1 + read-write + zeroToClear + + OVRR + read + + NoOverrun + No overrun/underrun occured + 0 + + + Overrun + Overrun/underrun occured + 1 + + + + OVRW + write + + Clear + Clear flag + 0 + + + + + AF + Acknowledge failure + 10 + 1 + read-write + zeroToClear + + AFR + read + + NoFailure + No acknowledge failure + 0 + + + Failure + Acknowledge failure + 1 + + + + AFW + write + + Clear + Clear flag + 0 + + + + + ARLO + Arbitration lost (master + mode) + 9 + 1 + read-write + zeroToClear + + ARLOR + read + + NoLost + No Arbitration Lost detected + 0 + + + Lost + Arbitration Lost detected + 1 + + + + ARLOW + write + + Clear + Clear flag + 0 + + + + + BERR + Bus error + 8 + 1 + read-write + zeroToClear + + BERRR + read + + NoError + No misplaced Start or Stop condition + 0 + + + Error + Misplaced Start or Stop condition + 1 + + + + BERRW + write + + Clear + Clear flag + 0 + + + + + TxE + Data register empty + (transmitters) + 7 + 1 + read-only + + TxE + read + + NotEmpty + Data register not empty + 0 + + + Empty + Data register empty + 1 + + + + + RxNE + Data register not empty + (receivers) + 6 + 1 + read-only + + RxNE + read + + Empty + Data register empty + 0 + + + NotEmpty + Data register not empty + 1 + + + + + STOPF + Stop detection (slave + mode) + 4 + 1 + read-only + + STOPF + read + + NoStop + No Stop condition detected + 0 + + + Stop + Stop condition detected + 1 + + + + + ADD10 + 10-bit header sent (Master + mode) + 3 + 1 + read-only + + + BTF + Byte transfer finished + 2 + 1 + read-only + + BTF + read + + NotFinished + Data byte transfer not done + 0 + + + Finished + Data byte transfer successful + 1 + + + + + ADDR + Address sent (master mode)/matched + (slave mode) + 1 + 1 + read-only + + ADDR + read + + NotMatch + Adress mismatched or not received + 0 + + + Match + Received slave address matched with one of the enabled slave addresses + 1 + + + + + SB + Start bit (Master mode) + 0 + 1 + read-only + + SB + read + + NoStart + No Start condition + 0 + + + Start + Start condition generated + 1 + + + + + + + SR2 + SR2 + Status register 2 + 0x18 + 0x20 + read-only + 0x00000000 + + + PEC + acket error checking + register + 8 + 8 + + + DUALF + Dual flag (Slave mode) + 7 + 1 + + + SMBHOST + SMBus host header (Slave + mode) + 6 + 1 + + + SMBDEFAULT + SMBus device default address (Slave + mode) + 5 + 1 + + + GENCALL + General call address (Slave + mode) + 4 + 1 + + + TRA + Transmitter/receiver + 2 + 1 + + + BUSY + Bus busy + 1 + 1 + + + MSL + Master/slave + 0 + 1 + + + + + CCR + CCR + Clock control register + 0x1C + 0x20 + read-write + 0x00000000 + + + F_S + I2C master mode selection + 15 + 1 + + F_S + read-write + + Standard + Standard mode I2C + 0 + + + Fast + Fast mode I2C + 1 + + + + + DUTY + Fast mode duty cycle + 14 + 1 + + DUTY + read-write + + Duty2_1 + Duty cycle t_low/t_high = 2/1 + 0 + + + Duty16_9 + Duty cycle t_low/t_high = 16/9 + 1 + + + + + CCR + Clock control register in Fast/Standard + mode (Master mode) + 0 + 12 + + + 1 + 4095 + + + + + + + TRISE + TRISE + TRISE register + 0x20 + 0x20 + read-write + 0x00000002 + + + TRISE + Maximum rise time in Fast/Standard mode + (Master mode) + 0 + 6 + + + 0 + 63 + + + + + + + FLTR + FLTR register + 0x24 + read-write + 0x00000000 + + + ANOFF + Analog noise filter + 4 + 1 + + ANOFF + read-write + + Enabled + Analog noise filter enabled + 0 + + + Disabled + Analog noise filter disabled + 1 + + + + + DNF + Digital noise filter + 0 + 4 + + DNF + read-write + + NoFilter + Digital filter disabled + 0 + + + Filter1 + Digital filter enabled and filtering capability up to 1 tI2CCLK + 1 + + + Filter2 + Digital filter enabled and filtering capability up to 2 tI2CCLK + 2 + + + Filter3 + Digital filter enabled and filtering capability up to 3 tI2CCLK + 3 + + + Filter4 + Digital filter enabled and filtering capability up to 4 tI2CCLK + 4 + + + Filter5 + Digital filter enabled and filtering capability up to 5 tI2CCLK + 5 + + + Filter6 + Digital filter enabled and filtering capability up to 6 tI2CCLK + 6 + + + Filter7 + Digital filter enabled and filtering capability up to 7 tI2CCLK + 7 + + + Filter8 + Digital filter enabled and filtering capability up to 8 tI2CCLK + 8 + + + Filter9 + Digital filter enabled and filtering capability up to 9 tI2CCLK + 9 + + + Filter10 + Digital filter enabled and filtering capability up to 10 tI2CCLK + 10 + + + Filter11 + Digital filter enabled and filtering capability up to 11 tI2CCLK + 11 + + + Filter12 + Digital filter enabled and filtering capability up to 12 tI2CCLK + 12 + + + Filter13 + Digital filter enabled and filtering capability up to 13 tI2CCLK + 13 + + + Filter14 + Digital filter enabled and filtering capability up to 14 tI2CCLK + 14 + + + Filter15 + Digital filter enabled and filtering capability up to 15 tI2CCLK + 15 + + + + + + + + + I2S2ext + 0x40003400 + + I2C1_EV + I2C1 event interrupt + 31 + + + I2C1_ER + I2C1 error interrupt + 32 + + + + I2S3ext + 0x40004000 + + + SPI1 + Serial peripheral interface + SPI + 0x40013000 + + 0x0 + 0x400 + registers + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + BIDIMODE + Bidirectional data mode + enable + 15 + 1 + + BIDIMODE + read-write + + Unidirectional + 2-line unidirectional data mode selected + 0 + + + Bidirectional + 1-line bidirectional data mode selected + 1 + + + + + BIDIOE + Output enable in bidirectional + mode + 14 + 1 + + BIDIOE + read-write + + OutputDisabled + Output disabled (receive-only mode) + 0 + + + OutputEnabled + Output enabled (transmit-only mode) + 1 + + + + + CRCEN + Hardware CRC calculation + enable + 13 + 1 + + CRCEN + read-write + + Disabled + CRC calculation disabled + 0 + + + Enabled + CRC calculation enabled + 1 + + + + + CRCNEXT + CRC transfer next + 12 + 1 + + CRCNEXT + read-write + + TxBuffer + Next transmit value is from Tx buffer + 0 + + + CRC + Next transmit value is from Tx CRC register + 1 + + + + + DFF + Data frame format + 11 + 1 + + DFF + read-write + + EightBit + 8-bit data frame format is selected for transmission/reception + 0 + + + SixteenBit + 16-bit data frame format is selected for transmission/reception + 1 + + + + + RXONLY + Receive only + 10 + 1 + + RXONLY + read-write + + FullDuplex + Full duplex (Transmit and receive) + 0 + + + OutputDisabled + Output disabled (Receive-only mode) + 1 + + + + + SSM + Software slave management + 9 + 1 + + SSM + read-write + + Disabled + Software slave management disabled + 0 + + + Enabled + Software slave management enabled + 1 + + + + + SSI + Internal slave select + 8 + 1 + + SSI + read-write + + SlaveSelected + 0 is forced onto the NSS pin and the I/O value of the NSS pin is ignored + 0 + + + SlaveNotSelected + 1 is forced onto the NSS pin and the I/O value of the NSS pin is ignored + 1 + + + + + LSBFIRST + Frame format + 7 + 1 + + LSBFIRST + read-write + + MSBFirst + Data is transmitted/received with the MSB first + 0 + + + LSBFirst + Data is transmitted/received with the LSB first + 1 + + + + + SPE + SPI enable + 6 + 1 + + SPE + read-write + + Disabled + Peripheral disabled + 0 + + + Enabled + Peripheral enabled + 1 + + + + + BR + Baud rate control + 3 + 3 + + BR + read-write + + Div2 + f_PCLK / 2 + 0 + + + Div4 + f_PCLK / 4 + 1 + + + Div8 + f_PCLK / 8 + 2 + + + Div16 + f_PCLK / 16 + 3 + + + Div32 + f_PCLK / 32 + 4 + + + Div64 + f_PCLK / 64 + 5 + + + Div128 + f_PCLK / 128 + 6 + + + Div256 + f_PCLK / 256 + 7 + + + + + MSTR + Master selection + 2 + 1 + + MSTR + read-write + + Slave + Slave configuration + 0 + + + Master + Master configuration + 1 + + + + + CPOL + Clock polarity + 1 + 1 + + CPOL + read-write + + IdleLow + CK to 0 when idle + 0 + + + IdleHigh + CK to 1 when idle + 1 + + + + + CPHA + Clock phase + 0 + 1 + + CPHA + read-write + + FirstEdge + The first clock transition is the first data capture edge + 0 + + + SecondEdge + The second clock transition is the first data capture edge + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + TXEIE + Tx buffer empty interrupt + enable + 7 + 1 + + TXEIE + read-write + + Masked + TXE interrupt masked + 0 + + + NotMasked + TXE interrupt not masked + 1 + + + + + RXNEIE + RX buffer not empty interrupt + enable + 6 + 1 + + RXNEIE + read-write + + Masked + RXE interrupt masked + 0 + + + NotMasked + RXE interrupt not masked + 1 + + + + + ERRIE + Error interrupt enable + 5 + 1 + + ERRIE + read-write + + Masked + Error interrupt masked + 0 + + + NotMasked + Error interrupt not masked + 1 + + + + + FRF + Frame format + 4 + 1 + + FRF + read-write + + Motorola + SPI Motorola mode + 0 + + + TI + SPI TI mode + 1 + + + + + SSOE + SS output enable + 2 + 1 + + SSOE + read-write + + Disabled + SS output is disabled in master mode + 0 + + + Enabled + SS output is enabled in master mode + 1 + + + + + TXDMAEN + Tx buffer DMA enable + 1 + 1 + + TXDMAEN + read-write + + Disabled + Tx buffer DMA disabled + 0 + + + Enabled + Tx buffer DMA enabled + 1 + + + + + RXDMAEN + Rx buffer DMA enable + 0 + 1 + + RXDMAEN + read-write + + Disabled + Rx buffer DMA disabled + 0 + + + Enabled + Rx buffer DMA enabled + 1 + + + + + + + SR + SR + status register + 0x8 + 0x20 + 0x00000002 + + + FRE + TI frame format error + 8 + 1 + read-only + + FRER + read + + NoError + No frame format error + 0 + + + Error + A frame format error occurred + 1 + + + + + BSY + Busy flag + 7 + 1 + read-only + + BSYR + read + + NotBusy + SPI not busy + 0 + + + Busy + SPI busy + 1 + + + + + OVR + Overrun flag + 6 + 1 + read-only + + OVRR + read + + NoOverrun + No overrun occurred + 0 + + + Overrun + Overrun occurred + 1 + + + + + MODF + Mode fault + 5 + 1 + read-only + + MODFR + read + + NoFault + No mode fault occurred + 0 + + + Fault + Mode fault occurred + 1 + + + + + CRCERR + CRC error flag + 4 + 1 + read-write + zeroToClear + + CRCERRR + read + + Match + CRC value received matches the SPIx_RXCRCR value + 0 + + + NoMatch + CRC value received does not match the SPIx_RXCRCR value + 1 + + + + CRCERRW + write + + Clear + Clear flag + 0 + + + + + UDR + Underrun flag + 3 + 1 + read-only + + UDRR + read + + NoUnderrun + No underrun occurred + 0 + + + Underrun + Underrun occurred + 1 + + + + + CHSIDE + Channel side + 2 + 1 + read-only + + CHSIDE + read + + Left + Channel left has to be transmitted or has been received + 0 + + + Right + Channel right has to be transmitted or has been received + 1 + + + + + TXE + Transmit buffer empty + 1 + 1 + read-only + + TXE + read + + NotEmpty + Tx buffer not empty + 0 + + + Empty + Tx buffer empty + 1 + + + + + RXNE + Receive buffer not empty + 0 + 1 + read-only + + RXNE + read + + Empty + Rx buffer empty + 0 + + + NotEmpty + Rx buffer not empty + 1 + + + + + + + DR + DR + data register + 0xC + 0x20 + read-write + 0x00000000 + + + DR + Data register + 0 + 16 + + + 0 + 65535 + + + + + + + CRCPR + CRCPR + CRC polynomial register + 0x10 + 0x20 + read-write + 0x00000007 + + + CRCPOLY + CRC polynomial register + 0 + 16 + + + 0 + 65535 + + + + + + + RXCRCR + RXCRCR + RX CRC register + 0x14 + 0x20 + read-only + 0x00000000 + + + RxCRC + Rx CRC register + 0 + 16 + + + 0 + 65535 + + + + + + + TXCRCR + TXCRCR + TX CRC register + 0x18 + 0x20 + read-only + 0x00000000 + + + TxCRC + Tx CRC register + 0 + 16 + + + 0 + 65535 + + + + + + + I2SCFGR + I2SCFGR + I2S configuration register + 0x1C + 0x20 + read-write + 0x00000000 + + + I2SMOD + I2S mode selection + 11 + 1 + + I2SMOD + read-write + + SPIMode + SPI mode is selected + 0 + + + I2SMode + I2S mode is selected + 1 + + + + + I2SE + I2S Enable + 10 + 1 + + I2SE + read-write + + Disabled + I2S peripheral is disabled + 0 + + + Enabled + I2S peripheral is enabled + 1 + + + + + I2SCFG + I2S configuration mode + 8 + 2 + + I2SCFG + read-write + + SlaveTx + Slave - transmit + 0 + + + SlaveRx + Slave - receive + 1 + + + MasterTx + Master - transmit + 2 + + + MasterRx + Master - receive + 3 + + + + + PCMSYNC + PCM frame synchronization + 7 + 1 + + PCMSYNC + read-write + + Short + Short frame synchronisation + 0 + + + Long + Long frame synchronisation + 1 + + + + + I2SSTD + I2S standard selection + 4 + 2 + + I2SSTD + read-write + + Philips + I2S Philips standard + 0 + + + MSB + MSB justified standard + 1 + + + LSB + LSB justified standard + 2 + + + PCM + PCM standard + 3 + + + + + CKPOL + Steady state clock + polarity + 3 + 1 + + CKPOL + read-write + + IdleLow + I2S clock inactive state is low level + 0 + + + IdleHigh + I2S clock inactive state is high level + 1 + + + + + DATLEN + Data length to be + transferred + 1 + 2 + + DATLEN + read-write + + SixteenBit + 16-bit data length + 0 + + + TwentyFourBit + 24-bit data length + 1 + + + ThirtyTwoBit + 32-bit data length + 2 + + + + + CHLEN + Channel length (number of bits per audio + channel) + 0 + 1 + + CHLEN + read-write + + SixteenBit + 16-bit wide + 0 + + + ThirtyTwoBit + 32-bit wide + 1 + + + + + + + I2SPR + I2SPR + I2S prescaler register + 0x20 + 0x20 + read-write + 0x0000000A + + + MCKOE + Master clock output enable + 9 + 1 + + MCKOE + read-write + + Disabled + Master clock output is disabled + 0 + + + Enabled + Master clock output is enabled + 1 + + + + + ODD + Odd factor for the + prescaler + 8 + 1 + + ODD + read-write + + Even + Real divider value is I2SDIV * 2 + 0 + + + Odd + Real divider value is (I2SDIV * 2) + 1 + 1 + + + + + I2SDIV + I2S Linear prescaler + 0 + 8 + + + 2 + 255 + + + + + + + + + SPI2 + 0x40003800 + + SPI1 + SPI1 global interrupt + 35 + + + + SPI3 + 0x40003C00 + + SPI2 + SPI2 global interrupt + 36 + + + + SPI4 + 0x40013400 + + SPI3 + SPI3 global interrupt + 51 + + + + NVIC + Nested Vectored Interrupt + Controller + NVIC + 0xE000E100 + + 0x0 + 0x351 + registers + + + + ISER0 + ISER0 + Interrupt Set-Enable Register + 0x0 + 0x20 + read-write + 0x00000000 + + + SETENA + SETENA + 0 + 32 + + + + + ISER1 + ISER1 + Interrupt Set-Enable Register + 0x4 + 0x20 + read-write + 0x00000000 + + + SETENA + SETENA + 0 + 32 + + + + + ISER2 + ISER2 + Interrupt Set-Enable Register + 0x8 + 0x20 + read-write + 0x00000000 + + + SETENA + SETENA + 0 + 32 + + + + + ICER0 + ICER0 + Interrupt Clear-Enable + Register + 0x80 + 0x20 + read-write + 0x00000000 + + + CLRENA + CLRENA + 0 + 32 + + + + + ICER1 + ICER1 + Interrupt Clear-Enable + Register + 0x84 + 0x20 + read-write + 0x00000000 + + + CLRENA + CLRENA + 0 + 32 + + + + + ICER2 + ICER2 + Interrupt Clear-Enable + Register + 0x88 + 0x20 + read-write + 0x00000000 + + + CLRENA + CLRENA + 0 + 32 + + + + + ISPR0 + ISPR0 + Interrupt Set-Pending Register + 0x100 + 0x20 + read-write + 0x00000000 + + + SETPEND + SETPEND + 0 + 32 + + + + + ISPR1 + ISPR1 + Interrupt Set-Pending Register + 0x104 + 0x20 + read-write + 0x00000000 + + + SETPEND + SETPEND + 0 + 32 + + + + + ISPR2 + ISPR2 + Interrupt Set-Pending Register + 0x108 + 0x20 + read-write + 0x00000000 + + + SETPEND + SETPEND + 0 + 32 + + + + + ICPR0 + ICPR0 + Interrupt Clear-Pending + Register + 0x180 + 0x20 + read-write + 0x00000000 + + + CLRPEND + CLRPEND + 0 + 32 + + + + + ICPR1 + ICPR1 + Interrupt Clear-Pending + Register + 0x184 + 0x20 + read-write + 0x00000000 + + + CLRPEND + CLRPEND + 0 + 32 + + + + + ICPR2 + ICPR2 + Interrupt Clear-Pending + Register + 0x188 + 0x20 + read-write + 0x00000000 + + + CLRPEND + CLRPEND + 0 + 32 + + + + + IABR0 + IABR0 + Interrupt Active Bit Register + 0x200 + 0x20 + read-only + 0x00000000 + + + ACTIVE + ACTIVE + 0 + 32 + + + + + IABR1 + IABR1 + Interrupt Active Bit Register + 0x204 + 0x20 + read-only + 0x00000000 + + + ACTIVE + ACTIVE + 0 + 32 + + + + + IABR2 + IABR2 + Interrupt Active Bit Register + 0x208 + 0x20 + read-only + 0x00000000 + + + ACTIVE + ACTIVE + 0 + 32 + + + + + IPR0 + IPR0 + Interrupt Priority Register + 0x300 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR1 + IPR1 + Interrupt Priority Register + 0x304 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR2 + IPR2 + Interrupt Priority Register + 0x308 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR3 + IPR3 + Interrupt Priority Register + 0x30C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR4 + IPR4 + Interrupt Priority Register + 0x310 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR5 + IPR5 + Interrupt Priority Register + 0x314 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR6 + IPR6 + Interrupt Priority Register + 0x318 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR7 + IPR7 + Interrupt Priority Register + 0x31C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR8 + IPR8 + Interrupt Priority Register + 0x320 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR9 + IPR9 + Interrupt Priority Register + 0x324 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR10 + IPR10 + Interrupt Priority Register + 0x328 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR11 + IPR11 + Interrupt Priority Register + 0x32C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR12 + IPR12 + Interrupt Priority Register + 0x330 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR13 + IPR13 + Interrupt Priority Register + 0x334 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR14 + IPR14 + Interrupt Priority Register + 0x338 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR15 + IPR15 + Interrupt Priority Register + 0x33C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR16 + IPR16 + Interrupt Priority Register + 0x340 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR17 + IPR17 + Interrupt Priority Register + 0x344 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR18 + IPR18 + Interrupt Priority Register + 0x348 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR19 + IPR19 + Interrupt Priority Register + 0x34C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + + + FPU + Floting point unit + FPU + 0xE000EF34 + + 0x0 + 0xD + registers + + + FPU + Floating point unit interrupt + 81 + + + + FPCCR + FPCCR + Floating-point context control + register + 0x0 + 0x20 + read-write + 0x00000000 + + + LSPACT + LSPACT + 0 + 1 + + + USER + USER + 1 + 1 + + + THREAD + THREAD + 3 + 1 + + + HFRDY + HFRDY + 4 + 1 + + + MMRDY + MMRDY + 5 + 1 + + + BFRDY + BFRDY + 6 + 1 + + + MONRDY + MONRDY + 8 + 1 + + + LSPEN + LSPEN + 30 + 1 + + + ASPEN + ASPEN + 31 + 1 + + + + + FPCAR + FPCAR + Floating-point context address + register + 0x4 + 0x20 + read-write + 0x00000000 + + + ADDRESS + Location of unpopulated + floating-point + 3 + 29 + + + + + FPSCR + FPSCR + Floating-point status control + register + 0x8 + 0x20 + read-write + 0x00000000 + + + IOC + Invalid operation cumulative exception + bit + 0 + 1 + + + DZC + Division by zero cumulative exception + bit. + 1 + 1 + + + OFC + Overflow cumulative exception + bit + 2 + 1 + + + UFC + Underflow cumulative exception + bit + 3 + 1 + + + IXC + Inexact cumulative exception + bit + 4 + 1 + + + IDC + Input denormal cumulative exception + bit. + 7 + 1 + + + RMode + Rounding Mode control + field + 22 + 2 + + + FZ + Flush-to-zero mode control + bit: + 24 + 1 + + + DN + Default NaN mode control + bit + 25 + 1 + + + AHP + Alternative half-precision control + bit + 26 + 1 + + + V + Overflow condition code + flag + 28 + 1 + + + C + Carry condition code flag + 29 + 1 + + + Z + Zero condition code flag + 30 + 1 + + + N + Negative condition code + flag + 31 + 1 + + + + + + + MPU + Memory protection unit + MPU + 0xE000ED90 + + 0x0 + 0x15 + registers + + + + TYPER + TYPER + MPU type register + 0x0 + 0x20 + read-only + 0x00000800 + + + SEPARATE + Separate flag + 0 + 1 + + + DREGION + Number of MPU data regions + 8 + 8 + + + IREGION + Number of MPU instruction + regions + 16 + 8 + + + + + CTRL + CTRL + MPU control register + 0x4 + 0x20 + read-only + 0x00000000 + + + ENABLE + Enables the MPU + 0 + 1 + + + HFNMIENA + Enables the operation of MPU during hard + fault + 1 + 1 + + + PRIVDEFENA + Enable priviliged software access to + default memory map + 2 + 1 + + + + + RNR + RNR + MPU region number register + 0x8 + 0x20 + read-write + 0x00000000 + + + REGION + MPU region + 0 + 8 + + + + + RBAR + RBAR + MPU region base address + register + 0xC + 0x20 + read-write + 0x00000000 + + + REGION + MPU region field + 0 + 4 + + + VALID + MPU region number valid + 4 + 1 + + + ADDR + Region base address field + 5 + 27 + + + + + RASR + RASR + MPU region attribute and size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + ENABLE + Region enable bit. + 0 + 1 + + + SIZE + Size of the MPU protection + region + 1 + 5 + + + SRD + Subregion disable bits + 8 + 8 + + + B + memory attribute + 16 + 1 + + + C + memory attribute + 17 + 1 + + + S + Shareable memory attribute + 18 + 1 + + + TEX + memory attribute + 19 + 3 + + + AP + Access permission + 24 + 3 + + + XN + Instruction access disable + bit + 28 + 1 + + + + + + + STK + SysTick timer + STK + 0xE000E010 + + 0x0 + 0x11 + registers + + + + CTRL + CTRL + SysTick control and status + register + 0x0 + 0x20 + read-write + 0x00000000 + + + ENABLE + Counter enable + 0 + 1 + + + TICKINT + SysTick exception request + enable + 1 + 1 + + + CLKSOURCE + Clock source selection + 2 + 1 + + + COUNTFLAG + COUNTFLAG + 16 + 1 + + + + + LOAD + LOAD + SysTick reload value register + 0x4 + 0x20 + read-write + 0x00000000 + + + RELOAD + RELOAD value + 0 + 24 + + + + + VAL + VAL + SysTick current value register + 0x8 + 0x20 + read-write + 0x00000000 + + + CURRENT + Current counter value + 0 + 24 + + + + + CALIB + CALIB + SysTick calibration value + register + 0xC + 0x20 + read-write + 0x00000000 + + + TENMS + Calibration value + 0 + 24 + + + SKEW + SKEW flag: Indicates whether the TENMS + value is exact + 30 + 1 + + + NOREF + NOREF flag. Reads as zero + 31 + 1 + + + + + + + SCB + System control block + SCB + 0xE000ED00 + + 0x0 + 0x41 + registers + + + + CPUID + CPUID + CPUID base register + 0x0 + 0x20 + read-only + 0x410FC241 + + + Revision + Revision number + 0 + 4 + + + PartNo + Part number of the + processor + 4 + 12 + + + Constant + Reads as 0xF + 16 + 4 + + + Variant + Variant number + 20 + 4 + + + Implementer + Implementer code + 24 + 8 + + + + + ICSR + ICSR + Interrupt control and state + register + 0x4 + 0x20 + read-write + 0x00000000 + + + VECTACTIVE + Active vector + 0 + 9 + + + RETTOBASE + Return to base level + 11 + 1 + + + VECTPENDING + Pending vector + 12 + 7 + + + ISRPENDING + Interrupt pending flag + 22 + 1 + + + PENDSTCLR + SysTick exception clear-pending + bit + 25 + 1 + + + PENDSTSET + SysTick exception set-pending + bit + 26 + 1 + + + PENDSVCLR + PendSV clear-pending bit + 27 + 1 + + + PENDSVSET + PendSV set-pending bit + 28 + 1 + + + NMIPENDSET + NMI set-pending bit. + 31 + 1 + + + + + VTOR + VTOR + Vector table offset register + 0x8 + 0x20 + read-write + 0x00000000 + + + TBLOFF + Vector table base offset + field + 9 + 21 + + + + + AIRCR + AIRCR + Application interrupt and reset control + register + 0xC + 0x20 + read-write + 0x00000000 + + + VECTRESET + VECTRESET + 0 + 1 + + + VECTCLRACTIVE + VECTCLRACTIVE + 1 + 1 + + + SYSRESETREQ + SYSRESETREQ + 2 + 1 + + + PRIGROUP + PRIGROUP + 8 + 3 + + + ENDIANESS + ENDIANESS + 15 + 1 + + + VECTKEYSTAT + Register key + 16 + 16 + + + + + SCR + SCR + System control register + 0x10 + 0x20 + read-write + 0x00000000 + + + SLEEPONEXIT + SLEEPONEXIT + 1 + 1 + + + SLEEPDEEP + SLEEPDEEP + 2 + 1 + + + SEVEONPEND + Send Event on Pending bit + 4 + 1 + + + + + CCR + CCR + Configuration and control + register + 0x14 + 0x20 + read-write + 0x00000000 + + + NONBASETHRDENA + Configures how the processor enters + Thread mode + 0 + 1 + + + USERSETMPEND + USERSETMPEND + 1 + 1 + + + UNALIGN__TRP + UNALIGN_ TRP + 3 + 1 + + + DIV_0_TRP + DIV_0_TRP + 4 + 1 + + + BFHFNMIGN + BFHFNMIGN + 8 + 1 + + + STKALIGN + STKALIGN + 9 + 1 + + + + + SHPR1 + SHPR1 + System handler priority + registers + 0x18 + 0x20 + read-write + 0x00000000 + + + PRI_4 + Priority of system handler + 4 + 0 + 8 + + + PRI_5 + Priority of system handler + 5 + 8 + 8 + + + PRI_6 + Priority of system handler + 6 + 16 + 8 + + + + + SHPR2 + SHPR2 + System handler priority + registers + 0x1C + 0x20 + read-write + 0x00000000 + + + PRI_11 + Priority of system handler + 11 + 24 + 8 + + + + + SHPR3 + SHPR3 + System handler priority + registers + 0x20 + 0x20 + read-write + 0x00000000 + + + PRI_14 + Priority of system handler + 14 + 16 + 8 + + + PRI_15 + Priority of system handler + 15 + 24 + 8 + + + + + SHCRS + SHCRS + System handler control and state + register + 0x24 + 0x20 + read-write + 0x00000000 + + + MEMFAULTACT + Memory management fault exception active + bit + 0 + 1 + + + BUSFAULTACT + Bus fault exception active + bit + 1 + 1 + + + USGFAULTACT + Usage fault exception active + bit + 3 + 1 + + + SVCALLACT + SVC call active bit + 7 + 1 + + + MONITORACT + Debug monitor active bit + 8 + 1 + + + PENDSVACT + PendSV exception active + bit + 10 + 1 + + + SYSTICKACT + SysTick exception active + bit + 11 + 1 + + + USGFAULTPENDED + Usage fault exception pending + bit + 12 + 1 + + + MEMFAULTPENDED + Memory management fault exception + pending bit + 13 + 1 + + + BUSFAULTPENDED + Bus fault exception pending + bit + 14 + 1 + + + SVCALLPENDED + SVC call pending bit + 15 + 1 + + + MEMFAULTENA + Memory management fault enable + bit + 16 + 1 + + + BUSFAULTENA + Bus fault enable bit + 17 + 1 + + + USGFAULTENA + Usage fault enable bit + 18 + 1 + + + + + CFSR_UFSR_BFSR_MMFSR + CFSR_UFSR_BFSR_MMFSR + Configurable fault status + register + 0x28 + 0x20 + read-write + 0x00000000 + + + IACCVIOL + Instruction access violation + flag + 1 + 1 + + + MUNSTKERR + Memory manager fault on unstacking for a + return from exception + 3 + 1 + + + MSTKERR + Memory manager fault on stacking for + exception entry. + 4 + 1 + + + MLSPERR + MLSPERR + 5 + 1 + + + MMARVALID + Memory Management Fault Address Register + (MMAR) valid flag + 7 + 1 + + + IBUSERR + Instruction bus error + 8 + 1 + + + PRECISERR + Precise data bus error + 9 + 1 + + + IMPRECISERR + Imprecise data bus error + 10 + 1 + + + UNSTKERR + Bus fault on unstacking for a return + from exception + 11 + 1 + + + STKERR + Bus fault on stacking for exception + entry + 12 + 1 + + + LSPERR + Bus fault on floating-point lazy state + preservation + 13 + 1 + + + BFARVALID + Bus Fault Address Register (BFAR) valid + flag + 15 + 1 + + + UNDEFINSTR + Undefined instruction usage + fault + 16 + 1 + + + INVSTATE + Invalid state usage fault + 17 + 1 + + + INVPC + Invalid PC load usage + fault + 18 + 1 + + + NOCP + No coprocessor usage + fault. + 19 + 1 + + + UNALIGNED + Unaligned access usage + fault + 24 + 1 + + + DIVBYZERO + Divide by zero usage fault + 25 + 1 + + + + + HFSR + HFSR + Hard fault status register + 0x2C + 0x20 + read-write + 0x00000000 + + + VECTTBL + Vector table hard fault + 1 + 1 + + + FORCED + Forced hard fault + 30 + 1 + + + DEBUG_VT + Reserved for Debug use + 31 + 1 + + + + + MMFAR + MMFAR + Memory management fault address + register + 0x34 + 0x20 + read-write + 0x00000000 + + + MMFAR + Memory management fault + address + 0 + 32 + + + + + BFAR + BFAR + Bus fault address register + 0x38 + 0x20 + read-write + 0x00000000 + + + BFAR + Bus fault address + 0 + 32 + + + + + AFSR + AFSR + Auxiliary fault status + register + 0x3C + 0x20 + read-write + 0x00000000 + + + IMPDEF + Implementation defined + 0 + 32 + + + + + + + NVIC_STIR + Nested vectored interrupt + controller + NVIC + 0xE000EF00 + + 0x0 + 0x5 + registers + + + + STIR + STIR + Software trigger interrupt + register + 0x0 + 0x20 + read-write + 0x00000000 + + + INTID + Software generated interrupt + ID + 0 + 9 + + + + + + + FPU_CPACR + Floating point unit CPACR + FPU + 0xE000ED88 + + 0x0 + 0x5 + registers + + + + CPACR + CPACR + Coprocessor access control + register + 0x0 + 0x20 + read-write + 0x00000000 + + + CP + CP + 20 + 4 + + + + + + + SCB_ACTRL + System control block ACTLR + SCB + 0xE000E008 + + 0x0 + 0x5 + registers + + + + ACTRL + ACTRL + Auxiliary control register + 0x0 + 0x20 + read-write + 0x00000000 + + + DISMCYCINT + DISMCYCINT + 0 + 1 + + + DISDEFWBUF + DISDEFWBUF + 1 + 1 + + + DISFOLD + DISFOLD + 2 + 1 + + + DISFPCA + DISFPCA + 8 + 1 + + + DISOOFP + DISOOFP + 9 + 1 + + + + + + + \ No newline at end of file From 1292355e531b11cb37668a915c8a5a6143f55904 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 26 Mar 2025 18:11:42 +0100 Subject: [PATCH 616/687] improved usb bridge error msgs --- crates/usb-bridge/deploy.sh | 6 ++++-- crates/usb-bridge/src/usb.rs | 2 +- crates/usb-bridge/src/usb/device.rs | 6 +++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/crates/usb-bridge/deploy.sh b/crates/usb-bridge/deploy.sh index dc5995f3..f1115263 100755 --- a/crates/usb-bridge/deploy.sh +++ b/crates/usb-bridge/deploy.sh @@ -2,7 +2,8 @@ set -e BUILD_ARG=--release -SERVER="sgc" # ssh config name or full address +SERVER1="sgc" # ssh config name or full address +SERVER2="eva@192.168.1.101" # ssh config name or full address NAME=usb-bridge cargo build --target=aarch64-unknown-linux-musl $BUILD_ARG @@ -16,4 +17,5 @@ sudo chown ha:ha /home/ha/$NAME sudo systemctl restart $NAME.service " -ssh -t $SERVER "$cmds" +ssh -t $SERVER1 "$cmds" +ssh -t $SERVER2 "$cmds" diff --git a/crates/usb-bridge/src/usb.rs b/crates/usb-bridge/src/usb.rs index 726d665e..b3f92ed7 100644 --- a/crates/usb-bridge/src/usb.rs +++ b/crates/usb-bridge/src/usb.rs @@ -48,7 +48,7 @@ impl ReconnectingUsb { Ok(Some(msg)) => break msg, Ok(None) => continue, // needs another call to decode more Err(e) => { - tracing::warn!("Error trying get affector list: {e}"); + tracing::warn!("Error trying get affector list: {e:?}"); sleep(Duration::from_secs(5)).await; } } diff --git a/crates/usb-bridge/src/usb/device.rs b/crates/usb-bridge/src/usb/device.rs index f2d9af00..4aa70c7c 100644 --- a/crates/usb-bridge/src/usb/device.rs +++ b/crates/usb-bridge/src/usb/device.rs @@ -61,9 +61,9 @@ pub(crate) fn get_usb_device( .suggestion("Try running as sudo") .with_suggestion(|| { format!( - "Add a .rules file in /etc/udev/rules.d with line: \ - ATTRS{{serial}}==\"{}\", MODE=\"660\", GROUP=\"{}\", TAG+=\"uaccess\"", - serial_number, + "Add a .rules file in /etc/udev/rules.d with line: \n\ + ATTRS{{serial}}==\"{serial_number}\", MODE=\"660\", GROUP=\"{}\", TAG+=\"uaccess\"\n\ + Then run: sudo udevadm control --reload && sudo udevadm trigger", users::get_current_groupname() .expect("process should always run as a group") .to_string_lossy() From a1b9c296732962e75776fc11b7297ec44043959b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 26 Mar 2025 18:51:01 +0100 Subject: [PATCH 617/687] replaces config function with macro --- nodes/embassy/bed-sb/src/main.rs | 38 +++++++++------------- nodes/embassy/button-panel/src/main.rs | 8 +++-- nodes/embassy/usb-bridge-client/src/lib.rs | 36 +++++++++++--------- 3 files changed, 43 insertions(+), 39 deletions(-) diff --git a/nodes/embassy/bed-sb/src/main.rs b/nodes/embassy/bed-sb/src/main.rs index 4eb569cc..37e90401 100644 --- a/nodes/embassy/bed-sb/src/main.rs +++ b/nodes/embassy/bed-sb/src/main.rs @@ -43,8 +43,8 @@ embassy_stm32::bind_interrupts!(struct Irqs { fn config() -> Config { use embassy_stm32::rcc::mux; use embassy_stm32::rcc::{ - AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllPreDiv, PllQDiv, - PllSource, Sysclk, + AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, + PllPreDiv, PllQDiv, PllSource, Sysclk, }; let mut config = Config::default(); @@ -71,7 +71,10 @@ fn config() -> Config { #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(config()); - let dog = IndependentWatchdog::new(p.IWDG, Duration::from_secs(5).as_micros() as u32); + let dog = IndependentWatchdog::new( + p.IWDG, + Duration::from_secs(5).as_micros() as u32, + ); let mut usart_config = usart::Config::default(); usart_config.baudrate = 9600; @@ -154,7 +157,12 @@ async fn main(_spawner: Spawner) { let affector_list = comms::affector_list(); let stack_a = usb_bridge_client::StackA::new(); let mut stack_b = usb_bridge_client::StackB::new(&stack_a, &affector_list); - let (mut usb_bus, usb_handle) = usb_bridge_client::new(&stack_a, &mut stack_b, usb_driver); + let (mut usb_bus, usb_handle) = usb_bridge_client::new( + &stack_a, + &mut stack_b, + usb_bridge_client::config!("small-bedroom-bed", "2478437"), + usb_driver, + ); let driver_orderers = slow::DriverOrderers::new(); let publish = Queues::new(); @@ -180,7 +188,10 @@ async fn main(_spawner: Spawner) { .await; let unrecoverable_err = match res { - Either4::First(_) | Either4::Second(Ok(())) | Either4::Third(()) | Either4::Fourth(_) => { + Either4::First(_) + | Either4::Second(Ok(())) + | Either4::Third(()) + | Either4::Fourth(_) => { defmt::unreachable!() } Either4::Second(Err(err)) => err, @@ -192,23 +203,6 @@ async fn main(_spawner: Spawner) { handle_network.await; // if this takes too long the dog will get us } -pub fn usb_config() -> embassy_usb::Config<'static> { - // Create embassy-usb Config - let mut config = embassy_usb::Config::new(0x16c0, 0x27DD); - config.manufacturer = Some("Vid"); - config.product = Some("Sensor node"); - config.serial_number = Some("2478437"); - - // Required for windows compatibility. - // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help - config.device_class = 0xEF; - config.device_sub_class = 0x02; - config.device_protocol = 0x01; - config.composite_with_iads = true; - - config -} - async fn keep_dog_happy(mut dog: IndependentWatchdog<'_, IWDG>) -> ! { loop { Timer::after_secs(1).await; diff --git a/nodes/embassy/button-panel/src/main.rs b/nodes/embassy/button-panel/src/main.rs index 00c6260d..49f4bf1d 100644 --- a/nodes/embassy/button-panel/src/main.rs +++ b/nodes/embassy/button-panel/src/main.rs @@ -96,8 +96,12 @@ async fn main(_spawner: Spawner) { let affector_list = comms::affector_list(); let stack_a = usb_bridge_client::StackA::new(); let mut stack_b = usb_bridge_client::StackB::new(&stack_a, &affector_list); - let (mut usb_bus, usb_handle) = - usb_bridge_client::new(&stack_a, &mut stack_b, usb_driver); + let (mut usb_bus, usb_handle) = usb_bridge_client::new( + &stack_a, + &mut stack_b, + usb_bridge_client::config!("small-bedroom-panel", "87244"), + usb_driver, + ); let handle_network = comms::handle(usb_handle); pin_mut!(handle_network); diff --git a/nodes/embassy/usb-bridge-client/src/lib.rs b/nodes/embassy/usb-bridge-client/src/lib.rs index 2a49e724..5624dfda 100644 --- a/nodes/embassy/usb-bridge-client/src/lib.rs +++ b/nodes/embassy/usb-bridge-client/src/lib.rs @@ -211,20 +211,25 @@ impl UsbReceiver<'_> { } } -pub fn config() -> embassy_usb::Config<'static> { - let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); - config.manufacturer = Some("Vid"); - config.product = Some(concat!("sensor node ", env!("CARGO_PKG_NAME"))); - config.serial_number = Some("2139874"); // Random, host driver finds device using this - - // Required for windows compatibility. - // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help - config.device_class = 0xEF; - config.device_sub_class = 0x02; - config.device_protocol = 0x01; - config.composite_with_iads = true; - - config +/// Given a node name and a *random* serial returns a usb config +#[macro_export] +macro_rules! config { + ($node_name:literal, $serial:literal) => { + { + let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); + config.manufacturer = Some("Vid"); + config.product = Some(concat!("sensor node ", $node_name)); + // Random, host driver finds device using this + config.serial_number = Some($serial); + // Required for windows compatibility. + // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help + config.device_class = 0xEF; + config.device_sub_class = 0x02; + config.device_protocol = 0x01; + config.composite_with_iads = true; + config + } + }; } pub struct StackA { @@ -282,6 +287,7 @@ impl<'a, D: embassy_usb::driver::Driver<'a>> Usb<'a, D> { pub fn new<'a, D: embassy_usb::driver::Driver<'a>>( stack_a: &'a StackA, stack_b: &'a mut StackB<'a>, + config: embassy_usb::Config<'static>, driver: D, ) -> (Usb<'a, D>, UsbHandle<'a>) { use embassy_usb::msos::{self, windows_version}; @@ -296,7 +302,7 @@ pub fn new<'a, D: embassy_usb::driver::Driver<'a>>( let mut builder = embassy_usb::Builder::new( driver, - config(), + config, config_descriptor, bos_descriptor, msos_descriptor, From c2642a556acd3e3cb8a058e50f6c02e04598ef68 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Wed, 26 Mar 2025 18:51:25 +0100 Subject: [PATCH 618/687] deploys to second pi --- crates/usb-bridge/deploy.sh | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/usb-bridge/deploy.sh b/crates/usb-bridge/deploy.sh index f1115263..9c4c255b 100755 --- a/crates/usb-bridge/deploy.sh +++ b/crates/usb-bridge/deploy.sh @@ -7,9 +7,13 @@ SERVER2="eva@192.168.1.101" # ssh config name or full address NAME=usb-bridge cargo build --target=aarch64-unknown-linux-musl $BUILD_ARG +cargo build --target=armv7-unknown-linux-musleabihf $BUILD_ARG rsync -vh --progress \ ../../target/aarch64-unknown-linux-musl/release/$NAME \ - $SERVER:/tmp/ + $SERVER1:/tmp/ +rsync -vh --progress \ + ../../target/armv7-unknown-linux-musleabihf/release/$NAME \ + $SERVER2:/tmp/ cmds=" sudo mv /tmp/$NAME /home/ha/$NAME @@ -18,4 +22,11 @@ sudo systemctl restart $NAME.service " ssh -t $SERVER1 "$cmds" + +cmds=" +mv /tmp/$NAME /home/eva/$NAME +sudo chown eva:eva /home/eva/$NAME +sudo systemctl restart $NAME.service +" + ssh -t $SERVER2 "$cmds" From 070c9037b34757abad0a60ada88b692666610c90 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 27 Mar 2025 16:16:14 +0100 Subject: [PATCH 619/687] Track Cargo.lock --- Cargo.lock | 4061 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 4061 insertions(+) create mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..9ee3590d --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,4061 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +dependencies = [ + "anstyle", + "once_cell", + "windows-sys 0.59.0", +] + +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + +[[package]] +name = "arraydeque" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide 0.7.4", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" +dependencies = [ + "serde", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bme280" +version = "0.5.1" +source = "git+https://github.com/dvdsk/bme280-rs#a147bfc93d73a827616121f194972d6cc9cb3d11" +dependencies = [ + "derive_more", + "embedded-hal", + "maybe-async-cfg", + "postcard", + "serde", +] + +[[package]] +name = "brain" +version = "0.1.0" +dependencies = [ + "bincode", + "byteorder", + "bytes", + "clap", + "color-eyre", + "data-server", + "dbstruct", + "futures", + "futures-concurrency", + "futures-util", + "jiff", + "logger", + "mpd", + "protocol", + "rand", + "serde", + "serde_yaml", + "sled", + "strum", + "thiserror 2.0.11", + "tokio", + "tracing", + "zigbee-bridge", +] + +[[package]] +name = "bufstream" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bytemuck" +version = "1.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" + +[[package]] +name = "byteseries" +version = "0.7.1" +source = "git+https://github.com/dvdsk/byteseries?rev=a9da72e9585e5f5a8cc3cf543d6ca2561ad7007a#a9da72e9585e5f5a8cc3cf543d6ca2561ad7007a" +dependencies = [ + "arraydeque", + "itertools 0.13.0", + "num-traits", + "ron", + "serde", + "smallvec 2.0.0-alpha.9", + "thiserror 1.0.69", + "tracing", +] + +[[package]] +name = "cassowary" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "castaway" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5" +dependencies = [ + "rustversion", +] + +[[package]] +name = "cc" +version = "1.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.5.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "clipboard-win" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" +dependencies = [ + "error-code", + "str-buf", + "winapi", +] + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + +[[package]] +name = "color-eyre" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "colored" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" +dependencies = [ + "lazy_static", + "windows-sys 0.59.0", +] + +[[package]] +name = "colorimetry" +version = "0.0.2" +source = "git+https://github.com/harbik/colorimetry#f55b1953653a8a264c54648ef3b6a3d5cfce9f14" +dependencies = [ + "approx", + "colored", + "js-sys", + "libm", + "nalgebra", + "num-traits", + "once_cell", + "paste", + "strum", + "strum_macros", + "thiserror 1.0.69", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", +] + +[[package]] +name = "compact_str" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "rustversion", + "ryu", + "static_assertions", +] + +[[package]] +name = "console" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width 0.2.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "cordyceps" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec10f0a762d93c4498d2e97a333805cb6250d60bead623f71d8034f9a4152ba3" +dependencies = [ + "loom", + "tracing", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "crossbeam-channel" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crossterm" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" +dependencies = [ + "bitflags 2.7.0", + "crossterm_winapi", + "mio", + "parking_lot 0.12.3", + "rustix", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.96", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core 0.9.10", +] + +[[package]] +name = "data-server" +version = "0.0.0" +dependencies = [ + "clap", + "color-eyre", + "futures", + "futures-concurrency", + "governor", + "logger", + "protocol", + "reserve-port", + "rpc", + "serde", + "slotmap", + "socket2", + "thiserror 2.0.11", + "tokio", + "tokio-serde", + "tokio-util", + "tracing", + "tracing-error", + "tracing-futures", + "tracing-subscriber", +] + +[[package]] +name = "data-store" +version = "0.1.0" +dependencies = [ + "byteseries", + "clap", + "color-eyre", + "data-server", + "futures", + "futures-concurrency", + "indicatif", + "itertools 0.14.0", + "jiff", + "logger", + "nucleo-matcher", + "num", + "protocol", + "reserve-port", + "ron", + "rpc", + "rstest", + "serde", + "smallvec 2.0.0-alpha.9", + "temp-dir", + "thiserror 2.0.11", + "tokio", + "tracing", + "tracing-error", + "tracing-subscriber", +] + +[[package]] +name = "dbstruct" +version = "0.4.1" +source = "git+https://github.com/dvdsk/dbstruct#e2f1147accff6a4d71d307d2311c7f493b31606e" +dependencies = [ + "bincode", + "dbstruct-derive", + "serde", + "sled", + "thiserror 1.0.69", + "tracing", +] + +[[package]] +name = "dbstruct-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "393042992e6516cf869ab7148ac3507ae1b9ce15d50b8f9bf43c8b05567b8acd" +dependencies = [ + "itertools 0.11.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.96", + "thiserror 1.0.69", +] + +[[package]] +name = "defmt" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f6162c53f659f65d00619fe31f14556a6e9f8752ccc4a41bd177ffcf3d6130" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d135dd939bad62d7490b0002602d35b358dce5fd9233a709d3c1ef467d4bde6" +dependencies = [ + "defmt-parser", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "defmt-parser" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3983b127f13995e68c1e29071e5d115cd96f215ccb5e6812e3728cd6f92653b3" +dependencies = [ + "thiserror 2.0.11", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.96", +] + +[[package]] +name = "desk-sensors" +version = "0.2.0" +dependencies = [ + "bme280", + "clap", + "color-eyre", + "data-server", + "governor", + "heapless 0.8.0", + "linux-embedded-hal", + "logger", + "protocol", + "tokio", + "tracing", + "tracing-error", + "tracing-subscriber", +] + +[[package]] +name = "diatomic-waker" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab03c107fafeb3ee9f5925686dbb7a73bc76e3932abb0d2b365cb64b169cf04c" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "educe" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4bd92664bf78c4d3dba9b7cdafce6fa15b13ed3ed16175218196942e99168a8" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" +dependencies = [ + "embedded-hal", + "nb", +] + +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + +[[package]] +name = "enum-ordinalize" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "error-code" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" +dependencies = [ + "libc", + "str-buf", +] + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fd-lock" +version = "3.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef033ed5e9bad94e55838ca0ca906db0e043f517adda0c8b79c7a8c66c93c1b5" +dependencies = [ + "cfg-if", + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flate2" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +dependencies = [ + "crc32fast", + "miniz_oxide 0.8.2", +] + +[[package]] +name = "flume" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +dependencies = [ + "futures-core", + "futures-sink", + "spin", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-buffered" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34acda8ae8b63fbe0b2195c998b180cff89a8212fb2622a78b572a9f1c6f7684" +dependencies = [ + "cordyceps", + "diatomic-waker", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-concurrency" +version = "7.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b724496da7c26fcce66458526ce68fc2ecf4aaaa994281cf322ded5755520c" +dependencies = [ + "fixedbitset", + "futures-buffered", + "futures-core", + "futures-lite", + "pin-project", + "slab", + "smallvec 1.13.2", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc3655aa6818d65bc620d6911f05aa7b6aeb596291e1e9f79e52df85583d1e30" +dependencies = [ + "rustix", + "windows-targets 0.52.6", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + +[[package]] +name = "governor" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "842dc78579ce01e6a1576ad896edc92fca002dd60c9c3746b7fc2bec6fb429d0" +dependencies = [ + "cfg-if", + "dashmap", + "futures-sink", + "futures-timer", + "futures-util", + "no-std-compat", + "nonzero_ext", + "parking_lot 0.12.3", + "portable-atomic", + "quanta", + "rand", + "smallvec 1.13.2", + "spinning_top", +] + +[[package]] +name = "gpio-cdev" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09831ec59b80be69e75d29cf36e16afbbe5fd1af9c1bf4689ad91c77db5aa6a6" +dependencies = [ + "bitflags 2.7.0", + "libc", + "nix 0.27.1", +] + +[[package]] +name = "ha-text-widget" +version = "0.1.0" +dependencies = [ + "clap", + "color-eyre", + "data-server", + "data-store", + "dirs", + "gethostname", + "itertools 0.14.0", + "logger", + "nucleo-matcher", + "promptly", + "protocol", + "ron", + "serde", + "tokio", + "tracing", + "tracing-error", + "tracing-subscriber", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + +[[package]] +name = "hdrhistogram" +version = "7.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" +dependencies = [ + "base64", + "byteorder", + "crossbeam-channel", + "flate2", + "nom", + "num-traits", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version", + "serde", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "defmt", + "hash32 0.3.1", + "serde", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "i2cdev" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01f563561b53e2def844167c92984da13779a53ca409e948a03400633cb8228" +dependencies = [ + "bitflags 2.7.0", + "byteorder", + "libc", + "nix 0.26.4", +] + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec 1.13.2", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec 1.13.2", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "indexmap" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", +] + +[[package]] +name = "indextree" +version = "4.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91f3e68a01402c3404bfb739079f38858325bc7ad775b07922278a8a415b1a3f" +dependencies = [ + "indextree-macros", +] + +[[package]] +name = "indextree-macros" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "477e2e7ec7379407656293ff74902caea786a1dda427ca1f84b923c4fdeb7659" +dependencies = [ + "either", + "itertools 0.13.0", + "proc-macro2", + "quote", + "strum", + "syn 2.0.96", + "thiserror 1.0.69", +] + +[[package]] +name = "indicatif" +version = "0.17.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf675b85ed934d3c67b5c5469701eec7db22689d0a2139d856e0925fa28b281" +dependencies = [ + "console", + "number_prefix", + "portable-atomic", + "unicode-width 0.2.0", + "web-time", +] + +[[package]] +name = "indoc" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" + +[[package]] +name = "instability" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf9fed6d91cfb734e7476a06bde8300a1b94e217e1b523b6f0cd1a01998c71d" +dependencies = [ + "darling", + "indoc", + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-kit-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b" +dependencies = [ + "core-foundation-sys", + "mach2", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "jiff" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c258647f65892e500c2478ef2c71ba008e7dc1774a8289345adbbb502a4def1" +dependencies = [ + "jiff-tzdb-platform", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", + "windows-sys 0.59.0", +] + +[[package]] +name = "jiff-tzdb" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91335e575850c5c4c673b9bd467b0e025f164ca59d0564f69d0c2ee0ffad4653" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9835f0060a626fe59f160437bc725491a6af23133ea906500027d1bd2f8f4329" +dependencies = [ + "jiff-tzdb", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.7.0", + "libc", +] + +[[package]] +name = "libsystemd" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c592dc396b464005f78a5853555b9f240bc5378bf5221acc4e129910b2678869" +dependencies = [ + "hmac", + "libc", + "log", + "nix 0.27.1", + "nom", + "once_cell", + "serde", + "sha2", + "thiserror 1.0.69", + "uuid", +] + +[[package]] +name = "linux-embedded-hal" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d566b726e1b6810f66c6f1c769889248439c27f06a59df2881a735454cfa02" +dependencies = [ + "cast", + "embedded-hal", + "embedded-hal-nb", + "gpio-cdev", + "i2cdev", + "nb", + "nix 0.27.1", + "serialport", + "spidev", + "sysfs_gpio", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "log-store" +version = "0.1.0" +dependencies = [ + "bincode", + "byteseries", + "clap", + "color-eyre", + "data-server", + "derivative", + "futures", + "futures-concurrency", + "hdrhistogram", + "heapless 0.8.0", + "jiff", + "logger", + "nucleo-matcher", + "protocol", + "reserve-port", + "rpc", + "serde", + "smallvec 2.0.0-alpha.9", + "temp-dir", + "thiserror 2.0.11", + "tokio", + "tracing", + "tracing-error", + "tracing-subscriber", +] + +[[package]] +name = "logger" +version = "0.1.0" +dependencies = [ + "color-eyre", + "governor", + "libsystemd", + "tracing", + "tracing-core", + "tracing-error", + "tracing-journald", + "tracing-subscriber", +] + +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +dependencies = [ + "hashbrown 0.15.2", +] + +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + +[[package]] +name = "manyhow" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b33efb3ca6d3b07393750d4030418d594ab1139cee518f0dc88db70fec873587" +dependencies = [ + "manyhow-macros", + "proc-macro2", + "quote", + "syn 1.0.109", + "syn 2.0.96", +] + +[[package]] +name = "manyhow-macros" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495" +dependencies = [ + "proc-macro-utils", + "proc-macro2", + "quote", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "matrixmultiply" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" +dependencies = [ + "autocfg", + "rawpointer", +] + +[[package]] +name = "maybe-async-cfg" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dbfaa67a76e2623580df07d6bb5e7956c0a4bae4b418314083a9c619bd66627" +dependencies = [ + "manyhow", + "proc-macro2", + "pulldown-cmark", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "mpd" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e12cace5746cb0aa78faa6cd2caec9f9c01882fc0e6b54d34685a2d3303ea34" +dependencies = [ + "bufstream", +] + +[[package]] +name = "nalgebra" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b" +dependencies = [ + "approx", + "matrixmultiply", + "nalgebra-macros", + "num-complex", + "num-rational", + "num-traits", + "simba", + "typenum", +] + +[[package]] +name = "nalgebra-macros" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec 1.13.2", +] + +[[package]] +name = "nix" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +dependencies = [ + "bitflags 1.3.2", + "cc", + "cfg-if", + "libc", + "memoffset 0.6.5", +] + +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.7.1", + "pin-utils", +] + +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.7.0", + "cfg-if", + "libc", + "memoffset 0.9.1", +] + +[[package]] +name = "no-std-compat" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nonzero_ext" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "nucleo-matcher" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf33f538733d1a5a3494b836ba913207f14d9d4a1d3cd67030c5061bdd2cac85" +dependencies = [ + "memchr", + "unicode-segmentation", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "nusb" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e1996397b9a2af6390bb9ef0386c429de1a81da246fa7ae31dc922be4b670b" +dependencies = [ + "atomic-waker", + "core-foundation 0.9.4", + "core-foundation-sys", + "futures-core", + "io-kit-sys", + "libc", + "log", + "once_cell", + "rustix", + "slab", + "windows-sys 0.48.0", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.10", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec 1.13.2", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.8", + "smallvec 1.13.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e2ec53ad785f4d35dac0adea7f7dc6f1bb277ad84a680c7afefeae05d1f5916" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "portable-atomic" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "postcard" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8" +dependencies = [ + "cobs", + "defmt", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "heapless 0.7.17", + "postcard-derive", + "serde", +] + +[[package]] +name = "postcard-derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0239fa9c1d225d4b7eb69925c25c5e082307a141e470573fbbe3a817ce6a7a37" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "proc-macro-utils" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071" +dependencies = [ + "proc-macro2", + "quote", + "smallvec 1.13.2", +] + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "promptly" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9acbc6c5a5b029fe58342f58445acb00ccfe24624e538894bc2f04ce112980ba" +dependencies = [ + "rustyline", +] + +[[package]] +name = "protocol" +version = "0.1.0" +dependencies = [ + "defmt", + "heapless 0.8.0", + "postcard", + "serde", + "strum", + "thiserror 2.0.11", +] + +[[package]] +name = "pulldown-cmark" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625" +dependencies = [ + "bitflags 2.7.0", + "memchr", + "unicase", +] + +[[package]] +name = "quanta" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bd1fe6824cea6538803de3ff1bc0cf3949024db3d43c9643024bfb33a807c0e" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi", + "web-sys", + "winapi", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radiator-bridge" +version = "0.1.0" +dependencies = [ + "clap", + "color-eyre", + "data-server", + "futures", + "futures-concurrency", + "logger", + "protocol", + "tokio", + "tracing", + "zigbee-bridge", +] + +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "ratatui" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" +dependencies = [ + "bitflags 2.7.0", + "cassowary", + "compact_str", + "crossterm", + "indoc", + "instability", + "itertools 0.13.0", + "lru", + "paste", + "strum", + "unicode-segmentation", + "unicode-truncate", + "unicode-width 0.2.0", +] + +[[package]] +name = "raw-cpuid" +version = "11.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0" +dependencies = [ + "bitflags 2.7.0", +] + +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags 2.7.0", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror 1.0.69", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + +[[package]] +name = "reserve-port" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9838134a2bfaa8e1f40738fcc972ac799de6e0e06b5157acb95fc2b05a0ea283" +dependencies = [ + "lazy_static", + "thiserror 1.0.69", +] + +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64", + "bitflags 2.7.0", + "serde", + "serde_derive", +] + +[[package]] +name = "rpc" +version = "0.1.0" +dependencies = [ + "color-eyre", + "futures", + "governor", + "serde", + "thiserror 2.0.11", + "tokio", + "tokio-serde", + "tokio-util", + "tracing", +] + +[[package]] +name = "rstest" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e905296805ab93e13c1ec3a03f4b6c4f35e9498a3d5fa96dc626d22c03cd89" +dependencies = [ + "futures-timer", + "futures-util", + "rstest_macros", + "rustc_version", +] + +[[package]] +name = "rstest_macros" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef0053bbffce09062bee4bcc499b0fbe7a57b879f1efe088d6d8d4c7adcdef9b" +dependencies = [ + "cfg-if", + "glob", + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version", + "syn 2.0.96", + "unicode-ident", +] + +[[package]] +name = "rumqttc" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1568e15fab2d546f940ed3a21f48bbbd1c494c90c99c4481339364a497f94a9" +dependencies = [ + "bytes", + "flume", + "futures-util", + "log", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" +dependencies = [ + "bitflags 2.7.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + +[[package]] +name = "rustyline" +version = "9.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db7826789c0e25614b03e5a54a0717a86f9ff6e6e5247f92b369472869320039" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "clipboard-win", + "dirs-next", + "fd-lock", + "libc", + "log", + "memchr", + "nix 0.23.2", + "radix_trie", + "scopeguard", + "smallvec 1.13.2", + "unicode-segmentation", + "unicode-width 0.1.14", + "utf8parse", + "winapi", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "safe_arch" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "serde_json" +version = "1.0.135" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "serialport" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "779e2977f0cc2ff39708fef48f96f3768ac8ddd8c6caaaab82e83bd240ef99b2" +dependencies = [ + "bitflags 2.7.0", + "cfg-if", + "core-foundation 0.10.0", + "core-foundation-sys", + "io-kit-sys", + "mach2", + "nix 0.26.4", + "scopeguard", + "unescaper", + "winapi", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "simba" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa" +dependencies = [ + "approx", + "num-complex", + "num-traits", + "paste", + "wide", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "sled" +version = "0.34.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" +dependencies = [ + "crc32fast", + "crossbeam-epoch", + "crossbeam-utils", + "fs2", + "fxhash", + "libc", + "log", + "parking_lot 0.11.2", +] + +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "smallvec" +version = "2.0.0-alpha.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e22442b16a0c1bfae679ffed8ec5e160ae2aa8495cea891f0d2ff7b84fe5c4c" + +[[package]] +name = "socket2" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spidev" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2800c129338c77998c1dcb6d4200447e018beb7d29959eb104cba2d45f83c1a" +dependencies = [ + "bitflags 2.7.0", + "libc", + "nix 0.26.4", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spinning_top" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "str-buf" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" + +[[package]] +name = "strip-ansi-escapes" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ff8ef943b384c414f54aefa961dd2bd853add74ec75e7ac74cf91dba62bcfa" +dependencies = [ + "vte", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.96", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "sysfs_gpio" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8808c55bc926565c62ef7838bcaa8add51585236803e2bdfa1472e3a3ab5e17" +dependencies = [ + "nix 0.23.2", +] + +[[package]] +name = "temp-dir" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc1ee6eef34f12f765cb94725905c6312b6610ab2b0940889cfe58dae7bc3c72" + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +dependencies = [ + "thiserror-impl 2.0.11", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot 0.12.3", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "tokio-serde" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf600e7036b17782571dd44fa0a5cea3c82f60db5137f774a325a76a0d6852b" +dependencies = [ + "bincode", + "bytes", + "educe", + "futures-core", + "futures-sink", + "pin-project", + "serde", +] + +[[package]] +name = "tokio-util" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "tracing-journald" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0b4143302cf1022dac868d521e36e8b27691f72c84b3311750d5188ebba657" +dependencies = [ + "libc", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec 1.13.2", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "tui-tree-widget" +version = "0.23.0" +source = "git+https://github.com/dvdsk/tui-rs-tree-widget#3bd3eeb0261fc7b64c04b5b6a63c9acdad234dc4" +dependencies = [ + "ratatui", + "unicode-width 0.2.0", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ui" +version = "0.0.0" +dependencies = [ + "clap", + "color-eyre", + "crossterm", + "data-server", + "data-store", + "derivative", + "gethostname", + "hdrhistogram", + "indextree", + "itertools 0.14.0", + "jiff", + "log-store", + "logger", + "protocol", + "ratatui", + "strip-ansi-escapes", + "thiserror 2.0.11", + "tokio", + "tracing", + "tracing-error", + "tracing-subscriber", + "tui-tree-widget", +] + +[[package]] +name = "unescaper" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c878a167baa8afd137494101a688ef8c67125089ff2249284bd2b5f9bfedb815" +dependencies = [ + "thiserror 1.0.69", +] + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-truncate" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" +dependencies = [ + "itertools 0.13.0", + "unicode-segmentation", + "unicode-width 0.1.14", +] + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "usb-bridge" +version = "0.1.0" +dependencies = [ + "clap", + "color-eyre", + "data-server", + "heapless 0.8.0", + "logger", + "nusb", + "protocol", + "tokio", + "tracing", + "tracing-error", + "tracing-subscriber", + "users", +] + +[[package]] +name = "users" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" +dependencies = [ + "libc", + "log", +] + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b913a3b5fe84142e269d63cc62b64319ccaf89b748fc31fe025177f767a756c4" +dependencies = [ + "serde", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vte" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197" +dependencies = [ + "utf8parse", + "vte_generate_state_changes", +] + +[[package]] +name = "vte_generate_state_changes" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.96", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wide" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b5576b9a81633f3e8df296ce0063042a73507636cbe956c61133dd7034ab22" +dependencies = [ + "bytemuck", + "safe_arch", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" +dependencies = [ + "memchr", +] + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "zigbee-bridge" +version = "0.1.0" +dependencies = [ + "color-eyre", + "colorimetry", + "logger", + "protocol", + "rand", + "regex", + "rumqttc", + "serde_json", + "strum", + "thiserror 2.0.11", + "tokio", + "tracing", +] From 9b23fc0363deae98900030e0272c1d9b323a9bfb Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 27 Mar 2025 17:20:21 +0100 Subject: [PATCH 620/687] Move small bedroom audio controls into brain Moved from evavh/button-panel/control --- Cargo.lock | 10 + crates/brain/Cargo.toml | 1 + .../src/controller/rooms/small_bedroom.rs | 94 ++- .../rooms/small_bedroom/audiocontrol.rs | 667 ++++++++++++++++++ .../rooms/small_bedroom/audiocontrol/db.rs | 137 ++++ .../rooms/small_bedroom/audiocontrol/db2.rs | 110 +++ .../audiocontrol/mpdinterface.rs | 161 +++++ .../controller/rooms/small_bedroom/state.rs | 17 + 8 files changed, 1193 insertions(+), 4 deletions(-) create mode 100644 crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs create mode 100644 crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db.rs create mode 100644 crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db2.rs create mode 100644 crates/brain/src/controller/rooms/small_bedroom/audiocontrol/mpdinterface.rs diff --git a/Cargo.lock b/Cargo.lock index 9ee3590d..0a8fbc49 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -207,6 +207,7 @@ dependencies = [ "jiff", "logger", "mpd", + "mpdrs", "protocol", "rand", "serde", @@ -2017,6 +2018,15 @@ dependencies = [ "bufstream", ] +[[package]] +name = "mpdrs" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dec81b7ee8968b02af77c52cbcee75a33e83924a4322090f3d83075bd2032686" +dependencies = [ + "bufstream", +] + [[package]] name = "nalgebra" version = "0.33.2" diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 6641aac9..5da7692f 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -38,3 +38,4 @@ futures-concurrency = { workspace = true } strum = { version = "0.26.2", default-features = false, features = ["derive"] } dbstruct = { git = "https://github.com/dvdsk/dbstruct" } color-eyre.workspace = true +mpdrs = "0.1.0" diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index c1bd9a83..fc9127b3 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -2,6 +2,7 @@ use std::collections::BTreeMap; use std::fmt::Debug; use std::time::Duration; +use audiocontrol::{AudioController, ForceRewind}; use futures_concurrency::future::Race; use futures_util::FutureExt; use jiff::civil::Time; @@ -9,7 +10,7 @@ use jiff::{ToSpan, Zoned}; use protocol::small_bedroom::{portable_button_panel, ButtonPanel}; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; -use tracing::{debug, trace}; +use tracing::{debug, error, info, trace}; use self::filter::{recv_filtered, RelevantEvent, Trigger}; use self::state::Room; @@ -18,6 +19,7 @@ use crate::controller::{Event, RestrictedSystem}; use crate::input::jobs::Job; use crate::time; +mod audiocontrol; mod filter; mod state; @@ -65,7 +67,7 @@ pub async fn run( event @ RelevantEvent::Button(_) | event @ RelevantEvent::PortableButton(_), ) => { - handle_buttonpress(&mut room, event).await; + handle_button(&mut room, event).await; } Trigger::Event(RelevantEvent::RadiatorOverride) => { // trace!("Starting radiator override"); @@ -85,7 +87,88 @@ pub async fn run( } } -async fn handle_buttonpress(room: &mut Room, event: RelevantEvent) { +async fn handle_button(room: &mut Room, event: RelevantEvent) { + use portable_button_panel::Reading as P; + use ButtonPanel as B; + + match event { + event @ RelevantEvent::Button(button) => match button { + B::TopLeft(_) | B::TopMiddle(_) | B::TopRight(_) => { + handle_audio_button(room, event).await; + } + B::BottomLeft(_) | B::BottomMiddle(_) | B::BottomRight(_) => { + handle_light_button(room, event).await; + } + }, + event @ RelevantEvent::PortableButton(button) => match button { + P::PlayPause + | P::TrackNext + | P::TrackPrevious + | P::VolumeUp + | P::VolumeUpHold + | P::VolumeDown + | P::VolumeDownHold => { + handle_audio_button(room, event).await; + } + P::Dots1ShortRelease + | P::Dots1LongRelease + | P::Dots2ShortRelease + | P::Dots2LongRelease => { + handle_light_button(room, event).await; + } + b => info!("Pressed unimplemented button: {b:?}") + }, + _ => unreachable!(), + } +} + +async fn handle_audio_button(room: &mut Room, button_press: RelevantEvent) { + use audiocontrol::AudioMode as A; + use portable_button_panel::Reading as P; + use ButtonPanel as B; + + let mut audio = room.audio_controller.lock().await; + let RelevantEvent::Button(button_press) = button_press else { + error!( + "Tried handling non-button as audio button: {:?}", + button_press + ); + return; + }; + match (&audio.mode, button_press) { + (A::Music | A::Singing | A::Meditation, B::TopLeft(press)) + if !press.is_long() => + { + audio.previous() + } + (A::Podcast, B::TopLeft(press)) if !press.is_long() => audio.rewind(), + + (A::Music | A::Singing | A::Meditation, B::TopRight(press)) + if !press.is_long() => + { + audio.next() + } + (A::Podcast, B::TopRight(press)) if !press.is_long() => audio.skip(), + + (_, B::TopMiddle(press)) if !press.is_long() => audio.toggle_playback(), + + (_, B::TopLeft(press)) if press.is_long() => { + audio.prev_playlist(); + audio.play(ForceRewind::No) + } + (_, B::TopRight(press)) if press.is_long() => { + audio.next_playlist(); + audio.play(ForceRewind::No) + } + (_, B::TopMiddle(press)) if press.is_long() => { + audio.next_mode(); + audio.play(ForceRewind::No) + } + (_, b) => info!("Unrecognised button pressed: {b:?}"), + } +} + +async fn handle_light_button(room: &mut Room, event: RelevantEvent) { use portable_button_panel::Reading as P; use ButtonPanel as B; use RelevantEvent as E; @@ -96,6 +179,7 @@ async fn handle_buttonpress(room: &mut Room, event: RelevantEvent) { // Dots2 short: to nightlight at night, otherwise daylight -> lamp(s) on // Dots2 long: to sleep, wakeup off -> lights off match event { + // Light buttons E::Button(B::BottomLeft(_)) => room.to_sleep_delayed().await, E::PortableButton(P::Dots1ShortRelease) => { room.to_sleep_immediate().await @@ -111,7 +195,9 @@ async fn handle_buttonpress(room: &mut Room, event: RelevantEvent) { } } E::Button(B::BottomRight(_)) => room.to_override().await, - E::PortableButton(P::Dots2LongRelease) => room.to_sleep_no_wakeup().await, + E::PortableButton(P::Dots2LongRelease) => { + room.to_sleep_no_wakeup().await + } E::PortableButton(P::Dots1LongRelease) => room.to_nightlight().await, _ => (), } diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs new file mode 100644 index 00000000..76d28575 --- /dev/null +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs @@ -0,0 +1,667 @@ +#![allow(clippy::enum_glob_use)] + +use std::fmt; +use std::time::Duration; + +use jiff::civil::Time; +use mpdrs::error::Error; +use mpdrs::status::State; +use mpdrs::Playlist; +use rand::seq::SliceRandom; +use tracing::{debug, info, instrument}; + +use db::Db; +use mpdinterface::MpdInterface; + +mod db; +mod db2; +mod mpdinterface; + +#[derive(Debug)] +enum Direction { + Next, + Previous, +} + +#[derive(Default)] +#[allow(clippy::struct_excessive_bools)] +struct Settings { + repeat: bool, + random: bool, + single: bool, + consume: bool, + + save_playlist: bool, +} + +#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize, Clone)] +pub enum AudioMode { + Music, + Singing, + Podcast, + Meditation, +} + +impl AudioMode { + fn next(&mut self) { + use AudioMode::*; + *self = match self { + Music => Singing, + Singing => Podcast, + Podcast => Meditation, + Meditation => Music, + } + } + + fn to_prefix(&self) -> &str { + use AudioMode::*; + match self { + Music => "music_", + Singing => "singing_", + Podcast => "podcast_", + Meditation => "meditation_", + } + } + + fn settings(&self) -> Settings { + use AudioMode::*; + match self { + Music | Singing => Settings::default(), + Podcast => Settings { + consume: true, + save_playlist: true, + ..Settings::default() + }, + Meditation => Settings { + single: true, + ..Settings::default() + }, + } + } + + fn to_bytes(&self) -> [u8; 1] { + use AudioMode::*; + match self { + Music => [1], + Singing => [2], + Podcast => [3], + Meditation => [4], + } + } + + fn from_bytes(bytes: &[u8]) -> Self { + use AudioMode::*; + match bytes { + &[1] => Music, + &[2] => Singing, + &[3] => Podcast, + &[4] => Meditation, + other => panic!("Unexpected serialized mode: {:?}", other), + } + } +} + +#[derive(Debug, PartialEq, Eq)] +pub enum ForceRewind { + Yes, + No, +} + +pub struct AudioController { + ip: String, + port: String, + client: MpdInterface, + db: Db, + pub(crate) mode: AudioMode, +} + +impl fmt::Debug for AudioController { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AudioController") + .field("mode", &self.mode) + .finish() + } +} + +impl AudioController { + pub fn new(ip: &str, port: &str) -> Self { + let address = format!("{}:{}", ip, port); + let client = MpdInterface::connect(&address).unwrap(); + let mut controller = AudioController { + ip: ip.to_owned(), + port: port.to_owned(), + client, + db: Db::open("database/small_bedroom_audio"), + mode: AudioMode::Music, + }; + + if let Some(mode) = controller.fetch_current_mode() { + info!("Initializing with stored mode {:?}", mode); + controller.mode = mode; + } else { + info!("No current mode stored, defaulting to music"); + } + + controller.playing(); + controller + } + + pub fn reconnect(&mut self) -> Result<(), Box> { + let address = format!("{}:{}", self.ip, self.port); + self.client = MpdInterface::connect(&address)?; + Ok(()) + } + + pub fn rescan(&mut self) { + info!("Rescanning mpd library"); + self.client.rescan().unwrap(); + } + + fn playing(&mut self) -> bool { + let playback_state = self.client.status().unwrap().state; + playback_state == State::Play + } + + fn stopped(&mut self) -> bool { + let playback_state = self.client.status().unwrap().state; + playback_state == State::Stop + } + + fn get_playlists(&mut self) -> Vec { + self.client.playlists().unwrap() + } + + #[instrument(ret)] + fn auto_rewind_time(last_played: u64) -> Duration { + const MIN_REWIND: u32 = 2; + + let since_last_played = Db::now_timestamp() - last_played; + info!("{}s since last played", since_last_played); + + #[allow( + clippy::cast_possible_truncation, + clippy::cast_sign_loss, + clippy::cast_precision_loss + )] + let rewind_time = (0.5 * (since_last_played as f64).sqrt()) + .round() + .clamp(0.0, 30.0) as u32; + + if rewind_time < MIN_REWIND { + Duration::from_secs(0) + } else { + Duration::from_secs(rewind_time.into()) + } + } + + fn store_current_pausing(&self) { + if let Some(current_playlist) = self.db.fetch_playlist_name(&self.mode) + { + self.db + .store_last_played(¤t_playlist, Db::now_timestamp()); + } + } + + fn rewind_after_pause(&mut self) { + use AudioMode::*; + const SONG_RESTART_THRESHOLD: Duration = + Duration::from_secs(4 * 60 * 60 * 10000); + const ALMOST_OVER: Duration = Duration::from_secs(30); + + let current_playlist = match self.db.fetch_playlist_name(&self.mode) { + Some(current_playlist) => current_playlist, + None => return, + }; + + let last_played = self.db.fetch_last_played(¤t_playlist); + + match (&self.mode, last_played) { + (Podcast, Some(last_played)) => { + self.rewind_by(Self::auto_rewind_time(last_played)); + } + (Music | Singing | Meditation, Some(last_played)) => { + if let (Some(length), Some(position)) = + (self.get_song_length(), self.get_elapsed()) + { + debug!( + "Song length: {length:?}, song position: {position:?}" + ); + let time_left = length - position; + if Duration::from_secs(Db::now_timestamp() - last_played) + > SONG_RESTART_THRESHOLD + && time_left > ALMOST_OVER + { + self.seek_in_cur(0); + } + } + } + (_, None) => (), + } + } + + #[instrument] + pub fn toggle_playback(&mut self) { + info!("Toggle playback"); + let was_playing = self.playing(); + + if self.stopped() { + self.client.play().unwrap(); + } else { + self.client.toggle_pause().unwrap(); + } + + if was_playing { + self.store_current_pausing(); + } else { + self.rewind_after_pause(); + } + } + + #[instrument] + pub fn play(&mut self, force_rewind: ForceRewind) { + if !self.playing() { + self.toggle_playback(); + } else if force_rewind == ForceRewind::Yes { + self.rewind_after_pause() + } + } + + fn get_song_length(&mut self) -> Option { + self.client.status().unwrap().duration + } + + fn get_elapsed(&mut self) -> Option { + self.client.status().unwrap().elapsed + } + + /// # Panics + /// + /// Panics if new position is over 4,294,967,295 seconds into the song, + /// which is 136 years. I assume this will never happen. + /// + /// Panics if client.rewind() returns an error. This may very well happen. + fn rewind_by(&mut self, duration: Duration) { + if duration == Duration::from_secs(0) { + debug!("0 seconds, not rewinding"); + return; + } + info!("Rewinding by {:?}", duration); + + if let Some(position) = self.get_elapsed() { + self.client + .rewind( + position + .saturating_sub(duration) + .as_secs() + .try_into() + .unwrap(), + ) + .unwrap(); + } + } + + pub fn rewind(&mut self) { + self.rewind_by(Duration::from_secs(15)); + self.play(ForceRewind::No); + } + + /// # Panics + /// + /// Panics if new position is over 4,294,967,295 seconds into the song, + /// which is 136 years. I assume this will never happen. + /// + /// Panics if client.rewind() returns an error. This may very well happen. + pub fn skip(&mut self) { + info!("Skipping by 15 seconds"); + + if let Some(position) = self.get_elapsed() { + self.client + .rewind((position.as_secs() + 15).try_into().unwrap()) + .unwrap(); + } + + self.play(ForceRewind::No); + } + + pub fn previous(&mut self) { + info!("Going to previous track"); + + match self.client.prev() { + Ok(_) => (), + Err(Error::Server(server_error)) => { + info!("Ignoring error during prev: {server_error}"); + assert!( + server_error.detail == "Not playing", + "Unexpected ServerError: {server_error}" + ); + } + Err(other_error) => panic!("Unexpected error: {other_error}"), + }; + // self.play(ForceRewind::No); + } + + #[instrument] + pub fn next(&mut self) { + info!("Next"); + + match self.client.next() { + Ok(_) => (), + Err(Error::Server(server_error)) => { + assert!( + server_error.detail == "Not playing", + "Unexpected ServerError: {server_error}" + ); + } + Err(other_error) => panic!("Unexpected error: {other_error}"), + }; + + self.play(ForceRewind::No); + } + + fn apply_shuffle(&mut self, playlist_name: &str) { + if playlist_name.ends_with("_shuf") { + self.client.random(true).unwrap(); + } else { + let random = self.mode.settings().random; + self.client.random(random).unwrap(); + } + self.client.pause().unwrap(); + } + + #[instrument] + fn switch_playlist(&mut self, direction: Direction) { + let current_playlist_name = + match self.db.fetch_playlist_name(&self.mode) { + Some(playlist_name) => playlist_name, + None => self.first_playlist_for_mode().unwrap(), + }; + self.store_position(¤t_playlist_name); + self.save_playlist_if_necessary(¤t_playlist_name); + self.db + .store_last_played(¤t_playlist_name, Db::now_timestamp()); + + let new_playlist_name = if let Some(playlist_name) = + self.playlist_for_mode(direction, ¤t_playlist_name) + { + playlist_name + } else { + current_playlist_name + }; + + info!("Switching to playlist {}", new_playlist_name); + self.load_playlist(&new_playlist_name); + self.db.store_playlist_name(&self.mode, &new_playlist_name); + self.apply_shuffle(&new_playlist_name); + + let new_position = self.db.fetch_position(&new_playlist_name); + self.load_position(new_position); + + //self.play(ForceRewind::Yes); + } + + pub fn prev_playlist(&mut self) { + self.switch_playlist(Direction::Previous); + } + + pub fn next_playlist(&mut self) { + self.switch_playlist(Direction::Next); + } + + /// Meditation mode is only enabled at night + fn is_meditation_time() -> bool { + const START_HOUR: i8 = 21; + const START_MIN: i8 = 30; + const END_HOUR: i8 = 9; + const END_MIN: i8 = 0; + + let now = crate::time::now().time(); + debug!("Checking if it is meditation time: now is {:?}", now); + let start = Time::new(START_HOUR, START_MIN, 0, 0).unwrap(); + let end = Time::new(END_HOUR, END_MIN, 0, 0).unwrap(); + + debug!("Meditation start time: {}, end time: {}", start, end); + let start_sm_now = start < now; + let now_sm_end = now < end; + debug!("start < now: {}, now < end: {}", start_sm_now, now_sm_end); + + start < now || now < end + } + + fn fetch_current_mode(&self) -> Option { + self.db.fetch_mode() + } + + fn store_current_mode(&self) { + self.db.store_mode(&self.mode); + } + + pub fn next_mode(&mut self) { + let current_playlist_name = + match self.db.fetch_playlist_name(&self.mode) { + Some(playlist_name) => playlist_name, + None => self.first_playlist_for_mode().unwrap(), + }; + self.store_position(¤t_playlist_name); + self.save_playlist_if_necessary(¤t_playlist_name); + self.db + .store_last_played(¤t_playlist_name, Db::now_timestamp()); + + self.mode.next(); + info!("Switching to mode {:?}", self.mode); + + // if self.mode == AudioMode::Meditation && !Self::is_meditation_time() { + // self.mode.next(); + // info!("Skipping meditation"); + // } + + // Check if a playlist is stored in the db, and still exists + let new_playlist_name = self.db.fetch_playlist_name(&self.mode); + let new_playlist_name = match new_playlist_name { + Some(playlist_name) + if self.client.playlist_exists(&playlist_name) => + { + playlist_name + } + _ => { + let playlist_name = self.first_playlist_for_mode().unwrap(); + self.db.store_playlist_name(&self.mode, &playlist_name); + playlist_name + } + }; + self.load_playlist(&new_playlist_name); + self.store_current_mode(); + + let new_position = self.db.fetch_position(&new_playlist_name); + self.load_position(new_position); + + self.apply_settings(&self.mode.settings()); + self.apply_shuffle(&new_playlist_name); + } + + fn save_playlist_if_necessary(&mut self, playlist_name: &str) { + if self.mode.settings().save_playlist { + self.client.pl_remove(playlist_name).unwrap(); + self.client.save(playlist_name).unwrap(); + } + } + + #[instrument(ret)] + fn first_playlist_for_mode(&mut self) -> Option { + let playlists = self.get_playlists(); + for playlist in playlists { + if playlist.name.starts_with(self.mode.to_prefix()) { + return Some(playlist.name); + } + } + None + } + + #[instrument(ret)] + fn playlist_for_mode( + &mut self, + direction: Direction, + current_playlist_name: &String, + ) -> Option { + let playlist_names = self.get_playlists().into_iter().map(|pl| pl.name); + let mut playlist_names = playlist_names + .filter(|pl| pl.starts_with(self.mode.to_prefix())) + .collect::>(); + + playlist_names.sort(); + + if let Direction::Previous = direction { + playlist_names.reverse(); + } + let mut playlist_names = playlist_names.iter().cycle().peekable(); + + while *playlist_names.peek().unwrap() != current_playlist_name { + playlist_names.next(); + } + playlist_names.nth(1).map(std::borrow::ToOwned::to_owned) + } + + fn store_position(&mut self, playlist_name: &str) { + let pos_in_pl = if let Some(song) = self.client.status().unwrap().song { + song.pos + } else { + 0 + }; + + let elapsed = if let Some(elapsed) = self.get_elapsed() { + elapsed.as_secs().try_into().unwrap() + } else { + 0 + }; + + let position = db::Position { pos_in_pl, elapsed }; + self.db.store_position(playlist_name, &position); + } + + fn load_playlist(&mut self, playlist_name: &str) { + self.client.clear().unwrap(); + self.client.load(playlist_name, ..).expect("Should exist"); + self.client.pause().unwrap(); + } + + fn load_position(&mut self, position: Option) { + if let Some(position) = position { + self.client.queue().unwrap(); + self.seek_to(position.pos_in_pl, position.elapsed); + } else { + self.seek_to(0, 0); + } + self.client.pause().unwrap(); + } + + fn seek_to(&mut self, pos_in_pl: u32, elapsed: u32) { + match self.client.seek(pos_in_pl, elapsed) { + Ok(_) => (), + Err(Error::Server(server_error)) => { + assert!( + server_error.detail == "Bad song index", + "Unexpected ServerError: {server_error}" + ); + } + Err(other_error) => panic!("Unexpected error: {other_error}"), + } + } + + fn seek_in_cur(&mut self, elapsed: u32) { + if let Some(song) = self.client.currentsong().unwrap() { + if let Some(place) = song.place { + self.seek_to(place.pos, elapsed); + } + } + } + + fn apply_settings(&mut self, audio_settings: &Settings) { + self.client.repeat(audio_settings.repeat).unwrap(); + self.client.random(audio_settings.random).unwrap(); + self.client.single(audio_settings.single).unwrap(); + self.client.consume(audio_settings.consume).unwrap(); + self.client.pause().unwrap(); + } + + pub(crate) fn go_to_mode(&mut self, target_mode: &AudioMode) { + while self.mode != *target_mode { + self.next_mode(); + } + } + + pub(crate) fn go_to_playlist( + &mut self, + target_playlist: &str, + ) -> Result<(), String> { + let old_playlist = self.db.fetch_playlist_name(&self.mode).unwrap(); + while self.db.fetch_playlist_name(&self.mode).unwrap() + != *target_playlist + { + self.switch_playlist(Direction::Next); + if self.db.fetch_playlist_name(&self.mode).unwrap() == old_playlist + { + return Err(format!( + "Could not find target playlist {target_playlist:?} to go to" + )); + } + } + + Ok(()) + } + + pub(crate) async fn play_mode_playlist( + &mut self, + mode: &AudioMode, + playlist: &str, + ) { + self.go_to_mode(mode); + tokio::time::sleep(Duration::from_millis(100)).await; + match self.go_to_playlist(playlist) { + Ok(()) => (), + Err(e) => println!("{e}"), + }; + tokio::time::sleep(Duration::from_millis(100)).await; + self.load_playlist(playlist); + tokio::time::sleep(Duration::from_millis(100)).await; + self.load_position(None); + tokio::time::sleep(Duration::from_millis(100)).await; + self.play(ForceRewind::No); + } + + pub(crate) async fn start_wakeup_music(&mut self) { + self.reconnect().unwrap(); + tokio::time::sleep(Duration::from_millis(500)).await; + + let pl_name = "music_wakeup"; + self.create_wakeup_playlist(pl_name).await; + self.play_mode_playlist(&AudioMode::Music, pl_name).await; + } + + async fn create_wakeup_playlist(&mut self, pl_name: &str) { + let slow_songs = self.client.playlist("slow").unwrap(); + tokio::time::sleep(Duration::from_millis(100)).await; + let normal_songs = self.client.playlist("music_all_shuf").unwrap(); + tokio::time::sleep(Duration::from_millis(100)).await; + + self.client.pl_clear(pl_name).unwrap(); + tokio::time::sleep(Duration::from_millis(100)).await; + + let to_add = { + let mut rng = rand::thread_rng(); + + slow_songs + .choose_multiple(&mut rng, 1) + .chain(normal_songs.choose_multiple(&mut rng, 30)) + }; + + for song in to_add { + self.client.pl_push(pl_name, song).unwrap(); + tokio::time::sleep(Duration::from_millis(10)).await; + } + } + + pub(crate) fn insert_next(&mut self, song_path: &str) { + if let Ok(id) = self.client.push(song_path) { + let _ = self.client.prioid(id, 128); + }; + } +} diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db.rs new file mode 100644 index 00000000..349040ab --- /dev/null +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db.rs @@ -0,0 +1,137 @@ +use super::AudioMode; +use std::time::{SystemTime, UNIX_EPOCH}; + +#[derive(Debug, serde::Serialize, serde::Deserialize)] +pub(crate) struct Position { + pub(crate) pos_in_pl: u32, + pub(crate) elapsed: u32, +} + +impl Position { + fn to_bytes(&self) -> Vec { + [self.pos_in_pl.to_ne_bytes(), self.elapsed.to_ne_bytes()].concat() + } + + fn from_bytes(bytes: &[u8]) -> Self { + Position { + pos_in_pl: u32::from_ne_bytes(bytes[..4].try_into().unwrap()), + elapsed: u32::from_ne_bytes(bytes[4..].try_into().unwrap()), + } + } +} + +#[derive(Debug)] +pub(crate) struct Db { + database: sled::Db, +} + +impl Db { + pub(crate) fn open(path: &str) -> Self { + Db { + database: sled::Config::default() + .path(path) + .cache_capacity(1_000_000) + .open() + .unwrap(), + } + } + + pub(crate) fn fetch_playlist_name( + &self, + mode: &AudioMode, + ) -> Option { + let key = mode.to_prefix().to_owned() + "cur_playlist"; + self.database + .get(key.as_bytes()) + .unwrap() + .map(|data| String::from_utf8(data.to_vec()).unwrap()) + } + + pub(crate) fn store_playlist_name( + &self, + mode: &AudioMode, + playlist_name: &str, + ) { + let key = mode.to_prefix().to_owned() + "cur_playlist"; + self.database + .insert(key.as_bytes(), playlist_name.as_bytes()) + .unwrap(); + } + + pub(crate) fn fetch_position( + &self, + playlist_name: &str, + ) -> Option { + let key = playlist_name.to_owned() + "_position"; + self.database + .get(key.as_bytes()) + .unwrap() + .map(|buffer| Position::from_bytes(buffer.as_ref())) + } + + pub(crate) fn store_position( + &mut self, + playlist_name: &str, + position: &Position, + ) { + let key = playlist_name.to_owned() + "_position"; + self.database + .insert(key.as_bytes(), position.to_bytes()) + .unwrap(); + } + + pub(crate) fn now_timestamp() -> u64 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + } + + pub(crate) fn fetch_last_played(&self, playlist: &str) -> Option { + let key = playlist.to_owned() + "last_played"; + self.database + .get(key.as_bytes()) + .unwrap() + .map(|bytes| u64::from_ne_bytes(bytes[..8].try_into().unwrap())) + } + + pub(crate) fn store_last_played(&self, playlist: &str, last_played: u64) { + let key = playlist.to_owned() + "last_played"; + + self.database + .insert(key.as_bytes(), &last_played.to_ne_bytes()) + .unwrap(); + } + + pub(crate) fn fetch_mode(&self) -> Option { + let key = "current_mode"; + self.database + .get(key.as_bytes()) + .unwrap() + .map(|buffer| AudioMode::from_bytes(buffer.as_ref())) + } + + pub(crate) fn store_mode(&self, mode: &AudioMode) { + let key = "current_mode"; + self.database + .insert(key.as_bytes(), &mode.to_bytes()) + .unwrap(); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn fetch_and_store_last_played() { + let db = Db::open("test_db"); + + let playlist = "test_playlist_name"; + let last_played = Db::now_timestamp(); + + db.store_last_played(&playlist, last_played); + let fetched = db.fetch_last_played(&playlist).unwrap(); + assert_eq!(fetched, last_played); + } +} diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db2.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db2.rs new file mode 100644 index 00000000..c4f4ccac --- /dev/null +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db2.rs @@ -0,0 +1,110 @@ +use super::{db::Position, AudioMode}; +use std::time::{SystemTime, UNIX_EPOCH}; + +#[dbstruct::dbstruct(db=sled)] +struct PersistentData { + mode_cur_playlist: HashMap, + playlist_positions: HashMap, + playlist_last_played: HashMap, + current_mode: Option, +} + +pub(crate) struct Db { + database: PersistentData, +} + +impl Db { + pub(crate) fn open(path: &str) -> Self { + Db { + database: PersistentData::new(path.to_owned()+"_test").unwrap(), + } + } + + pub(crate) fn fetch_playlist_name( + &self, + mode: &AudioMode, + ) -> Option { + self.database.mode_cur_playlist().get(mode).unwrap() + } + + pub(crate) fn store_playlist_name( + &self, + mode: &AudioMode, + playlist_name: &str, + ) { + self.database + .mode_cur_playlist() + .insert(mode, &playlist_name.to_owned()) + .unwrap(); + } + + pub(crate) fn fetch_position( + &self, + playlist_name: &str, + ) -> Option { + self.database + .playlist_positions() + .get(&playlist_name.to_owned()) + .unwrap() + } + + pub(crate) fn store_position( + &mut self, + playlist_name: &str, + position: &Position, + ) { + self.database + .playlist_positions() + .insert(&playlist_name.to_owned(), position) + .unwrap(); + } + + pub(crate) fn now_timestamp() -> u64 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + } + + pub(crate) fn fetch_last_played(&self, playlist: &str) -> Option { + self.database + .playlist_last_played() + .get(&playlist.to_owned()) + .unwrap() + } + + pub(crate) fn store_last_played(&self, playlist: &str, last_played: u64) { + self.database + .playlist_last_played() + .insert(&playlist.to_owned(), &last_played) + .unwrap(); + } + + pub(crate) fn fetch_mode(&self) -> Option { + self.database.current_mode().get().unwrap() + } + + pub(crate) fn store_mode(&self, mode: &AudioMode) { + self.database + .current_mode() + .set(mode) + .unwrap(); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn fetch_and_store_last_played() { + let db = Db::open("test_db2"); + + let playlist = "test_playlist_name"; + let last_played = Db::now_timestamp(); + + db.store_last_played(&playlist, last_played); + let fetched = db.fetch_last_played(&playlist).unwrap(); + assert_eq!(fetched, last_played); + } +} diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/mpdinterface.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/mpdinterface.rs new file mode 100644 index 00000000..d2ecf13f --- /dev/null +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/mpdinterface.rs @@ -0,0 +1,161 @@ +use std::fmt; +use std::thread; + +use mpdrs::error::{Error, Result}; +use mpdrs::song::Range; +use mpdrs::{Playlist, Song, Status}; +use tracing::{debug, instrument}; + +pub(super) struct MpdInterface { + ip: String, + client: mpdrs::Client, +} + +impl fmt::Debug for MpdInterface { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MpdClient").field("ip", &self.ip).finish() + } +} + +macro_rules! ok_or_reconnect_no_args { + ($name: ident, $return_type: ty) => { + pub(crate) fn $name(&mut self) -> Result<$return_type> { + match self.client.$name() { + Err(Error::Io(_)) => (), + Err(Error::Parse(_)) => (), + other => return other, + }; + + debug!("IOError or ParseError, reconnecting..."); + self.client = mpdrs::Client::connect(&self.ip)?; + self.client.$name() + } + }; +} +macro_rules! ok_or_reconnect_one_arg { + ($name: ident, $arg: ident, $arg_type: ty, $return_type: ty) => { + pub(crate) fn $name( + &mut self, + $arg: $arg_type, + ) -> Result<$return_type> { + match self.client.$name($arg) { + Err(Error::Io(_)) => (), + Err(Error::Parse(_)) => (), + other => return other, + }; + + debug!("IOError or ParseError, reconnecting..."); + self.client = mpdrs::Client::connect(&self.ip)?; + self.client.$name($arg) + } + }; +} + +impl MpdInterface { + #[instrument(ret, err)] + pub(crate) fn connect(ip: &str) -> Result { + let client = mpdrs::Client::connect(ip)?; + Ok(MpdInterface { + ip: ip.to_owned(), + client, + }) + } + + #[instrument(ret, err)] + pub(crate) fn rescan(&mut self) -> Result<()> { + use mpdrs::Idle; + + let mut watcher = mpdrs::Client::connect(&self.ip)?; + let thread_join_handle = thread::spawn(move || { + watcher.wait(&[mpdrs::idle::Subsystem::Update]) + }); + self.client.rescan()?; + thread_join_handle.join().unwrap()?; + Ok(()) + } + + ok_or_reconnect_no_args! {toggle_pause, ()} + ok_or_reconnect_no_args! {play, ()} + ok_or_reconnect_no_args! {prev, ()} + ok_or_reconnect_no_args! {next, ()} + ok_or_reconnect_no_args! {status, Status} + ok_or_reconnect_no_args! {playlists, Vec} + ok_or_reconnect_no_args! {queue, Vec} + ok_or_reconnect_no_args! {currentsong, Option} + ok_or_reconnect_no_args! {clear, ()} + + ok_or_reconnect_one_arg! {rewind, pos, u32, ()} + ok_or_reconnect_one_arg! {pl_remove, name, &str, ()} + ok_or_reconnect_one_arg! {pl_clear, name, &str, ()} + ok_or_reconnect_one_arg! {save, name, &str, ()} + ok_or_reconnect_one_arg! {repeat, value, bool, ()} + ok_or_reconnect_one_arg! {random, value, bool, ()} + ok_or_reconnect_one_arg! {single, value, bool, ()} + ok_or_reconnect_one_arg! {consume, value, bool, ()} + ok_or_reconnect_one_arg! {playlist, name, &str, Vec} + ok_or_reconnect_one_arg! {push, path, &str, u32} + + pub(crate) fn pause(&mut self) -> Result<()> { + match self.client.pause(true) { + Err(Error::Io(_)) => (), + Err(Error::Parse(_)) => (), + other => return other, + }; + + debug!("IOError or ParseError, reconnecting..."); + self.client = mpdrs::Client::connect(&self.ip)?; + self.client.pause(true) + } + + pub(crate) fn load + std::marker::Copy>( + &mut self, + name: &str, + range: T, + ) -> Result<()> { + match self.client.load(name, range) { + Err(Error::Io(_) | Error::Parse(_)) => (), + other => return other, + }; + + debug!("IOError or ParseError, reconnecting..."); + self.client = mpdrs::Client::connect(&self.ip)?; + self.client.load(name, range) + } + + pub(crate) fn pl_push(&mut self, pl_name: &str, song: &Song) -> Result<()> { + match self.client.pl_push(pl_name, &song.file) { + Err(Error::Io(_) | Error::Parse(_)) => (), + other => return other, + }; + + debug!("IOError or ParseError, reconnecting..."); + self.client = mpdrs::Client::connect(&self.ip)?; + self.client.pl_push(pl_name, &song.file) + } + + pub(crate) fn seek(&mut self, place: u32, pos: u32) -> Result<()> { + match self.client.seek(place, pos) { + Err(Error::Io(_) | Error::Parse(_)) => (), + other => return other, + }; + + debug!("IOError or ParseError, reconnecting..."); + self.client = mpdrs::Client::connect(&self.ip)?; + self.client.seek(place, pos) + } + + pub(crate) fn prioid(&mut self, id: u32, prio: u8) -> Result<()> { + match self.client.prioid(id, prio) { + Err(Error::Io(_) | Error::Parse(_)) => (), + other => return other, + }; + + debug!("IOError or ParseError, reconnecting..."); + self.client = mpdrs::Client::connect(&self.ip)?; + self.client.prioid(id, prio) + } + + pub(crate) fn playlist_exists(&mut self, playlist_name: &str) -> bool { + self.playlist(playlist_name).is_ok() + } +} diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index 0489ea9d..678c23e0 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -11,12 +11,16 @@ use tokio::task::{self, JoinHandle}; use tokio::time::sleep; use tracing::{trace, warn}; +use super::audiocontrol::AudioController; use super::{ air_filtration_now, daylight_now, goal_temp_now, is_nap_time, NAP_TIME, OFF_DELAY, }; use crate::controller::{Event, RestrictedSystem}; +const MPD_IP: &str = "192.168.1.101"; +const MPD_PORT: &str = "6600"; + #[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)] pub(crate) enum State { Sleep, @@ -36,6 +40,7 @@ pub(super) struct Room { system: RestrictedSystem, event_tx: broadcast::Sender, task_handle: Arc>>>, + pub(super) audio_controller: Arc>, } impl Room { @@ -50,9 +55,13 @@ impl Room { system, event_tx, task_handle: Arc::new(Mutex::new(None)), + audio_controller: Arc::new(Mutex::new(AudioController::new( + MPD_IP, MPD_PORT, + ))), } } + pub(super) async fn update_radiator(&mut self) { trace!("Updating radiator"); // trace!( @@ -171,8 +180,11 @@ impl Room { async fn run_wakeup_then_daylight(mut self) { const LIGHT_NAME: &str = "small_bedroom:ceiling"; const RUNTIME_MINS: i32 = 20; + const MUSIC_ON_AFTER_MINS: i32 = 13; + const STEP_SIZE_SECS: i32 = 30; const N_STEPS: i32 = RUNTIME_MINS * 60 / STEP_SIZE_SECS; + const MUSIC_STEP: i32 = MUSIC_ON_AFTER_MINS * 60 / STEP_SIZE_SECS; const START_BRI: f64 = 1. / 254.; const START_CT: usize = 2000; @@ -204,6 +216,11 @@ impl Room { (START_CT as f64 * ct_growth.powi(step)).round() as usize; self.system.one_lamp_ct(LIGHT_NAME, new_ct, new_bri).await; + + if step == MUSIC_STEP { + let mut audio = self.audio_controller.lock().await; + audio.start_wakeup_music().await; + } } self.to_state(State::Daylight).await; From 0bbef9ea6366a7ca2fb787c68ed6db0736569bcd Mon Sep 17 00:00:00 2001 From: dvdsk Date: Thu, 27 Mar 2025 21:52:50 +0100 Subject: [PATCH 621/687] switch to local embassy for debugging --- nodes/embassy/Cargo.lock | 17 - nodes/embassy/Cargo.toml | 31 +- nodes/embassy/bed-lb/output.txt | 19660 ------------------------------ 3 files changed, 21 insertions(+), 19687 deletions(-) delete mode 100644 nodes/embassy/bed-lb/output.txt diff --git a/nodes/embassy/Cargo.lock b/nodes/embassy/Cargo.lock index 9eb7ad6d..b4adaffe 100644 --- a/nodes/embassy/Cargo.lock +++ b/nodes/embassy/Cargo.lock @@ -292,7 +292,6 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", "embassy-futures", @@ -310,7 +309,6 @@ dependencies = [ [[package]] name = "embassy-executor" version = "0.7.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "cortex-m", "critical-section", @@ -322,7 +320,6 @@ dependencies = [ [[package]] name = "embassy-executor-macros" version = "0.6.2" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "darling", "proc-macro2", @@ -333,12 +330,10 @@ dependencies = [ [[package]] name = "embassy-futures" version = "0.1.1" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" [[package]] name = "embassy-hal-internal" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "cortex-m", "critical-section", @@ -349,7 +344,6 @@ dependencies = [ [[package]] name = "embassy-net" version = "0.7.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", "document-features", @@ -366,7 +360,6 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", ] @@ -374,7 +367,6 @@ dependencies = [ [[package]] name = "embassy-net-driver-channel" version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "embassy-futures", "embassy-net-driver", @@ -384,7 +376,6 @@ dependencies = [ [[package]] name = "embassy-net-wiznet" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", "embassy-futures", @@ -397,7 +388,6 @@ dependencies = [ [[package]] name = "embassy-stm32" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "aligned", "bit_field", @@ -444,7 +434,6 @@ dependencies = [ [[package]] name = "embassy-sync" version = "0.6.2" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "cfg-if", "critical-section", @@ -458,7 +447,6 @@ dependencies = [ [[package]] name = "embassy-time" version = "0.4.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "cfg-if", "critical-section", @@ -474,7 +462,6 @@ dependencies = [ [[package]] name = "embassy-time-driver" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "document-features", ] @@ -482,7 +469,6 @@ dependencies = [ [[package]] name = "embassy-time-queue-utils" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "embassy-executor", "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -491,7 +477,6 @@ dependencies = [ [[package]] name = "embassy-usb" version = "0.4.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", "embassy-futures", @@ -506,7 +491,6 @@ dependencies = [ [[package]] name = "embassy-usb-driver" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", ] @@ -514,7 +498,6 @@ dependencies = [ [[package]] name = "embassy-usb-synopsys-otg" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "critical-section", "defmt", diff --git a/nodes/embassy/Cargo.toml b/nodes/embassy/Cargo.toml index 5d4be4b6..7204c052 100644 --- a/nodes/embassy/Cargo.toml +++ b/nodes/embassy/Cargo.toml @@ -34,16 +34,27 @@ defmt-rtt = "0.4" panic-probe = { version = "0.3", features = ["print-defmt"] } [patch.crates-io] -embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +# embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +# embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +# embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +# embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +# embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +# embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +# embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +# embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +# embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +# embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } + +embassy-stm32 = {path = "/home/david/Documents/embassy/embassy-stm32" } +embassy-net = {path = "/home/david/Documents/embassy/embassy-net" } +embassy-net-wiznet = {path = "/home/david/Documents/embassy/embassy-net-wiznet" } +embassy-sync = {path = "/home/david/Documents/embassy/embassy-sync" } +embassy-executor = {path = "/home/david/Documents/embassy/embassy-executor" } +embassy-embedded-hal = {path = "/home/david/Documents/embassy/embassy-embedded-hal" } +embassy-futures = {path = "/home/david/Documents/embassy/embassy-futures" } +embassy-time = {path = "/home/david/Documents/embassy/embassy-time" } +embassy-time-driver = {path = "/home/david/Documents/embassy/embassy-time-driver" } +embassy-usb = {path = "/home/david/Documents/embassy/embassy-usb" } [workspace.package] rust-version = "1.78" diff --git a/nodes/embassy/bed-lb/output.txt b/nodes/embassy/bed-lb/output.txt deleted file mode 100644 index 48b0ff76..00000000 --- a/nodes/embassy/bed-lb/output.txt +++ /dev/null @@ -1,19660 +0,0 @@ -DEBUG flash: latency=2 -└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } -└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -INFO random seed: 867502111134296087 -└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 -DEBUG IPv4: UP -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG IP address: 192.168.1.7/24 -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Default gateway: Some(192.168.1.1) -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Configured socket and connecting -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 -WARN warning connection down, resetting if not up soon -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 -INFO initializing sensors -└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -INFO link_up = true -└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG timeout exceeded -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -WARN write error: ConnectionReset -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG flash: latency=2 -└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } -└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -INFO random seed: 14599460162574367279 -└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 -DEBUG IPv4: UP -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG IP address: 192.168.1.7/24 -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Default gateway: Some(192.168.1.1) -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Configured socket and connecting -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 -WARN warning connection down, resetting if not up soon -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 -INFO initializing sensors -└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -INFO link_up = true -└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG timeout exceeded -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -WARN write error: ConnectionReset -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG flash: latency=2 -└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } -└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -INFO random seed: 8070402030576215694 -└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 -DEBUG IPv4: UP -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG IP address: 192.168.1.7/24 -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Default gateway: Some(192.168.1.1) -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Configured socket and connecting -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 -WARN warning connection down, resetting if not up soon -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 -INFO initializing sensors -└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -INFO link_up = true -└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG timeout exceeded -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -WARN write error: ConnectionReset -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG timeout exceeded -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG flash: latency=2 -└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } -└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -INFO random seed: 4334505959795280607 -└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 -DEBUG IPv4: UP -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG IP address: 192.168.1.7/24 -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Default gateway: Some(192.168.1.1) -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Configured socket and connecting -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 -WARN warning connection down, resetting if not up soon -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 -INFO initializing sensors -└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -INFO link_up = true -└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG timeout exceeded -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -WARN write error: ConnectionReset -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG timeout exceeded -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG flash: latency=2 -└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } -└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -INFO random seed: 12614019627889602978 -└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 -DEBUG IPv4: UP -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG IP address: 192.168.1.7/24 -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Default gateway: Some(192.168.1.1) -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Configured socket and connecting -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 -WARN warning connection down, resetting if not up soon -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 -INFO initializing sensors -└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -INFO link_up = true -└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG timeout exceeded -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -WARN write error: ConnectionReset -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG flash: latency=2 -└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } -└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -INFO random seed: 13081958469941311299 -└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 -DEBUG IPv4: UP -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG IP address: 192.168.1.7/24 -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Default gateway: Some(192.168.1.1) -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Configured socket and connecting -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 -WARN warning connection down, resetting if not up soon -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 -INFO initializing sensors -└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -INFO link_up = true -└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG timeout exceeded -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -WARN write error: ConnectionReset -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG flash: latency=2 -└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } -└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -INFO random seed: 17908139605922323881 -└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 -DEBUG IPv4: UP -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG IP address: 192.168.1.7/24 -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Default gateway: Some(192.168.1.1) -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Configured socket and connecting -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 -WARN warning connection down, resetting if not up soon -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 -INFO initializing sensors -└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -INFO link_up = true -└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG timeout exceeded -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -WARN write error: ConnectionReset -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG timeout exceeded -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG flash: latency=2 -└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } -└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -INFO random seed: 2841131338015846188 -└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 -DEBUG IPv4: UP -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG IP address: 192.168.1.7/24 -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Default gateway: Some(192.168.1.1) -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Configured socket and connecting -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 -WARN warning connection down, resetting if not up soon -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 -INFO initializing sensors -└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -INFO link_up = true -└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG timeout exceeded -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -WARN write error: ConnectionReset -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG flash: latency=2 -└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } -└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -INFO random seed: 13356480873848707970 -└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 -DEBUG IPv4: UP -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG IP address: 192.168.1.7/24 -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Default gateway: Some(192.168.1.1) -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Configured socket and connecting -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 -WARN warning connection down, resetting if not up soon -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 -INFO initializing sensors -└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -INFO link_up = true -└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG timeout exceeded -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -WARN write error: ConnectionReset -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG timeout exceeded -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG flash: latency=2 -└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } -└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -INFO random seed: 1656018264575584532 -└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 -DEBUG IPv4: UP -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG IP address: 192.168.1.7/24 -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Default gateway: Some(192.168.1.1) -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Configured socket and connecting -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:84 -WARN warning connection down, resetting if not up soon -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:95 -INFO initializing sensors -└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -INFO link_up = true -└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG timeout exceeded -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -WARN write error: ConnectionReset -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:114 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -INFO (re-)connected -└─ bed_sensors::network::send_published::{async_fn#0} @ src/network.rs:106 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG can now write -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:84 -DEBUG need to read -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:78 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG tick -└─ embassy_net_wiznet::{impl#1}::run::{async_fn#0} @ /home/david/Documents/embassy/embassy-net-wiznet/src/lib.rs:89 -DEBUG flash: latency=2 -└─ embassy_stm32::rcc::_version::init @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -DEBUG rcc: Clocks { hclk1: MaybeHertz(84000000), pclk1: MaybeHertz(42000000), pclk1_tim: MaybeHertz(84000000), pclk2: MaybeHertz(84000000), pclk2_tim: MaybeHertz(84000000), pll1_q: MaybeHertz(0), pllsai1_q: MaybeHertz(0), rtc: MaybeHertz(32000), sys: MaybeHertz(84000000) } -└─ embassy_stm32::rcc::set_freqs @ /home/david/Documents/embassy/embassy-stm32/src/fmt.rs:138 -INFO random seed: 14091470885172412432 -└─ bed_sensors::____embassy_main_task::{async_fn#0} @ src/main.rs:90 -DEBUG IPv4: UP -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG IP address: 192.168.1.7/24 -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Default gateway: Some(192.168.1.1) -└─ embassy_net::{impl#5}::apply_static_config @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:138 -DEBUG Configured socket and connecting -└─ bed_sensors::network::handle::{async_fn#0} @ src/network.rs:78 -INFO initializing sensors -└─ bed_sensors::sensors::init_then_measure::{async_fn#0} @ src/sensors.rs:51 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -INFO link_up = true -└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 -DEBUG address 192.168.1.43 not in neighbor cache, sending ARP request -└─ smoltcp::iface::interface::{impl#2}::lookup_hardware_addr @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -INFO (re-)connected -└─ bed_sensors::network::handle::{async_fn#0} @ src/network.rs:85 -INFO link_up = false -└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 -DEBUG retransmitting at t+0.899s -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -INFO link_up = true -└─ embassy_net::{impl#5}::poll @ /home/david/Documents/embassy/embassy-net/src/fmt.rs:152 -DEBUG retransmitting at t+0.899s -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG retransmitting at t+0.899s -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG retransmitting at t+1.102s -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG retransmitting at t+1.102s -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG retransmitting at t+1.102s -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 -DEBUG queueing error: Timeout(Sht31) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Mhz14) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG queueing error: Timeout(Sps30) -└─ bed_sensors::channel::{impl#0}::queue_error @ src/channel.rs:69 -DEBUG retransmitting at t+1.508s -└─ smoltcp::socket::tcp::{impl#9}::dispatch @ /home/david/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smoltcp-0.11.0/src/macros.rs:18 From 44c2b7df687be00e372db1e684f5dad49bfa9c1a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 18 Jan 2025 12:06:08 +0100 Subject: [PATCH 622/687] switch data range from Range to RangeInclusive --- .../src/data/series/bitspec/spec.rs | 8 ++--- crates/protocol/src/button.rs | 2 +- crates/protocol/src/large_bedroom/bed.rs | 36 +++++++++---------- crates/protocol/src/large_bedroom/desk.rs | 6 ++-- crates/protocol/src/large_bedroom/radiator.rs | 8 ++--- crates/protocol/src/reading.rs | 4 +-- crates/protocol/src/small_bedroom/bed.rs | 34 +++++++++--------- crates/protocol/src/small_bedroom/desk.rs | 6 ++-- .../small_bedroom/portable_button_panel.rs | 2 +- crates/protocol/src/small_bedroom/radiator.rs | 8 ++--- crates/ui/examples/chart_gaps.rs | 2 +- crates/ui/src/tui/readings/render/chart.rs | 4 +-- .../ui/src/tui/readings/render/chart/split.rs | 2 +- 13 files changed, 61 insertions(+), 61 deletions(-) diff --git a/crates/data-store/src/data/series/bitspec/spec.rs b/crates/data-store/src/data/series/bitspec/spec.rs index d7ffca2c..4bd37578 100644 --- a/crates/data-store/src/data/series/bitspec/spec.rs +++ b/crates/data-store/src/data/series/bitspec/spec.rs @@ -1,4 +1,4 @@ -use std::ops::Range; +use std::ops::RangeInclusive; use serde::{Deserialize, Serialize}; @@ -6,7 +6,7 @@ use super::field::Field; #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub struct RangeWithRes { - pub range: Range, + pub range: RangeInclusive, pub resolution: f32, } @@ -20,13 +20,13 @@ pub struct LengthWithOps { impl From for LengthWithOps { #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] fn from(field: RangeWithRes) -> Self { - let given_range = field.range.end - field.range.start; + let given_range = field.range.end() - field.range.start(); let needed_range = given_range / field.resolution; let length = needed_range.log2().ceil() as u32; let length = length.try_into().expect("max field length is 256 bits"); let decode_scale = field.resolution; - let decode_add = field.range.start; + let decode_add = *field.range.start(); LengthWithOps { length, decode_scale, diff --git a/crates/protocol/src/button.rs b/crates/protocol/src/button.rs index c40bca25..a7b476d2 100644 --- a/crates/protocol/src/button.rs +++ b/crates/protocol/src/button.rs @@ -82,7 +82,7 @@ macro_rules! button_enum { val: (*self).into(), device: $device, description: "button", - range: 0.0..3.0, + range: 0.0..=2.0, resolution: 1.0, unit: crate::Unit::None, branch_id: self.branch_id(), diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index fae5f3c1..a68421e6 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -100,7 +100,7 @@ impl Tree for Reading { Reading::Brightness(val) => ( *val, Device::Max44.rooted(), - 0.0..188_000.0, + 0.0..=188_000.0, 0.045, Unit::Lux, "Brightness", @@ -108,7 +108,7 @@ impl Tree for Reading { Reading::Temperature(val) => ( *val, Device::Sht31.rooted(), - -10.0..45.0, + -10.0..=45.0, 0.01, Unit::C, "Temperature", @@ -116,7 +116,7 @@ impl Tree for Reading { Reading::Humidity(val) => ( *val, Device::Sht31.rooted(), - 0.0..100.0, + 0.0..=100.0, 0.01, Unit::RH, "Relative humidity", @@ -125,7 +125,7 @@ impl Tree for Reading { Reading::GassResistance(val) => ( *val, Device::Bme680.rooted(), - 0.0..1_000_000.0, + 0.0..=1_000_000.0, 1.0, Unit::Ohm, "Gass resistance", @@ -136,7 +136,7 @@ impl Tree for Reading { Reading::Pressure(val) => ( *val, Device::Bme680.rooted(), - 87_000.0..108_100.0, + 87_000.0..=108_100.0, 0.18, Unit::Pa, "Air pressure", @@ -144,7 +144,7 @@ impl Tree for Reading { Reading::Co2(val) => ( f32::from(*val), Device::Mhz14.rooted(), - 400.0..2_000.0, + 400.0..=2_000.0, 1.0, Unit::Ppm, "Co2 concentration", @@ -152,7 +152,7 @@ impl Tree for Reading { Reading::WeightLeft(val) => ( *val as f32, Device::Nau7802Left.rooted(), - 0.0..24.0_f32.exp2(), + 0.0..=24.0_f32.exp2(), 1.0, Unit::Ohm, "Left weight sensor resistance", @@ -160,7 +160,7 @@ impl Tree for Reading { Reading::WeightRight(val) => ( *val as f32, Device::Nau7802Right.rooted(), - 0.0..24.0_f32.exp2(), + 0.0..=24.0_f32.exp2(), 1.0, Unit::Ohm, "Right weight sensor resistance", @@ -169,7 +169,7 @@ impl Tree for Reading { Reading::MassPm1_0(val) => ( *val, Device::Sps30.rooted(), - 0.0..1000.0, + 0.0..=1000.0, 0.1, Unit::MicrogramPerM3, "Mass concentration particles between 0.3 to 1.0 μm", @@ -177,7 +177,7 @@ impl Tree for Reading { Reading::MassPm2_5(val) => ( *val, Device::Sps30.rooted(), - 0.0..1000.0, + 0.0..=1000.0, 0.1, Unit::MicrogramPerM3, "Mass concentration particles between 0.3 to 2.5 μm", @@ -185,7 +185,7 @@ impl Tree for Reading { Reading::MassPm4_0(val) => ( *val, Device::Sps30.rooted(), - 0.0..1000.0, + 0.0..=1000.0, 0.1, Unit::MicrogramPerM3, "Mass concentration particles between 0.3 to 4.0 μm", @@ -193,7 +193,7 @@ impl Tree for Reading { Reading::MassPm10(val) => ( *val, Device::Sps30.rooted(), - 0.0..1000.0, + 0.0..=1000.0, 0.1, Unit::MicrogramPerM3, "Mass concentration particles between 0.3 to 10.0 μm", @@ -201,7 +201,7 @@ impl Tree for Reading { Reading::NumberPm0_5(val) => ( *val, Device::Sps30.rooted(), - 0.0..3000.0, + 0.0..=3000.0, 0.1, Unit::NumberPerCm3, "Concentration of particles between 0.3 to 0.5 μm", @@ -209,7 +209,7 @@ impl Tree for Reading { Reading::NumberPm1_0(val) => ( *val, Device::Sps30.rooted(), - 0.0..3000.0, + 0.0..=3000.0, 0.1, Unit::NumberPerCm3, "Concentration of particles between 0.3 to 1.0 μm", @@ -217,7 +217,7 @@ impl Tree for Reading { Reading::NumberPm2_5(val) => ( *val, Device::Sps30.rooted(), - 0.0..3000.0, + 0.0..=3000.0, 0.1, Unit::NumberPerCm3, "Concentration of particles between 0.3 to 2.5 μm", @@ -225,7 +225,7 @@ impl Tree for Reading { Reading::NumberPm4_0(val) => ( *val, Device::Sps30.rooted(), - 0.0..3000.0, + 0.0..=3000.0, 0.1, Unit::NumberPerCm3, "Concentration of particles between 0.3 to 4.0 μm", @@ -233,7 +233,7 @@ impl Tree for Reading { Reading::NumberPm10(val) => ( *val, Device::Sps30.rooted(), - 0.0..3000.0, + 0.0..=3000.0, 0.1, Unit::NumberPerCm3, "Concentration of particles between 0.3 to 10.5 μm", @@ -241,7 +241,7 @@ impl Tree for Reading { Reading::TypicalParticleSize(val) => ( *val, Device::Sps30.rooted(), - 0.0..10_000.0, + 0.0..=10_000.0, 0.5, Unit::NanoMeter, "Typical particle size", diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index afc60acb..d74d8470 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -58,7 +58,7 @@ impl Tree for Reading { val: *val, device: Device::Bme280.rooted(), resolution: 0.01, - range: -10.0..45.0, + range: -10.0..=45.0, unit: Unit::C, description: "Temperature", branch_id: self.branch_id(), @@ -68,7 +68,7 @@ impl Tree for Reading { val: *val, device: Device::Bme280.rooted(), resolution: 0.008, - range: 0.0..100.0, + range: 0.0..=100.0, unit: Unit::RH, description: "Humidity", branch_id: self.branch_id(), @@ -77,7 +77,7 @@ impl Tree for Reading { Reading::Pressure(val) => Info { val: *val, device: Device::Bme280.rooted(), - range: 87_000.0..108_100.0, + range: 87_000.0..=108_100.0, resolution: 0.18, unit: Unit::Pa, description: "Air pressure", diff --git a/crates/protocol/src/large_bedroom/radiator.rs b/crates/protocol/src/large_bedroom/radiator.rs index f90ec492..5400d7c0 100644 --- a/crates/protocol/src/large_bedroom/radiator.rs +++ b/crates/protocol/src/large_bedroom/radiator.rs @@ -46,7 +46,7 @@ impl Tree for Reading { Device, )), resolution: 0.01, - range: -10.0..45.0, + range: -10.0..=45.0, unit: Unit::C, description: "Temperature", branch_id: self.branch_id(), @@ -58,7 +58,7 @@ impl Tree for Reading { Device, )), resolution: 1.0, - range: 0.0..100.0, + range: 0.0..=100.0, unit: Unit::RelativePower, description: "Heating valve", branch_id: self.branch_id(), @@ -70,7 +70,7 @@ impl Tree for Reading { Device, )), resolution: 1.0, - range: 0.0..3.0, + range: 0.0..=3.0, unit: Unit::None, description: "Manual value set", branch_id: self.branch_id(), @@ -84,7 +84,7 @@ impl Tree for Reading { Device, )), resolution: 0.5, - range: 0.0..30.0, + range: 0.0..=30.0, unit: Unit::C, description: "Set point", branch_id: self.branch_id(), diff --git a/crates/protocol/src/reading.rs b/crates/protocol/src/reading.rs index c2c13ec2..764cfb17 100644 --- a/crates/protocol/src/reading.rs +++ b/crates/protocol/src/reading.rs @@ -37,7 +37,7 @@ impl Reading { self.leaf().from_same_device() } #[must_use] - pub fn range(&self) -> core::ops::Range { + pub fn range(&self) -> core::ops::RangeInclusive { use tree::Tree; self.leaf().range } @@ -103,7 +103,7 @@ pub struct Info { pub device: Device, /// smallest step size the data can make pub resolution: f32, - pub range: core::ops::Range, + pub range: core::ops::RangeInclusive, pub unit: Unit, pub description: &'static str, pub branch_id: u8, diff --git a/crates/protocol/src/small_bedroom/bed.rs b/crates/protocol/src/small_bedroom/bed.rs index c851e2f8..b1b9209d 100644 --- a/crates/protocol/src/small_bedroom/bed.rs +++ b/crates/protocol/src/small_bedroom/bed.rs @@ -89,7 +89,7 @@ impl Tree for Reading { Reading::Brightness(val) => ( *val, Device::Max44.rooted(), - 0.0..188_000.0, + 0.0..=188_000.0, 0.045, Unit::Lux, "Brightness", @@ -97,7 +97,7 @@ impl Tree for Reading { Reading::Temperature(val) => ( *val, Device::Sht31.rooted(), - -10.0..45.0, + -10.0..=45.0, 0.01, Unit::C, "Temperature", @@ -105,7 +105,7 @@ impl Tree for Reading { Reading::Humidity(val) => ( *val, Device::Sht31.rooted(), - 0.0..100.0, + 0.0..=100.0, 0.01, Unit::RH, "Relative humidity", @@ -114,7 +114,7 @@ impl Tree for Reading { Reading::GassResistance(val) => ( *val, Device::Bme680.rooted(), - 0.0..1_000_000.0, + 0.0..=1_000_000.0, 1.0, Unit::Ohm, "Gass resistance", @@ -125,7 +125,7 @@ impl Tree for Reading { Reading::Pressure(val) => ( *val, Device::Bme680.rooted(), - 87_000.0..108_100.0, + 87_000.0..=108_100.0, 0.18, Unit::Pa, "Air pressure", @@ -133,7 +133,7 @@ impl Tree for Reading { Reading::Co2(val) => ( f32::from(*val), Device::Mhz14.rooted(), - 400.0..2_000.0, + 400.0..=2_000.0, 1.0, Unit::Ppm, "Co2 concentration", @@ -141,7 +141,7 @@ impl Tree for Reading { Reading::Weight(val) => ( *val as f32, Device::Nau7802.rooted(), - 0.0..24.0_f32.exp2(), + 0.0..=24.0_f32.exp2(), 1.0, Unit::Ohm, "weight sensor resistance", @@ -150,7 +150,7 @@ impl Tree for Reading { Reading::MassPm1_0(val) => ( *val, Device::Sps30.rooted(), - 0.0..1000.0, + 0.0..=1000.0, 0.1, Unit::MicrogramPerM3, "Mass concentration particles between 0.3 to 1.0 μm", @@ -158,7 +158,7 @@ impl Tree for Reading { Reading::MassPm2_5(val) => ( *val, Device::Sps30.rooted(), - 0.0..1000.0, + 0.0..=1000.0, 0.1, Unit::MicrogramPerM3, "Mass concentration particles between 0.3 to 2.5 μm", @@ -166,7 +166,7 @@ impl Tree for Reading { Reading::MassPm4_0(val) => ( *val, Device::Sps30.rooted(), - 0.0..1000.0, + 0.0..=1000.0, 0.1, Unit::MicrogramPerM3, "Mass concentration particles between 0.3 to 4.0 μm", @@ -174,7 +174,7 @@ impl Tree for Reading { Reading::MassPm10(val) => ( *val, Device::Sps30.rooted(), - 0.0..1000.0, + 0.0..=1000.0, 0.1, Unit::MicrogramPerM3, "Mass concentration particles between 0.3 to 10.0 μm", @@ -182,7 +182,7 @@ impl Tree for Reading { Reading::NumberPm0_5(val) => ( *val, Device::Sps30.rooted(), - 0.0..3000.0, + 0.0..=3000.0, 0.1, Unit::NumberPerCm3, "Concentration of particles between 0.3 to 0.5 μm", @@ -190,7 +190,7 @@ impl Tree for Reading { Reading::NumberPm1_0(val) => ( *val, Device::Sps30.rooted(), - 0.0..3000.0, + 0.0..=3000.0, 0.1, Unit::NumberPerCm3, "Concentration of particles between 0.3 to 1.0 μm", @@ -198,7 +198,7 @@ impl Tree for Reading { Reading::NumberPm2_5(val) => ( *val, Device::Sps30.rooted(), - 0.0..3000.0, + 0.0..=3000.0, 0.1, Unit::NumberPerCm3, "Concentration of particles between 0.3 to 2.5 μm", @@ -206,7 +206,7 @@ impl Tree for Reading { Reading::NumberPm4_0(val) => ( *val, Device::Sps30.rooted(), - 0.0..3000.0, + 0.0..=3000.0, 0.1, Unit::NumberPerCm3, "Concentration of particles between 0.3 to 4.0 μm", @@ -214,7 +214,7 @@ impl Tree for Reading { Reading::NumberPm10(val) => ( *val, Device::Sps30.rooted(), - 0.0..3000.0, + 0.0..=3000.0, 0.1, Unit::NumberPerCm3, "Concentration of particles between 0.3 to 10.5 μm", @@ -222,7 +222,7 @@ impl Tree for Reading { Reading::TypicalParticleSize(val) => ( *val, Device::Sps30.rooted(), - 0.0..10_000.0, + 0.0..=10_000.0, 0.5, Unit::NanoMeter, "Typical particle size", diff --git a/crates/protocol/src/small_bedroom/desk.rs b/crates/protocol/src/small_bedroom/desk.rs index 7d7badfa..367c35f9 100644 --- a/crates/protocol/src/small_bedroom/desk.rs +++ b/crates/protocol/src/small_bedroom/desk.rs @@ -41,7 +41,7 @@ impl Tree for Reading { val: *val, device: Device::Bme280.rooted(), resolution: 0.01, - range: -10.0..45.0, + range: -10.0..=45.0, unit: Unit::C, description: "Temperature", branch_id: self.branch_id(), @@ -51,7 +51,7 @@ impl Tree for Reading { val: *val, device: Device::Bme280.rooted(), resolution: 0.008, - range: 0.0..100.0, + range: 0.0..=100.0, unit: Unit::RH, description: "Humidity", branch_id: self.branch_id(), @@ -60,7 +60,7 @@ impl Tree for Reading { Reading::Pressure(val) => Info { val: *val, device: Device::Bme280.rooted(), - range: 87_000.0..108_100.0, + range: 87_000.0..=108_100.0, resolution: 0.18, unit: Unit::Pa, description: "Air pressure", diff --git a/crates/protocol/src/small_bedroom/portable_button_panel.rs b/crates/protocol/src/small_bedroom/portable_button_panel.rs index c3c3156d..bd48233b 100644 --- a/crates/protocol/src/small_bedroom/portable_button_panel.rs +++ b/crates/protocol/src/small_bedroom/portable_button_panel.rs @@ -51,7 +51,7 @@ impl Tree for Reading { super::Device::PortableButtonPanel(Device), ), description: "button", - range: 0.0..3.0, + range: 0.0..=2.0, resolution: 1.0, unit: crate::Unit::None, branch_id: self.branch_id(), diff --git a/crates/protocol/src/small_bedroom/radiator.rs b/crates/protocol/src/small_bedroom/radiator.rs index 5dfac2ed..7cedc63d 100644 --- a/crates/protocol/src/small_bedroom/radiator.rs +++ b/crates/protocol/src/small_bedroom/radiator.rs @@ -46,7 +46,7 @@ impl Tree for Reading { Device, )), resolution: 0.01, - range: -10.0..45.0, + range: -10.0..=45.0, unit: Unit::C, description: "Temperature", branch_id: self.branch_id(), @@ -58,7 +58,7 @@ impl Tree for Reading { Device, )), resolution: 1.0, - range: 0.0..100.0, + range: 0.0..=100.0, unit: Unit::RelativePower, description: "Heating valve", branch_id: self.branch_id(), @@ -70,7 +70,7 @@ impl Tree for Reading { Device, )), resolution: 1.0, - range: 0.0..3.0, + range: 0.0..=2.0, unit: Unit::None, description: "Manual value set", branch_id: self.branch_id(), @@ -84,7 +84,7 @@ impl Tree for Reading { Device, )), resolution: 0.5, - range: 0.0..30.0, + range: 0.0..=30.0, unit: Unit::C, description: "Set point", branch_id: self.branch_id(), diff --git a/crates/ui/examples/chart_gaps.rs b/crates/ui/examples/chart_gaps.rs index d1cf27ec..b7b14ffa 100644 --- a/crates/ui/examples/chart_gaps.rs +++ b/crates/ui/examples/chart_gaps.rs @@ -25,7 +25,7 @@ fn data_with_gap(buffer: &mut Vec<(f64, f64)>) -> ChartParts<'_> { ), ), resolution: 1.0, - range: 0.0..5.0, + range: 0.0..=5.0, unit: protocol::Unit::Ohm, description: "test data with gaps", branch_id: 0, diff --git a/crates/ui/src/tui/readings/render/chart.rs b/crates/ui/src/tui/readings/render/chart.rs index 78131cd6..3a0c00fd 100644 --- a/crates/ui/src/tui/readings/render/chart.rs +++ b/crates/ui/src/tui/readings/render/chart.rs @@ -266,7 +266,7 @@ fn ybounds(chart: &ChartParts, layout: Rect) -> Bounds { let y_margin = f64::max(y_range * margin, resolution / 2.0); let bounds = [bounds[0] - y_margin, bounds[1] + y_margin]; [ - bounds[0].max(range.start as f64), - bounds[1].min(range.end as f64), + bounds[0].max(*range.start() as f64), + bounds[1].min(*range.end() as f64), ] } diff --git a/crates/ui/src/tui/readings/render/chart/split.rs b/crates/ui/src/tui/readings/render/chart/split.rs index 0b6e676e..12726d17 100644 --- a/crates/ui/src/tui/readings/render/chart/split.rs +++ b/crates/ui/src/tui/readings/render/chart/split.rs @@ -78,7 +78,7 @@ mod test { large_bedroom::bed::Device::Bme680, )), resolution: 1.0, - range: 0.0..200.0, + range: 0.0..=200.0, unit: protocol::Unit::C, description: "test", branch_id: 1, From 6f0930e80d99096a01223ee846710ef3a194dc47 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 28 Mar 2025 15:56:52 +0100 Subject: [PATCH 623/687] Add meditation controls to portable button panels --- .../src/controller/rooms/small_bedroom.rs | 65 ++++++++++++------- .../rooms/small_bedroom/audiocontrol.rs | 19 +++--- 2 files changed, 51 insertions(+), 33 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index fc9127b3..3e2cb069 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -116,54 +116,71 @@ async fn handle_button(room: &mut Room, event: RelevantEvent) { | P::Dots2LongRelease => { handle_light_button(room, event).await; } - b => info!("Pressed unimplemented button: {b:?}") + b => info!("Pressed unimplemented button: {b:?}"), }, _ => unreachable!(), } } -async fn handle_audio_button(room: &mut Room, button_press: RelevantEvent) { +async fn handle_audio_button(room: &mut Room, button_event: RelevantEvent) { use audiocontrol::AudioMode as A; use portable_button_panel::Reading as P; use ButtonPanel as B; + use RelevantEvent as E; let mut audio = room.audio_controller.lock().await; - let RelevantEvent::Button(button_press) = button_press else { - error!( - "Tried handling non-button as audio button: {:?}", - button_press - ); - return; - }; - match (&audio.mode, button_press) { - (A::Music | A::Singing | A::Meditation, B::TopLeft(press)) - if !press.is_long() => - { - audio.previous() + match (&audio.mode, button_event) { + // Music, Singing, Meditation back (short) = previous + ( + A::Music | A::Singing | A::Meditation, + E::Button(B::TopLeft(press)), + ) if !press.is_long() => audio.previous(), + ( + A::Music | A::Singing | A::Meditation, + E::PortableButton(P::TrackPrevious), + ) => audio.previous(), + // Podcast back (short) = rewind + (A::Podcast, E::Button(B::TopLeft(press))) if !press.is_long() => { + audio.rewind() } - (A::Podcast, B::TopLeft(press)) if !press.is_long() => audio.rewind(), - (A::Music | A::Singing | A::Meditation, B::TopRight(press)) - if !press.is_long() => - { - audio.next() + // Music, Singing, Meditation forward (short) = next + ( + A::Music | A::Singing | A::Meditation, + E::Button(B::TopRight(press)), + ) if !press.is_long() => audio.next(), + ( + A::Music | A::Singing | A::Meditation, + E::PortableButton(P::TrackNext), + ) => audio.next(), + // Podcast forward (short) = skip + (A::Podcast, E::Button(B::TopRight(press))) if !press.is_long() => { + audio.skip() } - (A::Podcast, B::TopRight(press)) if !press.is_long() => audio.skip(), - (_, B::TopMiddle(press)) if !press.is_long() => audio.toggle_playback(), + (_, E::Button(B::TopMiddle(press))) if !press.is_long() => { + audio.toggle_playback() + } - (_, B::TopLeft(press)) if press.is_long() => { + (_, E::Button(B::TopLeft(press))) if press.is_long() => { audio.prev_playlist(); audio.play(ForceRewind::No) } - (_, B::TopRight(press)) if press.is_long() => { + (_, E::Button(B::TopRight(press))) if press.is_long() => { audio.next_playlist(); audio.play(ForceRewind::No) } - (_, B::TopMiddle(press)) if press.is_long() => { + (_, E::Button(B::TopMiddle(press))) if press.is_long() => { audio.next_mode(); audio.play(ForceRewind::No) } + (_, E::PortableButton(P::PlayPause)) => { + audio + .go_to_mode_playlist(&A::Meditation, "meditation_yoga-nidra") + .await; + audio.toggle_playback(); + } + (_, b) => info!("Unrecognised button pressed: {b:?}"), } } diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs index 76d28575..6b57dab4 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs @@ -157,7 +157,7 @@ impl AudioController { self.client.rescan().unwrap(); } - fn playing(&mut self) -> bool { + pub fn playing(&mut self) -> bool { let playback_state = self.client.status().unwrap().state; playback_state == State::Play } @@ -608,7 +608,7 @@ impl AudioController { Ok(()) } - pub(crate) async fn play_mode_playlist( + pub(crate) async fn go_to_mode_playlist( &mut self, mode: &AudioMode, playlist: &str, @@ -619,12 +619,6 @@ impl AudioController { Ok(()) => (), Err(e) => println!("{e}"), }; - tokio::time::sleep(Duration::from_millis(100)).await; - self.load_playlist(playlist); - tokio::time::sleep(Duration::from_millis(100)).await; - self.load_position(None); - tokio::time::sleep(Duration::from_millis(100)).await; - self.play(ForceRewind::No); } pub(crate) async fn start_wakeup_music(&mut self) { @@ -633,7 +627,14 @@ impl AudioController { let pl_name = "music_wakeup"; self.create_wakeup_playlist(pl_name).await; - self.play_mode_playlist(&AudioMode::Music, pl_name).await; + self.go_to_mode_playlist(&AudioMode::Music, pl_name).await; + + tokio::time::sleep(Duration::from_millis(100)).await; + self.load_playlist(pl_name); + tokio::time::sleep(Duration::from_millis(100)).await; + self.load_position(None); + tokio::time::sleep(Duration::from_millis(100)).await; + self.play(ForceRewind::No); } async fn create_wakeup_playlist(&mut self, pl_name: &str) { From 1e5d6c84c5b228849eeabbd6f9bd32d93050f76d Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 28 Mar 2025 16:50:56 +0100 Subject: [PATCH 624/687] update script now prompts user to make protocol change --- crates/data-store/update_data.sh | 140 ++++++++++++++++++------------- 1 file changed, 82 insertions(+), 58 deletions(-) diff --git a/crates/data-store/update_data.sh b/crates/data-store/update_data.sh index 8cfb034c..70e64053 100755 --- a/crates/data-store/update_data.sh +++ b/crates/data-store/update_data.sh @@ -2,61 +2,85 @@ set -e -if [ ! -d data ]; then - ssh sgc -q << ENDSSH -set -e -sudo systemctl stop data-store -cd /home/ha -sudo tar -czf data.tar.gz data -ENDSSH - - rsync sgc:/home/david/data.tar.gz . - tar -xzf data.tar.gz -else - echo "data directory already exists, skipping fetch data from server" -fi - -if [ ! -d data_updated ]; then - cargo r --release -- --data-dir data export - cp -r data data_updated - rm $(find data_updated | grep '.byteseries') -else - echo "data_updated directory already exists skipping exporting" -fi - -if [ ! -f data_updated.tar.gz ]; then - cargo r --release -- --data-dir data_updated import - rm $(find data_updated | grep '.csv') - tar -czf data_updated.tar.gz data_updated -else - echo "data_updated.tar.gz already exists skipping importing" -fi - -rsync $(pwd)/data_updated.tar.gz sgc:/home/david/ - -result=$(ssh sgc -q << ENDSSH -set -e -if [ -d /home/ha/data ]; then - sudo mv /home/ha/data{,_backup} -fi -sudo tar -xzf data_updated.tar.gz -C /home/ha -sudo mv /home/ha/data{_updated,} -sudo chown -R ha:ha /home/ha/data -echo success -ENDSSH -) - -if [[ $result != *success ]]; then - echo "Error, unpacking failed on server." - echo "$result" - exit -fi - -ssh sgc -q << ENDSSH -sudo systemctl start data-store -ENDSSH - -sleep 5 -ssh sgc -q << ENDSSH -sudo systemctl status data-store -ENDSSH +function download_and_export_to_csv { + if [ ! -d data ]; then + ssh sgc -q <<- ENDSSH + set -e + sudo systemctl stop data-store + cd /home/ha + sudo tar -czf data.tar.gz data + sudo chown david:david data.tar.gz + cp data.tar.gz /tmp/data.tar.gz + ENDSSH + + rsync sgc:/tmp/data.tar.gz . + tar -xzf data.tar.gz + else + echo "data directory already exists, skipping fetch data from server" + fi + + if [ ! -d data_updated ]; then + cargo r --release -- --data-dir data export + cp -r data data_updated + rm $(find data_updated | grep '.byteseries') + else + echo "data_updated directory already exists skipping exporting" + fi +} + +function import_from_csv_and_upload { + if [ ! -f data_updated.tar.gz ]; then + cargo r --release -- --data-dir data_updated import + rm $(find data_updated | grep '.csv') + tar -czf data_updated.tar.gz data_updated + else + echo "data_updated.tar.gz already exists skipping importing" + fi + + rsync $(pwd)/data_updated.tar.gz sgc:/tmp/ + + result=$(ssh sgc -q <<- ENDSSH + set -e + if [ -d /home/ha/data ]; then + sudo mv /home/ha/data{,_backup} + fi + sudo tar -xzf /tmp/data_updated.tar.gz -C /home/ha + sudo mv /home/ha/data{_updated,} + sudo chown -R ha:ha /home/ha/data + echo success + ENDSSH + ) + + if [[ $result != *success ]]; then + echo "Error, unpacking failed on server." + echo "$result" + exit + fi + + ssh sgc -q <<- ENDSSH + sudo systemctl start data-store + ENDSSH + + sleep 5 + ssh sgc -q <<- ENDSSH + sudo systemctl status data-store + ENDSSH +} + +echo -e "updating to a new encoding (range changed for example) is a two step process:\n\ + 1. download encoded data and export with the current encoding\n\ + 2. switch to the new data-store build\n\ + 3. import the data from the exported csv's\n\ +" + +while true +do + read -r -p 'at which step are you? (n to abort)' choice + case "$choice" in + n|N) break;; + 1) download_and_export_to_csv;; + 2) echo 'The script can not do that for you! do it then continue';; + 3) import_from_csv_and_upload && break;; + *) echo 'Response not valid try: 1,2,3 or n';; + esac +done From 1bb98e87e2db6ad23f06088b5fe917fc58609d38 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 28 Mar 2025 16:54:26 +0100 Subject: [PATCH 625/687] Add volume setting per mode --- .../rooms/small_bedroom/audiocontrol.rs | 18 +++++++++++++++++- .../small_bedroom/audiocontrol/mpdinterface.rs | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs index 6b57dab4..1e73e48d 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs @@ -23,17 +23,30 @@ enum Direction { Previous, } -#[derive(Default)] #[allow(clippy::struct_excessive_bools)] struct Settings { repeat: bool, random: bool, single: bool, consume: bool, + volume: i8, save_playlist: bool, } +impl Default for Settings { + fn default() -> Self { + Self { + repeat: false, + random: false, + single: false, + consume: false, + volume: 90, + save_playlist: false, + } + } +} + #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize, Clone)] pub enum AudioMode { Music, @@ -70,10 +83,12 @@ impl AudioMode { Podcast => Settings { consume: true, save_playlist: true, + volume: 100, ..Settings::default() }, Meditation => Settings { single: true, + volume: 100, ..Settings::default() }, } @@ -579,6 +594,7 @@ impl AudioController { self.client.random(audio_settings.random).unwrap(); self.client.single(audio_settings.single).unwrap(); self.client.consume(audio_settings.consume).unwrap(); + self.client.volume(audio_settings.volume).unwrap(); self.client.pause().unwrap(); } diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/mpdinterface.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/mpdinterface.rs index d2ecf13f..49958c6d 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/mpdinterface.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/mpdinterface.rs @@ -94,6 +94,7 @@ impl MpdInterface { ok_or_reconnect_one_arg! {consume, value, bool, ()} ok_or_reconnect_one_arg! {playlist, name, &str, Vec} ok_or_reconnect_one_arg! {push, path, &str, u32} + ok_or_reconnect_one_arg! {volume, volume, i8, ()} pub(crate) fn pause(&mut self) -> Result<()> { match self.client.pause(true) { From d2cffdfb879edef23d0a8780b1811ce74b21b01a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 28 Mar 2025 18:19:51 +0100 Subject: [PATCH 626/687] refactors update script --- crates/data-store/update_data.sh | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/crates/data-store/update_data.sh b/crates/data-store/update_data.sh index 70e64053..13aab61a 100755 --- a/crates/data-store/update_data.sh +++ b/crates/data-store/update_data.sh @@ -3,15 +3,20 @@ set -e function download_and_export_to_csv { + if [ -d data_updated ]; then + echo "nothing to do: data_updated directory already exists" + return + fi + if [ ! -d data ]; then ssh sgc -q <<- ENDSSH - set -e - sudo systemctl stop data-store - cd /home/ha - sudo tar -czf data.tar.gz data - sudo chown david:david data.tar.gz - cp data.tar.gz /tmp/data.tar.gz - ENDSSH + set -e + sudo systemctl stop data-store + cd /home/ha + sudo tar -czf data.tar.gz data + sudo chown david:david data.tar.gz + cp data.tar.gz /tmp/data.tar.gz + ENDSSH rsync sgc:/tmp/data.tar.gz . tar -xzf data.tar.gz @@ -19,13 +24,10 @@ function download_and_export_to_csv { echo "data directory already exists, skipping fetch data from server" fi - if [ ! -d data_updated ]; then - cargo r --release -- --data-dir data export - cp -r data data_updated - rm $(find data_updated | grep '.byteseries') - else - echo "data_updated directory already exists skipping exporting" - fi + cargo r --release -- --data-dir data export + cp -r data data_updated + + rm $(find data_updated | grep '.byteseries') } function import_from_csv_and_upload { From f637f120a3c8868a6f6da4d4ee87affb0e48860e Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 28 Mar 2025 18:48:51 +0100 Subject: [PATCH 627/687] make airbox use rangeinclusive --- crates/protocol/src/large_bedroom/airbox.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/protocol/src/large_bedroom/airbox.rs b/crates/protocol/src/large_bedroom/airbox.rs index 91257cca..ba344339 100644 --- a/crates/protocol/src/large_bedroom/airbox.rs +++ b/crates/protocol/src/large_bedroom/airbox.rs @@ -47,7 +47,7 @@ impl Tree for Reading { val: *val, device: Device::Bme280.rooted(), resolution: 0.01, - range: -10.0..45.0, + range: -10.0..=45.0, unit: Unit::C, description: "Temperature", branch_id: self.branch_id(), @@ -56,7 +56,7 @@ impl Tree for Reading { Reading::Pressure(val) => Info { val: *val, device: Device::Bme280.rooted(), - range: 87_000.0..108_100.0, + range: 87_000.0..=108_100.0, resolution: 0.18, unit: Unit::Pa, description: "Air pressure", @@ -69,7 +69,7 @@ impl Tree for Reading { Device::Fans, )), resolution: 1.0, - range: 0.0..100.0, + range: 0.0..=100.0, unit: Unit::RelativePower, description: "Fan power", branch_id: self.branch_id(), @@ -81,7 +81,7 @@ impl Tree for Reading { Device::Gpio, )), description: "button", - range: 0.0..3.0, + range: 0.0..=2.0, resolution: 1.0, unit: crate::Unit::None, branch_id: self.branch_id(), From 66f7d1f92bd770ef69eb8916b4473e412315e150 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 29 Mar 2025 00:22:07 +0100 Subject: [PATCH 628/687] update to avoid unmaintained users carte --- crates/usb-bridge/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/usb-bridge/Cargo.toml b/crates/usb-bridge/Cargo.toml index c1eb389a..d1b78d17 100644 --- a/crates/usb-bridge/Cargo.toml +++ b/crates/usb-bridge/Cargo.toml @@ -20,4 +20,4 @@ tracing-error = { workspace = true } tracing = { workspace = true } nusb = "0.1.10" color-eyre.workspace = true -users = "0.11.0" +uzers = "0.12.0" From 1dcd616804f675ac14483e8a8142415e3b4d0406 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 29 Mar 2025 01:15:01 +0100 Subject: [PATCH 629/687] Updates dependencies - `users` is replaced by `uzers` maintained fork - `rand` changed API slightly (Slice trait -> Index trait) - `bincode` majorly changed, explicitly opting into using `serde` encoding changed too (defaults changed) only affects on disk data for log store, its okay to wipe it. --- Cargo.lock | 690 ++++++++++-------- Cargo.toml | 11 +- crates/brain/Cargo.toml | 6 +- .../rooms/small_bedroom/audiocontrol.rs | 4 +- crates/data-server/Cargo.toml | 2 +- crates/data-store/Cargo.toml | 10 +- crates/log-store/Cargo.toml | 8 +- crates/log-store/src/server/db/log.rs | 22 +- crates/protocol/Cargo.toml | 2 +- crates/rpc/Cargo.toml | 2 +- crates/text-widget/Cargo.toml | 4 +- crates/usb-bridge/src/usb/device.rs | 2 +- crates/zigbee-bridge/Cargo.toml | 4 +- crates/zigbee-bridge/src/cached_bridge.rs | 2 +- 14 files changed, 430 insertions(+), 339 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0a8fbc49..c26de4ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,6 +145,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bincode" version = "1.3.3" @@ -154,6 +160,16 @@ dependencies = [ "serde", ] +[[package]] +name = "bincode" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" +dependencies = [ + "serde", + "unty", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -162,9 +178,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.7.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" dependencies = [ "serde", ] @@ -194,7 +210,7 @@ dependencies = [ name = "brain" version = "0.1.0" dependencies = [ - "bincode", + "bincode 2.0.1", "byteorder", "bytes", "clap", @@ -213,8 +229,8 @@ dependencies = [ "serde", "serde_yaml", "sled", - "strum", - "thiserror 2.0.11", + "strum 0.27.1", + "thiserror 2.0.12", "tokio", "tracing", "zigbee-bridge", @@ -228,15 +244,15 @@ checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "bytemuck" -version = "1.21.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" +checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" [[package]] name = "byteorder" @@ -246,9 +262,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.9.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "byteseries" @@ -258,9 +274,9 @@ dependencies = [ "arraydeque", "itertools 0.13.0", "num-traits", - "ron", + "ron 0.8.1", "serde", - "smallvec 2.0.0-alpha.9", + "smallvec 2.0.0-alpha.11", "thiserror 1.0.69", "tracing", ] @@ -288,9 +304,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.9" +version = "1.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" +checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" dependencies = [ "shlex", ] @@ -303,9 +319,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.26" +version = "4.5.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" +checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff" dependencies = [ "clap_builder", "clap_derive", @@ -313,9 +329,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.26" +version = "4.5.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" +checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489" dependencies = [ "anstream", "anstyle", @@ -325,14 +341,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.24" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" +checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] @@ -414,8 +430,8 @@ dependencies = [ "num-traits", "once_cell", "paste", - "strum", - "strum_macros", + "strum 0.26.3", + "strum_macros 0.26.4", "thiserror 1.0.69", "url", "wasm-bindgen", @@ -438,9 +454,9 @@ dependencies = [ [[package]] name = "console" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" dependencies = [ "encode_unicode", "libc", @@ -493,9 +509,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] @@ -545,7 +561,7 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", "crossterm_winapi", "mio", "parking_lot 0.12.3", @@ -576,9 +592,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ "darling_core", "darling_macro", @@ -586,27 +602,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] name = "darling_macro" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] @@ -639,7 +655,7 @@ dependencies = [ "serde", "slotmap", "socket2", - "thiserror 2.0.11", + "thiserror 2.0.12", "tokio", "tokio-serde", "tokio-util", @@ -667,13 +683,13 @@ dependencies = [ "num", "protocol", "reserve-port", - "ron", + "ron 0.9.0", "rpc", "rstest", "serde", - "smallvec 2.0.0-alpha.9", + "smallvec 2.0.0-alpha.11", "temp-dir", - "thiserror 2.0.11", + "thiserror 2.0.12", "tokio", "tracing", "tracing-error", @@ -682,29 +698,29 @@ dependencies = [ [[package]] name = "dbstruct" -version = "0.4.1" -source = "git+https://github.com/dvdsk/dbstruct#e2f1147accff6a4d71d307d2311c7f493b31606e" +version = "0.5.0" +source = "git+https://github.com/dvdsk/dbstruct#54862aec8c225d34925b5ec943e0d49fd9efab22" dependencies = [ - "bincode", + "bincode 1.3.3", "dbstruct-derive", "serde", "sled", - "thiserror 1.0.69", + "thiserror 2.0.12", "tracing", ] [[package]] name = "dbstruct-derive" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "393042992e6516cf869ab7148ac3507ae1b9ce15d50b8f9bf43c8b05567b8acd" +checksum = "57bf0e86bb052514efb4038337e3be7444b941d874e6a406795cdf4fbfbc55fc" dependencies = [ - "itertools 0.11.0", + "itertools 0.14.0", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.96", - "thiserror 1.0.69", + "syn 2.0.100", + "thiserror 2.0.12", ] [[package]] @@ -727,7 +743,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] @@ -736,7 +752,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3983b127f13995e68c1e29071e5d115cd96f215ccb5e6812e3728cd6f92653b3" dependencies = [ - "thiserror 2.0.11", + "thiserror 2.0.12", ] [[package]] @@ -752,15 +768,15 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.18" +version = "0.99.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] @@ -801,9 +817,9 @@ dependencies = [ [[package]] name = "dirs" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ "dirs-sys", ] @@ -820,14 +836,14 @@ dependencies = [ [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", - "redox_users", - "windows-sys 0.48.0", + "redox_users 0.5.0", + "windows-sys 0.59.0", ] [[package]] @@ -837,7 +853,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", - "redox_users", + "redox_users 0.4.6", "winapi", ] @@ -849,7 +865,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] @@ -861,14 +877,14 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "embedded-hal" @@ -927,14 +943,14 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" @@ -968,12 +984,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fd-lock" @@ -994,12 +1007,12 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.0.35" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" dependencies = [ "crc32fast", - "miniz_oxide 0.8.2", + "miniz_oxide 0.8.5", ] [[package]] @@ -1021,9 +1034,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "form_urlencoded" @@ -1061,14 +1074,15 @@ dependencies = [ [[package]] name = "futures-buffered" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34acda8ae8b63fbe0b2195c998b180cff89a8212fb2622a78b572a9f1c6f7684" +checksum = "fe940397c8b744b9c2c974791c2c08bca2c3242ce0290393249e98f215a00472" dependencies = [ "cordyceps", "diatomic-waker", "futures-core", "pin-project-lite", + "spin", ] [[package]] @@ -1083,9 +1097,9 @@ dependencies = [ [[package]] name = "futures-concurrency" -version = "7.6.2" +version = "7.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b724496da7c26fcce66458526ce68fc2ecf4aaaa994281cf322ded5755520c" +checksum = "0eb68017df91f2e477ed4bea586c59eaecaa47ed885a770d0444e21e62572cd2" dependencies = [ "fixedbitset", "futures-buffered", @@ -1093,7 +1107,7 @@ dependencies = [ "futures-lite", "pin-project", "slab", - "smallvec 1.13.2", + "smallvec 1.14.0", ] [[package]] @@ -1121,17 +1135,15 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "1.13.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" dependencies = [ "fastrand", "futures-core", "futures-io", - "memchr", "parking", "pin-project-lite", - "waker-fn", ] [[package]] @@ -1142,7 +1154,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] @@ -1231,7 +1243,21 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", ] [[package]] @@ -1248,23 +1274,25 @@ checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "governor" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "842dc78579ce01e6a1576ad896edc92fca002dd60c9c3746b7fc2bec6fb429d0" +checksum = "be93b4ec2e4710b04d9264c0c7350cdd62a8c20e5e4ac732552ebb8f0debe8eb" dependencies = [ "cfg-if", "dashmap", "futures-sink", "futures-timer", "futures-util", + "getrandom 0.3.2", "no-std-compat", "nonzero_ext", "parking_lot 0.12.3", "portable-atomic", "quanta", "rand", - "smallvec 1.13.2", + "smallvec 1.14.0", "spinning_top", + "web-time", ] [[package]] @@ -1273,7 +1301,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09831ec59b80be69e75d29cf36e16afbbe5fd1af9c1bf4689ad91c77db5aa6a6" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", "libc", "nix 0.27.1", ] @@ -1293,7 +1321,7 @@ dependencies = [ "nucleo-matcher", "promptly", "protocol", - "ron", + "ron 0.9.0", "serde", "tokio", "tracing", @@ -1342,7 +1370,7 @@ version = "7.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" dependencies = [ - "base64", + "base64 0.21.7", "byteorder", "crossbeam-channel", "flate2", @@ -1397,7 +1425,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a01f563561b53e2def844167c92984da13779a53ca409e948a03400633cb8228" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", "byteorder", "libc", "nix 0.26.4", @@ -1444,9 +1472,9 @@ dependencies = [ [[package]] name = "icu_locid_transform_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" +checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" [[package]] name = "icu_normalizer" @@ -1459,7 +1487,7 @@ dependencies = [ "icu_normalizer_data", "icu_properties", "icu_provider", - "smallvec 1.13.2", + "smallvec 1.14.0", "utf16_iter", "utf8_iter", "write16", @@ -1468,9 +1496,9 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" [[package]] name = "icu_properties" @@ -1489,9 +1517,9 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" [[package]] name = "icu_provider" @@ -1518,7 +1546,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] @@ -1534,7 +1562,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ "idna_adapter", - "smallvec 1.13.2", + "smallvec 1.14.0", "utf8_iter", ] @@ -1556,9 +1584,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -1583,16 +1611,16 @@ dependencies = [ "itertools 0.13.0", "proc-macro2", "quote", - "strum", - "syn 2.0.96", + "strum 0.26.3", + "syn 2.0.100", "thiserror 1.0.69", ] [[package]] name = "indicatif" -version = "0.17.9" +version = "0.17.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf675b85ed934d3c67b5c5469701eec7db22689d0a2139d856e0925fa28b281" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" dependencies = [ "console", "number_prefix", @@ -1603,9 +1631,9 @@ dependencies = [ [[package]] name = "indoc" -version = "2.0.5" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" +checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" [[package]] name = "instability" @@ -1617,7 +1645,7 @@ dependencies = [ "indoc", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] @@ -1645,15 +1673,6 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -1674,15 +1693,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" -version = "0.1.22" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c258647f65892e500c2478ef2c71ba008e7dc1774a8289345adbbb502a4def1" +checksum = "c04ef77ae73f3cf50510712722f0c4e8b46f5aaa1bf5ffad2ae213e6495e78e5" dependencies = [ "jiff-tzdb-platform", "log", @@ -1694,15 +1713,15 @@ dependencies = [ [[package]] name = "jiff-tzdb" -version = "0.1.1" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91335e575850c5c4c673b9bd467b0e025f164ca59d0564f69d0c2ee0ffad4653" +checksum = "c1283705eb0a21404d2bfd6eef2a7593d240bc42a0bdb39db0ad6fa2ec026524" [[package]] name = "jiff-tzdb-platform" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9835f0060a626fe59f160437bc725491a6af23133ea906500027d1bd2f8f4329" +checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" dependencies = [ "jiff-tzdb", ] @@ -1725,9 +1744,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.169" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "libm" @@ -1741,7 +1760,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", "libc", ] @@ -1789,9 +1808,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "litemap" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" +checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" [[package]] name = "lock_api" @@ -1805,15 +1824,15 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "log-store" version = "0.1.0" dependencies = [ - "bincode", + "bincode 2.0.1", "byteseries", "clap", "color-eyre", @@ -1830,9 +1849,9 @@ dependencies = [ "reserve-port", "rpc", "serde", - "smallvec 2.0.0-alpha.9", + "smallvec 2.0.0-alpha.11", "temp-dir", - "thiserror 2.0.11", + "thiserror 2.0.12", "tokio", "tracing", "tracing-error", @@ -1894,7 +1913,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] @@ -1990,9 +2009,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" +checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" dependencies = [ "adler2", ] @@ -2005,7 +2024,7 @@ checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] @@ -2051,7 +2070,7 @@ checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] @@ -2066,7 +2085,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" dependencies = [ - "smallvec 1.13.2", + "smallvec 1.14.0", ] [[package]] @@ -2101,7 +2120,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", "cfg-if", "libc", "memoffset 0.9.1", @@ -2230,9 +2249,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "nusb" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e1996397b9a2af6390bb9ef0386c429de1a81da246fa7ae31dc922be4b670b" +checksum = "99a726776e551f3ee9b467fe47202f26e64b9bbf715df5443b0904df6f2dcc41" dependencies = [ "atomic-waker", "core-foundation 0.9.4", @@ -2258,9 +2277,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.2" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "option-ext" @@ -2317,7 +2336,7 @@ dependencies = [ "instant", "libc", "redox_syscall 0.2.16", - "smallvec 1.13.2", + "smallvec 1.14.0", "winapi", ] @@ -2329,8 +2348,8 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.8", - "smallvec 1.13.2", + "redox_syscall 0.5.10", + "smallvec 1.14.0", "windows-targets 0.52.6", ] @@ -2348,22 +2367,22 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.8" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e2ec53ad785f4d35dac0adea7f7dc6f1bb277ad84a680c7afefeae05d1f5916" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.8" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] @@ -2380,9 +2399,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "portable-atomic" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" [[package]] name = "portable-atomic-util" @@ -2421,9 +2440,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] @@ -2480,7 +2499,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] @@ -2491,14 +2510,14 @@ checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071" dependencies = [ "proc-macro2", "quote", - "smallvec 1.13.2", + "smallvec 1.14.0", ] [[package]] name = "proc-macro2" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] @@ -2520,8 +2539,8 @@ dependencies = [ "heapless 0.8.0", "postcard", "serde", - "strum", - "thiserror 2.0.11", + "strum 0.27.1", + "thiserror 2.0.12", ] [[package]] @@ -2530,7 +2549,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", "memchr", "unicase", ] @@ -2545,20 +2564,26 @@ dependencies = [ "libc", "once_cell", "raw-cpuid", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "web-sys", "winapi", ] [[package]] name = "quote" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "radiator-bridge" version = "0.1.0" @@ -2587,20 +2612,20 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.5" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ - "libc", "rand_chacha", "rand_core", + "zerocopy", ] [[package]] name = "rand_chacha" -version = "0.3.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", "rand_core", @@ -2608,11 +2633,11 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.4" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom", + "getrandom 0.3.2", ] [[package]] @@ -2621,7 +2646,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", "cassowary", "compact_str", "crossterm", @@ -2630,7 +2655,7 @@ dependencies = [ "itertools 0.13.0", "lru", "paste", - "strum", + "strum 0.26.3", "unicode-segmentation", "unicode-truncate", "unicode-width 0.2.0", @@ -2638,11 +2663,11 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "11.2.0" +version = "11.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0" +checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", ] [[package]] @@ -2662,11 +2687,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", ] [[package]] @@ -2675,11 +2700,22 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom", + "getrandom 0.2.15", "libredox", "thiserror 1.0.69", ] +[[package]] +name = "redox_users" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +dependencies = [ + "getrandom 0.2.15", + "libredox", + "thiserror 2.0.12", +] + [[package]] name = "regex" version = "1.11.1" @@ -2732,12 +2768,11 @@ checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" [[package]] name = "reserve-port" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9838134a2bfaa8e1f40738fcc972ac799de6e0e06b5157acb95fc2b05a0ea283" +checksum = "ba3747658ee2585ecf5607fa9887c92eff61b362ff5253dbf797dfeb73d33d78" dependencies = [ - "lazy_static", - "thiserror 1.0.69", + "thiserror 2.0.12", ] [[package]] @@ -2746,12 +2781,25 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" dependencies = [ - "base64", - "bitflags 2.7.0", + "base64 0.21.7", + "bitflags 2.9.0", "serde", "serde_derive", ] +[[package]] +name = "ron" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63f3aa105dea217ef30d89581b65a4d527a19afc95ef5750be3890e8d3c5b837" +dependencies = [ + "base64 0.22.1", + "bitflags 2.9.0", + "serde", + "serde_derive", + "unicode-ident", +] + [[package]] name = "rpc" version = "0.1.0" @@ -2760,7 +2808,7 @@ dependencies = [ "futures", "governor", "serde", - "thiserror 2.0.11", + "thiserror 2.0.12", "tokio", "tokio-serde", "tokio-util", @@ -2769,9 +2817,9 @@ dependencies = [ [[package]] name = "rstest" -version = "0.24.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e905296805ab93e13c1ec3a03f4b6c4f35e9498a3d5fa96dc626d22c03cd89" +checksum = "6fc39292f8613e913f7df8fa892b8944ceb47c247b78e1b1ae2f09e019be789d" dependencies = [ "futures-timer", "futures-util", @@ -2781,9 +2829,9 @@ dependencies = [ [[package]] name = "rstest_macros" -version = "0.24.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef0053bbffce09062bee4bcc499b0fbe7a57b879f1efe088d6d8d4c7adcdef9b" +checksum = "1f168d99749d307be9de54d23fd226628d99768225ef08f6ffb52e0182a27746" dependencies = [ "cfg-if", "glob", @@ -2793,7 +2841,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.96", + "syn 2.0.100", "unicode-ident", ] @@ -2828,11 +2876,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.43" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", "errno", "libc", "linux-raw-sys", @@ -2841,9 +2889,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" [[package]] name = "rustyline" @@ -2862,7 +2910,7 @@ dependencies = [ "nix 0.23.2", "radix_trie", "scopeguard", - "smallvec 1.13.2", + "smallvec 1.14.0", "unicode-segmentation", "unicode-width 0.1.14", "utf8parse", @@ -2871,9 +2919,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "safe_arch" @@ -2898,35 +2946,35 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.24" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" -version = "1.0.217" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] name = "serde_json" -version = "1.0.135" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", @@ -2949,11 +2997,11 @@ dependencies = [ [[package]] name = "serialport" -version = "4.6.1" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "779e2977f0cc2ff39708fef48f96f3768ac8ddd8c6caaaab82e83bd240ef99b2" +checksum = "2daa7abb9b965493e3c8f4184c6f46435484ff2538a332b886788cf6768b927b" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", "cfg-if", "core-foundation 0.10.0", "core-foundation-sys", @@ -3070,15 +3118,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.2" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" [[package]] name = "smallvec" -version = "2.0.0-alpha.9" +version = "2.0.0-alpha.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e22442b16a0c1bfae679ffed8ec5e160ae2aa8495cea891f0d2ff7b84fe5c4c" +checksum = "87b96efa4bd6bdd2ff0c6615cc36fc4970cbae63cfd46ddff5cee35a1b4df570" [[package]] name = "socket2" @@ -3096,7 +3144,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2800c129338c77998c1dcb6d4200447e018beb7d29959eb104cba2d45f83c1a" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.9.0", "libc", "nix 0.26.4", ] @@ -3139,9 +3187,9 @@ checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" [[package]] name = "strip-ansi-escapes" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ff8ef943b384c414f54aefa961dd2bd853add74ec75e7ac74cf91dba62bcfa" +checksum = "2a8f8038e7e7969abb3f1b7c2a811225e9296da208539e0f79c5251d6cac0025" dependencies = [ "vte", ] @@ -3158,7 +3206,16 @@ version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ - "strum_macros", + "strum_macros 0.26.4", +] + +[[package]] +name = "strum" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" +dependencies = [ + "strum_macros 0.27.1", ] [[package]] @@ -3171,7 +3228,20 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.96", + "syn 2.0.100", +] + +[[package]] +name = "strum_macros" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.100", ] [[package]] @@ -3193,9 +3263,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.96" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -3210,7 +3280,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] @@ -3239,11 +3309,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ - "thiserror-impl 2.0.11", + "thiserror-impl 2.0.12", ] [[package]] @@ -3254,18 +3324,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] name = "thiserror-impl" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] @@ -3290,9 +3360,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.43.0" +version = "1.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" +checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" dependencies = [ "backtrace", "bytes", @@ -3314,7 +3384,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] @@ -3323,7 +3393,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "caf600e7036b17782571dd44fa0a5cea3c82f60db5137f774a325a76a0d6852b" dependencies = [ - "bincode", + "bincode 1.3.3", "bytes", "educe", "futures-core", @@ -3334,9 +3404,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" +checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" dependencies = [ "bytes", "futures-core", @@ -3381,7 +3451,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] @@ -3447,7 +3517,7 @@ dependencies = [ "once_cell", "regex", "sharded-slab", - "smallvec 1.13.2", + "smallvec 1.14.0", "thread_local", "tracing", "tracing-core", @@ -3465,9 +3535,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "ui" @@ -3489,7 +3559,7 @@ dependencies = [ "protocol", "ratatui", "strip-ansi-escapes", - "thiserror 2.0.11", + "thiserror 2.0.12", "tokio", "tracing", "tracing-error", @@ -3514,9 +3584,9 @@ checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-segmentation" @@ -3553,6 +3623,12 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" +[[package]] +name = "unty" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" + [[package]] name = "url" version = "2.5.4" @@ -3579,17 +3655,7 @@ dependencies = [ "tracing", "tracing-error", "tracing-subscriber", - "users", -] - -[[package]] -name = "users" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" -dependencies = [ - "libc", - "log", + "uzers", ] [[package]] @@ -3612,18 +3678,28 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.11.1" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b913a3b5fe84142e269d63cc62b64319ccaf89b748fc31fe025177f767a756c4" +checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" dependencies = [ "serde", ] +[[package]] +name = "uzers" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4df81ff504e7d82ad53e95ed1ad5b72103c11253f39238bcc0235b90768a97dd" +dependencies = [ + "libc", + "log", +] + [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "version_check" @@ -3633,35 +3709,27 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "vte" -version = "0.11.1" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197" +checksum = "231fdcd7ef3037e8330d8e17e61011a2c244126acc0a982f4040ac3f9f0bc077" dependencies = [ - "utf8parse", - "vte_generate_state_changes", -] - -[[package]] -name = "vte_generate_state_changes" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" -dependencies = [ - "proc-macro2", - "quote", + "memchr", ] [[package]] -name = "waker-fn" -version = "1.2.0" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] [[package]] name = "wasm-bindgen" @@ -3685,7 +3753,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", "wasm-bindgen-shared", ] @@ -3720,7 +3788,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3952,6 +4020,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.0", +] + [[package]] name = "write16" version = "1.0.0" @@ -3984,49 +4061,48 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", "synstructure", ] [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" dependencies = [ - "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] name = "zerofrom" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", "synstructure", ] @@ -4049,7 +4125,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.100", ] [[package]] @@ -4064,8 +4140,8 @@ dependencies = [ "regex", "rumqttc", "serde_json", - "strum", - "thiserror 2.0.11", + "strum 0.27.1", + "thiserror 2.0.12", "tokio", "tracing", ] diff --git a/Cargo.toml b/Cargo.toml index e8e0a51d..18c51476 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,18 +17,25 @@ byteseries = { git = "https://github.com/dvdsk/byteseries", rev="a9da72e9585e5f5 serde = { version = "1", features = ["derive"], default-features = false } tokio = { version = "1.38", features = ["rt-multi-thread"] } +tokio-util = { version = "0.7.13", features = ["codec"] } itertools = { version = "0.14" } -gethostname = "0.5.0" +bincode = { version = "2.0", default-features = false, features = ["serde", "std"] } +gethostname = "0.5" governor = "0.8" color-eyre = "0.6.3" tracing = "0.1.40" -tracing-error = "0.2.0" +tracing-error = "0.2" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } futures = "0.3.31" futures-concurrency = "7.6.2" jiff = "0.1" clap = { version = "4", features = ["derive"]} +rand = "0.9" +smallvec = { version = "2.0.0-alpha.11" } +strum = { version = "0.27", features = ["derive"] } +ron = "0.9" thiserror = "2" +reserve-port = "2.2.0" [workspace.package] rust-version = "1.82" diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 5da7692f..26f3a671 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -16,7 +16,7 @@ tokio = { workspace = true, features = ["full"] } serde.workspace = true serde_yaml = "0.9" -bincode = "1.3" +bincode.workspace = true thiserror.workspace = true @@ -28,14 +28,14 @@ byteorder = "1.4" sled = "0.34" mpd = "0.1" -rand = "0.8" +rand.workspace = true futures-util = "0.3.30" tracing = {workspace = true} logger.workspace = true clap = { workspace = true } futures-concurrency = { workspace = true } -strum = { version = "0.26.2", default-features = false, features = ["derive"] } +strum.workspace = true dbstruct = { git = "https://github.com/dvdsk/dbstruct" } color-eyre.workspace = true mpdrs = "0.1.0" diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs index 1e73e48d..a456840b 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs @@ -7,7 +7,7 @@ use jiff::civil::Time; use mpdrs::error::Error; use mpdrs::status::State; use mpdrs::Playlist; -use rand::seq::SliceRandom; +use rand::seq::IndexedRandom; use tracing::{debug, info, instrument}; use db::Db; @@ -663,7 +663,7 @@ impl AudioController { tokio::time::sleep(Duration::from_millis(100)).await; let to_add = { - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); slow_songs .choose_multiple(&mut rng, 1) diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index 31787a51..173c3985 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -23,7 +23,7 @@ tokio = { workspace = true, features = ["rt", "macros", "net", "sync", "io-util" thiserror.workspace = true futures.workspace = true tokio-serde = { version = "0.9.0", features = ["bincode"] } -tokio-util = { version = "0.7.11", features = ["codec"] } +tokio-util.workspace = true serde.workspace = true futures-concurrency = { workspace = true } slotmap = "1.0.7" diff --git a/crates/data-store/Cargo.toml b/crates/data-store/Cargo.toml index 393fe6f7..69fd6223 100644 --- a/crates/data-store/Cargo.toml +++ b/crates/data-store/Cargo.toml @@ -31,15 +31,15 @@ futures-concurrency = { workspace = true } serde.workspace = true thiserror = { workspace = true } futures.workspace = true -smallvec = "2.0.0-alpha.6" +smallvec.workspace = true num = "0.4.3" -ron = "0.8.1" +ron.workspace = true indicatif = "0.17.9" itertools.workspace = true -rstest = "0.24.0" +rstest = "0.25" [dev-dependencies] -futures-concurrency = { workspace = true } +futures-concurrency.workspace = true nucleo-matcher = "0.3.1" -reserve-port = "2.0.1" +reserve-port.workspace = true temp-dir = "0.1.13" diff --git a/crates/log-store/Cargo.toml b/crates/log-store/Cargo.toml index 1aac68f9..c4de9fea 100644 --- a/crates/log-store/Cargo.toml +++ b/crates/log-store/Cargo.toml @@ -28,10 +28,10 @@ rpc = { workspace = true } tokio = { workspace = true, features = ["fs", "net", "rt-multi-thread", "sync"] } futures-concurrency = { workspace = true } serde.workspace = true -bincode = "1.3.3" -thiserror = { workspace = true } +bincode.workspace = true +thiserror.workspace = true futures.workspace = true -smallvec = "2.0.0-alpha.6" +smallvec.workspace = true hdrhistogram = "7.5.4" derivative = "2.2.0" @@ -39,5 +39,5 @@ derivative = "2.2.0" futures-concurrency = { workspace = true } heapless = "0.8.0" nucleo-matcher = "0.3.1" -reserve-port = "2.0.1" +reserve-port.workspace = true temp-dir = "0.1.13" diff --git a/crates/log-store/src/server/db/log.rs b/crates/log-store/src/server/db/log.rs index 5c612d92..f768f7d4 100644 --- a/crates/log-store/src/server/db/log.rs +++ b/crates/log-store/src/server/db/log.rs @@ -49,8 +49,11 @@ impl CurrentError { let value = if buf.is_empty() { None } else { - match bincode::deserialize(&buf) { - Ok(value) => Some(value), + match bincode::serde::decode_from_slice( + &buf, + bincode::config::standard(), + ) { + Ok((value, _)) => Some(value), Err(err) => { tracing::debug!("Data was: {buf:?}"); warn!( @@ -78,8 +81,9 @@ impl CurrentError { fn set(&mut self, report: protocol::Error) -> Result<()> { let value = (jiff::Timestamp::now(), report); - let bytes = bincode::serialize(&value) - .wrap_err("could not serialize current error")?; + let bytes = + bincode::serde::encode_to_vec(&value, bincode::config::standard()) + .wrap_err("could not serialize current error")?; self.file .set_len(0) .wrap_err("Could not clear file prior to backing up value")?; @@ -163,8 +167,11 @@ impl Log { end: jiff::Timestamp::now(), error: report.clone(), }; - let line = bincode::serialize(&line) - .wrap_err("Could not serialize ErrorEvent")?; + let line = bincode::serde::encode_to_vec( + &line, + bincode::config::standard(), + ) + .wrap_err("Could not serialize ErrorEvent")?; let payload_size = protocol::Error::max_size(); let line: Vec<_> = line .into_iter() @@ -275,8 +282,9 @@ impl byteseries::Decoder for Decoder { type Item = StoredErrorEvent; fn decode_payload(&mut self, payload: &[u8]) -> Self::Item { - bincode::deserialize(payload) + bincode::serde::decode_from_slice(payload, bincode::config::standard()) .expect("if its successfully serialized it should deserialize") + .0 } } diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index 3d968c31..abdd7a24 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -12,7 +12,7 @@ authors.workspace = true serde.workspace = true postcard = { version = "1.0.10", features = ["experimental-derive", "use-defmt"] } heapless = { version = "0.8.0", features = ["serde", "defmt-03"] } -strum = { version = "0.26.2", default-features = false, features = ["derive"] } +strum = { workspace = true, default-features = false, features = ["derive"] } thiserror = { workspace = true, optional = true } defmt = "0.3.6" diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index d8834401..4e1f9876 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -11,7 +11,7 @@ color-eyre.workspace = true futures.workspace = true governor.workspace = true tokio = { workspace = true, features = ["net", "rt", "sync", "time"] } -tokio-util = { version = "0.7.11", features = ["codec"] } +tokio-util.workspace = true tracing.workspace = true serde.workspace = true diff --git a/crates/text-widget/Cargo.toml b/crates/text-widget/Cargo.toml index f44a7d82..681a6d74 100644 --- a/crates/text-widget/Cargo.toml +++ b/crates/text-widget/Cargo.toml @@ -21,7 +21,7 @@ logger.workspace = true tracing.workspace = true tracing-error.workspace = true tracing-subscriber.workspace = true -dirs = "5.0.1" +dirs = "6.0" serde.workspace = true promptly = "0.3.1" -ron = "0.8.1" +ron.workspace = true diff --git a/crates/usb-bridge/src/usb/device.rs b/crates/usb-bridge/src/usb/device.rs index 4aa70c7c..81a27098 100644 --- a/crates/usb-bridge/src/usb/device.rs +++ b/crates/usb-bridge/src/usb/device.rs @@ -64,7 +64,7 @@ pub(crate) fn get_usb_device( "Add a .rules file in /etc/udev/rules.d with line: \n\ ATTRS{{serial}}==\"{serial_number}\", MODE=\"660\", GROUP=\"{}\", TAG+=\"uaccess\"\n\ Then run: sudo udevadm control --reload && sudo udevadm trigger", - users::get_current_groupname() + uzers::get_current_groupname() .expect("process should always run as a group") .to_string_lossy() ) diff --git a/crates/zigbee-bridge/Cargo.toml b/crates/zigbee-bridge/Cargo.toml index d85ae71e..82fd9263 100644 --- a/crates/zigbee-bridge/Cargo.toml +++ b/crates/zigbee-bridge/Cargo.toml @@ -16,10 +16,10 @@ serde_json = "1.0.132" thiserror.workspace = true tokio = { workspace = true, features = ["sync"] } tracing = { workspace = true } -strum = { version = "0.26.3", features = ["derive"] } +strum.workspace = true color-eyre.workspace = true regex = "1.11.1" -rand = "0.8.5" +rand.workspace = true [dev-dependencies] logger.workspace = true diff --git a/crates/zigbee-bridge/src/cached_bridge.rs b/crates/zigbee-bridge/src/cached_bridge.rs index 3ff89fda..13fa67fb 100644 --- a/crates/zigbee-bridge/src/cached_bridge.rs +++ b/crates/zigbee-bridge/src/cached_bridge.rs @@ -27,7 +27,7 @@ pub(super) async fn run( reading_callback: impl Fn(protocol::Reading), ) -> ! { // The id string must be random or subscribe does not work - let id = name + " " + &rand::random::().to_string(); + let id = name + " " + &rand::random::().to_string(); let mut options = MqttOptions::new(id, mqtt_ip.to_string(), MQTT_PORT); // Set max mqtt packet size to 4kB options.set_max_packet_size(Some(8192)); From d26755f6b9b9840bea15582b0dda53f8fa500e1e Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 31 Mar 2025 17:31:34 +0200 Subject: [PATCH 630/687] Remove confusing defaults for audio modes --- .../src/controller/rooms/small_bedroom.rs | 2 +- .../rooms/small_bedroom/audiocontrol.rs | 33 +++++++++---------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 3e2cb069..cd6b7e84 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -45,7 +45,7 @@ pub async fn run( let mut next_update = Instant::now() + UPDATE_INTERVAL; let wakeup_job = - Job::every_day_at(8, 47, Event::WakeupSB, Some(WAKEUP_EXPIRATION)); + Job::every_day_at(10, 32, Event::WakeupSB, Some(WAKEUP_EXPIRATION)); let res = system .system diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs index a456840b..3d913d31 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs @@ -34,19 +34,6 @@ struct Settings { save_playlist: bool, } -impl Default for Settings { - fn default() -> Self { - Self { - repeat: false, - random: false, - single: false, - consume: false, - volume: 90, - save_playlist: false, - } - } -} - #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize, Clone)] pub enum AudioMode { Music, @@ -79,17 +66,29 @@ impl AudioMode { fn settings(&self) -> Settings { use AudioMode::*; match self { - Music | Singing => Settings::default(), + Music | Singing => Settings { + repeat: false, + random: false, + single: false, + consume: false, + volume: 70, + save_playlist: false, + }, Podcast => Settings { + repeat: false, + random: false, + single: false, consume: true, - save_playlist: true, volume: 100, - ..Settings::default() + save_playlist: true, }, Meditation => Settings { + repeat: false, + random: false, + consume: false, single: true, volume: 100, - ..Settings::default() + save_playlist: false, }, } } From aff76dc65c1de4e463a6f0883aab7977e09125db Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 3 Apr 2025 15:51:46 +0200 Subject: [PATCH 631/687] Make meditation mode dependent on time --- crates/brain/src/controller/rooms/small_bedroom.rs | 13 +++++++++---- .../controller/rooms/small_bedroom/audiocontrol.rs | 14 +++++++------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index cd6b7e84..cc6beda1 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -45,7 +45,7 @@ pub async fn run( let mut next_update = Instant::now() + UPDATE_INTERVAL; let wakeup_job = - Job::every_day_at(10, 32, Event::WakeupSB, Some(WAKEUP_EXPIRATION)); + Job::every_day_at(9, 30, Event::WakeupSB, Some(WAKEUP_EXPIRATION)); let res = system .system @@ -175,9 +175,14 @@ async fn handle_audio_button(room: &mut Room, button_event: RelevantEvent) { audio.play(ForceRewind::No) } (_, E::PortableButton(P::PlayPause)) => { - audio - .go_to_mode_playlist(&A::Meditation, "meditation_yoga-nidra") - .await; + if AudioController::is_meditation_time() { + audio + .go_to_mode_playlist( + &A::Meditation, + "meditation_yoga-nidra", + ) + .await; + } audio.toggle_playback(); } diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs index 3d913d31..fb82c2b6 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs @@ -8,7 +8,7 @@ use mpdrs::error::Error; use mpdrs::status::State; use mpdrs::Playlist; use rand::seq::IndexedRandom; -use tracing::{debug, info, instrument}; +use tracing::{debug, info, instrument, trace}; use db::Db; use mpdinterface::MpdInterface; @@ -422,8 +422,8 @@ impl AudioController { } /// Meditation mode is only enabled at night - fn is_meditation_time() -> bool { - const START_HOUR: i8 = 21; + pub fn is_meditation_time() -> bool { + const START_HOUR: i8 = 22; const START_MIN: i8 = 30; const END_HOUR: i8 = 9; const END_MIN: i8 = 0; @@ -463,10 +463,10 @@ impl AudioController { self.mode.next(); info!("Switching to mode {:?}", self.mode); - // if self.mode == AudioMode::Meditation && !Self::is_meditation_time() { - // self.mode.next(); - // info!("Skipping meditation"); - // } + if self.mode == AudioMode::Meditation && !Self::is_meditation_time() { + self.mode.next(); + trace!("Skipping meditation"); + } // Check if a playlist is stored in the db, and still exists let new_playlist_name = self.db.fetch_playlist_name(&self.mode); From efc36f5a7a860428dfefeef045beb960a9c3a58c Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 3 Apr 2025 15:55:36 +0200 Subject: [PATCH 632/687] Add kitchen to small bedroom override button --- crates/brain/src/controller/rooms/kitchen.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index b64f903b..efd6b680 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -17,6 +17,7 @@ enum State { Sleep, Morning, Daylight, + Override, } trait RecvFiltered { @@ -44,6 +45,7 @@ impl RecvFiltered for broadcast::Receiver { enum RelevantEvent { Sleep, Daylight, + Override, } fn filter(event: Event) -> Option { @@ -54,6 +56,9 @@ fn filter(event: Event) -> Option { Event::StateChangeSB(small_bedroom::State::Daylight) => { Some(RelevantEvent::Daylight) } + Event::StateChangeSB(small_bedroom::State::Override) => { + Some(RelevantEvent::Override) + } _ => None, } } @@ -92,6 +97,10 @@ pub async fn run( system.all_lamps_but_one_on("kitchen:hallway").await; } } + Res::Event(RelevantEvent::Override) => { + state = State::Override; + system.all_lamps_ct(2000, 1.0).await; + } Res::ShouldUpdate if state == State::Daylight || (state == State::Morning && is_late_morning()) => From 6619329352fa3d7377c0a43d16a901f408438b7b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 7 Apr 2025 14:55:24 +0200 Subject: [PATCH 633/687] remove error reporting for parsing (see comment) --- crates/zigbee-bridge/src/cached_bridge/poll.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/crates/zigbee-bridge/src/cached_bridge/poll.rs b/crates/zigbee-bridge/src/cached_bridge/poll.rs index 59df0080..ea43c628 100644 --- a/crates/zigbee-bridge/src/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/cached_bridge/poll.rs @@ -32,7 +32,15 @@ pub(super) async fn poll_mqtt( let message = match parse_message(message) { Ok(message) => message, Err(err) => { - warn!("ZB error parsing mqtt message: {err:?}"); + // zigbee2mqtt is quite fragile and frequently sends incorrect + // json. It seems to recover directly after though. + // + // The plan is to migrate away from zigbee2mqtt in the future to a + // custom build solution (because of the mentioned fragility). + // + // Until then this (zigbee bridge) is in maintenance only + // mode. For that reason we ignore any parsing error. + trace!("ZB error parsing mqtt message: {err:?}"); continue; } }; From 6573bab8ddb9c23d9819588a950bba1a1e909c6b Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 10 Apr 2025 18:10:47 +0200 Subject: [PATCH 634/687] Add noise to alarm to turn on speaker --- .../src/controller/rooms/small_bedroom/audiocontrol.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs index fb82c2b6..73cf4295 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs @@ -4,9 +4,9 @@ use std::fmt; use std::time::Duration; use jiff::civil::Time; -use mpdrs::error::Error; use mpdrs::status::State; use mpdrs::Playlist; +use mpdrs::{error::Error, Song}; use rand::seq::IndexedRandom; use tracing::{debug, info, instrument, trace}; @@ -669,6 +669,13 @@ impl AudioController { .chain(normal_songs.choose_multiple(&mut rng, 30)) }; + self.client.pl_push( + pl_name, + &Song { + file: "noise.ogg".to_string(), + ..Default::default() + }, + ).unwrap(); for song in to_add { self.client.pl_push(pl_name, song).unwrap(); tokio::time::sleep(Duration::from_millis(10)).await; From 4fb1c6d60cda5398143eee89b52f6a4875291f9f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 11 Apr 2025 15:16:54 +0200 Subject: [PATCH 635/687] comments out button presses that are eroneously triggerd --- Cargo.toml | 2 +- crates/protocol/Cargo.toml | 2 +- nodes/embassy/Cargo.lock | 25 ++++++++-- nodes/embassy/Cargo.toml | 40 ++++++++-------- nodes/embassy/bed-lb/src/sensors/fast.rs | 61 +++++++++++------------- 5 files changed, 71 insertions(+), 59 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 18c51476..e9073a8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ jiff = "0.1" clap = { version = "4", features = ["derive"]} rand = "0.9" smallvec = { version = "2.0.0-alpha.11" } -strum = { version = "0.27", features = ["derive"] } +strum = { version = "0.27", default-features = false, features = ["derive"] } ron = "0.9" thiserror = "2" reserve-port = "2.2.0" diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index abdd7a24..d410dbeb 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -12,7 +12,7 @@ authors.workspace = true serde.workspace = true postcard = { version = "1.0.10", features = ["experimental-derive", "use-defmt"] } heapless = { version = "0.8.0", features = ["serde", "defmt-03"] } -strum = { workspace = true, default-features = false, features = ["derive"] } +strum.workspace = true thiserror = { workspace = true, optional = true } defmt = "0.3.6" diff --git a/nodes/embassy/Cargo.lock b/nodes/embassy/Cargo.lock index b4adaffe..73272af0 100644 --- a/nodes/embassy/Cargo.lock +++ b/nodes/embassy/Cargo.lock @@ -292,6 +292,7 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" version = "0.3.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", "embassy-futures", @@ -309,6 +310,7 @@ dependencies = [ [[package]] name = "embassy-executor" version = "0.7.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "cortex-m", "critical-section", @@ -320,6 +322,7 @@ dependencies = [ [[package]] name = "embassy-executor-macros" version = "0.6.2" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "darling", "proc-macro2", @@ -330,10 +333,12 @@ dependencies = [ [[package]] name = "embassy-futures" version = "0.1.1" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" [[package]] name = "embassy-hal-internal" version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "cortex-m", "critical-section", @@ -344,6 +349,7 @@ dependencies = [ [[package]] name = "embassy-net" version = "0.7.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", "document-features", @@ -360,6 +366,7 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", ] @@ -367,6 +374,7 @@ dependencies = [ [[package]] name = "embassy-net-driver-channel" version = "0.3.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "embassy-futures", "embassy-net-driver", @@ -376,6 +384,7 @@ dependencies = [ [[package]] name = "embassy-net-wiznet" version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", "embassy-futures", @@ -388,6 +397,7 @@ dependencies = [ [[package]] name = "embassy-stm32" version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "aligned", "bit_field", @@ -434,6 +444,7 @@ dependencies = [ [[package]] name = "embassy-sync" version = "0.6.2" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "cfg-if", "critical-section", @@ -447,6 +458,7 @@ dependencies = [ [[package]] name = "embassy-time" version = "0.4.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "cfg-if", "critical-section", @@ -462,6 +474,7 @@ dependencies = [ [[package]] name = "embassy-time-driver" version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "document-features", ] @@ -469,6 +482,7 @@ dependencies = [ [[package]] name = "embassy-time-queue-utils" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "embassy-executor", "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -477,6 +491,7 @@ dependencies = [ [[package]] name = "embassy-usb" version = "0.4.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", "embassy-futures", @@ -491,6 +506,7 @@ dependencies = [ [[package]] name = "embassy-usb-driver" version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "defmt", ] @@ -498,6 +514,7 @@ dependencies = [ [[package]] name = "embassy-usb-synopsys-otg" version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" dependencies = [ "critical-section", "defmt", @@ -1242,18 +1259,18 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.26.3" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.26.4" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" dependencies = [ "heck", "proc-macro2", diff --git a/nodes/embassy/Cargo.toml b/nodes/embassy/Cargo.toml index 7204c052..624a6dc1 100644 --- a/nodes/embassy/Cargo.toml +++ b/nodes/embassy/Cargo.toml @@ -34,27 +34,27 @@ defmt-rtt = "0.4" panic-probe = { version = "0.3", features = ["print-defmt"] } [patch.crates-io] -# embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -# embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -# embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -# embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -# embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -# embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -# embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -# embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -# embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -# embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-stm32 = {path = "/home/david/Documents/embassy/embassy-stm32" } -embassy-net = {path = "/home/david/Documents/embassy/embassy-net" } -embassy-net-wiznet = {path = "/home/david/Documents/embassy/embassy-net-wiznet" } -embassy-sync = {path = "/home/david/Documents/embassy/embassy-sync" } -embassy-executor = {path = "/home/david/Documents/embassy/embassy-executor" } -embassy-embedded-hal = {path = "/home/david/Documents/embassy/embassy-embedded-hal" } -embassy-futures = {path = "/home/david/Documents/embassy/embassy-futures" } -embassy-time = {path = "/home/david/Documents/embassy/embassy-time" } -embassy-time-driver = {path = "/home/david/Documents/embassy/embassy-time-driver" } -embassy-usb = {path = "/home/david/Documents/embassy/embassy-usb" } +# embassy-stm32 = {path = "/home/david/Documents/embassy/embassy-stm32" } +# embassy-net = {path = "/home/david/Documents/embassy/embassy-net" } +# embassy-net-wiznet = {path = "/home/david/Documents/embassy/embassy-net-wiznet" } +# embassy-sync = {path = "/home/david/Documents/embassy/embassy-sync" } +# embassy-executor = {path = "/home/david/Documents/embassy/embassy-executor" } +# embassy-embedded-hal = {path = "/home/david/Documents/embassy/embassy-embedded-hal" } +# embassy-futures = {path = "/home/david/Documents/embassy/embassy-futures" } +# embassy-time = {path = "/home/david/Documents/embassy/embassy-time" } +# embassy-time-driver = {path = "/home/david/Documents/embassy/embassy-time-driver" } +# embassy-usb = {path = "/home/david/Documents/embassy/embassy-usb" } [workspace.package] rust-version = "1.78" diff --git a/nodes/embassy/bed-lb/src/sensors/fast.rs b/nodes/embassy/bed-lb/src/sensors/fast.rs index 865f6fa3..bc7eb348 100644 --- a/nodes/embassy/bed-lb/src/sensors/fast.rs +++ b/nodes/embassy/bed-lb/src/sensors/fast.rs @@ -21,10 +21,7 @@ fn sig_weight_diff(old: u32, new: u32) -> bool { diff > 15 } -async fn report_lux( - mut max44: Max44Driver<'_>, - rgb_led: rgb_led::LedHandle, -) { +async fn report_lux(mut max44: Max44Driver<'_>, rgb_led: rgb_led::LedHandle) { const MAX_INTERVAL: Duration = Duration::from_secs(5); let mut prev_lux = f32::MAX; @@ -123,37 +120,35 @@ async fn watch_button( ) { use sensors::{errors::PressTooLong, errors::SensorError, Error}; - let mut went_high_at: Option = None; loop { - if let Some(went_high_at) = went_high_at.take() { - input.wait_for_low().await; - let press = went_high_at.elapsed(); - let Ok(press) = press.as_millis().try_into() else { - let event_for_printing = (event)(protocol::button::Press(0)); - let name = event_for_printing.variant_name(); - PUBLISH.queue_error(Error::Running(SensorError::Button( - PressTooLong { button: name }, - ))); - continue; - }; - let event = (event)(protocol::button::Press(press)); - PUBLISH.send_p2(Reading::Button(event)); - } else { - input.wait_for_high().await; - Timer::after(Duration::from_millis(20)).await; - if input.is_low() { - continue; - } - Timer::after(Duration::from_millis(20)).await; - if input.is_low() { - continue; - } - Timer::after(Duration::from_millis(10)).await; - if input.is_high() { - went_high_at = Some(Instant::now()); - } - } + Timer::after(Duration::from_secs(200)).await; } + // let mut went_high_at: Option = None; + // loop { + // if let Some(went_high_at) = went_high_at.take() { + // input.wait_for_low().await; + // let press = went_high_at.elapsed(); + // let Ok(press) = press.as_millis().try_into() else { + // let event_for_printing = (event)(protocol::button::Press(0)); + // let name = event_for_printing.variant_name(); + // PUBLISH.queue_error(Error::Running(SensorError::Button( + // PressTooLong { button: name }, + // ))); + // continue; + // }; + // let event = (event)(protocol::button::Press(press)); + // PUBLISH.send_p2(Reading::Button(event)); + // } else { + // input.wait_for_high().await; + // let now = Instant::now(); + // Timer::after(Duration::from_millis(80)).await; + // if input.is_low() { + // continue; + // } else { + // went_high_at = Some(now); + // } + // } + // } } pub struct ButtonInputs { From 31e3101641b7e90369711845e65540892ad8bbbb Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 11 Apr 2025 15:17:21 +0200 Subject: [PATCH 636/687] some work on esp32 for air box --- nodes/esp32/airbox/.cargo/config.toml | 7 +-- nodes/esp32/airbox/Cargo.lock | 32 ++++++++----- nodes/esp32/airbox/Cargo.toml | 10 ++-- nodes/esp32/airbox/src/main.rs | 66 +++++++++++++-------------- 4 files changed, 62 insertions(+), 53 deletions(-) diff --git a/nodes/esp32/airbox/.cargo/config.toml b/nodes/esp32/airbox/.cargo/config.toml index 624f450e..0c352f5c 100644 --- a/nodes/esp32/airbox/.cargo/config.toml +++ b/nodes/esp32/airbox/.cargo/config.toml @@ -1,5 +1,6 @@ -[target.riscv32imc-unknown-none-elf] -runner = "espflash flash --monitor --chip esp32c3 --log-format defmt" +[target.riscv32imac-unknown-none-elf] +# runner = "espflash flash --monitor --chip esp32c3 --log-format defmt" +runner = "espflash flash --monitor --chip esp32c6 --log-format defmt" [env] DEFMT_LOG="info" @@ -12,7 +13,7 @@ rustflags = [ "-C", "force-frame-pointers", ] -target = "riscv32imc-unknown-none-elf" +target = "riscv32imac-unknown-none-elf" [unstable] build-std = ["alloc", "core"] diff --git a/nodes/esp32/airbox/Cargo.lock b/nodes/esp32/airbox/Cargo.lock index d42ac8dc..e57bbad6 100644 --- a/nodes/esp32/airbox/Cargo.lock +++ b/nodes/esp32/airbox/Cargo.lock @@ -157,9 +157,9 @@ checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "darling" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ "darling_core", "darling_macro", @@ -167,9 +167,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", @@ -181,9 +181,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", @@ -224,9 +224,9 @@ dependencies = [ [[package]] name = "delegate" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297806318ef30ad066b15792a8372858020ae3ca2e414ee6c2133b1eb9e9e945" +checksum = "b9b6483c2bbed26f97861cf57651d4f2b731964a28cd2257f934a4b452480d21" dependencies = [ "proc-macro2", "quote", @@ -626,6 +626,7 @@ dependencies = [ "darling", "document-features", "litrs", + "object", "proc-macro-crate", "proc-macro-error2", "proc-macro2", @@ -981,9 +982,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "managed" @@ -1041,6 +1042,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + [[package]] name = "paste" version = "1.0.15" @@ -1158,7 +1168,7 @@ dependencies = [ "heapless 0.8.0", "postcard", "serde", - "strum 0.26.3", + "strum 0.27.1", ] [[package]] diff --git a/nodes/esp32/airbox/Cargo.toml b/nodes/esp32/airbox/Cargo.toml index 7610df6a..46d22d6c 100644 --- a/nodes/esp32/airbox/Cargo.toml +++ b/nodes/esp32/airbox/Cargo.toml @@ -17,16 +17,16 @@ embedded-io-async = "0.6.1" esp-alloc = "0.7.0" esp-backtrace = { version = "0.15.1", features = [ "defmt", - "esp32c3", + "esp32c6", "exception-handler", "panic-handler", ] } esp-hal = { version = "1.0.0-beta.0", features = [ "defmt", - "esp32c3", + "esp32c6", "unstable", ] } -esp-println = { version = "0.13.0", features = ["defmt-espflash", "esp32c3"] } +esp-println = { version = "0.13.0", features = ["defmt-espflash", "esp32c6", "critical-section"] } smoltcp = { version = "0.12.0", default-features = false, features = [ "medium-ethernet", "multicast", @@ -48,12 +48,12 @@ embassy-executor = { version = "0.7.0", features = [ embassy-time = { version = "0.4.0", features = ["generic-queue-8"] } embassy-sync = { version = "0.6.2" } embassy-futures = { version = "0.1.1" } -esp-hal-embassy = { version = "0.7.0", features = ["esp32c3"] } +esp-hal-embassy = { version = "0.7.0", features = ["esp32c6"] } esp-wifi = { version = "0.13.0", features = [ "builtin-scheduler", "defmt", "esp-alloc", - "esp32c3", + "esp32c6", "wifi", ] } heapless = { version = "0.8.0", default-features = false } diff --git a/nodes/esp32/airbox/src/main.rs b/nodes/esp32/airbox/src/main.rs index 51e38f13..59bb0533 100644 --- a/nodes/esp32/airbox/src/main.rs +++ b/nodes/esp32/airbox/src/main.rs @@ -3,7 +3,7 @@ use core::net::Ipv4Addr; -use embassy_futures::join::{self, join3}; +use embassy_futures::join::join3; use embassy_net::{Ipv4Cidr, StackResources}; use esp_hal::clock::CpuClock; use esp_hal::rng::Rng; @@ -57,49 +57,47 @@ async fn main(spawner: Spawner) { esp_alloc::heap_allocator!(size: 72 * 1024); - // let timg0 = TimerGroup::new(peripherals.TIMG0); - // let mut rng = Rng::new(peripherals.RNG); + let timg0 = TimerGroup::new(peripherals.TIMG0); + let mut rng = Rng::new(peripherals.RNG); - // let esp_wifi_ctrl = &*mk_static!( - // EspWifiController<'static>, - // esp_wifi::init(timg0.timer0, rng, peripherals.RADIO_CLK).unwrap() - // ); + let esp_wifi_ctrl = &*mk_static!( + EspWifiController<'static>, + esp_wifi::init(timg0.timer0, rng, peripherals.RADIO_CLK).unwrap() + ); - // let (controller, interfaces) = - // esp_wifi::wifi::new(esp_wifi_ctrl, peripherals.WIFI).unwrap(); - // let wifi_interface = interfaces.sta; + let (controller, interfaces) = + esp_wifi::wifi::new(esp_wifi_ctrl, peripherals.WIFI).unwrap(); + let wifi_interface = interfaces.sta; let systimer = SystemTimer::new(peripherals.SYSTIMER); esp_hal_embassy::init(systimer.alarm0); - // let config = - // embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { - // address: Ipv4Cidr::new(Ipv4Addr::new(192, 168, 1, 8), 24), - // gateway: Some(Ipv4Addr::new(192, 168, 1, 1)), - // dns_servers: heapless::Vec::new(), - // }); - // - // let seed = ((rng.random() as u64) << 32) | rng.random() as u64; - - // // Init network stack - // let (stack, runner) = embassy_net::new( - // wifi_interface, - // config, - // mk_static!(StackResources<3>, StackResources::<3>::new()), - // seed, - // ); - - // spawner.spawn(network::connection(controller)).ok(); - // spawner.spawn(network::net_task(runner)).ok(); + let config = + embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { + address: Ipv4Cidr::new(Ipv4Addr::new(192, 168, 1, 8), 24), + gateway: Some(Ipv4Addr::new(192, 168, 1, 1)), + dns_servers: heapless::Vec::new(), + }); + + let seed = ((rng.random() as u64) << 32) | rng.random() as u64; + + // Init network stack + let (stack, runner) = embassy_net::new( + wifi_interface, + config, + mk_static!(StackResources<3>, StackResources::<3>::new()), + seed, + ); + + spawner.spawn(network::connection(controller)).ok(); + spawner.spawn(network::net_task(runner)).ok(); let queue = Channel::new(); let fan_stack = fans::FanStack::new(peripherals.LEDC); let fans = fans::Fans::new(&fan_stack, peripherals.GPIO3); - join::join( - sensor::button(peripherals.GPIO10, &queue, &fans), - sensor::measure(peripherals.I2C0, &queue), - ) - .await; + + network::handle(&stack, &queue, &fans).await; + // join3( // network::handle(&stack, &queue, &fans), // sensor::button(peripherals.GPIO10, &queue, &fans), From ff64f9cd5c25efb7e532862310b9fd6b6a6fff49 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 11 Apr 2025 15:26:13 +0200 Subject: [PATCH 637/687] usb-bridge: handle outdated data gracefully --- crates/usb-bridge/src/main.rs | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/crates/usb-bridge/src/main.rs b/crates/usb-bridge/src/main.rs index 140cb686..3c3a895d 100644 --- a/crates/usb-bridge/src/main.rs +++ b/crates/usb-bridge/src/main.rs @@ -3,16 +3,18 @@ use std::net::SocketAddr; use clap::Parser; use color_eyre::eyre::Context; -use color_eyre::Section; -use data_server::api::data_source::reconnecting; -use tracing::debug; +use data_server::api::data_source::reconnecting::SendError; +use data_server::api::data_source::{reconnecting, SendPreEncodedError}; +use tracing::{debug, warn}; mod usb; #[derive(Parser)] #[command(name = "usb-bridge")] #[command(version = "1.0")] -#[command(about = "forwards sensor info from and affector orders to nodes attached to usb")] +#[command( + about = "forwards sensor info from and affector orders to nodes attached to usb" +)] struct Cli { /// Where to send the data on the local system #[arg(short, long("data-server"), default_value = "192.168.1.43:1234")] @@ -36,18 +38,18 @@ async fn main() -> Result<(), color_eyre::Report> { .get_affectors() .await .wrap_err("Could not get affector list")?; - let mut server_client = reconnecting::Client::new( - args.data_server, - affectors, - Some(order_tx), - ).await?; + let mut server_client = + reconnecting::Client::new(args.data_server, affectors, Some(order_tx)) + .await?; loop { let encoded_msg = usb.handle_usb().await; - server_client - .check_send_encoded(encoded_msg) - .await - .wrap_err("Should be correctly encoded") - .suggestion("Check if this needs to be updated")?; + match server_client.check_send_encoded(encoded_msg).await { + Ok(()) => (), + Err(SendPreEncodedError::Sending(SendError::Outdated)) => { + warn!("Did not send data because it is outdated") + } + other @ Err(_) => other?, + } } } From 696518067e690a1b3bf9255d7a1ee109d3d76189 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 14 Apr 2025 12:52:59 +0200 Subject: [PATCH 638/687] brain: Tweak wakeup --- crates/brain/src/controller/rooms/small_bedroom.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index cc6beda1..9ead5ee4 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -25,7 +25,7 @@ mod state; const UPDATE_INTERVAL: Duration = Duration::from_secs(5); const OFF_DELAY: Duration = Duration::from_secs(60); -const WAKEUP_EXPIRATION: Duration = Duration::from_secs(60); +const WAKEUP_EXPIRATION: Duration = Duration::from_secs(1800); const NAP_TIME: Duration = Duration::from_secs(30 * 60); const RADIATOR_OVERRIDE_MINUTES: i32 = 60; From 9476d9b60c6afe40e8e65129d1d0ec1dd3d472c4 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Tue, 15 Apr 2025 22:14:47 +0200 Subject: [PATCH 639/687] adds asserts into audiocontrol --- .../brain/src/controller/rooms/small_bedroom/audiocontrol.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs index 73cf4295..9551c2f4 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs @@ -516,7 +516,9 @@ impl AudioController { direction: Direction, current_playlist_name: &String, ) -> Option { - let playlist_names = self.get_playlists().into_iter().map(|pl| pl.name); + let playlists = self.get_playlists(); + assert!(!playlists.is_empty()); + let playlist_names = playlists.into_iter().map(|pl| pl.name); let mut playlist_names = playlist_names .filter(|pl| pl.starts_with(self.mode.to_prefix())) .collect::>(); @@ -526,6 +528,7 @@ impl AudioController { if let Direction::Previous = direction { playlist_names.reverse(); } + assert!(!playlist_names.is_empty()); let mut playlist_names = playlist_names.iter().cycle().peekable(); while *playlist_names.peek().unwrap() != current_playlist_name { From e48b6d0c16eaf4b5e87a5828a2cd9ad6f90ae43f Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 17 Apr 2025 11:09:41 +0200 Subject: [PATCH 640/687] brain: Tweak alarm --- crates/brain/src/controller/rooms/small_bedroom.rs | 2 +- crates/brain/src/controller/rooms/small_bedroom/state.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 9ead5ee4..a1550144 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -45,7 +45,7 @@ pub async fn run( let mut next_update = Instant::now() + UPDATE_INTERVAL; let wakeup_job = - Job::every_day_at(9, 30, Event::WakeupSB, Some(WAKEUP_EXPIRATION)); + Job::every_day_at(9, 15, Event::WakeupSB, Some(WAKEUP_EXPIRATION)); let res = system .system diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index 678c23e0..f7762a6a 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -178,7 +178,7 @@ impl Room { } async fn run_wakeup_then_daylight(mut self) { - const LIGHT_NAME: &str = "small_bedroom:ceiling"; + const LIGHT_NAME: &str = "small_bedroom:piano"; const RUNTIME_MINS: i32 = 20; const MUSIC_ON_AFTER_MINS: i32 = 13; From a02e8cf93b0cc0a1b1664bc076d2e28f20b7709a Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 18 Apr 2025 13:14:47 +0200 Subject: [PATCH 641/687] Add logging for podcast position loading It's buggy --- .../rooms/small_bedroom/audiocontrol/db.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db.rs index 349040ab..5886fdb4 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db.rs @@ -1,3 +1,5 @@ +use tracing::warn; + use super::AudioMode; use std::time::{SystemTime, UNIX_EPOCH}; @@ -63,10 +65,17 @@ impl Db { playlist_name: &str, ) -> Option { let key = playlist_name.to_owned() + "_position"; - self.database + let position = self + .database .get(key.as_bytes()) .unwrap() - .map(|buffer| Position::from_bytes(buffer.as_ref())) + .map(|buffer| Position::from_bytes(buffer.as_ref())); + if playlist_name == "podcast_hank-and-john" + || playlist_name == "podcast_ross-and-carrie" + { + warn!("Fetched position: {key}, {position:?}"); + } + position } pub(crate) fn store_position( @@ -75,6 +84,11 @@ impl Db { position: &Position, ) { let key = playlist_name.to_owned() + "_position"; + if playlist_name == "podcast_hank-and-john" + || playlist_name == "podcast_ross-and-carrie" + { + warn!("Storing position: {key}, {position:?}"); + } self.database .insert(key.as_bytes(), position.to_bytes()) .unwrap(); From ec5d5ab88f596005455e0d417b666b2b87083a5c Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 24 Apr 2025 12:04:21 +0200 Subject: [PATCH 642/687] Tweak alarm small bedroom --- crates/brain/src/controller/rooms/small_bedroom.rs | 2 +- crates/brain/src/controller/rooms/small_bedroom/state.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index a1550144..95f36847 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -45,7 +45,7 @@ pub async fn run( let mut next_update = Instant::now() + UPDATE_INTERVAL; let wakeup_job = - Job::every_day_at(9, 15, Event::WakeupSB, Some(WAKEUP_EXPIRATION)); + Job::every_day_at(9, 00, Event::WakeupSB, Some(WAKEUP_EXPIRATION)); let res = system .system diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index f7762a6a..678c23e0 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -178,7 +178,7 @@ impl Room { } async fn run_wakeup_then_daylight(mut self) { - const LIGHT_NAME: &str = "small_bedroom:piano"; + const LIGHT_NAME: &str = "small_bedroom:ceiling"; const RUNTIME_MINS: i32 = 20; const MUSIC_ON_AFTER_MINS: i32 = 13; From 2687eebd1ea176c14a10c514e792b697875f9715 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 28 Apr 2025 13:42:15 +0200 Subject: [PATCH 643/687] Remove sunday delay from small bedr alarm --- crates/brain/src/controller/rooms/small_bedroom/state.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index 678c23e0..2a169493 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -195,10 +195,6 @@ impl Room { let ct_growth = (END_CT as f64 / START_CT as f64).powf(1. / N_STEPS as f64); - if crate::time::now().weekday() == Weekday::Sunday { - // On Sunday, delay wakeup one hour - sleep(Duration::from_secs(60 * 60)).await; - } self.system .one_lamp_ct(LIGHT_NAME, START_CT, START_BRI) .await; From 3ac042dec09b3ac4da6a4f9b2530b25cabd7db49 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 29 Apr 2025 11:36:34 +0200 Subject: [PATCH 644/687] Add possible fix for podcasts randomly resetting --- .../rooms/small_bedroom/audiocontrol.rs | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs index 9551c2f4..9485bbf4 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs @@ -541,13 +541,25 @@ impl AudioController { let pos_in_pl = if let Some(song) = self.client.status().unwrap().song { song.pos } else { - 0 + // Try again before we reset, because apparently sometimes + // this fails + if let Some(elapsed) = self.get_elapsed() { + elapsed.as_secs().try_into().unwrap() + } else { + 0 + } }; let elapsed = if let Some(elapsed) = self.get_elapsed() { elapsed.as_secs().try_into().unwrap() } else { - 0 + // Try again before we reset, because apparently sometimes + // this fails + if let Some(elapsed) = self.get_elapsed() { + elapsed.as_secs().try_into().unwrap() + } else { + 0 + } }; let position = db::Position { pos_in_pl, elapsed }; @@ -672,13 +684,15 @@ impl AudioController { .chain(normal_songs.choose_multiple(&mut rng, 30)) }; - self.client.pl_push( - pl_name, - &Song { - file: "noise.ogg".to_string(), - ..Default::default() - }, - ).unwrap(); + self.client + .pl_push( + pl_name, + &Song { + file: "noise.ogg".to_string(), + ..Default::default() + }, + ) + .unwrap(); for song in to_add { self.client.pl_push(pl_name, song).unwrap(); tokio::time::sleep(Duration::from_millis(10)).await; From 8473148fa78850d7f0738f072c7aa2ca3e3ddcdd Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 29 Apr 2025 12:10:11 +0200 Subject: [PATCH 645/687] Fix status = default, probably fixing multiple bugs Possible fix for podcast elapsed reset bug, and pause doing rewind bug. --- .../rooms/small_bedroom/audiocontrol.rs | 29 ++++++++----------- .../audiocontrol/mpdinterface.rs | 17 ++++++++++- crates/brain/test.sh | 2 +- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs index 9485bbf4..93690088 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs @@ -8,7 +8,7 @@ use mpdrs::status::State; use mpdrs::Playlist; use mpdrs::{error::Error, Song}; use rand::seq::IndexedRandom; -use tracing::{debug, info, instrument, trace}; +use tracing::{debug, info, instrument, trace, warn}; use db::Db; use mpdinterface::MpdInterface; @@ -172,7 +172,9 @@ impl AudioController { } pub fn playing(&mut self) -> bool { - let playback_state = self.client.status().unwrap().state; + let status = self.client.status(); + info!("Status: {status:?}"); + let playback_state = status.unwrap().state; playback_state == State::Play } @@ -240,7 +242,7 @@ impl AudioController { debug!( "Song length: {length:?}, song position: {position:?}" ); - let time_left = length - position; + let time_left = length.saturating_sub(position); if Duration::from_secs(Db::now_timestamp() - last_played) > SONG_RESTART_THRESHOLD && time_left > ALMOST_OVER @@ -257,16 +259,19 @@ impl AudioController { pub fn toggle_playback(&mut self) { info!("Toggle playback"); let was_playing = self.playing(); + info!("Was playing: {was_playing}"); if self.stopped() { self.client.play().unwrap(); } else { + info!("Toggling pause"); self.client.toggle_pause().unwrap(); } if was_playing { self.store_current_pausing(); } else { + info!("Rewinding after pause"); self.rewind_after_pause(); } } @@ -541,25 +546,15 @@ impl AudioController { let pos_in_pl = if let Some(song) = self.client.status().unwrap().song { song.pos } else { - // Try again before we reset, because apparently sometimes - // this fails - if let Some(elapsed) = self.get_elapsed() { - elapsed.as_secs().try_into().unwrap() - } else { - 0 - } + warn!("Unknown pos in ppl, resetting"); + 0 }; let elapsed = if let Some(elapsed) = self.get_elapsed() { elapsed.as_secs().try_into().unwrap() } else { - // Try again before we reset, because apparently sometimes - // this fails - if let Some(elapsed) = self.get_elapsed() { - elapsed.as_secs().try_into().unwrap() - } else { - 0 - } + warn!("Unknown elapsed, resetting"); + 0 }; let position = db::Position { pos_in_pl, elapsed }; diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/mpdinterface.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/mpdinterface.rs index 49958c6d..c434821e 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/mpdinterface.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/mpdinterface.rs @@ -78,7 +78,6 @@ impl MpdInterface { ok_or_reconnect_no_args! {play, ()} ok_or_reconnect_no_args! {prev, ()} ok_or_reconnect_no_args! {next, ()} - ok_or_reconnect_no_args! {status, Status} ok_or_reconnect_no_args! {playlists, Vec} ok_or_reconnect_no_args! {queue, Vec} ok_or_reconnect_no_args! {currentsong, Option} @@ -96,6 +95,22 @@ impl MpdInterface { ok_or_reconnect_one_arg! {push, path, &str, u32} ok_or_reconnect_one_arg! {volume, volume, i8, ()} + pub(crate) fn status(&mut self) -> Result { + match self.client.status() { + Err(Error::Io(_)) => (), + Err(Error::Parse(_)) => (), + // There is not always an error when something goes wrong + // Sometimes we just get the default status and we also + // need to retry, because this makes no sense in the logic + Ok(status) if status == Status::default() => (), + other => return other, + }; + + debug!("IOError or ParseError, reconnecting..."); + self.client = mpdrs::Client::connect(&self.ip)?; + self.client.status() + } + pub(crate) fn pause(&mut self) -> Result<()> { match self.client.pause(true) { Err(Error::Io(_)) => (), diff --git a/crates/brain/test.sh b/crates/brain/test.sh index 00bad8b1..1c75da61 100755 --- a/crates/brain/test.sh +++ b/crates/brain/test.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -RUST_LOG=brain=trace,zigbee_bridge=info,info RUST_BACKTRACE=1 cargo r -- \ +RUST_LOG=brain=info,zigbee_bridge=info,info RUST_BACKTRACE=1 cargo r -- \ --data-server 192.168.1.43:1235 \ --mpd-ip 192.168.1.43 \ --http-port 34326 \ From 3093cb3a9de213fad4984087f88b8b4eaac748a6 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Thu, 1 May 2025 12:44:11 +0200 Subject: [PATCH 646/687] Change heating settings for warmer weather --- crates/brain/src/controller/rooms/small_bedroom.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 95f36847..926ad3c7 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -239,8 +239,9 @@ pub(crate) fn goal_temp_now() -> f64 { ((10, 00), 20.0), ((11, 00), 20.5), ((12, 00), 21.0), - ((20, 00), 20.5), - ((21, 00), 20.0), + ((18, 00), 20.5), + ((19, 00), 20.0), + ((21, 00), 19.5), ((21, 30), 19.0), ((22, 00), 18.0), ]); From 3b31f0ac8747df5c5f2020e4c0dbc7ff37b2df97 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Wed, 7 May 2025 16:13:11 +0200 Subject: [PATCH 647/687] Change kitchen to turn on all lamps with wakeup --- crates/brain/src/controller/rooms/kitchen.rs | 24 ++++--------------- .../src/controller/rooms/small_bedroom.rs | 2 +- 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index efd6b680..d41a5204 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -2,7 +2,6 @@ use std::time::Duration; use futures_concurrency::future::Race; use futures_util::FutureExt; -use jiff::civil::Time; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; use tracing::warn; @@ -15,7 +14,6 @@ const INTERVAL: Duration = Duration::from_secs(5); #[derive(PartialEq, Eq)] enum State { Sleep, - Morning, Daylight, Override, } @@ -87,25 +85,15 @@ pub async fn run( system.all_lamps_off().await; } Res::Event(RelevantEvent::Daylight) => { - if is_late_morning() { - state = State::Daylight; - update(&mut system).await; - system.all_lamps_on().await; - } else { - state = State::Morning; - update(&mut system).await; - system.all_lamps_but_one_on("kitchen:hallway").await; - } + state = State::Daylight; + update(&mut system).await; + system.all_lamps_on().await; } Res::Event(RelevantEvent::Override) => { state = State::Override; system.all_lamps_ct(2000, 1.0).await; } - Res::ShouldUpdate - if state == State::Daylight - || (state == State::Morning && is_late_morning()) => - { - state = State::Daylight; + Res::ShouldUpdate if state == State::Daylight => { update(&mut system).await; system.all_lamps_on().await; next_update = Instant::now() + INTERVAL; @@ -115,10 +103,6 @@ pub async fn run( } } -fn is_late_morning() -> bool { - crate::time::now().datetime().time() > Time::new(10, 0, 0, 0).unwrap() -} - async fn update(system: &mut RestrictedSystem) { let (new_ct, new_bri) = small_bedroom::daylight_now(); // let (new_ct, new_bri) = _testing_ct_bri(); diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 926ad3c7..d79c712e 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -45,7 +45,7 @@ pub async fn run( let mut next_update = Instant::now() + UPDATE_INTERVAL; let wakeup_job = - Job::every_day_at(9, 00, Event::WakeupSB, Some(WAKEUP_EXPIRATION)); + Job::every_day_at(8, 45, Event::WakeupSB, Some(WAKEUP_EXPIRATION)); let res = system .system From b8fb15f3c7704604570f3ce979ee1ebe3896d8a4 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 15 Jun 2025 17:50:40 +0200 Subject: [PATCH 648/687] usb-bridge: fix hint with systemd transient user + allow dns name as arg --- crates/usb-bridge/src/main.rs | 13 +++++++++++- crates/usb-bridge/src/usb/device.rs | 33 +++++++++++++++++++---------- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/crates/usb-bridge/src/main.rs b/crates/usb-bridge/src/main.rs index 3c3a895d..8ef6b31b 100644 --- a/crates/usb-bridge/src/main.rs +++ b/crates/usb-bridge/src/main.rs @@ -17,7 +17,8 @@ mod usb; )] struct Cli { /// Where to send the data on the local system - #[arg(short, long("data-server"), default_value = "192.168.1.43:1234")] + #[arg(short, long("data-server"), + default_value = "192.168.1.43:1234", value_parser = resolve_socketaddr)] data_server: SocketAddr, /// Serial number of the device to connect case insensitive #[arg(short, long)] @@ -53,3 +54,13 @@ async fn main() -> Result<(), color_eyre::Report> { } } } + +pub fn resolve_socketaddr(arg: &str) -> Result { + use std::net::ToSocketAddrs; + + let mut addrs_iter = arg.to_socket_addrs()?; + addrs_iter.next().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + "Must pass one address", + )) +} diff --git a/crates/usb-bridge/src/usb/device.rs b/crates/usb-bridge/src/usb/device.rs index 81a27098..7e412674 100644 --- a/crates/usb-bridge/src/usb/device.rs +++ b/crates/usb-bridge/src/usb/device.rs @@ -45,28 +45,39 @@ pub(crate) fn get_usb_device( [dev] => dev, [] => { return Err(eyre!("No usb device found with the correct serial")) - .with_note(|| format!("looking for device with serial: {serial_number}")) + .with_note(|| { + format!("looking for device with serial: {serial_number}") + }) .suggestion( "Is the device working (sometimes programming fails) \ & connected?", ); } more => { - return Err(eyre!("Multiple usb devices have the same serial number") - .with_note(|| format!("they are: {more:?}"))); + return Err(eyre!( + "Multiple usb devices have the same serial number" + ) + .with_note(|| format!("they are: {more:?}"))); } } .open() .wrap_err("Could not open the usb device") .suggestion("Try running as sudo") - .with_suggestion(|| { + .with_suggestion(|| edit_udev_rules_instruction(serial_number)) +} + +fn edit_udev_rules_instruction(serial_number: &str) -> String { + if let Some(group) = uzers::get_current_groupname() { + let group = group.to_string_lossy(); format!( - "Add a .rules file in /etc/udev/rules.d with line: \n\ - ATTRS{{serial}}==\"{serial_number}\", MODE=\"660\", GROUP=\"{}\", TAG+=\"uaccess\"\n\ + "Add a .rules file in /etc/udev/rules.d with line: \n\ + ATTRS{{serial}}==\"{serial_number}\", MODE=\"660\", GROUP=\"{group}\", TAG+=\"uaccess\"\n\ Then run: sudo udevadm control --reload && sudo udevadm trigger", - uzers::get_current_groupname() - .expect("process should always run as a group") - .to_string_lossy() - ) - }) + ) + } else { + "Look up this users primary group then add a .rules file + in /etc/udev/rules.d, replace with the primary group: \n\ + ATTRS{{serial}}==\"{serial_number}\", MODE=\"660\", GROUP=\"\", TAG+=\"uaccess\"\n\ + Then run: sudo udevadm control --reload && sudo udevadm trigger".to_string() + } } From 68294d70db55e16fca33160b7f19215b2af6171f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 15 Jun 2025 18:26:51 +0200 Subject: [PATCH 649/687] usb-bridge make deploy work on fresh system --- crates/usb-bridge/deploy.sh | 44 ++++++++++++++-------------- crates/usb-bridge/usb-bridge.rules | 2 ++ crates/usb-bridge/usb-bridge.service | 20 +++++++++++++ 3 files changed, 44 insertions(+), 22 deletions(-) create mode 100644 crates/usb-bridge/usb-bridge.rules create mode 100644 crates/usb-bridge/usb-bridge.service diff --git a/crates/usb-bridge/deploy.sh b/crates/usb-bridge/deploy.sh index 9c4c255b..91ae0272 100755 --- a/crates/usb-bridge/deploy.sh +++ b/crates/usb-bridge/deploy.sh @@ -2,31 +2,31 @@ set -e BUILD_ARG=--release -SERVER1="sgc" # ssh config name or full address -SERVER2="eva@192.168.1.101" # ssh config name or full address NAME=usb-bridge cargo build --target=aarch64-unknown-linux-musl $BUILD_ARG -cargo build --target=armv7-unknown-linux-musleabihf $BUILD_ARG -rsync -vh --progress \ - ../../target/aarch64-unknown-linux-musl/release/$NAME \ - $SERVER1:/tmp/ -rsync -vh --progress \ - ../../target/armv7-unknown-linux-musleabihf/release/$NAME \ - $SERVER2:/tmp/ -cmds=" -sudo mv /tmp/$NAME /home/ha/$NAME -sudo chown ha:ha /home/ha/$NAME -sudo systemctl restart $NAME.service -" +for server in "atlantis"; do + rsync -vh --progress \ + ../../target/aarch64-unknown-linux-musl/release/$NAME \ + $server:/tmp/ + rsync -vh --progress \ + $NAME.service \ + $server:/tmp/ + rsync -vh --progress \ + $NAME.rules \ + $server:/tmp/ -ssh -t $SERVER1 "$cmds" + cmds=" + sudo mv /tmp/$NAME /usr/bin/ + sudo mv /tmp/$NAME.service /etc/systemd/system + sudo mv /tmp/$NAME.rules /etc/udev/rules.d + sudo udevadm control --reload-rules + sudo udevadm trigger + sudo systemctl daemon-reload + sudo systemctl enable $NAME.service + sudo systemctl restart $NAME.service + " -cmds=" -mv /tmp/$NAME /home/eva/$NAME -sudo chown eva:eva /home/eva/$NAME -sudo systemctl restart $NAME.service -" - -ssh -t $SERVER2 "$cmds" + ssh -t $server "$cmds" +done diff --git a/crates/usb-bridge/usb-bridge.rules b/crates/usb-bridge/usb-bridge.rules new file mode 100644 index 00000000..71af6af9 --- /dev/null +++ b/crates/usb-bridge/usb-bridge.rules @@ -0,0 +1,2 @@ +ATTRS{serial}=="2139874", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{serial}=="87244", MODE="660", GROUP="plugdev", TAG+="uaccess" diff --git a/crates/usb-bridge/usb-bridge.service b/crates/usb-bridge/usb-bridge.service new file mode 100644 index 00000000..7f7d0874 --- /dev/null +++ b/crates/usb-bridge/usb-bridge.service @@ -0,0 +1,20 @@ +[Unit] +Description=Usb bridge +After=network-online.target +Wants=network-online.target + +[Service] +Type=exec +DynamicUser=yes +User=usb-bridge +Group=usb-bridge +SupplementaryGroups=plugdev +Environment="RUST_BACKTRACE=1" +Environment="RUST_LOG=nusb=warn,info" +ExecStart=/usr/bin/usb-bridge \ + --data-server sgc:1234 \ + --serial-number 87244 +ExecStop=/bin/kill -s SIGKILL $MAINPID + +[Install] +WantedBy=multi-user.target From 3e3207f1e5857d67ddec71acd5a39f1fefea2f29 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 15 Jun 2025 21:38:26 +0200 Subject: [PATCH 650/687] desk-sensors deploy installs on fresh system --- crates/desk-sensors/deploy.sh | 52 ++++++++++++------------ crates/desk-sensors/desk-sensors.service | 20 +++++++++ crates/desk-sensors/src/main.rs | 13 +++++- 3 files changed, 57 insertions(+), 28 deletions(-) create mode 100644 crates/desk-sensors/desk-sensors.service diff --git a/crates/desk-sensors/deploy.sh b/crates/desk-sensors/deploy.sh index adab4d0f..34184325 100755 --- a/crates/desk-sensors/deploy.sh +++ b/crates/desk-sensors/deploy.sh @@ -1,34 +1,32 @@ #!/usr/bin/env bash set -e -SERVER="sgc" # ssh config name or full address BUILD_ARG=--release -RELEASE=release +NAME=desk-sensors cargo build --target=aarch64-unknown-linux-musl $BUILD_ARG -rsync -vh --progress \ - ../../target/aarch64-unknown-linux-musl/$RELEASE/desk-sensors \ - $SERVER:/tmp/ -cmds=" -sudo mv /tmp/desk-sensors /home/ha/desk-sensors -sudo chown ha:ha /home/ha/desk-sensors -sudo systemctl restart desk-sensors.service -" - -ssh -t $SERVER "$cmds" - - -SERVER="atlantis" # ssh config name or full address -cargo build --target=armv7-unknown-linux-musleabihf $BUILD_ARG -rsync -vh --progress \ - ../../target/armv7-unknown-linux-musleabihf/$RELEASE/desk-sensors \ - $SERVER:/tmp/ - -cmds=" -sudo mv /tmp/desk-sensors /home/eva/desk-sensors -sudo chown eva:eva /home/eva/desk-sensors -sudo systemctl restart desk-sensors.service -" - -ssh -t $SERVER "$cmds" +for server in "atlantis"; do + if [ $server == "atlantis" ]; then + sed -i 's/--bedroom large/--bedroom small/' $NAME.service + else + sed -i 's/--bedroom small/--bedroom large/' $NAME.service + fi + + rsync -vh --progress \ + ../../target/aarch64-unknown-linux-musl/release/$NAME \ + $server:/tmp/ + rsync -vh --progress \ + $NAME.service \ + $server:/tmp/ + + cmds=" + sudo mv /tmp/$NAME /usr/bin/ + sudo mv /tmp/$NAME.service /etc/systemd/system + sudo systemctl daemon-reload + sudo systemctl enable $NAME.service + sudo systemctl restart $NAME.service + " + + ssh -t $server "$cmds" +done diff --git a/crates/desk-sensors/desk-sensors.service b/crates/desk-sensors/desk-sensors.service new file mode 100644 index 00000000..e180eab0 --- /dev/null +++ b/crates/desk-sensors/desk-sensors.service @@ -0,0 +1,20 @@ +[Unit] +Description=Usb bridge +After=network-online.target +Wants=network-online.target + +[Service] +Type=exec +DynamicUser=yes +User=desk-sensors +Group=desk-sensors +SupplementaryGroups=i2c +Environment="RUST_BACKTRACE=1" +Environment="RUST_LOG=nusb=warn,info" +ExecStart=/usr/bin/desk-sensors \ + --bedroom small \ + --data-server sgc:1234 +ExecStop=/bin/kill -s SIGKILL $MAINPID + +[Install] +WantedBy=multi-user.target diff --git a/crates/desk-sensors/src/main.rs b/crates/desk-sensors/src/main.rs index cb391e06..c0375dc2 100644 --- a/crates/desk-sensors/src/main.rs +++ b/crates/desk-sensors/src/main.rs @@ -16,7 +16,8 @@ mod sensors; #[command(about = "reads sensors attached to rpi gpio pins and i2c perhipheral")] struct Cli { /// Where to send the data on the local system - #[arg(short, long("data-server"))] + #[arg(short, long("data-server"), + default_value = "sgc:1234", value_parser = resolve_socketaddr)] data_server: SocketAddr, /// Is this the pi in the large bedroom or small bedroom? #[arg(short, long)] @@ -55,3 +56,13 @@ async fn main() { } } } + +pub fn resolve_socketaddr(arg: &str) -> Result { + use std::net::ToSocketAddrs; + + let mut addrs_iter = arg.to_socket_addrs()?; + addrs_iter.next().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + "Must pass one address", + )) +} From 5d1e120bc4b2e551faf1033d2ec8c7b0d96fef18 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 15 Jun 2025 21:57:38 +0200 Subject: [PATCH 651/687] move must use from trait impl to decl --- crates/protocol/src/affector/tree.rs | 1 - crates/protocol/src/button.rs | 1 - crates/protocol/src/large_bedroom/airbox.rs | 3 --- crates/protocol/src/large_bedroom/bed.rs | 3 --- crates/protocol/src/large_bedroom/desk.rs | 2 -- crates/protocol/src/large_bedroom/radiator.rs | 2 -- crates/protocol/src/lib.rs | 1 + crates/protocol/src/reading/tree.rs | 3 ++- crates/protocol/src/small_bedroom/bed.rs | 3 --- crates/protocol/src/small_bedroom/desk.rs | 2 -- crates/protocol/src/small_bedroom/portable_button_panel.rs | 2 -- crates/protocol/src/small_bedroom/radiator.rs | 2 -- 12 files changed, 3 insertions(+), 22 deletions(-) diff --git a/crates/protocol/src/affector/tree.rs b/crates/protocol/src/affector/tree.rs index cddce41e..e7d22780 100644 --- a/crates/protocol/src/affector/tree.rs +++ b/crates/protocol/src/affector/tree.rs @@ -32,7 +32,6 @@ pub trait Tree: core::fmt::Debug { macro_rules! impl_zero { ($name:ident; $($var:ident),*) => { impl crate::IsSameAs for $name { - #[must_use] #[allow(unreachable_patterns)] fn is_same_as(&self, other: &Self) -> bool { match (self, other) { diff --git a/crates/protocol/src/button.rs b/crates/protocol/src/button.rs index a7b476d2..a063ec8c 100644 --- a/crates/protocol/src/button.rs +++ b/crates/protocol/src/button.rs @@ -103,7 +103,6 @@ macro_rules! button_enum { } impl crate::IsSameAs for $name { - #[must_use] fn is_same_as(&self, other: &Self) -> bool { match (self, other) { $(($name::$variant(_), $name::$variant(_)) => true,)* diff --git a/crates/protocol/src/large_bedroom/airbox.rs b/crates/protocol/src/large_bedroom/airbox.rs index ba344339..1e6c69f9 100644 --- a/crates/protocol/src/large_bedroom/airbox.rs +++ b/crates/protocol/src/large_bedroom/airbox.rs @@ -40,7 +40,6 @@ impl_is_same_as! {Reading; Temperature, Pressure, FanPower, Button} #[cfg(feature = "alloc")] impl Tree for Reading { - #[must_use] fn inner(&self) -> Item<'_> { let leaf = match self { Reading::Temperature(val) => Info { @@ -91,7 +90,6 @@ impl Tree for Reading { Item::Leaf(leaf) } - #[must_use] fn branch_id(&self) -> crate::reading::tree::Id { ReadingDiscriminants::from(self) as crate::reading::tree::Id } @@ -253,7 +251,6 @@ pub enum Affector { } impl crate::IsSameAs for Affector { - #[must_use] fn is_same_as(&self, other: &Self) -> bool { match (self, other) { (Affector::FanPower { .. }, Affector::FanPower { .. }) => true, diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index a68421e6..11a8e272 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -92,7 +92,6 @@ pub enum Reading { #[cfg(feature = "alloc")] impl Tree for Reading { - #[must_use] #[allow(clippy::too_many_lines)] #[allow(clippy::cast_precision_loss)] fn inner(&self) -> Item<'_> { @@ -260,7 +259,6 @@ impl Tree for Reading { }) } - #[must_use] fn branch_id(&self) -> Id { ReadingDiscriminants::from(self) as Id } @@ -521,7 +519,6 @@ pub enum Affector { } impl crate::IsSameAs for Affector { - #[must_use] fn is_same_as(&self, other: &Self) -> bool { #[allow(clippy::match_like_matches_macro)] match (self, other) { diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index d74d8470..38dab15c 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -51,7 +51,6 @@ pub enum Reading { #[cfg(feature = "alloc")] impl Tree for Reading { - #[must_use] fn inner(&self) -> Item<'_> { let leaf = match self { Reading::Temperature(val) => Info { @@ -89,7 +88,6 @@ impl Tree for Reading { Item::Leaf(leaf) } - #[must_use] fn branch_id(&self) -> crate::reading::tree::Id { ReadingDiscriminants::from(self) as crate::reading::tree::Id } diff --git a/crates/protocol/src/large_bedroom/radiator.rs b/crates/protocol/src/large_bedroom/radiator.rs index 5400d7c0..d54c871a 100644 --- a/crates/protocol/src/large_bedroom/radiator.rs +++ b/crates/protocol/src/large_bedroom/radiator.rs @@ -37,7 +37,6 @@ impl_is_same_as!{Reading; Temperature, Heating, SetBy, Setpoint} #[cfg(feature = "alloc")] impl Tree for Reading { - #[must_use] fn inner(&self) -> Item<'_> { let leaf = match self { Reading::Temperature(val) => Info { @@ -94,7 +93,6 @@ impl Tree for Reading { Item::Leaf(leaf) } - #[must_use] fn branch_id(&self) -> crate::reading::tree::Id { ReadingDiscriminants::from(self) as crate::reading::tree::Id } diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 1f52c24f..f8c3ff27 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -64,5 +64,6 @@ impl Display for Unit { /// Temperature(5) is the same as Temperature(6) pub trait IsSameAs { /// Is this the same variant as the other? + #[must_use] fn is_same_as(&self, other: &Self) -> bool; } diff --git a/crates/protocol/src/reading/tree.rs b/crates/protocol/src/reading/tree.rs index b0a9fb85..83ad8f53 100644 --- a/crates/protocol/src/reading/tree.rs +++ b/crates/protocol/src/reading/tree.rs @@ -8,6 +8,7 @@ pub enum Item<'a> { } pub trait Tree: core::fmt::Debug { + #[must_use] fn inner(&self) -> Item<'_>; fn leaf(&self) -> Info where @@ -28,13 +29,13 @@ pub trait Tree: core::fmt::Debug { .map_or("_", |(name, _)| name) .to_string() } + #[must_use] fn branch_id(&self) -> Id; } macro_rules! impl_zero { ($name:ident; $($var:ident),*) => { impl crate::IsSameAs for $name { - #[must_use] fn is_same_as(&self, other: &Self) -> bool { match (self, other) { $(($name::$var(a), $name::$var(b)) => a.is_same_as(b),)* diff --git a/crates/protocol/src/small_bedroom/bed.rs b/crates/protocol/src/small_bedroom/bed.rs index b1b9209d..9e9ba7ba 100644 --- a/crates/protocol/src/small_bedroom/bed.rs +++ b/crates/protocol/src/small_bedroom/bed.rs @@ -81,7 +81,6 @@ pub enum Reading { #[cfg(feature = "alloc")] impl Tree for Reading { - #[must_use] #[allow(clippy::too_many_lines)] #[allow(clippy::cast_precision_loss)] fn inner(&self) -> Item<'_> { @@ -241,7 +240,6 @@ impl Tree for Reading { }) } - #[must_use] fn branch_id(&self) -> Id { ReadingDiscriminants::from(self) as Id } @@ -486,7 +484,6 @@ pub enum Affector { } impl crate::IsSameAs for Affector { - #[must_use] fn is_same_as(&self, other: &Self) -> bool { self.eq(other) } diff --git a/crates/protocol/src/small_bedroom/desk.rs b/crates/protocol/src/small_bedroom/desk.rs index 367c35f9..04cdffda 100644 --- a/crates/protocol/src/small_bedroom/desk.rs +++ b/crates/protocol/src/small_bedroom/desk.rs @@ -34,7 +34,6 @@ pub enum Reading { #[cfg(feature = "alloc")] impl Tree for Reading { - #[must_use] fn inner(&self) -> Item<'_> { let leaf = match self { Reading::Temperature(val) => Info { @@ -71,7 +70,6 @@ impl Tree for Reading { Item::Leaf(leaf) } - #[must_use] fn branch_id(&self) -> crate::reading::tree::Id { ReadingDiscriminants::from(self) as crate::reading::tree::Id } diff --git a/crates/protocol/src/small_bedroom/portable_button_panel.rs b/crates/protocol/src/small_bedroom/portable_button_panel.rs index bd48233b..98ed5ab9 100644 --- a/crates/protocol/src/small_bedroom/portable_button_panel.rs +++ b/crates/protocol/src/small_bedroom/portable_button_panel.rs @@ -43,7 +43,6 @@ pub enum Reading { #[cfg(feature = "alloc")] impl Tree for Reading { - #[must_use] fn inner(&self) -> Item<'_> { Item::Leaf(crate::reading::Info { val: 1.0, @@ -64,7 +63,6 @@ impl Tree for Reading { dbg_repr } - #[must_use] fn branch_id(&self) -> crate::reading::tree::Id { ReadingDiscriminants::from(self) as crate::reading::tree::Id } diff --git a/crates/protocol/src/small_bedroom/radiator.rs b/crates/protocol/src/small_bedroom/radiator.rs index 7cedc63d..121767b2 100644 --- a/crates/protocol/src/small_bedroom/radiator.rs +++ b/crates/protocol/src/small_bedroom/radiator.rs @@ -37,7 +37,6 @@ impl_is_same_as!(Reading; Temperature, Heating, SetBy, Setpoint); #[cfg(feature = "alloc")] impl Tree for Reading { - #[must_use] fn inner(&self) -> Item<'_> { let leaf = match self { Reading::Temperature(val) => Info { @@ -94,7 +93,6 @@ impl Tree for Reading { Item::Leaf(leaf) } - #[must_use] fn branch_id(&self) -> crate::reading::tree::Id { ReadingDiscriminants::from(self) as crate::reading::tree::Id } From 2b63b2118bd60bb52ef2819134e926275944520a Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 21 Jun 2025 13:04:24 +0200 Subject: [PATCH 652/687] Tweak entrance lamps and audio warn statement --- crates/brain/src/controller/rooms/entrance.rs | 3 ++- .../brain/src/controller/rooms/small_bedroom/audiocontrol.rs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/brain/src/controller/rooms/entrance.rs b/crates/brain/src/controller/rooms/entrance.rs index 8b3fdcc3..b3a36764 100644 --- a/crates/brain/src/controller/rooms/entrance.rs +++ b/crates/brain/src/controller/rooms/entrance.rs @@ -99,7 +99,8 @@ pub async fn run( async fn update(system: &mut RestrictedSystem) { let (new_ct, new_bri) = small_bedroom::daylight_now(); - let new_bri = new_bri.clamp(0.8, 1.0); + let new_ct = new_ct.clamp(1000, 3000); + let new_bri = new_bri.clamp(0.5, 1.0); system.all_lamps_ct(new_ct, new_bri).await; tracing::trace!("updated lamps"); } diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs index 93690088..06116658 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs @@ -546,14 +546,14 @@ impl AudioController { let pos_in_pl = if let Some(song) = self.client.status().unwrap().song { song.pos } else { - warn!("Unknown pos in ppl, resetting"); + warn!("Unknown pos in pl {playlist_name}, resetting"); 0 }; let elapsed = if let Some(elapsed) = self.get_elapsed() { elapsed.as_secs().try_into().unwrap() } else { - warn!("Unknown elapsed, resetting"); + warn!("Unknown elapsed for {playlist_name}, resetting"); 0 }; From 2aacf0d3901aa2d476d96461566492626fcdf66c Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 21 Jun 2025 14:05:59 +0200 Subject: [PATCH 653/687] Fix crash when events missed, deduplicate event filter --- crates/brain/src/controller/rooms.rs | 5 +-- crates/brain/src/controller/rooms/common.rs | 32 +++++++++++++++++++ crates/brain/src/controller/rooms/entrance.rs | 23 +------------ crates/brain/src/controller/rooms/kitchen.rs | 22 +------------ .../src/controller/rooms/large_bedroom.rs | 22 +------------ .../src/controller/rooms/small_bedroom.rs | 9 ++++-- .../controller/rooms/small_bedroom/filter.rs | 19 +---------- 7 files changed, 45 insertions(+), 87 deletions(-) create mode 100644 crates/brain/src/controller/rooms/common.rs diff --git a/crates/brain/src/controller/rooms.rs b/crates/brain/src/controller/rooms.rs index 0375837a..3fae8bf8 100644 --- a/crates/brain/src/controller/rooms.rs +++ b/crates/brain/src/controller/rooms.rs @@ -1,4 +1,5 @@ +pub mod common; +pub mod entrance; +pub mod kitchen; pub mod large_bedroom; pub mod small_bedroom; -pub mod kitchen; -pub mod entrance; diff --git a/crates/brain/src/controller/rooms/common.rs b/crates/brain/src/controller/rooms/common.rs new file mode 100644 index 00000000..a4d80669 --- /dev/null +++ b/crates/brain/src/controller/rooms/common.rs @@ -0,0 +1,32 @@ +use tokio::sync::broadcast::{self, error::RecvError}; +use tracing::warn; + +use crate::controller::Event; + +pub(crate) trait RecvFiltered { + async fn recv_filter_mapped( + &mut self, + filter_map: impl Fn(Event) -> Option, + ) -> T; +} + +impl RecvFiltered for broadcast::Receiver { + async fn recv_filter_mapped( + &mut self, + filter_map: impl Fn(Event) -> Option, + ) -> T { + loop { + let event = match self.recv().await { + Ok(event) => event, + Err(RecvError::Lagged(n)) => { + warn!("A room missed {n} events"); + continue; + } + Err(err) => panic!("{err}"), + }; + if let Some(relevant) = filter_map(event) { + return relevant; + } + } + } +} diff --git a/crates/brain/src/controller/rooms/entrance.rs b/crates/brain/src/controller/rooms/entrance.rs index b3a36764..5efce990 100644 --- a/crates/brain/src/controller/rooms/entrance.rs +++ b/crates/brain/src/controller/rooms/entrance.rs @@ -5,6 +5,7 @@ use futures_concurrency::future::Race; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; +use crate::controller::rooms::common::RecvFiltered; use crate::controller::rooms::small_bedroom; use crate::controller::{Event, RestrictedSystem}; @@ -16,28 +17,6 @@ enum State { Daylight, } -// TODO: deduplicate filter code with kitchen -trait RecvFiltered { - async fn recv_filter_mapped( - &mut self, - filter_map: impl Fn(Event) -> Option, - ) -> T; -} - -impl RecvFiltered for broadcast::Receiver { - async fn recv_filter_mapped( - &mut self, - filter_map: impl Fn(Event) -> Option, - ) -> T { - loop { - let event = self.recv().await.unwrap(); - if let Some(relevant) = filter_map(event) { - return relevant; - } - } - } -} - #[derive(Debug)] enum RelevantEvent { Sleep, diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index d41a5204..f574383a 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -6,6 +6,7 @@ use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; use tracing::warn; +use crate::controller::rooms::common::RecvFiltered; use crate::controller::rooms::small_bedroom; use crate::controller::{Event, RestrictedSystem}; @@ -18,27 +19,6 @@ enum State { Override, } -trait RecvFiltered { - async fn recv_filter_mapped( - &mut self, - filter_map: impl Fn(Event) -> Option, - ) -> T; -} - -impl RecvFiltered for broadcast::Receiver { - async fn recv_filter_mapped( - &mut self, - filter_map: impl Fn(Event) -> Option, - ) -> T { - loop { - let event = self.recv().await.unwrap(); - if let Some(relevant) = filter_map(event) { - return relevant; - } - } - } -} - #[derive(Debug)] enum RelevantEvent { Sleep, diff --git a/crates/brain/src/controller/rooms/large_bedroom.rs b/crates/brain/src/controller/rooms/large_bedroom.rs index 18def619..de8f30f7 100644 --- a/crates/brain/src/controller/rooms/large_bedroom.rs +++ b/crates/brain/src/controller/rooms/large_bedroom.rs @@ -6,6 +6,7 @@ use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; use tracing::{info, warn}; +use crate::controller::rooms::common::RecvFiltered; use crate::controller::{Event, RestrictedSystem}; #[derive(Debug, Clone, PartialEq, Eq)] @@ -21,27 +22,6 @@ enum State { const INTERVAL: Duration = Duration::from_secs(5); -trait RecvFiltered { - async fn recv_filter_mapped( - &mut self, - filter_map: impl Fn(Event) -> Option, - ) -> T; -} - -impl RecvFiltered for broadcast::Receiver { - async fn recv_filter_mapped( - &mut self, - filter_map: impl Fn(Event) -> Option, - ) -> T { - loop { - let event = self.recv().await.unwrap(); - if let Some(relevant) = filter_map(event) { - return relevant; - } - } - } -} - #[derive(Debug)] enum RelevantEvent { WakeUp, diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index d79c712e..ee89a3ac 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -10,11 +10,12 @@ use jiff::{ToSpan, Zoned}; use protocol::small_bedroom::{portable_button_panel, ButtonPanel}; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; -use tracing::{debug, error, info, trace}; +use tracing::{info, trace}; -use self::filter::{recv_filtered, RelevantEvent, Trigger}; +use self::filter::{RelevantEvent, Trigger}; use self::state::Room; pub(crate) use self::state::State; +use crate::controller::rooms::common::RecvFiltered; use crate::controller::{Event, RestrictedSystem}; use crate::input::jobs::Job; use crate::time; @@ -58,7 +59,9 @@ pub async fn run( trace!("Jobs returned: {res:#?}"); loop { - let get_event = recv_filtered(&mut event_rx); + let get_event = event_rx + .recv_filter_mapped(filter::filter) + .map(Trigger::Event); let tick = sleep_until(next_update).map(|_| Trigger::ShouldUpdate); let trigger = (get_event, tick).race().await; diff --git a/crates/brain/src/controller/rooms/small_bedroom/filter.rs b/crates/brain/src/controller/rooms/small_bedroom/filter.rs index dd613b6e..c23cd768 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/filter.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/filter.rs @@ -23,24 +23,7 @@ pub(super) enum RelevantEvent { Pm2_5(f32), } -pub(super) async fn recv_filtered(event_rx: &mut Receiver) -> Trigger { - loop { - let event = match event_rx.recv().await { - Ok(event) => event, - Err(RecvError::Lagged(n)) => { - warn!("SB missed {n} events"); - continue; - } - Err(err) => panic!("{err}"), - }; - if let Some(relevant) = event_filter(event) { - trace!("SB received relevant event: {relevant:?}"); - return Trigger::Event(relevant); - } - } -} - -fn event_filter(event: Event) -> Option { +pub(super) fn filter(event: Event) -> Option { match event { Event::Sensor(Reading::SmallBedroom( small_bedroom::Reading::ButtonPanel(button), From 742202cef951e09912de749b69980f60a00d23eb Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 21 Jun 2025 16:03:14 +0200 Subject: [PATCH 654/687] Fix clippy lints --- crates/brain/src/controller/mod.rs | 2 + .../src/controller/rooms/small_bedroom.rs | 29 ++--- .../rooms/small_bedroom/audiocontrol.rs | 3 +- .../rooms/small_bedroom/audiocontrol/db.rs | 4 +- .../rooms/small_bedroom/audiocontrol/db2.rs | 110 ------------------ .../controller/rooms/small_bedroom/filter.rs | 3 +- .../controller/rooms/small_bedroom/state.rs | 41 +++---- crates/brain/src/input/jobs.rs | 19 +-- .../src/api/data_source/reconnecting.rs | 2 +- crates/protocol/src/large_bedroom/airbox.rs | 10 +- crates/zigbee-bridge/src/conversion.rs | 3 - crates/zigbee-bridge/src/lamp/model.rs | 4 +- crates/zigbee-bridge/src/parse.rs | 6 +- 13 files changed, 66 insertions(+), 170 deletions(-) delete mode 100644 crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db2.rs diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 3c885647..cbd78951 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -65,6 +65,7 @@ impl RestrictedSystem { } } + #[allow(unused)] async fn all_lamps_but_one_off(&mut self, leave_this_on: &str) { for name in &self.allowed_lights { if *name != leave_this_on { @@ -73,6 +74,7 @@ impl RestrictedSystem { } } + #[allow(unused)] async fn all_lamps_but_one_on(&mut self, leave_this_off: &str) { for name in &self.allowed_lights { if *name != leave_this_off { diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index ee89a3ac..d39641c1 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -28,7 +28,6 @@ const UPDATE_INTERVAL: Duration = Duration::from_secs(5); const OFF_DELAY: Duration = Duration::from_secs(60); const WAKEUP_EXPIRATION: Duration = Duration::from_secs(1800); const NAP_TIME: Duration = Duration::from_secs(30 * 60); -const RADIATOR_OVERRIDE_MINUTES: i32 = 60; const fn time(hour: i8, minute: i8) -> f64 { hour as f64 + minute as f64 / 60. @@ -76,7 +75,7 @@ pub async fn run( // trace!("Starting radiator override"); // room.start_radiator_override(); } - Trigger::Event(RelevantEvent::Wakeup) => room.to_wakeup().await, + Trigger::Event(RelevantEvent::Wakeup) => room.set_wakeup().await, Trigger::Event(RelevantEvent::Pm2_5(val)) => { room.pm2_5 = Some((val, crate::time::now())) } @@ -205,9 +204,9 @@ async fn handle_light_button(room: &mut Room, event: RelevantEvent) { // Dots2 long: to sleep, wakeup off -> lights off match event { // Light buttons - E::Button(B::BottomLeft(_)) => room.to_sleep_delayed().await, + E::Button(B::BottomLeft(_)) => room.set_sleep_delayed().await, E::PortableButton(P::Dots1ShortRelease) => { - room.to_sleep_immediate().await + room.set_sleep_immediate().await } E::Button(B::BottomMiddle(_)) | E::PortableButton(P::Dots2ShortRelease) => { @@ -215,15 +214,15 @@ async fn handle_light_button(room: &mut Room, event: RelevantEvent) { let now = time::now(); match time(now.hour(), now.minute()) { // rust analyzer seems to think this illegal, its not - T23_00.. | T0_00..T9_00 => room.to_nightlight().await, - _ => room.to_daylight().await, + T23_00.. | T0_00..T9_00 => room.set_nightlight().await, + _ => room.set_daylight().await, } } - E::Button(B::BottomRight(_)) => room.to_override().await, + E::Button(B::BottomRight(_)) => room.set_override().await, E::PortableButton(P::Dots2LongRelease) => { - room.to_sleep_no_wakeup().await + room.set_sleep_no_wakeup().await } - E::PortableButton(P::Dots1LongRelease) => room.to_nightlight().await, + E::PortableButton(P::Dots1LongRelease) => room.set_nightlight().await, _ => (), } } @@ -237,8 +236,8 @@ pub(super) fn is_nap_time() -> bool { pub(crate) fn goal_temp_now() -> f64 { let goals = BTreeMap::from([ - ((00, 00), 18.0), - ((08, 30), 19.0), + ((0, 00), 18.0), + ((8, 30), 19.0), ((10, 00), 20.0), ((11, 00), 20.5), ((12, 00), 21.0), @@ -268,6 +267,8 @@ fn air_filtration_now(pm2_5_measurement: &Option<(f32, Zoned)>) -> Option { if is_expired { Some(default) } else { + // TODO: use pm 2.5 value again + #[allow(clippy::match_single_binding)] match pm2_5 { // 0.0..2.0 => Some(0), // // Don't change anything @@ -280,9 +281,9 @@ fn air_filtration_now(pm2_5_measurement: &Option<(f32, Zoned)>) -> Option { // TODO: move to jobs system and remove update trigger pub(super) fn daylight_now() -> (usize, f64) { let goals = BTreeMap::from([ - ((00, 00), (1800, 0.5)), - ((08, 00), (2000, 0.5)), - ((09, 00), (3800, 1.0)), + ((0, 00), (1800, 0.5)), + ((8, 00), (2000, 0.5)), + ((9, 00), (3800, 1.0)), ((19, 00), (3600, 1.0)), ((19, 30), (3300, 1.0)), ((19, 45), (3000, 1.0)), diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs index 06116658..c445e829 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs @@ -14,7 +14,6 @@ use db::Db; use mpdinterface::MpdInterface; mod db; -mod db2; mod mpdinterface; #[derive(Debug)] @@ -166,6 +165,7 @@ impl AudioController { Ok(()) } + #[allow(unused)] pub fn rescan(&mut self) { info!("Rescanning mpd library"); self.client.rescan().unwrap(); @@ -694,6 +694,7 @@ impl AudioController { } } + #[allow(unused)] pub(crate) fn insert_next(&mut self, song_path: &str) { if let Ok(id) = self.client.push(song_path) { let _ = self.client.prioid(id, 128); diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db.rs index 5886fdb4..013b67c8 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db.rs @@ -144,8 +144,8 @@ mod tests { let playlist = "test_playlist_name"; let last_played = Db::now_timestamp(); - db.store_last_played(&playlist, last_played); - let fetched = db.fetch_last_played(&playlist).unwrap(); + db.store_last_played(playlist, last_played); + let fetched = db.fetch_last_played(playlist).unwrap(); assert_eq!(fetched, last_played); } } diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db2.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db2.rs deleted file mode 100644 index c4f4ccac..00000000 --- a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol/db2.rs +++ /dev/null @@ -1,110 +0,0 @@ -use super::{db::Position, AudioMode}; -use std::time::{SystemTime, UNIX_EPOCH}; - -#[dbstruct::dbstruct(db=sled)] -struct PersistentData { - mode_cur_playlist: HashMap, - playlist_positions: HashMap, - playlist_last_played: HashMap, - current_mode: Option, -} - -pub(crate) struct Db { - database: PersistentData, -} - -impl Db { - pub(crate) fn open(path: &str) -> Self { - Db { - database: PersistentData::new(path.to_owned()+"_test").unwrap(), - } - } - - pub(crate) fn fetch_playlist_name( - &self, - mode: &AudioMode, - ) -> Option { - self.database.mode_cur_playlist().get(mode).unwrap() - } - - pub(crate) fn store_playlist_name( - &self, - mode: &AudioMode, - playlist_name: &str, - ) { - self.database - .mode_cur_playlist() - .insert(mode, &playlist_name.to_owned()) - .unwrap(); - } - - pub(crate) fn fetch_position( - &self, - playlist_name: &str, - ) -> Option { - self.database - .playlist_positions() - .get(&playlist_name.to_owned()) - .unwrap() - } - - pub(crate) fn store_position( - &mut self, - playlist_name: &str, - position: &Position, - ) { - self.database - .playlist_positions() - .insert(&playlist_name.to_owned(), position) - .unwrap(); - } - - pub(crate) fn now_timestamp() -> u64 { - SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_secs() - } - - pub(crate) fn fetch_last_played(&self, playlist: &str) -> Option { - self.database - .playlist_last_played() - .get(&playlist.to_owned()) - .unwrap() - } - - pub(crate) fn store_last_played(&self, playlist: &str, last_played: u64) { - self.database - .playlist_last_played() - .insert(&playlist.to_owned(), &last_played) - .unwrap(); - } - - pub(crate) fn fetch_mode(&self) -> Option { - self.database.current_mode().get().unwrap() - } - - pub(crate) fn store_mode(&self, mode: &AudioMode) { - self.database - .current_mode() - .set(mode) - .unwrap(); - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn fetch_and_store_last_played() { - let db = Db::open("test_db2"); - - let playlist = "test_playlist_name"; - let last_played = Db::now_timestamp(); - - db.store_last_played(&playlist, last_played); - let fetched = db.fetch_last_played(&playlist).unwrap(); - assert_eq!(fetched, last_played); - } -} diff --git a/crates/brain/src/controller/rooms/small_bedroom/filter.rs b/crates/brain/src/controller/rooms/small_bedroom/filter.rs index c23cd768..ad2ee664 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/filter.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/filter.rs @@ -1,5 +1,4 @@ -use tokio::sync::broadcast::{error::RecvError, Receiver}; -use tracing::{trace, warn}; +use tracing::trace; use crate::controller::Event; use protocol::{ diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index 2a169493..d71f5174 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -1,7 +1,6 @@ use std::sync::Arc; use std::time::Duration; -use jiff::civil::Weekday; use jiff::Zoned; use serde::{Deserialize, Serialize}; use tokio::io::AsyncWriteExt; @@ -86,6 +85,8 @@ impl Room { self.radiator_override = None; } + #[allow(unused)] + //TODO: fix radiator override pub(crate) fn start_radiator_override(&mut self) { // Don't set if the radiator resends the manual state if self.radiator_override.is_none() { @@ -95,18 +96,18 @@ impl Room { } } - pub(super) async fn to_sleep_immediate(&mut self) { + pub(super) async fn set_sleep_immediate(&mut self) { self.system.all_lamps_off().await; - self.to_state_cancel_prev(State::Sleep).await; + self.set_state_cancel_prev(State::Sleep).await; } - pub(super) async fn to_sleep_no_wakeup(&mut self) { + pub(super) async fn set_sleep_no_wakeup(&mut self) { self.system.all_lamps_off().await; - self.to_state_cancel_prev(State::SleepNoWakeup).await; + self.set_state_cancel_prev(State::SleepNoWakeup).await; } - pub(super) async fn to_sleep_delayed(&mut self) { - self.to_state_cancel_prev(State::DelayedOff).await; + pub(super) async fn set_sleep_delayed(&mut self) { + self.set_state_cancel_prev(State::DelayedOff).await; self.system.one_lamp_off("small_bedroom:bureau").await; self.system.one_lamp_off("small_bedroom:piano").await; @@ -115,45 +116,45 @@ impl Room { *self.task_handle.lock().await = Some(task_handle); } - pub(super) async fn to_wakeup(&mut self) { + pub(super) async fn set_wakeup(&mut self) { if *self.state.read().await == State::SleepNoWakeup { warn!("Ignoring wakeup because of override"); return; } warn!("Starting wakeup"); - self.to_state_cancel_prev(State::Wakeup).await; + self.set_state_cancel_prev(State::Wakeup).await; let task_handle = task::spawn(self.clone().run_wakeup_then_daylight()); *self.task_handle.lock().await = Some(task_handle); } - pub(super) async fn to_daylight(&mut self) { - self.to_state_cancel_prev(State::Daylight).await; + pub(super) async fn set_daylight(&mut self) { + self.set_state_cancel_prev(State::Daylight).await; self.all_lights_daylight().await; self.system.all_lamps_on().await; } - pub(super) async fn to_nightlight(&mut self) { - self.to_state_cancel_prev(State::Nightlight).await; + pub(super) async fn set_nightlight(&mut self) { + self.set_state_cancel_prev(State::Nightlight).await; self.system .one_lamp_ct("small_bedroom:ceiling", 1800, 0.1) .await; self.system.one_lamp_on("small_bedroom:ceiling").await; } - pub(super) async fn to_override(&mut self) { - self.to_state_cancel_prev(State::Override).await; + pub(super) async fn set_override(&mut self) { + self.set_state_cancel_prev(State::Override).await; self.system.all_lamps_ct(2000, 1.0).await; self.system.all_lamps_on().await; } - async fn to_state_cancel_prev(&mut self, state: State) { + async fn set_state_cancel_prev(&mut self, state: State) { self.cancel_task().await; *self.state.write().await = state.clone(); let _ = self.event_tx.send(Event::StateChangeSB(state)); } - async fn to_state(&mut self, state: State) { + async fn set_state(&mut self, state: State) { *self.state.write().await = state.clone(); let _ = self.event_tx.send(Event::StateChangeSB(state)); } @@ -167,11 +168,11 @@ impl Room { async fn delayed_off_then_sleep(mut self) { sleep(OFF_DELAY).await; self.system.all_lamps_off().await; - self.to_state(State::Sleep).await; + self.set_state(State::Sleep).await; if is_nap_time() { sleep(NAP_TIME).await; - self.to_state(State::Daylight).await; + self.set_state(State::Daylight).await; self.all_lights_daylight().await; self.system.all_lamps_on().await; } @@ -219,7 +220,7 @@ impl Room { } } - self.to_state(State::Daylight).await; + self.set_state(State::Daylight).await; self.all_lights_daylight().await; self.system.all_lamps_on().await; warn!("Wakeup done"); diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index 6e7292a8..391e594a 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -4,18 +4,18 @@ use jiff::{Span, ToSpan, Zoned}; use serde::{Deserialize, Serialize}; use tokio::sync::{broadcast, mpsc, Mutex}; use tokio::{task, time}; -use tracing::{error, info, warn}; +use tracing::{error, info, trace}; use crate::{controller::Event, time::to_next_datetime}; #[derive(thiserror::Error, Debug)] pub(crate) enum Error { #[error("Could not store/edit job on disk")] - DbError(#[from] sled::Error), + Db(#[from] sled::Error), #[error("Could not inform event timer about new job")] - CommError(#[from] mpsc::error::SendError<()>), + Comm(#[from] mpsc::error::SendError<()>), #[error("Dbstruct error")] - DbStructError(#[from] dbstruct::Error), + DbStruct(#[from] dbstruct::Error), // #[error("Dbstruct error")] // DbStructDoubleError(#[from] dbstruct::Error>), } @@ -31,6 +31,7 @@ pub(crate) struct Job { } impl Job { + #[allow(unused)] pub(crate) fn at_next( hour: i8, min: i8, @@ -148,6 +149,8 @@ impl Jobs { self.job_change_tx.send(()).await?; Ok(removed_job) } + + #[allow(unused)] pub(crate) async fn get(&self, id: i64) -> Result, Error> { self.list.lock().await.get_job(id) } @@ -185,7 +188,7 @@ impl JobList { fn peek_next(&mut self) -> Option<(i64, Job)> { let list: Vec<_> = self.jobs().iter().filter_map(|r| r.ok()).collect(); - list.get(0).cloned() + list.first().cloned() } } @@ -224,7 +227,7 @@ async fn event_timer( return; } Err(_) => { - warn!("Sending out event for job {current_job:#?}"); + trace!("Sending out event for job {current_job:#?}"); // time to send the job event event_tx .send(current_job.event.clone()) @@ -239,7 +242,9 @@ async fn event_timer( .add_job(new_job.clone()) .await .unwrap(); - warn!("Added repeat job {new_job:#?} with id {new_id}"); + trace!( + "Added repeat job {new_job:#?} with id {new_id}" + ); } continue; //get next job } diff --git a/crates/data-server/src/api/data_source/reconnecting.rs b/crates/data-server/src/api/data_source/reconnecting.rs index fa4f1692..e167f4a3 100644 --- a/crates/data-server/src/api/data_source/reconnecting.rs +++ b/crates/data-server/src/api/data_source/reconnecting.rs @@ -55,7 +55,7 @@ async fn handle_conn( affectors: Vec, msgs_to_send: mpsc::Receiver, msgs_recieved: Option>, -) -> () { +) { let mut to_send = SendQueue { rx: msgs_to_send, need_retry: VecDeque::new(), diff --git a/crates/protocol/src/large_bedroom/airbox.rs b/crates/protocol/src/large_bedroom/airbox.rs index 1e6c69f9..79306274 100644 --- a/crates/protocol/src/large_bedroom/airbox.rs +++ b/crates/protocol/src/large_bedroom/airbox.rs @@ -252,11 +252,11 @@ pub enum Affector { impl crate::IsSameAs for Affector { fn is_same_as(&self, other: &Self) -> bool { - match (self, other) { - (Affector::FanPower { .. }, Affector::FanPower { .. }) => true, - (Affector::ResetNode, Affector::ResetNode) => true, - _ => false, - } + matches!( + (self, other), + (Affector::FanPower { .. }, Affector::FanPower { .. }) + | (Affector::ResetNode, Affector::ResetNode) + ) } } diff --git a/crates/zigbee-bridge/src/conversion.rs b/crates/zigbee-bridge/src/conversion.rs index 43f3283c..8c7909dd 100644 --- a/crates/zigbee-bridge/src/conversion.rs +++ b/crates/zigbee-bridge/src/conversion.rs @@ -1,8 +1,5 @@ use colorimetry::{cct::CCT, xyz::XYZ}; -// Deviation from black body, must be between -0.05 and 0.05 -const DUV_IKEA: f64 = -0.002; - #[must_use] pub(super) fn mired_to_kelvin(mired: usize) -> usize { 1_000_000 / mired diff --git a/crates/zigbee-bridge/src/lamp/model.rs b/crates/zigbee-bridge/src/lamp/model.rs index ea26db5a..f3eb7fef 100644 --- a/crates/zigbee-bridge/src/lamp/model.rs +++ b/crates/zigbee-bridge/src/lamp/model.rs @@ -75,9 +75,9 @@ impl Model { pub(super) fn color_deviation(&self, color_temp: usize) -> f64 { let temp = color_temp.saturating_add_signed( - color_correction::temp_correction(&self, color_temp), + color_correction::temp_correction(self, color_temp), ); - color_correction::blackbody_deviation(&self, temp) + color_correction::blackbody_deviation(self, temp) } pub(crate) fn is_hue(&self) -> bool { diff --git a/crates/zigbee-bridge/src/parse.rs b/crates/zigbee-bridge/src/parse.rs index 617c4255..7dd486f0 100644 --- a/crates/zigbee-bridge/src/parse.rs +++ b/crates/zigbee-bridge/src/parse.rs @@ -65,7 +65,7 @@ pub(crate) fn portable_button_panel( action_reading_mapping .iter() .find(|(a, _)| action == *a) - .map(|(_, reading)| reading.clone()) + .map(|(_, reading)| *reading) .map(small_bedroom::Reading::PortableButtonPanel) .map(protocol::Reading::SmallBedroom) .ok_or_eyre( @@ -295,10 +295,10 @@ fn json_to_f64(json: &Value) -> Result { } fn json_to_str(json: &Value) -> Result<&str> { - Ok(json + json .as_str() .ok_or_eyre("Must be a string") - .with_note(|| format!("got: {json:?}"))?) + .with_note(|| format!("got: {json:?}")) } fn json_to_f32(json: &Value) -> Result { From 35826b4fb57ff264e4150f07fd0549f1423927aa Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 30 Jun 2025 14:27:07 +0200 Subject: [PATCH 655/687] Disable automatic wakeup and add wakeup to button --- .../src/controller/rooms/small_bedroom.rs | 11 ++--------- .../controller/rooms/small_bedroom/state.rs | 19 ++++++++++++------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index d39641c1..011d796b 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -44,18 +44,12 @@ pub async fn run( let mut room = Room::new(event_tx, system.clone()); let mut next_update = Instant::now() + UPDATE_INTERVAL; - let wakeup_job = - Job::every_day_at(8, 45, Event::WakeupSB, Some(WAKEUP_EXPIRATION)); - let res = system .system .jobs .remove_all_with_event(Event::WakeupSB) .await; trace!("Removing old SB wakeup jobs returned: {res:#?}"); - let res = system.system.jobs.add(wakeup_job.clone()).await; - trace!("Tried to add job for SB wakeup: {wakeup_job:#?}"); - trace!("Jobs returned: {res:#?}"); loop { let get_event = event_rx @@ -210,12 +204,11 @@ async fn handle_light_button(room: &mut Room, event: RelevantEvent) { } E::Button(B::BottomMiddle(_)) | E::PortableButton(P::Dots2ShortRelease) => { - use crate::time; - let now = time::now(); + let now = crate::time::now(); match time(now.hour(), now.minute()) { // rust analyzer seems to think this illegal, its not T23_00.. | T0_00..T9_00 => room.set_nightlight().await, - _ => room.set_daylight().await, + _ => room.set_daylight_or_wakeup().await, } } E::Button(B::BottomRight(_)) => room.set_override().await, diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index d71f5174..366623c1 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -60,7 +60,6 @@ impl Room { } } - pub(super) async fn update_radiator(&mut self) { trace!("Updating radiator"); // trace!( @@ -128,10 +127,16 @@ impl Room { *self.task_handle.lock().await = Some(task_handle); } - pub(super) async fn set_daylight(&mut self) { - self.set_state_cancel_prev(State::Daylight).await; - self.all_lights_daylight().await; - self.system.all_lamps_on().await; + pub(super) async fn set_daylight_or_wakeup(&mut self) { + if *self.state.read().await == State::Sleep + || *self.state.read().await == State::SleepNoWakeup + { + self.set_wakeup().await; + } else { + self.set_state_cancel_prev(State::Daylight).await; + self.all_lights_daylight().await; + self.system.all_lamps_on().await; + } } pub(super) async fn set_nightlight(&mut self) { @@ -180,8 +185,8 @@ impl Room { async fn run_wakeup_then_daylight(mut self) { const LIGHT_NAME: &str = "small_bedroom:ceiling"; - const RUNTIME_MINS: i32 = 20; - const MUSIC_ON_AFTER_MINS: i32 = 13; + const RUNTIME_MINS: i32 = 5; + const MUSIC_ON_AFTER_MINS: i32 = 5; const STEP_SIZE_SECS: i32 = 30; const N_STEPS: i32 = RUNTIME_MINS * 60 / STEP_SIZE_SECS; From 5d853fc90f3fa499e7a10a3da408d125312b3220 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 19 Jul 2025 18:01:02 +0200 Subject: [PATCH 656/687] Set small bedroom airbox to quieter --- crates/brain/src/controller/rooms/small_bedroom.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 011d796b..70c26056 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -247,7 +247,7 @@ pub(crate) fn goal_temp_now() -> f64 { fn air_filtration_now(pm2_5_measurement: &Option<(f32, Zoned)>) -> Option { let pm2_5_expiration = 10.minutes(); let goals = - BTreeMap::from([((00, 00), 80), ((18, 00), 100), ((22, 30), 80)]); + BTreeMap::from([((00, 00), 80), ((18, 00), 80), ((22, 30), 80)]); let default = goal_now(goals, 80); From 8fd3675d89639451e99e568f7b30ee3c3996c20f Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 21 Jul 2025 01:28:20 +0200 Subject: [PATCH 657/687] limit max packet size to nodes --- Cargo.lock | 18 +++++-- crates/data-server/Cargo.toml | 2 +- crates/data-server/src/server/data_source.rs | 49 ++++++++++++++++---- 3 files changed, 55 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c26de4ff..fcfe89fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -654,7 +654,7 @@ dependencies = [ "rpc", "serde", "slotmap", - "socket2", + "socket2 0.6.0", "thiserror 2.0.12", "tokio", "tokio-serde", @@ -1744,9 +1744,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.171" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libm" @@ -3138,6 +3138,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "spidev" version = "0.6.0" @@ -3371,7 +3381,7 @@ dependencies = [ "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.5.8", "tokio-macros", "windows-sys 0.52.0", ] diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index 173c3985..c1b41ef6 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -28,7 +28,7 @@ serde.workspace = true futures-concurrency = { workspace = true } slotmap = "1.0.7" tracing-futures = "0.2.5" -socket2 = "0.5.7" +socket2 = { version = "0.6.0", features = ["all"] } governor.workspace = true [dev-dependencies] diff --git a/crates/data-server/src/server/data_source.rs b/crates/data-server/src/server/data_source.rs index 5765e4cd..c4e8f815 100644 --- a/crates/data-server/src/server/data_source.rs +++ b/crates/data-server/src/server/data_source.rs @@ -8,10 +8,9 @@ use futures_concurrency::future::Race; use governor::clock::Clock; use governor::{Quota, RateLimiter}; use protocol::Affector; -use socket2::TcpKeepalive; +use socket2::{Socket, TcpKeepalive}; use tokio::io::{AsyncBufReadExt, BufReader}; use tokio::net::tcp::OwnedReadHalf; -use tokio::net::TcpListener; use tokio::net::TcpStream; use tokio::sync::mpsc::Sender; @@ -28,17 +27,40 @@ pub async fn handle_nodes( share: &Sender, registar: Registar, ) -> Result<()> { - let listener = TcpListener::bind(addr) - .await + let socket = + Socket::new(socket2::Domain::IPV4, socket2::Type::STREAM, None)?; + socket + .set_tcp_nodelay(true) + .expect("should be able to disable nagle algorithm"); + socket + .set_tcp_mss(2048) + .expect("should be able to set max segment size for outgoing packets"); + socket + .bind(&addr.into()) + .wrap_err("Could not bind to addr for new subscribers") + .with_note(|| format!("trying to listen on: {addr}"))?; + socket + .listen(128) .wrap_err("Could not start listening for new subscribers") .with_note(|| format!("trying to listen on: {addr}"))?; + let listener: std::net::TcpListener = socket.into(); + listener + .set_nonblocking(true) + .expect("Should be able to set nonblocking mode"); + let listener = tokio::net::TcpListener::from_std(listener) + .expect("Conversion from std to tokio listener should always succeed"); loop { let res = listener.accept().await; match res { Ok((stream, source)) => { info!("new data source connected from: {source}"); - tokio::spawn(handle_node(stream, source, share.clone(), registar.clone())); + tokio::spawn(handle_node( + stream, + source, + share.clone(), + registar.clone(), + )); } Err(e) => { warn!("new connection failed: {e}"); @@ -109,23 +131,32 @@ async fn handle_node( warn!("node removed (lost connection)"); } -async fn handshake(reader: &mut BufReader) -> Result, String> { +async fn handshake( + reader: &mut BufReader, +) -> Result, String> { let mut buf = Vec::new(); let msg = match read_and_decode_packet(reader, &mut buf).await { Ok(decoded) => decoded, Err(e) => { - return Err(format!("Error while reading and decoding packet: {e}")); + return Err(format!( + "Error while reading and decoding packet: {e}" + )); } }; let protocol::Msg::AffectorList(list) = msg else { - return Err("Must get affector list as first message (handshake)".to_owned()); + return Err( + "Must get affector list as first message (handshake)".to_owned() + ); }; Ok(list.values.to_vec()) } #[instrument(skip_all)] -async fn receive_and_spread_updates(mut reader: BufReader, queue: Sender) { +async fn receive_and_spread_updates( + mut reader: BufReader, + queue: Sender, +) { let quota = Quota::per_second(NonZeroU32::new(40).unwrap()) .allow_burst(NonZeroU32::new(200u32).unwrap()); let limiter = RateLimiter::direct(quota); From b90fc5833ecea2711c172188babe595bb1405325 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Mon, 21 Jul 2025 12:45:15 +0200 Subject: [PATCH 658/687] update embassy to latest git --- nodes/embassy/Cargo.lock | 166 ++++++++++-------- nodes/embassy/Cargo.toml | 30 ++-- nodes/embassy/bed-lb/src/rgb_led.rs | 23 ++- nodes/embassy/bed-lb/src/rng.rs | 2 +- nodes/embassy/bed-lb/src/sensors.rs | 8 +- nodes/embassy/bed-sb/src/sensors.rs | 4 +- nodes/embassy/sensors/src/drivers.rs | 5 +- .../sensors/src/drivers/driver_impl_bme680.rs | 3 +- .../src/drivers/driver_impl_max44009.rs | 3 +- .../src/drivers/driver_impl_nau7802.rs | 5 +- .../sensors/src/drivers/driver_impl_sht31.rs | 3 +- 11 files changed, 140 insertions(+), 112 deletions(-) diff --git a/nodes/embassy/Cargo.lock b/nodes/embassy/Cargo.lock index 73272af0..8f33d88a 100644 --- a/nodes/embassy/Cargo.lock +++ b/nodes/embassy/Cargo.lock @@ -100,7 +100,7 @@ name = "bosch-bme680" version = "1.0.2" dependencies = [ "bitfield 0.14.0", - "defmt", + "defmt 0.3.100", "embedded-hal 1.0.0", "embedded-hal-async", ] @@ -111,7 +111,7 @@ version = "0.2.0" dependencies = [ "cortex-m", "cortex-m-rt", - "defmt", + "defmt 1.0.1", "defmt-rtt", "embassy-embedded-hal", "embassy-executor", @@ -240,9 +240,18 @@ dependencies = [ [[package]] name = "defmt" -version = "0.3.10" +version = "0.3.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f6162c53f659f65d00619fe31f14556a6e9f8752ccc4a41bd177ffcf3d6130" +checksum = "f0963443817029b2024136fc4dd07a5107eb8f977eaf18fcd1fdeb11306b64ad" +dependencies = [ + "defmt 1.0.1", +] + +[[package]] +name = "defmt" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "548d977b6da32fa1d1fda2876453da1e7df63ad0304c8b3dae4dbe7b96f39b78" dependencies = [ "bitflags 1.3.2", "defmt-macros", @@ -250,9 +259,9 @@ dependencies = [ [[package]] name = "defmt-macros" -version = "0.4.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d135dd939bad62d7490b0002602d35b358dce5fd9233a709d3c1ef467d4bde6" +checksum = "3d4fc12a85bcf441cfe44344c4b72d58493178ce635338a3f3b78943aceb258e" dependencies = [ "defmt-parser", "proc-macro-error2", @@ -263,21 +272,21 @@ dependencies = [ [[package]] name = "defmt-parser" -version = "0.4.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3983b127f13995e68c1e29071e5d115cd96f215ccb5e6812e3728cd6f92653b3" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" dependencies = [ "thiserror", ] [[package]] name = "defmt-rtt" -version = "0.4.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab697b3dbbc1750b7c8b821aa6f6e7f2480b47a99bc057a2ed7b170ebef0c51" +checksum = "b2cac3b8a5644a9e02b75085ebad3b6deafdbdbdec04bb25086523828aa4dfd1" dependencies = [ "critical-section", - "defmt", + "defmt 1.0.1", ] [[package]] @@ -291,10 +300,10 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" -version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" +version = "0.3.1" +source = "git+https://github.com/embassy-rs/embassy?rev=2cae242#2cae242f51cd1553ca9deb1cfd73daed606c5476" dependencies = [ - "defmt", + "defmt 1.0.1", "embassy-futures", "embassy-hal-internal", "embassy-sync", @@ -310,11 +319,11 @@ dependencies = [ [[package]] name = "embassy-executor" version = "0.7.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" +source = "git+https://github.com/embassy-rs/embassy?rev=2cae242#2cae242f51cd1553ca9deb1cfd73daed606c5476" dependencies = [ "cortex-m", "critical-section", - "defmt", + "defmt 1.0.1", "document-features", "embassy-executor-macros", ] @@ -322,7 +331,7 @@ dependencies = [ [[package]] name = "embassy-executor-macros" version = "0.6.2" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" +source = "git+https://github.com/embassy-rs/embassy?rev=2cae242#2cae242f51cd1553ca9deb1cfd73daed606c5476" dependencies = [ "darling", "proc-macro2", @@ -333,25 +342,25 @@ dependencies = [ [[package]] name = "embassy-futures" version = "0.1.1" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" +source = "git+https://github.com/embassy-rs/embassy?rev=2cae242#2cae242f51cd1553ca9deb1cfd73daed606c5476" [[package]] name = "embassy-hal-internal" -version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" +version = "0.3.0" +source = "git+https://github.com/embassy-rs/embassy?rev=2cae242#2cae242f51cd1553ca9deb1cfd73daed606c5476" dependencies = [ "cortex-m", "critical-section", - "defmt", + "defmt 1.0.1", "num-traits", ] [[package]] name = "embassy-net" version = "0.7.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" +source = "git+https://github.com/embassy-rs/embassy?rev=2cae242#2cae242f51cd1553ca9deb1cfd73daed606c5476" dependencies = [ - "defmt", + "defmt 1.0.1", "document-features", "embassy-net-driver", "embassy-sync", @@ -366,15 +375,15 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" +source = "git+https://github.com/embassy-rs/embassy?rev=2cae242#2cae242f51cd1553ca9deb1cfd73daed606c5476" dependencies = [ - "defmt", + "defmt 1.0.1", ] [[package]] name = "embassy-net-driver-channel" -version = "0.3.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" +version = "0.3.1" +source = "git+https://github.com/embassy-rs/embassy?rev=2cae242#2cae242f51cd1553ca9deb1cfd73daed606c5476" dependencies = [ "embassy-futures", "embassy-net-driver", @@ -384,9 +393,9 @@ dependencies = [ [[package]] name = "embassy-net-wiznet" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" +source = "git+https://github.com/embassy-rs/embassy?rev=2cae242#2cae242f51cd1553ca9deb1cfd73daed606c5476" dependencies = [ - "defmt", + "defmt 1.0.1", "embassy-futures", "embassy-net-driver-channel", "embassy-time", @@ -397,7 +406,7 @@ dependencies = [ [[package]] name = "embassy-stm32" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" +source = "git+https://github.com/embassy-rs/embassy?rev=2cae242#2cae242f51cd1553ca9deb1cfd73daed606c5476" dependencies = [ "aligned", "bit_field", @@ -407,7 +416,7 @@ dependencies = [ "cortex-m", "cortex-m-rt", "critical-section", - "defmt", + "defmt 1.0.1", "document-features", "embassy-embedded-hal", "embassy-futures", @@ -432,7 +441,8 @@ dependencies = [ "nb 1.1.0", "proc-macro2", "quote", - "rand_core", + "rand_core 0.6.4", + "rand_core 0.9.3", "sdio-host", "static_assertions", "stm32-fmc", @@ -443,38 +453,38 @@ dependencies = [ [[package]] name = "embassy-sync" -version = "0.6.2" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" +version = "0.7.0" +source = "git+https://github.com/embassy-rs/embassy?rev=2cae242#2cae242f51cd1553ca9deb1cfd73daed606c5476" dependencies = [ "cfg-if", "critical-section", - "defmt", + "defmt 1.0.1", "embedded-io-async", + "futures-core", "futures-sink", - "futures-util", "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "embassy-time" version = "0.4.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" +source = "git+https://github.com/embassy-rs/embassy?rev=2cae242#2cae242f51cd1553ca9deb1cfd73daed606c5476" dependencies = [ "cfg-if", "critical-section", - "defmt", + "defmt 1.0.1", "document-features", "embassy-time-driver", "embedded-hal 0.2.7", "embedded-hal 1.0.0", "embedded-hal-async", - "futures-util", + "futures-core", ] [[package]] name = "embassy-time-driver" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" +source = "git+https://github.com/embassy-rs/embassy?rev=2cae242#2cae242f51cd1553ca9deb1cfd73daed606c5476" dependencies = [ "document-features", ] @@ -482,7 +492,7 @@ dependencies = [ [[package]] name = "embassy-time-queue-utils" version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" +source = "git+https://github.com/embassy-rs/embassy?rev=2cae242#2cae242f51cd1553ca9deb1cfd73daed606c5476" dependencies = [ "embassy-executor", "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -490,14 +500,15 @@ dependencies = [ [[package]] name = "embassy-usb" -version = "0.4.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" +version = "0.5.0" +source = "git+https://github.com/embassy-rs/embassy?rev=2cae242#2cae242f51cd1553ca9deb1cfd73daed606c5476" dependencies = [ - "defmt", + "defmt 1.0.1", "embassy-futures", "embassy-net-driver-channel", "embassy-sync", "embassy-usb-driver", + "embedded-io-async", "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "ssmarshal", "usbd-hid", @@ -505,19 +516,20 @@ dependencies = [ [[package]] name = "embassy-usb-driver" -version = "0.1.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=2cae242#2cae242f51cd1553ca9deb1cfd73daed606c5476" dependencies = [ - "defmt", + "defmt 1.0.1", + "embedded-io-async", ] [[package]] name = "embassy-usb-synopsys-otg" version = "0.2.0" -source = "git+https://github.com/embassy-rs/embassy?rev=fecb7a2#fecb7a2b2b6f1953a2fe57557cb83d063ab5eea4" +source = "git+https://github.com/embassy-rs/embassy?rev=2cae242#2cae242f51cd1553ca9deb1cfd73daed606c5476" dependencies = [ "critical-section", - "defmt", + "defmt 1.0.1", "embassy-sync", "embassy-usb-driver", ] @@ -547,7 +559,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" dependencies = [ - "defmt", + "defmt 0.3.100", ] [[package]] @@ -556,7 +568,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" dependencies = [ - "defmt", + "defmt 0.3.100", "embedded-hal 1.0.0", ] @@ -567,7 +579,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d3980bf28e8577db59fe2bdb3df868a419469d2cecb363644eea2b6f7797669" dependencies = [ "critical-section", - "defmt", + "defmt 0.3.100", "embedded-hal 1.0.0", "embedded-hal-async", "portable-atomic", @@ -589,7 +601,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" dependencies = [ - "defmt", + "defmt 0.3.100", ] [[package]] @@ -598,7 +610,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" dependencies = [ - "defmt", + "defmt 0.3.100", "embedded-io", ] @@ -768,7 +780,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" dependencies = [ - "defmt", + "defmt 0.3.100", "hash32 0.3.1", "serde", "stable_deref_trait", @@ -801,7 +813,7 @@ version = "0.2.0" dependencies = [ "cortex-m", "cortex-m-rt", - "defmt", + "defmt 1.0.1", "defmt-rtt", "embassy-embedded-hal", "embassy-executor", @@ -857,7 +869,7 @@ name = "max44009" version = "0.2.0" source = "git+https://github.com/dvdsk/max44009-rs#7b7df2e3173476c250fca3eb242f0dd366857599" dependencies = [ - "defmt", + "defmt 0.3.100", "embedded-hal-async", ] @@ -865,7 +877,7 @@ dependencies = [ name = "mhzx" version = "0.3.0" dependencies = [ - "defmt", + "defmt 0.3.100", "embedded-io-async", "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "postcard", @@ -877,7 +889,7 @@ name = "nau7802-async" version = "0.2.0" dependencies = [ "byteorder", - "defmt", + "defmt 0.3.100", "embedded-hal-async", "postcard", "serde", @@ -915,12 +927,12 @@ checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" [[package]] name = "panic-probe" -version = "0.3.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4047d9235d1423d66cc97da7d07eddb54d4f154d6c13805c6d0793956f4f25b0" +checksum = "fd402d00b0fb94c5aee000029204a46884b1262e0c443f166d86d2c0747e1a1a" dependencies = [ "cortex-m", - "defmt", + "defmt 1.0.1", ] [[package]] @@ -948,7 +960,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8" dependencies = [ "cobs", - "defmt", + "defmt 0.3.100", "heapless 0.7.17", "postcard-derive", "serde", @@ -1000,7 +1012,7 @@ dependencies = [ name = "protocol" version = "0.1.0" dependencies = [ - "defmt", + "defmt 0.3.100", "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "postcard", "serde", @@ -1022,7 +1034,7 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -1031,6 +1043,12 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" + [[package]] name = "rustc_version" version = "0.2.3" @@ -1063,9 +1081,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sdio-host" -version = "0.5.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93c025f9cfe4c388c328ece47d11a54a823da3b5ad0370b22d95ad47137f85a" +checksum = "b328e2cb950eeccd55b7f55c3a963691455dcd044cfb5354f0c5e68d2c2d6ee2" [[package]] name = "semver" @@ -1093,7 +1111,7 @@ name = "sensors" version = "0.1.0" dependencies = [ "bosch-bme680", - "defmt", + "defmt 1.0.1", "embassy-embedded-hal", "embassy-stm32", "embassy-sync", @@ -1134,7 +1152,7 @@ version = "0.3.1" source = "git+https://github.com/dvdsk/SHT31-rs#a7b6bd94fb137e16bf326eff5fb591624369a2cf" dependencies = [ "crc", - "defmt", + "defmt 0.3.100", "embedded-hal-async", "postcard", ] @@ -1145,7 +1163,7 @@ version = "0.2.0" dependencies = [ "cortex-m", "cortex-m-rt", - "defmt", + "defmt 1.0.1", "defmt-rtt", "embassy-embedded-hal", "embassy-executor", @@ -1175,7 +1193,7 @@ dependencies = [ "bitflags 1.3.2", "byteorder", "cfg-if", - "defmt", + "defmt 0.3.100", "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "managed", ] @@ -1193,7 +1211,7 @@ dependencies = [ name = "sps30-async" version = "0.3.0" dependencies = [ - "defmt", + "defmt 0.3.100", "embedded-hal-async", "embedded-io-async", "futures", @@ -1245,7 +1263,7 @@ dependencies = [ [[package]] name = "stm32-metapac" version = "16.0.0" -source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-4a964af03b298de30ff9f84fcfa890bcab4ce609#aee345990e1a14efd018877b52aff1d63e16bb7f" +source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-dded8a33a460ae0eb182aee3ccb048beb659982b#6ca0dbc4fb27b3482642d2db484633be3298b528" dependencies = [ "cortex-m", "cortex-m-rt", @@ -1331,7 +1349,7 @@ checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" name = "usb-bridge-client" version = "0.1.0" dependencies = [ - "defmt", + "defmt 1.0.1", "embassy-sync", "embassy-usb", "heapless 0.8.0 (git+https://github.com/rust-embedded/heapless?rev=0ebca23)", diff --git a/nodes/embassy/Cargo.toml b/nodes/embassy/Cargo.toml index 624a6dc1..41ef0354 100644 --- a/nodes/embassy/Cargo.toml +++ b/nodes/embassy/Cargo.toml @@ -12,14 +12,14 @@ embassy-stm32 = { version = "0.2.0", features = [ "defmt", "stm32f401cc", "unstable-pac", "memory-x", "time-driver-tim9", "time", "exti" ] } embassy-net = { version = "0.7.0", features = ["defmt", "proto-ipv4", "tcp", "dhcpv4","medium-ethernet"] } embassy-net-wiznet = { version = "0.2.0", features = ["defmt"] } -embassy-sync = { version = "0.6.2", features = ["defmt"] } +embassy-sync = { version = "0.7", features = ["defmt"] } embassy-executor = { version = "0.7", features = ["arch-cortex-m", "executor-thread", "defmt", "executor-interrupt"] } embassy-embedded-hal = { version = "0.3.0" } embassy-time = { version = "0.4", features = ["defmt", "defmt-timestamp-uptime-ms", "tick-hz-32_768"] } embassy-futures = { version = "0.1.1"} -embassy-usb = { version = "0.4.0", features = ["defmt"] } +embassy-usb = { version = "0.5.0", features = ["defmt"] } embedded-hal = "1.0.0" embedded-hal-async = "1.0" @@ -29,21 +29,21 @@ futures = { version = "0.3.31", default-features = false, features = ["async-awa heapless = { git = "https://github.com/rust-embedded/heapless", version = "0.8", rev = "0ebca23", default-features = false } -defmt = "0.3" -defmt-rtt = "0.4" -panic-probe = { version = "0.3", features = ["print-defmt"] } +defmt = "1.0" +defmt-rtt = "1.0" +panic-probe = { version = "1.0", features = ["print-defmt"] } [patch.crates-io] -embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } -embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "fecb7a2" } +embassy-stm32 = {git = "https://github.com/embassy-rs/embassy", rev = "2cae242" } +embassy-net = {git = "https://github.com/embassy-rs/embassy", rev = "2cae242" } +embassy-net-wiznet = {git = "https://github.com/embassy-rs/embassy", rev = "2cae242" } +embassy-sync = {git = "https://github.com/embassy-rs/embassy", rev = "2cae242" } +embassy-executor = {git = "https://github.com/embassy-rs/embassy", rev = "2cae242" } +embassy-embedded-hal = {git = "https://github.com/embassy-rs/embassy", rev = "2cae242" } +embassy-futures = {git = "https://github.com/embassy-rs/embassy", rev = "2cae242" } +embassy-time = {git = "https://github.com/embassy-rs/embassy", rev = "2cae242" } +embassy-time-driver = {git = "https://github.com/embassy-rs/embassy", rev = "2cae242" } +embassy-usb = {git = "https://github.com/embassy-rs/embassy", rev = "2cae242" } # embassy-stm32 = {path = "/home/david/Documents/embassy/embassy-stm32" } # embassy-net = {path = "/home/david/Documents/embassy/embassy-net" } diff --git a/nodes/embassy/bed-lb/src/rgb_led.rs b/nodes/embassy/bed-lb/src/rgb_led.rs index 735ca4a3..43874cdc 100644 --- a/nodes/embassy/bed-lb/src/rgb_led.rs +++ b/nodes/embassy/bed-lb/src/rgb_led.rs @@ -2,10 +2,10 @@ use embassy_executor::task; use embassy_stm32::gpio::OutputType; use embassy_stm32::peripherals::{PB13, PB14, PB15, TIM1}; use embassy_stm32::time::khz; -use embassy_stm32::timer; use embassy_stm32::timer::complementary_pwm::{ ComplementaryPwm, ComplementaryPwmPin, }; +use embassy_stm32::{timer, Peri}; use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; use embassy_sync::channel::Channel; @@ -17,12 +17,17 @@ struct RgbLed { } impl RgbLed { - fn new(timer: TIM1, b: PB15, r: PB14, g: PB13) -> Self { + fn new( + timer: Peri<'static, TIM1>, + b: Peri<'static, PB15>, + r: Peri<'static, PB14>, + g: Peri<'static, PB13>, + ) -> Self { use embassy_stm32::timer::Channel; - let b = ComplementaryPwmPin::new_ch3(b, OutputType::PushPull); - let r = ComplementaryPwmPin::new_ch2(r, OutputType::PushPull); - let g = ComplementaryPwmPin::new_ch1(g, OutputType::PushPull); + let b = ComplementaryPwmPin::new(b, OutputType::PushPull); + let r = ComplementaryPwmPin::new(r, OutputType::PushPull); + let g = ComplementaryPwmPin::new(g, OutputType::PushPull); let mut pwm = ComplementaryPwm::new( timer, @@ -127,10 +132,10 @@ fn lookup_bri(lux: f32) -> f32 { #[task] pub(crate) async fn control_leds( - timer: TIM1, - r: PB14, - g: PB13, - b: PB15, + timer: Peri<'static, TIM1>, + r: Peri<'static, PB14>, + g: Peri<'static, PB13>, + b: Peri<'static, PB15>, led_comms: &'static Channel, ) { let mut led = RgbLed::new(timer, b, r, g); diff --git a/nodes/embassy/bed-lb/src/rng.rs b/nodes/embassy/bed-lb/src/rng.rs index 8770b4e1..f489557d 100644 --- a/nodes/embassy/bed-lb/src/rng.rs +++ b/nodes/embassy/bed-lb/src/rng.rs @@ -6,7 +6,7 @@ use embassy_stm32::adc::{Adc, Temperature, VrefInt}; /// #Warning /// Should only be called before async tasks are spawned. This takes a lot of /// time to run and will disturb any async task running. -pub async fn generate_seed_blocking(adc: ADC1) -> u64 { +pub async fn generate_seed_blocking(adc: embassy_stm32::Peri<'_, ADC1>) -> u64 { let mut adc = Adc::new(adc); let mut vrefint = adc.enable_vrefint(); diff --git a/nodes/embassy/bed-lb/src/sensors.rs b/nodes/embassy/bed-lb/src/sensors.rs index 833770ca..04565f91 100644 --- a/nodes/embassy/bed-lb/src/sensors.rs +++ b/nodes/embassy/bed-lb/src/sensors.rs @@ -1,7 +1,7 @@ use defmt::info; use embassy_executor::task; use embassy_futures::join; -use embassy_stm32::i2c::I2c; +use embassy_stm32::i2c::{I2c, Master}; use embassy_stm32::mode::{Async, Blocking}; use embassy_stm32::usart::Uart; use embassy_sync::blocking_mutex::raw::NoopRawMutex; @@ -27,9 +27,9 @@ fn local_dev(dev: protocol::large_bedroom::bed::Device) -> protocol::Device { pub async fn init_then_measure( orderers: &'static slow::DriverOrderers, rgb_led: rgb_led::LedHandle, - i2c_1: Mutex>, - i2c_2: Mutex>, - i2c_3: Mutex>, + i2c_1: Mutex>, + i2c_2: Mutex>, + i2c_3: Mutex>, usart_mhz: Uart<'static, Async>, usart_sps: Uart<'static, Async>, buttons: ButtonInputs, diff --git a/nodes/embassy/bed-sb/src/sensors.rs b/nodes/embassy/bed-sb/src/sensors.rs index 5b8d7789..85d5d80d 100644 --- a/nodes/embassy/bed-sb/src/sensors.rs +++ b/nodes/embassy/bed-sb/src/sensors.rs @@ -24,8 +24,8 @@ fn local_dev(dev: protocol::small_bedroom::bed::Device) -> protocol::Device { pub async fn init_then_measure( publish: &Queues, orderers: &slow::DriverOrderers, - i2c_1: Mutex>, - i2c_3: Mutex>, + i2c_1: Mutex>, + i2c_3: Mutex>, usart_mhz: Uart<'static, Async>, usart_sps: Uart<'static, Async>, buttons: ButtonInputs, diff --git a/nodes/embassy/sensors/src/drivers.rs b/nodes/embassy/sensors/src/drivers.rs index d5d34165..0bcd8704 100644 --- a/nodes/embassy/sensors/src/drivers.rs +++ b/nodes/embassy/sensors/src/drivers.rs @@ -13,14 +13,15 @@ use reinit_on_error::ReInitOnErrorDriver; use embassy_embedded_hal::shared_bus; use embassy_stm32::i2c::I2c; +use embassy_stm32::i2c::Master; use embassy_stm32::mode::{Async, Blocking}; use embassy_stm32::usart::{RingBufferedUartRx, UartTx}; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use shared_bus::asynch::i2c::I2cDevice; pub type ConcreteSharedI2c<'a> = - I2cDevice<'a, NoopRawMutex, I2c<'static, Async>>; -pub type ConcreteBlockingI2c<'a> = &'a I2cWrapper>; + I2cDevice<'a, NoopRawMutex, I2c<'static, Async, Master>>; +pub type ConcreteBlockingI2c<'a> = &'a I2cWrapper>; pub type ConcreteTx<'a> = UartTx<'a, Async>; pub type ConcreteRx<'a> = RingBufferedUartRx<'a>; diff --git a/nodes/embassy/sensors/src/drivers/driver_impl_bme680.rs b/nodes/embassy/sensors/src/drivers/driver_impl_bme680.rs index f56f3411..f25d7cc5 100644 --- a/nodes/embassy/sensors/src/drivers/driver_impl_bme680.rs +++ b/nodes/embassy/sensors/src/drivers/driver_impl_bme680.rs @@ -1,6 +1,7 @@ use bosch_bme680::Bme680; use embassy_embedded_hal::shared_bus; use embassy_stm32::i2c::I2c; +use embassy_stm32::i2c::Master; use embassy_stm32::mode::Async; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; @@ -12,7 +13,7 @@ use crate::ReInitableDriver; use super::ConcreteSharedI2c; impl<'a> ReInitableDriver for Bme680, Delay> { - type Parts = &'a Mutex>; + type Parts = &'a Mutex>; type Measurement = bosch_bme680::MeasurementData; async fn init(parts: Self::Parts) -> Result { diff --git a/nodes/embassy/sensors/src/drivers/driver_impl_max44009.rs b/nodes/embassy/sensors/src/drivers/driver_impl_max44009.rs index e0a7c36c..05d33bfd 100644 --- a/nodes/embassy/sensors/src/drivers/driver_impl_max44009.rs +++ b/nodes/embassy/sensors/src/drivers/driver_impl_max44009.rs @@ -1,6 +1,7 @@ use embassy_embedded_hal::shared_bus; use embassy_stm32::i2c::I2c; use embassy_stm32::mode::Async; +use embassy_stm32::i2c::Master; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; use max44009::{Max44009, SlaveAddr}; @@ -11,7 +12,7 @@ use crate::ReInitableDriver; use super::ConcreteSharedI2c; impl<'a> ReInitableDriver for Max44009> { - type Parts = &'a Mutex>; + type Parts = &'a Mutex>; type Measurement = f32; async fn init(parts: Self::Parts) -> Result { diff --git a/nodes/embassy/sensors/src/drivers/driver_impl_nau7802.rs b/nodes/embassy/sensors/src/drivers/driver_impl_nau7802.rs index e4206886..08db9a65 100644 --- a/nodes/embassy/sensors/src/drivers/driver_impl_nau7802.rs +++ b/nodes/embassy/sensors/src/drivers/driver_impl_nau7802.rs @@ -1,5 +1,6 @@ use embassy_embedded_hal::shared_bus; use embassy_stm32::i2c::I2c; +use embassy_stm32::i2c::Master; use embassy_stm32::mode::{Async, Blocking}; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; @@ -12,7 +13,7 @@ use crate::ReInitableDriver; use super::{ConcreteBlockingI2c, ConcreteSharedI2c, I2cWrapper}; impl<'a> ReInitableDriver for Nau7802, Delay> { - type Parts = &'a Mutex>; + type Parts = &'a Mutex>; type Measurement = u32; async fn init(parts: Self::Parts) -> Result { @@ -31,7 +32,7 @@ impl<'a> ReInitableDriver for Nau7802, Delay> { } impl<'a> ReInitableDriver for Nau7802, Delay> { - type Parts = &'a I2cWrapper>; + type Parts = &'a I2cWrapper>; type Measurement = u32; async fn init(parts: Self::Parts) -> Result { diff --git a/nodes/embassy/sensors/src/drivers/driver_impl_sht31.rs b/nodes/embassy/sensors/src/drivers/driver_impl_sht31.rs index a279f8b7..e5b7cd65 100644 --- a/nodes/embassy/sensors/src/drivers/driver_impl_sht31.rs +++ b/nodes/embassy/sensors/src/drivers/driver_impl_sht31.rs @@ -1,6 +1,7 @@ use embassy_embedded_hal::shared_bus; use embassy_stm32::i2c::I2c; use embassy_stm32::mode::Async; +use embassy_stm32::i2c::Master; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::mutex::Mutex; use embassy_time::{Delay, Timer}; @@ -13,7 +14,7 @@ use crate::ReInitableDriver; use super::ConcreteSharedI2c; impl<'a> ReInitableDriver for SHT31> { - type Parts = &'a Mutex>; + type Parts = &'a Mutex>; type Measurement = sht31::Reading; async fn init(parts: Self::Parts) -> Result { From 4fa7ebdc47c0503610bc3715042bc6e295183abe Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 1 Aug 2025 13:28:56 +0200 Subject: [PATCH 659/687] Change button functionality for small bedroom --- .../src/controller/rooms/small_bedroom.rs | 58 +++++++++---------- .../controller/rooms/small_bedroom/state.rs | 46 +++++++++++---- 2 files changed, 64 insertions(+), 40 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 70c26056..16c091a4 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -17,7 +17,6 @@ use self::state::Room; pub(crate) use self::state::State; use crate::controller::rooms::common::RecvFiltered; use crate::controller::{Event, RestrictedSystem}; -use crate::input::jobs::Job; use crate::time; mod audiocontrol; @@ -33,8 +32,8 @@ const fn time(hour: i8, minute: i8) -> f64 { hour as f64 + minute as f64 / 60. } const T0_00: f64 = time(0, 0); -const T9_00: f64 = time(9, 0); -const T23_00: f64 = time(23, 0); +const T10_00: f64 = time(10, 0); +const T21_00: f64 = time(21, 0); pub async fn run( mut event_rx: broadcast::Receiver, @@ -103,13 +102,12 @@ async fn handle_button(room: &mut Room, event: RelevantEvent) { | P::VolumeUp | P::VolumeUpHold | P::VolumeDown - | P::VolumeDownHold => { - handle_audio_button(room, event).await; - } - P::Dots1ShortRelease + | P::VolumeDownHold | P::Dots1LongRelease - | P::Dots2ShortRelease | P::Dots2LongRelease => { + handle_audio_button(room, event).await; + } + P::Dots1ShortRelease | P::Dots2ShortRelease => { handle_light_button(room, event).await; } b => info!("Pressed unimplemented button: {b:?}"), @@ -139,6 +137,7 @@ async fn handle_audio_button(room: &mut Room, button_event: RelevantEvent) { (A::Podcast, E::Button(B::TopLeft(press))) if !press.is_long() => { audio.rewind() } + (A::Podcast, E::PortableButton(P::TrackPrevious)) => audio.rewind(), // Music, Singing, Meditation forward (short) = next ( @@ -153,6 +152,7 @@ async fn handle_audio_button(room: &mut Room, button_event: RelevantEvent) { (A::Podcast, E::Button(B::TopRight(press))) if !press.is_long() => { audio.skip() } + (A::Podcast, E::PortableButton(P::TrackNext)) => audio.skip(), (_, E::Button(B::TopMiddle(press))) if !press.is_long() => { audio.toggle_playback() @@ -162,23 +162,25 @@ async fn handle_audio_button(room: &mut Room, button_event: RelevantEvent) { audio.prev_playlist(); audio.play(ForceRewind::No) } + (_, E::Button(B::TopRight(press))) if press.is_long() => { audio.next_playlist(); audio.play(ForceRewind::No) } + (_, E::PortableButton(P::Dots1LongRelease)) => { + audio.next_playlist(); + audio.play(ForceRewind::No) + } + (_, E::Button(B::TopMiddle(press))) if press.is_long() => { audio.next_mode(); audio.play(ForceRewind::No) } + (_, E::PortableButton(P::Dots2LongRelease)) => { + audio.next_mode(); + audio.play(ForceRewind::No) + } (_, E::PortableButton(P::PlayPause)) => { - if AudioController::is_meditation_time() { - audio - .go_to_mode_playlist( - &A::Meditation, - "meditation_yoga-nidra", - ) - .await; - } audio.toggle_playback(); } @@ -191,31 +193,27 @@ async fn handle_light_button(room: &mut Room, event: RelevantEvent) { use ButtonPanel as B; use RelevantEvent as E; - // Dots1 short: to sleep -> lights off - // Dots1 long: to nightlight always -> one lamp on + // Dots1 short: toggle sleep/daylight // - // Dots2 short: to nightlight at night, otherwise daylight -> lamp(s) on - // Dots2 long: to sleep, wakeup off -> lights off + // Dots2 short: wakeup match event { // Light buttons E::Button(B::BottomLeft(_)) => room.set_sleep_delayed().await, E::PortableButton(P::Dots1ShortRelease) => { - room.set_sleep_immediate().await - } - E::Button(B::BottomMiddle(_)) - | E::PortableButton(P::Dots2ShortRelease) => { let now = crate::time::now(); match time(now.hour(), now.minute()) { // rust analyzer seems to think this illegal, its not - T23_00.. | T0_00..T9_00 => room.set_nightlight().await, - _ => room.set_daylight_or_wakeup().await, + T21_00.. | T0_00..T10_00 => { + room.toggle_sleep_nightlight().await + } + _ => room.toggle_sleep_daylight().await, } } - E::Button(B::BottomRight(_)) => room.set_override().await, - E::PortableButton(P::Dots2LongRelease) => { - room.set_sleep_no_wakeup().await + E::Button(B::BottomMiddle(_)) + | E::PortableButton(P::Dots2ShortRelease) => { + room.set_wakeup().await; } - E::PortableButton(P::Dots1LongRelease) => room.set_nightlight().await, + E::Button(B::BottomRight(_)) => room.set_override().await, _ => (), } } diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index 366623c1..75193e5d 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -95,6 +95,38 @@ impl Room { } } + pub(super) async fn toggle_sleep_daylight(&mut self) { + let state = self.state.read().await.clone(); + match state { + State::Sleep | State::SleepNoWakeup => { + self.set_daylight().await; + } + State::Daylight + | State::Wakeup + | State::Override + | State::DelayedOff + | State::Nightlight => { + self.set_sleep_immediate().await; + } + } + } + + pub(super) async fn toggle_sleep_nightlight(&mut self) { + let state = self.state.read().await.clone(); + match state { + State::Sleep | State::SleepNoWakeup => { + self.set_nightlight().await; + } + State::Daylight + | State::Wakeup + | State::Override + | State::DelayedOff + | State::Nightlight => { + self.set_sleep_immediate().await; + } + } + } + pub(super) async fn set_sleep_immediate(&mut self) { self.system.all_lamps_off().await; self.set_state_cancel_prev(State::Sleep).await; @@ -127,16 +159,10 @@ impl Room { *self.task_handle.lock().await = Some(task_handle); } - pub(super) async fn set_daylight_or_wakeup(&mut self) { - if *self.state.read().await == State::Sleep - || *self.state.read().await == State::SleepNoWakeup - { - self.set_wakeup().await; - } else { - self.set_state_cancel_prev(State::Daylight).await; - self.all_lights_daylight().await; - self.system.all_lamps_on().await; - } + pub(super) async fn set_daylight(&mut self) { + self.set_state_cancel_prev(State::Daylight).await; + self.all_lights_daylight().await; + self.system.all_lamps_on().await; } pub(super) async fn set_nightlight(&mut self) { From e07d21a0b3635fa1b162a550e3a4f4f50f72344c Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 1 Aug 2025 14:51:21 +0200 Subject: [PATCH 660/687] Add volume control for small bedroom audio --- .../src/controller/rooms/small_bedroom.rs | 2 ++ .../rooms/small_bedroom/audiocontrol.rs | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 16c091a4..39cdb8c2 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -183,6 +183,8 @@ async fn handle_audio_button(room: &mut Room, button_event: RelevantEvent) { (_, E::PortableButton(P::PlayPause)) => { audio.toggle_playback(); } + (_, E::PortableButton(P::VolumeUp)) => audio.increase_volume(), + (_, E::PortableButton(P::VolumeDown)) => audio.decrease_volume(), (_, b) => info!("Unrecognised button pressed: {b:?}"), } diff --git a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs index c445e829..9cba7046 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/audiocontrol.rs @@ -293,6 +293,15 @@ impl AudioController { self.client.status().unwrap().elapsed } + fn get_volume(&mut self) -> Option { + let volume = self.client.status().unwrap().volume; + if volume == -1 { + None + } else { + Some(volume) + } + } + /// # Panics /// /// Panics if new position is over 4,294,967,295 seconds into the song, @@ -387,6 +396,20 @@ impl AudioController { self.client.pause().unwrap(); } + pub fn increase_volume(&mut self) { + if let Some(volume) = self.get_volume() { + let new_volume = volume.saturating_add(5).clamp(0, 100); + self.client.volume(new_volume).unwrap(); + } + } + + pub fn decrease_volume(&mut self) { + if let Some(volume) = self.get_volume() { + let new_volume = volume.saturating_sub(5).clamp(0, 100); + self.client.volume(new_volume).unwrap(); + } + } + #[instrument] fn switch_playlist(&mut self, direction: Direction) { let current_playlist_name = From 33540ba196800f2612c5448b69e5772b6d4c710a Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 1 Aug 2025 15:21:50 +0200 Subject: [PATCH 661/687] Add fix for kitchen override Still some bugs around off/on toggle, possibly caused by zigbee or deadlock --- crates/brain/src/controller/rooms/kitchen.rs | 1 + crates/brain/src/controller/rooms/small_bedroom.rs | 4 ++-- crates/brain/src/controller/rooms/small_bedroom/state.rs | 4 ++-- crates/brain/test.sh | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index f574383a..bad7937d 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -72,6 +72,7 @@ pub async fn run( Res::Event(RelevantEvent::Override) => { state = State::Override; system.all_lamps_ct(2000, 1.0).await; + system.all_lamps_on().await; } Res::ShouldUpdate if state == State::Daylight => { update(&mut system).await; diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 39cdb8c2..f4a03d9c 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -211,8 +211,8 @@ async fn handle_light_button(room: &mut Room, event: RelevantEvent) { _ => room.toggle_sleep_daylight().await, } } - E::Button(B::BottomMiddle(_)) - | E::PortableButton(P::Dots2ShortRelease) => { + E::Button(B::BottomMiddle(_)) => room.set_daylight().await, + E::PortableButton(P::Dots2ShortRelease) => { room.set_wakeup().await; } E::Button(B::BottomRight(_)) => room.set_override().await, diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index 75193e5d..a25b36da 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -96,7 +96,7 @@ impl Room { } pub(super) async fn toggle_sleep_daylight(&mut self) { - let state = self.state.read().await.clone(); + let state = { self.state.read().await.clone() }; match state { State::Sleep | State::SleepNoWakeup => { self.set_daylight().await; @@ -112,7 +112,7 @@ impl Room { } pub(super) async fn toggle_sleep_nightlight(&mut self) { - let state = self.state.read().await.clone(); + let state = { self.state.read().await.clone() }; match state { State::Sleep | State::SleepNoWakeup => { self.set_nightlight().await; diff --git a/crates/brain/test.sh b/crates/brain/test.sh index 1c75da61..00bad8b1 100755 --- a/crates/brain/test.sh +++ b/crates/brain/test.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -RUST_LOG=brain=info,zigbee_bridge=info,info RUST_BACKTRACE=1 cargo r -- \ +RUST_LOG=brain=trace,zigbee_bridge=info,info RUST_BACKTRACE=1 cargo r -- \ --data-server 192.168.1.43:1235 \ --mpd-ip 192.168.1.43 \ --http-port 34326 \ From 94c7bd0813ae931e15c4409c5b0be60d73d8cb70 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 3 Aug 2025 14:51:46 +0200 Subject: [PATCH 662/687] Turn off small bedroom radiator --- .../src/controller/rooms/small_bedroom.rs | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index f4a03d9c..a8e7b38e 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -228,20 +228,21 @@ pub(super) fn is_nap_time() -> bool { } pub(crate) fn goal_temp_now() -> f64 { - let goals = BTreeMap::from([ - ((0, 00), 18.0), - ((8, 30), 19.0), - ((10, 00), 20.0), - ((11, 00), 20.5), - ((12, 00), 21.0), - ((18, 00), 20.5), - ((19, 00), 20.0), - ((21, 00), 19.5), - ((21, 30), 19.0), - ((22, 00), 18.0), - ]); - - goal_now(goals, 18.0) + // let goals = BTreeMap::from([ + // ((0, 00), 18.0), + // ((8, 30), 19.0), + // ((10, 00), 20.0), + // ((11, 00), 20.5), + // ((12, 00), 21.0), + // ((18, 00), 20.5), + // ((19, 00), 20.0), + // ((21, 00), 19.5), + // ((21, 30), 19.0), + // ((22, 00), 18.0), + // ]); + // + // goal_now(goals, 18.0) + 16.0 } fn air_filtration_now(pm2_5_measurement: &Option<(f32, Zoned)>) -> Option { From 4b6f9a8814f528392ab48b79577315fdbaec6a46 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 4 Aug 2025 14:56:18 +0200 Subject: [PATCH 663/687] Fix outrageous cpu usage for brain Bug in kitchen and entrance caused them to loop non-stop on update --- crates/brain/src/controller/rooms/entrance.rs | 4 ++-- crates/brain/src/controller/rooms/kitchen.rs | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/brain/src/controller/rooms/entrance.rs b/crates/brain/src/controller/rooms/entrance.rs index 5efce990..026ca895 100644 --- a/crates/brain/src/controller/rooms/entrance.rs +++ b/crates/brain/src/controller/rooms/entrance.rs @@ -68,9 +68,9 @@ pub async fn run( if state == State::Daylight { update(&mut system).await; system.all_lamps_on().await; - - next_update = Instant::now() + INTERVAL; } + + next_update = Instant::now() + INTERVAL; } } } diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index bad7937d..423dc644 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -47,6 +47,7 @@ pub async fn run( _event_tx: broadcast::Sender, mut system: RestrictedSystem, ) { + #[derive(Debug)] enum Res { Event(RelevantEvent), ShouldUpdate, @@ -74,9 +75,11 @@ pub async fn run( system.all_lamps_ct(2000, 1.0).await; system.all_lamps_on().await; } - Res::ShouldUpdate if state == State::Daylight => { - update(&mut system).await; - system.all_lamps_on().await; + Res::ShouldUpdate => { + if state == State::Daylight { + update(&mut system).await; + system.all_lamps_on().await; + } next_update = Instant::now() + INTERVAL; } _ => (), From edeb377805e4082aea9e7e14edbb8164afc5c664 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 4 Aug 2025 15:57:34 +0200 Subject: [PATCH 664/687] Autoformat --- crates/brain/src/input/sensors.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/crates/brain/src/input/sensors.rs b/crates/brain/src/input/sensors.rs index 54382384..bcc84637 100644 --- a/crates/brain/src/input/sensors.rs +++ b/crates/brain/src/input/sensors.rs @@ -5,14 +5,19 @@ use tokio::sync::broadcast; use crate::controller::Event; -pub async fn subscribe(event_tx: broadcast::Sender, data_server: SocketAddr) { - let mut sub = ReconnectingClient::new(data_server, "ha-brain".to_owned()).subscribe(); +pub async fn subscribe( + event_tx: broadcast::Sender, + data_server: SocketAddr, +) { + let mut sub = + ReconnectingClient::new(data_server, "ha-brain".to_owned()).subscribe(); loop { match sub.next().await { SubMessage::Reading(reading) => { event_tx.send(Event::Sensor(reading)).unwrap(); } - SubMessage::ErrorReport(_) | SubMessage::AffectorControlled { .. } => continue, + SubMessage::ErrorReport(_) + | SubMessage::AffectorControlled { .. } => continue, } } } From c7a6e46cd44716f3ec04ee7b8a62b1b983440a71 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Mon, 4 Aug 2025 15:57:47 +0200 Subject: [PATCH 665/687] Fix remaining high cpu usage due to offline lamp --- crates/zigbee-bridge/src/cached_bridge.rs | 1 + crates/zigbee-bridge/src/cached_bridge/changes.rs | 15 ++++++++++----- crates/zigbee-bridge/src/device.rs | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/crates/zigbee-bridge/src/cached_bridge.rs b/crates/zigbee-bridge/src/cached_bridge.rs index 13fa67fb..41a7a2c7 100644 --- a/crates/zigbee-bridge/src/cached_bridge.rs +++ b/crates/zigbee-bridge/src/cached_bridge.rs @@ -19,6 +19,7 @@ const WAIT_FOR_INIT_STATES: Duration = Duration::from_millis(500); const TIME_IT_TAKES_TO_APPLY_CHANGE: Duration = Duration::from_secs(10); const CHANGE_ACCUMULATION_TIME: Duration = Duration::from_millis(100); const MIN_TIME_BETWEEN_SENDS: Duration = Duration::from_millis(200); +const OFFLINE_CHECK_INTERVAL: Duration = Duration::from_millis(500); pub(super) async fn run( mqtt_ip: IpAddr, diff --git a/crates/zigbee-bridge/src/cached_bridge/changes.rs b/crates/zigbee-bridge/src/cached_bridge/changes.rs index 1803454d..04e9c918 100644 --- a/crates/zigbee-bridge/src/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/cached_bridge/changes.rs @@ -7,7 +7,7 @@ use tracing::{debug, error, instrument}; use super::mqtt::Mqtt; use super::{ - CHANGE_ACCUMULATION_TIME, MQTT_MIGHT_BE_DOWN_TIMEOUT, WAIT_FOR_INIT_STATES, + CHANGE_ACCUMULATION_TIME, MQTT_MIGHT_BE_DOWN_TIMEOUT, OFFLINE_CHECK_INTERVAL, WAIT_FOR_INIT_STATES }; use crate::device::{Device, Property}; @@ -81,13 +81,18 @@ async fn send_diff_get_timeout( if is_online { let merged_payloads = needed.needs_merged_payloads(); + // This is where we can send changes, and thus the deadline can change let _ = mqtt .send_diff_where_due(device_name, merged_payloads, &diff) .await; - } - - if let Some(deadline) = mqtt.next_deadline(device_name, &diff) { - device_deadlines.push(deadline); + // Only check what the next deadline is if it could have changed + if let Some(deadline) = mqtt.next_deadline(device_name, &diff) { + device_deadlines.push(deadline); + } + } else { + // If the device is offline, the deadline can't have changed, so + // we use the offline check interval + device_deadlines.push(Instant::now() + OFFLINE_CHECK_INTERVAL); } } diff --git a/crates/zigbee-bridge/src/device.rs b/crates/zigbee-bridge/src/device.rs index 306df41b..d60c1fea 100644 --- a/crates/zigbee-bridge/src/device.rs +++ b/crates/zigbee-bridge/src/device.rs @@ -22,7 +22,7 @@ impl Property { } } -#[derive(PartialEq, Eq, Hash)] +#[derive(PartialEq, Eq, Hash, Debug)] pub(crate) enum PropertyDiscriminants { Lamp(LampPropertyDiscriminants), Radiator(RadiatorPropertyDiscriminants), From 6ecc3c7e19bd73effc984a37dd9a327c11bdca3c Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Tue, 5 Aug 2025 17:07:46 +0200 Subject: [PATCH 666/687] Fix button delays by spawning task for update --- crates/brain/src/controller/rooms/kitchen.rs | 1 - .../src/controller/rooms/small_bedroom.rs | 18 ++++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index 423dc644..01456daa 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -82,7 +82,6 @@ pub async fn run( } next_update = Instant::now() + INTERVAL; } - _ => (), } } } diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index a8e7b38e..b3c5681f 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -2,13 +2,14 @@ use std::collections::BTreeMap; use std::fmt::Debug; use std::time::Duration; -use audiocontrol::{AudioController, ForceRewind}; +use audiocontrol::ForceRewind; use futures_concurrency::future::Race; use futures_util::FutureExt; use jiff::civil::Time; use jiff::{ToSpan, Zoned}; use protocol::small_bedroom::{portable_button_panel, ButtonPanel}; use tokio::sync::broadcast; +use tokio::task::{self, JoinHandle}; use tokio::time::{sleep_until, Instant}; use tracing::{info, trace}; @@ -42,6 +43,7 @@ pub async fn run( ) { let mut room = Room::new(event_tx, system.clone()); let mut next_update = Instant::now() + UPDATE_INTERVAL; + let mut update_task: Option> = None; let res = system .system @@ -73,15 +75,23 @@ pub async fn run( room.pm2_5 = Some((val, crate::time::now())) } Trigger::ShouldUpdate => { - room.update_airbox().await; - room.update_radiator().await; - room.all_lights_daylight().await; + // We don't want this to block if it takes a while, so + // we spawn a separate task for it that we need to abort + // in case it hangs + update_task.map(|task| task.abort()); + update_task = Some(task::spawn(update(room.clone()))); next_update = Instant::now() + UPDATE_INTERVAL; } } } } +async fn update(mut room: Room) { + room.update_airbox().await; + room.update_radiator().await; + room.all_lights_daylight().await; +} + async fn handle_button(room: &mut Room, event: RelevantEvent) { use portable_button_panel::Reading as P; use ButtonPanel as B; From a388e8f0daa3dd29bfe2cec533a70ff697304599 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 8 Aug 2025 18:46:07 +0200 Subject: [PATCH 667/687] increase rx size for lb sensor ethernet --- nodes/embassy/bed-lb/src/network.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/nodes/embassy/bed-lb/src/network.rs b/nodes/embassy/bed-lb/src/network.rs index 6228cff3..ade0958a 100644 --- a/nodes/embassy/bed-lb/src/network.rs +++ b/nodes/embassy/bed-lb/src/network.rs @@ -80,9 +80,11 @@ pub async fn handle( led: LedHandle, driver_orderers: &'static slow::DriverOrderers, ) { - let mut rx_buffer = [0; 1024]; - let mut tx_buffer = - [0; max(SensMsg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE) * 2]; + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; max( + max(SensMsg::ENCODED_SIZE, ErrorReport::ENCODED_SIZE) * 2, + 4096, + )]; let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); socket.set_timeout(Some(Duration::from_secs(5))); From bb74ecfe1ca3e2865c2115a283a1cf34e5bedee5 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 8 Aug 2025 20:37:20 +0200 Subject: [PATCH 668/687] update gitignore to ignore passwords for airbox --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 9a1c1d59..6bb53369 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +nodes/esp32/airbox/cfg.toml + # Compiled source # ################### *.com From 4a9da4a1e2e5609c794f82ec533e545cb1612213 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Fri, 8 Aug 2025 20:42:21 +0200 Subject: [PATCH 669/687] fixes new elided lifetime warnings --- crates/protocol/src/affector.rs | 2 +- crates/protocol/src/large_bedroom.rs | 2 +- crates/protocol/src/large_bedroom/airbox.rs | 2 +- crates/protocol/src/large_bedroom/bed.rs | 2 +- crates/protocol/src/small_bedroom.rs | 2 +- crates/protocol/src/small_bedroom/bed.rs | 2 +- crates/ui/src/tui/readings/render/chart.rs | 2 +- crates/usb-bridge/src/usb/device.rs | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/protocol/src/affector.rs b/crates/protocol/src/affector.rs index 5ffdac7d..3b1e37a0 100644 --- a/crates/protocol/src/affector.rs +++ b/crates/protocol/src/affector.rs @@ -75,7 +75,7 @@ impl Affector { // Info() is explicitly not defined, use the tree impl to get at it #[cfg(feature = "alloc")] - pub fn controls(&mut self) -> Vec { + pub fn controls(&mut self) -> Vec> { match self { Affector::LargeBedroom(a) => a.controls(), Affector::SmallBedroom(a) => a.controls(), diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index 08ad4a87..8ed9d482 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -120,7 +120,7 @@ pub enum Affector { } impl Affector { #[cfg(feature = "alloc")] - pub(crate) fn controls(&mut self) -> Vec { + pub(crate) fn controls(&mut self) -> Vec> { match self { Affector::Bed(a) => a.controls(), Affector::Airbox(a) => a.controls(), diff --git a/crates/protocol/src/large_bedroom/airbox.rs b/crates/protocol/src/large_bedroom/airbox.rs index 79306274..3338e95e 100644 --- a/crates/protocol/src/large_bedroom/airbox.rs +++ b/crates/protocol/src/large_bedroom/airbox.rs @@ -262,7 +262,7 @@ impl crate::IsSameAs for Affector { impl Affector { #[cfg(feature = "alloc")] - pub fn controls(&mut self) -> Vec { + pub fn controls(&mut self) -> Vec> { match self { Affector::FanPower { power } => vec![Control { name: "red", diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 11a8e272..4d32c3b5 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -535,7 +535,7 @@ impl crate::IsSameAs for Affector { impl Affector { #[cfg(feature = "alloc")] - pub fn controls(&mut self) -> Vec { + pub fn controls(&mut self) -> Vec> { match self { Affector::Sps30FanClean => vec![Control { name: "start fan cleaning", diff --git a/crates/protocol/src/small_bedroom.rs b/crates/protocol/src/small_bedroom.rs index 228e3abc..13b4f046 100644 --- a/crates/protocol/src/small_bedroom.rs +++ b/crates/protocol/src/small_bedroom.rs @@ -163,7 +163,7 @@ pub enum Affector { impl Affector { #[cfg(feature = "alloc")] - pub(crate) fn controls(&mut self) -> Vec { + pub(crate) fn controls(&mut self) -> Vec> { match self { Affector::Bed(a) => a.controls(), } diff --git a/crates/protocol/src/small_bedroom/bed.rs b/crates/protocol/src/small_bedroom/bed.rs index 9e9ba7ba..bca1d64b 100644 --- a/crates/protocol/src/small_bedroom/bed.rs +++ b/crates/protocol/src/small_bedroom/bed.rs @@ -490,7 +490,7 @@ impl crate::IsSameAs for Affector { } impl Affector { #[cfg(feature = "alloc")] - pub fn controls(&mut self) -> Vec { + pub fn controls(&mut self) -> Vec> { match self { Affector::Sps30FanClean => vec![Control { name: "start fan cleaning", diff --git a/crates/ui/src/tui/readings/render/chart.rs b/crates/ui/src/tui/readings/render/chart.rs index 3a0c00fd..cd3d55f7 100644 --- a/crates/ui/src/tui/readings/render/chart.rs +++ b/crates/ui/src/tui/readings/render/chart.rs @@ -228,7 +228,7 @@ fn fmt_reading( (&protocol::Reading, Color), Option>, ), -) -> Line { +) -> Line<'_> { use protocol::reading::tree::{Item, Tree}; let mut node = reading as &dyn Tree; let mut text = node.name(); diff --git a/crates/usb-bridge/src/usb/device.rs b/crates/usb-bridge/src/usb/device.rs index 7e412674..930a942a 100644 --- a/crates/usb-bridge/src/usb/device.rs +++ b/crates/usb-bridge/src/usb/device.rs @@ -13,7 +13,7 @@ pub(crate) fn get(request: u8) -> transfer::ControlIn { } } -pub(crate) fn send(request: u8, data: &[u8]) -> transfer::ControlOut { +pub(crate) fn send(request: u8, data: &[u8]) -> transfer::ControlOut<'_> { transfer::ControlOut { control_type: transfer::ControlType::Vendor, recipient: transfer::Recipient::Interface, From d9658c611cd5c209fb9db9dc443211bf2f52845a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 7 Sep 2025 21:31:46 +0200 Subject: [PATCH 670/687] renames node folders + add large-bedroom-desk node --- Cargo.lock | 4 + crates/protocol/src/large_bedroom.rs | 8 +- .../protocol/src/large_bedroom/desk_right.rs | 135 + crates/protocol/src/reading/tree.rs | 4 +- crates/wiznet-echo-tester/Cargo.toml | 9 + crates/wiznet-echo-tester/rust-toolchain.toml | 5 + crates/wiznet-echo-tester/src/main.rs | 40 + nodes/embassy/Cargo.lock | 107 +- nodes/embassy/Cargo.toml | 5 +- .../embassy/button-panel/src/buttons/slow.rs | 205 - .../.cargo/config.toml | 0 .../{bed-lb => large-bedroom-bed}/Cargo.lock | 0 .../{bed-lb => large-bedroom-bed}/Cargo.toml | 4 +- .../{bed-lb => large-bedroom-bed}/build.rs | 0 .../rust-toolchain.toml | 0 .../src/channel.rs | 0 .../{bed-lb => large-bedroom-bed}/src/main.rs | 0 .../src/network.rs | 0 .../src/rgb_led.rs | 0 .../{bed-lb => large-bedroom-bed}/src/rng.rs | 0 .../src/sensors.rs | 0 .../src/sensors/fast.rs | 0 .../src/sensors/slow.rs | 0 .../stm32f401.svd | 0 .../.cargo/config.toml | 0 nodes/embassy/large-bedroom-desk/Cargo.toml | 38 + .../{bed-sb => large-bedroom-desk}/build.rs | 0 .../rust-toolchain.toml | 0 .../src/comms.rs | 0 nodes/embassy/large-bedroom-desk/src/main.rs | 172 + .../stm32f401.svd | 0 nodes/embassy/sensors/Cargo.toml | 1 + nodes/embassy/sensors/src/buttons.rs | 69 + nodes/embassy/sensors/src/lib.rs | 1 + .../.cargo/config.toml | 0 .../{bed-sb => small-bedroom-bed}/Cargo.lock | 0 .../{bed-sb => small-bedroom-bed}/Cargo.toml | 6 +- .../build.rs | 0 .../{bed-sb => small-bedroom-bed}/output.txt | 0 .../rust-toolchain.toml | 0 .../src/channel.rs | 0 .../src/comms.rs | 0 .../{bed-sb => small-bedroom-bed}/src/main.rs | 0 .../src/sensors.rs | 0 .../src/sensors/fast.rs | 0 .../src/sensors/slow.rs | 0 .../stm32f401.svd | 0 .../.cargo/config.toml | 18 + .../Cargo.toml | 4 +- .../small-bedroom-button-panel/build.rs | 5 + .../rust-toolchain.toml | 6 + .../src/buttons.rs | 0 .../src/buttons/fast.rs | 0 .../small-bedroom-button-panel/src/comms.rs | 67 + .../src/main.rs | 0 .../src/usb_wrapper.rs | 0 .../small-bedroom-button-panel/stm32f401.svd | 35196 ++++++++++++++++ nodes/embassy/test-wiznet/.cargo/config.toml | 18 + nodes/embassy/test-wiznet/Cargo.lock | 1274 + nodes/embassy/test-wiznet/Cargo.toml | 28 + nodes/embassy/test-wiznet/build.rs | 5 + nodes/embassy/test-wiznet/rust-toolchain.toml | 6 + nodes/embassy/test-wiznet/src/main.rs | 134 + nodes/embassy/test-wiznet/src/network.rs | 60 + nodes/embassy/test-wiznet/src/rng.rs | 31 + 65 files changed, 37420 insertions(+), 245 deletions(-) create mode 100644 crates/protocol/src/large_bedroom/desk_right.rs create mode 100644 crates/wiznet-echo-tester/Cargo.toml create mode 100644 crates/wiznet-echo-tester/rust-toolchain.toml create mode 100644 crates/wiznet-echo-tester/src/main.rs delete mode 100644 nodes/embassy/button-panel/src/buttons/slow.rs rename nodes/embassy/{bed-lb => large-bedroom-bed}/.cargo/config.toml (100%) rename nodes/embassy/{bed-lb => large-bedroom-bed}/Cargo.lock (100%) rename nodes/embassy/{bed-lb => large-bedroom-bed}/Cargo.toml (93%) rename nodes/embassy/{bed-lb => large-bedroom-bed}/build.rs (100%) rename nodes/embassy/{bed-lb => large-bedroom-bed}/rust-toolchain.toml (100%) rename nodes/embassy/{bed-lb => large-bedroom-bed}/src/channel.rs (100%) rename nodes/embassy/{bed-lb => large-bedroom-bed}/src/main.rs (100%) rename nodes/embassy/{bed-lb => large-bedroom-bed}/src/network.rs (100%) rename nodes/embassy/{bed-lb => large-bedroom-bed}/src/rgb_led.rs (100%) rename nodes/embassy/{bed-lb => large-bedroom-bed}/src/rng.rs (100%) rename nodes/embassy/{bed-lb => large-bedroom-bed}/src/sensors.rs (100%) rename nodes/embassy/{bed-lb => large-bedroom-bed}/src/sensors/fast.rs (100%) rename nodes/embassy/{bed-lb => large-bedroom-bed}/src/sensors/slow.rs (100%) rename nodes/embassy/{bed-lb => large-bedroom-bed}/stm32f401.svd (100%) rename nodes/embassy/{button-panel => large-bedroom-desk}/.cargo/config.toml (100%) create mode 100644 nodes/embassy/large-bedroom-desk/Cargo.toml rename nodes/embassy/{bed-sb => large-bedroom-desk}/build.rs (100%) rename nodes/embassy/{bed-sb => large-bedroom-desk}/rust-toolchain.toml (100%) rename nodes/embassy/{button-panel => large-bedroom-desk}/src/comms.rs (100%) create mode 100644 nodes/embassy/large-bedroom-desk/src/main.rs rename nodes/embassy/{bed-sb => large-bedroom-desk}/stm32f401.svd (100%) create mode 100644 nodes/embassy/sensors/src/buttons.rs rename nodes/embassy/{bed-sb => small-bedroom-bed}/.cargo/config.toml (100%) rename nodes/embassy/{bed-sb => small-bedroom-bed}/Cargo.lock (100%) rename nodes/embassy/{bed-sb => small-bedroom-bed}/Cargo.toml (85%) rename nodes/embassy/{button-panel => small-bedroom-bed}/build.rs (100%) rename nodes/embassy/{bed-sb => small-bedroom-bed}/output.txt (100%) rename nodes/embassy/{button-panel => small-bedroom-bed}/rust-toolchain.toml (100%) rename nodes/embassy/{bed-sb => small-bedroom-bed}/src/channel.rs (100%) rename nodes/embassy/{bed-sb => small-bedroom-bed}/src/comms.rs (100%) rename nodes/embassy/{bed-sb => small-bedroom-bed}/src/main.rs (100%) rename nodes/embassy/{bed-sb => small-bedroom-bed}/src/sensors.rs (100%) rename nodes/embassy/{bed-sb => small-bedroom-bed}/src/sensors/fast.rs (100%) rename nodes/embassy/{bed-sb => small-bedroom-bed}/src/sensors/slow.rs (100%) rename nodes/embassy/{button-panel => small-bedroom-bed}/stm32f401.svd (100%) create mode 100644 nodes/embassy/small-bedroom-button-panel/.cargo/config.toml rename nodes/embassy/{button-panel => small-bedroom-button-panel}/Cargo.toml (90%) create mode 100644 nodes/embassy/small-bedroom-button-panel/build.rs create mode 100644 nodes/embassy/small-bedroom-button-panel/rust-toolchain.toml rename nodes/embassy/{button-panel => small-bedroom-button-panel}/src/buttons.rs (100%) rename nodes/embassy/{button-panel => small-bedroom-button-panel}/src/buttons/fast.rs (100%) create mode 100644 nodes/embassy/small-bedroom-button-panel/src/comms.rs rename nodes/embassy/{button-panel => small-bedroom-button-panel}/src/main.rs (100%) rename nodes/embassy/{button-panel => small-bedroom-button-panel}/src/usb_wrapper.rs (100%) create mode 100644 nodes/embassy/small-bedroom-button-panel/stm32f401.svd create mode 100644 nodes/embassy/test-wiznet/.cargo/config.toml create mode 100644 nodes/embassy/test-wiznet/Cargo.lock create mode 100644 nodes/embassy/test-wiznet/Cargo.toml create mode 100644 nodes/embassy/test-wiznet/build.rs create mode 100644 nodes/embassy/test-wiznet/rust-toolchain.toml create mode 100644 nodes/embassy/test-wiznet/src/main.rs create mode 100644 nodes/embassy/test-wiznet/src/network.rs create mode 100644 nodes/embassy/test-wiznet/src/rng.rs diff --git a/Cargo.lock b/Cargo.lock index fcfe89fe..3e2a863e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4039,6 +4039,10 @@ dependencies = [ "bitflags 2.9.0", ] +[[package]] +name = "wiznet-echo-tester" +version = "0.1.0" + [[package]] name = "write16" version = "1.0.0" diff --git a/crates/protocol/src/large_bedroom.rs b/crates/protocol/src/large_bedroom.rs index 8ed9d482..cba205c9 100644 --- a/crates/protocol/src/large_bedroom.rs +++ b/crates/protocol/src/large_bedroom.rs @@ -4,10 +4,11 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "alloc")] use crate::{affector, reading}; +pub mod airbox; pub mod bed; pub mod desk; +pub mod desk_right; pub mod radiator; -pub mod airbox; #[derive( strum::EnumDiscriminants, @@ -25,12 +26,13 @@ pub mod airbox; pub enum Reading { Bed(bed::Reading) = 0, Desk(desk::Reading) = 1, + DeskRight(desk_right::Reading) = 4, Radiator(radiator::Reading) = 2, Airbox(airbox::Reading) = 3, } #[cfg(feature = "alloc")] -reading::tree::all_nodes! {Reading; ReadingDiscriminants; Bed, Desk, Radiator, Airbox} +reading::tree::all_nodes! {Reading; ReadingDiscriminants; Bed, Desk, Radiator, Airbox, DeskRight} #[derive( strum::EnumDiscriminants, @@ -84,6 +86,7 @@ impl core::fmt::Display for Error { pub enum Device { Bed(bed::Device), Desk(desk::Device), + DeskRight(desk_right::Device), Radiator(radiator::Device), Airbox(airbox::Device), } @@ -94,6 +97,7 @@ impl Device { match self { Self::Bed(dev) => dev.info(), Self::Desk(dev) => dev.info(), + Self::DeskRight(dev) => dev.info(), Self::Radiator(dev) => dev.info(), Self::Airbox(dev) => dev.info(), } diff --git a/crates/protocol/src/large_bedroom/desk_right.rs b/crates/protocol/src/large_bedroom/desk_right.rs new file mode 100644 index 00000000..7cd0050f --- /dev/null +++ b/crates/protocol/src/large_bedroom/desk_right.rs @@ -0,0 +1,135 @@ +use core::time::Duration; + +use postcard::experimental::max_size::MaxSize; +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "alloc")] +use crate::reading::tree::Tree; +use crate::IsSameAs; + +crate::button_enum! { + /// +----------------------------------------------------+ + /// | LL | LM | LR RLm | RL | RR | RRm | + /// +----------------------------------------------------+ + /// + /// LL LeftLeft, + /// LN LeftMiddle, + /// LR LeftRight, + /// RLm RightLeftmost, + /// RL RightLeft, + /// RR RightRight, + /// RRm RightRightmost, + Button { + LeftLeft, + LeftMiddle, + LeftRight, + RightLeftmost, + RightLeft, + RightRight, + RightRightmost, + } + crate::Device::LargeBedroom(super::Device::DeskRight(Device)); +} + +#[derive( + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + PartialEq, +)] +#[strum_discriminants(derive(Hash))] +#[repr(u8)] +pub enum Reading { + Button(Button), + PirActivation, +} + +#[cfg(feature = "alloc")] +impl Tree for Reading { + fn inner(&self) -> crate::reading::tree::Item<'_> { + match self { + Reading::Button(button_panel) => button_panel.inner(), + Reading::PirActivation => { + use crate::reading::tree::Item; + use crate::reading::Info; + + Item::Leaf(Info { + val: 1.0, + device: Device.rooted(), + description: "button", + range: 0.0..=1.0, + resolution: 1.0, + unit: crate::Unit::None, + branch_id: self.branch_id(), + label_formatter: Box::new( + crate::button::ButtonLabelFormatter, + ), + }) + } + } + } + + fn branch_id(&self) -> crate::reading::tree::Id { + todo!() + } +} + +impl IsSameAs for Reading { + fn is_same_as(&self, other: &Self) -> bool { + match (self, other) { + (Self::Button(a), Self::Button(b)) => a.is_same_as(b), + (Self::PirActivation, Self::PirActivation) => true, + (_, _) => false, + } + } +} + +#[derive( + Clone, + Debug, + defmt::Format, + Serialize, + Deserialize, + MaxSize, + Eq, + PartialEq, + Hash, +)] +pub struct Device; + +impl Device { + #[must_use] + pub fn rooted(self) -> crate::Device { + crate::Device::LargeBedroom(crate::large_bedroom::Device::DeskRight( + self, + )) + } + + #[must_use] + pub const fn info(&self) -> crate::DeviceInfo { + macro_rules! rtree { + [$($reading:expr),+] => { + [$(crate::Reading::LargeBedroom( + crate::large_bedroom::Reading::DeskRight($reading), + )),+] + }; + } + + crate::DeviceInfo { + name: "Desk Buttons and Pir", + affects_readings: &rtree![ + Reading::Button(Button::LeftLeft(crate::button::Press(0))), + Reading::PirActivation + ], + affectors: &[], + min_sample_interval: Duration::from_secs(1), + max_sample_interval: Duration::MAX, + temporal_resolution: Duration::from_secs(1), + } + } +} diff --git a/crates/protocol/src/reading/tree.rs b/crates/protocol/src/reading/tree.rs index 83ad8f53..8d7489a5 100644 --- a/crates/protocol/src/reading/tree.rs +++ b/crates/protocol/src/reading/tree.rs @@ -35,8 +35,10 @@ pub trait Tree: core::fmt::Debug { macro_rules! impl_zero { ($name:ident; $($var:ident),*) => { - impl crate::IsSameAs for $name { + impl $crate::IsSameAs for $name { fn is_same_as(&self, other: &Self) -> bool { + #[allow(unused_imports)] + use $crate::IsSameAs; match (self, other) { $(($name::$var(a), $name::$var(b)) => a.is_same_as(b),)* (_, _) => false, diff --git a/crates/wiznet-echo-tester/Cargo.toml b/crates/wiznet-echo-tester/Cargo.toml new file mode 100644 index 00000000..8c7b90b6 --- /dev/null +++ b/crates/wiznet-echo-tester/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "wiznet-echo-tester" +version = "0.1.0" +rust-version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true + +[dependencies] diff --git a/crates/wiznet-echo-tester/rust-toolchain.toml b/crates/wiznet-echo-tester/rust-toolchain.toml new file mode 100644 index 00000000..6e888d40 --- /dev/null +++ b/crates/wiznet-echo-tester/rust-toolchain.toml @@ -0,0 +1,5 @@ +[toolchain] +channel = "stable" +components = [] +targets = [ "aarch64-unknown-linux-musl" ] +profile = "minimal" diff --git a/crates/wiznet-echo-tester/src/main.rs b/crates/wiznet-echo-tester/src/main.rs new file mode 100644 index 00000000..bf8c2014 --- /dev/null +++ b/crates/wiznet-echo-tester/src/main.rs @@ -0,0 +1,40 @@ +use std::io::{Read, Write}; +use std::net::TcpListener; +use std::thread; +use std::time::Duration; + +fn main() { + let listener = TcpListener::bind("0.0.0.0:6969").unwrap(); + + println!("waiting for incoming connections"); + for conn in listener.incoming() { + let mut conn = match conn { + Ok(conn) => conn, + Err(e) => { + eprintln!("error with incoming connection: {e}"); + continue; + }, + }; + + println!("Got connection from: {:?}", conn.peer_addr()); + let mut buf = [0u8; 100]; + for i in 0u64.. { + buf[0..8].copy_from_slice(&i.to_be_bytes()); + if let Err(e) = conn.write_all(&buf) { + eprintln!("Could not write to incoming conn: {e}"); + break; + } + if let Err(e) = conn.read_exact(&mut buf) { + eprintln!("Could not read echo from incoming conn: {e}"); + break; + } + + assert_eq!(i, u64::from_be_bytes(buf[0..8].try_into().unwrap())); + + if i % 1000 == 0 { + println!("Performed {i} echos"); + } + thread::sleep(Duration::from_millis(100)); + } + } +} diff --git a/nodes/embassy/Cargo.lock b/nodes/embassy/Cargo.lock index 8f33d88a..403bf4c5 100644 --- a/nodes/embassy/Cargo.lock +++ b/nodes/embassy/Cargo.lock @@ -56,6 +56,33 @@ dependencies = [ "rustc_version 0.2.3", ] +[[package]] +name = "bed" +version = "0.2.0" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "defmt 1.0.1", + "defmt-rtt", + "embassy-embedded-hal", + "embassy-executor", + "embassy-futures", + "embassy-stm32", + "embassy-sync", + "embassy-time", + "embassy-usb", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-bus", + "embedded-io-async", + "futures", + "heapless 0.8.0 (git+https://github.com/rust-embedded/heapless?rev=0ebca23)", + "panic-probe", + "protocol", + "sensors", + "usb-bridge-client", +] + [[package]] name = "bit_field" version = "0.10.2" @@ -105,32 +132,6 @@ dependencies = [ "embedded-hal-async", ] -[[package]] -name = "button-panel" -version = "0.2.0" -dependencies = [ - "cortex-m", - "cortex-m-rt", - "defmt 1.0.1", - "defmt-rtt", - "embassy-embedded-hal", - "embassy-executor", - "embassy-futures", - "embassy-stm32", - "embassy-sync", - "embassy-time", - "embassy-usb", - "embedded-hal 1.0.0", - "embedded-hal-async", - "embedded-hal-bus", - "embedded-io-async", - "futures", - "heapless 0.8.0 (git+https://github.com/rust-embedded/heapless?rev=0ebca23)", - "panic-probe", - "protocol", - "usb-bridge-client", -] - [[package]] name = "byteorder" version = "1.5.0" @@ -808,7 +809,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] -name = "large-bedroom-sensor-node" +name = "large-bedroom-bed" version = "0.2.0" dependencies = [ "cortex-m", @@ -836,6 +837,33 @@ dependencies = [ "static_cell", ] +[[package]] +name = "large-bedroom-desk" +version = "0.2.0" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "defmt 1.0.1", + "defmt-rtt", + "embassy-embedded-hal", + "embassy-executor", + "embassy-futures", + "embassy-stm32", + "embassy-sync", + "embassy-time", + "embassy-usb", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-bus", + "embedded-io-async", + "futures", + "heapless 0.8.0 (git+https://github.com/rust-embedded/heapless?rev=0ebca23)", + "panic-probe", + "protocol", + "sensors", + "usb-bridge-client", +] + [[package]] name = "litrs" version = "0.4.1" @@ -1113,6 +1141,7 @@ dependencies = [ "bosch-bme680", "defmt 1.0.1", "embassy-embedded-hal", + "embassy-futures", "embassy-stm32", "embassy-sync", "embassy-time", @@ -1158,7 +1187,7 @@ dependencies = [ ] [[package]] -name = "small-bedroom-sensor-node" +name = "small-bedroom-button-panel" version = "0.2.0" dependencies = [ "cortex-m", @@ -1180,7 +1209,6 @@ dependencies = [ "heapless 0.8.0 (git+https://github.com/rust-embedded/heapless?rev=0ebca23)", "panic-probe", "protocol", - "sensors", "usb-bridge-client", ] @@ -1319,6 +1347,27 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "test-wiznet" +version = "0.2.0" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "defmt 1.0.1", + "defmt-rtt", + "embassy-executor", + "embassy-net", + "embassy-net-wiznet", + "embassy-stm32", + "embassy-time", + "embedded-hal-bus", + "embedded-io-async", + "heapless 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "panic-probe", + "rand", + "static_cell", +] + [[package]] name = "thiserror" version = "2.0.12" diff --git a/nodes/embassy/Cargo.toml b/nodes/embassy/Cargo.toml index 41ef0354..f2235ad7 100644 --- a/nodes/embassy/Cargo.toml +++ b/nodes/embassy/Cargo.toml @@ -1,9 +1,12 @@ [workspace] resolver = "2" -members = ["bed-sb", "bed-lb", "button-panel", "sensors", "usb-bridge-client"] +members = ["large-bedroom-bed", "small-bedroom-bed", +"small-bedroom-button-panel", "large-bedroom-desk", "sensors", "usb-bridge-client", "test-wiznet"] [workspace.dependencies] protocol = { path = "../../crates/protocol" } +sensors = { path = "sensors" } +usb-bridge-client = { path = "usb-bridge-client" } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/nodes/embassy/button-panel/src/buttons/slow.rs b/nodes/embassy/button-panel/src/buttons/slow.rs deleted file mode 100644 index f1d1a973..00000000 --- a/nodes/embassy/button-panel/src/buttons/slow.rs +++ /dev/null @@ -1,205 +0,0 @@ -use defmt::unwrap; -use embassy_futures::join::join5; -use embassy_futures::select; -use embassy_sync::blocking_mutex::raw::NoopRawMutex; -use embassy_sync::channel::Channel; -use embassy_time::Timer; -use embassy_time::{with_timeout, Duration}; - -use protocol::small_bedroom::bed::Reading; - -use crate::channel::Queues; -use sensors::measurements; -use sensors::{Bme680Driver, Driver, Sht31Driver, Sps30Driver}; -use sensors::{Error, MhzDriver}; - -type Signal = embassy_sync::signal::Signal; - -/// Measure when signal is received or control the device's -/// affector when it is ordered -#[inline(always)] -async fn measure_and_control( - mut driver: D, - order: &Channel, - send: F, - signal: &Signal, -) where - D: Driver, - F: Fn(Result) -> (), -{ - let timeout = Duration::from_secs(15); - loop { - match select::select(signal.wait(), order.receive()).await { - select::Either::First(_) => { - let try_measure = Driver::try_measure(&mut driver); - let res = match with_timeout(timeout, try_measure).await { - Ok(res) => res, - Err(_) => Err(Error::Timeout(driver.device())), - }; - send(res); - } - select::Either::Second(order) => { - let affect = Driver::affect(&mut driver, order); - let res = match with_timeout(timeout, affect).await { - Ok(Ok(_)) => continue, - Ok(Err(e)) => Err(e), - Err(_) => Err(Error::Timeout(driver.device())), - }; - send(res); - } - } - } -} - -async fn order_measurements_every_period(signals: &[Signal]) { - loop { - for signal in signals { - signal.signal(()); - } - Timer::after_secs(5).await; - } -} - -pub(crate) struct Drivers<'a> { - pub sht: Sht31Driver<'a>, - pub bme: Bme680Driver<'a>, - pub mhz: MhzDriver<'a>, - pub sps: Sps30Driver<'a>, -} - -pub(crate) struct DriverOrderers { - pub sht: Channel, - pub bme: Channel, - pub mhz: Channel, - pub sps: Channel, -} -impl DriverOrderers { - pub(crate) fn new() -> Self { - Self { - sht: Channel::new(), - bme: Channel::new(), - mhz: Channel::new(), - sps: Channel::new(), - } - } -} - -#[inline(always)] -pub async fn read( - drivers: Drivers<'_>, - orderers: &DriverOrderers, - publish: &'_ Queues, -) { - let signals = [const { Signal::new() }; 4]; - - join5( - order_measurements_every_period(&signals), - measure_and_control( - drivers.sht, - &orderers.sht, - |res| publish_sht_result(res, &publish), - &signals[0], - ), - measure_and_control( - drivers.bme, - &orderers.bme, - |res| publish_bme_result(res, &publish), - &signals[1], - ), - measure_and_control( - drivers.mhz, - &orderers.mhz, - |res| publish_mhz_result(res, &publish), - &signals[2], - ), - measure_and_control( - drivers.sps, - &orderers.sps, - |res| publish_sps_result(res, &publish), - &signals[3], - ), - ) - .await; -} - -fn publish_sps_result( - sps_res: Result, - publish: &Queues, -) { - match sps_res { - Ok(measurements::Sps30 { - mass_pm1_0, - mass_pm2_5, - mass_pm4_0, - mass_pm10, - number_pm0_5, - number_pm1_0, - number_pm2_5, - number_pm4_0, - number_pm10, - typical_particle_size, - .. - }) => { - publish.send_p0(Reading::MassPm1_0(mass_pm1_0)); - publish.send_p0(Reading::MassPm2_5(mass_pm2_5)); - publish.send_p0(Reading::MassPm4_0(mass_pm4_0)); - publish.send_p0(Reading::MassPm10(mass_pm10)); - publish.send_p0(Reading::NumberPm0_5(number_pm0_5)); - publish.send_p0(Reading::NumberPm1_0(number_pm1_0)); - publish.send_p0(Reading::NumberPm2_5(number_pm2_5)); - publish.send_p0(Reading::NumberPm4_0(number_pm4_0)); - publish.send_p0(Reading::NumberPm10(number_pm10)); - publish - .send_p0(Reading::TypicalParticleSize(typical_particle_size)); - } - Err(err) => publish.queue_error(err), - } -} - -fn publish_mhz_result( - mhz_res: Result, - publish: &Queues, -) { - match mhz_res { - Ok(measurements::Mhz { co2, .. }) => { - publish.send_p0(Reading::Co2(co2)); - } - Err(err) => { - publish.queue_error(err); - } - } -} - -fn publish_sht_result( - sht_res: Result, - publish: &Queues, -) { - match sht_res { - Ok(measurements::Sht31 { - temperature, - humidity, - }) => { - publish.send_p0(Reading::Temperature(temperature)); - publish.send_p0(Reading::Humidity(humidity)); - } - Err(err) => publish.queue_error(err), - } -} - -fn publish_bme_result( - bme_res: Result, - publish: &Queues, -) { - match bme_res { - Ok(measurements::Bme { - pressure, - gas_resistance, - .. - }) => { - let gas_resistance = unwrap!(gas_resistance); // sensor is on - publish.send_p0(Reading::GassResistance(gas_resistance)); - publish.send_p0(Reading::Pressure(pressure)); - } - Err(err) => publish.queue_error(err), - } -} diff --git a/nodes/embassy/bed-lb/.cargo/config.toml b/nodes/embassy/large-bedroom-bed/.cargo/config.toml similarity index 100% rename from nodes/embassy/bed-lb/.cargo/config.toml rename to nodes/embassy/large-bedroom-bed/.cargo/config.toml diff --git a/nodes/embassy/bed-lb/Cargo.lock b/nodes/embassy/large-bedroom-bed/Cargo.lock similarity index 100% rename from nodes/embassy/bed-lb/Cargo.lock rename to nodes/embassy/large-bedroom-bed/Cargo.lock diff --git a/nodes/embassy/bed-lb/Cargo.toml b/nodes/embassy/large-bedroom-bed/Cargo.toml similarity index 93% rename from nodes/embassy/bed-lb/Cargo.toml rename to nodes/embassy/large-bedroom-bed/Cargo.toml index ac595b85..da44dc4c 100644 --- a/nodes/embassy/bed-lb/Cargo.toml +++ b/nodes/embassy/large-bedroom-bed/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "large-bedroom-sensor-node" +name = "large-bedroom-bed" version = "0.2.0" rust-version.workspace = true edition.workspace = true @@ -34,7 +34,7 @@ rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } heapless = { version = "0.8", default-features = false } # sensors -sensors = { path = "../sensors" } +sensors.workspace = true # encoding protocol = { workspace = true } diff --git a/nodes/embassy/bed-lb/build.rs b/nodes/embassy/large-bedroom-bed/build.rs similarity index 100% rename from nodes/embassy/bed-lb/build.rs rename to nodes/embassy/large-bedroom-bed/build.rs diff --git a/nodes/embassy/bed-lb/rust-toolchain.toml b/nodes/embassy/large-bedroom-bed/rust-toolchain.toml similarity index 100% rename from nodes/embassy/bed-lb/rust-toolchain.toml rename to nodes/embassy/large-bedroom-bed/rust-toolchain.toml diff --git a/nodes/embassy/bed-lb/src/channel.rs b/nodes/embassy/large-bedroom-bed/src/channel.rs similarity index 100% rename from nodes/embassy/bed-lb/src/channel.rs rename to nodes/embassy/large-bedroom-bed/src/channel.rs diff --git a/nodes/embassy/bed-lb/src/main.rs b/nodes/embassy/large-bedroom-bed/src/main.rs similarity index 100% rename from nodes/embassy/bed-lb/src/main.rs rename to nodes/embassy/large-bedroom-bed/src/main.rs diff --git a/nodes/embassy/bed-lb/src/network.rs b/nodes/embassy/large-bedroom-bed/src/network.rs similarity index 100% rename from nodes/embassy/bed-lb/src/network.rs rename to nodes/embassy/large-bedroom-bed/src/network.rs diff --git a/nodes/embassy/bed-lb/src/rgb_led.rs b/nodes/embassy/large-bedroom-bed/src/rgb_led.rs similarity index 100% rename from nodes/embassy/bed-lb/src/rgb_led.rs rename to nodes/embassy/large-bedroom-bed/src/rgb_led.rs diff --git a/nodes/embassy/bed-lb/src/rng.rs b/nodes/embassy/large-bedroom-bed/src/rng.rs similarity index 100% rename from nodes/embassy/bed-lb/src/rng.rs rename to nodes/embassy/large-bedroom-bed/src/rng.rs diff --git a/nodes/embassy/bed-lb/src/sensors.rs b/nodes/embassy/large-bedroom-bed/src/sensors.rs similarity index 100% rename from nodes/embassy/bed-lb/src/sensors.rs rename to nodes/embassy/large-bedroom-bed/src/sensors.rs diff --git a/nodes/embassy/bed-lb/src/sensors/fast.rs b/nodes/embassy/large-bedroom-bed/src/sensors/fast.rs similarity index 100% rename from nodes/embassy/bed-lb/src/sensors/fast.rs rename to nodes/embassy/large-bedroom-bed/src/sensors/fast.rs diff --git a/nodes/embassy/bed-lb/src/sensors/slow.rs b/nodes/embassy/large-bedroom-bed/src/sensors/slow.rs similarity index 100% rename from nodes/embassy/bed-lb/src/sensors/slow.rs rename to nodes/embassy/large-bedroom-bed/src/sensors/slow.rs diff --git a/nodes/embassy/bed-lb/stm32f401.svd b/nodes/embassy/large-bedroom-bed/stm32f401.svd similarity index 100% rename from nodes/embassy/bed-lb/stm32f401.svd rename to nodes/embassy/large-bedroom-bed/stm32f401.svd diff --git a/nodes/embassy/button-panel/.cargo/config.toml b/nodes/embassy/large-bedroom-desk/.cargo/config.toml similarity index 100% rename from nodes/embassy/button-panel/.cargo/config.toml rename to nodes/embassy/large-bedroom-desk/.cargo/config.toml diff --git a/nodes/embassy/large-bedroom-desk/Cargo.toml b/nodes/embassy/large-bedroom-desk/Cargo.toml new file mode 100644 index 00000000..b1a00cf6 --- /dev/null +++ b/nodes/embassy/large-bedroom-desk/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "large-bedroom-desk" +version = "0.2.0" +rust-version = "1.85" +edition = "2024" +license = "GPLv3" +authors = ["David Kleingeld & Eva van Houten"] + +[dependencies] +cortex-m.workspace = true +cortex-m-rt.workspace = true + +embassy-stm32.workspace = true +embassy-sync.workspace = true +embassy-executor.workspace = true +embassy-embedded-hal.workspace = true +embassy-time.workspace = true +embassy-futures.workspace = true +embassy-usb.workspace = true + +defmt.workspace = true +defmt-rtt.workspace = true + +embedded-hal.workspace = true +embedded-hal-async.workspace = true +embedded-hal-bus.workspace = true +embedded-io-async.workspace = true + +panic-probe.workspace = true +futures.workspace = true +heapless.workspace = true + +# encoding + +protocol.workspace = true +sensors.workspace = true + +usb-bridge-client.workspace = true diff --git a/nodes/embassy/bed-sb/build.rs b/nodes/embassy/large-bedroom-desk/build.rs similarity index 100% rename from nodes/embassy/bed-sb/build.rs rename to nodes/embassy/large-bedroom-desk/build.rs diff --git a/nodes/embassy/bed-sb/rust-toolchain.toml b/nodes/embassy/large-bedroom-desk/rust-toolchain.toml similarity index 100% rename from nodes/embassy/bed-sb/rust-toolchain.toml rename to nodes/embassy/large-bedroom-desk/rust-toolchain.toml diff --git a/nodes/embassy/button-panel/src/comms.rs b/nodes/embassy/large-bedroom-desk/src/comms.rs similarity index 100% rename from nodes/embassy/button-panel/src/comms.rs rename to nodes/embassy/large-bedroom-desk/src/comms.rs diff --git a/nodes/embassy/large-bedroom-desk/src/main.rs b/nodes/embassy/large-bedroom-desk/src/main.rs new file mode 100644 index 00000000..6196e349 --- /dev/null +++ b/nodes/embassy/large-bedroom-desk/src/main.rs @@ -0,0 +1,172 @@ +#![no_std] +#![no_main] + +use core::time::Duration; + +use embassy_executor::Spawner; +use embassy_futures::join; +use embassy_stm32::exti::ExtiInput; +use embassy_stm32::gpio::Pull; +use embassy_stm32::peripherals::IWDG; +use embassy_stm32::time::Hertz; +use embassy_stm32::wdg::IndependentWatchdog; +use embassy_stm32::{Config, usb}; +use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; +use embassy_sync::channel::Channel; +use embassy_time::Timer; +use futures::pin_mut; + +use defmt::trace; +use {defmt_rtt as _, panic_probe as _}; + +mod comms; + +embassy_stm32::bind_interrupts!(struct Irqs { + OTG_FS => embassy_stm32::usb::InterruptHandler; +}); + +static PUBLISH: Channel = + Channel::new(); + +// 84 Mhz clock stm32f401 +// 48 Mhz clock for usb +fn config() -> Config { + use embassy_stm32::rcc::mux; + use embassy_stm32::rcc::{ + AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, + PllPreDiv, PllQDiv, PllSource, Sysclk, + }; + + let mut config = Config::default(); + config.rcc.hse = Some(Hse { + freq: Hertz(25_000_000), + mode: HseMode::Oscillator, + }); + config.rcc.pll_src = PllSource::HSE; + config.rcc.pll = Some(Pll { + prediv: PllPreDiv::DIV25, + mul: PllMul::MUL336, + divp: Some(PllPDiv::DIV4), // 25mhz / 25 * 336 / 4 = 84Mhz. + divq: Some(PllQDiv::DIV7), // 25mhz / 25 * 336 / 7 = 48Mhz. + divr: None, + }); + config.rcc.ahb_pre = AHBPrescaler::DIV1; + config.rcc.apb1_pre = APBPrescaler::DIV2; + config.rcc.apb2_pre = APBPrescaler::DIV1; + config.rcc.sys = Sysclk::PLL1_P; + config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q; + config +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_stm32::init(config()); + let dog = IndependentWatchdog::new( + p.IWDG, + Duration::from_secs(5).as_micros() as u32, + ); + + use protocol::large_bedroom::desk_right::Button; + let buttons = [ + ( + ExtiInput::new(p.PC15, p.EXTI15, Pull::Down), + Button::LeftLeft, + ), + (ExtiInput::new(p.PB0, p.EXTI0, Pull::Down), Button::LeftLeft), + ( + ExtiInput::new(p.PC14, p.EXTI14, Pull::Down), + Button::LeftLeft, + ), + ( + ExtiInput::new(p.PB12, p.EXTI12, Pull::Down), + Button::LeftLeft, + ), + ( + ExtiInput::new(p.PB13, p.EXTI13, Pull::Down), + Button::LeftLeft, + ), + (ExtiInput::new(p.PB8, p.EXTI8, Pull::Down), Button::LeftLeft), + (ExtiInput::new(p.PB6, p.EXTI6, Pull::Down), Button::LeftLeft), + ]; + + // let pir = buttons::Pir { + // left_left: ExtiInput::new(p.PC11, p.EXTI11, Pull::Down), + // }; // TODO + + let mut usb_driver_config = embassy_stm32::usb::Config::default(); + // Do not enable vbus_detection. This is a safe default that works in all + // boards. However, if your USB device is self-powered (can stay powered on + // if USB is unplugged), you need to enable vbus_detection to comply with + // the USB spec. If you enable it, the board + usb_driver_config.vbus_detection = false; + + let mut ep_out_buffer = [0u8; 256]; + let usb_driver = usb::Driver::new_fs( + p.USB_OTG_FS, + Irqs, + p.PA12, + p.PA11, + &mut ep_out_buffer, + usb_driver_config, + ); + + let affector_list = comms::affector_list(); + let stack_a = usb_bridge_client::StackA::new(); + let mut stack_b = usb_bridge_client::StackB::new(&stack_a, &affector_list); + let (mut usb_bus, usb_handle) = usb_bridge_client::new( + &stack_a, + &mut stack_b, + usb_bridge_client::config!("large-bedroom-righ", "87244"), + usb_driver, + ); + + let handle_network = comms::handle(usb_handle); + pin_mut!(handle_network); + + let init_then_measure = sensors::buttons::watch_array(buttons, |button| { + let _err = PUBLISH.try_send(button_into_reading(button)); + }); + + join::join4( + &mut handle_network, + init_then_measure, + usb_bus.run(), + keep_dog_happy(dog), + ) + .await; +} + +pub fn usb_config() -> embassy_usb::Config<'static> { + // Create embassy-usb Config + let mut config = embassy_usb::Config::new(0x16c0, 0x27DD); + config.manufacturer = Some("Vid"); + config.product = Some("Sensor node"); + config.serial_number = Some("2478437"); + + // Required for windows compatibility. + // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help + config.device_class = 0xEF; + config.device_sub_class = 0x02; + config.device_protocol = 0x01; + config.composite_with_iads = true; + + config +} + +async fn keep_dog_happy(mut dog: IndependentWatchdog<'_, IWDG>) -> ! { + loop { + Timer::after_secs(1).await; + trace!("petting dog"); + dog.pet(); + } +} + +fn button_into_reading( + button: protocol::large_bedroom::desk_right::Button, +) -> protocol::Reading { + protocol::Reading::LargeBedroom( + protocol::large_bedroom::Reading::DeskRight( + protocol::large_bedroom::desk_right::Reading::Button(button), + ), + ) +} diff --git a/nodes/embassy/bed-sb/stm32f401.svd b/nodes/embassy/large-bedroom-desk/stm32f401.svd similarity index 100% rename from nodes/embassy/bed-sb/stm32f401.svd rename to nodes/embassy/large-bedroom-desk/stm32f401.svd diff --git a/nodes/embassy/sensors/Cargo.toml b/nodes/embassy/sensors/Cargo.toml index bb3043af..c0aecf94 100644 --- a/nodes/embassy/sensors/Cargo.toml +++ b/nodes/embassy/sensors/Cargo.toml @@ -11,6 +11,7 @@ protocol = { workspace = true } embassy-stm32.workspace = true embassy-sync.workspace = true embassy-time.workspace = true +embassy-futures.workspace = true embassy-embedded-hal.workspace = true defmt.workspace = true diff --git a/nodes/embassy/sensors/src/buttons.rs b/nodes/embassy/sensors/src/buttons.rs new file mode 100644 index 00000000..6a7ff5d1 --- /dev/null +++ b/nodes/embassy/sensors/src/buttons.rs @@ -0,0 +1,69 @@ +use embassy_stm32::exti::ExtiInput; +use embassy_time::{Duration, Instant, Timer}; +use protocol::button; + +pub async fn watch_array( + buttons: [(ExtiInput<'static>, F); N], + on_button: impl Fn(B) + Clone, +) where + B: defmt::Format, + F: Fn(protocol::button::Press) -> B + Clone, +{ + embassy_futures::join::join_array(buttons.map(|(input, into_button)| { + let local_into_button = into_button.clone(); + let on_err = move || print_error(&local_into_button); + + let local_into_button = into_button.clone(); + let local_on_button = on_button.clone(); + let on_ok = move |press| { + let on_button = &local_on_button; + let into_button = &local_into_button; + on_button(into_button(press)); + }; + + watch_button(input, on_ok, on_err) + })) + .await; +} + +fn print_error( + into_reading: impl Fn(protocol::button::Press) -> B, +) { + let event_for_printing = into_reading(protocol::button::Press(0)); + let name = event_for_printing; // todo variant trait + defmt::error!("Button pressed too long: {:?}", name); +} + +async fn watch_button( + mut input: ExtiInput<'static>, + on_ok_press: impl Fn(protocol::button::Press), + on_err_press: impl Fn(), +) { + let mut went_high_at: Option = None; + loop { + if let Some(went_high_at) = went_high_at.take() { + input.wait_for_low().await; + let press = went_high_at.elapsed(); + let Ok(press) = press.as_millis().try_into().map(button::Press) + else { + on_err_press(); + continue; + }; + on_ok_press(press); + } else { + input.wait_for_high().await; + Timer::after(Duration::from_millis(20)).await; + if input.is_low() { + continue; + } + Timer::after(Duration::from_millis(20)).await; + if input.is_low() { + continue; + } + Timer::after(Duration::from_millis(10)).await; + if input.is_high() { + went_high_at = Some(Instant::now()); + } + } + } +} diff --git a/nodes/embassy/sensors/src/lib.rs b/nodes/embassy/sensors/src/lib.rs index 2e84ca50..d3c9fcc1 100644 --- a/nodes/embassy/sensors/src/lib.rs +++ b/nodes/embassy/sensors/src/lib.rs @@ -1,6 +1,7 @@ #![no_std] mod drivers; +pub mod buttons; pub mod errors; pub mod measurements; diff --git a/nodes/embassy/bed-sb/.cargo/config.toml b/nodes/embassy/small-bedroom-bed/.cargo/config.toml similarity index 100% rename from nodes/embassy/bed-sb/.cargo/config.toml rename to nodes/embassy/small-bedroom-bed/.cargo/config.toml diff --git a/nodes/embassy/bed-sb/Cargo.lock b/nodes/embassy/small-bedroom-bed/Cargo.lock similarity index 100% rename from nodes/embassy/bed-sb/Cargo.lock rename to nodes/embassy/small-bedroom-bed/Cargo.lock diff --git a/nodes/embassy/bed-sb/Cargo.toml b/nodes/embassy/small-bedroom-bed/Cargo.toml similarity index 85% rename from nodes/embassy/bed-sb/Cargo.toml rename to nodes/embassy/small-bedroom-bed/Cargo.toml index eb546799..fac6480d 100644 --- a/nodes/embassy/bed-sb/Cargo.toml +++ b/nodes/embassy/small-bedroom-bed/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "small-bedroom-sensor-node" +name = "bed" version = "0.2.0" rust-version = "1.78" edition = "2021" @@ -31,8 +31,8 @@ futures.workspace = true heapless.workspace = true # sensors -sensors = { path = "../sensors" } +sensors.workspace = true # encoding protocol.workspace = true -usb-bridge-client = { path = "../usb-bridge-client" } +usb-bridge-client.workspace = true diff --git a/nodes/embassy/button-panel/build.rs b/nodes/embassy/small-bedroom-bed/build.rs similarity index 100% rename from nodes/embassy/button-panel/build.rs rename to nodes/embassy/small-bedroom-bed/build.rs diff --git a/nodes/embassy/bed-sb/output.txt b/nodes/embassy/small-bedroom-bed/output.txt similarity index 100% rename from nodes/embassy/bed-sb/output.txt rename to nodes/embassy/small-bedroom-bed/output.txt diff --git a/nodes/embassy/button-panel/rust-toolchain.toml b/nodes/embassy/small-bedroom-bed/rust-toolchain.toml similarity index 100% rename from nodes/embassy/button-panel/rust-toolchain.toml rename to nodes/embassy/small-bedroom-bed/rust-toolchain.toml diff --git a/nodes/embassy/bed-sb/src/channel.rs b/nodes/embassy/small-bedroom-bed/src/channel.rs similarity index 100% rename from nodes/embassy/bed-sb/src/channel.rs rename to nodes/embassy/small-bedroom-bed/src/channel.rs diff --git a/nodes/embassy/bed-sb/src/comms.rs b/nodes/embassy/small-bedroom-bed/src/comms.rs similarity index 100% rename from nodes/embassy/bed-sb/src/comms.rs rename to nodes/embassy/small-bedroom-bed/src/comms.rs diff --git a/nodes/embassy/bed-sb/src/main.rs b/nodes/embassy/small-bedroom-bed/src/main.rs similarity index 100% rename from nodes/embassy/bed-sb/src/main.rs rename to nodes/embassy/small-bedroom-bed/src/main.rs diff --git a/nodes/embassy/bed-sb/src/sensors.rs b/nodes/embassy/small-bedroom-bed/src/sensors.rs similarity index 100% rename from nodes/embassy/bed-sb/src/sensors.rs rename to nodes/embassy/small-bedroom-bed/src/sensors.rs diff --git a/nodes/embassy/bed-sb/src/sensors/fast.rs b/nodes/embassy/small-bedroom-bed/src/sensors/fast.rs similarity index 100% rename from nodes/embassy/bed-sb/src/sensors/fast.rs rename to nodes/embassy/small-bedroom-bed/src/sensors/fast.rs diff --git a/nodes/embassy/bed-sb/src/sensors/slow.rs b/nodes/embassy/small-bedroom-bed/src/sensors/slow.rs similarity index 100% rename from nodes/embassy/bed-sb/src/sensors/slow.rs rename to nodes/embassy/small-bedroom-bed/src/sensors/slow.rs diff --git a/nodes/embassy/button-panel/stm32f401.svd b/nodes/embassy/small-bedroom-bed/stm32f401.svd similarity index 100% rename from nodes/embassy/button-panel/stm32f401.svd rename to nodes/embassy/small-bedroom-bed/stm32f401.svd diff --git a/nodes/embassy/small-bedroom-button-panel/.cargo/config.toml b/nodes/embassy/small-bedroom-button-panel/.cargo/config.toml new file mode 100644 index 00000000..f00aaa5f --- /dev/null +++ b/nodes/embassy/small-bedroom-button-panel/.cargo/config.toml @@ -0,0 +1,18 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +# replace STM32F103C8 with your chip as listed in `probe-rs chip list` +# runner = "probe-rs run --chip STM32F103C8" +runner = "probe-rs run --chip STM32F401CCUx" +# runner = "probe-rs run --chip STM32F401CCUx --host ws://192.168.1.43:3000 --token secret_token_redacted --probe c251:f001:202108120001" +linker = "flip-link" + +[build] +# target = "thumbv7m-none-eabi" for f103 +target = "thumbv7em-none-eabihf" + +[env] +DEFMT_LOG = "debug,sps30_async=warn,bosch_bme680=info" +EMBASSY_EXECUTOR_TASK_ARENA_SIZE="10900" + +# [unstable] +# build-std = ["core"] +# build-std-features = ["panic_immediate_abort"] diff --git a/nodes/embassy/button-panel/Cargo.toml b/nodes/embassy/small-bedroom-button-panel/Cargo.toml similarity index 90% rename from nodes/embassy/button-panel/Cargo.toml rename to nodes/embassy/small-bedroom-button-panel/Cargo.toml index 87502de6..fe5eb8bc 100644 --- a/nodes/embassy/button-panel/Cargo.toml +++ b/nodes/embassy/small-bedroom-button-panel/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "button-panel" +name = "small-bedroom-button-panel" version = "0.2.0" rust-version = "1.85" edition = "2024" @@ -33,4 +33,4 @@ heapless.workspace = true # encoding protocol = { workspace = true } -usb-bridge-client = { path = "../usb-bridge-client" } +usb-bridge-client.workspace = true diff --git a/nodes/embassy/small-bedroom-button-panel/build.rs b/nodes/embassy/small-bedroom-button-panel/build.rs new file mode 100644 index 00000000..8cd32d7e --- /dev/null +++ b/nodes/embassy/small-bedroom-button-panel/build.rs @@ -0,0 +1,5 @@ +fn main() { + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tlink.x"); + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); +} diff --git a/nodes/embassy/small-bedroom-button-panel/rust-toolchain.toml b/nodes/embassy/small-bedroom-button-panel/rust-toolchain.toml new file mode 100644 index 00000000..c17f644e --- /dev/null +++ b/nodes/embassy/small-bedroom-button-panel/rust-toolchain.toml @@ -0,0 +1,6 @@ +[toolchain] +channel = "stable" +components = [ "rust-src", "rustfmt", "llvm-tools" ] +targets = [ + "thumbv7em-none-eabihf", +] diff --git a/nodes/embassy/button-panel/src/buttons.rs b/nodes/embassy/small-bedroom-button-panel/src/buttons.rs similarity index 100% rename from nodes/embassy/button-panel/src/buttons.rs rename to nodes/embassy/small-bedroom-button-panel/src/buttons.rs diff --git a/nodes/embassy/button-panel/src/buttons/fast.rs b/nodes/embassy/small-bedroom-button-panel/src/buttons/fast.rs similarity index 100% rename from nodes/embassy/button-panel/src/buttons/fast.rs rename to nodes/embassy/small-bedroom-button-panel/src/buttons/fast.rs diff --git a/nodes/embassy/small-bedroom-button-panel/src/comms.rs b/nodes/embassy/small-bedroom-button-panel/src/comms.rs new file mode 100644 index 00000000..64de4ef0 --- /dev/null +++ b/nodes/embassy/small-bedroom-button-panel/src/comms.rs @@ -0,0 +1,67 @@ +use defmt::warn; +use embassy_time::{Duration, Instant}; +use heapless::HistoryBuffer; +use protocol::{SensorMessage, affector}; +use usb_bridge_client::{NoSpaceInQueue, UsbHandle, UsbSender}; + +pub async fn handle(usb: UsbHandle<'_>) -> ! { + const MIN_BETWEEN_COMM_ERRS: Duration = Duration::from_secs(30); + let mut last_errors_at: HistoryBuffer<_, 5> = HistoryBuffer::new(); + + loop { + crate::PUBLISH.clear(); + + let (writer, _) = usb.split(); + send_messages(writer).await; + warn!("Error while sending messages"); + + let mut error_after = Instant::now(); + if last_errors_at.oldest_ordered().rev().copied().all( + |error: Instant| { + let is_recent = + error_after.duration_since(error) < MIN_BETWEEN_COMM_ERRS; + error_after = error; + is_recent + }, + ) { + defmt::error!( + "Something is terribly wrong with the connection, \ + 5 errors occured each within 30 seconds of the previous. \ + Resetting entire node" + ); + cortex_m::peripheral::SCB::sys_reset(); + } else { + last_errors_at.write(Instant::now()); + } + } +} + +const AFFECTOR_LIST_MAX_SIZE: usize = protocol::Msg::<5>::max_size(); +pub fn affector_list() -> heapless::Vec { + let list = affector::ListMessage::<5>::empty(); + let mut buf = heapless::Vec::new(); + defmt::unwrap!(buf.resize_default(AFFECTOR_LIST_MAX_SIZE)); + let encoded_len = list.encode_slice(&mut buf).len(); + buf.truncate(encoded_len); + buf +} + +async fn collect_msg() -> SensorMessage<10> { + let mut msg = SensorMessage::<10>::default(); + let reading = crate::PUBLISH.receive().await; + defmt::unwrap!(msg.values.push(reading)); + msg +} + +async fn send_messages(usb: UsbSender<'_>) { + let mut buf = [0; protocol::Msg::<5>::max_size()]; + loop { + let msg = collect_msg().await; + let encoded_len = msg.encode_slice(&mut buf[1..]).len(); + buf[0] = protocol::Msg::<0>::READINGS; + let to_send = &buf[..=encoded_len]; + while let Err(NoSpaceInQueue) = usb.send(to_send, true).await { + usb.wait_till_queue_free().await; + } + } +} diff --git a/nodes/embassy/button-panel/src/main.rs b/nodes/embassy/small-bedroom-button-panel/src/main.rs similarity index 100% rename from nodes/embassy/button-panel/src/main.rs rename to nodes/embassy/small-bedroom-button-panel/src/main.rs diff --git a/nodes/embassy/button-panel/src/usb_wrapper.rs b/nodes/embassy/small-bedroom-button-panel/src/usb_wrapper.rs similarity index 100% rename from nodes/embassy/button-panel/src/usb_wrapper.rs rename to nodes/embassy/small-bedroom-button-panel/src/usb_wrapper.rs diff --git a/nodes/embassy/small-bedroom-button-panel/stm32f401.svd b/nodes/embassy/small-bedroom-button-panel/stm32f401.svd new file mode 100644 index 00000000..b9353d01 --- /dev/null +++ b/nodes/embassy/small-bedroom-button-panel/stm32f401.svd @@ -0,0 +1,35196 @@ + + + STM32F401 + 1.1 + STM32F401 + + CM4 + r1p0 + little + false + false + 4 + false + + 8 + 32 + 0x20 + 0x00000000 + 0xFFFFFFFF + + + ADC_Common + ADC common registers + ADC_Common + 0x40012300 + + 0x0 + 0x9 + registers + + + FPU + FPU interrupt + 81 + + + + CCR + CCR + ADC common control register + 0x4 + 0x20 + read-write + 0x00000000 + + + TSVREFE + Temperature sensor and VREFINT + enable + 23 + 1 + + TSVREFE + read-write + + Disabled + Temperature sensor and V_REFINT channel disabled + 0 + + + Enabled + Temperature sensor and V_REFINT channel enabled + 1 + + + + + VBATE + VBAT enable + 22 + 1 + + VBATE + read-write + + Disabled + V_BAT channel disabled + 0 + + + Enabled + V_BAT channel enabled + 1 + + + + + ADCPRE + ADC prescaler + 16 + 2 + + ADCPRE + read-write + + Div2 + PCLK2 divided by 2 + 0 + + + Div4 + PCLK2 divided by 4 + 1 + + + Div6 + PCLK2 divided by 6 + 2 + + + Div8 + PCLK2 divided by 8 + 3 + + + + + + + + + ADC1 + Analog-to-digital converter + ADC + 0x40012000 + + 0x0 + 0x51 + registers + + + ADC + ADC1 global interrupt + 18 + + + + SR + SR + status register + 0x0 + 0x20 + read-write + 0x00000000 + + + OVR + Overrun + 5 + 1 + zeroToClear + + OVRR + read + + NoOverrun + No overrun occurred + 0 + + + Overrun + Overrun occurred + 1 + + + + OVRW + write + + Clear + Clear flag + 0 + + + + + STRT + Regular channel start flag + 4 + 1 + zeroToClear + + STRTR + read + + NotStarted + No regular channel conversion started + 0 + + + Started + Regular channel conversion has started + 1 + + + + STRTW + write + + Clear + Clear flag + 0 + + + + + JSTRT + Injected channel start + flag + 3 + 1 + zeroToClear + + JSTRTR + read + + NotStarted + No injected channel conversion started + 0 + + + Started + Injected channel conversion has started + 1 + + + + JSTRTW + write + + Clear + Clear flag + 0 + + + + + JEOC + Injected channel end of + conversion + 2 + 1 + zeroToClear + + JEOCR + read + + NotComplete + Conversion is not complete + 0 + + + Complete + Conversion complete + 1 + + + + JEOCW + write + + Clear + Clear flag + 0 + + + + + EOC + Regular channel end of + conversion + 1 + 1 + zeroToClear + + EOCR + read + + NotComplete + Conversion is not complete + 0 + + + Complete + Conversion complete + 1 + + + + EOCW + write + + Clear + Clear flag + 0 + + + + + AWD + Analog watchdog flag + 0 + 1 + zeroToClear + + AWDR + read + + NoEvent + No analog watchdog event occurred + 0 + + + Event + Analog watchdog event occurred + 1 + + + + AWDW + write + + Clear + Clear flag + 0 + + + + + + + CR1 + CR1 + control register 1 + 0x4 + 0x20 + read-write + 0x00000000 + + + OVRIE + Overrun interrupt enable + 26 + 1 + + OVRIE + read-write + + Disabled + Overrun interrupt disabled + 0 + + + Enabled + Overrun interrupt enabled + 1 + + + + + RES + Resolution + 24 + 2 + + RES + read-write + + TwelveBit + 12-bit (15 ADCCLK cycles) + 0 + + + TenBit + 10-bit (13 ADCCLK cycles) + 1 + + + EightBit + 8-bit (11 ADCCLK cycles) + 2 + + + SixBit + 6-bit (9 ADCCLK cycles) + 3 + + + + + AWDEN + Analog watchdog enable on regular + channels + 23 + 1 + + AWDEN + read-write + + Disabled + Analog watchdog disabled on regular channels + 0 + + + Enabled + Analog watchdog enabled on regular channels + 1 + + + + + JAWDEN + Analog watchdog enable on injected + channels + 22 + 1 + + JAWDEN + read-write + + Disabled + Analog watchdog disabled on injected channels + 0 + + + Enabled + Analog watchdog enabled on injected channels + 1 + + + + + DISCNUM + Discontinuous mode channel + count + 13 + 3 + + + 0 + 7 + + + + + JDISCEN + Discontinuous mode on injected + channels + 12 + 1 + + JDISCEN + read-write + + Disabled + Discontinuous mode on injected channels disabled + 0 + + + Enabled + Discontinuous mode on injected channels enabled + 1 + + + + + DISCEN + Discontinuous mode on regular + channels + 11 + 1 + + DISCEN + read-write + + Disabled + Discontinuous mode on regular channels disabled + 0 + + + Enabled + Discontinuous mode on regular channels enabled + 1 + + + + + JAUTO + Automatic injected group + conversion + 10 + 1 + + JAUTO + read-write + + Disabled + Automatic injected group conversion disabled + 0 + + + Enabled + Automatic injected group conversion enabled + 1 + + + + + AWDSGL + Enable the watchdog on a single channel + in scan mode + 9 + 1 + + AWDSGL + read-write + + AllChannels + Analog watchdog enabled on all channels + 0 + + + SingleChannel + Analog watchdog enabled on a single channel + 1 + + + + + SCAN + Scan mode + 8 + 1 + + SCAN + read-write + + Disabled + Scan mode disabled + 0 + + + Enabled + Scan mode enabled + 1 + + + + + JEOCIE + Interrupt enable for injected + channels + 7 + 1 + + JEOCIE + read-write + + Disabled + JEOC interrupt disabled + 0 + + + Enabled + JEOC interrupt enabled + 1 + + + + + AWDIE + Analog watchdog interrupt + enable + 6 + 1 + + AWDIE + read-write + + Disabled + Analogue watchdog interrupt disabled + 0 + + + Enabled + Analogue watchdog interrupt enabled + 1 + + + + + EOCIE + Interrupt enable for EOC + 5 + 1 + + EOCIE + read-write + + Disabled + EOC interrupt disabled + 0 + + + Enabled + EOC interrupt enabled + 1 + + + + + AWDCH + Analog watchdog channel select + bits + 0 + 5 + + + 0 + 18 + + + + + + + CR2 + CR2 + control register 2 + 0x8 + 0x20 + read-write + 0x00000000 + + + SWSTART + Start conversion of regular + channels + 30 + 1 + + SWSTARTW + write + + Start + Starts conversion of regular channels + 1 + + + + + EXTEN + External trigger enable for regular + channels + 28 + 2 + + EXTEN + read-write + + Disabled + Trigger detection disabled + 0 + + + RisingEdge + Trigger detection on the rising edge + 1 + + + FallingEdge + Trigger detection on the falling edge + 2 + + + BothEdges + Trigger detection on both the rising and falling edges + 3 + + + + + EXTSEL + External event select for regular + group + 24 + 4 + + EXTSEL + read-write + + TIM1CC1 + Timer 1 CC1 event + 0 + + + TIM1CC2 + Timer 1 CC2 event + 1 + + + TIM1CC3 + Timer 1 CC3 event + 2 + + + TIM2CC2 + Timer 2 CC2 event + 3 + + + TIM2CC3 + Timer 2 CC3 event + 4 + + + TIM2CC4 + Timer 2 CC4 event + 5 + + + TIM2TRGO + Timer 2 TRGO event + 6 + + + TIM3CC1 + Timer 3 CC1 event + 7 + + + TIM3TRGO + Timer 3 TRGO event + 8 + + + TIM4CC4 + Timer 4 CC4 event + 9 + + + TIM5CC1 + Timer 5 CC1 event + 10 + + + TIM5CC2 + Timer 5 CC2 event + 11 + + + TIM5CC3 + Timer 5 CC3 event + 12 + + + EXTI11 + EXTI line 11 + 15 + + + + + JSWSTART + Start conversion of injected + channels + 22 + 1 + + JSWSTARTW + write + + Start + Starts conversion of injected channels + 1 + + + + + JEXTEN + External trigger enable for injected + channels + 20 + 2 + + JEXTEN + read-write + + Disabled + Trigger detection disabled + 0 + + + RisingEdge + Trigger detection on the rising edge + 1 + + + FallingEdge + Trigger detection on the falling edge + 2 + + + BothEdges + Trigger detection on both the rising and falling edges + 3 + + + + + JEXTSEL + External event select for injected + group + 16 + 4 + + JEXTSEL + read-write + + TIM1CC4 + Timer 1 CC4 event + 0 + + + TIM1TRGO + Timer 1 TRGO event + 1 + + + TIM2CC1 + Timer 2 CC1 event + 2 + + + TIM2TRGO + Timer 2 TRGO event + 3 + + + TIM3CC2 + Timer 3 CC2 event + 4 + + + TIM3CC4 + Timer 3 CC4 event + 5 + + + TIM4CC1 + Timer 4 CC1 event + 6 + + + TIM4CC2 + Timer 4 CC2 event + 7 + + + TIM4CC3 + Timer 4 CC3 event + 8 + + + TIM4TRGO + Timer 4 TRGO event + 9 + + + TIM5CC4 + Timer 5 CC4 event + 10 + + + TIM5TRGO + Timer 5 TRGO event + 11 + + + EXTI15 + EXTI line 15 + 15 + + + + + ALIGN + Data alignment + 11 + 1 + + ALIGN + read-write + + Right + Right alignment + 0 + + + Left + Left alignment + 1 + + + + + EOCS + End of conversion + selection + 10 + 1 + + EOCS + read-write + + EachSequence + The EOC bit is set at the end of each sequence of regular conversions + 0 + + + EachConversion + The EOC bit is set at the end of each regular conversion + 1 + + + + + DDS + DMA disable selection (for single ADC + mode) + 9 + 1 + + DDS + read-write + + Single + No new DMA request is issued after the last transfer + 0 + + + Continuous + DMA requests are issued as long as data are converted and DMA=1 + 1 + + + + + DMA + Direct memory access mode (for single + ADC mode) + 8 + 1 + + DMA + read-write + + Disabled + DMA mode disabled + 0 + + + Enabled + DMA mode enabled + 1 + + + + + CONT + Continuous conversion + 1 + 1 + + CONT + read-write + + Single + Single conversion mode + 0 + + + Continuous + Continuous conversion mode + 1 + + + + + ADON + A/D Converter ON / OFF + 0 + 1 + + ADON + read-write + + Disabled + Disable ADC conversion and go to power down mode + 0 + + + Enabled + Enable ADC + 1 + + + + + + + SMPR1 + SMPR1 + sample time register 1 + 0xC + 0x20 + read-write + 0x00000000 + + + SMP18 + Channel 18 sampling time selection + 24 + 3 + + + + SMP17 + Channel 17 sampling time selection + 21 + 3 + + + + SMP16 + Channel 16 sampling time selection + 18 + 3 + + + + SMP15 + Channel 15 sampling time selection + 15 + 3 + + + + SMP14 + Channel 14 sampling time selection + 12 + 3 + + + + SMP13 + Channel 13 sampling time selection + 9 + 3 + + + + SMP12 + Channel 12 sampling time selection + 6 + 3 + + + + SMP11 + Channel 11 sampling time selection + 3 + 3 + + + + SMP10 + Channel 10 sampling time selection + 0 + 3 + + SMP10 + read-write + + Cycles3 + 3 cycles + 0 + + + Cycles15 + 15 cycles + 1 + + + Cycles28 + 28 cycles + 2 + + + Cycles56 + 56 cycles + 3 + + + Cycles84 + 84 cycles + 4 + + + Cycles112 + 112 cycles + 5 + + + Cycles144 + 144 cycles + 6 + + + Cycles480 + 480 cycles + 7 + + + + + + + SMPR2 + SMPR2 + sample time register 2 + 0x10 + 0x20 + read-write + 0x00000000 + + + SMP9 + Channel 9 sampling time selection + 27 + 3 + + + + SMP8 + Channel 8 sampling time selection + 24 + 3 + + + + SMP7 + Channel 7 sampling time selection + 21 + 3 + + + + SMP6 + Channel 6 sampling time selection + 18 + 3 + + + + SMP5 + Channel 5 sampling time selection + 15 + 3 + + + + SMP4 + Channel 4 sampling time selection + 12 + 3 + + + + SMP3 + Channel 3 sampling time selection + 9 + 3 + + + + SMP2 + Channel 2 sampling time selection + 6 + 3 + + + + SMP1 + Channel 1 sampling time selection + 3 + 3 + + + + SMP0 + Channel 0 sampling time selection + 0 + 3 + + SMP0 + read-write + + Cycles3 + 3 cycles + 0 + + + Cycles15 + 15 cycles + 1 + + + Cycles28 + 28 cycles + 2 + + + Cycles56 + 56 cycles + 3 + + + Cycles84 + 84 cycles + 4 + + + Cycles112 + 112 cycles + 5 + + + Cycles144 + 144 cycles + 6 + + + Cycles480 + 480 cycles + 7 + + + + + + + 4 + 0x4 + 1-4 + JOFR%s + JOFR1 + injected channel data offset register + x + 0x14 + 0x20 + read-write + 0x00000000 + + + JOFFSET + Data offset for injected channel + x + 0 + 12 + + + 0 + 4095 + + + + + + + HTR + HTR + watchdog higher threshold + register + 0x24 + 0x20 + read-write + 0x00000FFF + + + HT + Analog watchdog higher + threshold + 0 + 12 + + + 0 + 4095 + + + + + + + LTR + LTR + watchdog lower threshold + register + 0x28 + 0x20 + read-write + 0x00000000 + + + LT + Analog watchdog lower + threshold + 0 + 12 + + + 0 + 4095 + + + + + + + SQR1 + SQR1 + regular sequence register 1 + 0x2C + 0x20 + read-write + 0x00000000 + + + L + Regular channel sequence + length + 20 + 4 + + + 0 + 15 + + + + + SQ16 + 16th conversion in regular + sequence + 15 + 5 + + + 0 + 18 + + + + + SQ15 + 15th conversion in regular + sequence + 10 + 5 + + + 0 + 18 + + + + + SQ14 + 14th conversion in regular + sequence + 5 + 5 + + + 0 + 18 + + + + + SQ13 + 13th conversion in regular + sequence + 0 + 5 + + + 0 + 18 + + + + + + + SQR2 + SQR2 + regular sequence register 2 + 0x30 + 0x20 + read-write + 0x00000000 + + + SQ12 + 12th conversion in regular + sequence + 25 + 5 + + + 0 + 18 + + + + + SQ11 + 11th conversion in regular + sequence + 20 + 5 + + + 0 + 18 + + + + + SQ10 + 10th conversion in regular + sequence + 15 + 5 + + + 0 + 18 + + + + + SQ9 + 9th conversion in regular + sequence + 10 + 5 + + + 0 + 18 + + + + + SQ8 + 8th conversion in regular + sequence + 5 + 5 + + + 0 + 18 + + + + + SQ7 + 7th conversion in regular + sequence + 0 + 5 + + + 0 + 18 + + + + + + + SQR3 + SQR3 + regular sequence register 3 + 0x34 + 0x20 + read-write + 0x00000000 + + + SQ6 + 6th conversion in regular + sequence + 25 + 5 + + + 0 + 18 + + + + + SQ5 + 5th conversion in regular + sequence + 20 + 5 + + + 0 + 18 + + + + + SQ4 + 4th conversion in regular + sequence + 15 + 5 + + + 0 + 18 + + + + + SQ3 + 3rd conversion in regular + sequence + 10 + 5 + + + 0 + 18 + + + + + SQ2 + 2nd conversion in regular + sequence + 5 + 5 + + + 0 + 18 + + + + + SQ1 + 1st conversion in regular + sequence + 0 + 5 + + + 0 + 18 + + + + + + + JSQR + JSQR + injected sequence register + 0x38 + 0x20 + read-write + 0x00000000 + + + JL + Injected sequence length + 20 + 2 + + + 0 + 3 + + + + + JSQ4 + 4th conversion in injected + sequence + 15 + 5 + + + 0 + 18 + + + + + JSQ3 + 3rd conversion in injected + sequence + 10 + 5 + + + 0 + 18 + + + + + JSQ2 + 2nd conversion in injected + sequence + 5 + 5 + + + 0 + 18 + + + + + JSQ1 + 1st conversion in injected + sequence + 0 + 5 + + + 0 + 18 + + + + + + + 4 + 0x4 + 1-4 + JDR%s + JDR1 + injected data register x + 0x3C + 0x20 + read-only + 0x00000000 + + + JDATA + Injected data + 0 + 16 + + + + + DR + DR + regular data register + 0x4C + 0x20 + read-only + 0x00000000 + + + DATA + Regular data + 0 + 16 + + + + + + + CRC + Cryptographic processor + CRC + 0x40023000 + + 0x0 + 0x400 + registers + + + + DR + DR + Data register + 0x0 + 0x20 + read-write + 0xFFFFFFFF + + + DR + Data Register + 0 + 32 + + + 0 + 4294967295 + + + + + + + IDR + IDR + Independent Data register + 0x4 + 0x20 + read-write + 0x00000000 + + + IDR + Independent Data register + 0 + 8 + + + 0 + 255 + + + + + + + CR + CR + Control register + 0x8 + 0x20 + write-only + 0x00000000 + + + RESET + Control regidter + 0 + 1 + + RESETW + write + + Reset + Resets the CRC calculation unit and sets the data register to 0xFFFF FFFF + 1 + + + + + + + + + DBGMCU + Debug support + DBG + 0xE0042000 + + 0x0 + 0x400 + registers + + + + IDCODE + IDCODE + IDCODE + 0x0 + 0x20 + read-only + 0x10006411 + + + DEV_ID + DEV_ID + 0 + 12 + + + REV_ID + REV_ID + 16 + 16 + + + + + CR + CR + Control Register + 0x4 + 0x20 + read-write + 0x00000000 + + + DBG_SLEEP + DBG_SLEEP + 0 + 1 + + + DBG_STOP + DBG_STOP + 1 + 1 + + + DBG_STANDBY + DBG_STANDBY + 2 + 1 + + + TRACE_IOEN + TRACE_IOEN + 5 + 1 + + + TRACE_MODE + TRACE_MODE + 6 + 2 + + + + + APB1_FZ + APB1_FZ + Debug MCU APB1 Freeze registe + 0x8 + 0x20 + read-write + 0x00000000 + + + DBG_TIM2_STOP + DBG_TIM2_STOP + 0 + 1 + + + DBG_TIM3_STOP + DBG_TIM3 _STOP + 1 + 1 + + + DBG_TIM4_STOP + DBG_TIM4_STOP + 2 + 1 + + + DBG_TIM5_STOP + DBG_TIM5_STOP + 3 + 1 + + + DBG_RTC_Stop + RTC stopped when Core is + halted + 10 + 1 + + + DBG_WWDG_STOP + DBG_WWDG_STOP + 11 + 1 + + + DBG_IWDG_STOP + DBG_IWDEG_STOP + 12 + 1 + + + DBG_I2C1_SMBUS_TIMEOUT + DBG_J2C1_SMBUS_TIMEOUT + 21 + 1 + + + DBG_I2C2_SMBUS_TIMEOUT + DBG_J2C2_SMBUS_TIMEOUT + 22 + 1 + + + DBG_I2C3SMBUS_TIMEOUT + DBG_J2C3SMBUS_TIMEOUT + 23 + 1 + + + + + APB2_FZ + APB2_FZ + Debug MCU APB2 Freeze registe + 0xC + 0x20 + read-write + 0x00000000 + + + DBG_TIM1_STOP + TIM1 counter stopped when core is + halted + 0 + 1 + + + DBG_TIM9_STOP + TIM9 counter stopped when core is + halted + 16 + 1 + + + DBG_TIM10_STOP + TIM10 counter stopped when core is + halted + 17 + 1 + + + DBG_TIM11_STOP + TIM11 counter stopped when core is + halted + 18 + 1 + + + + + + + EXTI + External interrupt/event + controller + EXTI + 0x40013C00 + + 0x0 + 0x400 + registers + + + TAMP_STAMP + Tamper and TimeStamp interrupts through the + EXTI line + 2 + + + EXTI0 + EXTI Line0 interrupt + 6 + + + EXTI1 + EXTI Line1 interrupt + 7 + + + EXTI2 + EXTI Line2 interrupt + 8 + + + EXTI3 + EXTI Line3 interrupt + 9 + + + EXTI4 + EXTI Line4 interrupt + 10 + + + EXTI9_5 + EXTI Line[9:5] interrupts + 23 + + + EXTI15_10 + EXTI Line[15:10] interrupts + 40 + + + + IMR + IMR + Interrupt mask register + (EXTI_IMR) + 0x0 + 0x20 + read-write + 0x00000000 + + + MR0 + Interrupt Mask on line 0 + 0 + 1 + + MR0 + read-write + + Masked + Interrupt request line is masked + 0 + + + Unmasked + Interrupt request line is unmasked + 1 + + + + + MR1 + Interrupt Mask on line 1 + 1 + 1 + + + + MR2 + Interrupt Mask on line 2 + 2 + 1 + + + + MR3 + Interrupt Mask on line 3 + 3 + 1 + + + + MR4 + Interrupt Mask on line 4 + 4 + 1 + + + + MR5 + Interrupt Mask on line 5 + 5 + 1 + + + + MR6 + Interrupt Mask on line 6 + 6 + 1 + + + + MR7 + Interrupt Mask on line 7 + 7 + 1 + + + + MR8 + Interrupt Mask on line 8 + 8 + 1 + + + + MR9 + Interrupt Mask on line 9 + 9 + 1 + + + + MR10 + Interrupt Mask on line 10 + 10 + 1 + + + + MR11 + Interrupt Mask on line 11 + 11 + 1 + + + + MR12 + Interrupt Mask on line 12 + 12 + 1 + + + + MR13 + Interrupt Mask on line 13 + 13 + 1 + + + + MR14 + Interrupt Mask on line 14 + 14 + 1 + + + + MR15 + Interrupt Mask on line 15 + 15 + 1 + + + + MR16 + Interrupt Mask on line 16 + 16 + 1 + + + + MR17 + Interrupt Mask on line 17 + 17 + 1 + + + + MR18 + Interrupt Mask on line 18 + 18 + 1 + + + + MR19 + Interrupt Mask on line 19 + 19 + 1 + + + + MR20 + Interrupt Mask on line 20 + 20 + 1 + + + + MR21 + Interrupt Mask on line 21 + 21 + 1 + + + + MR22 + Interrupt Mask on line 22 + 22 + 1 + + + + + + EMR + EMR + Event mask register (EXTI_EMR) + 0x4 + 0x20 + read-write + 0x00000000 + + + MR0 + Event Mask on line 0 + 0 + 1 + + MR0 + read-write + + Masked + Interrupt request line is masked + 0 + + + Unmasked + Interrupt request line is unmasked + 1 + + + + + MR1 + Event Mask on line 1 + 1 + 1 + + + + MR2 + Event Mask on line 2 + 2 + 1 + + + + MR3 + Event Mask on line 3 + 3 + 1 + + + + MR4 + Event Mask on line 4 + 4 + 1 + + + + MR5 + Event Mask on line 5 + 5 + 1 + + + + MR6 + Event Mask on line 6 + 6 + 1 + + + + MR7 + Event Mask on line 7 + 7 + 1 + + + + MR8 + Event Mask on line 8 + 8 + 1 + + + + MR9 + Event Mask on line 9 + 9 + 1 + + + + MR10 + Event Mask on line 10 + 10 + 1 + + + + MR11 + Event Mask on line 11 + 11 + 1 + + + + MR12 + Event Mask on line 12 + 12 + 1 + + + + MR13 + Event Mask on line 13 + 13 + 1 + + + + MR14 + Event Mask on line 14 + 14 + 1 + + + + MR15 + Event Mask on line 15 + 15 + 1 + + + + MR16 + Event Mask on line 16 + 16 + 1 + + + + MR17 + Event Mask on line 17 + 17 + 1 + + + + MR18 + Event Mask on line 18 + 18 + 1 + + + + MR19 + Event Mask on line 19 + 19 + 1 + + + + MR20 + Event Mask on line 20 + 20 + 1 + + + + MR21 + Event Mask on line 21 + 21 + 1 + + + + MR22 + Event Mask on line 22 + 22 + 1 + + + + + + RTSR + RTSR + Rising Trigger selection register + (EXTI_RTSR) + 0x8 + 0x20 + read-write + 0x00000000 + + + TR0 + Rising trigger event configuration of + line 0 + 0 + 1 + + TR0 + read-write + + Disabled + Rising edge trigger is disabled + 0 + + + Enabled + Rising edge trigger is enabled + 1 + + + + + TR1 + Rising trigger event configuration of + line 1 + 1 + 1 + + + + TR2 + Rising trigger event configuration of + line 2 + 2 + 1 + + + + TR3 + Rising trigger event configuration of + line 3 + 3 + 1 + + + + TR4 + Rising trigger event configuration of + line 4 + 4 + 1 + + + + TR5 + Rising trigger event configuration of + line 5 + 5 + 1 + + + + TR6 + Rising trigger event configuration of + line 6 + 6 + 1 + + + + TR7 + Rising trigger event configuration of + line 7 + 7 + 1 + + + + TR8 + Rising trigger event configuration of + line 8 + 8 + 1 + + + + TR9 + Rising trigger event configuration of + line 9 + 9 + 1 + + + + TR10 + Rising trigger event configuration of + line 10 + 10 + 1 + + + + TR11 + Rising trigger event configuration of + line 11 + 11 + 1 + + + + TR12 + Rising trigger event configuration of + line 12 + 12 + 1 + + + + TR13 + Rising trigger event configuration of + line 13 + 13 + 1 + + + + TR14 + Rising trigger event configuration of + line 14 + 14 + 1 + + + + TR15 + Rising trigger event configuration of + line 15 + 15 + 1 + + + + TR16 + Rising trigger event configuration of + line 16 + 16 + 1 + + + + TR17 + Rising trigger event configuration of + line 17 + 17 + 1 + + + + TR18 + Rising trigger event configuration of + line 18 + 18 + 1 + + + + TR19 + Rising trigger event configuration of + line 19 + 19 + 1 + + + + TR20 + Rising trigger event configuration of + line 20 + 20 + 1 + + + + TR21 + Rising trigger event configuration of + line 21 + 21 + 1 + + + + TR22 + Rising trigger event configuration of + line 22 + 22 + 1 + + + + + + FTSR + FTSR + Falling Trigger selection register + (EXTI_FTSR) + 0xC + 0x20 + read-write + 0x00000000 + + + TR0 + Falling trigger event configuration of + line 0 + 0 + 1 + + TR0 + read-write + + Disabled + Falling edge trigger is disabled + 0 + + + Enabled + Falling edge trigger is enabled + 1 + + + + + TR1 + Falling trigger event configuration of + line 1 + 1 + 1 + + + + TR2 + Falling trigger event configuration of + line 2 + 2 + 1 + + + + TR3 + Falling trigger event configuration of + line 3 + 3 + 1 + + + + TR4 + Falling trigger event configuration of + line 4 + 4 + 1 + + + + TR5 + Falling trigger event configuration of + line 5 + 5 + 1 + + + + TR6 + Falling trigger event configuration of + line 6 + 6 + 1 + + + + TR7 + Falling trigger event configuration of + line 7 + 7 + 1 + + + + TR8 + Falling trigger event configuration of + line 8 + 8 + 1 + + + + TR9 + Falling trigger event configuration of + line 9 + 9 + 1 + + + + TR10 + Falling trigger event configuration of + line 10 + 10 + 1 + + + + TR11 + Falling trigger event configuration of + line 11 + 11 + 1 + + + + TR12 + Falling trigger event configuration of + line 12 + 12 + 1 + + + + TR13 + Falling trigger event configuration of + line 13 + 13 + 1 + + + + TR14 + Falling trigger event configuration of + line 14 + 14 + 1 + + + + TR15 + Falling trigger event configuration of + line 15 + 15 + 1 + + + + TR16 + Falling trigger event configuration of + line 16 + 16 + 1 + + + + TR17 + Falling trigger event configuration of + line 17 + 17 + 1 + + + + TR18 + Falling trigger event configuration of + line 18 + 18 + 1 + + + + TR19 + Falling trigger event configuration of + line 19 + 19 + 1 + + + + TR20 + Falling trigger event configuration of + line 20 + 20 + 1 + + + + TR21 + Falling trigger event configuration of + line 21 + 21 + 1 + + + + TR22 + Falling trigger event configuration of + line 22 + 22 + 1 + + + + + + SWIER + SWIER + Software interrupt event register + (EXTI_SWIER) + 0x10 + 0x20 + read-write + 0x00000000 + + + SWIER0 + Software Interrupt on line + 0 + 0 + 1 + + SWIER0W + write + + Pend + Generates an interrupt request + 1 + + + + + SWIER1 + Software Interrupt on line + 1 + 1 + 1 + + + + SWIER2 + Software Interrupt on line + 2 + 2 + 1 + + + + SWIER3 + Software Interrupt on line + 3 + 3 + 1 + + + + SWIER4 + Software Interrupt on line + 4 + 4 + 1 + + + + SWIER5 + Software Interrupt on line + 5 + 5 + 1 + + + + SWIER6 + Software Interrupt on line + 6 + 6 + 1 + + + + SWIER7 + Software Interrupt on line + 7 + 7 + 1 + + + + SWIER8 + Software Interrupt on line + 8 + 8 + 1 + + + + SWIER9 + Software Interrupt on line + 9 + 9 + 1 + + + + SWIER10 + Software Interrupt on line + 10 + 10 + 1 + + + + SWIER11 + Software Interrupt on line + 11 + 11 + 1 + + + + SWIER12 + Software Interrupt on line + 12 + 12 + 1 + + + + SWIER13 + Software Interrupt on line + 13 + 13 + 1 + + + + SWIER14 + Software Interrupt on line + 14 + 14 + 1 + + + + SWIER15 + Software Interrupt on line + 15 + 15 + 1 + + + + SWIER16 + Software Interrupt on line + 16 + 16 + 1 + + + + SWIER17 + Software Interrupt on line + 17 + 17 + 1 + + + + SWIER18 + Software Interrupt on line + 18 + 18 + 1 + + + + SWIER19 + Software Interrupt on line + 19 + 19 + 1 + + + + SWIER20 + Software Interrupt on line + 20 + 20 + 1 + + + + SWIER21 + Software Interrupt on line + 21 + 21 + 1 + + + + SWIER22 + Software Interrupt on line + 22 + 22 + 1 + + + + + + PR + PR + Pending register (EXTI_PR) + 0x14 + 0x20 + read-write + 0x00000000 + + + PR0 + Pending bit 0 + 0 + 1 + oneToClear + + PR0R + read + + NotPending + No trigger request occurred + 0 + + + Pending + Selected trigger request occurred + 1 + + + + PR0W + write + + Clear + Clears pending bit + 1 + + + + + PR1 + Pending bit 1 + 1 + 1 + oneToClear + + read + + + write + + + + PR2 + Pending bit 2 + 2 + 1 + oneToClear + + read + + + write + + + + PR3 + Pending bit 3 + 3 + 1 + oneToClear + + read + + + write + + + + PR4 + Pending bit 4 + 4 + 1 + oneToClear + + read + + + write + + + + PR5 + Pending bit 5 + 5 + 1 + oneToClear + + read + + + write + + + + PR6 + Pending bit 6 + 6 + 1 + oneToClear + + read + + + write + + + + PR7 + Pending bit 7 + 7 + 1 + oneToClear + + read + + + write + + + + PR8 + Pending bit 8 + 8 + 1 + oneToClear + + read + + + write + + + + PR9 + Pending bit 9 + 9 + 1 + oneToClear + + read + + + write + + + + PR10 + Pending bit 10 + 10 + 1 + oneToClear + + read + + + write + + + + PR11 + Pending bit 11 + 11 + 1 + oneToClear + + read + + + write + + + + PR12 + Pending bit 12 + 12 + 1 + oneToClear + + read + + + write + + + + PR13 + Pending bit 13 + 13 + 1 + oneToClear + + read + + + write + + + + PR14 + Pending bit 14 + 14 + 1 + oneToClear + + read + + + write + + + + PR15 + Pending bit 15 + 15 + 1 + oneToClear + + read + + + write + + + + PR16 + Pending bit 16 + 16 + 1 + oneToClear + + read + + + write + + + + PR17 + Pending bit 17 + 17 + 1 + oneToClear + + read + + + write + + + + PR18 + Pending bit 18 + 18 + 1 + oneToClear + + read + + + write + + + + PR19 + Pending bit 19 + 19 + 1 + oneToClear + + read + + + write + + + + PR20 + Pending bit 20 + 20 + 1 + oneToClear + + read + + + write + + + + PR21 + Pending bit 21 + 21 + 1 + oneToClear + + read + + + write + + + + PR22 + Pending bit 22 + 22 + 1 + oneToClear + + read + + + write + + + + + + + + FLASH + FLASH + FLASH + 0x40023C00 + + 0x0 + 0x400 + registers + + + FLASH + FLASH global interrupt + 4 + + + + ACR + ACR + Flash access control register + 0x0 + 0x20 + 0x00000000 + + + LATENCY + Latency + 0 + 4 + read-write + + LATENCY + read-write + + WS0 + 0 wait states + 0 + + + WS1 + 1 wait states + 1 + + + WS2 + 2 wait states + 2 + + + WS3 + 3 wait states + 3 + + + WS4 + 4 wait states + 4 + + + WS5 + 5 wait states + 5 + + + WS6 + 6 wait states + 6 + + + WS7 + 7 wait states + 7 + + + WS8 + 8 wait states + 8 + + + WS9 + 9 wait states + 9 + + + WS10 + 10 wait states + 10 + + + WS11 + 11 wait states + 11 + + + WS12 + 12 wait states + 12 + + + WS13 + 13 wait states + 13 + + + WS14 + 14 wait states + 14 + + + WS15 + 15 wait states + 15 + + + + + PRFTEN + Prefetch enable + 8 + 1 + read-write + + PRFTEN + read-write + + Disabled + Prefetch is disabled + 0 + + + Enabled + Prefetch is enabled + 1 + + + + + ICEN + Instruction cache enable + 9 + 1 + read-write + + ICEN + read-write + + Disabled + Instruction cache is disabled + 0 + + + Enabled + Instruction cache is enabled + 1 + + + + + DCEN + Data cache enable + 10 + 1 + read-write + + DCEN + read-write + + Disabled + Data cache is disabled + 0 + + + Enabled + Data cache is enabled + 1 + + + + + ICRST + Instruction cache reset + 11 + 1 + write-only + + ICRST + write + + NotReset + Instruction cache is not reset + 0 + + + Reset + Instruction cache is reset + 1 + + + + + DCRST + Data cache reset + 12 + 1 + read-write + + DCRST + read-write + + NotReset + Data cache is not reset + 0 + + + Reset + Data cache is reset + 1 + + + + + + + KEYR + KEYR + Flash key register + 0x4 + 0x20 + write-only + 0x00000000 + + + KEY + FPEC key + 0 + 32 + + + 0 + 4294967295 + + + + + + + OPTKEYR + OPTKEYR + Flash option key register + 0x8 + 0x20 + write-only + 0x00000000 + + + OPTKEY + Option byte key + 0 + 32 + + + 0 + 4294967295 + + + + + + + SR + SR + Status register + 0xC + 0x20 + 0x00000000 + + + EOP + End of operation + 0 + 1 + read-write + oneToClear + + EOPW + write + + Clear + Clear error flag + 1 + + + + + OPERR + Operation error + 1 + 1 + read-write + oneToClear + + OPERRW + write + + Clear + Clear error flag + 1 + + + + + WRPERR + Write protection error + 4 + 1 + read-write + oneToClear + + WRPERRW + write + + Clear + Clear error flag + 1 + + + + + PGAERR + Programming alignment + error + 5 + 1 + read-write + oneToClear + + PGAERRW + write + + Clear + Clear error flag + 1 + + + + + PGPERR + Programming parallelism + error + 6 + 1 + read-write + oneToClear + + PGPERRW + write + + Clear + Clear error flag + 1 + + + + + PGSERR + Programming sequence error + 7 + 1 + read-write + oneToClear + + PGSERRW + write + + Clear + Clear error flag + 1 + + + + + BSY + Busy + 16 + 1 + read-only + + BSYR + read + + NotBusy + no Flash memory operation ongoing + 0 + + + Busy + Flash memory operation ongoing + 1 + + + + + + + CR + CR + Control register + 0x10 + 0x20 + read-write + 0x80000000 + + + PG + Programming + 0 + 1 + + PG + read-write + + Program + Flash programming activated + 1 + + + + + SER + Sector Erase + 1 + 1 + + SER + read-write + + SectorErase + Erase activated for selected sector + 1 + + + + + MER + Mass Erase + 2 + 1 + + MER + read-write + + MassErase + Erase activated for all user sectors + 1 + + + + + SNB + Sector number + 3 + 4 + + + 0 + 11 + + + + + PSIZE + Program size + 8 + 2 + + PSIZE + read-write + + PSIZE8 + Program x8 + 0 + + + PSIZE16 + Program x16 + 1 + + + PSIZE32 + Program x32 + 2 + + + PSIZE64 + Program x64 + 3 + + + + + STRT + Start + 16 + 1 + + STRT + read-write + + Start + Trigger an erase operation + 1 + + + + + EOPIE + End of operation interrupt + enable + 24 + 1 + + EOPIE + read-write + + Disabled + End of operation interrupt disabled + 0 + + + Enabled + End of operation interrupt enabled + 1 + + + + + ERRIE + Error interrupt enable + 25 + 1 + + ERRIE + read-write + + Disabled + Error interrupt generation disabled + 0 + + + Enabled + Error interrupt generation enabled + 1 + + + + + LOCK + Lock + 31 + 1 + + LOCK + read-write + + Unlocked + FLASH_CR register is unlocked + 0 + + + Locked + FLASH_CR register is locked + 1 + + + + + + + OPTCR + OPTCR + Flash option control register + 0x14 + 0x20 + read-write + 0x00000014 + + + OPTLOCK + Option lock + 0 + 1 + + + OPTSTRT + Option start + 1 + 1 + + + BOR_LEV + BOR reset Level + 2 + 2 + + + WDG_SW + WDG_SW User option bytes + 5 + 1 + + + nRST_STOP + nRST_STOP User option + bytes + 6 + 1 + + + nRST_STDBY + nRST_STDBY User option + bytes + 7 + 1 + + + RDP + Read protect + 8 + 8 + + + nWRP + Not write protect + 16 + 12 + + + + + + + IWDG + Independent watchdog + IWDG + 0x40003000 + + 0x0 + 0x400 + registers + + + + KR + KR + Key register + 0x0 + 0x20 + write-only + 0x00000000 + + + KEY + Key value + 0 + 16 + + KEY + write + + Enable + Enable access to PR, RLR and WINR registers (0x5555) + 21845 + + + Reset + Reset the watchdog value (0xAAAA) + 43690 + + + Start + Start the watchdog (0xCCCC) + 52428 + + + + + + + PR + PR + Prescaler register + 0x4 + 0x20 + read-write + 0x00000000 + + + PR + Prescaler divider + 0 + 3 + + PR + read-write + + DivideBy4 + Divider /4 + 0 + + + DivideBy8 + Divider /8 + 1 + + + DivideBy16 + Divider /16 + 2 + + + DivideBy32 + Divider /32 + 3 + + + DivideBy64 + Divider /64 + 4 + + + DivideBy128 + Divider /128 + 5 + + + DivideBy256 + Divider /256 + 6 + + + DivideBy256bis + Divider /256 + 7 + + + + + + + RLR + RLR + Reload register + 0x8 + 0x20 + read-write + 0x00000FFF + + + RL + Watchdog counter reload + value + 0 + 12 + + + 0 + 4095 + + + + + + + SR + SR + Status register + 0xC + 0x20 + read-only + 0x00000000 + + + RVU + Watchdog counter reload value + update + 1 + 1 + + + PVU + Watchdog prescaler value + update + 0 + 1 + + + + + + + OTG_FS_DEVICE + USB on the go full speed + USB_OTG_FS + 0x50000800 + + 0x0 + 0x400 + registers + + + + DCFG + DCFG + OTG_FS device configuration register + (OTG_FS_DCFG) + 0x0 + 0x20 + read-write + 0x02200000 + + + DSPD + Device speed + 0 + 2 + + + NZLSOHSK + Non-zero-length status OUT + handshake + 2 + 1 + + + DAD + Device address + 4 + 7 + + + PFIVL + Periodic frame interval + 11 + 2 + + + + + DCTL + DCTL + OTG_FS device control register + (OTG_FS_DCTL) + 0x4 + 0x20 + 0x00000000 + + + RWUSIG + Remote wakeup signaling + 0 + 1 + read-write + + + SDIS + Soft disconnect + 1 + 1 + read-write + + + GINSTS + Global IN NAK status + 2 + 1 + read-only + + + GONSTS + Global OUT NAK status + 3 + 1 + read-only + + + TCTL + Test control + 4 + 3 + read-write + + + SGINAK + Set global IN NAK + 7 + 1 + read-write + + + CGINAK + Clear global IN NAK + 8 + 1 + read-write + + + SGONAK + Set global OUT NAK + 9 + 1 + read-write + + + CGONAK + Clear global OUT NAK + 10 + 1 + read-write + + + POPRGDNE + Power-on programming done + 11 + 1 + read-write + + + + + DSTS + DSTS + OTG_FS device status register + (OTG_FS_DSTS) + 0x8 + 0x20 + read-only + 0x00000010 + + + SUSPSTS + Suspend status + 0 + 1 + + + ENUMSPD + Enumerated speed + 1 + 2 + + + EERR + Erratic error + 3 + 1 + + + FNSOF + Frame number of the received + SOF + 8 + 14 + + + + + DIEPMSK + DIEPMSK + OTG_FS device IN endpoint common interrupt + mask register (OTG_FS_DIEPMSK) + 0x10 + 0x20 + read-write + 0x00000000 + + + XFRCM + Transfer completed interrupt + mask + 0 + 1 + + + EPDM + Endpoint disabled interrupt + mask + 1 + 1 + + + TOM + Timeout condition mask (Non-isochronous + endpoints) + 3 + 1 + + + ITTXFEMSK + IN token received when TxFIFO empty + mask + 4 + 1 + + + INEPNMM + IN token received with EP mismatch + mask + 5 + 1 + + + INEPNEM + IN endpoint NAK effective + mask + 6 + 1 + + + + + DOEPMSK + DOEPMSK + OTG_FS device OUT endpoint common interrupt + mask register (OTG_FS_DOEPMSK) + 0x14 + 0x20 + read-write + 0x00000000 + + + XFRCM + Transfer completed interrupt + mask + 0 + 1 + + + EPDM + Endpoint disabled interrupt + mask + 1 + 1 + + + STUPM + SETUP phase done mask + 3 + 1 + + + OTEPDM + OUT token received when endpoint + disabled mask + 4 + 1 + + + + + DAINT + DAINT + OTG_FS device all endpoints interrupt + register (OTG_FS_DAINT) + 0x18 + 0x20 + read-only + 0x00000000 + + + IEPINT + IN endpoint interrupt bits + 0 + 16 + + + OEPINT + OUT endpoint interrupt + bits + 16 + 16 + + + + + DAINTMSK + DAINTMSK + OTG_FS all endpoints interrupt mask register + (OTG_FS_DAINTMSK) + 0x1C + 0x20 + read-write + 0x00000000 + + + IEPM + IN EP interrupt mask bits + 0 + 16 + + + OEPM + OUT EP interrupt mask bits + 16 + 16 + + + + + DVBUSDIS + DVBUSDIS + OTG_FS device VBUS discharge time + register + 0x28 + 0x20 + read-write + 0x000017D7 + + + VBUSDT + Device VBUS discharge time + 0 + 16 + + + + + DVBUSPULSE + DVBUSPULSE + OTG_FS device VBUS pulsing time + register + 0x2C + 0x20 + read-write + 0x000005B8 + + + DVBUSP + Device VBUS pulsing time + 0 + 12 + + + + + DIEPEMPMSK + DIEPEMPMSK + OTG_FS device IN endpoint FIFO empty + interrupt mask register + 0x34 + 0x20 + read-write + 0x00000000 + + + INEPTXFEM + IN EP Tx FIFO empty interrupt mask + bits + 0 + 16 + + + + + DIEP0 + Device IN endpoint 0 + 0x100 + + CTL + DIEPCTL0 + OTG_FS device control IN endpoint 0 control + register (OTG_FS_DIEPCTL0) + 0x0 + 0x20 + 0x00000000 + + + MPSIZ + Maximum packet size + 0 + 2 + read-write + + + USBAEP + USB active endpoint + 15 + 1 + read-only + + + NAKSTS + NAK status + 17 + 1 + read-only + + + EPTYP + Endpoint type + 18 + 2 + read-only + + + STALL + STALL handshake + 21 + 1 + read-write + + + TXFNUM + TxFIFO number + 22 + 4 + read-write + + + CNAK + Clear NAK + 26 + 1 + write-only + + + SNAK + Set NAK + 27 + 1 + write-only + + + EPDIS + Endpoint disable + 30 + 1 + read-only + + + EPENA + Endpoint enable + 31 + 1 + read-write + + + + + INT + DIEPINT0 + device endpoint-x interrupt + register + 0x8 + 0x20 + 0x00000080 + + + TXFE + TXFE + 7 + 1 + read-only + + + INEPNE + INEPNE + 6 + 1 + read-write + + + ITTXFE + ITTXFE + 4 + 1 + read-write + + + TOC + TOC + 3 + 1 + read-write + + + EPDISD + EPDISD + 1 + 1 + read-write + + + XFRC + XFRC + 0 + 1 + read-write + + + + + TSIZ + DIEPTSIZ0 + device endpoint-0 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + PKTCNT + Packet count + 19 + 2 + + + XFRSIZ + Transfer size + 0 + 7 + + + + + TXFSTS + DTXFSTS0 + OTG_FS device IN endpoint transmit FIFO + status register + 0x18 + 0x20 + read-only + 0x00000000 + + + INEPTFSAV + IN endpoint TxFIFO space + available + 0 + 16 + + + + + + 3 + 0x20 + 1-3 + DIEP%s + Device IN endpoint X + 0x120 + + CTL + DIEPCTL1 + OTG device endpoint-1 control + register + 0x0 + 0x20 + 0x00000000 + + + EPENA + EPENA + 31 + 1 + read-write + + + EPDIS + EPDIS + 30 + 1 + read-write + + + SODDFRM_SD1PID + SODDFRM/SD1PID + 29 + 1 + write-only + + + SD0PID_SEVNFRM + SD0PID/SEVNFRM + 28 + 1 + write-only + + + SNAK + SNAK + 27 + 1 + write-only + + + CNAK + CNAK + 26 + 1 + write-only + + + TXFNUM + TXFNUM + 22 + 4 + read-write + + + STALL + STALL handshake + 21 + 1 + read-write + + + EPTYP + EPTYP + 18 + 2 + read-write + + + NAKSTS + NAKSTS + 17 + 1 + read-only + + + EONUM_DPID + EONUM/DPID + 16 + 1 + read-only + + + USBAEP + USBAEP + 15 + 1 + read-write + + + MPSIZ + MPSIZ + 0 + 11 + read-write + + + + + INT + DIEPINT1 + device endpoint-1 interrupt + register + 0x8 + 0x20 + 0x00000080 + + + TXFE + TXFE + 7 + 1 + read-only + + + INEPNE + INEPNE + 6 + 1 + read-write + + + ITTXFE + ITTXFE + 4 + 1 + read-write + + + TOC + TOC + 3 + 1 + read-write + + + EPDISD + EPDISD + 1 + 1 + read-write + + + XFRC + XFRC + 0 + 1 + read-write + + + + + TSIZ + DIEPTSIZ1 + device endpoint-1 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + MCNT + Multi count + 29 + 2 + + + PKTCNT + Packet count + 19 + 10 + + + XFRSIZ + Transfer size + 0 + 19 + + + + + TXFSTS + DTXFSTS1 + OTG_FS device IN endpoint transmit FIFO + status register + 0x18 + 0x20 + read-only + 0x00000000 + + + INEPTFSAV + IN endpoint TxFIFO space + available + 0 + 16 + + + + + + DOEP0 + Device OUT endpoint 0 + 0x300 + + CTL + DOEPCTL0 + device endpoint-0 control + register + 0x0 + 0x20 + 0x00008000 + + + EPENA + EPENA + 31 + 1 + read-write + + + EPDIS + EPDIS + 30 + 1 + read-only + + + SNAK + SNAK + 27 + 1 + write-only + + + CNAK + CNAK + 26 + 1 + write-only + + + STALL + STALL handshake + 21 + 1 + read-write + + + SNPM + SNPM + 20 + 1 + read-write + + + EPTYP + EPTYP + 18 + 2 + read-only + + + NAKSTS + NAKSTS + 17 + 1 + read-only + + + USBAEP + USBAEP + 15 + 1 + read-only + + + MPSIZ + MPSIZ + 0 + 2 + read-only + + + + + INT + DOEPINT0 + device endpoint-0 interrupt + register + 0x8 + 0x20 + read-write + 0x00000080 + + + B2BSTUP + B2BSTUP + 6 + 1 + + + OTEPDIS + OTEPDIS + 4 + 1 + + + STUP + STUP + 3 + 1 + + + EPDISD + EPDISD + 1 + 1 + + + XFRC + XFRC + 0 + 1 + + + + + TSIZ + DOEPTSIZ0 + device OUT endpoint-0 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + STUPCNT + SETUP packet count + 29 + 2 + + + PKTCNT + Packet count + 19 + 1 + + + XFRSIZ + Transfer size + 0 + 7 + + + + + + 3 + 0x20 + 1-3 + DOEP%s + Device IN endpoint X + 0x320 + + CTL + DOEPCTL1 + device endpoint-1 control + register + 0x0 + 0x20 + 0x00000000 + + + EPENA + EPENA + 31 + 1 + read-write + + + EPDIS + EPDIS + 30 + 1 + read-write + + + SODDFRM + SODDFRM + 29 + 1 + write-only + + + SD0PID_SEVNFRM + SD0PID/SEVNFRM + 28 + 1 + write-only + + + SNAK + SNAK + 27 + 1 + write-only + + + CNAK + CNAK + 26 + 1 + write-only + + + STALL + STALL handshake + 21 + 1 + read-write + + + SNPM + SNPM + 20 + 1 + read-write + + + EPTYP + EPTYP + 18 + 2 + read-write + + + NAKSTS + NAKSTS + 17 + 1 + read-only + + + EONUM_DPID + EONUM/DPID + 16 + 1 + read-only + + + USBAEP + USBAEP + 15 + 1 + read-write + + + MPSIZ + MPSIZ + 0 + 11 + read-write + + + + + INT + DOEPINT1 + device endpoint-1 interrupt + register + 0x8 + 0x20 + read-write + 0x00000080 + + + B2BSTUP + B2BSTUP + 6 + 1 + + + OTEPDIS + OTEPDIS + 4 + 1 + + + STUP + STUP + 3 + 1 + + + EPDISD + EPDISD + 1 + 1 + + + XFRC + XFRC + 0 + 1 + + + + + TSIZ + DOEPTSIZ1 + device OUT endpoint-1 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + RXDPID_STUPCNT + Received data PID/SETUP packet + count + 29 + 2 + + + PKTCNT + Packet count + 19 + 10 + + + XFRSIZ + Transfer size + 0 + 19 + + + + + + + + OTG_FS_GLOBAL + USB on the go full speed + USB_OTG_FS + 0x50000000 + + 0x0 + 0x400 + registers + + + + GOTGCTL + GOTGCTL + OTG_FS control and status register + (OTG_FS_GOTGCTL) + 0x0 + 0x20 + 0x00000800 + + + SRQSCS + Session request success + 0 + 1 + read-only + + + SRQ + Session request + 1 + 1 + read-write + + + HNGSCS + Host negotiation success + 8 + 1 + read-only + + + HNPRQ + HNP request + 9 + 1 + read-write + + + HSHNPEN + Host set HNP enable + 10 + 1 + read-write + + + DHNPEN + Device HNP enabled + 11 + 1 + read-write + + + CIDSTS + Connector ID status + 16 + 1 + read-only + + + DBCT + Long/short debounce time + 17 + 1 + read-only + + + ASVLD + A-session valid + 18 + 1 + read-only + + + BSVLD + B-session valid + 19 + 1 + read-only + + + + + GOTGINT + GOTGINT + OTG_FS interrupt register + (OTG_FS_GOTGINT) + 0x4 + 0x20 + read-write + 0x00000000 + + + SEDET + Session end detected + 2 + 1 + + + SRSSCHG + Session request success status + change + 8 + 1 + + + HNSSCHG + Host negotiation success status + change + 9 + 1 + + + HNGDET + Host negotiation detected + 17 + 1 + + + ADTOCHG + A-device timeout change + 18 + 1 + + + DBCDNE + Debounce done + 19 + 1 + + + + + GAHBCFG + GAHBCFG + OTG_FS AHB configuration register + (OTG_FS_GAHBCFG) + 0x8 + 0x20 + read-write + 0x00000000 + + + GINT + Global interrupt mask + 0 + 1 + + + TXFELVL + TxFIFO empty level + 7 + 1 + + + PTXFELVL + Periodic TxFIFO empty + level + 8 + 1 + + + + + GUSBCFG + GUSBCFG + OTG_FS USB configuration register + (OTG_FS_GUSBCFG) + 0xC + 0x20 + 0x00000A00 + + + TOCAL + FS timeout calibration + 0 + 3 + read-write + + + PHYSEL + Full Speed serial transceiver + select + 6 + 1 + write-only + + + SRPCAP + SRP-capable + 8 + 1 + read-write + + + HNPCAP + HNP-capable + 9 + 1 + read-write + + + TRDT + USB turnaround time + 10 + 4 + read-write + + + FHMOD + Force host mode + 29 + 1 + read-write + + + FDMOD + Force device mode + 30 + 1 + read-write + + + CTXPKT + Corrupt Tx packet + 31 + 1 + read-write + + + + + GRSTCTL + GRSTCTL + OTG_FS reset register + (OTG_FS_GRSTCTL) + 0x10 + 0x20 + 0x20000000 + + + CSRST + Core soft reset + 0 + 1 + read-write + + + HSRST + HCLK soft reset + 1 + 1 + read-write + + + FCRST + Host frame counter reset + 2 + 1 + read-write + + + RXFFLSH + RxFIFO flush + 4 + 1 + read-write + + + TXFFLSH + TxFIFO flush + 5 + 1 + read-write + + + TXFNUM + TxFIFO number + 6 + 5 + read-write + + + AHBIDL + AHB master idle + 31 + 1 + read-only + + + + + GINTSTS + GINTSTS + OTG_FS core interrupt register + (OTG_FS_GINTSTS) + 0x14 + 0x20 + 0x04000020 + + + CMOD + Current mode of operation + 0 + 1 + read-only + + + MMIS + Mode mismatch interrupt + 1 + 1 + read-write + + + OTGINT + OTG interrupt + 2 + 1 + read-only + + + SOF + Start of frame + 3 + 1 + read-write + + + RXFLVL + RxFIFO non-empty + 4 + 1 + read-only + + + NPTXFE + Non-periodic TxFIFO empty + 5 + 1 + read-only + + + GINAKEFF + Global IN non-periodic NAK + effective + 6 + 1 + read-only + + + GOUTNAKEFF + Global OUT NAK effective + 7 + 1 + read-only + + + ESUSP + Early suspend + 10 + 1 + read-write + + + USBSUSP + USB suspend + 11 + 1 + read-write + + + USBRST + USB reset + 12 + 1 + read-write + + + ENUMDNE + Enumeration done + 13 + 1 + read-write + + + ISOODRP + Isochronous OUT packet dropped + interrupt + 14 + 1 + read-write + + + EOPF + End of periodic frame + interrupt + 15 + 1 + read-write + + + IEPINT + IN endpoint interrupt + 18 + 1 + read-only + + + OEPINT + OUT endpoint interrupt + 19 + 1 + read-only + + + IISOIXFR + Incomplete isochronous IN + transfer + 20 + 1 + read-write + + + IPXFR_INCOMPISOOUT + Incomplete periodic transfer(Host + mode)/Incomplete isochronous OUT transfer(Device + mode) + 21 + 1 + read-write + + + HPRTINT + Host port interrupt + 24 + 1 + read-only + + + HCINT + Host channels interrupt + 25 + 1 + read-only + + + PTXFE + Periodic TxFIFO empty + 26 + 1 + read-only + + + CIDSCHG + Connector ID status change + 28 + 1 + read-write + + + DISCINT + Disconnect detected + interrupt + 29 + 1 + read-write + + + SRQINT + Session request/new session detected + interrupt + 30 + 1 + read-write + + + WKUPINT + Resume/remote wakeup detected + interrupt + 31 + 1 + read-write + + + + + GINTMSK + GINTMSK + OTG_FS interrupt mask register + (OTG_FS_GINTMSK) + 0x18 + 0x20 + 0x00000000 + + + MMISM + Mode mismatch interrupt + mask + 1 + 1 + read-write + + + OTGINT + OTG interrupt mask + 2 + 1 + read-write + + + SOFM + Start of frame mask + 3 + 1 + read-write + + + RXFLVLM + Receive FIFO non-empty + mask + 4 + 1 + read-write + + + NPTXFEM + Non-periodic TxFIFO empty + mask + 5 + 1 + read-write + + + GINAKEFFM + Global non-periodic IN NAK effective + mask + 6 + 1 + read-write + + + GONAKEFFM + Global OUT NAK effective + mask + 7 + 1 + read-write + + + ESUSPM + Early suspend mask + 10 + 1 + read-write + + + USBSUSPM + USB suspend mask + 11 + 1 + read-write + + + USBRST + USB reset mask + 12 + 1 + read-write + + + ENUMDNEM + Enumeration done mask + 13 + 1 + read-write + + + ISOODRPM + Isochronous OUT packet dropped interrupt + mask + 14 + 1 + read-write + + + EOPFM + End of periodic frame interrupt + mask + 15 + 1 + read-write + + + EPMISM + Endpoint mismatch interrupt + mask + 17 + 1 + read-write + + + IEPINT + IN endpoints interrupt + mask + 18 + 1 + read-write + + + OEPINT + OUT endpoints interrupt + mask + 19 + 1 + read-write + + + IISOIXFRM + Incomplete isochronous IN transfer + mask + 20 + 1 + read-write + + + IPXFRM_IISOOXFRM + Incomplete periodic transfer mask(Host + mode)/Incomplete isochronous OUT transfer mask(Device + mode) + 21 + 1 + read-write + + + PRTIM + Host port interrupt mask + 24 + 1 + read-write + + + HCIM + Host channels interrupt + mask + 25 + 1 + read-write + + + PTXFEM + Periodic TxFIFO empty mask + 26 + 1 + read-write + + + CIDSCHGM + Connector ID status change + mask + 28 + 1 + read-write + + + DISCINT + Disconnect detected interrupt + mask + 29 + 1 + read-write + + + SRQIM + Session request/new session detected + interrupt mask + 30 + 1 + read-write + + + WUIM + Resume/remote wakeup detected interrupt + mask + 31 + 1 + read-write + + + + + GRXSTSR_Device + GRXSTSR_Device + OTG_FS Receive status debug read(Device + mode) + 0x1C + 0x20 + read-only + 0x00000000 + + + EPNUM + Endpoint number + 0 + 4 + + + BCNT + Byte count + 4 + 11 + + + DPID + Data PID + 15 + 2 + + + PKTSTS + Packet status + 17 + 4 + + + FRMNUM + Frame number + 21 + 4 + + + + + GRXSTSR_Host + GRXSTSR_Host + OTG status debug read (host mode) + GRXSTSR_Device + 0x1C + 0x20 + read-only + 0x00000000 + + + CHNUM + Channel number + 0 + 4 + + + BCNT + Byte count + 4 + 11 + + + DPID + Data PID + 15 + 2 + + + PKTSTS + Packet status + 17 + 4 + + + + + GRXFSIZ + GRXFSIZ + OTG_FS Receive FIFO size register + (OTG_FS_GRXFSIZ) + 0x24 + 0x20 + read-write + 0x00000200 + + + RXFD + RxFIFO depth + 0 + 16 + + + + + DIEPTXF0 + DIEPTXF0 + OTG_FS non-periodic transmit FIFO size + register (Device mode) + 0x28 + 0x20 + read-write + 0x00000200 + + + TX0FSA + Endpoint 0 transmit RAM start + address + 0 + 16 + + + TX0FD + Endpoint 0 TxFIFO depth + 16 + 16 + + + + + HNPTXFSIZ + HNPTXFSIZ + OTG_FS non-periodic transmit FIFO size + register (Host mode) + DIEPTXF0 + 0x28 + 0x20 + read-write + 0x00000200 + + + NPTXFSA + Non-periodic transmit RAM start + address + 0 + 16 + + + NPTXFD + Non-periodic TxFIFO depth + 16 + 16 + + + + + GNPTXSTS + GNPTXSTS + OTG_FS non-periodic transmit FIFO/queue + status register (OTG_FS_GNPTXSTS) + 0x2C + 0x20 + read-only + 0x00080200 + + + NPTXFSAV + Non-periodic TxFIFO space + available + 0 + 16 + + + NPTQXSAV + Non-periodic transmit request queue + space available + 16 + 8 + + + NPTXQTOP + Top of the non-periodic transmit request + queue + 24 + 7 + + + + + GCCFG + GCCFG + OTG_FS general core configuration register + (OTG_FS_GCCFG) + 0x38 + 0x20 + read-write + 0x00000000 + + + PWRDWN + Power down + 16 + 1 + + + VBUSASEN + Enable the VBUS sensing + device + 18 + 1 + + + VBUSBSEN + Enable the VBUS sensing + device + 19 + 1 + + + SOFOUTEN + SOF output enable + 20 + 1 + + + NOVBUSSENS + Vbus sensing disable option + 21 + 1 + + + + + CID + CID + core ID register + 0x3C + 0x20 + read-write + 0x00001000 + + + PRODUCT_ID + Product ID field + 0 + 32 + + + + + HPTXFSIZ + HPTXFSIZ + OTG_FS Host periodic transmit FIFO size + register (OTG_FS_HPTXFSIZ) + 0x100 + 0x20 + read-write + 0x02000600 + + + PTXSA + Host periodic TxFIFO start + address + 0 + 16 + + + PTXFSIZ + Host periodic TxFIFO depth + 16 + 16 + + + + + 3 + 0x4 + 1-3 + DIEPTXF%s + DIEPTXF1 + OTF_FS device IN endpoint transmit FIFO size register + 0x104 + 0x20 + read-write + 0x02000400 + + + INEPTXSA + IN endpoint FIFO2 transmit RAM start + address + 0 + 16 + + + INEPTXFD + IN endpoint TxFIFO depth + 16 + 16 + + + + + GRXSTSP_Device + OTG status read and pop (device mode) + 0x20 + 0x20 + read-only + 0x00000000 + + + FRMNUM + Frame number + 21 + 4 + + + PKTSTS + Packet status + 17 + 4 + + + DPID + Data PID + 15 + 2 + + + BCNT + Byte count + 4 + 11 + + + EPNUM + Endpoint number + 0 + 4 + + + + + GRXSTSP_Host + OTG status read and pop (host mode) + GRXSTSP_Device + 0x20 + 0x20 + read-only + 0x00000000 + + + PKTSTS + Packet status + 17 + 4 + + + DPID + Data PID + 15 + 2 + + + BCNT + Byte count + 4 + 11 + + + CHNUM + Channel number + 0 + 4 + + + + + + + OTG_FS_HOST + USB on the go full speed + USB_OTG_FS + 0x50000400 + + 0x0 + 0x400 + registers + + + + HCFG + HCFG + OTG_FS host configuration register + (OTG_FS_HCFG) + 0x0 + 0x20 + 0x00000000 + + + FSLSPCS + FS/LS PHY clock select + 0 + 2 + read-write + + + FSLSS + FS- and LS-only support + 2 + 1 + read-write + + + + + HFIR + HFIR + OTG_FS Host frame interval + register + 0x4 + 0x20 + read-write + 0x0000EA60 + + + FRIVL + Frame interval + 0 + 16 + + + + + HFNUM + HFNUM + OTG_FS host frame number/frame time + remaining register (OTG_FS_HFNUM) + 0x8 + 0x20 + read-only + 0x00003FFF + + + FRNUM + Frame number + 0 + 16 + + + FTREM + Frame time remaining + 16 + 16 + + + + + HPTXSTS + HPTXSTS + OTG_FS_Host periodic transmit FIFO/queue + status register (OTG_FS_HPTXSTS) + 0x10 + 0x20 + 0x00080100 + + + PTXFSAVL + Periodic transmit data FIFO space + available + 0 + 16 + read-write + + + PTXQSAV + Periodic transmit request queue space + available + 16 + 8 + read-only + + + PTXQTOP + Top of the periodic transmit request + queue + 24 + 8 + read-only + + + + + HAINT + HAINT + OTG_FS Host all channels interrupt + register + 0x14 + 0x20 + read-only + 0x00000000 + + + HAINT + Channel interrupts + 0 + 16 + + + + + HAINTMSK + HAINTMSK + OTG_FS host all channels interrupt mask + register + 0x18 + 0x20 + read-write + 0x00000000 + + + HAINTM + Channel interrupt mask + 0 + 16 + + + + + HPRT + HPRT + OTG_FS host port control and status register + (OTG_FS_HPRT) + 0x40 + 0x20 + 0x00000000 + + + PCSTS + Port connect status + 0 + 1 + read-only + + + PCDET + Port connect detected + 1 + 1 + read-write + + + PENA + Port enable + 2 + 1 + read-write + + + PENCHNG + Port enable/disable change + 3 + 1 + read-write + + + POCA + Port overcurrent active + 4 + 1 + read-only + + + POCCHNG + Port overcurrent change + 5 + 1 + read-write + + + PRES + Port resume + 6 + 1 + read-write + + + PSUSP + Port suspend + 7 + 1 + read-write + + + PRST + Port reset + 8 + 1 + read-write + + + PLSTS + Port line status + 10 + 2 + read-only + + + PPWR + Port power + 12 + 1 + read-write + + + PTCTL + Port test control + 13 + 4 + read-write + + + PSPD + Port speed + 17 + 2 + read-only + + + + + 8 + 0x20 + 0-7 + HC%s + Host channel + 0x100 + + CHAR + HCCHAR0 + OTG_FS host channel-0 characteristics + register (OTG_FS_HCCHAR0) + 0x0 + 0x20 + read-write + 0x00000000 + + + MPSIZ + Maximum packet size + 0 + 11 + + + EPNUM + Endpoint number + 11 + 4 + + + EPDIR + Endpoint direction + 15 + 1 + + + LSDEV + Low-speed device + 17 + 1 + + + EPTYP + Endpoint type + 18 + 2 + + + MCNT + Multicount + 20 + 2 + + + DAD + Device address + 22 + 7 + + + ODDFRM + Odd frame + 29 + 1 + + + CHDIS + Channel disable + 30 + 1 + + + CHENA + Channel enable + 31 + 1 + + + + + INT + HCINT0 + OTG_FS host channel-0 interrupt register + (OTG_FS_HCINT0) + 0x8 + 0x20 + read-write + 0x00000000 + + + XFRC + Transfer completed + 0 + 1 + + + CHH + Channel halted + 1 + 1 + + + STALL + STALL response received + interrupt + 3 + 1 + + + NAK + NAK response received + interrupt + 4 + 1 + + + ACK + ACK response received/transmitted + interrupt + 5 + 1 + + + TXERR + Transaction error + 7 + 1 + + + BBERR + Babble error + 8 + 1 + + + FRMOR + Frame overrun + 9 + 1 + + + DTERR + Data toggle error + 10 + 1 + + + + + INTMSK + HCINTMSK0 + OTG_FS host channel-0 mask register + (OTG_FS_HCINTMSK0) + 0xC + 0x20 + read-write + 0x00000000 + + + XFRCM + Transfer completed mask + 0 + 1 + + + CHHM + Channel halted mask + 1 + 1 + + + STALLM + STALL response received interrupt + mask + 3 + 1 + + + NAKM + NAK response received interrupt + mask + 4 + 1 + + + ACKM + ACK response received/transmitted + interrupt mask + 5 + 1 + + + NYET + response received interrupt + mask + 6 + 1 + + + TXERRM + Transaction error mask + 7 + 1 + + + BBERRM + Babble error mask + 8 + 1 + + + FRMORM + Frame overrun mask + 9 + 1 + + + DTERRM + Data toggle error mask + 10 + 1 + + + + + TSIZ + HCTSIZ0 + OTG_FS host channel-0 transfer size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + XFRSIZ + Transfer size + 0 + 19 + + + PKTCNT + Packet count + 19 + 10 + + + DPID + Data PID + 29 + 2 + + + + + + + + OTG_FS_PWRCLK + USB on the go full speed + USB_OTG_FS + 0x50000E00 + + 0x0 + 0x400 + registers + + + + PCGCCTL + PCGCCTL + OTG_FS power and clock gating control + register + 0x0 + 0x20 + read-write + 0x00000000 + + + STPPCLK + Stop PHY clock + 0 + 1 + + + GATEHCLK + Gate HCLK + 1 + 1 + + + PHYSUSP + PHY Suspended + 4 + 1 + + + + + + + PWR + Power control + PWR + 0x40007000 + + 0x0 + 0x400 + registers + + + + CR + CR + power control register + 0x0 + 0x20 + read-write + 0x00000000 + + + VOS + Regulator voltage scaling output + selection + 14 + 2 + + + ADCDC1 + ADCDC1 + 13 + 1 + + + FPDS + Flash power down in Stop + mode + 9 + 1 + + + DBP + Disable backup domain write + protection + 8 + 1 + + + PLS + PVD level selection + 5 + 3 + + + PVDE + Power voltage detector + enable + 4 + 1 + + + CSBF + Clear standby flag + 3 + 1 + + + CWUF + Clear wakeup flag + 2 + 1 + + + PDDS + Power down deepsleep + 1 + 1 + + + LPDS + Low-power deep sleep + 0 + 1 + + + + + CSR + CSR + power control/status register + 0x4 + 0x20 + 0x00000000 + + + WUF + Wakeup flag + 0 + 1 + read-only + + + SBF + Standby flag + 1 + 1 + read-only + + + PVDO + PVD output + 2 + 1 + read-only + + + BRR + Backup regulator ready + 3 + 1 + read-only + + + EWUP + Enable WKUP pin + 8 + 1 + read-write + + + BRE + Backup regulator enable + 9 + 1 + read-write + + + VOSRDY + Regulator voltage scaling output + selection ready bit + 14 + 1 + read-write + + + + + + + RCC + Reset and clock control + RCC + 0x40023800 + + 0x0 + 0x400 + registers + + + I2C1_EV + I2C1 event interrupt + 31 + + + I2C1_ER + I2C1 error interrupt + 32 + + + + CR + CR + clock control register + 0x0 + 0x20 + 0x00000083 + + + PLLI2SRDY + PLLI2S clock ready flag + 27 + 1 + read-only + + + + PLLI2SON + PLLI2S enable + 26 + 1 + read-write + + + + PLLRDY + Main PLL (PLL) clock ready + flag + 25 + 1 + read-only + + + + PLLON + Main PLL (PLL) enable + 24 + 1 + read-write + + + + CSSON + Clock security system + enable + 19 + 1 + read-write + + CSSON + read-write + + Off + Clock security system disabled (clock detector OFF) + 0 + + + On + Clock security system enable (clock detector ON if the HSE is ready, OFF if not) + 1 + + + + + HSEBYP + HSE clock bypass + 18 + 1 + read-write + + HSEBYP + read-write + + NotBypassed + HSE crystal oscillator not bypassed + 0 + + + Bypassed + HSE crystal oscillator bypassed with external clock + 1 + + + + + HSERDY + HSE clock ready flag + 17 + 1 + read-only + + + + HSEON + HSE clock enable + 16 + 1 + read-write + + + + HSICAL + Internal high-speed clock + calibration + 8 + 8 + read-only + + + 0 + 255 + + + + + HSITRIM + Internal high-speed clock + trimming + 3 + 5 + read-write + + + 0 + 31 + + + + + HSIRDY + Internal high-speed clock ready + flag + 1 + 1 + read-only + + HSIRDYR + read + + NotReady + Clock not ready + 0 + + + Ready + Clock ready + 1 + + + + + HSION + Internal high-speed clock + enable + 0 + 1 + read-write + + HSION + read-write + + Off + Clock Off + 0 + + + On + Clock On + 1 + + + + + + + PLLCFGR + PLLCFGR + PLL configuration register + 0x4 + 0x20 + read-write + 0x24003010 + + + PLLSRC + Main PLL(PLL) and audio PLL (PLLI2S) + entry clock source + 22 + 1 + + PLLSRC + read-write + + HSI + HSI clock selected as PLL and PLLI2S clock entry + 0 + + + HSE + HSE oscillator clock selected as PLL and PLLI2S clock entry + 1 + + + + + PLLM + Division factor for the main PLL (PLL) + and audio PLL (PLLI2S) input clock + 0 + 6 + + + 2 + 63 + + + + + PLLN + Main PLL (PLL) multiplication factor for + VCO + 6 + 9 + + + 50 + 432 + + + + + PLLP + Main PLL (PLL) division factor for main + system clock + 16 + 2 + + PLLP + read-write + + Div2 + PLLP=2 + 0 + + + Div4 + PLLP=4 + 1 + + + Div6 + PLLP=6 + 2 + + + Div8 + PLLP=8 + 3 + + + + + PLLQ + Main PLL (PLL) division factor for USB + OTG FS, SDIO and random number generator + clocks + 24 + 4 + + + 2 + 15 + + + + + + + CFGR + CFGR + clock configuration register + 0x8 + 0x20 + 0x00000000 + + + MCO2 + Microcontroller clock output + 2 + 30 + 2 + read-write + + MCO2 + read-write + + SYSCLK + System clock (SYSCLK) selected + 0 + + + PLLI2S + PLLI2S clock selected + 1 + + + HSE + HSE oscillator clock selected + 2 + + + PLL + PLL clock selected + 3 + + + + + MCO2PRE + MCO2 prescaler + 27 + 3 + read-write + + + + MCO1PRE + MCO1 prescaler + 24 + 3 + read-write + + MCO1PRE + read-write + + Div1 + No division + 0 + + + Div2 + Division by 2 + 4 + + + Div3 + Division by 3 + 5 + + + Div4 + Division by 4 + 6 + + + Div5 + Division by 5 + 7 + + + + + I2SSRC + I2S clock selection + 23 + 1 + read-write + + I2SSRC + read-write + + PLLI2S + PLLI2S clock used as I2S clock source + 0 + + + CKIN + External clock mapped on the I2S_CKIN pin used as I2S clock source + 1 + + + + + MCO1 + Microcontroller clock output + 1 + 21 + 2 + read-write + + MCO1 + read-write + + HSI + HSI clock selected + 0 + + + LSE + LSE oscillator selected + 1 + + + HSE + HSE oscillator clock selected + 2 + + + PLL + PLL clock selected + 3 + + + + + RTCPRE + HSE division factor for RTC + clock + 16 + 5 + read-write + + + 0 + 31 + + + + + PPRE2 + APB high-speed prescaler + (APB2) + 13 + 3 + read-write + + + + PPRE1 + APB Low speed prescaler + (APB1) + 10 + 3 + read-write + + PPRE1 + read-write + + Div1 + HCLK not divided + 0 + + + Div2 + HCLK divided by 2 + 4 + + + Div4 + HCLK divided by 4 + 5 + + + Div8 + HCLK divided by 8 + 6 + + + Div16 + HCLK divided by 16 + 7 + + + + + HPRE + AHB prescaler + 4 + 4 + read-write + + HPRE + read-write + + Div1 + SYSCLK not divided + 0 + + + Div2 + SYSCLK divided by 2 + 8 + + + Div4 + SYSCLK divided by 4 + 9 + + + Div8 + SYSCLK divided by 8 + 10 + + + Div16 + SYSCLK divided by 16 + 11 + + + Div64 + SYSCLK divided by 64 + 12 + + + Div128 + SYSCLK divided by 128 + 13 + + + Div256 + SYSCLK divided by 256 + 14 + + + Div512 + SYSCLK divided by 512 + 15 + + + + + SW + System clock switch + 0 + 2 + + SW + read-write + + HSI + HSI selected as system clock + 0 + + + HSE + HSE selected as system clock + 1 + + + PLL + PLL selected as system clock + 2 + + + + + SWS + System clock switch status + 2 + 2 + + SWSR + read + + HSI + HSI oscillator used as system clock + 0 + + + HSE + HSE oscillator used as system clock + 1 + + + PLL + PLL used as system clock + 2 + + + + + + + CIR + CIR + clock interrupt register + 0xC + 0x20 + 0x00000000 + + + CSSC + Clock security system interrupt + clear + 23 + 1 + write-only + + CSSCW + write + + Clear + Clear CSSF flag + 1 + + + + + PLLI2SRDYC + PLLI2S ready interrupt + clear + 21 + 1 + write-only + + + + PLLRDYC + Main PLL(PLL) ready interrupt + clear + 20 + 1 + write-only + + + + HSERDYC + HSE ready interrupt clear + 19 + 1 + write-only + + + + HSIRDYC + HSI ready interrupt clear + 18 + 1 + write-only + + + + LSERDYC + LSE ready interrupt clear + 17 + 1 + write-only + + + + LSIRDYC + LSI ready interrupt clear + 16 + 1 + write-only + + LSIRDYCW + write + + Clear + Clear interrupt flag + 1 + + + + + PLLI2SRDYIE + PLLI2S ready interrupt + enable + 13 + 1 + read-write + + + + PLLRDYIE + Main PLL (PLL) ready interrupt + enable + 12 + 1 + read-write + + + + HSERDYIE + HSE ready interrupt enable + 11 + 1 + read-write + + + + HSIRDYIE + HSI ready interrupt enable + 10 + 1 + read-write + + + + LSERDYIE + LSE ready interrupt enable + 9 + 1 + read-write + + + + LSIRDYIE + LSI ready interrupt enable + 8 + 1 + read-write + + LSIRDYIE + read-write + + Disabled + Interrupt disabled + 0 + + + Enabled + Interrupt enabled + 1 + + + + + CSSF + Clock security system interrupt + flag + 7 + 1 + read-only + + CSSFR + read + + NotInterrupted + No clock security interrupt caused by HSE clock failure + 0 + + + Interrupted + Clock security interrupt caused by HSE clock failure + 1 + + + + + PLLI2SRDYF + PLLI2S ready interrupt + flag + 5 + 1 + read-only + + + + PLLRDYF + Main PLL (PLL) ready interrupt + flag + 4 + 1 + read-only + + + + HSERDYF + HSE ready interrupt flag + 3 + 1 + read-only + + + + HSIRDYF + HSI ready interrupt flag + 2 + 1 + read-only + + + + LSERDYF + LSE ready interrupt flag + 1 + 1 + read-only + + + + LSIRDYF + LSI ready interrupt flag + 0 + 1 + read-only + + LSIRDYFR + read + + NotInterrupted + No clock ready interrupt + 0 + + + Interrupted + Clock ready interrupt + 1 + + + + + + + AHB1RSTR + AHB1RSTR + AHB1 peripheral reset register + 0x10 + 0x20 + read-write + 0x00000000 + + + DMA2RST + DMA2 reset + 22 + 1 + + + + DMA1RST + DMA2 reset + 21 + 1 + + + + CRCRST + CRC reset + 12 + 1 + + + + GPIOHRST + IO port H reset + 7 + 1 + + + + GPIOERST + IO port E reset + 4 + 1 + + + + GPIODRST + IO port D reset + 3 + 1 + + + + GPIOCRST + IO port C reset + 2 + 1 + + + + GPIOBRST + IO port B reset + 1 + 1 + + + + GPIOARST + IO port A reset + 0 + 1 + + GPIOARST + read-write + + Reset + Reset the selected module + 1 + + + + + + + AHB2RSTR + AHB2RSTR + AHB2 peripheral reset register + 0x14 + 0x20 + read-write + 0x00000000 + + + OTGFSRST + USB OTG FS module reset + 7 + 1 + + OTGFSRST + read-write + + Reset + Reset the selected module + 1 + + + + + + + APB1RSTR + APB1RSTR + APB1 peripheral reset register + 0x20 + 0x20 + read-write + 0x00000000 + + + PWRRST + Power interface reset + 28 + 1 + + + + I2C3RST + I2C3 reset + 23 + 1 + + + + I2C2RST + I2C 2 reset + 22 + 1 + + + + I2C1RST + I2C 1 reset + 21 + 1 + + + + USART2RST + USART 2 reset + 17 + 1 + + + + SPI3RST + SPI 3 reset + 15 + 1 + + + + SPI2RST + SPI 2 reset + 14 + 1 + + + + WWDGRST + Window watchdog reset + 11 + 1 + + + + TIM5RST + TIM5 reset + 3 + 1 + + + + TIM4RST + TIM4 reset + 2 + 1 + + + + TIM3RST + TIM3 reset + 1 + 1 + + + + TIM2RST + TIM2 reset + 0 + 1 + + TIM2RST + read-write + + Reset + Reset the selected module + 1 + + + + + + + APB2RSTR + APB2RSTR + APB2 peripheral reset register + 0x24 + 0x20 + read-write + 0x00000000 + + + TIM11RST + TIM11 reset + 18 + 1 + + + + TIM10RST + TIM10 reset + 17 + 1 + + + + TIM9RST + TIM9 reset + 16 + 1 + + + + SYSCFGRST + System configuration controller + reset + 14 + 1 + + + + SPI1RST + SPI 1 reset + 12 + 1 + + + + SDIORST + SDIO reset + 11 + 1 + + + + ADCRST + ADC interface reset (common to all + ADCs) + 8 + 1 + + + + USART6RST + USART6 reset + 5 + 1 + + + + USART1RST + USART1 reset + 4 + 1 + + + + TIM1RST + TIM1 reset + 0 + 1 + + TIM1RST + read-write + + Reset + Reset the selected module + 1 + + + + + SPI4RST + SPI4 reset + 13 + 1 + + + + + + AHB1ENR + AHB1ENR + AHB1 peripheral clock register + 0x30 + 0x20 + read-write + 0x00100000 + + + DMA2EN + DMA2 clock enable + 22 + 1 + + + + DMA1EN + DMA1 clock enable + 21 + 1 + + + + CRCEN + CRC clock enable + 12 + 1 + + + + GPIOHEN + IO port H clock enable + 7 + 1 + + + + GPIOEEN + IO port E clock enable + 4 + 1 + + + + GPIODEN + IO port D clock enable + 3 + 1 + + + + GPIOCEN + IO port C clock enable + 2 + 1 + + + + GPIOBEN + IO port B clock enable + 1 + 1 + + + + GPIOAEN + IO port A clock enable + 0 + 1 + + GPIOAEN + read-write + + Disabled + The selected clock is disabled + 0 + + + Enabled + The selected clock is enabled + 1 + + + + + + + AHB2ENR + AHB2ENR + AHB2 peripheral clock enable + register + 0x34 + 0x20 + read-write + 0x00000000 + + + OTGFSEN + USB OTG FS clock enable + 7 + 1 + + OTGFSEN + read-write + + Disabled + The selected clock is disabled + 0 + + + Enabled + The selected clock is enabled + 1 + + + + + + + APB1ENR + APB1ENR + APB1 peripheral clock enable + register + 0x40 + 0x20 + read-write + 0x00000000 + + + PWREN + Power interface clock + enable + 28 + 1 + + + + I2C3EN + I2C3 clock enable + 23 + 1 + + + + I2C2EN + I2C2 clock enable + 22 + 1 + + + + I2C1EN + I2C1 clock enable + 21 + 1 + + + + USART2EN + USART 2 clock enable + 17 + 1 + + + + SPI3EN + SPI3 clock enable + 15 + 1 + + + + SPI2EN + SPI2 clock enable + 14 + 1 + + + + WWDGEN + Window watchdog clock + enable + 11 + 1 + + + + TIM5EN + TIM5 clock enable + 3 + 1 + + + + TIM4EN + TIM4 clock enable + 2 + 1 + + + + TIM3EN + TIM3 clock enable + 1 + 1 + + + + TIM2EN + TIM2 clock enable + 0 + 1 + + TIM2EN + read-write + + Disabled + The selected clock is disabled + 0 + + + Enabled + The selected clock is enabled + 1 + + + + + + + APB2ENR + APB2ENR + APB2 peripheral clock enable + register + 0x44 + 0x20 + read-write + 0x00000000 + + + TIM11EN + TIM11 clock enable + 18 + 1 + + + + TIM10EN + TIM10 clock enable + 17 + 1 + + + + TIM9EN + TIM9 clock enable + 16 + 1 + + + + SYSCFGEN + System configuration controller clock + enable + 14 + 1 + + + + SPI1EN + SPI1 clock enable + 12 + 1 + + + + SDIOEN + SDIO clock enable + 11 + 1 + + + + ADC1EN + ADC1 clock enable + 8 + 1 + + + + USART6EN + USART6 clock enable + 5 + 1 + + + + USART1EN + USART1 clock enable + 4 + 1 + + + + TIM1EN + TIM1 clock enable + 0 + 1 + + TIM1EN + read-write + + Disabled + The selected clock is disabled + 0 + + + Enabled + The selected clock is enabled + 1 + + + + + SPI4EN + SPI4 clock enable + 13 + 1 + + + + + + AHB1LPENR + AHB1LPENR + AHB1 peripheral clock enable in low power + mode register + 0x50 + 0x20 + read-write + 0x7E6791FF + + + DMA2LPEN + DMA2 clock enable during Sleep + mode + 22 + 1 + + + + DMA1LPEN + DMA1 clock enable during Sleep + mode + 21 + 1 + + + + SRAM1LPEN + SRAM 1interface clock enable during + Sleep mode + 16 + 1 + + + + FLITFLPEN + Flash interface clock enable during + Sleep mode + 15 + 1 + + + + CRCLPEN + CRC clock enable during Sleep + mode + 12 + 1 + + + + GPIOHLPEN + IO port H clock enable during Sleep + mode + 7 + 1 + + + + GPIOELPEN + IO port E clock enable during Sleep + mode + 4 + 1 + + + + GPIODLPEN + IO port D clock enable during Sleep + mode + 3 + 1 + + + + GPIOCLPEN + IO port C clock enable during Sleep + mode + 2 + 1 + + + + GPIOBLPEN + IO port B clock enable during Sleep + mode + 1 + 1 + + + + GPIOALPEN + IO port A clock enable during sleep + mode + 0 + 1 + + GPIOALPEN + read-write + + DisabledInSleep + Selected module is disabled during Sleep mode + 0 + + + EnabledInSleep + Selected module is enabled during Sleep mode + 1 + + + + + + + AHB2LPENR + AHB2LPENR + AHB2 peripheral clock enable in low power + mode register + 0x54 + 0x20 + read-write + 0x000000F1 + + + OTGFSLPEN + USB OTG FS clock enable during Sleep + mode + 7 + 1 + + OTGFSLPEN + read-write + + DisabledInSleep + Selected module is disabled during Sleep mode + 0 + + + EnabledInSleep + Selected module is enabled during Sleep mode + 1 + + + + + + + APB1LPENR + APB1LPENR + APB1 peripheral clock enable in low power + mode register + 0x60 + 0x20 + read-write + 0x36FEC9FF + + + PWRLPEN + Power interface clock enable during + Sleep mode + 28 + 1 + + + + I2C3LPEN + I2C3 clock enable during Sleep + mode + 23 + 1 + + + + I2C2LPEN + I2C2 clock enable during Sleep + mode + 22 + 1 + + + + I2C1LPEN + I2C1 clock enable during Sleep + mode + 21 + 1 + + + + USART2LPEN + USART2 clock enable during Sleep + mode + 17 + 1 + + + + SPI3LPEN + SPI3 clock enable during Sleep + mode + 15 + 1 + + + + SPI2LPEN + SPI2 clock enable during Sleep + mode + 14 + 1 + + + + WWDGLPEN + Window watchdog clock enable during + Sleep mode + 11 + 1 + + + + TIM5LPEN + TIM5 clock enable during Sleep + mode + 3 + 1 + + + + TIM4LPEN + TIM4 clock enable during Sleep + mode + 2 + 1 + + + + TIM3LPEN + TIM3 clock enable during Sleep + mode + 1 + 1 + + + + TIM2LPEN + TIM2 clock enable during Sleep + mode + 0 + 1 + + TIM2LPEN + read-write + + DisabledInSleep + Selected module is disabled during Sleep mode + 0 + + + EnabledInSleep + Selected module is enabled during Sleep mode + 1 + + + + + + + APB2LPENR + APB2LPENR + APB2 peripheral clock enabled in low power + mode register + 0x64 + 0x20 + read-write + 0x00075F33 + + + TIM11LPEN + TIM11 clock enable during Sleep + mode + 18 + 1 + + + + TIM10LPEN + TIM10 clock enable during Sleep + mode + 17 + 1 + + + + TIM9LPEN + TIM9 clock enable during sleep + mode + 16 + 1 + + + + SYSCFGLPEN + System configuration controller clock + enable during Sleep mode + 14 + 1 + + + + SPI1LPEN + SPI 1 clock enable during Sleep + mode + 12 + 1 + + + + SDIOLPEN + SDIO clock enable during Sleep + mode + 11 + 1 + + + + ADC1LPEN + ADC1 clock enable during Sleep + mode + 8 + 1 + + + + USART6LPEN + USART6 clock enable during Sleep + mode + 5 + 1 + + + + USART1LPEN + USART1 clock enable during Sleep + mode + 4 + 1 + + + + TIM1LPEN + TIM1 clock enable during Sleep + mode + 0 + 1 + + TIM1LPEN + read-write + + DisabledInSleep + Selected module is disabled during Sleep mode + 0 + + + EnabledInSleep + Selected module is enabled during Sleep mode + 1 + + + + + SPI4LPEN + SPI4 clock enable during Sleep mode + 13 + 1 + + + + + + BDCR + BDCR + Backup domain control register + 0x70 + 0x20 + 0x00000000 + + + BDRST + Backup domain software + reset + 16 + 1 + read-write + + BDRST + read-write + + Disabled + Reset not activated + 0 + + + Enabled + Reset the entire RTC domain + 1 + + + + + RTCEN + RTC clock enable + 15 + 1 + read-write + + RTCEN + read-write + + Disabled + RTC clock disabled + 0 + + + Enabled + RTC clock enabled + 1 + + + + + LSEBYP + External low-speed oscillator + bypass + 2 + 1 + read-write + + LSEBYP + read-write + + NotBypassed + LSE crystal oscillator not bypassed + 0 + + + Bypassed + LSE crystal oscillator bypassed with external clock + 1 + + + + + LSERDY + External low-speed oscillator + ready + 1 + 1 + read-only + + LSERDYR + read + + NotReady + LSE oscillator not ready + 0 + + + Ready + LSE oscillator ready + 1 + + + + + LSEON + External low-speed oscillator + enable + 0 + 1 + read-write + + LSEON + read-write + + Off + LSE oscillator Off + 0 + + + On + LSE oscillator On + 1 + + + + + RTCSEL + RTC clock source selection + 8 + 2 + + RTCSEL + read-write + + NoClock + No clock + 0 + + + LSE + LSE oscillator clock used as RTC clock + 1 + + + LSI + LSI oscillator clock used as RTC clock + 2 + + + HSE + HSE oscillator clock divided by a prescaler used as RTC clock + 3 + + + + + + + CSR + CSR + clock control & status + register + 0x74 + 0x20 + 0x0E000000 + + + LPWRRSTF + Low-power reset flag + 31 + 1 + read-write + + + + WWDGRSTF + Window watchdog reset flag + 30 + 1 + read-write + + + + WDGRSTF + Independent watchdog reset + flag + 29 + 1 + read-write + + + + SFTRSTF + Software reset flag + 28 + 1 + read-write + + + + PORRSTF + POR/PDR reset flag + 27 + 1 + read-write + + + + PADRSTF + PIN reset flag + 26 + 1 + read-write + + + + BORRSTF + BOR reset flag + 25 + 1 + read-write + + BORRSTFR + read + + NoReset + No reset has occured + 0 + + + Reset + A reset has occured + 1 + + + + + RMVF + Remove reset flag + 24 + 1 + read-write + + RMVFW + write + + Clear + Clears the reset flag + 1 + + + + + LSIRDY + Internal low-speed oscillator + ready + 1 + 1 + read-only + + LSIRDYR + read + + NotReady + LSI oscillator not ready + 0 + + + Ready + LSI oscillator ready + 1 + + + + + LSION + Internal low-speed oscillator + enable + 0 + 1 + read-write + + LSION + read-write + + Off + LSI oscillator Off + 0 + + + On + LSI oscillator On + 1 + + + + + + + SSCGR + SSCGR + spread spectrum clock generation + register + 0x80 + 0x20 + read-write + 0x00000000 + + + SSCGEN + Spread spectrum modulation + enable + 31 + 1 + + SSCGEN + read-write + + Disabled + Spread spectrum modulation disabled + 0 + + + Enabled + Spread spectrum modulation enabled + 1 + + + + + SPREADSEL + Spread Select + 30 + 1 + + SPREADSEL + read-write + + Center + Center spread + 0 + + + Down + Down spread + 1 + + + + + INCSTEP + Incrementation step + 13 + 15 + + + 0 + 32767 + + + + + MODPER + Modulation period + 0 + 13 + + + 0 + 8191 + + + + + + + PLLI2SCFGR + PLLI2SCFGR + PLLI2S configuration register + 0x84 + 0x20 + read-write + 0x20003000 + + + PLLI2SR + PLLI2S division factor for I2S + clocks + 28 + 3 + + + 2 + 7 + + + + + PLLI2SN + PLLI2S multiplication factor for + VCO + 6 + 9 + + + 50 + 432 + + + + + + + DCKCFGR + RCC Dedicated Clock Configuration Register + 0x8C + 0x20 + read-write + 0x00000000 + + + TIMPRE + Timers clocks prescalers selection + 24 + 1 + + TIMPRE + read-write + + Mul1Or2 + If the APB prescaler is configured 1, TIMxCLK = PCLKx. Otherwise, TIMxCLK = 2xPCLKx + 0 + + + Mul1Or4 + If the APB prescaler is configured 1, 2 or 4, TIMxCLK = HCLK. Otherwise, TIMxCLK = 4xPCLKx + 1 + + + + + + + + + RTC + Real-time clock + RTC + 0x40002800 + + 0x0 + 0x400 + registers + + + I2C2_EV + I2C2 event interrupt + 33 + + + I2C2_ER + I2C2 error interrupt + 34 + + + + TR + TR + time register + 0x0 + 0x20 + read-write + 0x00000000 + + + PM + AM/PM notation + 22 + 1 + + PM + read-write + + AM + AM or 24-hour format + 0 + + + PM + PM + 1 + + + + + HT + Hour tens in BCD format + 20 + 2 + + + 0 + 3 + + + + + HU + Hour units in BCD format + 16 + 4 + + + 0 + 15 + + + + + MNT + Minute tens in BCD format + 12 + 3 + + + 0 + 7 + + + + + MNU + Minute units in BCD format + 8 + 4 + + + 0 + 15 + + + + + ST + Second tens in BCD format + 4 + 3 + + + 0 + 7 + + + + + SU + Second units in BCD format + 0 + 4 + + + 0 + 15 + + + + + + + DR + DR + date register + 0x4 + 0x20 + read-write + 0x00002101 + + + YT + Year tens in BCD format + 20 + 4 + + + 0 + 15 + + + + + YU + Year units in BCD format + 16 + 4 + + + 0 + 15 + + + + + WDU + Week day units + 13 + 3 + + + 1 + 7 + + + + + MT + Month tens in BCD format + 12 + 1 + + MT + read-write + + Zero + Month tens is 0 + 0 + + + One + Month tens is 1 + 1 + + + + + MU + Month units in BCD format + 8 + 4 + + + 0 + 15 + + + + + DT + Date tens in BCD format + 4 + 2 + + + 0 + 3 + + + + + DU + Date units in BCD format + 0 + 4 + + + 0 + 15 + + + + + + + CR + CR + control register + 0x8 + 0x20 + read-write + 0x00000000 + + + COE + Calibration output enable + 23 + 1 + + COE + read-write + + Disabled + Calibration output disabled + 0 + + + Enabled + Calibration output enabled + 1 + + + + + OSEL + Output selection + 21 + 2 + + OSEL + read-write + + Disabled + Output disabled + 0 + + + AlarmA + Alarm A output enabled + 1 + + + AlarmB + Alarm B output enabled + 2 + + + Wakeup + Wakeup output enabled + 3 + + + + + POL + Output polarity + 20 + 1 + + POL + read-write + + High + The pin is high when ALRAF/ALRBF/WUTF is asserted (depending on OSEL[1:0]) + 0 + + + Low + The pin is low when ALRAF/ALRBF/WUTF is asserted (depending on OSEL[1:0]) + 1 + + + + + COSEL + Calibration Output + selection + 19 + 1 + + COSEL + read-write + + CalFreq_512Hz + Calibration output is 512 Hz (with default prescaler setting) + 0 + + + CalFreq_1Hz + Calibration output is 1 Hz (with default prescaler setting) + 1 + + + + + BKP + Backup + 18 + 1 + + BKP + read-write + + DST_Not_Changed + Daylight Saving Time change has not been performed + 0 + + + DST_Changed + Daylight Saving Time change has been performed + 1 + + + + + SUB1H + Subtract 1 hour (winter time + change) + 17 + 1 + + SUB1HW + write + + Sub1 + Subtracts 1 hour to the current time. This can be used for winter time change outside initialization mode + 1 + + + + + ADD1H + Add 1 hour (summer time + change) + 16 + 1 + + ADD1HW + write + + Add1 + Adds 1 hour to the current time. This can be used for summer time change outside initialization mode + 1 + + + + + TSIE + Time-stamp interrupt + enable + 15 + 1 + + TSIE + read-write + + Disabled + Time-stamp Interrupt disabled + 0 + + + Enabled + Time-stamp Interrupt enabled + 1 + + + + + WUTIE + Wakeup timer interrupt + enable + 14 + 1 + + WUTIE + read-write + + Disabled + Wakeup timer interrupt disabled + 0 + + + Enabled + Wakeup timer interrupt enabled + 1 + + + + + ALRBIE + Alarm B interrupt enable + 13 + 1 + + ALRBIE + read-write + + Disabled + Alarm B Interrupt disabled + 0 + + + Enabled + Alarm B Interrupt enabled + 1 + + + + + ALRAIE + Alarm A interrupt enable + 12 + 1 + + ALRAIE + read-write + + Disabled + Alarm A interrupt disabled + 0 + + + Enabled + Alarm A interrupt enabled + 1 + + + + + TSE + Time stamp enable + 11 + 1 + + TSE + read-write + + Disabled + Timestamp disabled + 0 + + + Enabled + Timestamp enabled + 1 + + + + + WUTE + Wakeup timer enable + 10 + 1 + + WUTE + read-write + + Disabled + Wakeup timer disabled + 0 + + + Enabled + Wakeup timer enabled + 1 + + + + + ALRBE + Alarm B enable + 9 + 1 + + ALRBE + read-write + + Disabled + Alarm B disabled + 0 + + + Enabled + Alarm B enabled + 1 + + + + + ALRAE + Alarm A enable + 8 + 1 + + ALRAE + read-write + + Disabled + Alarm A disabled + 0 + + + Enabled + Alarm A enabled + 1 + + + + + DCE + Coarse digital calibration + enable + 7 + 1 + + + FMT + Hour format + 6 + 1 + + FMT + read-write + + Twenty_Four_Hour + 24 hour/day format + 0 + + + AM_PM + AM/PM hour format + 1 + + + + + BYPSHAD + Bypass the shadow + registers + 5 + 1 + + BYPSHAD + read-write + + ShadowReg + Calendar values (when reading from RTC_SSR, RTC_TR, and RTC_DR) are taken from the shadow registers, which are updated once every two RTCCLK cycles + 0 + + + BypassShadowReg + Calendar values (when reading from RTC_SSR, RTC_TR, and RTC_DR) are taken directly from the calendar counters + 1 + + + + + REFCKON + Reference clock detection enable (50 or + 60 Hz) + 4 + 1 + + REFCKON + read-write + + Disabled + RTC_REFIN detection disabled + 0 + + + Enabled + RTC_REFIN detection enabled + 1 + + + + + TSEDGE + Time-stamp event active + edge + 3 + 1 + + TSEDGE + read-write + + RisingEdge + RTC_TS input rising edge generates a time-stamp event + 0 + + + FallingEdge + RTC_TS input falling edge generates a time-stamp event + 1 + + + + + WUCKSEL + Wakeup clock selection + 0 + 3 + + WUCKSEL + read-write + + Div16 + RTC/16 clock is selected + 0 + + + Div8 + RTC/8 clock is selected + 1 + + + Div4 + RTC/4 clock is selected + 2 + + + Div2 + RTC/2 clock is selected + 3 + + + ClockSpare + ck_spre (usually 1 Hz) clock is selected + 4 + + + ClockSpareWithOffset + ck_spre (usually 1 Hz) clock is selected and 2^16 is added to the WUT counter value + 6 + + + + + + + ISR + ISR + initialization and status + register + 0xC + 0x20 + 0x00000007 + + + ALRAWF + Alarm A write flag + 0 + 1 + read-only + + ALRAWFR + read + + UpdateNotAllowed + Alarm update not allowed + 0 + + + UpdateAllowed + Alarm update allowed + 1 + + + + + ALRBWF + Alarm B write flag + 1 + 1 + read-only + + + + WUTWF + Wakeup timer write flag + 2 + 1 + read-only + + WUTWFR + read + + UpdateNotAllowed + Wakeup timer configuration update not allowed + 0 + + + UpdateAllowed + Wakeup timer configuration update allowed + 1 + + + + + SHPF + Shift operation pending + 3 + 1 + read-write + + SHPFR + read + + NoShiftPending + No shift operation is pending + 0 + + + ShiftPending + A shift operation is pending + 1 + + + + + INITS + Initialization status flag + 4 + 1 + read-only + + INITSR + read + + NotInitalized + Calendar has not been initialized + 0 + + + Initalized + Calendar has been initialized + 1 + + + + + RSF + Registers synchronization + flag + 5 + 1 + read-write + zeroToClear + + RSFR + read + + NotSynced + Calendar shadow registers not yet synchronized + 0 + + + Synced + Calendar shadow registers synchronized + 1 + + + + RSFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + INITF + Initialization flag + 6 + 1 + read-only + + INITFR + read + + NotAllowed + Calendar registers update is not allowed + 0 + + + Allowed + Calendar registers update is allowed + 1 + + + + + INIT + Initialization mode + 7 + 1 + read-write + + INIT + read-write + + FreeRunningMode + Free running mode + 0 + + + InitMode + Initialization mode used to program time and date register (RTC_TR and RTC_DR), and prescaler register (RTC_PRER). Counters are stopped and start counting from the new value when INIT is reset. + 1 + + + + + ALRAF + Alarm A flag + 8 + 1 + read-write + zeroToClear + + ALRAFR + read + + Match + This flag is set by hardware when the time/date registers (RTC_TR and RTC_DR) match the Alarm A register (RTC_ALRMAR) + 1 + + + + ALRAFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + ALRBF + Alarm B flag + 9 + 1 + read-write + zeroToClear + + ALRBFR + read + + Match + This flag is set by hardware when the time/date registers (RTC_TR and RTC_DR) match the Alarm B register (RTC_ALRMBR) + 1 + + + + ALRBFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + WUTF + Wakeup timer flag + 10 + 1 + read-write + zeroToClear + + WUTFR + read + + Zero + This flag is set by hardware when the wakeup auto-reload counter reaches 0 + 1 + + + + WUTFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + TSF + Time-stamp flag + 11 + 1 + read-write + zeroToClear + + TSFR + read + + TimestampEvent + This flag is set by hardware when a time-stamp event occurs + 1 + + + + TSFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + TSOVF + Time-stamp overflow flag + 12 + 1 + read-write + zeroToClear + + TSOVFR + read + + Overflow + This flag is set by hardware when a time-stamp event occurs while TSF is already set + 1 + + + + TSOVFW + write + + Clear + This flag is cleared by software by writing 0 + 0 + + + + + TAMP1F + Tamper detection flag + 13 + 1 + read-write + zeroToClear + + TAMP1FR + read + + Tampered + This flag is set by hardware when a tamper detection event is detected on the RTC_TAMPx input + 1 + + + + TAMP1FW + write + + Clear + Flag cleared by software writing 0 + 0 + + + + + TAMP2F + TAMPER2 detection flag + 14 + 1 + read-write + zeroToClear + + read + + + write + + + + RECALPF + Recalibration pending Flag + 16 + 1 + read-only + + RECALPFR + read + + Pending + The RECALPF status flag is automatically set to 1 when software writes to the RTC_CALR register, indicating that the RTC_CALR register is blocked. When the new calibration settings are taken into account, this bit returns to 0 + 1 + + + + + + + PRER + PRER + prescaler register + 0x10 + 0x20 + read-write + 0x007F00FF + + + PREDIV_A + Asynchronous prescaler + factor + 16 + 7 + + + 0 + 127 + + + + + PREDIV_S + Synchronous prescaler + factor + 0 + 15 + + + 0 + 32767 + + + + + + + WUTR + WUTR + wakeup timer register + 0x14 + 0x20 + read-write + 0x0000FFFF + + + WUT + Wakeup auto-reload value + bits + 0 + 16 + + + 0 + 65535 + + + + + + + CALIBR + CALIBR + calibration register + 0x18 + 0x20 + read-write + 0x00000000 + + + DCS + Digital calibration sign + 7 + 1 + + + DC + Digital calibration + 0 + 5 + + + + + 2 + 0x4 + A,B + ALRM%sR + ALRMAR + Alarm register + 0x1C + 0x20 + read-write + 0x00000000 + + + MSK4 + Alarm date mask + 31 + 1 + + + + WDSEL + Week day selection + 30 + 1 + + WDSEL + read-write + + DateUnits + DU[3:0] represents the date units + 0 + + + WeekDay + DU[3:0] represents the week day. DT[1:0] is don’t care. + 1 + + + + + DT + Date tens in BCD format + 28 + 2 + + + 0 + 3 + + + + + DU + Date units or day in BCD format + 24 + 4 + + + 0 + 15 + + + + + MSK3 + Alarm hours mask + 23 + 1 + + + + PM + AM/PM notation + 22 + 1 + + PM + read-write + + AM + AM or 24-hour format + 0 + + + PM + PM + 1 + + + + + HT + Hour tens in BCD format + 20 + 2 + + + 0 + 3 + + + + + HU + Hour units in BCD format + 16 + 4 + + + 0 + 15 + + + + + MSK2 + Alarm minutes mask + 15 + 1 + + + + MNT + Minute tens in BCD format + 12 + 3 + + + 0 + 7 + + + + + MNU + Minute units in BCD format + 8 + 4 + + + 0 + 15 + + + + + MSK1 + Alarm seconds mask + 7 + 1 + + MSK1 + read-write + + Mask + Alarm set if the date/day match + 0 + + + NotMask + Date/day don’t care in Alarm comparison + 1 + + + + + ST + Second tens in BCD format + 4 + 3 + + + 0 + 7 + + + + + SU + Second units in BCD format + 0 + 4 + + + 0 + 15 + + + + + + + WPR + WPR + write protection register + 0x24 + 0x20 + write-only + 0x00000000 + + + KEY + Write protection key + 0 + 8 + + + 0 + 255 + + + + + + + SSR + SSR + sub second register + 0x28 + 0x20 + read-only + 0x00000000 + + + SS + Sub second value + 0 + 16 + + + 0 + 65535 + + + + + + + SHIFTR + SHIFTR + shift control register + 0x2C + 0x20 + write-only + 0x00000000 + + + ADD1S + Add one second + 31 + 1 + + ADD1SW + write + + Add1 + Add one second to the clock/calendar + 1 + + + + + SUBFS + Subtract a fraction of a + second + 0 + 15 + + + 0 + 32767 + + + + + + + TSTR + TSTR + time stamp time register + 0x30 + + + TSDR + TSDR + time stamp date register + 0x34 + + + TSSSR + TSSSR + timestamp sub second register + 0x38 + + + CALR + CALR + calibration register + 0x3C + 0x20 + read-write + 0x00000000 + + + CALP + Increase frequency of RTC by 488.5 + ppm + 15 + 1 + + CALP + read-write + + NoChange + No RTCCLK pulses are added + 0 + + + IncreaseFreq + One RTCCLK pulse is effectively inserted every 2^11 pulses (frequency increased by 488.5 ppm) + 1 + + + + + CALW8 + Use an 8-second calibration cycle + period + 14 + 1 + + CALW8 + read-write + + Eight_Second + When CALW8 is set to ‘1’, the 8-second calibration cycle period is selected + 1 + + + + + CALW16 + Use a 16-second calibration cycle + period + 13 + 1 + + CALW16 + read-write + + Sixteen_Second + When CALW16 is set to ‘1’, the 16-second calibration cycle period is selected.This bit must not be set to ‘1’ if CALW8=1 + 1 + + + + + CALM + Calibration minus + 0 + 9 + + + 0 + 511 + + + + + + + TAFCR + TAFCR + tamper and alternate function configuration + register + 0x40 + 0x20 + read-write + 0x00000000 + + + ALARMOUTTYPE + AFO_ALARM output type + 18 + 1 + + + TSINSEL + TIMESTAMP mapping + 17 + 1 + + + TAMP1INSEL + TAMPER1 mapping + 16 + 1 + + + TAMPPUDIS + TAMPER pull-up disable + 15 + 1 + + + TAMPPRCH + Tamper precharge duration + 13 + 2 + + + TAMPFLT + Tamper filter count + 11 + 2 + + + TAMPFREQ + Tamper sampling frequency + 8 + 3 + + + TAMPTS + Activate timestamp on tamper detection + event + 7 + 1 + + + TAMP2TRG + Active level for tamper 2 + 4 + 1 + + + TAMP2E + Tamper 2 detection enable + 3 + 1 + + + TAMPIE + Tamper interrupt enable + 2 + 1 + + + TAMP1TRG + Active level for tamper 1 + 1 + 1 + + + TAMP1E + Tamper 1 detection enable + 0 + 1 + + + + + 2 + 0x4 + A,B + ALRM%sSSR + ALRMASSR + Alarm sub-second register + 0x44 + 0x20 + read-write + 0x00000000 + + + MASKSS + Mask the most-significant bits starting + at this bit + 24 + 4 + + + 0 + 15 + + + + + SS + Sub seconds value + 0 + 15 + + + 0 + 32767 + + + + + + + 20 + 0x4 + 0-19 + BKP%sR + BKP0R + backup register + 0x50 + 0x20 + read-write + 0x00000000 + + + BKP + BKP + 0 + 32 + + + 0 + 4294967295 + + + + + + + + + SDIO + Secure digital input/output + interface + SDIO + 0x40012C00 + + 0x0 + 0x400 + registers + + + I2C3_EV + I2C3 event interrupt + 72 + + + I2C3_ER + I2C3 error interrupt + 73 + + + + POWER + POWER + power control register + 0x0 + 0x20 + read-write + 0x00000000 + + + PWRCTRL + PWRCTRL + 0 + 2 + + PWRCTRL + read-write + + PowerOff + Power off + 0 + + + PowerOn + Power on + 3 + + + + + + + CLKCR + CLKCR + SDI clock control register + 0x4 + 0x20 + read-write + 0x00000000 + + + HWFC_EN + HW Flow Control enable + 14 + 1 + + HWFC_EN + read-write + + Disabled + HW Flow Control is disabled + 0 + + + Enabled + HW Flow Control is enabled + 1 + + + + + NEGEDGE + SDIO_CK dephasing selection + bit + 13 + 1 + + NEGEDGE + read-write + + Rising + SDIO_CK generated on the rising edge + 0 + + + Falling + SDIO_CK generated on the falling edge + 1 + + + + + WIDBUS + Wide bus mode enable bit + 11 + 2 + + WIDBUS + read-write + + BusWidth1 + 1 lane wide bus + 0 + + + BusWidth4 + 4 lane wide bus + 1 + + + BusWidth8 + 8 lane wide bus + 2 + + + + + BYPASS + Clock divider bypass enable + bit + 10 + 1 + + BYPASS + read-write + + Disabled + SDIOCLK is divided according to the CLKDIV value before driving the SDIO_CK output signal. + 0 + + + Enabled + SDIOCLK directly drives the SDIO_CK output signal + 1 + + + + + PWRSAV + Power saving configuration + bit + 9 + 1 + + PWRSAV + read-write + + Enabled + SDIO_CK clock is always enabled + 0 + + + Disabled + SDIO_CK is only enabled when the bus is active + 1 + + + + + CLKEN + Clock enable bit + 8 + 1 + + CLKEN + read-write + + Disabled + Disable clock + 0 + + + Enabled + Enable clock + 1 + + + + + CLKDIV + Clock divide factor + 0 + 8 + + + 0 + 255 + + + + + + + ARG + ARG + argument register + 0x8 + 0x20 + read-write + 0x00000000 + + + CMDARG + Command argument + 0 + 32 + + + 0 + 4294967295 + + + + + + + CMD + CMD + command register + 0xC + 0x20 + read-write + 0x00000000 + + + CE_ATACMD + CE-ATA command + 14 + 1 + + CE_ATACMD + read-write + + Disabled + CE-ATA command disabled + 0 + + + Enabled + CE-ATA command enabled + 1 + + + + + nIEN + not Interrupt Enable + 13 + 1 + + nIEN + read-write + + Disabled + Interrupts to the CE-ATA not disabled + 0 + + + Enabled + Interrupt to the CE-ATA are disabled + 1 + + + + + ENCMDcompl + Enable CMD completion + 12 + 1 + + ENCMDcompl + read-write + + Disabled + Command complete signal disabled + 0 + + + Enabled + Command complete signal enabled + 1 + + + + + SDIOSuspend + SD I/O suspend command + 11 + 1 + + SDIOSuspend + read-write + + Disabled + Next command is not a SDIO suspend command + 0 + + + Enabled + Next command send is a SDIO suspend command + 1 + + + + + CPSMEN + Command path state machine (CPSM) Enable + bit + 10 + 1 + + CPSMEN + read-write + + Disabled + Command path state machine disabled + 0 + + + Enabled + Command path state machine enabled + 1 + + + + + WAITPEND + CPSM Waits for ends of data transfer + (CmdPend internal signal). + 9 + 1 + + WAITPEND + read-write + + Disabled + Don't wait for data end + 0 + + + Enabled + Wait for end of data transfer signal before sending command + 1 + + + + + WAITINT + CPSM waits for interrupt + request + 8 + 1 + + WAITINT + read-write + + Disabled + Don't wait for interrupt request + 0 + + + Enabled + Wait for interrupt request + 1 + + + + + WAITRESP + Wait for response bits + 6 + 2 + + WAITRESP + read-write + + NoResponse + No response + 0 + + + ShortResponse + Short response + 1 + + + NoResponse2 + No reponse + 2 + + + LongResponse + Long reponse + 3 + + + + + CMDINDEX + Command index + 0 + 6 + + + 0 + 63 + + + + + + + RESPCMD + RESPCMD + command response register + 0x10 + 0x20 + read-only + 0x00000000 + + + RESPCMD + Response command index + 0 + 6 + + + 0 + 63 + + + + + + + RESP1 + RESP1 + response 1..4 register + 0x14 + 0x20 + read-only + 0x00000000 + + + CARDSTATUS1 + Card Status + 0 + 32 + + + 0 + 4294967295 + + + + + + + RESP2 + RESP2 + response 1..4 register + 0x18 + 0x20 + read-only + 0x00000000 + + + CARDSTATUS2 + Card Status + 0 + 32 + + + 0 + 4294967295 + + + + + + + RESP3 + RESP3 + response 1..4 register + 0x1C + 0x20 + read-only + 0x00000000 + + + CARDSTATUS3 + Card Status + 0 + 32 + + + 0 + 4294967295 + + + + + + + RESP4 + RESP4 + response 1..4 register + 0x20 + 0x20 + read-only + 0x00000000 + + + CARDSTATUS4 + Card Status + 0 + 32 + + + 0 + 4294967295 + + + + + + + DTIMER + DTIMER + data timer register + 0x24 + 0x20 + read-write + 0x00000000 + + + DATATIME + Data timeout period + 0 + 32 + + + 0 + 4294967295 + + + + + + + DLEN + DLEN + data length register + 0x28 + 0x20 + read-write + 0x00000000 + + + DATALENGTH + Data length value + 0 + 25 + + + 0 + 33554431 + + + + + + + DCTRL + DCTRL + data control register + 0x2C + 0x20 + read-write + 0x00000000 + + + SDIOEN + SD I/O enable functions + 11 + 1 + + SDIOEN + read-write + + Disabled + SDIO operations disabled + 0 + + + Enabled + SDIO operations enabled + 1 + + + + + RWMOD + Read wait mode + 10 + 1 + + RWMOD + read-write + + D2 + Read wait control stopping using SDIO_D2 + 0 + + + Ck + Read wait control using SDIO_CK + 1 + + + + + RWSTOP + Read wait stop + 9 + 1 + + RWSTOP + read-write + + Disabled + Read wait in progress if RWSTART is enabled + 0 + + + Enabled + Enable for read wait stop if RWSTART is enabled + 1 + + + + + RWSTART + Read wait start + 8 + 1 + + RWSTART + read-write + + Disabled + Don't start read wait operation + 0 + + + Enabled + Read wait operation starts + 1 + + + + + DBLOCKSIZE + Data block size + 4 + 4 + + + 0 + 15 + + + + + DMAEN + DMA enable bit + 3 + 1 + + DMAEN + read-write + + Disabled + Dma disabled + 0 + + + Enabled + Dma enabled + 1 + + + + + DTMODE + Data transfer mode selection 1: Stream + or SDIO multibyte data transfer. + 2 + 1 + + DTMODE + read-write + + BlockMode + Bloack data transfer + 0 + + + StreamMode + Stream or SDIO multibyte data transfer + 1 + + + + + DTDIR + Data transfer direction + selection + 1 + 1 + + DTDIR + read-write + + ControllerToCard + From controller to card + 0 + + + CardToController + From card to controller + 1 + + + + + DTEN + DTEN + 0 + 1 + + DTEN + read-write + + Disabled + Disabled + 0 + + + Enabled + Start transfer + 1 + + + + + + + DCOUNT + DCOUNT + data counter register + 0x30 + 0x20 + read-only + 0x00000000 + + + DATACOUNT + Data count value + 0 + 25 + + + 0 + 33554431 + + + + + + + STA + STA + status register + 0x34 + 0x20 + read-only + 0x00000000 + + + CEATAEND + CE-ATA command completion signal + received for CMD61 + 23 + 1 + + CEATAEND + read + + NotReceived + Completion signal not received + 0 + + + Received + CE-ATA command completion signal received for CMD61 + 1 + + + + + SDIOIT + SDIO interrupt received + 22 + 1 + + SDIOIT + read + + NotReceived + SDIO interrupt not receieved + 0 + + + Received + SDIO interrupt received + 1 + + + + + RXDAVL + Data available in receive + FIFO + 21 + 1 + + RXDAVL + read + + NotAvailable + Data not available in receive FIFO + 0 + + + Available + Data available in receive FIFO + 1 + + + + + TXDAVL + Data available in transmit + FIFO + 20 + 1 + + TXDAVL + read + + NotAvailable + Data not available in transmit FIFO + 0 + + + Available + Data available in transmit FIFO + 1 + + + + + RXFIFOE + Receive FIFO empty + 19 + 1 + + RXFIFOE + read + + NotEmpty + Receive FIFO not empty + 0 + + + Empty + Receive FIFO empty + 1 + + + + + TXFIFOE + Transmit FIFO empty + 18 + 1 + + TXFIFOE + read + + NotEmpty + Transmit FIFO not empty + 0 + + + Empty + Transmit FIFO empty. When HW Flow Control is enabled, TXFIFOE signals becomes activated when the FIFO contains 2 words. + 1 + + + + + RXFIFOF + Receive FIFO full + 17 + 1 + + RXFIFOF + read + + NotFull + Transmit FIFO not full + 0 + + + Full + Receive FIFO full. When HW Flow Control is enabled, RXFIFOF signals becomes activated 2 words before the FIFO is full. + 1 + + + + + TXFIFOF + Transmit FIFO full + 16 + 1 + + TXFIFOF + read + + NotFull + Transmit FIFO not full + 0 + + + Full + Transmit FIFO full + 1 + + + + + RXFIFOHF + Receive FIFO half full: there are at + least 8 words in the FIFO + 15 + 1 + + RXFIFOHF + read + + NotHalfFull + Receive FIFO not half full + 0 + + + HalfFull + Receive FIFO half full. At least 8 words in the FIFO + 1 + + + + + TXFIFOHE + Transmit FIFO half empty: at least 8 + words can be written into the FIFO + 14 + 1 + + TXFIFOHE + read + + NotHalfEmpty + Transmit FIFO not half empty + 0 + + + HalfEmpty + Transmit FIFO half empty. At least 8 words can be written into the FIFO + 1 + + + + + RXACT + Data receive in progress + 13 + 1 + + RXACT + read + + NotInProgress + Data receive not in progress + 0 + + + InProgress + Data receive in progress + 1 + + + + + TXACT + Data transmit in progress + 12 + 1 + + TXACT + read + + NotInProgress + Data transmit is not in progress + 0 + + + InProgress + Data transmit in progress + 1 + + + + + CMDACT + Command transfer in + progress + 11 + 1 + + CMDACT + read + + NotInProgress + Command transfer not in progress + 0 + + + InProgress + Command tranfer in progress + 1 + + + + + DBCKEND + Data block sent/received (CRC check + passed) + 10 + 1 + + DBCKEND + read + + NotTransferred + Data block not sent/received (CRC check failed) + 0 + + + Transferred + Data block sent/received (CRC check passed) + 1 + + + + + STBITERR + Start bit not detected on all data + signals in wide bus mode + 9 + 1 + + STBITERR + read + + Detected + No start bit detected error + 0 + + + NotDetected + Start bit not detected error + 1 + + + + + DATAEND + Data end (data counter, SDIDCOUNT, is + zero) + 8 + 1 + + DATAEND + read + + NotDone + Not done + 0 + + + Done + Data end (DCOUNT, is zero) + 1 + + + + + CMDSENT + Command sent (no response + required) + 7 + 1 + + CMDSENT + read + + NotSent + Command not sent + 0 + + + Sent + Command sent (no response required) + 1 + + + + + CMDREND + Command response received (CRC check + passed) + 6 + 1 + + CMDREND + read + + NotDone + Command not done + 0 + + + Done + Command response received (CRC check passed) + 1 + + + + + RXOVERR + Received FIFO overrun + error + 5 + 1 + + RXOVERR + read + + NoOverrun + No FIFO overrun error + 0 + + + Overrun + Receive FIFO overrun error + 1 + + + + + TXUNDERR + Transmit FIFO underrun + error + 4 + 1 + + TXUNDERR + read + + NoUnderrun + No transmit FIFO underrun error + 0 + + + Underrun + Transmit FIFO underrun error + 1 + + + + + DTIMEOUT + Data timeout + 3 + 1 + + DTIMEOUT + read + + NoTimeout + No data timeout + 0 + + + Timeout + Data timeout + 1 + + + + + CTIMEOUT + Command response timeout + 2 + 1 + + CTIMEOUT + read + + NoTimeout + No Command timeout + 0 + + + Timeout + Command timeout + 1 + + + + + DCRCFAIL + Data block sent/received (CRC check + failed) + 1 + 1 + + DCRCFAIL + read + + NotFailed + No Data block sent/received crc check fail + 0 + + + Failed + Data block sent/received crc failed + 1 + + + + + CCRCFAIL + Command response received (CRC check + failed) + 0 + 1 + + CCRCFAIL + read + + NotFailed + Command response received, crc check passed + 0 + + + Failed + Command response received, crc check failed + 1 + + + + + + + ICR + ICR + interrupt clear register + 0x38 + 0x20 + read-write + 0x00000000 + + + CEATAENDC + CEATAEND flag clear bit + 23 + 1 + + + + SDIOITC + SDIOIT flag clear bit + 22 + 1 + + + + DBCKENDC + DBCKEND flag clear bit + 10 + 1 + + + + STBITERRC + STBITERR flag clear bit + 9 + 1 + + + + DATAENDC + DATAEND flag clear bit + 8 + 1 + + + + CMDSENTC + CMDSENT flag clear bit + 7 + 1 + + + + CMDRENDC + CMDREND flag clear bit + 6 + 1 + + + + RXOVERRC + RXOVERR flag clear bit + 5 + 1 + + + + TXUNDERRC + TXUNDERR flag clear bit + 4 + 1 + + + + DTIMEOUTC + DTIMEOUT flag clear bit + 3 + 1 + + + + CTIMEOUTC + CTIMEOUT flag clear bit + 2 + 1 + + + + DCRCFAILC + DCRCFAIL flag clear bit + 1 + 1 + + + + CCRCFAILC + CCRCFAIL flag clear bit + 0 + 1 + + CCRCFAILCW + write + + Clear + Clear flag + 1 + + + + + + + MASK + MASK + mask register + 0x3C + 0x20 + read-write + 0x00000000 + + + CEATAENDIE + CE-ATA command completion signal + received interrupt enable + 23 + 1 + + + + SDIOITIE + SDIO mode interrupt received interrupt + enable + 22 + 1 + + + + RXDAVLIE + Data available in Rx FIFO interrupt + enable + 21 + 1 + + + + TXDAVLIE + Data available in Tx FIFO interrupt + enable + 20 + 1 + + + + RXFIFOEIE + Rx FIFO empty interrupt + enable + 19 + 1 + + + + TXFIFOEIE + Tx FIFO empty interrupt + enable + 18 + 1 + + + + RXFIFOFIE + Rx FIFO full interrupt + enable + 17 + 1 + + + + TXFIFOFIE + Tx FIFO full interrupt + enable + 16 + 1 + + + + RXFIFOHFIE + Rx FIFO half full interrupt + enable + 15 + 1 + + + + TXFIFOHEIE + Tx FIFO half empty interrupt + enable + 14 + 1 + + + + RXACTIE + Data receive acting interrupt + enable + 13 + 1 + + + + TXACTIE + Data transmit acting interrupt + enable + 12 + 1 + + + + CMDACTIE + Command acting interrupt + enable + 11 + 1 + + + + DBCKENDIE + Data block end interrupt + enable + 10 + 1 + + + + STBITERRIE + Start bit error interrupt + enable + 9 + 1 + + + + DATAENDIE + Data end interrupt enable + 8 + 1 + + + + CMDSENTIE + Command sent interrupt + enable + 7 + 1 + + + + CMDRENDIE + Command response received interrupt + enable + 6 + 1 + + + + RXOVERRIE + Rx FIFO overrun error interrupt + enable + 5 + 1 + + + + TXUNDERRIE + Tx FIFO underrun error interrupt + enable + 4 + 1 + + + + DTIMEOUTIE + Data timeout interrupt + enable + 3 + 1 + + + + CTIMEOUTIE + Command timeout interrupt + enable + 2 + 1 + + + + DCRCFAILIE + Data CRC fail interrupt + enable + 1 + 1 + + + + CCRCFAILIE + Command CRC fail interrupt + enable + 0 + 1 + + CCRCFAILIE + read-write + + Disabled + Interrupt disabled + 0 + + + Enabled + Interrupt enabled + 1 + + + + + + + FIFOCNT + FIFOCNT + FIFO counter register + 0x48 + 0x20 + read-only + 0x00000000 + + + FIFOCOUNT + Remaining number of words to be written + to or read from the FIFO. + 0 + 24 + + + 0 + 16777215 + + + + + + + FIFO + FIFO + data FIFO register + 0x80 + 0x20 + read-write + 0x00000000 + + + FIFOData + Receive and transmit FIFO + data + 0 + 32 + + + 0 + 4294967295 + + + + + + + + + SYSCFG + System configuration controller + SYSCFG + 0x40013800 + + 0x0 + 0x400 + registers + + + + MEMRM + MEMRM + memory remap register + 0x0 + 0x20 + read-write + 0x00000000 + + + MEM_MODE + MEM_MODE + 0 + 2 + + + + + PMC + PMC + peripheral mode configuration + register + 0x4 + 0x20 + read-write + 0x00000000 + + + ADC1DC2 + ADC1DC2 + 16 + 1 + + + + + EXTICR1 + EXTICR1 + external interrupt configuration register + 1 + 0x8 + 0x20 + read-write + 0x00000000 + + + EXTI3 + EXTI x configuration (x = 0 to + 3) + 12 + 4 + + + EXTI2 + EXTI x configuration (x = 0 to + 3) + 8 + 4 + + + EXTI1 + EXTI x configuration (x = 0 to + 3) + 4 + 4 + + + EXTI0 + EXTI x configuration (x = 0 to + 3) + 0 + 4 + + + + + EXTICR2 + EXTICR2 + external interrupt configuration register + 2 + 0xC + 0x20 + read-write + 0x00000000 + + + EXTI7 + EXTI x configuration (x = 4 to + 7) + 12 + 4 + + + EXTI6 + EXTI x configuration (x = 4 to + 7) + 8 + 4 + + + EXTI5 + EXTI x configuration (x = 4 to + 7) + 4 + 4 + + + EXTI4 + EXTI x configuration (x = 4 to + 7) + 0 + 4 + + + + + EXTICR3 + EXTICR3 + external interrupt configuration register + 3 + 0x10 + 0x20 + read-write + 0x00000000 + + + EXTI11 + EXTI x configuration (x = 8 to + 11) + 12 + 4 + + + EXTI10 + EXTI10 + 8 + 4 + + + EXTI9 + EXTI x configuration (x = 8 to + 11) + 4 + 4 + + + EXTI8 + EXTI x configuration (x = 8 to + 11) + 0 + 4 + + + + + EXTICR4 + EXTICR4 + external interrupt configuration register + 4 + 0x14 + 0x20 + read-write + 0x00000000 + + + EXTI15 + EXTI x configuration (x = 12 to + 15) + 12 + 4 + + + EXTI14 + EXTI x configuration (x = 12 to + 15) + 8 + 4 + + + EXTI13 + EXTI x configuration (x = 12 to + 15) + 4 + 4 + + + EXTI12 + EXTI x configuration (x = 12 to + 15) + 0 + 4 + + + + + CMPCR + CMPCR + Compensation cell control + register + 0x20 + 0x20 + read-only + 0x00000000 + + + READY + READY + 8 + 1 + + + CMP_PD + Compensation cell + power-down + 0 + 1 + + + + + + + TIM1 + Advanced-timers + TIM + 0x40010000 + + 0x0 + 0x400 + registers + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + CMS + Center-aligned mode + selection + 5 + 2 + + CMS + read-write + + EdgeAligned + The counter counts up or down depending on the direction bit + 0 + + + CenterAligned1 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting down. + 1 + + + CenterAligned2 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting up. + 2 + + + CenterAligned3 + The counter counts up and down alternatively. Output compare interrupt flags are set both when the counter is counting up or down. + 3 + + + + + DIR + Direction + 4 + 1 + + DIR + read-write + + Up + Counter used as upcounter + 0 + + + Down + Counter used as downcounter + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + OIS4 + Output Idle state 4 + 14 + 1 + + + + OIS3N + Output Idle state 3 + 13 + 1 + + + + OIS3 + Output Idle state 3 + 12 + 1 + + + + OIS2N + Output Idle state 2 + 11 + 1 + + + + OIS2 + Output Idle state 2 + 10 + 1 + + + + OIS1N + Output Idle state 1 + 9 + 1 + + OIS1N + read-write + + Reset + OCxN=0 after a dead-time when MOE=0 + 0 + + + Set + OCxN=1 after a dead-time when MOE=0 + 1 + + + + + OIS1 + Output Idle state 1 + 8 + 1 + + OIS1 + read-write + + Reset + OCx=0 (after a dead-time if OCx(N) is implemented) when MOE=0 + 0 + + + Set + OCx=1 (after a dead-time if OCx(N) is implemented) when MOE=0 + 1 + + + + + TI1S + TI1 selection + 7 + 1 + + TI1S + read-write + + Normal + The TIMx_CH1 pin is connected to TI1 input + 0 + + + XOR + The TIMx_CH1, CH2, CH3 pins are connected to TI1 input + 1 + + + + + MMS + Master mode selection + 4 + 3 + + MMS + read-write + + Reset + The UG bit from the TIMx_EGR register is used as trigger output + 0 + + + Enable + The counter enable signal, CNT_EN, is used as trigger output + 1 + + + Update + The update event is selected as trigger output + 2 + + + ComparePulse + The trigger output send a positive pulse when the CC1IF flag it to be set, as soon as a capture or a compare match occurred + 3 + + + CompareOC1 + OC1REF signal is used as trigger output + 4 + + + CompareOC2 + OC2REF signal is used as trigger output + 5 + + + CompareOC3 + OC3REF signal is used as trigger output + 6 + + + CompareOC4 + OC4REF signal is used as trigger output + 7 + + + + + CCDS + Capture/compare DMA + selection + 3 + 1 + + CCDS + read-write + + OnCompare + CCx DMA request sent when CCx event occurs + 0 + + + OnUpdate + CCx DMA request sent when update event occurs + 1 + + + + + CCUS + Capture/compare control update + selection + 2 + 1 + + + CCPC + Capture/compare preloaded + control + 0 + 1 + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + ETP + External trigger polarity + 15 + 1 + + ETP + read-write + + NotInverted + ETR is noninverted, active at high level or rising edge + 0 + + + Inverted + ETR is inverted, active at low level or falling edge + 1 + + + + + ECE + External clock enable + 14 + 1 + + ECE + read-write + + Disabled + External clock mode 2 disabled + 0 + + + Enabled + External clock mode 2 enabled. The counter is clocked by any active edge on the ETRF signal. + 1 + + + + + ETPS + External trigger prescaler + 12 + 2 + + ETPS + read-write + + Div1 + Prescaler OFF + 0 + + + Div2 + ETRP frequency divided by 2 + 1 + + + Div4 + ETRP frequency divided by 4 + 2 + + + Div8 + ETRP frequency divided by 8 + 3 + + + + + ETF + External trigger filter + 8 + 4 + + ETF + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + MSM + Master/Slave mode + 7 + 1 + + MSM + read-write + + NoSync + No action + 0 + + + Sync + The effect of an event on the trigger input (TRGI) is delayed to allow a perfect synchronization between the current timer and its slaves (through TRGO). It is useful if we want to synchronize several timers on a single external event. + 1 + + + + + TS + Trigger selection + 4 + 3 + + TS + read-write + + ITR0 + Internal Trigger 0 (ITR0) + 0 + + + ITR1 + Internal Trigger 1 (ITR1) + 1 + + + ITR2 + Internal Trigger 2 (ITR2) + 2 + + + TI1F_ED + TI1 Edge Detector (TI1F_ED) + 4 + + + TI1FP1 + Filtered Timer Input 1 (TI1FP1) + 5 + + + TI2FP2 + Filtered Timer Input 2 (TI2FP2) + 6 + + + ETRF + External Trigger input (ETRF) + 7 + + + + + SMS + Slave mode selection + 0 + 3 + + SMS + read-write + + Disabled + Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal clock. + 0 + + + Encoder_Mode_1 + Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending on TI1FP2 level. + 1 + + + Encoder_Mode_2 + Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level. + 2 + + + Encoder_Mode_3 + Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. + 3 + + + Reset_Mode + Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and generates an update of the registers. + 4 + + + Gated_Mode + Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of the counter are controlled. + 5 + + + Trigger_Mode + Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not reset). Only the start of the counter is controlled. + 6 + + + Ext_Clock_Mode + External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter. + 7 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TDE + Trigger DMA request enable + 14 + 1 + + TDE + read-write + + Disabled + Trigger DMA request disabled + 0 + + + Enabled + Trigger DMA request enabled + 1 + + + + + COMDE + COM DMA request enable + 13 + 1 + + + CC4DE + Capture/Compare 4 DMA request + enable + 12 + 1 + + + + CC3DE + Capture/Compare 3 DMA request + enable + 11 + 1 + + + + CC2DE + Capture/Compare 2 DMA request + enable + 10 + 1 + + + + CC1DE + Capture/Compare 1 DMA request + enable + 9 + 1 + + CC1DE + read-write + + Disabled + CCx DMA request disabled + 0 + + + Enabled + CCx DMA request enabled + 1 + + + + + UDE + Update DMA request enable + 8 + 1 + + UDE + read-write + + Disabled + Update DMA request disabled + 0 + + + Enabled + Update DMA request enabled + 1 + + + + + BIE + Break interrupt enable + 7 + 1 + + + TIE + Trigger interrupt enable + 6 + 1 + + TIE + read-write + + Disabled + Trigger interrupt disabled + 0 + + + Enabled + Trigger interrupt enabled + 1 + + + + + COMIE + COM interrupt enable + 5 + 1 + + + CC4IE + Capture/Compare 4 interrupt + enable + 4 + 1 + + + + CC3IE + Capture/Compare 3 interrupt + enable + 3 + 1 + + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + CC1IE + read-write + + Disabled + CCx interrupt disabled + 0 + + + Enabled + CCx interrupt enabled + 1 + + + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC4OF + Capture/Compare 4 overcapture + flag + 12 + 1 + zeroToClear + + read + + + write + + + + CC3OF + Capture/Compare 3 overcapture + flag + 11 + 1 + zeroToClear + + read + + + write + + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + zeroToClear + + read + + + write + + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + zeroToClear + + CC1OFR + read + + Overcapture + The counter value has been captured in TIMx_CCRx register while CCxIF flag was already set + 1 + + + + CC1OFW + write + + Clear + Clear flag + 0 + + + + + BIF + Break interrupt flag + 7 + 1 + + + TIF + Trigger interrupt flag + 6 + 1 + zeroToClear + + TIFR + read + + NoTrigger + No trigger event occurred + 0 + + + Trigger + Trigger interrupt pending + 1 + + + + TIFW + write + + Clear + Clear flag + 0 + + + + + COMIF + COM interrupt flag + 5 + 1 + + + CC4IF + Capture/Compare 4 interrupt + flag + 4 + 1 + zeroToClear + + read + + + write + + + + CC3IF + Capture/Compare 3 interrupt + flag + 3 + 1 + zeroToClear + + read + + + write + + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + zeroToClear + + read + + + write + + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + zeroToClear + + CC1IFR + read + + Match + If CC1 is an output: The content of the counter TIMx_CNT matches the content of the TIMx_CCR1 register. If CC1 is an input: The counter value has been captured in TIMx_CCR1 register. + 1 + + + + CC1IFW + write + + Clear + Clear flag + 0 + + + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + BG + Break generation + 7 + 1 + + + TG + Trigger generation + 6 + 1 + + TGW + write + + Trigger + The TIF flag is set in TIMx_SR register. Related interrupt or DMA transfer can occur if enabled. + 1 + + + + + COMG + Capture/Compare control update + generation + 5 + 1 + + + CC4G + Capture/compare 4 + generation + 4 + 1 + + + + CC3G + Capture/compare 3 + generation + 3 + 1 + + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + CC1GW + write + + Trigger + If CC1 is an output: CC1IF flag is set, Corresponding interrupt or DMA request is sent if enabled. If CC1 is an input: The current value of the counter is captured in TIMx_CCR1 register. + 1 + + + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2CE + Output Compare 2 clear + enable + 15 + 1 + + + OC2M + Output Compare 2 mode + 12 + 3 + + + + OC2PE + Output Compare 2 preload + enable + 11 + 1 + + OC2PE + read-write + + Disabled + Preload register on CCR2 disabled. New values written to CCR2 are taken into account immediately + 0 + + + Enabled + Preload register on CCR2 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC2FE + Output Compare 2 fast + enable + 10 + 1 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + Output + CC2 channel is configured as output + 0 + + + + + OC1CE + Output Compare 1 clear + enable + 7 + 1 + + + OC1M + Output Compare 1 mode + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + Output Compare 1 preload + enable + 3 + 1 + + OC1PE + read-write + + Disabled + Preload register on CCR1 disabled. New values written to CCR1 are taken into account immediately + 0 + + + Enabled + Preload register on CCR1 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC1FE + Output Compare 1 fast + enable + 2 + 1 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + Output + CC1 channel is configured as output + 0 + + + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 4 + + + 0 + 15 + + + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + TI2 + CC2 channel is configured as input, IC2 is mapped on TI2 + 1 + + + TI1 + CC2 channel is configured as input, IC2 is mapped on TI1 + 2 + + + TRC + CC2 channel is configured as input, IC2 is mapped on TRC + 3 + + + + + IC1F + Input capture 1 filter + 4 + 4 + + IC1F + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + TI1 + CC1 channel is configured as input, IC1 is mapped on TI1 + 1 + + + TI2 + CC1 channel is configured as input, IC1 is mapped on TI2 + 2 + + + TRC + CC1 channel is configured as input, IC1 is mapped on TRC + 3 + + + + + + + CCMR2_Output + CCMR2_Output + capture/compare mode register 2 (output + mode) + 0x1C + 0x20 + read-write + 0x00000000 + + + OC4CE + Output compare 4 clear + enable + 15 + 1 + + + OC4M + Output compare 4 mode + 12 + 3 + + + + OC4PE + Output compare 4 preload + enable + 11 + 1 + + OC4PE + read-write + + Disabled + Preload register on CCR4 disabled. New values written to CCR4 are taken into account immediately + 0 + + + Enabled + Preload register on CCR4 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC4FE + Output compare 4 fast + enable + 10 + 1 + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + Output + CC4 channel is configured as output + 0 + + + + + OC3CE + Output compare 3 clear + enable + 7 + 1 + + + OC3M + Output compare 3 mode + 4 + 3 + + OC3M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC3PE + Output compare 3 preload + enable + 3 + 1 + + OC3PE + read-write + + Disabled + Preload register on CCR3 disabled. New values written to CCR3 are taken into account immediately + 0 + + + Enabled + Preload register on CCR3 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC3FE + Output compare 3 fast + enable + 2 + 1 + + + CC3S + Capture/Compare 3 + selection + 0 + 2 + + CC3S + read-write + + Output + CC3 channel is configured as output + 0 + + + + + + + CCMR2_Input + CCMR2_Input + capture/compare mode register 2 (input + mode) + CCMR2_Output + 0x1C + 0x20 + read-write + 0x00000000 + + + IC4F + Input capture 4 filter + 12 + 4 + + + 0 + 15 + + + + + IC4PSC + Input capture 4 prescaler + 10 + 2 + + + 0 + 3 + + + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + TI4 + CC4 channel is configured as input, IC4 is mapped on TI4 + 1 + + + TI3 + CC4 channel is configured as input, IC4 is mapped on TI3 + 2 + + + TRC + CC4 channel is configured as input, IC4 is mapped on TRC + 3 + + + + + IC3F + Input capture 3 filter + 4 + 4 + + + 0 + 15 + + + + + IC3PSC + Input capture 3 prescaler + 2 + 2 + + + 0 + 3 + + + + + CC3S + Capture/compare 3 + selection + 0 + 2 + + CC3S + read-write + + TI3 + CC3 channel is configured as input, IC3 is mapped on TI3 + 1 + + + TI4 + CC3 channel is configured as input, IC3 is mapped on TI4 + 2 + + + TRC + CC3 channel is configured as input, IC3 is mapped on TRC + 3 + + + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC4P + Capture/Compare 3 output + Polarity + 13 + 1 + + + CC4E + Capture/Compare 4 output + enable + 12 + 1 + + + CC3NP + Capture/Compare 3 output + Polarity + 11 + 1 + + + CC3NE + Capture/Compare 3 complementary output + enable + 10 + 1 + + + CC3P + Capture/Compare 3 output + Polarity + 9 + 1 + + + CC3E + Capture/Compare 3 output + enable + 8 + 1 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2NE + Capture/Compare 2 complementary output + enable + 6 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1NE + Capture/Compare 1 complementary output + enable + 2 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + counter value + 0 + 16 + + + 0 + 65535 + + + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + 0 + 65535 + + + + + + + 4 + 0x4 + 1-4 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + 0 + 65535 + + + + + + + DCR + DCR + DMA control register + 0x48 + 0x20 + read-write + 0x00000000 + + + DBL + DMA burst length + 8 + 5 + + + 0 + 18 + + + + + DBA + DMA base address + 0 + 5 + + + 0 + 31 + + + + + + + DMAR + DMAR + DMA address for full transfer + 0x4C + 0x20 + read-write + 0x00000000 + + + DMAB + DMA register for burst + accesses + 0 + 16 + + + + + RCR + RCR + repetition counter register + 0x30 + 0x20 + read-write + 0x00000000 + + + REP + Repetition counter value + 0 + 8 + + + + + BDTR + BDTR + break and dead-time register + 0x44 + 0x20 + read-write + 0x00000000 + + + MOE + Main output enable + 15 + 1 + + MOE + read-write + + DisabledIdle + OC/OCN are disabled or forced idle depending on OSSI + 0 + + + Enabled + OC/OCN are enabled if CCxE/CCxNE are set + 1 + + + + + AOE + Automatic output enable + 14 + 1 + + AOE + read-write + + Manual + MOE can be set only by software + 0 + + + Automatic + MOE can be set by software or automatically at the next update event (if none of the break inputs BRK and BRK2 is active) + 1 + + + + + BKP + Break polarity + 13 + 1 + + BKP + read-write + + ActiveLow + Break input BRKx is active low + 0 + + + ActiveHigh + Break input BRKx is active high + 1 + + + + + BKE + Break enable + 12 + 1 + + BKE + read-write + + Disabled + Break function x disabled + 0 + + + Enabled + Break function x disabled + 1 + + + + + OSSR + Off-state selection for Run + mode + 11 + 1 + + OSSR + read-write + + Disabled + When inactive, OC/OCN outputs are disabled + 0 + + + IdleLevel + When inactive, OC/OCN outputs are enabled with their inactive level + 1 + + + + + OSSI + Off-state selection for Idle + mode + 10 + 1 + + OSSI + read-write + + Disabled + When inactive, OC/OCN outputs are disabled + 0 + + + IdleLevel + When inactive, OC/OCN outputs are forced to idle level + 1 + + + + + LOCK + Lock configuration + 8 + 2 + + LOCK + read-write + + Off + No bit is write protected + 0 + + + Level1 + Any bits except MOE, OSSR, OSSI and LOCK in TIMx_BDTR register, OISx and OISxN bits in TIMx_CR2 register can no longer be written + 1 + + + Level2 + LOCK Level 1 + CC Polarity bits (CCxP/CCxNP bits in TIMx_CCER register, as long as the related channel is configured in output through the CCxS bits) as well as OSSR and OSSI bits can no longer be written + 2 + + + Level3 + LOCK Level 2 + CC Control bits (OCxM and OCxPE bits in TIMx_CCMRx registers, as long as the related channel is configured in output through the CCxS bits) can no longer be written + 3 + + + + + DTG + Dead-time generator setup + 0 + 8 + + + 0 + 255 + + + + + + + + + TIM10 + General-purpose-timers + TIM + 0x40014400 + + 0x0 + 0x400 + registers + + + SPI1 + SPI1 global interrupt + 35 + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC1M + Output Compare 1 mode + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + Output Compare 1 preload + enable + 3 + 1 + + + OC1FE + Output Compare 1 fast + enable + 2 + 1 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC1F + Input capture 1 filter + 4 + 4 + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + counter value + 0 + 16 + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + + + 1 + 0x0 + 1-1 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + + + + + TIM11 + General-purpose-timers + TIM + 0x40014800 + + 0x0 + 0x400 + registers + + + SPI2 + SPI2 global interrupt + 36 + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC1M + Output Compare 1 mode + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + Output Compare 1 preload + enable + 3 + 1 + + + OC1FE + Output Compare 1 fast + enable + 2 + 1 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC1F + Input capture 1 filter + 4 + 4 + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + counter value + 0 + 16 + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + + + 1 + 0x0 + 1-1 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + + + OR + OR + option register + 0x50 + 0x20 + read-write + 0x00000000 + + + RMP + Input 1 remapping + capability + 0 + 2 + + + + + + + TIM2 + General purpose timers + TIM + 0x40000000 + + 0x0 + 0x400 + registers + + + SPI3 + SPI3 global interrupt + 51 + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + CMS + Center-aligned mode + selection + 5 + 2 + + CMS + read-write + + EdgeAligned + The counter counts up or down depending on the direction bit + 0 + + + CenterAligned1 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting down. + 1 + + + CenterAligned2 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting up. + 2 + + + CenterAligned3 + The counter counts up and down alternatively. Output compare interrupt flags are set both when the counter is counting up or down. + 3 + + + + + DIR + Direction + 4 + 1 + + DIR + read-write + + Up + Counter used as upcounter + 0 + + + Down + Counter used as downcounter + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + TI1S + TI1 selection + 7 + 1 + + TI1S + read-write + + Normal + The TIMx_CH1 pin is connected to TI1 input + 0 + + + XOR + The TIMx_CH1, CH2, CH3 pins are connected to TI1 input + 1 + + + + + MMS + Master mode selection + 4 + 3 + + MMS + read-write + + Reset + The UG bit from the TIMx_EGR register is used as trigger output + 0 + + + Enable + The counter enable signal, CNT_EN, is used as trigger output + 1 + + + Update + The update event is selected as trigger output + 2 + + + ComparePulse + The trigger output send a positive pulse when the CC1IF flag it to be set, as soon as a capture or a compare match occurred + 3 + + + CompareOC1 + OC1REF signal is used as trigger output + 4 + + + CompareOC2 + OC2REF signal is used as trigger output + 5 + + + CompareOC3 + OC3REF signal is used as trigger output + 6 + + + CompareOC4 + OC4REF signal is used as trigger output + 7 + + + + + CCDS + Capture/compare DMA + selection + 3 + 1 + + CCDS + read-write + + OnCompare + CCx DMA request sent when CCx event occurs + 0 + + + OnUpdate + CCx DMA request sent when update event occurs + 1 + + + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + ETP + External trigger polarity + 15 + 1 + + ETP + read-write + + NotInverted + ETR is noninverted, active at high level or rising edge + 0 + + + Inverted + ETR is inverted, active at low level or falling edge + 1 + + + + + ECE + External clock enable + 14 + 1 + + ECE + read-write + + Disabled + External clock mode 2 disabled + 0 + + + Enabled + External clock mode 2 enabled. The counter is clocked by any active edge on the ETRF signal. + 1 + + + + + ETPS + External trigger prescaler + 12 + 2 + + ETPS + read-write + + Div1 + Prescaler OFF + 0 + + + Div2 + ETRP frequency divided by 2 + 1 + + + Div4 + ETRP frequency divided by 4 + 2 + + + Div8 + ETRP frequency divided by 8 + 3 + + + + + ETF + External trigger filter + 8 + 4 + + ETF + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + MSM + Master/Slave mode + 7 + 1 + + MSM + read-write + + NoSync + No action + 0 + + + Sync + The effect of an event on the trigger input (TRGI) is delayed to allow a perfect synchronization between the current timer and its slaves (through TRGO). It is useful if we want to synchronize several timers on a single external event. + 1 + + + + + TS + Trigger selection + 4 + 3 + + TS + read-write + + ITR0 + Internal Trigger 0 (ITR0) + 0 + + + ITR1 + Internal Trigger 1 (ITR1) + 1 + + + ITR2 + Internal Trigger 2 (ITR2) + 2 + + + TI1F_ED + TI1 Edge Detector (TI1F_ED) + 4 + + + TI1FP1 + Filtered Timer Input 1 (TI1FP1) + 5 + + + TI2FP2 + Filtered Timer Input 2 (TI2FP2) + 6 + + + ETRF + External Trigger input (ETRF) + 7 + + + + + SMS + Slave mode selection + 0 + 3 + + SMS + read-write + + Disabled + Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal clock. + 0 + + + Encoder_Mode_1 + Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending on TI1FP2 level. + 1 + + + Encoder_Mode_2 + Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level. + 2 + + + Encoder_Mode_3 + Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. + 3 + + + Reset_Mode + Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and generates an update of the registers. + 4 + + + Gated_Mode + Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of the counter are controlled. + 5 + + + Trigger_Mode + Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not reset). Only the start of the counter is controlled. + 6 + + + Ext_Clock_Mode + External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter. + 7 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TDE + Trigger DMA request enable + 14 + 1 + + TDE + read-write + + Disabled + Trigger DMA request disabled + 0 + + + Enabled + Trigger DMA request enabled + 1 + + + + + CC4DE + Capture/Compare 4 DMA request + enable + 12 + 1 + + + + CC3DE + Capture/Compare 3 DMA request + enable + 11 + 1 + + + + CC2DE + Capture/Compare 2 DMA request + enable + 10 + 1 + + + + CC1DE + Capture/Compare 1 DMA request + enable + 9 + 1 + + CC1DE + read-write + + Disabled + CCx DMA request disabled + 0 + + + Enabled + CCx DMA request enabled + 1 + + + + + UDE + Update DMA request enable + 8 + 1 + + UDE + read-write + + Disabled + Update DMA request disabled + 0 + + + Enabled + Update DMA request enabled + 1 + + + + + TIE + Trigger interrupt enable + 6 + 1 + + TIE + read-write + + Disabled + Trigger interrupt disabled + 0 + + + Enabled + Trigger interrupt enabled + 1 + + + + + CC4IE + Capture/Compare 4 interrupt + enable + 4 + 1 + + + + CC3IE + Capture/Compare 3 interrupt + enable + 3 + 1 + + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + CC1IE + read-write + + Disabled + CCx interrupt disabled + 0 + + + Enabled + CCx interrupt enabled + 1 + + + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC4OF + Capture/Compare 4 overcapture + flag + 12 + 1 + zeroToClear + + read + + + write + + + + CC3OF + Capture/Compare 3 overcapture + flag + 11 + 1 + zeroToClear + + read + + + write + + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + zeroToClear + + read + + + write + + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + zeroToClear + + CC1OFR + read + + Overcapture + The counter value has been captured in TIMx_CCRx register while CCxIF flag was already set + 1 + + + + CC1OFW + write + + Clear + Clear flag + 0 + + + + + TIF + Trigger interrupt flag + 6 + 1 + zeroToClear + + TIFR + read + + NoTrigger + No trigger event occurred + 0 + + + Trigger + Trigger interrupt pending + 1 + + + + TIFW + write + + Clear + Clear flag + 0 + + + + + CC4IF + Capture/Compare 4 interrupt + flag + 4 + 1 + zeroToClear + + read + + + write + + + + CC3IF + Capture/Compare 3 interrupt + flag + 3 + 1 + zeroToClear + + read + + + write + + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + zeroToClear + + read + + + write + + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + zeroToClear + + CC1IFR + read + + Match + If CC1 is an output: The content of the counter TIMx_CNT matches the content of the TIMx_CCR1 register. If CC1 is an input: The counter value has been captured in TIMx_CCR1 register. + 1 + + + + CC1IFW + write + + Clear + Clear flag + 0 + + + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + TG + Trigger generation + 6 + 1 + + TGW + write + + Trigger + The TIF flag is set in TIMx_SR register. Related interrupt or DMA transfer can occur if enabled. + 1 + + + + + CC4G + Capture/compare 4 + generation + 4 + 1 + + + + CC3G + Capture/compare 3 + generation + 3 + 1 + + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + CC1GW + write + + Trigger + If CC1 is an output: CC1IF flag is set, Corresponding interrupt or DMA request is sent if enabled. If CC1 is an input: The current value of the counter is captured in TIMx_CCR1 register. + 1 + + + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2CE + OC2CE + 15 + 1 + + + OC2M + OC2M + 12 + 3 + + + + OC2PE + OC2PE + 11 + 1 + + OC2PE + read-write + + Disabled + Preload register on CCR2 disabled. New values written to CCR2 are taken into account immediately + 0 + + + Enabled + Preload register on CCR2 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC2FE + OC2FE + 10 + 1 + + + CC2S + CC2S + 8 + 2 + + CC2S + read-write + + Output + CC2 channel is configured as output + 0 + + + + + OC1CE + OC1CE + 7 + 1 + + + OC1M + OC1M + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + OC1PE + 3 + 1 + + OC1PE + read-write + + Disabled + Preload register on CCR1 disabled. New values written to CCR1 are taken into account immediately + 0 + + + Enabled + Preload register on CCR1 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC1FE + OC1FE + 2 + 1 + + + CC1S + CC1S + 0 + 2 + + CC1S + read-write + + Output + CC1 channel is configured as output + 0 + + + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 4 + + + 0 + 15 + + + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + TI2 + CC2 channel is configured as input, IC2 is mapped on TI2 + 1 + + + TI1 + CC2 channel is configured as input, IC2 is mapped on TI1 + 2 + + + TRC + CC2 channel is configured as input, IC2 is mapped on TRC + 3 + + + + + IC1F + Input capture 1 filter + 4 + 4 + + IC1F + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + TI1 + CC1 channel is configured as input, IC1 is mapped on TI1 + 1 + + + TI2 + CC1 channel is configured as input, IC1 is mapped on TI2 + 2 + + + TRC + CC1 channel is configured as input, IC1 is mapped on TRC + 3 + + + + + + + CCMR2_Output + CCMR2_Output + capture/compare mode register 2 (output + mode) + 0x1C + 0x20 + read-write + 0x00000000 + + + OC4CE + O24CE + 15 + 1 + + + OC4M + OC4M + 12 + 3 + + + + OC4PE + OC4PE + 11 + 1 + + OC4PE + read-write + + Disabled + Preload register on CCR4 disabled. New values written to CCR4 are taken into account immediately + 0 + + + Enabled + Preload register on CCR4 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC4FE + OC4FE + 10 + 1 + + + CC4S + CC4S + 8 + 2 + + CC4S + read-write + + Output + CC4 channel is configured as output + 0 + + + + + OC3CE + OC3CE + 7 + 1 + + + OC3M + OC3M + 4 + 3 + + OC3M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC3PE + OC3PE + 3 + 1 + + OC3PE + read-write + + Disabled + Preload register on CCR3 disabled. New values written to CCR3 are taken into account immediately + 0 + + + Enabled + Preload register on CCR3 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC3FE + OC3FE + 2 + 1 + + + CC3S + CC3S + 0 + 2 + + CC3S + read-write + + Output + CC3 channel is configured as output + 0 + + + + + + + CCMR2_Input + CCMR2_Input + capture/compare mode register 2 (input + mode) + CCMR2_Output + 0x1C + 0x20 + read-write + 0x00000000 + + + IC4F + Input capture 4 filter + 12 + 4 + + + 0 + 15 + + + + + IC4PSC + Input capture 4 prescaler + 10 + 2 + + + 0 + 3 + + + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + TI4 + CC4 channel is configured as input, IC4 is mapped on TI4 + 1 + + + TI3 + CC4 channel is configured as input, IC4 is mapped on TI3 + 2 + + + TRC + CC4 channel is configured as input, IC4 is mapped on TRC + 3 + + + + + IC3F + Input capture 3 filter + 4 + 4 + + + 0 + 15 + + + + + IC3PSC + Input capture 3 prescaler + 2 + 2 + + + 0 + 3 + + + + + CC3S + Capture/compare 3 + selection + 0 + 2 + + CC3S + read-write + + TI3 + CC3 channel is configured as input, IC3 is mapped on TI3 + 1 + + + TI4 + CC3 channel is configured as input, IC3 is mapped on TI4 + 2 + + + TRC + CC3 channel is configured as input, IC3 is mapped on TRC + 3 + + + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC4NP + Capture/Compare 4 output + Polarity + 15 + 1 + + + CC4P + Capture/Compare 3 output + Polarity + 13 + 1 + + + CC4E + Capture/Compare 4 output + enable + 12 + 1 + + + CC3NP + Capture/Compare 3 output + Polarity + 11 + 1 + + + CC3P + Capture/Compare 3 output + Polarity + 9 + 1 + + + CC3E + Capture/Compare 3 output + enable + 8 + 1 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + Counter value + 0 + 32 + + + 0 + 4294967295 + + + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 32 + + + 0 + 4294967295 + + + + + + + 4 + 0x4 + 1-4 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 32 + + + 0 + 4294967295 + + + + + + + DCR + DCR + DMA control register + 0x48 + 0x20 + read-write + 0x00000000 + + + DBL + DMA burst length + 8 + 5 + + + 0 + 18 + + + + + DBA + DMA base address + 0 + 5 + + + 0 + 31 + + + + + + + DMAR + DMAR + DMA address for full transfer + 0x4C + 0x20 + read-write + 0x00000000 + + + DMAB + DMA register for burst + accesses + 0 + 16 + + + + + OR + OR + TIM5 option register + 0x50 + 0x20 + read-write + 0x00000000 + + + ITR1_RMP + Timer Input 4 remap + 10 + 2 + + + + + + + TIM3 + General purpose timers + TIM + 0x40000400 + + 0x0 + 0x400 + registers + + + SPI4 + SPI4 global interrupt + 84 + + + TIM4 + TIM4 global interrupt + 30 + + + TIM5 + TIM5 global interrupt + 50 + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + CMS + Center-aligned mode + selection + 5 + 2 + + CMS + read-write + + EdgeAligned + The counter counts up or down depending on the direction bit + 0 + + + CenterAligned1 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting down. + 1 + + + CenterAligned2 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting up. + 2 + + + CenterAligned3 + The counter counts up and down alternatively. Output compare interrupt flags are set both when the counter is counting up or down. + 3 + + + + + DIR + Direction + 4 + 1 + + DIR + read-write + + Up + Counter used as upcounter + 0 + + + Down + Counter used as downcounter + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + TI1S + TI1 selection + 7 + 1 + + TI1S + read-write + + Normal + The TIMx_CH1 pin is connected to TI1 input + 0 + + + XOR + The TIMx_CH1, CH2, CH3 pins are connected to TI1 input + 1 + + + + + MMS + Master mode selection + 4 + 3 + + MMS + read-write + + Reset + The UG bit from the TIMx_EGR register is used as trigger output + 0 + + + Enable + The counter enable signal, CNT_EN, is used as trigger output + 1 + + + Update + The update event is selected as trigger output + 2 + + + ComparePulse + The trigger output send a positive pulse when the CC1IF flag it to be set, as soon as a capture or a compare match occurred + 3 + + + CompareOC1 + OC1REF signal is used as trigger output + 4 + + + CompareOC2 + OC2REF signal is used as trigger output + 5 + + + CompareOC3 + OC3REF signal is used as trigger output + 6 + + + CompareOC4 + OC4REF signal is used as trigger output + 7 + + + + + CCDS + Capture/compare DMA + selection + 3 + 1 + + CCDS + read-write + + OnCompare + CCx DMA request sent when CCx event occurs + 0 + + + OnUpdate + CCx DMA request sent when update event occurs + 1 + + + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + ETP + External trigger polarity + 15 + 1 + + ETP + read-write + + NotInverted + ETR is noninverted, active at high level or rising edge + 0 + + + Inverted + ETR is inverted, active at low level or falling edge + 1 + + + + + ECE + External clock enable + 14 + 1 + + ECE + read-write + + Disabled + External clock mode 2 disabled + 0 + + + Enabled + External clock mode 2 enabled. The counter is clocked by any active edge on the ETRF signal. + 1 + + + + + ETPS + External trigger prescaler + 12 + 2 + + ETPS + read-write + + Div1 + Prescaler OFF + 0 + + + Div2 + ETRP frequency divided by 2 + 1 + + + Div4 + ETRP frequency divided by 4 + 2 + + + Div8 + ETRP frequency divided by 8 + 3 + + + + + ETF + External trigger filter + 8 + 4 + + ETF + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + MSM + Master/Slave mode + 7 + 1 + + MSM + read-write + + NoSync + No action + 0 + + + Sync + The effect of an event on the trigger input (TRGI) is delayed to allow a perfect synchronization between the current timer and its slaves (through TRGO). It is useful if we want to synchronize several timers on a single external event. + 1 + + + + + TS + Trigger selection + 4 + 3 + + TS + read-write + + ITR0 + Internal Trigger 0 (ITR0) + 0 + + + ITR1 + Internal Trigger 1 (ITR1) + 1 + + + ITR2 + Internal Trigger 2 (ITR2) + 2 + + + TI1F_ED + TI1 Edge Detector (TI1F_ED) + 4 + + + TI1FP1 + Filtered Timer Input 1 (TI1FP1) + 5 + + + TI2FP2 + Filtered Timer Input 2 (TI2FP2) + 6 + + + ETRF + External Trigger input (ETRF) + 7 + + + + + SMS + Slave mode selection + 0 + 3 + + SMS + read-write + + Disabled + Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal clock. + 0 + + + Encoder_Mode_1 + Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending on TI1FP2 level. + 1 + + + Encoder_Mode_2 + Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level. + 2 + + + Encoder_Mode_3 + Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. + 3 + + + Reset_Mode + Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and generates an update of the registers. + 4 + + + Gated_Mode + Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of the counter are controlled. + 5 + + + Trigger_Mode + Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not reset). Only the start of the counter is controlled. + 6 + + + Ext_Clock_Mode + External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter. + 7 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TDE + Trigger DMA request enable + 14 + 1 + + TDE + read-write + + Disabled + Trigger DMA request disabled + 0 + + + Enabled + Trigger DMA request enabled + 1 + + + + + CC4DE + Capture/Compare 4 DMA request + enable + 12 + 1 + + + + CC3DE + Capture/Compare 3 DMA request + enable + 11 + 1 + + + + CC2DE + Capture/Compare 2 DMA request + enable + 10 + 1 + + + + CC1DE + Capture/Compare 1 DMA request + enable + 9 + 1 + + CC1DE + read-write + + Disabled + CCx DMA request disabled + 0 + + + Enabled + CCx DMA request enabled + 1 + + + + + UDE + Update DMA request enable + 8 + 1 + + UDE + read-write + + Disabled + Update DMA request disabled + 0 + + + Enabled + Update DMA request enabled + 1 + + + + + TIE + Trigger interrupt enable + 6 + 1 + + TIE + read-write + + Disabled + Trigger interrupt disabled + 0 + + + Enabled + Trigger interrupt enabled + 1 + + + + + CC4IE + Capture/Compare 4 interrupt + enable + 4 + 1 + + + + CC3IE + Capture/Compare 3 interrupt + enable + 3 + 1 + + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + CC1IE + read-write + + Disabled + CCx interrupt disabled + 0 + + + Enabled + CCx interrupt enabled + 1 + + + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC4OF + Capture/Compare 4 overcapture + flag + 12 + 1 + zeroToClear + + read + + + write + + + + CC3OF + Capture/Compare 3 overcapture + flag + 11 + 1 + zeroToClear + + read + + + write + + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + zeroToClear + + read + + + write + + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + zeroToClear + + CC1OFR + read + + Overcapture + The counter value has been captured in TIMx_CCRx register while CCxIF flag was already set + 1 + + + + CC1OFW + write + + Clear + Clear flag + 0 + + + + + TIF + Trigger interrupt flag + 6 + 1 + zeroToClear + + TIFR + read + + NoTrigger + No trigger event occurred + 0 + + + Trigger + Trigger interrupt pending + 1 + + + + TIFW + write + + Clear + Clear flag + 0 + + + + + CC4IF + Capture/Compare 4 interrupt + flag + 4 + 1 + zeroToClear + + read + + + write + + + + CC3IF + Capture/Compare 3 interrupt + flag + 3 + 1 + zeroToClear + + read + + + write + + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + zeroToClear + + read + + + write + + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + zeroToClear + + CC1IFR + read + + Match + If CC1 is an output: The content of the counter TIMx_CNT matches the content of the TIMx_CCR1 register. If CC1 is an input: The counter value has been captured in TIMx_CCR1 register. + 1 + + + + CC1IFW + write + + Clear + Clear flag + 0 + + + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + TG + Trigger generation + 6 + 1 + + TGW + write + + Trigger + The TIF flag is set in TIMx_SR register. Related interrupt or DMA transfer can occur if enabled. + 1 + + + + + CC4G + Capture/compare 4 + generation + 4 + 1 + + + + CC3G + Capture/compare 3 + generation + 3 + 1 + + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + CC1GW + write + + Trigger + If CC1 is an output: CC1IF flag is set, Corresponding interrupt or DMA request is sent if enabled. If CC1 is an input: The current value of the counter is captured in TIMx_CCR1 register. + 1 + + + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2CE + OC2CE + 15 + 1 + + + OC2M + OC2M + 12 + 3 + + + + OC2PE + OC2PE + 11 + 1 + + OC2PE + read-write + + Disabled + Preload register on CCR2 disabled. New values written to CCR2 are taken into account immediately + 0 + + + Enabled + Preload register on CCR2 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC2FE + OC2FE + 10 + 1 + + + CC2S + CC2S + 8 + 2 + + CC2S + read-write + + Output + CC2 channel is configured as output + 0 + + + + + OC1CE + OC1CE + 7 + 1 + + + OC1M + OC1M + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + OC1PE + 3 + 1 + + OC1PE + read-write + + Disabled + Preload register on CCR1 disabled. New values written to CCR1 are taken into account immediately + 0 + + + Enabled + Preload register on CCR1 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC1FE + OC1FE + 2 + 1 + + + CC1S + CC1S + 0 + 2 + + CC1S + read-write + + Output + CC1 channel is configured as output + 0 + + + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 4 + + + 0 + 15 + + + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + TI2 + CC2 channel is configured as input, IC2 is mapped on TI2 + 1 + + + TI1 + CC2 channel is configured as input, IC2 is mapped on TI1 + 2 + + + TRC + CC2 channel is configured as input, IC2 is mapped on TRC + 3 + + + + + IC1F + Input capture 1 filter + 4 + 4 + + IC1F + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + TI1 + CC1 channel is configured as input, IC1 is mapped on TI1 + 1 + + + TI2 + CC1 channel is configured as input, IC1 is mapped on TI2 + 2 + + + TRC + CC1 channel is configured as input, IC1 is mapped on TRC + 3 + + + + + + + CCMR2_Output + CCMR2_Output + capture/compare mode register 2 (output + mode) + 0x1C + 0x20 + read-write + 0x00000000 + + + OC4CE + O24CE + 15 + 1 + + + OC4M + OC4M + 12 + 3 + + + + OC4PE + OC4PE + 11 + 1 + + OC4PE + read-write + + Disabled + Preload register on CCR4 disabled. New values written to CCR4 are taken into account immediately + 0 + + + Enabled + Preload register on CCR4 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC4FE + OC4FE + 10 + 1 + + + CC4S + CC4S + 8 + 2 + + CC4S + read-write + + Output + CC4 channel is configured as output + 0 + + + + + OC3CE + OC3CE + 7 + 1 + + + OC3M + OC3M + 4 + 3 + + OC3M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC3PE + OC3PE + 3 + 1 + + OC3PE + read-write + + Disabled + Preload register on CCR3 disabled. New values written to CCR3 are taken into account immediately + 0 + + + Enabled + Preload register on CCR3 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC3FE + OC3FE + 2 + 1 + + + CC3S + CC3S + 0 + 2 + + CC3S + read-write + + Output + CC3 channel is configured as output + 0 + + + + + + + CCMR2_Input + CCMR2_Input + capture/compare mode register 2 (input + mode) + CCMR2_Output + 0x1C + 0x20 + read-write + 0x00000000 + + + IC4F + Input capture 4 filter + 12 + 4 + + + 0 + 15 + + + + + IC4PSC + Input capture 4 prescaler + 10 + 2 + + + 0 + 3 + + + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + TI4 + CC4 channel is configured as input, IC4 is mapped on TI4 + 1 + + + TI3 + CC4 channel is configured as input, IC4 is mapped on TI3 + 2 + + + TRC + CC4 channel is configured as input, IC4 is mapped on TRC + 3 + + + + + IC3F + Input capture 3 filter + 4 + 4 + + + 0 + 15 + + + + + IC3PSC + Input capture 3 prescaler + 2 + 2 + + + 0 + 3 + + + + + CC3S + Capture/compare 3 + selection + 0 + 2 + + CC3S + read-write + + TI3 + CC3 channel is configured as input, IC3 is mapped on TI3 + 1 + + + TI4 + CC3 channel is configured as input, IC3 is mapped on TI4 + 2 + + + TRC + CC3 channel is configured as input, IC3 is mapped on TRC + 3 + + + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC4NP + Capture/Compare 4 output + Polarity + 15 + 1 + + + CC4P + Capture/Compare 3 output + Polarity + 13 + 1 + + + CC4E + Capture/Compare 4 output + enable + 12 + 1 + + + CC3NP + Capture/Compare 3 output + Polarity + 11 + 1 + + + CC3P + Capture/Compare 3 output + Polarity + 9 + 1 + + + CC3E + Capture/Compare 3 output + enable + 8 + 1 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + Counter value + 0 + 16 + + + 0 + 65535 + + + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + 0 + 65535 + + + + + + + 4 + 0x4 + 1-4 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + 0 + 65535 + + + + + + + DCR + DCR + DMA control register + 0x48 + 0x20 + read-write + 0x00000000 + + + DBL + DMA burst length + 8 + 5 + + + 0 + 18 + + + + + DBA + DMA base address + 0 + 5 + + + 0 + 31 + + + + + + + DMAR + DMAR + DMA address for full transfer + 0x4C + 0x20 + read-write + 0x00000000 + + + DMAB + DMA register for burst + accesses + 0 + 16 + + + + + + + TIM4 + TIM + 0x40000800 + + + TIM5 + General-purpose-timers + TIM + 0x40000C00 + + 0x0 + 0x400 + registers + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + CMS + Center-aligned mode + selection + 5 + 2 + + CMS + read-write + + EdgeAligned + The counter counts up or down depending on the direction bit + 0 + + + CenterAligned1 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting down. + 1 + + + CenterAligned2 + The counter counts up and down alternatively. Output compare interrupt flags are set only when the counter is counting up. + 2 + + + CenterAligned3 + The counter counts up and down alternatively. Output compare interrupt flags are set both when the counter is counting up or down. + 3 + + + + + DIR + Direction + 4 + 1 + + DIR + read-write + + Up + Counter used as upcounter + 0 + + + Down + Counter used as downcounter + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + TI1S + TI1 selection + 7 + 1 + + TI1S + read-write + + Normal + The TIMx_CH1 pin is connected to TI1 input + 0 + + + XOR + The TIMx_CH1, CH2, CH3 pins are connected to TI1 input + 1 + + + + + MMS + Master mode selection + 4 + 3 + + MMS + read-write + + Reset + The UG bit from the TIMx_EGR register is used as trigger output + 0 + + + Enable + The counter enable signal, CNT_EN, is used as trigger output + 1 + + + Update + The update event is selected as trigger output + 2 + + + ComparePulse + The trigger output send a positive pulse when the CC1IF flag it to be set, as soon as a capture or a compare match occurred + 3 + + + CompareOC1 + OC1REF signal is used as trigger output + 4 + + + CompareOC2 + OC2REF signal is used as trigger output + 5 + + + CompareOC3 + OC3REF signal is used as trigger output + 6 + + + CompareOC4 + OC4REF signal is used as trigger output + 7 + + + + + CCDS + Capture/compare DMA + selection + 3 + 1 + + CCDS + read-write + + OnCompare + CCx DMA request sent when CCx event occurs + 0 + + + OnUpdate + CCx DMA request sent when update event occurs + 1 + + + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + ETP + External trigger polarity + 15 + 1 + + ETP + read-write + + NotInverted + ETR is noninverted, active at high level or rising edge + 0 + + + Inverted + ETR is inverted, active at low level or falling edge + 1 + + + + + ECE + External clock enable + 14 + 1 + + ECE + read-write + + Disabled + External clock mode 2 disabled + 0 + + + Enabled + External clock mode 2 enabled. The counter is clocked by any active edge on the ETRF signal. + 1 + + + + + ETPS + External trigger prescaler + 12 + 2 + + ETPS + read-write + + Div1 + Prescaler OFF + 0 + + + Div2 + ETRP frequency divided by 2 + 1 + + + Div4 + ETRP frequency divided by 4 + 2 + + + Div8 + ETRP frequency divided by 8 + 3 + + + + + ETF + External trigger filter + 8 + 4 + + ETF + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + MSM + Master/Slave mode + 7 + 1 + + MSM + read-write + + NoSync + No action + 0 + + + Sync + The effect of an event on the trigger input (TRGI) is delayed to allow a perfect synchronization between the current timer and its slaves (through TRGO). It is useful if we want to synchronize several timers on a single external event. + 1 + + + + + TS + Trigger selection + 4 + 3 + + TS + read-write + + ITR0 + Internal Trigger 0 (ITR0) + 0 + + + ITR1 + Internal Trigger 1 (ITR1) + 1 + + + ITR2 + Internal Trigger 2 (ITR2) + 2 + + + TI1F_ED + TI1 Edge Detector (TI1F_ED) + 4 + + + TI1FP1 + Filtered Timer Input 1 (TI1FP1) + 5 + + + TI2FP2 + Filtered Timer Input 2 (TI2FP2) + 6 + + + ETRF + External Trigger input (ETRF) + 7 + + + + + SMS + Slave mode selection + 0 + 3 + + SMS + read-write + + Disabled + Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal clock. + 0 + + + Encoder_Mode_1 + Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending on TI1FP2 level. + 1 + + + Encoder_Mode_2 + Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level. + 2 + + + Encoder_Mode_3 + Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. + 3 + + + Reset_Mode + Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and generates an update of the registers. + 4 + + + Gated_Mode + Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of the counter are controlled. + 5 + + + Trigger_Mode + Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not reset). Only the start of the counter is controlled. + 6 + + + Ext_Clock_Mode + External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter. + 7 + + + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TDE + Trigger DMA request enable + 14 + 1 + + TDE + read-write + + Disabled + Trigger DMA request disabled + 0 + + + Enabled + Trigger DMA request enabled + 1 + + + + + CC4DE + Capture/Compare 4 DMA request + enable + 12 + 1 + + + + CC3DE + Capture/Compare 3 DMA request + enable + 11 + 1 + + + + CC2DE + Capture/Compare 2 DMA request + enable + 10 + 1 + + + + CC1DE + Capture/Compare 1 DMA request + enable + 9 + 1 + + CC1DE + read-write + + Disabled + CCx DMA request disabled + 0 + + + Enabled + CCx DMA request enabled + 1 + + + + + UDE + Update DMA request enable + 8 + 1 + + UDE + read-write + + Disabled + Update DMA request disabled + 0 + + + Enabled + Update DMA request enabled + 1 + + + + + TIE + Trigger interrupt enable + 6 + 1 + + TIE + read-write + + Disabled + Trigger interrupt disabled + 0 + + + Enabled + Trigger interrupt enabled + 1 + + + + + CC4IE + Capture/Compare 4 interrupt + enable + 4 + 1 + + + + CC3IE + Capture/Compare 3 interrupt + enable + 3 + 1 + + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + CC1IE + read-write + + Disabled + CCx interrupt disabled + 0 + + + Enabled + CCx interrupt enabled + 1 + + + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC4OF + Capture/Compare 4 overcapture + flag + 12 + 1 + zeroToClear + + read + + + write + + + + CC3OF + Capture/Compare 3 overcapture + flag + 11 + 1 + zeroToClear + + read + + + write + + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + zeroToClear + + read + + + write + + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + zeroToClear + + CC1OFR + read + + Overcapture + The counter value has been captured in TIMx_CCRx register while CCxIF flag was already set + 1 + + + + CC1OFW + write + + Clear + Clear flag + 0 + + + + + TIF + Trigger interrupt flag + 6 + 1 + zeroToClear + + TIFR + read + + NoTrigger + No trigger event occurred + 0 + + + Trigger + Trigger interrupt pending + 1 + + + + TIFW + write + + Clear + Clear flag + 0 + + + + + CC4IF + Capture/Compare 4 interrupt + flag + 4 + 1 + zeroToClear + + read + + + write + + + + CC3IF + Capture/Compare 3 interrupt + flag + 3 + 1 + zeroToClear + + read + + + write + + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + zeroToClear + + read + + + write + + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + zeroToClear + + CC1IFR + read + + Match + If CC1 is an output: The content of the counter TIMx_CNT matches the content of the TIMx_CCR1 register. If CC1 is an input: The counter value has been captured in TIMx_CCR1 register. + 1 + + + + CC1IFW + write + + Clear + Clear flag + 0 + + + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + TG + Trigger generation + 6 + 1 + + TGW + write + + Trigger + The TIF flag is set in TIMx_SR register. Related interrupt or DMA transfer can occur if enabled. + 1 + + + + + CC4G + Capture/compare 4 + generation + 4 + 1 + + + + CC3G + Capture/compare 3 + generation + 3 + 1 + + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + CC1GW + write + + Trigger + If CC1 is an output: CC1IF flag is set, Corresponding interrupt or DMA request is sent if enabled. If CC1 is an input: The current value of the counter is captured in TIMx_CCR1 register. + 1 + + + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2CE + OC2CE + 15 + 1 + + + OC2M + OC2M + 12 + 3 + + + + OC2PE + OC2PE + 11 + 1 + + OC2PE + read-write + + Disabled + Preload register on CCR2 disabled. New values written to CCR2 are taken into account immediately + 0 + + + Enabled + Preload register on CCR2 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC2FE + OC2FE + 10 + 1 + + + CC2S + CC2S + 8 + 2 + + CC2S + read-write + + Output + CC2 channel is configured as output + 0 + + + + + OC1CE + OC1CE + 7 + 1 + + + OC1M + OC1M + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + OC1PE + 3 + 1 + + OC1PE + read-write + + Disabled + Preload register on CCR1 disabled. New values written to CCR1 are taken into account immediately + 0 + + + Enabled + Preload register on CCR1 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC1FE + OC1FE + 2 + 1 + + + CC1S + CC1S + 0 + 2 + + CC1S + read-write + + Output + CC1 channel is configured as output + 0 + + + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 4 + + + 0 + 15 + + + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + CC2S + read-write + + TI2 + CC2 channel is configured as input, IC2 is mapped on TI2 + 1 + + + TI1 + CC2 channel is configured as input, IC2 is mapped on TI1 + 2 + + + TRC + CC2 channel is configured as input, IC2 is mapped on TRC + 3 + + + + + IC1F + Input capture 1 filter + 4 + 4 + + IC1F + read-write + + NoFilter + No filter, sampling is done at fDTS + 0 + + + FCK_INT_N2 + fSAMPLING=fCK_INT, N=2 + 1 + + + FCK_INT_N4 + fSAMPLING=fCK_INT, N=4 + 2 + + + FCK_INT_N8 + fSAMPLING=fCK_INT, N=8 + 3 + + + FDTS_Div2_N6 + fSAMPLING=fDTS/2, N=6 + 4 + + + FDTS_Div2_N8 + fSAMPLING=fDTS/2, N=8 + 5 + + + FDTS_Div4_N6 + fSAMPLING=fDTS/4, N=6 + 6 + + + FDTS_Div4_N8 + fSAMPLING=fDTS/4, N=8 + 7 + + + FDTS_Div8_N6 + fSAMPLING=fDTS/8, N=6 + 8 + + + FDTS_Div8_N8 + fSAMPLING=fDTS/8, N=8 + 9 + + + FDTS_Div16_N5 + fSAMPLING=fDTS/16, N=5 + 10 + + + FDTS_Div16_N6 + fSAMPLING=fDTS/16, N=6 + 11 + + + FDTS_Div16_N8 + fSAMPLING=fDTS/16, N=8 + 12 + + + FDTS_Div32_N5 + fSAMPLING=fDTS/32, N=5 + 13 + + + FDTS_Div32_N6 + fSAMPLING=fDTS/32, N=6 + 14 + + + FDTS_Div32_N8 + fSAMPLING=fDTS/32, N=8 + 15 + + + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + CC1S + read-write + + TI1 + CC1 channel is configured as input, IC1 is mapped on TI1 + 1 + + + TI2 + CC1 channel is configured as input, IC1 is mapped on TI2 + 2 + + + TRC + CC1 channel is configured as input, IC1 is mapped on TRC + 3 + + + + + + + CCMR2_Output + CCMR2_Output + capture/compare mode register 2 (output + mode) + 0x1C + 0x20 + read-write + 0x00000000 + + + OC4CE + O24CE + 15 + 1 + + + OC4M + OC4M + 12 + 3 + + + + OC4PE + OC4PE + 11 + 1 + + OC4PE + read-write + + Disabled + Preload register on CCR4 disabled. New values written to CCR4 are taken into account immediately + 0 + + + Enabled + Preload register on CCR4 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC4FE + OC4FE + 10 + 1 + + + CC4S + CC4S + 8 + 2 + + CC4S + read-write + + Output + CC4 channel is configured as output + 0 + + + + + OC3CE + OC3CE + 7 + 1 + + + OC3M + OC3M + 4 + 3 + + OC3M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC3PE + OC3PE + 3 + 1 + + OC3PE + read-write + + Disabled + Preload register on CCR3 disabled. New values written to CCR3 are taken into account immediately + 0 + + + Enabled + Preload register on CCR3 enabled. Preload value is loaded into active register on each update event + 1 + + + + + OC3FE + OC3FE + 2 + 1 + + + CC3S + CC3S + 0 + 2 + + CC3S + read-write + + Output + CC3 channel is configured as output + 0 + + + + + + + CCMR2_Input + CCMR2_Input + capture/compare mode register 2 (input + mode) + CCMR2_Output + 0x1C + 0x20 + read-write + 0x00000000 + + + IC4F + Input capture 4 filter + 12 + 4 + + + 0 + 15 + + + + + IC4PSC + Input capture 4 prescaler + 10 + 2 + + + 0 + 3 + + + + + CC4S + Capture/Compare 4 + selection + 8 + 2 + + CC4S + read-write + + TI4 + CC4 channel is configured as input, IC4 is mapped on TI4 + 1 + + + TI3 + CC4 channel is configured as input, IC4 is mapped on TI3 + 2 + + + TRC + CC4 channel is configured as input, IC4 is mapped on TRC + 3 + + + + + IC3F + Input capture 3 filter + 4 + 4 + + + 0 + 15 + + + + + IC3PSC + Input capture 3 prescaler + 2 + 2 + + + 0 + 3 + + + + + CC3S + Capture/compare 3 + selection + 0 + 2 + + CC3S + read-write + + TI3 + CC3 channel is configured as input, IC3 is mapped on TI3 + 1 + + + TI4 + CC3 channel is configured as input, IC3 is mapped on TI4 + 2 + + + TRC + CC3 channel is configured as input, IC3 is mapped on TRC + 3 + + + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC4NP + Capture/Compare 4 output + Polarity + 15 + 1 + + + CC4P + Capture/Compare 3 output + Polarity + 13 + 1 + + + CC4E + Capture/Compare 4 output + enable + 12 + 1 + + + CC3NP + Capture/Compare 3 output + Polarity + 11 + 1 + + + CC3P + Capture/Compare 3 output + Polarity + 9 + 1 + + + CC3E + Capture/Compare 3 output + enable + 8 + 1 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + Counter value + 0 + 32 + + + 0 + 4294967295 + + + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 32 + + + 0 + 4294967295 + + + + + + + 4 + 0x4 + 1-4 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 32 + + + 0 + 4294967295 + + + + + + + DCR + DCR + DMA control register + 0x48 + 0x20 + read-write + 0x00000000 + + + DBL + DMA burst length + 8 + 5 + + + 0 + 18 + + + + + DBA + DMA base address + 0 + 5 + + + 0 + 31 + + + + + + + DMAR + DMAR + DMA address for full transfer + 0x4C + 0x20 + read-write + 0x00000000 + + + DMAB + DMA register for burst + accesses + 0 + 16 + + + + + OR + OR + TIM5 option register + 0x50 + 0x20 + read-write + 0x00000000 + + + IT4_RMP + Timer Input 4 remap + 6 + 2 + + + + + + + TIM9 + General purpose timers + TIM + 0x40014000 + + 0x0 + 0x400 + registers + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + CKD + Clock division + 8 + 2 + + CKD + read-write + + Div1 + t_DTS = t_CK_INT + 0 + + + Div2 + t_DTS = 2 × t_CK_INT + 1 + + + Div4 + t_DTS = 4 × t_CK_INT + 2 + + + + + ARPE + Auto-reload preload enable + 7 + 1 + + ARPE + read-write + + Disabled + TIMx_APRR register is not buffered + 0 + + + Enabled + TIMx_APRR register is buffered + 1 + + + + + OPM + One-pulse mode + 3 + 1 + + OPM + read-write + + Disabled + Counter is not stopped at update event + 0 + + + Enabled + Counter stops counting at the next update event (clearing the CEN bit) + 1 + + + + + URS + Update request source + 2 + 1 + + URS + read-write + + AnyEvent + Any of counter overflow/underflow, setting UG, or update through slave mode, generates an update interrupt or DMA request + 0 + + + CounterOnly + Only counter overflow/underflow generates an update interrupt or DMA request + 1 + + + + + UDIS + Update disable + 1 + 1 + + UDIS + read-write + + Enabled + Update event enabled + 0 + + + Disabled + Update event disabled + 1 + + + + + CEN + Counter enable + 0 + 1 + + CEN + read-write + + Disabled + Counter disabled + 0 + + + Enabled + Counter enabled + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + MMS + Master mode selection + 4 + 3 + + + + + SMCR + SMCR + slave mode control register + 0x8 + 0x20 + read-write + 0x00000000 + + + MSM + Master/Slave mode + 7 + 1 + + + TS + Trigger selection + 4 + 3 + + + SMS + Slave mode selection + 0 + 3 + + + + + DIER + DIER + DMA/Interrupt enable register + 0xC + 0x20 + read-write + 0x00000000 + + + TIE + Trigger interrupt enable + 6 + 1 + + + CC2IE + Capture/Compare 2 interrupt + enable + 2 + 1 + + + CC1IE + Capture/Compare 1 interrupt + enable + 1 + 1 + + + UIE + Update interrupt enable + 0 + 1 + + UIE + read-write + + Disabled + Update interrupt disabled + 0 + + + Enabled + Update interrupt enabled + 1 + + + + + + + SR + SR + status register + 0x10 + 0x20 + read-write + 0x00000000 + + + CC2OF + Capture/compare 2 overcapture + flag + 10 + 1 + + + CC1OF + Capture/Compare 1 overcapture + flag + 9 + 1 + + + TIF + Trigger interrupt flag + 6 + 1 + + + CC2IF + Capture/Compare 2 interrupt + flag + 2 + 1 + + + CC1IF + Capture/compare 1 interrupt + flag + 1 + 1 + + + UIF + Update interrupt flag + 0 + 1 + zeroToClear + + UIFR + read + + NoUpdateOccurred + No update occurred + 0 + + + UpdatePending + Update interrupt pending + 1 + + + + UIFW + write + + Clear + Clear flag + 0 + + + + + + + EGR + EGR + event generation register + 0x14 + 0x20 + write-only + 0x00000000 + + + TG + Trigger generation + 6 + 1 + + + CC2G + Capture/compare 2 + generation + 2 + 1 + + + CC1G + Capture/compare 1 + generation + 1 + 1 + + + UG + Update generation + 0 + 1 + + UG + write + + Update + Re-initializes the timer counter and generates an update of the registers. + 1 + + + + + + + CCMR1_Output + CCMR1_Output + capture/compare mode register 1 (output + mode) + 0x18 + 0x20 + read-write + 0x00000000 + + + OC2M + Output Compare 2 mode + 12 + 3 + + + + OC2PE + Output Compare 2 preload + enable + 11 + 1 + + + OC2FE + Output Compare 2 fast + enable + 10 + 1 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + + OC1M + Output Compare 1 mode + 4 + 3 + + OC1M + read-write + + Frozen + The comparison between the output compare register TIMx_CCRy and the counter TIMx_CNT has no effect on the outputs + 0 + + + ActiveOnMatch + Set channel to active level on match. OCyREF signal is forced high when the counter matches the capture/compare register + 1 + + + InactiveOnMatch + Set channel to inactive level on match. OCyREF signal is forced low when the counter matches the capture/compare register + 2 + + + Toggle + OCyREF toggles when TIMx_CNT=TIMx_CCRy + 3 + + + ForceInactive + OCyREF is forced low + 4 + + + ForceActive + OCyREF is forced high + 5 + + + PwmMode1 + In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRy else inactive. In downcounting, channel is inactive as long as TIMx_CNT>TIMx_CCRy else active + 6 + + + PwmMode2 + Inversely to PwmMode1 + 7 + + + + + OC1PE + Output Compare 1 preload + enable + 3 + 1 + + + OC1FE + Output Compare 1 fast + enable + 2 + 1 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCMR1_Input + CCMR1_Input + capture/compare mode register 1 (input + mode) + CCMR1_Output + 0x18 + 0x20 + read-write + 0x00000000 + + + IC2F + Input capture 2 filter + 12 + 3 + + + IC2PSC + Input capture 2 prescaler + 10 + 2 + + + CC2S + Capture/Compare 2 + selection + 8 + 2 + + + IC1F + Input capture 1 filter + 4 + 3 + + + IC1PSC + Input capture 1 prescaler + 2 + 2 + + + CC1S + Capture/Compare 1 + selection + 0 + 2 + + + + + CCER + CCER + capture/compare enable + register + 0x20 + 0x20 + read-write + 0x00000000 + + + CC2NP + Capture/Compare 2 output + Polarity + 7 + 1 + + + CC2P + Capture/Compare 2 output + Polarity + 5 + 1 + + + CC2E + Capture/Compare 2 output + enable + 4 + 1 + + + CC1NP + Capture/Compare 1 output + Polarity + 3 + 1 + + + CC1P + Capture/Compare 1 output + Polarity + 1 + 1 + + + CC1E + Capture/Compare 1 output + enable + 0 + 1 + + + + + CNT + CNT + counter + 0x24 + 0x20 + read-write + 0x00000000 + + + CNT + counter value + 0 + 16 + + + + + PSC + PSC + prescaler + 0x28 + 0x20 + read-write + 0x00000000 + + + PSC + Prescaler value + 0 + 16 + + + 0 + 65535 + + + + + + + ARR + ARR + auto-reload register + 0x2C + 0x20 + read-write + 0x00000000 + + + ARR + Auto-reload value + 0 + 16 + + + + + 2 + 0x4 + 1-2 + CCR%s + CCR1 + capture/compare register + 0x34 + 0x20 + read-write + 0x00000000 + + + CCR + Capture/Compare value + 0 + 16 + + + + + + + USART1 + Universal synchronous asynchronous receiver + transmitter + USART + 0x40011000 + + 0x0 + 0x400 + registers + + + OTG_FS_WKUP + USB On-The-Go FS Wakeup through EXTI line + interrupt + 42 + + + OTG_FS + USB On The Go FS global + interrupt + 67 + + + USART1 + USART1 global interrupt + 37 + + + USART2 + USART2 global interrupt + 38 + + + USART6 + USART6 global interrupt + 71 + + + + SR + SR + Status register + 0x0 + 0x20 + 0x00C00000 + + + CTS + CTS flag + 9 + 1 + read-write + + + LBD + LIN break detection flag + 8 + 1 + read-write + + + TXE + Transmit data register + empty + 7 + 1 + read-only + + + TC + Transmission complete + 6 + 1 + read-write + + + RXNE + Read data register not + empty + 5 + 1 + read-write + + + IDLE + IDLE line detected + 4 + 1 + read-only + + + ORE + Overrun error + 3 + 1 + read-only + + + NF + Noise detected flag + 2 + 1 + read-only + + + FE + Framing error + 1 + 1 + read-only + + + PE + Parity error + 0 + 1 + read-only + + + + + DR + DR + Data register + 0x4 + 0x20 + read-write + 0x00000000 + + + DR + Data value + 0 + 9 + + + 0 + 511 + + + + + + + BRR + BRR + Baud rate register + 0x8 + 0x20 + read-write + 0x00000000 + + + DIV_Mantissa + mantissa of USARTDIV + 4 + 12 + + + 0 + 4095 + + + + + DIV_Fraction + fraction of USARTDIV + 0 + 4 + + + 0 + 15 + + + + + + + CR1 + CR1 + Control register 1 + 0xC + 0x20 + read-write + 0x00000000 + + + OVER8 + Oversampling mode + 15 + 1 + + OVER8 + read-write + + Oversample16 + Oversampling by 16 + 0 + + + Oversample8 + Oversampling by 8 + 1 + + + + + UE + USART enable + 13 + 1 + + UE + read-write + + Disabled + USART prescaler and outputs disabled + 0 + + + Enabled + USART enabled + 1 + + + + + M + Word length + 12 + 1 + + M + read-write + + M8 + 8 data bits + 0 + + + M9 + 9 data bits + 1 + + + + + WAKE + Wakeup method + 11 + 1 + + WAKE + read-write + + IdleLine + USART wakeup on idle line + 0 + + + AddressMark + USART wakeup on address mark + 1 + + + + + PCE + Parity control enable + 10 + 1 + + PCE + read-write + + Disabled + Parity control disabled + 0 + + + Enabled + Parity control enabled + 1 + + + + + PS + Parity selection + 9 + 1 + + PS + read-write + + Even + Even parity + 0 + + + Odd + Odd parity + 1 + + + + + PEIE + PE interrupt enable + 8 + 1 + + PEIE + read-write + + Disabled + PE interrupt disabled + 0 + + + Enabled + PE interrupt enabled + 1 + + + + + TXEIE + TXE interrupt enable + 7 + 1 + + TXEIE + read-write + + Disabled + TXE interrupt disabled + 0 + + + Enabled + TXE interrupt enabled + 1 + + + + + TCIE + Transmission complete interrupt + enable + 6 + 1 + + TCIE + read-write + + Disabled + TC interrupt disabled + 0 + + + Enabled + TC interrupt enabled + 1 + + + + + RXNEIE + RXNE interrupt enable + 5 + 1 + + RXNEIE + read-write + + Disabled + RXNE interrupt disabled + 0 + + + Enabled + RXNE interrupt enabled + 1 + + + + + IDLEIE + IDLE interrupt enable + 4 + 1 + + IDLEIE + read-write + + Disabled + IDLE interrupt disabled + 0 + + + Enabled + IDLE interrupt enabled + 1 + + + + + TE + Transmitter enable + 3 + 1 + + TE + read-write + + Disabled + Transmitter disabled + 0 + + + Enabled + Transmitter enabled + 1 + + + + + RE + Receiver enable + 2 + 1 + + RE + read-write + + Disabled + Receiver disabled + 0 + + + Enabled + Receiver enabled + 1 + + + + + RWU + Receiver wakeup + 1 + 1 + + RWU + read-write + + Active + Receiver in active mode + 0 + + + Mute + Receiver in mute mode + 1 + + + + + SBK + Send break + 0 + 1 + + SBK + read-write + + NoBreak + No break character is transmitted + 0 + + + Break + Break character transmitted + 1 + + + + + + + CR2 + CR2 + Control register 2 + 0x10 + 0x20 + read-write + 0x00000000 + + + LINEN + LIN mode enable + 14 + 1 + + LINEN + read-write + + Disabled + LIN mode disabled + 0 + + + Enabled + LIN mode enabled + 1 + + + + + STOP + STOP bits + 12 + 2 + + STOP + read-write + + Stop1 + 1 stop bit + 0 + + + Stop0p5 + 0.5 stop bits + 1 + + + Stop2 + 2 stop bits + 2 + + + Stop1p5 + 1.5 stop bits + 3 + + + + + CLKEN + Clock enable + 11 + 1 + + CLKEN + read-write + + Disabled + CK pin disabled + 0 + + + Enabled + CK pin enabled + 1 + + + + + CPOL + Clock polarity + 10 + 1 + + CPOL + read-write + + Low + Steady low value on CK pin outside transmission window + 0 + + + High + Steady high value on CK pin outside transmission window + 1 + + + + + CPHA + Clock phase + 9 + 1 + + CPHA + read-write + + First + The first clock transition is the first data capture edge + 0 + + + Second + The second clock transition is the first data capture edge + 1 + + + + + LBCL + Last bit clock pulse + 8 + 1 + + + LBDIE + LIN break detection interrupt + enable + 6 + 1 + + LBDIE + read-write + + Disabled + LIN break detection interrupt disabled + 0 + + + Enabled + LIN break detection interrupt enabled + 1 + + + + + LBDL + lin break detection length + 5 + 1 + + LBDL + read-write + + LBDL10 + 10-bit break detection + 0 + + + LBDL11 + 11-bit break detection + 1 + + + + + ADD + Address of the USART node + 0 + 4 + + + 0 + 15 + + + + + + + CR3 + CR3 + Control register 3 + 0x14 + 0x20 + read-write + 0x00000000 + + + ONEBIT + One sample bit method + enable + 11 + 1 + + ONEBIT + read-write + + Sample3 + Three sample bit method + 0 + + + Sample1 + One sample bit method + 1 + + + + + CTSIE + CTS interrupt enable + 10 + 1 + + CTSIE + read-write + + Disabled + CTS interrupt disabled + 0 + + + Enabled + CTS interrupt enabled + 1 + + + + + CTSE + CTS enable + 9 + 1 + + CTSE + read-write + + Disabled + CTS hardware flow control disabled + 0 + + + Enabled + CTS hardware flow control enabled + 1 + + + + + RTSE + RTS enable + 8 + 1 + + RTSE + read-write + + Disabled + RTS hardware flow control disabled + 0 + + + Enabled + RTS hardware flow control enabled + 1 + + + + + DMAT + DMA enable transmitter + 7 + 1 + + DMAT + read-write + + Disabled + DMA mode is disabled for transmission + 0 + + + Enabled + DMA mode is enabled for transmission + 1 + + + + + DMAR + DMA enable receiver + 6 + 1 + + DMAR + read-write + + Disabled + DMA mode is disabled for reception + 0 + + + Enabled + DMA mode is enabled for reception + 1 + + + + + SCEN + Smartcard mode enable + 5 + 1 + + SCEN + read-write + + Disabled + Smartcard mode disabled + 0 + + + Enabled + Smartcard mode enabled + 1 + + + + + NACK + Smartcard NACK enable + 4 + 1 + + NACK + read-write + + Disabled + NACK transmission in case of parity error is disabled + 0 + + + Enabled + NACK transmission during parity error is enabled + 1 + + + + + HDSEL + Half-duplex selection + 3 + 1 + + HDSEL + read-write + + FullDuplex + Half duplex mode is not selected + 0 + + + HalfDuplex + Half duplex mode is selected + 1 + + + + + IRLP + IrDA low-power + 2 + 1 + + IRLP + read-write + + Normal + Normal mode + 0 + + + LowPower + Low-power mode + 1 + + + + + IREN + IrDA mode enable + 1 + 1 + + IREN + read-write + + Disabled + IrDA disabled + 0 + + + Enabled + IrDA enabled + 1 + + + + + EIE + Error interrupt enable + 0 + 1 + + EIE + read-write + + Disabled + Error interrupt disabled + 0 + + + Enabled + Error interrupt enabled + 1 + + + + + + + GTPR + GTPR + Guard time and prescaler + register + 0x18 + 0x20 + read-write + 0x00000000 + + + GT + Guard time value + 8 + 8 + + + PSC + Prescaler value + 0 + 8 + + + + + + + USART2 + 0x40004400 + + + USART6 + 0x40011400 + + + WWDG + Window watchdog + WWDG + 0x40002C00 + + 0x0 + 0x400 + registers + + + PVD + PVD through EXTI line detection + interrupt + 1 + + + + CR + CR + Control register + 0x0 + 0x20 + read-write + 0x0000007F + + + WDGA + Activation bit + 7 + 1 + + WDGA + read-write + + Disabled + Watchdog disabled + 0 + + + Enabled + Watchdog enabled + 1 + + + + + T + 7-bit counter (MSB to LSB) + 0 + 7 + + + 0 + 127 + + + + + + + CFR + CFR + Configuration register + 0x4 + 0x20 + read-write + 0x0000007F + + + EWI + Early wakeup interrupt + 9 + 1 + + EWIW + write + + Enable + interrupt occurs whenever the counter reaches the value 0x40 + 1 + + + + + W + 7-bit window value + 0 + 7 + + + 0 + 127 + + + + + WDGTB + Timer base + 7 + 2 + + WDGTB + read-write + + Div1 + Counter clock (PCLK1 div 4096) div 1 + 0 + + + Div2 + Counter clock (PCLK1 div 4096) div 2 + 1 + + + Div4 + Counter clock (PCLK1 div 4096) div 4 + 2 + + + Div8 + Counter clock (PCLK1 div 4096) div 8 + 3 + + + + + + + SR + SR + Status register + 0x8 + 0x20 + read-write + 0x00000000 + + + EWIF + Early wakeup interrupt + flag + 0 + 1 + zeroToClear + + EWIFR + read + + Finished + The EWI Interrupt Service Routine has been serviced + 0 + + + Pending + The EWI Interrupt Service Routine has been triggered + 1 + + + + EWIFW + write + + Finished + The EWI Interrupt Service Routine has been serviced + 0 + + + + + + + + + DMA2 + DMA controller + DMA + 0x40026400 + + 0x0 + 0x400 + registers + + + RCC + RCC global interrupt + 5 + + + DMA1_STREAM0 + DMA1_STREAM0 global interrupt + 11 + + + DMA1_STREAM1 + DMA1_STREAM1 global interrupt + 12 + + + DMA1_STREAM2 + DMA1_STREAM2 global interrupt + 13 + + + DMA1_STREAM3 + DMA1_STREAM3 global interrupt + 14 + + + DMA1_STREAM4 + DMA1_STREAM4 global interrupt + 15 + + + DMA1_STREAM5 + DMA1_STREAM5 global interrupt + 16 + + + DMA1_STREAM6 + DMA1_STREAM6 global interrupt + 17 + + + DMA1_STREAM7 + DMA1_STREAM7 global interrupt + 47 + + + DMA2_STREAM0 + DMA2_STREAM0 global interrupt + 56 + + + DMA2_STREAM1 + DMA2_STREAM1 global interrupt + 57 + + + DMA2_STREAM2 + DMA2_STREAM2 global interrupt + 58 + + + DMA2_STREAM3 + DMA2_STREAM3 global interrupt + 59 + + + DMA2_STREAM4 + DMA2_STREAM4 global interrupt + 60 + + + DMA2_STREAM5 + DMA2_STREAM5 global interrupt + 68 + + + DMA2_STREAM6 + DMA2_STREAM6 global interrupt + 69 + + + DMA2_STREAM7 + DMA2_STREAM7 global interrupt + 70 + + + + LISR + LISR + low interrupt status register + 0x0 + 0x20 + read-only + 0x00000000 + + + TCIF3 + Stream x transfer complete interrupt + flag (x = 3..0) + 27 + 1 + + + + HTIF3 + Stream x half transfer interrupt flag + (x=3..0) + 26 + 1 + + + + TEIF3 + Stream x transfer error interrupt flag + (x=3..0) + 25 + 1 + + + + DMEIF3 + Stream x direct mode error interrupt + flag (x=3..0) + 24 + 1 + + + + FEIF3 + Stream x FIFO error interrupt flag + (x=3..0) + 22 + 1 + + + + TCIF2 + Stream x transfer complete interrupt + flag (x = 3..0) + 21 + 1 + + + + HTIF2 + Stream x half transfer interrupt flag + (x=3..0) + 20 + 1 + + + + TEIF2 + Stream x transfer error interrupt flag + (x=3..0) + 19 + 1 + + + + DMEIF2 + Stream x direct mode error interrupt + flag (x=3..0) + 18 + 1 + + + + FEIF2 + Stream x FIFO error interrupt flag + (x=3..0) + 16 + 1 + + + + TCIF1 + Stream x transfer complete interrupt + flag (x = 3..0) + 11 + 1 + + + + HTIF1 + Stream x half transfer interrupt flag + (x=3..0) + 10 + 1 + + + + TEIF1 + Stream x transfer error interrupt flag + (x=3..0) + 9 + 1 + + + + DMEIF1 + Stream x direct mode error interrupt + flag (x=3..0) + 8 + 1 + + + + FEIF1 + Stream x FIFO error interrupt flag + (x=3..0) + 6 + 1 + + + + TCIF0 + Stream x transfer complete interrupt + flag (x = 3..0) + 5 + 1 + + TCIF0 + read + + NotComplete + No transfer complete event on stream x + 0 + + + Complete + A transfer complete event occurred on stream x + 1 + + + + + HTIF0 + Stream x half transfer interrupt flag + (x=3..0) + 4 + 1 + + HTIF0 + read + + NotHalf + No half transfer event on stream x + 0 + + + Half + A half transfer event occurred on stream x + 1 + + + + + TEIF0 + Stream x transfer error interrupt flag + (x=3..0) + 3 + 1 + + TEIF0 + read + + NoError + No transfer error on stream x + 0 + + + Error + A transfer error occurred on stream x + 1 + + + + + DMEIF0 + Stream x direct mode error interrupt + flag (x=3..0) + 2 + 1 + + DMEIF0 + read + + NoError + No Direct Mode error on stream x + 0 + + + Error + A Direct Mode error occurred on stream x + 1 + + + + + FEIF0 + Stream x FIFO error interrupt flag + (x=3..0) + 0 + 1 + + FEIF0 + read + + NoError + No FIFO error event on stream x + 0 + + + Error + A FIFO error event occurred on stream x + 1 + + + + + + + HISR + HISR + high interrupt status register + 0x4 + 0x20 + read-only + 0x00000000 + + + TCIF7 + Stream x transfer complete interrupt + flag (x=7..4) + 27 + 1 + + + + HTIF7 + Stream x half transfer interrupt flag + (x=7..4) + 26 + 1 + + + + TEIF7 + Stream x transfer error interrupt flag + (x=7..4) + 25 + 1 + + + + DMEIF7 + Stream x direct mode error interrupt + flag (x=7..4) + 24 + 1 + + + + FEIF7 + Stream x FIFO error interrupt flag + (x=7..4) + 22 + 1 + + + + TCIF6 + Stream x transfer complete interrupt + flag (x=7..4) + 21 + 1 + + + + HTIF6 + Stream x half transfer interrupt flag + (x=7..4) + 20 + 1 + + + + TEIF6 + Stream x transfer error interrupt flag + (x=7..4) + 19 + 1 + + + + DMEIF6 + Stream x direct mode error interrupt + flag (x=7..4) + 18 + 1 + + + + FEIF6 + Stream x FIFO error interrupt flag + (x=7..4) + 16 + 1 + + + + TCIF5 + Stream x transfer complete interrupt + flag (x=7..4) + 11 + 1 + + + + HTIF5 + Stream x half transfer interrupt flag + (x=7..4) + 10 + 1 + + + + TEIF5 + Stream x transfer error interrupt flag + (x=7..4) + 9 + 1 + + + + DMEIF5 + Stream x direct mode error interrupt + flag (x=7..4) + 8 + 1 + + + + FEIF5 + Stream x FIFO error interrupt flag + (x=7..4) + 6 + 1 + + + + TCIF4 + Stream x transfer complete interrupt + flag (x=7..4) + 5 + 1 + + TCIF4 + read + + NotComplete + No transfer complete event on stream x + 0 + + + Complete + A transfer complete event occurred on stream x + 1 + + + + + HTIF4 + Stream x half transfer interrupt flag + (x=7..4) + 4 + 1 + + HTIF4 + read + + NotHalf + No half transfer event on stream x + 0 + + + Half + A half transfer event occurred on stream x + 1 + + + + + TEIF4 + Stream x transfer error interrupt flag + (x=7..4) + 3 + 1 + + TEIF4 + read + + NoError + No transfer error on stream x + 0 + + + Error + A transfer error occurred on stream x + 1 + + + + + DMEIF4 + Stream x direct mode error interrupt + flag (x=7..4) + 2 + 1 + + DMEIF4 + read + + NoError + No Direct Mode error on stream x + 0 + + + Error + A Direct Mode error occurred on stream x + 1 + + + + + FEIF4 + Stream x FIFO error interrupt flag + (x=7..4) + 0 + 1 + + FEIF4 + read + + NoError + No FIFO error event on stream x + 0 + + + Error + A FIFO error event occurred on stream x + 1 + + + + + + + LIFCR + LIFCR + low interrupt flag clear + register + 0x8 + 0x20 + write-only + 0x00000000 + + + CTCIF3 + Stream x clear transfer complete + interrupt flag (x = 3..0) + 27 + 1 + + + + CHTIF3 + Stream x clear half transfer interrupt + flag (x = 3..0) + 26 + 1 + + + + CTEIF3 + Stream x clear transfer error interrupt + flag (x = 3..0) + 25 + 1 + + + + CDMEIF3 + Stream x clear direct mode error + interrupt flag (x = 3..0) + 24 + 1 + + + + CFEIF3 + Stream x clear FIFO error interrupt flag + (x = 3..0) + 22 + 1 + + + + CTCIF2 + Stream x clear transfer complete + interrupt flag (x = 3..0) + 21 + 1 + + + + CHTIF2 + Stream x clear half transfer interrupt + flag (x = 3..0) + 20 + 1 + + + + CTEIF2 + Stream x clear transfer error interrupt + flag (x = 3..0) + 19 + 1 + + + + CDMEIF2 + Stream x clear direct mode error + interrupt flag (x = 3..0) + 18 + 1 + + + + CFEIF2 + Stream x clear FIFO error interrupt flag + (x = 3..0) + 16 + 1 + + + + CTCIF1 + Stream x clear transfer complete + interrupt flag (x = 3..0) + 11 + 1 + + + + CHTIF1 + Stream x clear half transfer interrupt + flag (x = 3..0) + 10 + 1 + + + + CTEIF1 + Stream x clear transfer error interrupt + flag (x = 3..0) + 9 + 1 + + + + CDMEIF1 + Stream x clear direct mode error + interrupt flag (x = 3..0) + 8 + 1 + + + + CFEIF1 + Stream x clear FIFO error interrupt flag + (x = 3..0) + 6 + 1 + + + + CTCIF0 + Stream x clear transfer complete + interrupt flag (x = 3..0) + 5 + 1 + + CTCIF0 + write + + Clear + Clear the corresponding TCIFx flag + 1 + + + + + CHTIF0 + Stream x clear half transfer interrupt + flag (x = 3..0) + 4 + 1 + + CHTIF0 + write + + Clear + Clear the corresponding HTIFx flag + 1 + + + + + CTEIF0 + Stream x clear transfer error interrupt + flag (x = 3..0) + 3 + 1 + + CTEIF0 + write + + Clear + Clear the corresponding TEIFx flag + 1 + + + + + CDMEIF0 + Stream x clear direct mode error + interrupt flag (x = 3..0) + 2 + 1 + + CDMEIF0 + write + + Clear + Clear the corresponding DMEIFx flag + 1 + + + + + CFEIF0 + Stream x clear FIFO error interrupt flag + (x = 3..0) + 0 + 1 + + CFEIF0 + write + + Clear + Clear the corresponding CFEIFx flag + 1 + + + + + + + HIFCR + HIFCR + high interrupt flag clear + register + 0xC + 0x20 + write-only + 0x00000000 + + + CTCIF7 + Stream x clear transfer complete + interrupt flag (x = 7..4) + 27 + 1 + + + + CHTIF7 + Stream x clear half transfer interrupt + flag (x = 7..4) + 26 + 1 + + + + CTEIF7 + Stream x clear transfer error interrupt + flag (x = 7..4) + 25 + 1 + + + + CDMEIF7 + Stream x clear direct mode error + interrupt flag (x = 7..4) + 24 + 1 + + + + CFEIF7 + Stream x clear FIFO error interrupt flag + (x = 7..4) + 22 + 1 + + + + CTCIF6 + Stream x clear transfer complete + interrupt flag (x = 7..4) + 21 + 1 + + + + CHTIF6 + Stream x clear half transfer interrupt + flag (x = 7..4) + 20 + 1 + + + + CTEIF6 + Stream x clear transfer error interrupt + flag (x = 7..4) + 19 + 1 + + + + CDMEIF6 + Stream x clear direct mode error + interrupt flag (x = 7..4) + 18 + 1 + + + + CFEIF6 + Stream x clear FIFO error interrupt flag + (x = 7..4) + 16 + 1 + + + + CTCIF5 + Stream x clear transfer complete + interrupt flag (x = 7..4) + 11 + 1 + + + + CHTIF5 + Stream x clear half transfer interrupt + flag (x = 7..4) + 10 + 1 + + + + CTEIF5 + Stream x clear transfer error interrupt + flag (x = 7..4) + 9 + 1 + + + + CDMEIF5 + Stream x clear direct mode error + interrupt flag (x = 7..4) + 8 + 1 + + + + CFEIF5 + Stream x clear FIFO error interrupt flag + (x = 7..4) + 6 + 1 + + + + CTCIF4 + Stream x clear transfer complete + interrupt flag (x = 7..4) + 5 + 1 + + CTCIF4 + write + + Clear + Clear the corresponding TCIFx flag + 1 + + + + + CHTIF4 + Stream x clear half transfer interrupt + flag (x = 7..4) + 4 + 1 + + CHTIF4 + write + + Clear + Clear the corresponding HTIFx flag + 1 + + + + + CTEIF4 + Stream x clear transfer error interrupt + flag (x = 7..4) + 3 + 1 + + CTEIF4 + write + + Clear + Clear the corresponding TEIFx flag + 1 + + + + + CDMEIF4 + Stream x clear direct mode error + interrupt flag (x = 7..4) + 2 + 1 + + CDMEIF4 + write + + Clear + Clear the corresponding DMEIFx flag + 1 + + + + + CFEIF4 + Stream x clear FIFO error interrupt flag + (x = 7..4) + 0 + 1 + + CFEIF4 + write + + Clear + Clear the corresponding CFEIFx flag + 1 + + + + + + + 8 + 0x18 + 0-7 + ST%s + Stream cluster: S?CR, S?NDTR, S?M0AR, S?M1AR and S?FCR registers + 0x10 + + CR + S0CR + stream x configuration + register + 0x0 + 0x20 + read-write + 0x00000000 + + + CHSEL + Channel selection + 25 + 3 + + + 0 + 7 + + + + + MBURST + Memory burst transfer + configuration + 23 + 2 + + + + PBURST + Peripheral burst transfer + configuration + 21 + 2 + + PBURST + read-write + + Single + Single transfer + 0 + + + INCR4 + Incremental burst of 4 beats + 1 + + + INCR8 + Incremental burst of 8 beats + 2 + + + INCR16 + Incremental burst of 16 beats + 3 + + + + + CT + Current target (only in double buffer + mode) + 19 + 1 + + CT + read-write + + Memory0 + The current target memory is Memory 0 + 0 + + + Memory1 + The current target memory is Memory 1 + 1 + + + + + DBM + Double buffer mode + 18 + 1 + + DBM + read-write + + Disabled + No buffer switching at the end of transfer + 0 + + + Enabled + Memory target switched at the end of the DMA transfer + 1 + + + + + PL + Priority level + 16 + 2 + + PL + read-write + + Low + Low + 0 + + + Medium + Medium + 1 + + + High + High + 2 + + + VeryHigh + Very high + 3 + + + + + PINCOS + Peripheral increment offset + size + 15 + 1 + + PINCOS + read-write + + PSIZE + The offset size for the peripheral address calculation is linked to the PSIZE + 0 + + + Fixed4 + The offset size for the peripheral address calculation is fixed to 4 (32-bit alignment) + 1 + + + + + MSIZE + Memory data size + 13 + 2 + + + + PSIZE + Peripheral data size + 11 + 2 + + PSIZE + read-write + + Bits8 + Byte (8-bit) + 0 + + + Bits16 + Half-word (16-bit) + 1 + + + Bits32 + Word (32-bit) + 2 + + + + + MINC + Memory increment mode + 10 + 1 + + + + PINC + Peripheral increment mode + 9 + 1 + + PINC + read-write + + Fixed + Address pointer is fixed + 0 + + + Incremented + Address pointer is incremented after each data transfer + 1 + + + + + CIRC + Circular mode + 8 + 1 + + CIRC + read-write + + Disabled + Circular mode disabled + 0 + + + Enabled + Circular mode enabled + 1 + + + + + DIR + Data transfer direction + 6 + 2 + + DIR + read-write + + PeripheralToMemory + Peripheral-to-memory + 0 + + + MemoryToPeripheral + Memory-to-peripheral + 1 + + + MemoryToMemory + Memory-to-memory + 2 + + + + + PFCTRL + Peripheral flow controller + 5 + 1 + + PFCTRL + read-write + + DMA + The DMA is the flow controller + 0 + + + Peripheral + The peripheral is the flow controller + 1 + + + + + TCIE + Transfer complete interrupt + enable + 4 + 1 + + TCIE + read-write + + Disabled + TC interrupt disabled + 0 + + + Enabled + TC interrupt enabled + 1 + + + + + HTIE + Half transfer interrupt + enable + 3 + 1 + + HTIE + read-write + + Disabled + HT interrupt disabled + 0 + + + Enabled + HT interrupt enabled + 1 + + + + + TEIE + Transfer error interrupt + enable + 2 + 1 + + TEIE + read-write + + Disabled + TE interrupt disabled + 0 + + + Enabled + TE interrupt enabled + 1 + + + + + DMEIE + Direct mode error interrupt + enable + 1 + 1 + + DMEIE + read-write + + Disabled + DME interrupt disabled + 0 + + + Enabled + DME interrupt enabled + 1 + + + + + EN + Stream enable / flag stream ready when + read low + 0 + 1 + + EN + read-write + + Disabled + Stream disabled + 0 + + + Enabled + Stream enabled + 1 + + + + + + + NDTR + S0NDTR + stream x number of data + register + 0x4 + 0x20 + read-write + 0x00000000 + + + NDT + Number of data items to + transfer + 0 + 16 + + + 0 + 65535 + + + + + + + PAR + S0PAR + stream x peripheral address + register + 0x8 + 0x20 + read-write + 0x00000000 + + + PA + Peripheral address + 0 + 32 + + + + + M0AR + S0M0AR + stream x memory 0 address + register + 0xC + 0x20 + read-write + 0x00000000 + + + M0A + Memory 0 address + 0 + 32 + + + + + M1AR + S0M1AR + stream x memory 1 address + register + 0x10 + 0x20 + read-write + 0x00000000 + + + M1A + Memory 1 address (used in case of Double + buffer mode) + 0 + 32 + + + + + FCR + S0FCR + stream x FIFO control register + 0x14 + 0x20 + 0x00000021 + + + FEIE + FIFO error interrupt + enable + 7 + 1 + read-write + + FEIE + read-write + + Disabled + FE interrupt disabled + 0 + + + Enabled + FE interrupt enabled + 1 + + + + + FS + FIFO status + 3 + 3 + read-only + + FS + read + + Quarter1 + 0 < fifo_level < 1/4 + 0 + + + Quarter2 + 1/4 <= fifo_level < 1/2 + 1 + + + Quarter3 + 1/2 <= fifo_level < 3/4 + 2 + + + Quarter4 + 3/4 <= fifo_level < full + 3 + + + Empty + FIFO is empty + 4 + + + Full + FIFO is full + 5 + + + + + DMDIS + Direct mode disable + 2 + 1 + read-write + + DMDIS + read-write + + Enabled + Direct mode is enabled + 0 + + + Disabled + Direct mode is disabled + 1 + + + + + FTH + FIFO threshold selection + 0 + 2 + read-write + + FTH + read-write + + Quarter + 1/4 full FIFO + 0 + + + Half + 1/2 full FIFO + 1 + + + ThreeQuarters + 3/4 full FIFO + 2 + + + Full + Full FIFO + 3 + + + + + + + + + + DMA1 + 0x40026000 + + RTC_WKUP + RTC Wakeup interrupt through the EXTI + line + 3 + + + RTC_Alarm + RTC Alarms (A and B) through EXTI line + interrupt + 41 + + + + GPIOH + General-purpose I/Os + GPIO + 0x40021C00 + + 0x0 + 0x400 + registers + + + SDIO + SDIO global interrupt + 49 + + + + MODER + MODER + GPIO port mode register + 0x0 + 0x20 + read-write + 0x00000000 + + + MODER15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + MODER14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + MODER13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + MODER12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + MODER11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + MODER10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + MODER9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + MODER8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + MODER7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + MODER6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + MODER5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + MODER4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + MODER3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + MODER2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + MODER1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + MODER0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + MODER0 + read-write + + Input + Input mode (reset state) + 0 + + + Output + General purpose output mode + 1 + + + Alternate + Alternate function mode + 2 + + + Analog + Analog mode + 3 + + + + + + + OTYPER + OTYPER + GPIO port output type register + 0x4 + 0x20 + read-write + 0x00000000 + + + OT15 + Port x configuration bits (y = + 0..15) + 15 + 1 + + + + OT14 + Port x configuration bits (y = + 0..15) + 14 + 1 + + + + OT13 + Port x configuration bits (y = + 0..15) + 13 + 1 + + + + OT12 + Port x configuration bits (y = + 0..15) + 12 + 1 + + + + OT11 + Port x configuration bits (y = + 0..15) + 11 + 1 + + + + OT10 + Port x configuration bits (y = + 0..15) + 10 + 1 + + + + OT9 + Port x configuration bits (y = + 0..15) + 9 + 1 + + + + OT8 + Port x configuration bits (y = + 0..15) + 8 + 1 + + + + OT7 + Port x configuration bits (y = + 0..15) + 7 + 1 + + + + OT6 + Port x configuration bits (y = + 0..15) + 6 + 1 + + + + OT5 + Port x configuration bits (y = + 0..15) + 5 + 1 + + + + OT4 + Port x configuration bits (y = + 0..15) + 4 + 1 + + + + OT3 + Port x configuration bits (y = + 0..15) + 3 + 1 + + + + OT2 + Port x configuration bits (y = + 0..15) + 2 + 1 + + + + OT1 + Port x configuration bits (y = + 0..15) + 1 + 1 + + + + OT0 + Port x configuration bits (y = + 0..15) + 0 + 1 + + OT0 + read-write + + PushPull + Output push-pull (reset state) + 0 + + + OpenDrain + Output open-drain + 1 + + + + + + + OSPEEDR + OSPEEDR + GPIO port output speed + register + 0x8 + 0x20 + read-write + 0x00000000 + + + OSPEEDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + OSPEEDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + OSPEEDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + OSPEEDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + OSPEEDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + OSPEEDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + OSPEEDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + OSPEEDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + OSPEEDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + OSPEEDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + OSPEEDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + OSPEEDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + OSPEEDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + OSPEEDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + OSPEEDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + OSPEEDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + OSPEEDR0 + read-write + + LowSpeed + Low speed + 0 + + + MediumSpeed + Medium speed + 1 + + + HighSpeed + High speed + 2 + + + VeryHighSpeed + Very high speed + 3 + + + + + + + PUPDR + PUPDR + GPIO port pull-up/pull-down + register + 0xC + 0x20 + read-write + 0x00000000 + + + PUPDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + PUPDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + PUPDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + PUPDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + PUPDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + PUPDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + PUPDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + PUPDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + PUPDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + PUPDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + PUPDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + PUPDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + PUPDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + PUPDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + PUPDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + PUPDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + PUPDR0 + read-write + + Floating + No pull-up, pull-down + 0 + + + PullUp + Pull-up + 1 + + + PullDown + Pull-down + 2 + + + + + + + IDR + IDR + GPIO port input data register + 0x10 + 0x20 + read-only + 0x00000000 + + + IDR15 + Port input data (y = + 0..15) + 15 + 1 + + + + IDR14 + Port input data (y = + 0..15) + 14 + 1 + + + + IDR13 + Port input data (y = + 0..15) + 13 + 1 + + + + IDR12 + Port input data (y = + 0..15) + 12 + 1 + + + + IDR11 + Port input data (y = + 0..15) + 11 + 1 + + + + IDR10 + Port input data (y = + 0..15) + 10 + 1 + + + + IDR9 + Port input data (y = + 0..15) + 9 + 1 + + + + IDR8 + Port input data (y = + 0..15) + 8 + 1 + + + + IDR7 + Port input data (y = + 0..15) + 7 + 1 + + + + IDR6 + Port input data (y = + 0..15) + 6 + 1 + + + + IDR5 + Port input data (y = + 0..15) + 5 + 1 + + + + IDR4 + Port input data (y = + 0..15) + 4 + 1 + + + + IDR3 + Port input data (y = + 0..15) + 3 + 1 + + + + IDR2 + Port input data (y = + 0..15) + 2 + 1 + + + + IDR1 + Port input data (y = + 0..15) + 1 + 1 + + + + IDR0 + Port input data (y = + 0..15) + 0 + 1 + + IDR0 + read + + Low + Input is logic low + 0 + + + High + Input is logic high + 1 + + + + + + + ODR + ODR + GPIO port output data register + 0x14 + 0x20 + read-write + 0x00000000 + + + ODR15 + Port output data (y = + 0..15) + 15 + 1 + + + + ODR14 + Port output data (y = + 0..15) + 14 + 1 + + + + ODR13 + Port output data (y = + 0..15) + 13 + 1 + + + + ODR12 + Port output data (y = + 0..15) + 12 + 1 + + + + ODR11 + Port output data (y = + 0..15) + 11 + 1 + + + + ODR10 + Port output data (y = + 0..15) + 10 + 1 + + + + ODR9 + Port output data (y = + 0..15) + 9 + 1 + + + + ODR8 + Port output data (y = + 0..15) + 8 + 1 + + + + ODR7 + Port output data (y = + 0..15) + 7 + 1 + + + + ODR6 + Port output data (y = + 0..15) + 6 + 1 + + + + ODR5 + Port output data (y = + 0..15) + 5 + 1 + + + + ODR4 + Port output data (y = + 0..15) + 4 + 1 + + + + ODR3 + Port output data (y = + 0..15) + 3 + 1 + + + + ODR2 + Port output data (y = + 0..15) + 2 + 1 + + + + ODR1 + Port output data (y = + 0..15) + 1 + 1 + + + + ODR0 + Port output data (y = + 0..15) + 0 + 1 + + ODR0 + read-write + + Low + Set output to logic low + 0 + + + High + Set output to logic high + 1 + + + + + + + BSRR + BSRR + GPIO port bit set/reset + register + 0x18 + 0x20 + write-only + 0x00000000 + + + BR15 + Port x reset bit y (y = + 0..15) + 31 + 1 + + + + BR14 + Port x reset bit y (y = + 0..15) + 30 + 1 + + + + BR13 + Port x reset bit y (y = + 0..15) + 29 + 1 + + + + BR12 + Port x reset bit y (y = + 0..15) + 28 + 1 + + + + BR11 + Port x reset bit y (y = + 0..15) + 27 + 1 + + + + BR10 + Port x reset bit y (y = + 0..15) + 26 + 1 + + + + BR9 + Port x reset bit y (y = + 0..15) + 25 + 1 + + + + BR8 + Port x reset bit y (y = + 0..15) + 24 + 1 + + + + BR7 + Port x reset bit y (y = + 0..15) + 23 + 1 + + + + BR6 + Port x reset bit y (y = + 0..15) + 22 + 1 + + + + BR5 + Port x reset bit y (y = + 0..15) + 21 + 1 + + + + BR4 + Port x reset bit y (y = + 0..15) + 20 + 1 + + + + BR3 + Port x reset bit y (y = + 0..15) + 19 + 1 + + + + BR2 + Port x reset bit y (y = + 0..15) + 18 + 1 + + + + BR1 + Port x reset bit y (y = + 0..15) + 17 + 1 + + + + BR0 + Port x set bit y (y= + 0..15) + 16 + 1 + + BR0W + write + + Reset + Resets the corresponding ODRx bit + 1 + + + + + BS15 + Port x set bit y (y= + 0..15) + 15 + 1 + + + + BS14 + Port x set bit y (y= + 0..15) + 14 + 1 + + + + BS13 + Port x set bit y (y= + 0..15) + 13 + 1 + + + + BS12 + Port x set bit y (y= + 0..15) + 12 + 1 + + + + BS11 + Port x set bit y (y= + 0..15) + 11 + 1 + + + + BS10 + Port x set bit y (y= + 0..15) + 10 + 1 + + + + BS9 + Port x set bit y (y= + 0..15) + 9 + 1 + + + + BS8 + Port x set bit y (y= + 0..15) + 8 + 1 + + + + BS7 + Port x set bit y (y= + 0..15) + 7 + 1 + + + + BS6 + Port x set bit y (y= + 0..15) + 6 + 1 + + + + BS5 + Port x set bit y (y= + 0..15) + 5 + 1 + + + + BS4 + Port x set bit y (y= + 0..15) + 4 + 1 + + + + BS3 + Port x set bit y (y= + 0..15) + 3 + 1 + + + + BS2 + Port x set bit y (y= + 0..15) + 2 + 1 + + + + BS1 + Port x set bit y (y= + 0..15) + 1 + 1 + + + + BS0 + Port x set bit y (y= + 0..15) + 0 + 1 + + BS0W + write + + Set + Sets the corresponding ODRx bit + 1 + + + + + + + LCKR + LCKR + GPIO port configuration lock + register + 0x1C + 0x20 + read-write + 0x00000000 + + + LCKK + Port x lock bit y (y= + 0..15) + 16 + 1 + + LCKK + read-write + + NotActive + Port configuration lock key not active + 0 + + + Active + Port configuration lock key active + 1 + + + + + LCK15 + Port x lock bit y (y= + 0..15) + 15 + 1 + + + + LCK14 + Port x lock bit y (y= + 0..15) + 14 + 1 + + + + LCK13 + Port x lock bit y (y= + 0..15) + 13 + 1 + + + + LCK12 + Port x lock bit y (y= + 0..15) + 12 + 1 + + + + LCK11 + Port x lock bit y (y= + 0..15) + 11 + 1 + + + + LCK10 + Port x lock bit y (y= + 0..15) + 10 + 1 + + + + LCK9 + Port x lock bit y (y= + 0..15) + 9 + 1 + + + + LCK8 + Port x lock bit y (y= + 0..15) + 8 + 1 + + + + LCK7 + Port x lock bit y (y= + 0..15) + 7 + 1 + + + + LCK6 + Port x lock bit y (y= + 0..15) + 6 + 1 + + + + LCK5 + Port x lock bit y (y= + 0..15) + 5 + 1 + + + + LCK4 + Port x lock bit y (y= + 0..15) + 4 + 1 + + + + LCK3 + Port x lock bit y (y= + 0..15) + 3 + 1 + + + + LCK2 + Port x lock bit y (y= + 0..15) + 2 + 1 + + + + LCK1 + Port x lock bit y (y= + 0..15) + 1 + 1 + + + + LCK0 + Port x lock bit y (y= + 0..15) + 0 + 1 + + LCK0 + read-write + + Unlocked + Port configuration not locked + 0 + + + Locked + Port configuration locked + 1 + + + + + + + AFRL + AFRL + GPIO alternate function low + register + 0x20 + 0x20 + read-write + 0x00000000 + + + AFRL7 + Alternate function selection for port x + bit y (y = 0..7) + 28 + 4 + + + + AFRL6 + Alternate function selection for port x + bit y (y = 0..7) + 24 + 4 + + + + AFRL5 + Alternate function selection for port x + bit y (y = 0..7) + 20 + 4 + + + + AFRL4 + Alternate function selection for port x + bit y (y = 0..7) + 16 + 4 + + + + AFRL3 + Alternate function selection for port x + bit y (y = 0..7) + 12 + 4 + + + + AFRL2 + Alternate function selection for port x + bit y (y = 0..7) + 8 + 4 + + + + AFRL1 + Alternate function selection for port x + bit y (y = 0..7) + 4 + 4 + + + + AFRL0 + Alternate function selection for port x + bit y (y = 0..7) + 0 + 4 + + AFRL0 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + AFRH + AFRH + GPIO alternate function high + register + 0x24 + 0x20 + read-write + 0x00000000 + + + AFRH15 + Alternate function selection for port x + bit y (y = 8..15) + 28 + 4 + + + + AFRH14 + Alternate function selection for port x + bit y (y = 8..15) + 24 + 4 + + + + AFRH13 + Alternate function selection for port x + bit y (y = 8..15) + 20 + 4 + + + + AFRH12 + Alternate function selection for port x + bit y (y = 8..15) + 16 + 4 + + + + AFRH11 + Alternate function selection for port x + bit y (y = 8..15) + 12 + 4 + + + + AFRH10 + Alternate function selection for port x + bit y (y = 8..15) + 8 + 4 + + + + AFRH9 + Alternate function selection for port x + bit y (y = 8..15) + 4 + 4 + + + + AFRH8 + Alternate function selection for port x + bit y (y = 8..15) + 0 + 4 + + AFRH8 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + + + GPIOE + 0x40021000 + + + GPIOD + 0x40020C00 + + TIM1_BRK_TIM9 + TIM1 Break interrupt and TIM9 global + interrupt + 24 + + + TIM1_UP_TIM10 + TIM1 Update interrupt and TIM10 global + interrupt + 25 + + + TIM1_TRG_COM_TIM11 + TIM1 Trigger and Commutation interrupts and + TIM11 global interrupt + 26 + + + TIM1_CC + TIM1 Capture Compare interrupt + 27 + + + + GPIOC + 0x40020800 + + TIM1_UP_TIM10 + TIM1 Update interrupt and TIM10 global + interrupt + 25 + + + + GPIOB + General-purpose I/Os + GPIO + 0x40020400 + + 0x0 + 0x400 + registers + + + TIM1_TRG_COM_TIM11 + TIM1 Trigger and Commutation interrupts and + TIM11 global interrupt + 26 + + + + MODER + MODER + GPIO port mode register + 0x0 + 0x20 + read-write + 0x00000280 + + + MODER15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + MODER14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + MODER13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + MODER12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + MODER11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + MODER10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + MODER9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + MODER8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + MODER7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + MODER6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + MODER5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + MODER4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + MODER3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + MODER2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + MODER1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + MODER0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + MODER0 + read-write + + Input + Input mode (reset state) + 0 + + + Output + General purpose output mode + 1 + + + Alternate + Alternate function mode + 2 + + + Analog + Analog mode + 3 + + + + + + + OTYPER + OTYPER + GPIO port output type register + 0x4 + 0x20 + read-write + 0x00000000 + + + OT15 + Port x configuration bits (y = + 0..15) + 15 + 1 + + + + OT14 + Port x configuration bits (y = + 0..15) + 14 + 1 + + + + OT13 + Port x configuration bits (y = + 0..15) + 13 + 1 + + + + OT12 + Port x configuration bits (y = + 0..15) + 12 + 1 + + + + OT11 + Port x configuration bits (y = + 0..15) + 11 + 1 + + + + OT10 + Port x configuration bits (y = + 0..15) + 10 + 1 + + + + OT9 + Port x configuration bits (y = + 0..15) + 9 + 1 + + + + OT8 + Port x configuration bits (y = + 0..15) + 8 + 1 + + + + OT7 + Port x configuration bits (y = + 0..15) + 7 + 1 + + + + OT6 + Port x configuration bits (y = + 0..15) + 6 + 1 + + + + OT5 + Port x configuration bits (y = + 0..15) + 5 + 1 + + + + OT4 + Port x configuration bits (y = + 0..15) + 4 + 1 + + + + OT3 + Port x configuration bits (y = + 0..15) + 3 + 1 + + + + OT2 + Port x configuration bits (y = + 0..15) + 2 + 1 + + + + OT1 + Port x configuration bits (y = + 0..15) + 1 + 1 + + + + OT0 + Port x configuration bits (y = + 0..15) + 0 + 1 + + OT0 + read-write + + PushPull + Output push-pull (reset state) + 0 + + + OpenDrain + Output open-drain + 1 + + + + + + + OSPEEDR + OSPEEDR + GPIO port output speed + register + 0x8 + 0x20 + read-write + 0x000000C0 + + + OSPEEDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + OSPEEDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + OSPEEDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + OSPEEDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + OSPEEDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + OSPEEDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + OSPEEDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + OSPEEDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + OSPEEDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + OSPEEDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + OSPEEDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + OSPEEDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + OSPEEDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + OSPEEDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + OSPEEDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + OSPEEDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + OSPEEDR0 + read-write + + LowSpeed + Low speed + 0 + + + MediumSpeed + Medium speed + 1 + + + HighSpeed + High speed + 2 + + + VeryHighSpeed + Very high speed + 3 + + + + + + + PUPDR + PUPDR + GPIO port pull-up/pull-down + register + 0xC + 0x20 + read-write + 0x00000100 + + + PUPDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + PUPDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + PUPDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + PUPDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + PUPDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + PUPDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + PUPDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + PUPDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + PUPDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + PUPDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + PUPDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + PUPDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + PUPDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + PUPDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + PUPDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + PUPDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + PUPDR0 + read-write + + Floating + No pull-up, pull-down + 0 + + + PullUp + Pull-up + 1 + + + PullDown + Pull-down + 2 + + + + + + + IDR + IDR + GPIO port input data register + 0x10 + 0x20 + read-only + 0x00000000 + + + IDR15 + Port input data (y = + 0..15) + 15 + 1 + + + + IDR14 + Port input data (y = + 0..15) + 14 + 1 + + + + IDR13 + Port input data (y = + 0..15) + 13 + 1 + + + + IDR12 + Port input data (y = + 0..15) + 12 + 1 + + + + IDR11 + Port input data (y = + 0..15) + 11 + 1 + + + + IDR10 + Port input data (y = + 0..15) + 10 + 1 + + + + IDR9 + Port input data (y = + 0..15) + 9 + 1 + + + + IDR8 + Port input data (y = + 0..15) + 8 + 1 + + + + IDR7 + Port input data (y = + 0..15) + 7 + 1 + + + + IDR6 + Port input data (y = + 0..15) + 6 + 1 + + + + IDR5 + Port input data (y = + 0..15) + 5 + 1 + + + + IDR4 + Port input data (y = + 0..15) + 4 + 1 + + + + IDR3 + Port input data (y = + 0..15) + 3 + 1 + + + + IDR2 + Port input data (y = + 0..15) + 2 + 1 + + + + IDR1 + Port input data (y = + 0..15) + 1 + 1 + + + + IDR0 + Port input data (y = + 0..15) + 0 + 1 + + IDR0 + read + + Low + Input is logic low + 0 + + + High + Input is logic high + 1 + + + + + + + ODR + ODR + GPIO port output data register + 0x14 + 0x20 + read-write + 0x00000000 + + + ODR15 + Port output data (y = + 0..15) + 15 + 1 + + + + ODR14 + Port output data (y = + 0..15) + 14 + 1 + + + + ODR13 + Port output data (y = + 0..15) + 13 + 1 + + + + ODR12 + Port output data (y = + 0..15) + 12 + 1 + + + + ODR11 + Port output data (y = + 0..15) + 11 + 1 + + + + ODR10 + Port output data (y = + 0..15) + 10 + 1 + + + + ODR9 + Port output data (y = + 0..15) + 9 + 1 + + + + ODR8 + Port output data (y = + 0..15) + 8 + 1 + + + + ODR7 + Port output data (y = + 0..15) + 7 + 1 + + + + ODR6 + Port output data (y = + 0..15) + 6 + 1 + + + + ODR5 + Port output data (y = + 0..15) + 5 + 1 + + + + ODR4 + Port output data (y = + 0..15) + 4 + 1 + + + + ODR3 + Port output data (y = + 0..15) + 3 + 1 + + + + ODR2 + Port output data (y = + 0..15) + 2 + 1 + + + + ODR1 + Port output data (y = + 0..15) + 1 + 1 + + + + ODR0 + Port output data (y = + 0..15) + 0 + 1 + + ODR0 + read-write + + Low + Set output to logic low + 0 + + + High + Set output to logic high + 1 + + + + + + + BSRR + BSRR + GPIO port bit set/reset + register + 0x18 + 0x20 + write-only + 0x00000000 + + + BR15 + Port x reset bit y (y = + 0..15) + 31 + 1 + + + + BR14 + Port x reset bit y (y = + 0..15) + 30 + 1 + + + + BR13 + Port x reset bit y (y = + 0..15) + 29 + 1 + + + + BR12 + Port x reset bit y (y = + 0..15) + 28 + 1 + + + + BR11 + Port x reset bit y (y = + 0..15) + 27 + 1 + + + + BR10 + Port x reset bit y (y = + 0..15) + 26 + 1 + + + + BR9 + Port x reset bit y (y = + 0..15) + 25 + 1 + + + + BR8 + Port x reset bit y (y = + 0..15) + 24 + 1 + + + + BR7 + Port x reset bit y (y = + 0..15) + 23 + 1 + + + + BR6 + Port x reset bit y (y = + 0..15) + 22 + 1 + + + + BR5 + Port x reset bit y (y = + 0..15) + 21 + 1 + + + + BR4 + Port x reset bit y (y = + 0..15) + 20 + 1 + + + + BR3 + Port x reset bit y (y = + 0..15) + 19 + 1 + + + + BR2 + Port x reset bit y (y = + 0..15) + 18 + 1 + + + + BR1 + Port x reset bit y (y = + 0..15) + 17 + 1 + + + + BR0 + Port x set bit y (y= + 0..15) + 16 + 1 + + BR0W + write + + Reset + Resets the corresponding ODRx bit + 1 + + + + + BS15 + Port x set bit y (y= + 0..15) + 15 + 1 + + + + BS14 + Port x set bit y (y= + 0..15) + 14 + 1 + + + + BS13 + Port x set bit y (y= + 0..15) + 13 + 1 + + + + BS12 + Port x set bit y (y= + 0..15) + 12 + 1 + + + + BS11 + Port x set bit y (y= + 0..15) + 11 + 1 + + + + BS10 + Port x set bit y (y= + 0..15) + 10 + 1 + + + + BS9 + Port x set bit y (y= + 0..15) + 9 + 1 + + + + BS8 + Port x set bit y (y= + 0..15) + 8 + 1 + + + + BS7 + Port x set bit y (y= + 0..15) + 7 + 1 + + + + BS6 + Port x set bit y (y= + 0..15) + 6 + 1 + + + + BS5 + Port x set bit y (y= + 0..15) + 5 + 1 + + + + BS4 + Port x set bit y (y= + 0..15) + 4 + 1 + + + + BS3 + Port x set bit y (y= + 0..15) + 3 + 1 + + + + BS2 + Port x set bit y (y= + 0..15) + 2 + 1 + + + + BS1 + Port x set bit y (y= + 0..15) + 1 + 1 + + + + BS0 + Port x set bit y (y= + 0..15) + 0 + 1 + + BS0W + write + + Set + Sets the corresponding ODRx bit + 1 + + + + + + + LCKR + LCKR + GPIO port configuration lock + register + 0x1C + 0x20 + read-write + 0x00000000 + + + LCKK + Port x lock bit y (y= + 0..15) + 16 + 1 + + LCKK + read-write + + NotActive + Port configuration lock key not active + 0 + + + Active + Port configuration lock key active + 1 + + + + + LCK15 + Port x lock bit y (y= + 0..15) + 15 + 1 + + + + LCK14 + Port x lock bit y (y= + 0..15) + 14 + 1 + + + + LCK13 + Port x lock bit y (y= + 0..15) + 13 + 1 + + + + LCK12 + Port x lock bit y (y= + 0..15) + 12 + 1 + + + + LCK11 + Port x lock bit y (y= + 0..15) + 11 + 1 + + + + LCK10 + Port x lock bit y (y= + 0..15) + 10 + 1 + + + + LCK9 + Port x lock bit y (y= + 0..15) + 9 + 1 + + + + LCK8 + Port x lock bit y (y= + 0..15) + 8 + 1 + + + + LCK7 + Port x lock bit y (y= + 0..15) + 7 + 1 + + + + LCK6 + Port x lock bit y (y= + 0..15) + 6 + 1 + + + + LCK5 + Port x lock bit y (y= + 0..15) + 5 + 1 + + + + LCK4 + Port x lock bit y (y= + 0..15) + 4 + 1 + + + + LCK3 + Port x lock bit y (y= + 0..15) + 3 + 1 + + + + LCK2 + Port x lock bit y (y= + 0..15) + 2 + 1 + + + + LCK1 + Port x lock bit y (y= + 0..15) + 1 + 1 + + + + LCK0 + Port x lock bit y (y= + 0..15) + 0 + 1 + + LCK0 + read-write + + Unlocked + Port configuration not locked + 0 + + + Locked + Port configuration locked + 1 + + + + + + + AFRL + AFRL + GPIO alternate function low + register + 0x20 + 0x20 + read-write + 0x00000000 + + + AFRL7 + Alternate function selection for port x + bit y (y = 0..7) + 28 + 4 + + + + AFRL6 + Alternate function selection for port x + bit y (y = 0..7) + 24 + 4 + + + + AFRL5 + Alternate function selection for port x + bit y (y = 0..7) + 20 + 4 + + + + AFRL4 + Alternate function selection for port x + bit y (y = 0..7) + 16 + 4 + + + + AFRL3 + Alternate function selection for port x + bit y (y = 0..7) + 12 + 4 + + + + AFRL2 + Alternate function selection for port x + bit y (y = 0..7) + 8 + 4 + + + + AFRL1 + Alternate function selection for port x + bit y (y = 0..7) + 4 + 4 + + + + AFRL0 + Alternate function selection for port x + bit y (y = 0..7) + 0 + 4 + + AFRL0 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + AFRH + AFRH + GPIO alternate function high + register + 0x24 + 0x20 + read-write + 0x00000000 + + + AFRH15 + Alternate function selection for port x + bit y (y = 8..15) + 28 + 4 + + + + AFRH14 + Alternate function selection for port x + bit y (y = 8..15) + 24 + 4 + + + + AFRH13 + Alternate function selection for port x + bit y (y = 8..15) + 20 + 4 + + + + AFRH12 + Alternate function selection for port x + bit y (y = 8..15) + 16 + 4 + + + + AFRH11 + Alternate function selection for port x + bit y (y = 8..15) + 12 + 4 + + + + AFRH10 + Alternate function selection for port x + bit y (y = 8..15) + 8 + 4 + + + + AFRH9 + Alternate function selection for port x + bit y (y = 8..15) + 4 + 4 + + + + AFRH8 + Alternate function selection for port x + bit y (y = 8..15) + 0 + 4 + + AFRH8 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + + + GPIOA + General-purpose I/Os + GPIO + 0x40020000 + + 0x0 + 0x400 + registers + + + TIM2 + TIM2 global interrupt + 28 + + + + MODER + MODER + GPIO port mode register + 0x0 + 0x20 + read-write + 0xA8000000 + + + MODER15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + MODER14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + MODER13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + MODER12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + MODER11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + MODER10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + MODER9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + MODER8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + MODER7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + MODER6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + MODER5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + MODER4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + MODER3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + MODER2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + MODER1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + MODER0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + MODER0 + read-write + + Input + Input mode (reset state) + 0 + + + Output + General purpose output mode + 1 + + + Alternate + Alternate function mode + 2 + + + Analog + Analog mode + 3 + + + + + + + OTYPER + OTYPER + GPIO port output type register + 0x4 + 0x20 + read-write + 0x00000000 + + + OT15 + Port x configuration bits (y = + 0..15) + 15 + 1 + + + + OT14 + Port x configuration bits (y = + 0..15) + 14 + 1 + + + + OT13 + Port x configuration bits (y = + 0..15) + 13 + 1 + + + + OT12 + Port x configuration bits (y = + 0..15) + 12 + 1 + + + + OT11 + Port x configuration bits (y = + 0..15) + 11 + 1 + + + + OT10 + Port x configuration bits (y = + 0..15) + 10 + 1 + + + + OT9 + Port x configuration bits (y = + 0..15) + 9 + 1 + + + + OT8 + Port x configuration bits (y = + 0..15) + 8 + 1 + + + + OT7 + Port x configuration bits (y = + 0..15) + 7 + 1 + + + + OT6 + Port x configuration bits (y = + 0..15) + 6 + 1 + + + + OT5 + Port x configuration bits (y = + 0..15) + 5 + 1 + + + + OT4 + Port x configuration bits (y = + 0..15) + 4 + 1 + + + + OT3 + Port x configuration bits (y = + 0..15) + 3 + 1 + + + + OT2 + Port x configuration bits (y = + 0..15) + 2 + 1 + + + + OT1 + Port x configuration bits (y = + 0..15) + 1 + 1 + + + + OT0 + Port x configuration bits (y = + 0..15) + 0 + 1 + + OT0 + read-write + + PushPull + Output push-pull (reset state) + 0 + + + OpenDrain + Output open-drain + 1 + + + + + + + OSPEEDR + OSPEEDR + GPIO port output speed + register + 0x8 + 0x20 + read-write + 0x00000000 + + + OSPEEDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + OSPEEDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + OSPEEDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + OSPEEDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + OSPEEDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + OSPEEDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + OSPEEDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + OSPEEDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + OSPEEDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + OSPEEDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + OSPEEDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + OSPEEDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + OSPEEDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + OSPEEDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + OSPEEDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + OSPEEDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + OSPEEDR0 + read-write + + LowSpeed + Low speed + 0 + + + MediumSpeed + Medium speed + 1 + + + HighSpeed + High speed + 2 + + + VeryHighSpeed + Very high speed + 3 + + + + + + + PUPDR + PUPDR + GPIO port pull-up/pull-down + register + 0xC + 0x20 + read-write + 0x64000000 + + + PUPDR15 + Port x configuration bits (y = + 0..15) + 30 + 2 + + + + PUPDR14 + Port x configuration bits (y = + 0..15) + 28 + 2 + + + + PUPDR13 + Port x configuration bits (y = + 0..15) + 26 + 2 + + + + PUPDR12 + Port x configuration bits (y = + 0..15) + 24 + 2 + + + + PUPDR11 + Port x configuration bits (y = + 0..15) + 22 + 2 + + + + PUPDR10 + Port x configuration bits (y = + 0..15) + 20 + 2 + + + + PUPDR9 + Port x configuration bits (y = + 0..15) + 18 + 2 + + + + PUPDR8 + Port x configuration bits (y = + 0..15) + 16 + 2 + + + + PUPDR7 + Port x configuration bits (y = + 0..15) + 14 + 2 + + + + PUPDR6 + Port x configuration bits (y = + 0..15) + 12 + 2 + + + + PUPDR5 + Port x configuration bits (y = + 0..15) + 10 + 2 + + + + PUPDR4 + Port x configuration bits (y = + 0..15) + 8 + 2 + + + + PUPDR3 + Port x configuration bits (y = + 0..15) + 6 + 2 + + + + PUPDR2 + Port x configuration bits (y = + 0..15) + 4 + 2 + + + + PUPDR1 + Port x configuration bits (y = + 0..15) + 2 + 2 + + + + PUPDR0 + Port x configuration bits (y = + 0..15) + 0 + 2 + + PUPDR0 + read-write + + Floating + No pull-up, pull-down + 0 + + + PullUp + Pull-up + 1 + + + PullDown + Pull-down + 2 + + + + + + + IDR + IDR + GPIO port input data register + 0x10 + 0x20 + read-only + 0x00000000 + + + IDR15 + Port input data (y = + 0..15) + 15 + 1 + + + + IDR14 + Port input data (y = + 0..15) + 14 + 1 + + + + IDR13 + Port input data (y = + 0..15) + 13 + 1 + + + + IDR12 + Port input data (y = + 0..15) + 12 + 1 + + + + IDR11 + Port input data (y = + 0..15) + 11 + 1 + + + + IDR10 + Port input data (y = + 0..15) + 10 + 1 + + + + IDR9 + Port input data (y = + 0..15) + 9 + 1 + + + + IDR8 + Port input data (y = + 0..15) + 8 + 1 + + + + IDR7 + Port input data (y = + 0..15) + 7 + 1 + + + + IDR6 + Port input data (y = + 0..15) + 6 + 1 + + + + IDR5 + Port input data (y = + 0..15) + 5 + 1 + + + + IDR4 + Port input data (y = + 0..15) + 4 + 1 + + + + IDR3 + Port input data (y = + 0..15) + 3 + 1 + + + + IDR2 + Port input data (y = + 0..15) + 2 + 1 + + + + IDR1 + Port input data (y = + 0..15) + 1 + 1 + + + + IDR0 + Port input data (y = + 0..15) + 0 + 1 + + IDR0 + read + + Low + Input is logic low + 0 + + + High + Input is logic high + 1 + + + + + + + ODR + ODR + GPIO port output data register + 0x14 + 0x20 + read-write + 0x00000000 + + + ODR15 + Port output data (y = + 0..15) + 15 + 1 + + + + ODR14 + Port output data (y = + 0..15) + 14 + 1 + + + + ODR13 + Port output data (y = + 0..15) + 13 + 1 + + + + ODR12 + Port output data (y = + 0..15) + 12 + 1 + + + + ODR11 + Port output data (y = + 0..15) + 11 + 1 + + + + ODR10 + Port output data (y = + 0..15) + 10 + 1 + + + + ODR9 + Port output data (y = + 0..15) + 9 + 1 + + + + ODR8 + Port output data (y = + 0..15) + 8 + 1 + + + + ODR7 + Port output data (y = + 0..15) + 7 + 1 + + + + ODR6 + Port output data (y = + 0..15) + 6 + 1 + + + + ODR5 + Port output data (y = + 0..15) + 5 + 1 + + + + ODR4 + Port output data (y = + 0..15) + 4 + 1 + + + + ODR3 + Port output data (y = + 0..15) + 3 + 1 + + + + ODR2 + Port output data (y = + 0..15) + 2 + 1 + + + + ODR1 + Port output data (y = + 0..15) + 1 + 1 + + + + ODR0 + Port output data (y = + 0..15) + 0 + 1 + + ODR0 + read-write + + Low + Set output to logic low + 0 + + + High + Set output to logic high + 1 + + + + + + + BSRR + BSRR + GPIO port bit set/reset + register + 0x18 + 0x20 + write-only + 0x00000000 + + + BR15 + Port x reset bit y (y = + 0..15) + 31 + 1 + + + + BR14 + Port x reset bit y (y = + 0..15) + 30 + 1 + + + + BR13 + Port x reset bit y (y = + 0..15) + 29 + 1 + + + + BR12 + Port x reset bit y (y = + 0..15) + 28 + 1 + + + + BR11 + Port x reset bit y (y = + 0..15) + 27 + 1 + + + + BR10 + Port x reset bit y (y = + 0..15) + 26 + 1 + + + + BR9 + Port x reset bit y (y = + 0..15) + 25 + 1 + + + + BR8 + Port x reset bit y (y = + 0..15) + 24 + 1 + + + + BR7 + Port x reset bit y (y = + 0..15) + 23 + 1 + + + + BR6 + Port x reset bit y (y = + 0..15) + 22 + 1 + + + + BR5 + Port x reset bit y (y = + 0..15) + 21 + 1 + + + + BR4 + Port x reset bit y (y = + 0..15) + 20 + 1 + + + + BR3 + Port x reset bit y (y = + 0..15) + 19 + 1 + + + + BR2 + Port x reset bit y (y = + 0..15) + 18 + 1 + + + + BR1 + Port x reset bit y (y = + 0..15) + 17 + 1 + + + + BR0 + Port x set bit y (y= + 0..15) + 16 + 1 + + BR0W + write + + Reset + Resets the corresponding ODRx bit + 1 + + + + + BS15 + Port x set bit y (y= + 0..15) + 15 + 1 + + + + BS14 + Port x set bit y (y= + 0..15) + 14 + 1 + + + + BS13 + Port x set bit y (y= + 0..15) + 13 + 1 + + + + BS12 + Port x set bit y (y= + 0..15) + 12 + 1 + + + + BS11 + Port x set bit y (y= + 0..15) + 11 + 1 + + + + BS10 + Port x set bit y (y= + 0..15) + 10 + 1 + + + + BS9 + Port x set bit y (y= + 0..15) + 9 + 1 + + + + BS8 + Port x set bit y (y= + 0..15) + 8 + 1 + + + + BS7 + Port x set bit y (y= + 0..15) + 7 + 1 + + + + BS6 + Port x set bit y (y= + 0..15) + 6 + 1 + + + + BS5 + Port x set bit y (y= + 0..15) + 5 + 1 + + + + BS4 + Port x set bit y (y= + 0..15) + 4 + 1 + + + + BS3 + Port x set bit y (y= + 0..15) + 3 + 1 + + + + BS2 + Port x set bit y (y= + 0..15) + 2 + 1 + + + + BS1 + Port x set bit y (y= + 0..15) + 1 + 1 + + + + BS0 + Port x set bit y (y= + 0..15) + 0 + 1 + + BS0W + write + + Set + Sets the corresponding ODRx bit + 1 + + + + + + + LCKR + LCKR + GPIO port configuration lock + register + 0x1C + 0x20 + read-write + 0x00000000 + + + LCKK + Port x lock bit y (y= + 0..15) + 16 + 1 + + LCKK + read-write + + NotActive + Port configuration lock key not active + 0 + + + Active + Port configuration lock key active + 1 + + + + + LCK15 + Port x lock bit y (y= + 0..15) + 15 + 1 + + + + LCK14 + Port x lock bit y (y= + 0..15) + 14 + 1 + + + + LCK13 + Port x lock bit y (y= + 0..15) + 13 + 1 + + + + LCK12 + Port x lock bit y (y= + 0..15) + 12 + 1 + + + + LCK11 + Port x lock bit y (y= + 0..15) + 11 + 1 + + + + LCK10 + Port x lock bit y (y= + 0..15) + 10 + 1 + + + + LCK9 + Port x lock bit y (y= + 0..15) + 9 + 1 + + + + LCK8 + Port x lock bit y (y= + 0..15) + 8 + 1 + + + + LCK7 + Port x lock bit y (y= + 0..15) + 7 + 1 + + + + LCK6 + Port x lock bit y (y= + 0..15) + 6 + 1 + + + + LCK5 + Port x lock bit y (y= + 0..15) + 5 + 1 + + + + LCK4 + Port x lock bit y (y= + 0..15) + 4 + 1 + + + + LCK3 + Port x lock bit y (y= + 0..15) + 3 + 1 + + + + LCK2 + Port x lock bit y (y= + 0..15) + 2 + 1 + + + + LCK1 + Port x lock bit y (y= + 0..15) + 1 + 1 + + + + LCK0 + Port x lock bit y (y= + 0..15) + 0 + 1 + + LCK0 + read-write + + Unlocked + Port configuration not locked + 0 + + + Locked + Port configuration locked + 1 + + + + + + + AFRL + AFRL + GPIO alternate function low + register + 0x20 + 0x20 + read-write + 0x00000000 + + + AFRL7 + Alternate function selection for port x + bit y (y = 0..7) + 28 + 4 + + + + AFRL6 + Alternate function selection for port x + bit y (y = 0..7) + 24 + 4 + + + + AFRL5 + Alternate function selection for port x + bit y (y = 0..7) + 20 + 4 + + + + AFRL4 + Alternate function selection for port x + bit y (y = 0..7) + 16 + 4 + + + + AFRL3 + Alternate function selection for port x + bit y (y = 0..7) + 12 + 4 + + + + AFRL2 + Alternate function selection for port x + bit y (y = 0..7) + 8 + 4 + + + + AFRL1 + Alternate function selection for port x + bit y (y = 0..7) + 4 + 4 + + + + AFRL0 + Alternate function selection for port x + bit y (y = 0..7) + 0 + 4 + + AFRL0 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + AFRH + AFRH + GPIO alternate function high + register + 0x24 + 0x20 + read-write + 0x00000000 + + + AFRH15 + Alternate function selection for port x + bit y (y = 8..15) + 28 + 4 + + + + AFRH14 + Alternate function selection for port x + bit y (y = 8..15) + 24 + 4 + + + + AFRH13 + Alternate function selection for port x + bit y (y = 8..15) + 20 + 4 + + + + AFRH12 + Alternate function selection for port x + bit y (y = 8..15) + 16 + 4 + + + + AFRH11 + Alternate function selection for port x + bit y (y = 8..15) + 12 + 4 + + + + AFRH10 + Alternate function selection for port x + bit y (y = 8..15) + 8 + 4 + + + + AFRH9 + Alternate function selection for port x + bit y (y = 8..15) + 4 + 4 + + + + AFRH8 + Alternate function selection for port x + bit y (y = 8..15) + 0 + 4 + + AFRH8 + read-write + + AF0 + AF0 + 0 + + + AF1 + AF1 + 1 + + + AF2 + AF2 + 2 + + + AF3 + AF3 + 3 + + + AF4 + AF4 + 4 + + + AF5 + AF5 + 5 + + + AF6 + AF6 + 6 + + + AF7 + AF7 + 7 + + + AF8 + AF8 + 8 + + + AF9 + AF9 + 9 + + + AF10 + AF10 + 10 + + + AF11 + AF11 + 11 + + + AF12 + AF12 + 12 + + + AF13 + AF13 + 13 + + + AF14 + AF14 + 14 + + + AF15 + AF15 + 15 + + + + + + + + + I2C3 + 0x40005C00 + + TIM3 + TIM3 global interrupt + 29 + + + + I2C2 + 0x40005800 + + I2C3_EV + I2C3 event interrupt + 72 + + + I2C3_ER + I2C3 error interrupt + 73 + + + + I2C1 + Inter-integrated circuit + I2C + 0x40005400 + + 0x0 + 0x400 + registers + + + I2C2_EV + I2C2 event interrupt + 33 + + + I2C2_ER + I2C2 error interrupt + 34 + + + + CR1 + CR1 + Control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + SWRST + Software reset + 15 + 1 + + SWRST + read-write + + NotReset + I2C peripheral not under reset + 0 + + + Reset + I2C peripheral under reset + 1 + + + + + ALERT + SMBus alert + 13 + 1 + + ALERT + read-write + + Release + SMBA pin released high + 0 + + + Drive + SMBA pin driven low + 1 + + + + + PEC + Packet error checking + 12 + 1 + + PEC + read-write + + Disabled + No PEC transfer + 0 + + + Enabled + PEC transfer + 1 + + + + + POS + Acknowledge/PEC Position (for data + reception) + 11 + 1 + + POS + read-write + + Current + ACK bit controls the (N)ACK of the current byte being received + 0 + + + Next + ACK bit controls the (N)ACK of the next byte to be received + 1 + + + + + ACK + Acknowledge enable + 10 + 1 + + ACK + read-write + + NAK + No acknowledge returned + 0 + + + ACK + Acknowledge returned after a byte is received + 1 + + + + + STOP + Stop generation + 9 + 1 + + STOP + read-write + + NoStop + No Stop generation + 0 + + + Stop + In master mode: stop generation after current byte/start, in slave mode: release SCL and SDA after current byte + 1 + + + + + START + Start generation + 8 + 1 + + START + read-write + + NoStart + No Start generation + 0 + + + Start + In master mode: repeated start generation, in slave mode: start generation when bus is free + 1 + + + + + NOSTRETCH + Clock stretching disable (Slave + mode) + 7 + 1 + + NOSTRETCH + read-write + + Enabled + Clock stretching enabled + 0 + + + Disabled + Clock stretching disabled + 1 + + + + + ENGC + General call enable + 6 + 1 + + ENGC + read-write + + Disabled + General call disabled + 0 + + + Enabled + General call enabled + 1 + + + + + ENPEC + PEC enable + 5 + 1 + + ENPEC + read-write + + Disabled + PEC calculation disabled + 0 + + + Enabled + PEC calculation enabled + 1 + + + + + ENARP + ARP enable + 4 + 1 + + ENARP + read-write + + Disabled + ARP disabled + 0 + + + Enabled + ARP enabled + 1 + + + + + SMBTYPE + SMBus type + 3 + 1 + + SMBTYPE + read-write + + Device + SMBus Device + 0 + + + Host + SMBus Host + 1 + + + + + SMBUS + SMBus mode + 1 + 1 + + SMBUS + read-write + + I2C + I2C Mode + 0 + + + SMBus + SMBus + 1 + + + + + PE + Peripheral enable + 0 + 1 + + PE + read-write + + Disabled + Peripheral disabled + 0 + + + Enabled + Peripheral enabled + 1 + + + + + + + CR2 + CR2 + Control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + LAST + DMA last transfer + 12 + 1 + + LAST + read-write + + NotLast + Next DMA EOT is not the last transfer + 0 + + + Last + Next DMA EOT is the last transfer + 1 + + + + + DMAEN + DMA requests enable + 11 + 1 + + DMAEN + read-write + + Disabled + DMA requests disabled + 0 + + + Enabled + DMA request enabled when TxE=1 or RxNE=1 + 1 + + + + + ITBUFEN + Buffer interrupt enable + 10 + 1 + + ITBUFEN + read-write + + Disabled + TxE=1 or RxNE=1 does not generate any interrupt + 0 + + + Enabled + TxE=1 or RxNE=1 generates Event interrupt + 1 + + + + + ITEVTEN + Event interrupt enable + 9 + 1 + + ITEVTEN + read-write + + Disabled + Event interrupt disabled + 0 + + + Enabled + Event interrupt enabled + 1 + + + + + ITERREN + Error interrupt enable + 8 + 1 + + ITERREN + read-write + + Disabled + Error interrupt disabled + 0 + + + Enabled + Error interrupt enabled + 1 + + + + + FREQ + Peripheral clock frequency + 0 + 6 + + + 2 + 50 + + + + + + + OAR1 + OAR1 + Own address register 1 + 0x8 + 0x20 + read-write + 0x00000000 + + + ADDMODE + Addressing mode (slave + mode) + 15 + 1 + + ADDMODE + read-write + + ADD7 + 7-bit slave address + 0 + + + ADD10 + 10-bit slave address + 1 + + + + + ADD + Interface address + 0 + 10 + + + 0 + 1023 + + + + + + + OAR2 + OAR2 + Own address register 2 + 0xC + 0x20 + read-write + 0x00000000 + + + ADD2 + Interface address + 1 + 7 + + + 0 + 127 + + + + + ENDUAL + Dual addressing mode + enable + 0 + 1 + + ENDUAL + read-write + + Single + Single addressing mode + 0 + + + Dual + Dual addressing mode + 1 + + + + + + + DR + DR + Data register + 0x10 + 0x20 + read-write + 0x00000000 + + + DR + 8-bit data register + 0 + 8 + + + 0 + 255 + + + + + + + SR1 + SR1 + Status register 1 + 0x14 + 0x20 + 0x00000000 + + + SMBALERT + SMBus alert + 15 + 1 + read-write + zeroToClear + + SMBALERTR + read + + NoAlert + No SMBALERT occured + 0 + + + Alert + SMBALERT occurred + 1 + + + + SMBALERTW + write + + Clear + Clear flag + 0 + + + + + TIMEOUT + Timeout or Tlow error + 14 + 1 + read-write + zeroToClear + + TIMEOUTR + read + + NoTimeout + No Timeout error + 0 + + + Timeout + SCL remained LOW for 25 ms + 1 + + + + TIMEOUTW + write + + Clear + Clear flag + 0 + + + + + PECERR + PEC Error in reception + 12 + 1 + read-write + zeroToClear + + PECERRR + read + + NoError + no PEC error: receiver returns ACK after PEC reception (if ACK=1) + 0 + + + Error + PEC error: receiver returns NACK after PEC reception (whatever ACK) + 1 + + + + PECERRW + write + + Clear + Clear flag + 0 + + + + + OVR + Overrun/Underrun + 11 + 1 + read-write + zeroToClear + + OVRR + read + + NoOverrun + No overrun/underrun occured + 0 + + + Overrun + Overrun/underrun occured + 1 + + + + OVRW + write + + Clear + Clear flag + 0 + + + + + AF + Acknowledge failure + 10 + 1 + read-write + zeroToClear + + AFR + read + + NoFailure + No acknowledge failure + 0 + + + Failure + Acknowledge failure + 1 + + + + AFW + write + + Clear + Clear flag + 0 + + + + + ARLO + Arbitration lost (master + mode) + 9 + 1 + read-write + zeroToClear + + ARLOR + read + + NoLost + No Arbitration Lost detected + 0 + + + Lost + Arbitration Lost detected + 1 + + + + ARLOW + write + + Clear + Clear flag + 0 + + + + + BERR + Bus error + 8 + 1 + read-write + zeroToClear + + BERRR + read + + NoError + No misplaced Start or Stop condition + 0 + + + Error + Misplaced Start or Stop condition + 1 + + + + BERRW + write + + Clear + Clear flag + 0 + + + + + TxE + Data register empty + (transmitters) + 7 + 1 + read-only + + TxE + read + + NotEmpty + Data register not empty + 0 + + + Empty + Data register empty + 1 + + + + + RxNE + Data register not empty + (receivers) + 6 + 1 + read-only + + RxNE + read + + Empty + Data register empty + 0 + + + NotEmpty + Data register not empty + 1 + + + + + STOPF + Stop detection (slave + mode) + 4 + 1 + read-only + + STOPF + read + + NoStop + No Stop condition detected + 0 + + + Stop + Stop condition detected + 1 + + + + + ADD10 + 10-bit header sent (Master + mode) + 3 + 1 + read-only + + + BTF + Byte transfer finished + 2 + 1 + read-only + + BTF + read + + NotFinished + Data byte transfer not done + 0 + + + Finished + Data byte transfer successful + 1 + + + + + ADDR + Address sent (master mode)/matched + (slave mode) + 1 + 1 + read-only + + ADDR + read + + NotMatch + Adress mismatched or not received + 0 + + + Match + Received slave address matched with one of the enabled slave addresses + 1 + + + + + SB + Start bit (Master mode) + 0 + 1 + read-only + + SB + read + + NoStart + No Start condition + 0 + + + Start + Start condition generated + 1 + + + + + + + SR2 + SR2 + Status register 2 + 0x18 + 0x20 + read-only + 0x00000000 + + + PEC + acket error checking + register + 8 + 8 + + + DUALF + Dual flag (Slave mode) + 7 + 1 + + + SMBHOST + SMBus host header (Slave + mode) + 6 + 1 + + + SMBDEFAULT + SMBus device default address (Slave + mode) + 5 + 1 + + + GENCALL + General call address (Slave + mode) + 4 + 1 + + + TRA + Transmitter/receiver + 2 + 1 + + + BUSY + Bus busy + 1 + 1 + + + MSL + Master/slave + 0 + 1 + + + + + CCR + CCR + Clock control register + 0x1C + 0x20 + read-write + 0x00000000 + + + F_S + I2C master mode selection + 15 + 1 + + F_S + read-write + + Standard + Standard mode I2C + 0 + + + Fast + Fast mode I2C + 1 + + + + + DUTY + Fast mode duty cycle + 14 + 1 + + DUTY + read-write + + Duty2_1 + Duty cycle t_low/t_high = 2/1 + 0 + + + Duty16_9 + Duty cycle t_low/t_high = 16/9 + 1 + + + + + CCR + Clock control register in Fast/Standard + mode (Master mode) + 0 + 12 + + + 1 + 4095 + + + + + + + TRISE + TRISE + TRISE register + 0x20 + 0x20 + read-write + 0x00000002 + + + TRISE + Maximum rise time in Fast/Standard mode + (Master mode) + 0 + 6 + + + 0 + 63 + + + + + + + FLTR + FLTR register + 0x24 + read-write + 0x00000000 + + + ANOFF + Analog noise filter + 4 + 1 + + ANOFF + read-write + + Enabled + Analog noise filter enabled + 0 + + + Disabled + Analog noise filter disabled + 1 + + + + + DNF + Digital noise filter + 0 + 4 + + DNF + read-write + + NoFilter + Digital filter disabled + 0 + + + Filter1 + Digital filter enabled and filtering capability up to 1 tI2CCLK + 1 + + + Filter2 + Digital filter enabled and filtering capability up to 2 tI2CCLK + 2 + + + Filter3 + Digital filter enabled and filtering capability up to 3 tI2CCLK + 3 + + + Filter4 + Digital filter enabled and filtering capability up to 4 tI2CCLK + 4 + + + Filter5 + Digital filter enabled and filtering capability up to 5 tI2CCLK + 5 + + + Filter6 + Digital filter enabled and filtering capability up to 6 tI2CCLK + 6 + + + Filter7 + Digital filter enabled and filtering capability up to 7 tI2CCLK + 7 + + + Filter8 + Digital filter enabled and filtering capability up to 8 tI2CCLK + 8 + + + Filter9 + Digital filter enabled and filtering capability up to 9 tI2CCLK + 9 + + + Filter10 + Digital filter enabled and filtering capability up to 10 tI2CCLK + 10 + + + Filter11 + Digital filter enabled and filtering capability up to 11 tI2CCLK + 11 + + + Filter12 + Digital filter enabled and filtering capability up to 12 tI2CCLK + 12 + + + Filter13 + Digital filter enabled and filtering capability up to 13 tI2CCLK + 13 + + + Filter14 + Digital filter enabled and filtering capability up to 14 tI2CCLK + 14 + + + Filter15 + Digital filter enabled and filtering capability up to 15 tI2CCLK + 15 + + + + + + + + + I2S2ext + 0x40003400 + + I2C1_EV + I2C1 event interrupt + 31 + + + I2C1_ER + I2C1 error interrupt + 32 + + + + I2S3ext + 0x40004000 + + + SPI1 + Serial peripheral interface + SPI + 0x40013000 + + 0x0 + 0x400 + registers + + + + CR1 + CR1 + control register 1 + 0x0 + 0x20 + read-write + 0x00000000 + + + BIDIMODE + Bidirectional data mode + enable + 15 + 1 + + BIDIMODE + read-write + + Unidirectional + 2-line unidirectional data mode selected + 0 + + + Bidirectional + 1-line bidirectional data mode selected + 1 + + + + + BIDIOE + Output enable in bidirectional + mode + 14 + 1 + + BIDIOE + read-write + + OutputDisabled + Output disabled (receive-only mode) + 0 + + + OutputEnabled + Output enabled (transmit-only mode) + 1 + + + + + CRCEN + Hardware CRC calculation + enable + 13 + 1 + + CRCEN + read-write + + Disabled + CRC calculation disabled + 0 + + + Enabled + CRC calculation enabled + 1 + + + + + CRCNEXT + CRC transfer next + 12 + 1 + + CRCNEXT + read-write + + TxBuffer + Next transmit value is from Tx buffer + 0 + + + CRC + Next transmit value is from Tx CRC register + 1 + + + + + DFF + Data frame format + 11 + 1 + + DFF + read-write + + EightBit + 8-bit data frame format is selected for transmission/reception + 0 + + + SixteenBit + 16-bit data frame format is selected for transmission/reception + 1 + + + + + RXONLY + Receive only + 10 + 1 + + RXONLY + read-write + + FullDuplex + Full duplex (Transmit and receive) + 0 + + + OutputDisabled + Output disabled (Receive-only mode) + 1 + + + + + SSM + Software slave management + 9 + 1 + + SSM + read-write + + Disabled + Software slave management disabled + 0 + + + Enabled + Software slave management enabled + 1 + + + + + SSI + Internal slave select + 8 + 1 + + SSI + read-write + + SlaveSelected + 0 is forced onto the NSS pin and the I/O value of the NSS pin is ignored + 0 + + + SlaveNotSelected + 1 is forced onto the NSS pin and the I/O value of the NSS pin is ignored + 1 + + + + + LSBFIRST + Frame format + 7 + 1 + + LSBFIRST + read-write + + MSBFirst + Data is transmitted/received with the MSB first + 0 + + + LSBFirst + Data is transmitted/received with the LSB first + 1 + + + + + SPE + SPI enable + 6 + 1 + + SPE + read-write + + Disabled + Peripheral disabled + 0 + + + Enabled + Peripheral enabled + 1 + + + + + BR + Baud rate control + 3 + 3 + + BR + read-write + + Div2 + f_PCLK / 2 + 0 + + + Div4 + f_PCLK / 4 + 1 + + + Div8 + f_PCLK / 8 + 2 + + + Div16 + f_PCLK / 16 + 3 + + + Div32 + f_PCLK / 32 + 4 + + + Div64 + f_PCLK / 64 + 5 + + + Div128 + f_PCLK / 128 + 6 + + + Div256 + f_PCLK / 256 + 7 + + + + + MSTR + Master selection + 2 + 1 + + MSTR + read-write + + Slave + Slave configuration + 0 + + + Master + Master configuration + 1 + + + + + CPOL + Clock polarity + 1 + 1 + + CPOL + read-write + + IdleLow + CK to 0 when idle + 0 + + + IdleHigh + CK to 1 when idle + 1 + + + + + CPHA + Clock phase + 0 + 1 + + CPHA + read-write + + FirstEdge + The first clock transition is the first data capture edge + 0 + + + SecondEdge + The second clock transition is the first data capture edge + 1 + + + + + + + CR2 + CR2 + control register 2 + 0x4 + 0x20 + read-write + 0x00000000 + + + TXEIE + Tx buffer empty interrupt + enable + 7 + 1 + + TXEIE + read-write + + Masked + TXE interrupt masked + 0 + + + NotMasked + TXE interrupt not masked + 1 + + + + + RXNEIE + RX buffer not empty interrupt + enable + 6 + 1 + + RXNEIE + read-write + + Masked + RXE interrupt masked + 0 + + + NotMasked + RXE interrupt not masked + 1 + + + + + ERRIE + Error interrupt enable + 5 + 1 + + ERRIE + read-write + + Masked + Error interrupt masked + 0 + + + NotMasked + Error interrupt not masked + 1 + + + + + FRF + Frame format + 4 + 1 + + FRF + read-write + + Motorola + SPI Motorola mode + 0 + + + TI + SPI TI mode + 1 + + + + + SSOE + SS output enable + 2 + 1 + + SSOE + read-write + + Disabled + SS output is disabled in master mode + 0 + + + Enabled + SS output is enabled in master mode + 1 + + + + + TXDMAEN + Tx buffer DMA enable + 1 + 1 + + TXDMAEN + read-write + + Disabled + Tx buffer DMA disabled + 0 + + + Enabled + Tx buffer DMA enabled + 1 + + + + + RXDMAEN + Rx buffer DMA enable + 0 + 1 + + RXDMAEN + read-write + + Disabled + Rx buffer DMA disabled + 0 + + + Enabled + Rx buffer DMA enabled + 1 + + + + + + + SR + SR + status register + 0x8 + 0x20 + 0x00000002 + + + FRE + TI frame format error + 8 + 1 + read-only + + FRER + read + + NoError + No frame format error + 0 + + + Error + A frame format error occurred + 1 + + + + + BSY + Busy flag + 7 + 1 + read-only + + BSYR + read + + NotBusy + SPI not busy + 0 + + + Busy + SPI busy + 1 + + + + + OVR + Overrun flag + 6 + 1 + read-only + + OVRR + read + + NoOverrun + No overrun occurred + 0 + + + Overrun + Overrun occurred + 1 + + + + + MODF + Mode fault + 5 + 1 + read-only + + MODFR + read + + NoFault + No mode fault occurred + 0 + + + Fault + Mode fault occurred + 1 + + + + + CRCERR + CRC error flag + 4 + 1 + read-write + zeroToClear + + CRCERRR + read + + Match + CRC value received matches the SPIx_RXCRCR value + 0 + + + NoMatch + CRC value received does not match the SPIx_RXCRCR value + 1 + + + + CRCERRW + write + + Clear + Clear flag + 0 + + + + + UDR + Underrun flag + 3 + 1 + read-only + + UDRR + read + + NoUnderrun + No underrun occurred + 0 + + + Underrun + Underrun occurred + 1 + + + + + CHSIDE + Channel side + 2 + 1 + read-only + + CHSIDE + read + + Left + Channel left has to be transmitted or has been received + 0 + + + Right + Channel right has to be transmitted or has been received + 1 + + + + + TXE + Transmit buffer empty + 1 + 1 + read-only + + TXE + read + + NotEmpty + Tx buffer not empty + 0 + + + Empty + Tx buffer empty + 1 + + + + + RXNE + Receive buffer not empty + 0 + 1 + read-only + + RXNE + read + + Empty + Rx buffer empty + 0 + + + NotEmpty + Rx buffer not empty + 1 + + + + + + + DR + DR + data register + 0xC + 0x20 + read-write + 0x00000000 + + + DR + Data register + 0 + 16 + + + 0 + 65535 + + + + + + + CRCPR + CRCPR + CRC polynomial register + 0x10 + 0x20 + read-write + 0x00000007 + + + CRCPOLY + CRC polynomial register + 0 + 16 + + + 0 + 65535 + + + + + + + RXCRCR + RXCRCR + RX CRC register + 0x14 + 0x20 + read-only + 0x00000000 + + + RxCRC + Rx CRC register + 0 + 16 + + + 0 + 65535 + + + + + + + TXCRCR + TXCRCR + TX CRC register + 0x18 + 0x20 + read-only + 0x00000000 + + + TxCRC + Tx CRC register + 0 + 16 + + + 0 + 65535 + + + + + + + I2SCFGR + I2SCFGR + I2S configuration register + 0x1C + 0x20 + read-write + 0x00000000 + + + I2SMOD + I2S mode selection + 11 + 1 + + I2SMOD + read-write + + SPIMode + SPI mode is selected + 0 + + + I2SMode + I2S mode is selected + 1 + + + + + I2SE + I2S Enable + 10 + 1 + + I2SE + read-write + + Disabled + I2S peripheral is disabled + 0 + + + Enabled + I2S peripheral is enabled + 1 + + + + + I2SCFG + I2S configuration mode + 8 + 2 + + I2SCFG + read-write + + SlaveTx + Slave - transmit + 0 + + + SlaveRx + Slave - receive + 1 + + + MasterTx + Master - transmit + 2 + + + MasterRx + Master - receive + 3 + + + + + PCMSYNC + PCM frame synchronization + 7 + 1 + + PCMSYNC + read-write + + Short + Short frame synchronisation + 0 + + + Long + Long frame synchronisation + 1 + + + + + I2SSTD + I2S standard selection + 4 + 2 + + I2SSTD + read-write + + Philips + I2S Philips standard + 0 + + + MSB + MSB justified standard + 1 + + + LSB + LSB justified standard + 2 + + + PCM + PCM standard + 3 + + + + + CKPOL + Steady state clock + polarity + 3 + 1 + + CKPOL + read-write + + IdleLow + I2S clock inactive state is low level + 0 + + + IdleHigh + I2S clock inactive state is high level + 1 + + + + + DATLEN + Data length to be + transferred + 1 + 2 + + DATLEN + read-write + + SixteenBit + 16-bit data length + 0 + + + TwentyFourBit + 24-bit data length + 1 + + + ThirtyTwoBit + 32-bit data length + 2 + + + + + CHLEN + Channel length (number of bits per audio + channel) + 0 + 1 + + CHLEN + read-write + + SixteenBit + 16-bit wide + 0 + + + ThirtyTwoBit + 32-bit wide + 1 + + + + + + + I2SPR + I2SPR + I2S prescaler register + 0x20 + 0x20 + read-write + 0x0000000A + + + MCKOE + Master clock output enable + 9 + 1 + + MCKOE + read-write + + Disabled + Master clock output is disabled + 0 + + + Enabled + Master clock output is enabled + 1 + + + + + ODD + Odd factor for the + prescaler + 8 + 1 + + ODD + read-write + + Even + Real divider value is I2SDIV * 2 + 0 + + + Odd + Real divider value is (I2SDIV * 2) + 1 + 1 + + + + + I2SDIV + I2S Linear prescaler + 0 + 8 + + + 2 + 255 + + + + + + + + + SPI2 + 0x40003800 + + SPI1 + SPI1 global interrupt + 35 + + + + SPI3 + 0x40003C00 + + SPI2 + SPI2 global interrupt + 36 + + + + SPI4 + 0x40013400 + + SPI3 + SPI3 global interrupt + 51 + + + + NVIC + Nested Vectored Interrupt + Controller + NVIC + 0xE000E100 + + 0x0 + 0x351 + registers + + + + ISER0 + ISER0 + Interrupt Set-Enable Register + 0x0 + 0x20 + read-write + 0x00000000 + + + SETENA + SETENA + 0 + 32 + + + + + ISER1 + ISER1 + Interrupt Set-Enable Register + 0x4 + 0x20 + read-write + 0x00000000 + + + SETENA + SETENA + 0 + 32 + + + + + ISER2 + ISER2 + Interrupt Set-Enable Register + 0x8 + 0x20 + read-write + 0x00000000 + + + SETENA + SETENA + 0 + 32 + + + + + ICER0 + ICER0 + Interrupt Clear-Enable + Register + 0x80 + 0x20 + read-write + 0x00000000 + + + CLRENA + CLRENA + 0 + 32 + + + + + ICER1 + ICER1 + Interrupt Clear-Enable + Register + 0x84 + 0x20 + read-write + 0x00000000 + + + CLRENA + CLRENA + 0 + 32 + + + + + ICER2 + ICER2 + Interrupt Clear-Enable + Register + 0x88 + 0x20 + read-write + 0x00000000 + + + CLRENA + CLRENA + 0 + 32 + + + + + ISPR0 + ISPR0 + Interrupt Set-Pending Register + 0x100 + 0x20 + read-write + 0x00000000 + + + SETPEND + SETPEND + 0 + 32 + + + + + ISPR1 + ISPR1 + Interrupt Set-Pending Register + 0x104 + 0x20 + read-write + 0x00000000 + + + SETPEND + SETPEND + 0 + 32 + + + + + ISPR2 + ISPR2 + Interrupt Set-Pending Register + 0x108 + 0x20 + read-write + 0x00000000 + + + SETPEND + SETPEND + 0 + 32 + + + + + ICPR0 + ICPR0 + Interrupt Clear-Pending + Register + 0x180 + 0x20 + read-write + 0x00000000 + + + CLRPEND + CLRPEND + 0 + 32 + + + + + ICPR1 + ICPR1 + Interrupt Clear-Pending + Register + 0x184 + 0x20 + read-write + 0x00000000 + + + CLRPEND + CLRPEND + 0 + 32 + + + + + ICPR2 + ICPR2 + Interrupt Clear-Pending + Register + 0x188 + 0x20 + read-write + 0x00000000 + + + CLRPEND + CLRPEND + 0 + 32 + + + + + IABR0 + IABR0 + Interrupt Active Bit Register + 0x200 + 0x20 + read-only + 0x00000000 + + + ACTIVE + ACTIVE + 0 + 32 + + + + + IABR1 + IABR1 + Interrupt Active Bit Register + 0x204 + 0x20 + read-only + 0x00000000 + + + ACTIVE + ACTIVE + 0 + 32 + + + + + IABR2 + IABR2 + Interrupt Active Bit Register + 0x208 + 0x20 + read-only + 0x00000000 + + + ACTIVE + ACTIVE + 0 + 32 + + + + + IPR0 + IPR0 + Interrupt Priority Register + 0x300 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR1 + IPR1 + Interrupt Priority Register + 0x304 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR2 + IPR2 + Interrupt Priority Register + 0x308 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR3 + IPR3 + Interrupt Priority Register + 0x30C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR4 + IPR4 + Interrupt Priority Register + 0x310 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR5 + IPR5 + Interrupt Priority Register + 0x314 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR6 + IPR6 + Interrupt Priority Register + 0x318 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR7 + IPR7 + Interrupt Priority Register + 0x31C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR8 + IPR8 + Interrupt Priority Register + 0x320 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR9 + IPR9 + Interrupt Priority Register + 0x324 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR10 + IPR10 + Interrupt Priority Register + 0x328 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR11 + IPR11 + Interrupt Priority Register + 0x32C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR12 + IPR12 + Interrupt Priority Register + 0x330 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR13 + IPR13 + Interrupt Priority Register + 0x334 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR14 + IPR14 + Interrupt Priority Register + 0x338 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR15 + IPR15 + Interrupt Priority Register + 0x33C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR16 + IPR16 + Interrupt Priority Register + 0x340 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR17 + IPR17 + Interrupt Priority Register + 0x344 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR18 + IPR18 + Interrupt Priority Register + 0x348 + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + IPR19 + IPR19 + Interrupt Priority Register + 0x34C + 0x20 + read-write + 0x00000000 + + + IPR_N0 + IPR_N0 + 0 + 8 + + + IPR_N1 + IPR_N1 + 8 + 8 + + + IPR_N2 + IPR_N2 + 16 + 8 + + + IPR_N3 + IPR_N3 + 24 + 8 + + + + + + + FPU + Floting point unit + FPU + 0xE000EF34 + + 0x0 + 0xD + registers + + + FPU + Floating point unit interrupt + 81 + + + + FPCCR + FPCCR + Floating-point context control + register + 0x0 + 0x20 + read-write + 0x00000000 + + + LSPACT + LSPACT + 0 + 1 + + + USER + USER + 1 + 1 + + + THREAD + THREAD + 3 + 1 + + + HFRDY + HFRDY + 4 + 1 + + + MMRDY + MMRDY + 5 + 1 + + + BFRDY + BFRDY + 6 + 1 + + + MONRDY + MONRDY + 8 + 1 + + + LSPEN + LSPEN + 30 + 1 + + + ASPEN + ASPEN + 31 + 1 + + + + + FPCAR + FPCAR + Floating-point context address + register + 0x4 + 0x20 + read-write + 0x00000000 + + + ADDRESS + Location of unpopulated + floating-point + 3 + 29 + + + + + FPSCR + FPSCR + Floating-point status control + register + 0x8 + 0x20 + read-write + 0x00000000 + + + IOC + Invalid operation cumulative exception + bit + 0 + 1 + + + DZC + Division by zero cumulative exception + bit. + 1 + 1 + + + OFC + Overflow cumulative exception + bit + 2 + 1 + + + UFC + Underflow cumulative exception + bit + 3 + 1 + + + IXC + Inexact cumulative exception + bit + 4 + 1 + + + IDC + Input denormal cumulative exception + bit. + 7 + 1 + + + RMode + Rounding Mode control + field + 22 + 2 + + + FZ + Flush-to-zero mode control + bit: + 24 + 1 + + + DN + Default NaN mode control + bit + 25 + 1 + + + AHP + Alternative half-precision control + bit + 26 + 1 + + + V + Overflow condition code + flag + 28 + 1 + + + C + Carry condition code flag + 29 + 1 + + + Z + Zero condition code flag + 30 + 1 + + + N + Negative condition code + flag + 31 + 1 + + + + + + + MPU + Memory protection unit + MPU + 0xE000ED90 + + 0x0 + 0x15 + registers + + + + TYPER + TYPER + MPU type register + 0x0 + 0x20 + read-only + 0x00000800 + + + SEPARATE + Separate flag + 0 + 1 + + + DREGION + Number of MPU data regions + 8 + 8 + + + IREGION + Number of MPU instruction + regions + 16 + 8 + + + + + CTRL + CTRL + MPU control register + 0x4 + 0x20 + read-only + 0x00000000 + + + ENABLE + Enables the MPU + 0 + 1 + + + HFNMIENA + Enables the operation of MPU during hard + fault + 1 + 1 + + + PRIVDEFENA + Enable priviliged software access to + default memory map + 2 + 1 + + + + + RNR + RNR + MPU region number register + 0x8 + 0x20 + read-write + 0x00000000 + + + REGION + MPU region + 0 + 8 + + + + + RBAR + RBAR + MPU region base address + register + 0xC + 0x20 + read-write + 0x00000000 + + + REGION + MPU region field + 0 + 4 + + + VALID + MPU region number valid + 4 + 1 + + + ADDR + Region base address field + 5 + 27 + + + + + RASR + RASR + MPU region attribute and size + register + 0x10 + 0x20 + read-write + 0x00000000 + + + ENABLE + Region enable bit. + 0 + 1 + + + SIZE + Size of the MPU protection + region + 1 + 5 + + + SRD + Subregion disable bits + 8 + 8 + + + B + memory attribute + 16 + 1 + + + C + memory attribute + 17 + 1 + + + S + Shareable memory attribute + 18 + 1 + + + TEX + memory attribute + 19 + 3 + + + AP + Access permission + 24 + 3 + + + XN + Instruction access disable + bit + 28 + 1 + + + + + + + STK + SysTick timer + STK + 0xE000E010 + + 0x0 + 0x11 + registers + + + + CTRL + CTRL + SysTick control and status + register + 0x0 + 0x20 + read-write + 0x00000000 + + + ENABLE + Counter enable + 0 + 1 + + + TICKINT + SysTick exception request + enable + 1 + 1 + + + CLKSOURCE + Clock source selection + 2 + 1 + + + COUNTFLAG + COUNTFLAG + 16 + 1 + + + + + LOAD + LOAD + SysTick reload value register + 0x4 + 0x20 + read-write + 0x00000000 + + + RELOAD + RELOAD value + 0 + 24 + + + + + VAL + VAL + SysTick current value register + 0x8 + 0x20 + read-write + 0x00000000 + + + CURRENT + Current counter value + 0 + 24 + + + + + CALIB + CALIB + SysTick calibration value + register + 0xC + 0x20 + read-write + 0x00000000 + + + TENMS + Calibration value + 0 + 24 + + + SKEW + SKEW flag: Indicates whether the TENMS + value is exact + 30 + 1 + + + NOREF + NOREF flag. Reads as zero + 31 + 1 + + + + + + + SCB + System control block + SCB + 0xE000ED00 + + 0x0 + 0x41 + registers + + + + CPUID + CPUID + CPUID base register + 0x0 + 0x20 + read-only + 0x410FC241 + + + Revision + Revision number + 0 + 4 + + + PartNo + Part number of the + processor + 4 + 12 + + + Constant + Reads as 0xF + 16 + 4 + + + Variant + Variant number + 20 + 4 + + + Implementer + Implementer code + 24 + 8 + + + + + ICSR + ICSR + Interrupt control and state + register + 0x4 + 0x20 + read-write + 0x00000000 + + + VECTACTIVE + Active vector + 0 + 9 + + + RETTOBASE + Return to base level + 11 + 1 + + + VECTPENDING + Pending vector + 12 + 7 + + + ISRPENDING + Interrupt pending flag + 22 + 1 + + + PENDSTCLR + SysTick exception clear-pending + bit + 25 + 1 + + + PENDSTSET + SysTick exception set-pending + bit + 26 + 1 + + + PENDSVCLR + PendSV clear-pending bit + 27 + 1 + + + PENDSVSET + PendSV set-pending bit + 28 + 1 + + + NMIPENDSET + NMI set-pending bit. + 31 + 1 + + + + + VTOR + VTOR + Vector table offset register + 0x8 + 0x20 + read-write + 0x00000000 + + + TBLOFF + Vector table base offset + field + 9 + 21 + + + + + AIRCR + AIRCR + Application interrupt and reset control + register + 0xC + 0x20 + read-write + 0x00000000 + + + VECTRESET + VECTRESET + 0 + 1 + + + VECTCLRACTIVE + VECTCLRACTIVE + 1 + 1 + + + SYSRESETREQ + SYSRESETREQ + 2 + 1 + + + PRIGROUP + PRIGROUP + 8 + 3 + + + ENDIANESS + ENDIANESS + 15 + 1 + + + VECTKEYSTAT + Register key + 16 + 16 + + + + + SCR + SCR + System control register + 0x10 + 0x20 + read-write + 0x00000000 + + + SLEEPONEXIT + SLEEPONEXIT + 1 + 1 + + + SLEEPDEEP + SLEEPDEEP + 2 + 1 + + + SEVEONPEND + Send Event on Pending bit + 4 + 1 + + + + + CCR + CCR + Configuration and control + register + 0x14 + 0x20 + read-write + 0x00000000 + + + NONBASETHRDENA + Configures how the processor enters + Thread mode + 0 + 1 + + + USERSETMPEND + USERSETMPEND + 1 + 1 + + + UNALIGN__TRP + UNALIGN_ TRP + 3 + 1 + + + DIV_0_TRP + DIV_0_TRP + 4 + 1 + + + BFHFNMIGN + BFHFNMIGN + 8 + 1 + + + STKALIGN + STKALIGN + 9 + 1 + + + + + SHPR1 + SHPR1 + System handler priority + registers + 0x18 + 0x20 + read-write + 0x00000000 + + + PRI_4 + Priority of system handler + 4 + 0 + 8 + + + PRI_5 + Priority of system handler + 5 + 8 + 8 + + + PRI_6 + Priority of system handler + 6 + 16 + 8 + + + + + SHPR2 + SHPR2 + System handler priority + registers + 0x1C + 0x20 + read-write + 0x00000000 + + + PRI_11 + Priority of system handler + 11 + 24 + 8 + + + + + SHPR3 + SHPR3 + System handler priority + registers + 0x20 + 0x20 + read-write + 0x00000000 + + + PRI_14 + Priority of system handler + 14 + 16 + 8 + + + PRI_15 + Priority of system handler + 15 + 24 + 8 + + + + + SHCRS + SHCRS + System handler control and state + register + 0x24 + 0x20 + read-write + 0x00000000 + + + MEMFAULTACT + Memory management fault exception active + bit + 0 + 1 + + + BUSFAULTACT + Bus fault exception active + bit + 1 + 1 + + + USGFAULTACT + Usage fault exception active + bit + 3 + 1 + + + SVCALLACT + SVC call active bit + 7 + 1 + + + MONITORACT + Debug monitor active bit + 8 + 1 + + + PENDSVACT + PendSV exception active + bit + 10 + 1 + + + SYSTICKACT + SysTick exception active + bit + 11 + 1 + + + USGFAULTPENDED + Usage fault exception pending + bit + 12 + 1 + + + MEMFAULTPENDED + Memory management fault exception + pending bit + 13 + 1 + + + BUSFAULTPENDED + Bus fault exception pending + bit + 14 + 1 + + + SVCALLPENDED + SVC call pending bit + 15 + 1 + + + MEMFAULTENA + Memory management fault enable + bit + 16 + 1 + + + BUSFAULTENA + Bus fault enable bit + 17 + 1 + + + USGFAULTENA + Usage fault enable bit + 18 + 1 + + + + + CFSR_UFSR_BFSR_MMFSR + CFSR_UFSR_BFSR_MMFSR + Configurable fault status + register + 0x28 + 0x20 + read-write + 0x00000000 + + + IACCVIOL + Instruction access violation + flag + 1 + 1 + + + MUNSTKERR + Memory manager fault on unstacking for a + return from exception + 3 + 1 + + + MSTKERR + Memory manager fault on stacking for + exception entry. + 4 + 1 + + + MLSPERR + MLSPERR + 5 + 1 + + + MMARVALID + Memory Management Fault Address Register + (MMAR) valid flag + 7 + 1 + + + IBUSERR + Instruction bus error + 8 + 1 + + + PRECISERR + Precise data bus error + 9 + 1 + + + IMPRECISERR + Imprecise data bus error + 10 + 1 + + + UNSTKERR + Bus fault on unstacking for a return + from exception + 11 + 1 + + + STKERR + Bus fault on stacking for exception + entry + 12 + 1 + + + LSPERR + Bus fault on floating-point lazy state + preservation + 13 + 1 + + + BFARVALID + Bus Fault Address Register (BFAR) valid + flag + 15 + 1 + + + UNDEFINSTR + Undefined instruction usage + fault + 16 + 1 + + + INVSTATE + Invalid state usage fault + 17 + 1 + + + INVPC + Invalid PC load usage + fault + 18 + 1 + + + NOCP + No coprocessor usage + fault. + 19 + 1 + + + UNALIGNED + Unaligned access usage + fault + 24 + 1 + + + DIVBYZERO + Divide by zero usage fault + 25 + 1 + + + + + HFSR + HFSR + Hard fault status register + 0x2C + 0x20 + read-write + 0x00000000 + + + VECTTBL + Vector table hard fault + 1 + 1 + + + FORCED + Forced hard fault + 30 + 1 + + + DEBUG_VT + Reserved for Debug use + 31 + 1 + + + + + MMFAR + MMFAR + Memory management fault address + register + 0x34 + 0x20 + read-write + 0x00000000 + + + MMFAR + Memory management fault + address + 0 + 32 + + + + + BFAR + BFAR + Bus fault address register + 0x38 + 0x20 + read-write + 0x00000000 + + + BFAR + Bus fault address + 0 + 32 + + + + + AFSR + AFSR + Auxiliary fault status + register + 0x3C + 0x20 + read-write + 0x00000000 + + + IMPDEF + Implementation defined + 0 + 32 + + + + + + + NVIC_STIR + Nested vectored interrupt + controller + NVIC + 0xE000EF00 + + 0x0 + 0x5 + registers + + + + STIR + STIR + Software trigger interrupt + register + 0x0 + 0x20 + read-write + 0x00000000 + + + INTID + Software generated interrupt + ID + 0 + 9 + + + + + + + FPU_CPACR + Floating point unit CPACR + FPU + 0xE000ED88 + + 0x0 + 0x5 + registers + + + + CPACR + CPACR + Coprocessor access control + register + 0x0 + 0x20 + read-write + 0x00000000 + + + CP + CP + 20 + 4 + + + + + + + SCB_ACTRL + System control block ACTLR + SCB + 0xE000E008 + + 0x0 + 0x5 + registers + + + + ACTRL + ACTRL + Auxiliary control register + 0x0 + 0x20 + read-write + 0x00000000 + + + DISMCYCINT + DISMCYCINT + 0 + 1 + + + DISDEFWBUF + DISDEFWBUF + 1 + 1 + + + DISFOLD + DISFOLD + 2 + 1 + + + DISFPCA + DISFPCA + 8 + 1 + + + DISOOFP + DISOOFP + 9 + 1 + + + + + + + \ No newline at end of file diff --git a/nodes/embassy/test-wiznet/.cargo/config.toml b/nodes/embassy/test-wiznet/.cargo/config.toml new file mode 100644 index 00000000..b0f2a66e --- /dev/null +++ b/nodes/embassy/test-wiznet/.cargo/config.toml @@ -0,0 +1,18 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +# replace STM32F103C8 with your chip as listed in `probe-rs chip list` +# runner = "probe-rs run --chip STM32F103C8" +# runner = "probe-rs run --chip STM32F401CCUx --host ws://192.168.1.43:3000 --token secret_token_redacted --probe c251:f001:202108120001" +runner = "probe-rs run --chip STM32F401CCUx" +linker = "flip-link" + +[build] +# target = "thumbv7m-none-eabi" for f103 +target = "thumbv7em-none-eabihf" + +[env] +DEFMT_LOG = "debug,sps30_async=warn,bosch_bme680=info" +EMBASSY_EXECUTOR_TASK_ARENA_SIZE="10900" + +# [unstable] +# build-std = ["core"] +# build-std-features = ["panic_immediate_abort"] diff --git a/nodes/embassy/test-wiznet/Cargo.lock b/nodes/embassy/test-wiznet/Cargo.lock new file mode 100644 index 00000000..50cd7987 --- /dev/null +++ b/nodes/embassy/test-wiznet/Cargo.lock @@ -0,0 +1,1274 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aligned" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "377e4c0ba83e4431b10df45c1d4666f178ea9c552cac93e60c3a88bf32785923" +dependencies = [ + "as-slice", +] + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + +[[package]] +name = "bed-sensors" +version = "0.2.0" +dependencies = [ + "bosch-bme680", + "cortex-m", + "cortex-m-rt", + "defmt", + "defmt-rtt", + "embassy-embedded-hal", + "embassy-executor", + "embassy-futures", + "embassy-stm32", + "embassy-sync", + "embassy-time", + "embassy-usb", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-bus", + "embedded-io-async", + "futures", + "heapless 0.8.0", + "max44009", + "mhzx", + "nau7802-async", + "nb 1.1.0", + "panic-probe", + "protocol", + "rand", + "sht31", + "sps30-async", + "static_cell", +] + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "bitfield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "block-device-driver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c051592f59fe68053524b4c4935249b806f72c1f544cfb7abe4f57c3be258e" +dependencies = [ + "aligned", +] + +[[package]] +name = "bosch-bme680" +version = "1.0.2" +dependencies = [ + "bitfield 0.14.0", + "defmt", + "embedded-hal 1.0.0", + "embedded-hal-async", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal", + "bitfield 0.13.2", + "critical-section", + "embedded-hal 0.2.7", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "critical-section" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.77", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "defmt" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb" +dependencies = [ + "defmt-parser", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "defmt-parser" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" +dependencies = [ + "thiserror", +] + +[[package]] +name = "defmt-rtt" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab697b3dbbc1750b7c8b821aa6f6e7f2480b47a99bc057a2ed7b170ebef0c51" +dependencies = [ + "critical-section", + "defmt", +] + +[[package]] +name = "document-features" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" +dependencies = [ + "litrs", +] + +[[package]] +name = "embassy-embedded-hal" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "defmt", + "embassy-futures", + "embassy-sync", + "embassy-time", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-storage", + "embedded-storage-async", + "nb 1.1.0", +] + +[[package]] +name = "embassy-executor" +version = "0.6.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "cortex-m", + "critical-section", + "defmt", + "document-features", + "embassy-executor-macros", + "embassy-time-driver", + "embassy-time-queue-driver", +] + +[[package]] +name = "embassy-executor-macros" +version = "0.5.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "embassy-futures" +version = "0.1.1" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" + +[[package]] +name = "embassy-hal-internal" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "cortex-m", + "critical-section", + "defmt", + "num-traits", +] + +[[package]] +name = "embassy-net-driver" +version = "0.2.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "defmt", +] + +[[package]] +name = "embassy-net-driver-channel" +version = "0.3.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "embassy-futures", + "embassy-net-driver", + "embassy-sync", +] + +[[package]] +name = "embassy-stm32" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "aligned", + "bit_field", + "bitflags 2.6.0", + "block-device-driver", + "cfg-if", + "cortex-m", + "cortex-m-rt", + "critical-section", + "defmt", + "document-features", + "embassy-embedded-hal", + "embassy-futures", + "embassy-hal-internal", + "embassy-net-driver", + "embassy-sync", + "embassy-time", + "embassy-time-driver", + "embassy-usb-driver", + "embassy-usb-synopsys-otg", + "embedded-can", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-nb", + "embedded-io", + "embedded-io-async", + "embedded-storage", + "embedded-storage-async", + "futures-util", + "nb 1.1.0", + "proc-macro2", + "quote", + "rand_core", + "sdio-host", + "static_assertions", + "stm32-fmc", + "stm32-metapac", + "vcell", + "volatile-register", +] + +[[package]] +name = "embassy-sync" +version = "0.6.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "cfg-if", + "critical-section", + "defmt", + "embedded-io-async", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time" +version = "0.3.2" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "cfg-if", + "critical-section", + "defmt", + "document-features", + "embassy-time-driver", + "embassy-time-queue-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time-driver" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "document-features", +] + +[[package]] +name = "embassy-time-queue-driver" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" + +[[package]] +name = "embassy-usb" +version = "0.3.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "defmt", + "embassy-futures", + "embassy-net-driver-channel", + "embassy-sync", + "embassy-usb-driver", + "heapless 0.8.0", + "ssmarshal", + "usbd-hid", +] + +[[package]] +name = "embassy-usb-driver" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "defmt", +] + +[[package]] +name = "embassy-usb-synopsys-otg" +version = "0.1.0" +source = "git+https://github.com/embassy-rs/embassy?rev=d7780fc#d7780fcf83a8a35d7b09e5df7b62dd8218436715" +dependencies = [ + "critical-section", + "embassy-sync", + "embassy-usb-driver", +] + +[[package]] +name = "embedded-can" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "defmt", + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-hal-bus" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d3980bf28e8577db59fe2bdb3df868a419469d2cecb363644eea2b6f7797669" +dependencies = [ + "critical-section", + "defmt", + "embedded-hal 1.0.0", + "embedded-hal-async", + "portable-atomic", +] + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" +dependencies = [ + "embedded-hal 1.0.0", + "nb 1.1.0", +] + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" +dependencies = [ + "defmt", +] + +[[package]] +name = "embedded-io-async" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" +dependencies = [ + "defmt", + "embedded-io", +] + +[[package]] +name = "embedded-storage" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" + +[[package]] +name = "embedded-storage-async" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc" +dependencies = [ + "embedded-storage", +] + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-macro", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version 0.4.1", + "serde", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "defmt", + "hash32 0.3.1", + "serde", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "max44009" +version = "0.2.0" +source = "git+https://github.com/dvdsk/max44009-rs#7b7df2e3173476c250fca3eb242f0dd366857599" +dependencies = [ + "defmt", + "embedded-hal-async", +] + +[[package]] +name = "mhzx" +version = "0.3.0" +dependencies = [ + "defmt", + "embedded-io-async", + "heapless 0.8.0", + "postcard", + "serde", +] + +[[package]] +name = "nau7802-async" +version = "0.2.0" +dependencies = [ + "byteorder", + "defmt", + "embedded-hal-async", + "postcard", + "serde", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "panic-probe" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4047d9235d1423d66cc97da7d07eddb54d4f154d6c13805c6d0793956f4f25b0" +dependencies = [ + "cortex-m", + "defmt", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "portable-atomic" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce" + +[[package]] +name = "postcard" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" +dependencies = [ + "cobs", + "defmt", + "heapless 0.7.17", + "postcard-derive", + "serde", +] + +[[package]] +name = "postcard-derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0239fa9c1d225d4b7eb69925c25c5e082307a141e470573fbbe3a817ce6a7a37" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "protocol" +version = "0.1.0" +dependencies = [ + "defmt", + "heapless 0.8.0", + "postcard", + "serde", + "strum", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver 1.0.23", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sdio-host" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93c025f9cfe4c388c328ece47d11a54a823da3b5ad0370b22d95ad47137f85a" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "sht31" +version = "0.3.1" +source = "git+https://github.com/dvdsk/SHT31-rs#a7b6bd94fb137e16bf326eff5fb591624369a2cf" +dependencies = [ + "crc", + "defmt", + "embedded-hal-async", + "postcard", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "sps30-async" +version = "0.3.0" +dependencies = [ + "defmt", + "embedded-hal-async", + "embedded-io-async", + "futures", + "heapless 0.8.0", + "postcard", + "serde", +] + +[[package]] +name = "ssmarshal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3e6ad23b128192ed337dfa4f1b8099ced0c2bf30d61e551b65fda5916dbb850" +dependencies = [ + "encode_unicode", + "serde", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "static_cell" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89b0684884a883431282db1e4343f34afc2ff6996fe1f4a1664519b66e14c1e" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "stm32-fmc" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f0639399e2307c2446c54d91d4f1596343a1e1d5cab605b9cce11d0ab3858c" +dependencies = [ + "embedded-hal 0.2.7", +] + +[[package]] +name = "stm32-metapac" +version = "15.0.0" +source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-ad00827345b4b758b2453082809d6e3b634b5364#e442835159a7a311410cd4a2879da52c6f57af52" +dependencies = [ + "cortex-m", + "cortex-m-rt", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.77", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "usb-device" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98816b1accafbb09085168b90f27e93d790b4bfa19d883466b5e53315b5f06a6" +dependencies = [ + "heapless 0.8.0", + "portable-atomic", +] + +[[package]] +name = "usbd-hid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6f291ab53d428685cc780f08a2eb9d5d6ff58622db2b36e239a4f715f1e184c" +dependencies = [ + "serde", + "ssmarshal", + "usb-device", + "usbd-hid-macros", +] + +[[package]] +name = "usbd-hid-descriptors" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee54712c5d778d2fb2da43b1ce5a7b5060886ef7b09891baeb4bf36910a3ed" +dependencies = [ + "bitfield 0.14.0", +] + +[[package]] +name = "usbd-hid-macros" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb573c76e7884035ac5e1ab4a81234c187a82b6100140af0ab45757650ccda38" +dependencies = [ + "byteorder", + "hashbrown", + "log", + "proc-macro2", + "quote", + "serde", + "syn 1.0.109", + "usbd-hid-descriptors", +] + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] diff --git a/nodes/embassy/test-wiznet/Cargo.toml b/nodes/embassy/test-wiznet/Cargo.toml new file mode 100644 index 00000000..d46b5c24 --- /dev/null +++ b/nodes/embassy/test-wiznet/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "test-wiznet" +version = "0.2.0" +rust-version.workspace = true +edition.workspace = true +license = "GPLv3" +authors = ["David Kleingeld & Eva van Houten"] + +[dependencies] +cortex-m.workspace = true +cortex-m-rt.workspace = true + +embassy-stm32.workspace = true +embassy-executor.workspace = true +embassy-net.workspace = true +embassy-net-wiznet.workspace = true +embassy-time.workspace = true + +defmt.workspace = true +defmt-rtt.workspace = true + +embedded-hal-bus.workspace = true +embedded-io-async.workspace = true + +panic-probe.workspace = true +static_cell = "2.0.0" +rand = { version = "0.8.5", default-features = false, features = ["small_rng"] } +heapless = { version = "0.8", default-features = false } diff --git a/nodes/embassy/test-wiznet/build.rs b/nodes/embassy/test-wiznet/build.rs new file mode 100644 index 00000000..8cd32d7e --- /dev/null +++ b/nodes/embassy/test-wiznet/build.rs @@ -0,0 +1,5 @@ +fn main() { + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tlink.x"); + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); +} diff --git a/nodes/embassy/test-wiznet/rust-toolchain.toml b/nodes/embassy/test-wiznet/rust-toolchain.toml new file mode 100644 index 00000000..c17f644e --- /dev/null +++ b/nodes/embassy/test-wiznet/rust-toolchain.toml @@ -0,0 +1,6 @@ +[toolchain] +channel = "stable" +components = [ "rust-src", "rustfmt", "llvm-tools" ] +targets = [ + "thumbv7em-none-eabihf", +] diff --git a/nodes/embassy/test-wiznet/src/main.rs b/nodes/embassy/test-wiznet/src/main.rs new file mode 100644 index 00000000..0e46455b --- /dev/null +++ b/nodes/embassy/test-wiznet/src/main.rs @@ -0,0 +1,134 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_net::{Ipv4Address, Ipv4Cidr, StackResources}; +use embassy_net_wiznet::{chip::W5500, Device, Runner, State}; +use embassy_stm32::exti::ExtiInput; +use embassy_stm32::gpio::{Level, Output, Pull, Speed}; +use embassy_stm32::mode::Async; +use embassy_stm32::peripherals::IWDG; +use embassy_stm32::spi::{Config as SpiConfig, Spi}; +use embassy_stm32::time::Hertz; +use embassy_stm32::wdg::IndependentWatchdog; +use embassy_stm32::Config; +use embassy_time::{Delay, Timer}; +use embedded_hal_bus::spi::ExclusiveDevice; +use heapless::Vec; +use static_cell::StaticCell; + +use defmt::{trace, unwrap}; +use {defmt_rtt as _, panic_probe as _}; + +mod network; +mod rng; + +type EthernetSPI = ExclusiveDevice, Output<'static>, Delay>; +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + W5500, + EthernetSPI, + ExtiInput<'static>, + Output<'static>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task( + mut runner: embassy_net::Runner<'static, Device<'static>>, +) -> ! { + runner.run().await +} + +// 84 Mhz clock stm32f401 +fn config() -> Config { + use embassy_stm32::rcc::{ + AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, + PllPreDiv, PllSource, Sysclk, + }; + + let mut config = Config::default(); + config.rcc.hse = Some(Hse { + freq: Hertz(25_000_000), + mode: HseMode::Oscillator, + }); + config.rcc.pll_src = PllSource::HSE; + config.rcc.pll = Some(Pll { + prediv: PllPreDiv::DIV25, + mul: PllMul::MUL336, + divp: Some(PllPDiv::DIV4), + divq: None, + divr: None, + }); + config.rcc.ahb_pre = AHBPrescaler::DIV1; + config.rcc.apb1_pre = APBPrescaler::DIV2; + config.rcc.apb2_pre = APBPrescaler::DIV1; + config.rcc.sys = Sysclk::PLL1_P; + config +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_stm32::init(config()); + let mut dog = IndependentWatchdog::new( + p.IWDG, 10_000_000, // microseconds + ); + dog.unleash(); + let seed = rng::generate_seed_blocking(p.ADC1).await; + defmt::info!("random seed: {}", seed); + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = Hertz(5_000_000); // Up to 50m works + let (miso, mosi, clk) = (p.PA6, p.PA7, p.PA5); + let spi = + Spi::new(p.SPI1, clk, mosi, miso, p.DMA2_CH3, p.DMA2_CH0, spi_cfg); + let cs = Output::new(p.PA4, Level::High, Speed::VeryHigh); + let spi = unwrap!(ExclusiveDevice::new(spi, cs, Delay)); + + let w5500_int = ExtiInput::new(p.PB0, p.EXTI0, Pull::Up); + let w5500_reset = Output::new(p.PB1, Level::High, Speed::Medium); + + let mac_addr = [0x02, 234, 3, 4, 82, 231]; + static STATE: StaticCell> = StaticCell::new(); + let state = STATE.init(State::<3, 2>::new()); + let (device, runner) = unwrap!( + embassy_net_wiznet::new(mac_addr, state, spi, w5500_int, w5500_reset) + .await + ); + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Init network stack + static RESOURCES: StaticCell> = StaticCell::new(); + let config = + embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { + address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 1, 7), 24), + gateway: Some(Ipv4Address::new(192, 168, 1, 1)), + dns_servers: Vec::new(), + }); + let (stack, runner) = embassy_net::new( + device, + config, + RESOURCES.init(StackResources::new()), + seed, + ); + + // Launch network task + unwrap!(spawner.spawn(net_task(runner))); + + let handle_network = network::handle(stack); + spawner.must_spawn(handle_network); + + keep_dog_happy(dog).await; +} + +async fn keep_dog_happy(mut dog: IndependentWatchdog<'_, IWDG>) { + loop { + Timer::after_secs(8).await; + trace!("petting dog"); + dog.pet(); + } +} diff --git a/nodes/embassy/test-wiznet/src/network.rs b/nodes/embassy/test-wiznet/src/network.rs new file mode 100644 index 00000000..419a18e9 --- /dev/null +++ b/nodes/embassy/test-wiznet/src/network.rs @@ -0,0 +1,60 @@ +use defmt::{debug, info, warn}; +use embassy_executor::task; +use embassy_net::tcp::TcpSocket; +use embassy_net::{Ipv4Address, Stack}; +use embassy_time::{Duration, Timer}; + +use embedded_io_async::Write; +use embedded_io_async::Read; + +#[task] +pub async fn handle( + stack: Stack<'static>, +) { + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + + let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(Duration::from_secs(5))); + socket.set_keep_alive(Some(Duration::from_secs(1))); + let host_addr = Ipv4Address::new(192, 168, 1, 43); + let host_port = 6969; + + let mut sequential_errors = 0; + + debug!("Configured socket and connecting"); + loop { + debug!("socket state: {:?}", socket.state()); + if let Err(e) = socket.connect((host_addr, host_port)).await { + if sequential_errors > 3 { + defmt::info!("failing to reconnect, resetting node"); + defmt::flush(); + Timer::after_secs(1).await; + cortex_m::peripheral::SCB::sys_reset(); + } + warn!("connect error: {}", e); + sequential_errors += 1; + Timer::after_secs(5).await; + continue; + } + + info!("(re-)connected"); + sequential_errors = 0; + // Prevent out-dated data from being send + + let mut buf = [0u8; 100]; + loop { + let Ok(_) = socket.read_exact(&mut buf).await else { + break + }; + let Ok(_) = socket.write_all(&buf).await else { + break + }; + } + + // Or the socket will hang for a while waiting to close this makes sure + // we can reconnect instantly + socket.abort(); + Timer::after_secs(60).await; // Experiment: does this help? + } +} diff --git a/nodes/embassy/test-wiznet/src/rng.rs b/nodes/embassy/test-wiznet/src/rng.rs new file mode 100644 index 00000000..f489557d --- /dev/null +++ b/nodes/embassy/test-wiznet/src/rng.rs @@ -0,0 +1,31 @@ +use embassy_stm32::peripherals::ADC1; +use embassy_time::Timer; +use rand::{RngCore, SeedableRng}; + +use embassy_stm32::adc::{Adc, Temperature, VrefInt}; +/// #Warning +/// Should only be called before async tasks are spawned. This takes a lot of +/// time to run and will disturb any async task running. +pub async fn generate_seed_blocking(adc: embassy_stm32::Peri<'_, ADC1>) -> u64 { + let mut adc = Adc::new(adc); + + let mut vrefint = adc.enable_vrefint(); + let mut temp = adc.enable_temperature(); + + // Startup delay can be combined to the maximum of either + Timer::after_micros(Temperature::start_time_us().max(VrefInt::start_time_us()) as u64).await; + + let mut seed = [0u8; 16]; + let mut bytes = seed.chunks_exact_mut(2); + while let Some([byte1, byte2]) = bytes.next() { + let sample = adc.blocking_read(&mut temp); + let most_noisy_byte = (sample & 0b0000_0000_1111_1111) as u8; + *byte1 = most_noisy_byte; + let sample = adc.blocking_read(&mut vrefint); + let most_noisy_byte = (sample & 0b0000_0000_1111_1111) as u8; + *byte2 = most_noisy_byte; + } + + let mut rng = rand::rngs::SmallRng::from_seed(seed); + rng.next_u64() +} From 6b29d913791e3bc39e45706c269b4fc6a28bffbb Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 13 Sep 2025 15:35:02 +0200 Subject: [PATCH 671/687] adds pir support to protocol, sensors and desk-sensors --- .../protocol/src/large_bedroom/desk_right.rs | 18 ++--- crates/protocol/src/lib.rs | 1 + crates/protocol/src/pir.rs | 43 ++++++++++++ nodes/embassy/large-bedroom-desk/src/main.rs | 50 ++++++++++---- .../sensors/src/{buttons.rs => button.rs} | 0 nodes/embassy/sensors/src/lib.rs | 3 +- nodes/embassy/sensors/src/pir.rs | 66 +++++++++++++++++++ 7 files changed, 158 insertions(+), 23 deletions(-) create mode 100644 crates/protocol/src/pir.rs rename nodes/embassy/sensors/src/{buttons.rs => button.rs} (100%) create mode 100644 nodes/embassy/sensors/src/pir.rs diff --git a/crates/protocol/src/large_bedroom/desk_right.rs b/crates/protocol/src/large_bedroom/desk_right.rs index 7cd0050f..3c1a39e4 100644 --- a/crates/protocol/src/large_bedroom/desk_right.rs +++ b/crates/protocol/src/large_bedroom/desk_right.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "alloc")] use crate::reading::tree::Tree; -use crate::IsSameAs; +use crate::{pir, IsSameAs}; crate::button_enum! { /// +----------------------------------------------------+ @@ -46,7 +46,7 @@ crate::button_enum! { #[repr(u8)] pub enum Reading { Button(Button), - PirActivation, + Pir(pir::Status), } #[cfg(feature = "alloc")] @@ -54,20 +54,20 @@ impl Tree for Reading { fn inner(&self) -> crate::reading::tree::Item<'_> { match self { Reading::Button(button_panel) => button_panel.inner(), - Reading::PirActivation => { + Reading::Pir(status) => { use crate::reading::tree::Item; use crate::reading::Info; Item::Leaf(Info { - val: 1.0, + val: *status as u8 as f32, device: Device.rooted(), - description: "button", - range: 0.0..=1.0, + description: "pir", + range: 0.0..=2.0, resolution: 1.0, unit: crate::Unit::None, branch_id: self.branch_id(), label_formatter: Box::new( - crate::button::ButtonLabelFormatter, + crate::pir::PirLabelFormatter, ), }) } @@ -83,7 +83,7 @@ impl IsSameAs for Reading { fn is_same_as(&self, other: &Self) -> bool { match (self, other) { (Self::Button(a), Self::Button(b)) => a.is_same_as(b), - (Self::PirActivation, Self::PirActivation) => true, + (Self::Pir(_), Self::Pir(_)) => true, (_, _) => false, } } @@ -124,7 +124,7 @@ impl Device { name: "Desk Buttons and Pir", affects_readings: &rtree![ Reading::Button(Button::LeftLeft(crate::button::Press(0))), - Reading::PirActivation + Reading::Pir(crate::pir::Status::Unknown) ], affectors: &[], min_sample_interval: Duration::from_secs(1), diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index f8c3ff27..06cfa4b6 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -13,6 +13,7 @@ pub mod shared; pub mod affector; mod device; mod error; +pub mod pir; pub mod reading; pub mod usb; diff --git a/crates/protocol/src/pir.rs b/crates/protocol/src/pir.rs new file mode 100644 index 00000000..7aa3d469 --- /dev/null +++ b/crates/protocol/src/pir.rs @@ -0,0 +1,43 @@ +use postcard::experimental::max_size::MaxSize; +#[cfg(feature = "alloc")] +use crate::reading::LabelFormatter; + +#[derive( + strum::EnumDiscriminants, + Clone, + Copy, + Debug, + defmt::Format, + serde::Serialize, + serde::Deserialize, + MaxSize, + PartialEq, +)] +#[repr(u8)] +pub enum Status { + Started = 2, + End = 0, + /// because the node went offline + Unknown = 1, +} + + +#[cfg(feature = "alloc")] +#[derive(Debug)] +pub struct PirLabelFormatter; + +#[cfg(feature = "alloc")] +impl LabelFormatter for PirLabelFormatter { + fn format(&self, value: f64, _: &crate::reading::Info) -> String { + match value { + 0.0 => "activity ended", + 1.0 => "node went down mid activity", + 2.0 => "activity started", + _ => "ButtonLabelFormatter error", + } + .to_string() + } + fn box_clone(&self) -> Box { + Box::new(Self) + } +} diff --git a/nodes/embassy/large-bedroom-desk/src/main.rs b/nodes/embassy/large-bedroom-desk/src/main.rs index 6196e349..52f9de4f 100644 --- a/nodes/embassy/large-bedroom-desk/src/main.rs +++ b/nodes/embassy/large-bedroom-desk/src/main.rs @@ -66,32 +66,44 @@ async fn main(_spawner: Spawner) { Duration::from_secs(5).as_micros() as u32, ); + use protocol::large_bedroom::desk_right; use protocol::large_bedroom::desk_right::Button; + type IntoButton = fn(protocol::button::Press) -> Button; let buttons = [ ( ExtiInput::new(p.PC15, p.EXTI15, Pull::Down), - Button::LeftLeft, + Button::LeftLeft as IntoButton, + ), + ( + ExtiInput::new(p.PB0, p.EXTI0, Pull::Down), + Button::LeftMiddle as IntoButton, ), - (ExtiInput::new(p.PB0, p.EXTI0, Pull::Down), Button::LeftLeft), ( ExtiInput::new(p.PC14, p.EXTI14, Pull::Down), - Button::LeftLeft, + Button::LeftRight as IntoButton, ), ( ExtiInput::new(p.PB12, p.EXTI12, Pull::Down), - Button::LeftLeft, + Button::RightLeftmost as IntoButton, ), ( ExtiInput::new(p.PB13, p.EXTI13, Pull::Down), - Button::LeftLeft, + Button::RightLeft as IntoButton, + ), + ( + ExtiInput::new(p.PB8, p.EXTI8, Pull::Down), + Button::RightRight as IntoButton, + ), + ( + ExtiInput::new(p.PB6, p.EXTI6, Pull::Down), + Button::RightRightmost as IntoButton, ), - (ExtiInput::new(p.PB8, p.EXTI8, Pull::Down), Button::LeftLeft), - (ExtiInput::new(p.PB6, p.EXTI6, Pull::Down), Button::LeftLeft), ]; - // let pir = buttons::Pir { - // left_left: ExtiInput::new(p.PC11, p.EXTI11, Pull::Down), - // }; // TODO + let pirs = [( + ExtiInput::new(p.PA5, p.EXTI5, Pull::Down), + desk_right::Reading::Pir, + )]; let mut usb_driver_config = embassy_stm32::usb::Config::default(); // Do not enable vbus_detection. This is a safe default that works in all @@ -123,13 +135,17 @@ async fn main(_spawner: Spawner) { let handle_network = comms::handle(usb_handle); pin_mut!(handle_network); - let init_then_measure = sensors::buttons::watch_array(buttons, |button| { + let watch_buttons = sensors::button::watch_array(buttons, |button| { let _err = PUBLISH.try_send(button_into_reading(button)); }); + let watch_pir = sensors::pir::watch_array(pirs, |pir| { + let _err = PUBLISH.try_send(into_reading(pir)); + }); - join::join4( + join::join5( &mut handle_network, - init_then_measure, + watch_buttons, + watch_pir, usb_bus.run(), keep_dog_happy(dog), ) @@ -170,3 +186,11 @@ fn button_into_reading( ), ) } + +fn into_reading( + pir: protocol::large_bedroom::desk_right::Reading, +) -> protocol::Reading { + protocol::Reading::LargeBedroom( + protocol::large_bedroom::Reading::DeskRight(pir), + ) +} diff --git a/nodes/embassy/sensors/src/buttons.rs b/nodes/embassy/sensors/src/button.rs similarity index 100% rename from nodes/embassy/sensors/src/buttons.rs rename to nodes/embassy/sensors/src/button.rs diff --git a/nodes/embassy/sensors/src/lib.rs b/nodes/embassy/sensors/src/lib.rs index d3c9fcc1..3ba8b1dc 100644 --- a/nodes/embassy/sensors/src/lib.rs +++ b/nodes/embassy/sensors/src/lib.rs @@ -1,7 +1,8 @@ #![no_std] mod drivers; -pub mod buttons; +pub mod button; +pub mod pir; pub mod errors; pub mod measurements; diff --git a/nodes/embassy/sensors/src/pir.rs b/nodes/embassy/sensors/src/pir.rs new file mode 100644 index 00000000..18c722d0 --- /dev/null +++ b/nodes/embassy/sensors/src/pir.rs @@ -0,0 +1,66 @@ +use embassy_stm32::exti::ExtiInput; +use embassy_time::{Timer, Duration}; + +use protocol::pir::Status; + +pub async fn watch_array( + pirs: [(ExtiInput<'static>, F); N], + on_pir: impl Fn(P) + Clone, +) where + P: defmt::Format, + F: Fn(protocol::pir::Status) -> P + Clone, +{ + embassy_futures::join::join_array(pirs.map(|(input, into_pir)| { + let local_into_pir = into_pir.clone(); + let local_on_pir = on_pir.clone(); + let on_ok = move |press| { + let on_pir = &local_on_pir; + let into_pir = &local_into_pir; + on_pir(into_pir(press)); + }; + + watch_pir(input, on_ok) + })) + .await; +} + +async fn watch_pir( + mut input: ExtiInput<'static>, + on_change: impl Fn(protocol::pir::Status), +) { + loop { + input.wait_for_high().await; + Timer::after(Duration::from_millis(25)).await; + if input.is_low() { + continue; + } + Timer::after(Duration::from_millis(25)).await; + if input.is_low() { + continue; + } + Timer::after(Duration::from_millis(25)).await; + if input.is_low() { + continue; + } + // pretty sure at this point this is not some random noise + on_change(Status::Started); + loop { + input.wait_for_low().await; + Timer::after(Duration::from_millis(25)).await; + if input.is_high() { + continue; + } + Timer::after(Duration::from_millis(25)).await; + if input.is_high() { + continue; + } + Timer::after(Duration::from_millis(25)).await; + if input.is_high() { + continue; + } + // pretty sure at this point this is not some random noise + on_change(Status::End); + break; + } + } +} From 3e6f15f659d5f8fa90c90d42f7e86da46f3c510a Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 10 Oct 2025 15:46:41 +0200 Subject: [PATCH 672/687] Switch on temperature control for winter --- .../src/controller/rooms/small_bedroom.rs | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index b3c5681f..168b4712 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -238,21 +238,20 @@ pub(super) fn is_nap_time() -> bool { } pub(crate) fn goal_temp_now() -> f64 { - // let goals = BTreeMap::from([ - // ((0, 00), 18.0), - // ((8, 30), 19.0), - // ((10, 00), 20.0), - // ((11, 00), 20.5), - // ((12, 00), 21.0), - // ((18, 00), 20.5), - // ((19, 00), 20.0), - // ((21, 00), 19.5), - // ((21, 30), 19.0), - // ((22, 00), 18.0), - // ]); - // - // goal_now(goals, 18.0) - 16.0 + let goals = BTreeMap::from([ + ((0, 00), 18.0), + ((8, 30), 19.0), + ((10, 00), 20.0), + ((11, 00), 20.5), + ((12, 00), 21.0), + ((18, 00), 20.5), + ((19, 00), 20.0), + ((21, 00), 19.5), + ((21, 30), 19.0), + ((22, 00), 18.0), + ]); + + goal_now(goals, 18.0) } fn air_filtration_now(pm2_5_measurement: &Option<(f32, Zoned)>) -> Option { From 9dd5bb6ec0c3f224775acbe2d31068ec163e6399 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 10 Oct 2025 15:48:55 +0200 Subject: [PATCH 673/687] Clean up excessive tracing for zigbee_bridge --- crates/zigbee-bridge/src/cached_bridge/changes.rs | 7 +++---- crates/zigbee-bridge/src/cached_bridge/mqtt.rs | 1 - crates/zigbee-bridge/src/cached_bridge/poll.rs | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/zigbee-bridge/src/cached_bridge/changes.rs b/crates/zigbee-bridge/src/cached_bridge/changes.rs index 04e9c918..c0c3f32c 100644 --- a/crates/zigbee-bridge/src/cached_bridge/changes.rs +++ b/crates/zigbee-bridge/src/cached_bridge/changes.rs @@ -3,11 +3,12 @@ use std::time::{Duration, Instant}; use tokio::sync::{mpsc, RwLock}; use tokio::time::{sleep, timeout}; -use tracing::{debug, error, instrument}; +use tracing::{error, instrument, warn}; use super::mqtt::Mqtt; use super::{ - CHANGE_ACCUMULATION_TIME, MQTT_MIGHT_BE_DOWN_TIMEOUT, OFFLINE_CHECK_INTERVAL, WAIT_FOR_INIT_STATES + CHANGE_ACCUMULATION_TIME, MQTT_MIGHT_BE_DOWN_TIMEOUT, + OFFLINE_CHECK_INTERVAL, WAIT_FOR_INIT_STATES, }; use crate::device::{Device, Property}; @@ -25,7 +26,6 @@ pub(super) async fn handle( let mut call_at_least_in = MQTT_MIGHT_BE_DOWN_TIMEOUT; loop { - debug!("timeout: {call_at_least_in:?}"); match timeout(call_at_least_in, change_receiver.recv()).await { // On change, update needed, but only actually send the changes // after a timeout @@ -33,7 +33,6 @@ pub(super) async fn handle( let (device_name, change) = update.expect("Channel should never close"); - tracing::debug!("Received change order: {change:?} for device {device_name}"); apply_change_to_needed(device_name, change, &mut needed_states); // When there hasn't been a new change in 100 milliseconds, we diff --git a/crates/zigbee-bridge/src/cached_bridge/mqtt.rs b/crates/zigbee-bridge/src/cached_bridge/mqtt.rs index ea15c562..decd511a 100644 --- a/crates/zigbee-bridge/src/cached_bridge/mqtt.rs +++ b/crates/zigbee-bridge/src/cached_bridge/mqtt.rs @@ -129,7 +129,6 @@ impl Mqtt { ) -> Result<(), ClientError> { let topic = format!("zigbee2mqtt/{friendly_name}/set"); - trace!("Sending"); self.publish(&topic, payload).await?; Ok(()) } diff --git a/crates/zigbee-bridge/src/cached_bridge/poll.rs b/crates/zigbee-bridge/src/cached_bridge/poll.rs index ea43c628..64ef788b 100644 --- a/crates/zigbee-bridge/src/cached_bridge/poll.rs +++ b/crates/zigbee-bridge/src/cached_bridge/poll.rs @@ -74,7 +74,7 @@ async fn update_state( } return; }; - trace!("applying properties"); + for property in new { current_device.apply(property); } From 9a97488b6822d1e8fe06885585811dcb2132c1b3 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 10 Oct 2025 15:56:35 +0200 Subject: [PATCH 674/687] Add simple wakeup to kitchen --- crates/brain/src/controller/mod.rs | 1 + crates/brain/src/controller/rooms/kitchen.rs | 35 +++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index cbd78951..5eb05593 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -11,6 +11,7 @@ pub enum Event { Sensor(Reading), WakeupLB, WakeupSB, + WakeupKitchen, StateChangeSB(rooms::small_bedroom::State), } diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index 01456daa..7ac480a4 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -4,11 +4,12 @@ use futures_concurrency::future::Race; use futures_util::FutureExt; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; -use tracing::warn; +use tracing::{trace, warn}; use crate::controller::rooms::common::RecvFiltered; use crate::controller::rooms::small_bedroom; use crate::controller::{Event, RestrictedSystem}; +use crate::input::jobs::Job; const INTERVAL: Duration = Duration::from_secs(5); @@ -17,6 +18,7 @@ enum State { Sleep, Daylight, Override, + Wakeup, } #[derive(Debug)] @@ -24,6 +26,7 @@ enum RelevantEvent { Sleep, Daylight, Override, + Wakeup, } fn filter(event: Event) -> Option { @@ -37,6 +40,7 @@ fn filter(event: Event) -> Option { Event::StateChangeSB(small_bedroom::State::Override) => { Some(RelevantEvent::Override) } + Event::WakeupKitchen => Some(RelevantEvent::Wakeup), _ => None, } } @@ -55,6 +59,17 @@ pub async fn run( let mut state = State::Daylight; let mut next_update = Instant::now() + INTERVAL; + + let wakeup_job = Job::every_day_at(10, 0, Event::WakeupKitchen, None); + let res = system + .system + .jobs + .remove_all_with_event(Event::WakeupKitchen) + .await; + trace!("Kitchen wakeup job remove result: {res:?}"); + let res = system.system.jobs.add(wakeup_job.clone()).await; + trace!("Kitchen wakeup job add result: {res:?}"); + loop { let get_event = event_rx.recv_filter_mapped(filter).map(Res::Event); let tick = sleep_until(next_update).map(|_| Res::ShouldUpdate); @@ -65,6 +80,11 @@ pub async fn run( state = State::Sleep; system.all_lamps_off().await; } + Res::Event(RelevantEvent::Wakeup) => { + state = State::Wakeup; + trace!("Starting kitchen wakeup"); + wakeup_some_lamps(&mut system).await; + } Res::Event(RelevantEvent::Daylight) => { state = State::Daylight; update(&mut system).await; @@ -86,6 +106,19 @@ pub async fn run( } } +async fn wakeup_some_lamps(system: &mut RestrictedSystem) { + const BRI: f64 = 10. / 254.; + const CT: usize = 2000; + + system.one_lamp_ct("kitchen:hood_left", CT, BRI).await; + system.one_lamp_ct("kitchen:hood_right", CT, BRI).await; + system.one_lamp_ct("kitchen:fridge", CT, BRI).await; + + system.one_lamp_on("kitchen:hood_left").await; + system.one_lamp_on("kitchen:hood_right").await; + system.one_lamp_on("kitchen:fridge").await; +} + async fn update(system: &mut RestrictedSystem) { let (new_ct, new_bri) = small_bedroom::daylight_now(); // let (new_ct, new_bri) = _testing_ct_bri(); From 99f3834dd46522a489865373cdb6794a9c79fa5b Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 12 Oct 2025 23:15:22 +0200 Subject: [PATCH 675/687] Add Tree::value_mut to get &mut Any for a Readings value This works using a new IterMut enum/tree walk. It mirrors reading::Item in having a Node and Leaf variant however the Leaf variant allows mutable access via dyn Any. Currently used for pir heartbeat checking. After having send active a pir needs to keep sending active every 5 seconds or send inactive once. data-server only forwards the initial active and will send status Unknown if the heartbeat is missed. --- Cargo.lock | 137 ++++++++++++++- Cargo.toml | 2 +- crates/data-server/Cargo.toml | 3 +- crates/data-server/src/main.rs | 4 +- crates/data-server/src/server.rs | 2 +- crates/data-server/src/server/subscribe.rs | 156 +++++++++++++++--- crates/data-server/src/server/watch.rs | 5 +- crates/data-server/tests/pir-status.rs | 101 ++++++++++++ crates/data-server/tests/source_api.rs | 2 +- crates/data-server/tests/subscriber_api.rs | 2 +- crates/data-store/src/data/series.rs | 20 +-- crates/data-store/src/export.rs | 2 +- crates/data-store/tests/list_data.rs | 2 +- crates/log-store/tests/list_data.rs | 2 +- crates/protocol/src/button.rs | 9 +- crates/protocol/src/device.rs | 13 ++ crates/protocol/src/large_bedroom/airbox.rs | 14 +- crates/protocol/src/large_bedroom/bed.rs | 46 ++++-- crates/protocol/src/large_bedroom/desk.rs | 29 +++- .../protocol/src/large_bedroom/desk_right.rs | 35 ++-- crates/protocol/src/large_bedroom/radiator.rs | 13 +- crates/protocol/src/lib.rs | 2 +- crates/protocol/src/msg.rs | 4 +- crates/protocol/src/pir.rs | 7 +- crates/protocol/src/reading.rs | 39 ++++- crates/protocol/src/reading/tree.rs | 44 ++++- crates/protocol/src/shared.rs | 3 +- crates/protocol/src/small_bedroom/bed.rs | 41 ++++- crates/protocol/src/small_bedroom/desk.rs | 14 +- .../small_bedroom/portable_button_panel.rs | 12 +- crates/protocol/src/small_bedroom/radiator.rs | 13 +- crates/text-widget/src/main.rs | 8 +- crates/ui/src/tui/readings/render/chart.rs | 2 +- crates/ui/src/tui/readings/sensor_info.rs | 10 +- 34 files changed, 664 insertions(+), 134 deletions(-) create mode 100644 crates/data-server/tests/pir-status.rs diff --git a/Cargo.lock b/Cargo.lock index 3e2a863e..51cbf53c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -103,6 +103,26 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" +[[package]] +name = "async-stdin" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1ff8b5d9b5ec29e0f49583ba71847b8c8888b67a8510133048a380903aa6822" +dependencies = [ + "tokio", +] + +[[package]] +name = "async-throttle" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c99532de164435a0b91279e715bff4fa0d164643b409a67761907ffc210ee8f" +dependencies = [ + "backoff", + "dashmap 5.5.3", + "tokio", +] + [[package]] name = "atomic-polyfill" version = "1.0.3" @@ -124,6 +144,20 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "backoff" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" +dependencies = [ + "futures-core", + "getrandom 0.2.15", + "instant", + "pin-project-lite", + "rand 0.8.5", + "tokio", +] + [[package]] name = "backtrace" version = "0.3.71" @@ -225,7 +259,7 @@ dependencies = [ "mpd", "mpdrs", "protocol", - "rand", + "rand 0.9.0", "serde", "serde_yaml", "sled", @@ -549,6 +583,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -625,6 +668,19 @@ dependencies = [ "syn 2.0.100", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core 0.9.10", +] + [[package]] name = "dashmap" version = "6.1.0" @@ -659,6 +715,7 @@ dependencies = [ "tokio", "tokio-serde", "tokio-util", + "tokio-utils", "tracing", "tracing-error", "tracing-futures", @@ -1279,7 +1336,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be93b4ec2e4710b04d9264c0c7350cdd62a8c20e5e4ac732552ebb8f0debe8eb" dependencies = [ "cfg-if", - "dashmap", + "dashmap 6.1.0", "futures-sink", "futures-timer", "futures-util", @@ -1289,7 +1346,7 @@ dependencies = [ "parking_lot 0.12.3", "portable-atomic", "quanta", - "rand", + "rand 0.9.0", "smallvec 1.14.0", "spinning_top", "web-time", @@ -2610,17 +2667,38 @@ dependencies = [ "nibble_vec", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + [[package]] name = "rand" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ - "rand_chacha", - "rand_core", + "rand_chacha 0.9.0", + "rand_core 0.9.3", "zerocopy", ] +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + [[package]] name = "rand_chacha" version = "0.9.0" @@ -2628,7 +2706,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", ] [[package]] @@ -3039,6 +3126,15 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "shutdown-async" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2799e69bde7e68bedd86c6d94bffa783219114f1f31435ddda61f4aeba348ff" +dependencies = [ + "tokio", +] + [[package]] name = "signal-hook" version = "0.3.17" @@ -3414,17 +3510,30 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.14" +version = "0.7.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", + "slab", "tokio", ] +[[package]] +name = "tokio-utils" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de75f75f464153a50fe48b9675360e3cf2ae1d7d81f9751363bd2ee4888f5ce8" +dependencies = [ + "async-stdin", + "async-throttle", + "shutdown-async", + "tub", +] + [[package]] name = "toml_datetime" version = "0.6.8" @@ -3534,6 +3643,16 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "tub" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bca43faba247bc76eb1d6c1b8b561e4a1c5bdd427cc3d7a007faabea75c683a" +dependencies = [ + "crossbeam-queue", + "tokio", +] + [[package]] name = "tui-tree-widget" version = "0.23.0" @@ -4150,7 +4269,7 @@ dependencies = [ "colorimetry", "logger", "protocol", - "rand", + "rand 0.9.0", "regex", "rumqttc", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index e9073a8f..947da175 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ byteseries = { git = "https://github.com/dvdsk/byteseries", rev="a9da72e9585e5f5 serde = { version = "1", features = ["derive"], default-features = false } tokio = { version = "1.38", features = ["rt-multi-thread"] } -tokio-util = { version = "0.7.13", features = ["codec"] } +tokio-util = { version = "0.7.16", features = ["codec"] } itertools = { version = "0.14" } bincode = { version = "2.0", default-features = false, features = ["serde", "std"] } gethostname = "0.5" diff --git a/crates/data-server/Cargo.toml b/crates/data-server/Cargo.toml index c1b41ef6..2913a704 100644 --- a/crates/data-server/Cargo.toml +++ b/crates/data-server/Cargo.toml @@ -23,13 +23,14 @@ tokio = { workspace = true, features = ["rt", "macros", "net", "sync", "io-util" thiserror.workspace = true futures.workspace = true tokio-serde = { version = "0.9.0", features = ["bincode"] } -tokio-util.workspace = true +tokio-util = { workspace = true, features = ["time"] } serde.workspace = true futures-concurrency = { workspace = true } slotmap = "1.0.7" tracing-futures = "0.2.5" socket2 = { version = "0.6.0", features = ["all"] } governor.workspace = true +tokio-utils = "0.1.2" [dev-dependencies] reserve-port = "2" diff --git a/crates/data-server/src/main.rs b/crates/data-server/src/main.rs index 1fd6ba29..33b054b3 100644 --- a/crates/data-server/src/main.rs +++ b/crates/data-server/src/main.rs @@ -48,14 +48,14 @@ async fn main() -> Result<()> { select! { e = server::client::handle(subscribe_addr, tx.clone(), affectors.clone()) => e, e = server::handle_nodes(update_addr, &tx, affectors.clone()) => e, - e = server::spread_updates(rx) => e, + e = server::handle_updates(rx) => e, _ = server::node_watchdog(affectors, &tx) => Ok(()), } } else { select! { e = server::client::handle(subscribe_addr, tx.clone(), affectors.clone()) => e, e = server::handle_nodes(update_addr, &tx, affectors.clone()) => e, - e = server::spread_updates(rx) => e, + e = server::handle_updates(rx) => e, } } } diff --git a/crates/data-server/src/server.rs b/crates/data-server/src/server.rs index 819d9a3d..84a71179 100644 --- a/crates/data-server/src/server.rs +++ b/crates/data-server/src/server.rs @@ -13,7 +13,7 @@ mod watch; pub use affector::Registar as AffectorRegistar; pub use data_source::handle_nodes; -pub use subscribe::spread_updates; +pub use subscribe::handle_updates; pub use watch::node_watchdog; use crate::api::subscriber::{self, SubMessage}; diff --git a/crates/data-server/src/server/subscribe.rs b/crates/data-server/src/server/subscribe.rs index d450f46b..98bdc3cb 100644 --- a/crates/data-server/src/server/subscribe.rs +++ b/crates/data-server/src/server/subscribe.rs @@ -1,6 +1,12 @@ +use protocol::reading::tree::Tree; +use protocol::reading::ReadingId; +use protocol::{pir, Reading}; +use std::collections::HashMap; use std::mem; +use std::time::{Duration, Instant}; use tokio::sync::mpsc; use tokio::sync::mpsc::error::TrySendError; +use tokio_util::time::FutureExt; use tracing::trace; use color_eyre::Result; @@ -8,38 +14,140 @@ use color_eyre::Result; use super::Event; use crate::api::subscriber::SubMessage; -pub async fn spread_updates(mut events: mpsc::Receiver) -> Result<()> { +pub async fn handle_updates(mut events: mpsc::Receiver) -> Result<()> { + let mut pir_state_tracker = PirStateTracker::new(); let mut subscribers = Vec::new(); loop { - let event = events + let update = events .recv() + .timeout_at(pir_state_tracker.call_again_at.into()) .await - .expect("queue is kept open by register_subs"); - trace!("event: {event:?}"); + .map(|recv_res| { + recv_res.expect("queue is kept open by register_subs") + }); + trace!("update: {update:?}"); - let to_forward = match event { - Event::NewSub { tx } => { - subscribers.push(tx); - continue; + match update { + Err(_timeout) => { + for pir_went_dark in pir_state_tracker.dark_pirs() { + broadcast_reading( + &mut subscribers, + SubMessage::Reading(pir_went_dark), + ); + } } - Event::NewReading(Ok(reading)) => SubMessage::Reading(reading), - Event::NewReading(Err(err)) => SubMessage::ErrorReport(err), - Event::AffectorControlled { - affector, - controlled_by, - } => SubMessage::AffectorControlled { - affector, - controlled_by, - }, - }; - - let subs = mem::take(&mut subscribers); - for sub in subs { - let res = sub.try_send(to_forward.clone()); - if let Ok(()) | Err(TrySendError::Full(_)) = res { - subscribers.push(sub) + Ok(event) => { + spread_updates(&mut pir_state_tracker, &mut subscribers, event) } } } } + +fn spread_updates( + pir_state_tracker: &mut PirStateTracker, + subscribers: &mut Vec>, + event: Event, +) { + let to_forward = match event { + Event::NewSub { tx } => { + subscribers.push(tx); + return; + } + Event::NewReading(Ok(reading)) => { + if let Some(reading) = + pir_state_tracker.intercept_pir_status(reading) + { + SubMessage::Reading(reading) + } else { + return; + } + } + Event::NewReading(Err(err)) => SubMessage::ErrorReport(err), + Event::AffectorControlled { + affector, + controlled_by, + } => SubMessage::AffectorControlled { + affector, + controlled_by, + }, + }; + broadcast_reading(subscribers, to_forward); +} + +fn broadcast_reading( + subscribers: &mut Vec>, + to_forward: SubMessage, +) { + let subs = mem::take(subscribers); + for sub in subs { + let res = sub.try_send(to_forward.clone()); + if let Ok(()) | Err(TrySendError::Full(_)) = res { + subscribers.push(sub) + } + } +} + +/// Pirs should send Status::Active every 5 seconds to confirm they have not +/// gone down/defective. It makes no sense to store Status::Active every 5 +/// seconds. +/// +/// - drops a Status::Active if one was already send +/// - inserts a Status::Unknown if no Status::Active was received in the last +/// 6s. Unless a Status::InActive was received in between +struct PirStateTracker { + active: HashMap, + call_again_at: Instant, +} + +const ACTIVE_PIR_HEARTBEAT: Duration = Duration::from_secs(5); + +impl PirStateTracker { + fn new() -> Self { + Self { + active: HashMap::new(), + call_again_at: Instant::now(), + } + } + fn dark_pirs<'a>(&'a mut self) -> impl Iterator + 'a { + self.active + .extract_if(|_, (last_active, _)| { + last_active.elapsed() > ACTIVE_PIR_HEARTBEAT + }) + .map(|(_, (_, mut reading))| { + let pir_status = reading + .value_mut() + .downcast_mut::() + .expect("we only insert pir::Status"); + *pir_status = pir::Status::Unknown; + reading + }) + } + + fn intercept_pir_status( + &mut self, + mut reading: Reading, + ) -> Option { + match reading.value_mut().downcast_ref() { + Some(pir::Status::OngoingActivity) => { + if self + .active + .insert(reading.id(), (Instant::now(), reading.clone())) + .is_none() + { + Some(reading) + } else { + None + } + } + Some(pir::Status::NoActivity) => { + self.active.remove(&reading.id()); + Some(reading) + } + Some(pir::Status::Unknown) => { + unreachable!("Should never be send by node") + } + None => Some(reading), + } + } +} diff --git a/crates/data-server/src/server/watch.rs b/crates/data-server/src/server/watch.rs index a73cb492..ecf6e2fd 100644 --- a/crates/data-server/src/server/watch.rs +++ b/crates/data-server/src/server/watch.rs @@ -42,7 +42,7 @@ impl LastSeen { fn check_and_bite(&mut self, registar: &AffectorRegistar) { let to_reset = self.map.iter().filter(|(reading, last_seen)| { - let max_interval = reading.leaf().device.info().max_sample_interval; + let max_interval = reading.info().device.info().max_sample_interval; last_seen.elapsed() > max_interval.saturating_mul(10) }); @@ -71,6 +71,9 @@ impl LastSeen { ), )), Reading::LargeBedroom(large_bedroom::Reading::Desk(_)) + | Reading::LargeBedroom( + large_bedroom::Reading::DeskRight(_), + ) | Reading::LargeBedroom( large_bedroom::Reading::Radiator(_), ) diff --git a/crates/data-server/tests/pir-status.rs b/crates/data-server/tests/pir-status.rs new file mode 100644 index 00000000..f6d0049d --- /dev/null +++ b/crates/data-server/tests/pir-status.rs @@ -0,0 +1,101 @@ +use std::net::{Ipv4Addr, SocketAddr}; +use std::time::Duration; + +use color_eyre::Result; +use data_server::api::subscriber::{Client, SubMessage}; +use data_server::server::{self, AffectorRegistar}; +use protocol::large_bedroom; +use protocol::large_bedroom::desk_right; +use protocol::{pir, Reading}; +use tokio::io::AsyncWriteExt; +use tokio::net::TcpStream; +use tokio::select; +use tokio::sync::mpsc; +use tokio::time::sleep; + +#[derive(Debug, PartialEq)] +enum Done { + RunServer, + SendValue, + Test, +} + +const TEST_PIR_ACTIVE: Reading = + Reading::LargeBedroom(large_bedroom::Reading::DeskRight( + desk_right::Reading::Pir(pir::Status::OngoingActivity), + )); +const TEST_PIR_WENT_DARK: Reading = + Reading::LargeBedroom(large_bedroom::Reading::DeskRight( + desk_right::Reading::Pir(pir::Status::Unknown), + )); + +async fn run_server( + client_addr: impl Into, + data_port: impl Into, +) -> Result { + let (tx, rx) = mpsc::channel(2000); + let affectors = AffectorRegistar::default(); + select! { + e = server::client::handle(client_addr.into(), tx.clone(), affectors.clone()) => e.unwrap(), + e = server::handle_nodes(data_port.into(), &tx, affectors) => e.unwrap(), + e = server::handle_updates(rx) => e?, + }; + + Ok(Done::RunServer) +} + +async fn send_pir_active(data_port: u16) -> Result { + tokio::time::sleep(Duration::from_millis(400)).await; + + let list = protocol::affector::ListMessage::<50>::empty(); + let handshake = protocol::Msg::AffectorList(list).encode(); + + let mut conn = TcpStream::connect(("127.0.0.1", data_port)).await.unwrap(); + conn.write_all(&handshake).await.unwrap(); + + let mut sensor_msg = protocol::SensorMessage::<50>::default(); + sensor_msg.values.push(TEST_PIR_ACTIVE).unwrap(); + let sensor_msg = protocol::Msg::Readings(sensor_msg).encode(); + conn.write_all(&sensor_msg).await.unwrap(); + + sleep(Duration::from_secs(999)).await; + Ok(Done::SendValue) +} + +async fn wait_for_pir_then_unknown(sub_port: u16) -> Result { + tokio::time::sleep(Duration::from_millis(100)).await; + let mut sub = Client::connect( + (Ipv4Addr::LOCALHOST, sub_port), + "api_integration_tests".to_owned(), + ) + .await + .unwrap() + .subscribe() + .await + .unwrap(); + + let received = sub.next().await.unwrap(); + assert!(matches!(received, SubMessage::Reading(TEST_PIR_ACTIVE))); + tokio::time::sleep(Duration::from_millis(5100)).await; + let received = sub.next().await.unwrap(); + assert!( + matches!(received, SubMessage::Reading(TEST_PIR_WENT_DARK)), + "got: {received:?}" + ); + + Ok(Done::Test) +} + +#[tokio::test] +async fn pir_unknown_send_if_active_pir_heartbeat_stops() { + logger::tracing::setup_for_tests(); + + let sub_port = reserve_port::ReservedPort::random().unwrap(); + let data_port = reserve_port::ReservedPort::random().unwrap(); + let res = select! { + e = run_server(([127,0,0,1], sub_port.port()), ([127,0,0,1], data_port.port())) => e, + e = send_pir_active(data_port.port()) => e, + e = wait_for_pir_then_unknown(sub_port.port()) => e, + }; + assert_eq!(res.unwrap(), Done::Test); +} diff --git a/crates/data-server/tests/source_api.rs b/crates/data-server/tests/source_api.rs index d53d98cc..50a78f06 100644 --- a/crates/data-server/tests/source_api.rs +++ b/crates/data-server/tests/source_api.rs @@ -38,7 +38,7 @@ async fn run_server( select! { e = server::client::handle(client_addr.into(), tx.clone(), affectors.clone()) => e.unwrap(), e = server::handle_nodes(data_port.into(), &tx, affectors) => e.unwrap(), - e = server::spread_updates(rx) => e?, + e = server::handle_updates(rx) => e?, }; Ok(Done::RunServer) diff --git a/crates/data-server/tests/subscriber_api.rs b/crates/data-server/tests/subscriber_api.rs index e99b1580..d5708b46 100644 --- a/crates/data-server/tests/subscriber_api.rs +++ b/crates/data-server/tests/subscriber_api.rs @@ -29,7 +29,7 @@ async fn run_server( select! { e = server::client::handle(client_addr.into(), tx.clone(), affectors.clone()) => e.unwrap(), e = server::handle_nodes(data_port.into(), &tx, affectors) => e.unwrap(), - e = server::spread_updates(rx) => e?, + e = server::handle_updates(rx) => e?, }; Ok(Done::RunServer) diff --git a/crates/data-store/src/data/series.rs b/crates/data-store/src/data/series.rs index 976252a4..56dd38f7 100644 --- a/crates/data-store/src/data/series.rs +++ b/crates/data-store/src/data/series.rs @@ -121,20 +121,20 @@ impl Series { .info() .affects_readings .iter() - .map(|r| r.leaf().branch_id) - .position(|id_in_list| id_in_list == reading.leaf().branch_id); + .map(|r| r.info().branch_id) + .position(|id_in_list| id_in_list == reading.info().branch_id); let index = wrap_inder_err(res, reading)?; let meta = &mut self.meta_list[index]; - if !reading.leaf().range.contains(&reading.leaf().val) { + if !reading.info().range.contains(&reading.info().val) { return Err(eyre!( "value {} is out of range: {:?}", - reading.leaf().val, - reading.leaf().range + reading.info().val, + reading.info().range )); } - meta.field.encode(reading.leaf().val, &mut self.line); + meta.field.encode(reading.info().val, &mut self.line); meta.set_at = Some(Instant::now()); let max_interval = reading.device().info().max_sample_interval; @@ -147,7 +147,7 @@ impl Series { { let time = jiff::Timestamp::now(); - let device_info = reading.leaf().device.info(); + let device_info = reading.info().device.info(); let scale_factor = millis_to_minimal_representation(device_info); let scaled_time = time.as_millisecond() as u64 / scale_factor; let new_ts = scaled_time; @@ -186,7 +186,7 @@ impl Series { let device_info = readings .first() .expect("There is at least one reading to read") - .leaf() + .info() .device .info(); let scale_factor = millis_to_minimal_representation(device_info); @@ -259,7 +259,7 @@ fn wrap_inder_err( ) .suggestion("In protocol lib, is every reading variant in the affected readings list?") .with_note(|| format!("reading: {reading:?}")) - .with_note(|| format!("reading branch id: {:?}", reading.leaf().branch_id)) + .with_note(|| format!("reading branch id: {:?}", reading.info().branch_id)) .with_note(|| { format!( "affected readings: {:?}", @@ -268,7 +268,7 @@ fn wrap_inder_err( .info() .affects_readings .into_iter() - .map(|r| r.leaf()) + .map(|r| r.info()) .collect::>() ) }) diff --git a/crates/data-store/src/export.rs b/crates/data-store/src/export.rs index ff59ee41..4159913b 100644 --- a/crates/data-store/src/export.rs +++ b/crates/data-store/src/export.rs @@ -133,7 +133,7 @@ fn copy_over_content( let mut read_start = 0; let precisions = readings .into_iter() - .map(|r| r.leaf().precision()) + .map(|r| r.info().precision()) .collect_vec(); loop { diff --git a/crates/data-store/tests/list_data.rs b/crates/data-store/tests/list_data.rs index e16f0abd..3e7350a6 100644 --- a/crates/data-store/tests/list_data.rs +++ b/crates/data-store/tests/list_data.rs @@ -32,7 +32,7 @@ async fn data_server(client_addr: impl Into, data_port: impl Into e.unwrap(), e = server::handle_nodes(data_port.into(), &tx, affectors) => e.unwrap(), - e = server::spread_updates(rx) => e.unwrap(), + e = server::handle_updates(rx) => e.unwrap(), }; } diff --git a/crates/log-store/tests/list_data.rs b/crates/log-store/tests/list_data.rs index 4cc23f53..4b483bd3 100644 --- a/crates/log-store/tests/list_data.rs +++ b/crates/log-store/tests/list_data.rs @@ -38,7 +38,7 @@ async fn data_server(client_addr: impl Into, data_port: impl Into e.unwrap(), e = server::handle_nodes(data_port.into(), &tx, affectors) => e.unwrap(), - e = server::spread_updates(rx) => e.unwrap(), + e = server::handle_updates(rx) => e.unwrap(), }; } diff --git a/crates/protocol/src/button.rs b/crates/protocol/src/button.rs index a063ec8c..d27f06f7 100644 --- a/crates/protocol/src/button.rs +++ b/crates/protocol/src/button.rs @@ -78,7 +78,7 @@ macro_rules! button_enum { #[cfg(feature = "alloc")] impl crate::reading::tree::Tree for $name { fn inner(&self) -> crate::reading::tree::Item<'_> { - crate::reading::tree::Item::Leaf(crate::reading::Info { + let info = crate::reading::Info { val: (*self).into(), device: $device, description: "button", @@ -87,8 +87,13 @@ macro_rules! button_enum { unit: crate::Unit::None, branch_id: self.branch_id(), label_formatter: Box::new(crate::button::ButtonLabelFormatter), - }) + }; + crate::reading::tree::Item::Leaf(info) } + fn inner_mut(&mut self) -> crate::reading::tree::ItemMut<'_> { + crate::reading::tree::ItemMut::Leaf(self as &mut dyn core::any::Any) + } + fn name(&self) -> String { self.variant_name().to_owned() } diff --git a/crates/protocol/src/device.rs b/crates/protocol/src/device.rs index 9e915201..f9beeb0f 100644 --- a/crates/protocol/src/device.rs +++ b/crates/protocol/src/device.rs @@ -39,3 +39,16 @@ pub struct Info { pub max_sample_interval: Duration, pub temporal_resolution: Duration, } + +impl Info { + pub(crate) const fn button_defaults() -> Self { + Self { + name: "Buttons", + affects_readings: &[], + temporal_resolution: Duration::from_millis(1), + min_sample_interval: Duration::from_millis(2), + max_sample_interval: Duration::MAX, + affectors: &[], + } + } +} diff --git a/crates/protocol/src/large_bedroom/airbox.rs b/crates/protocol/src/large_bedroom/airbox.rs index 3338e95e..ad013488 100644 --- a/crates/protocol/src/large_bedroom/airbox.rs +++ b/crates/protocol/src/large_bedroom/airbox.rs @@ -7,7 +7,7 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; #[cfg(feature = "alloc")] -use crate::reading::tree::{Item, Tree}; +use crate::reading::tree::{Item, ItemMut, Tree}; #[cfg(feature = "alloc")] use crate::reading::FloatLabelFormatter; #[cfg(feature = "alloc")] @@ -41,7 +41,7 @@ impl_is_same_as! {Reading; Temperature, Pressure, FanPower, Button} #[cfg(feature = "alloc")] impl Tree for Reading { fn inner(&self) -> Item<'_> { - let leaf = match self { + let info = match self { Reading::Temperature(val) => Info { val: *val, device: Device::Bme280.rooted(), @@ -87,7 +87,15 @@ impl Tree for Reading { label_formatter: Box::new(crate::button::ButtonLabelFormatter), }, }; - Item::Leaf(leaf) + Item::Leaf(info) + } + + fn inner_mut(&mut self) -> ItemMut<'_> { + use crate::reading::tree::field_as_any; + + let value = + field_as_any!(self, Temperature, Pressure, FanPower, Button); + ItemMut::Leaf(value) } fn branch_id(&self) -> crate::reading::tree::Id { diff --git a/crates/protocol/src/large_bedroom/bed.rs b/crates/protocol/src/large_bedroom/bed.rs index 4d32c3b5..208c560e 100644 --- a/crates/protocol/src/large_bedroom/bed.rs +++ b/crates/protocol/src/large_bedroom/bed.rs @@ -5,7 +5,7 @@ use crate::affector::{Control, ControlValue}; use crate::button::Press; use crate::button_enum; #[cfg(feature = "alloc")] -use crate::reading::tree::{Id, Item, Tree}; +use crate::reading::tree::{Id, Item, ItemMut, Tree}; #[cfg(feature = "alloc")] use crate::reading::FloatLabelFormatter; #[cfg(feature = "alloc")] @@ -247,7 +247,7 @@ impl Tree for Reading { ), }; - Item::Leaf(Info { + let info = Info { val, device, resolution, @@ -256,7 +256,37 @@ impl Tree for Reading { description, branch_id: self.branch_id(), label_formatter: Box::new(FloatLabelFormatter), - }) + }; + + Item::Leaf(info) + } + + fn inner_mut(&mut self) -> ItemMut<'_> { + use crate::reading::tree::field_as_any; + + let value = field_as_any!( + self, + Brightness, + Temperature, + Humidity, + GassResistance, + Pressure, + Co2, + WeightLeft, + WeightRight, + MassPm1_0, + MassPm2_5, + MassPm4_0, + MassPm10, + NumberPm0_5, + NumberPm1_0, + NumberPm2_5, + NumberPm4_0, + NumberPm10, + TypicalParticleSize, + Button + ); + ItemMut::Leaf(value) } fn branch_id(&self) -> Id { @@ -265,8 +295,8 @@ impl Tree for Reading { } impl_is_same_as! {Reading; Brightness, Temperature, Humidity, GassResistance, Pressure, - Co2, WeightLeft, WeightRight, MassPm1_0, MassPm2_5, MassPm4_0, MassPm10, NumberPm0_5, - NumberPm1_0, NumberPm2_5, NumberPm4_0, NumberPm10, TypicalParticleSize; + Co2, WeightLeft, WeightRight, MassPm1_0, MassPm2_5, MassPm4_0, MassPm10, NumberPm0_5, + NumberPm1_0, NumberPm2_5, NumberPm4_0, NumberPm10, TypicalParticleSize; (Self::Button(a), Self::Button(b)) => a.is_same_as(b) } @@ -470,7 +500,6 @@ impl Device { affectors: &tree!(Affector; Affector::Nau7802RightCalib), }, Device::Gpio => crate::DeviceInfo { - name: "Gpio", affects_readings: &tree![Reading; Reading::Button(Button::Top(Press(0))), Reading::Button(Button::MiddleInner(Press(0))), @@ -480,10 +509,7 @@ impl Device { Reading::Button(Button::LowerCenter(Press(0))), Reading::Button(Button::LowerOuter(Press(0))) ], - temporal_resolution: Duration::from_millis(1), - min_sample_interval: Duration::from_millis(2), - max_sample_interval: Duration::MAX, - affectors: &[], + ..crate::DeviceInfo::button_defaults() }, } } diff --git a/crates/protocol/src/large_bedroom/desk.rs b/crates/protocol/src/large_bedroom/desk.rs index 38dab15c..2185a986 100644 --- a/crates/protocol/src/large_bedroom/desk.rs +++ b/crates/protocol/src/large_bedroom/desk.rs @@ -3,7 +3,7 @@ use core::time::Duration; use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; -use crate::button_enum; +use crate::button::Press; #[cfg(feature = "alloc")] use crate::reading::tree::{Item, Tree}; #[cfg(feature = "alloc")] @@ -13,6 +13,7 @@ use crate::reading::Info; use crate::shared::impl_is_same_as; #[cfg(feature = "alloc")] use crate::Unit; +use crate::{button_enum, DeviceInfo}; button_enum! { /// No these are not borg, these are buttons on a string of cat5. @@ -52,7 +53,7 @@ pub enum Reading { #[cfg(feature = "alloc")] impl Tree for Reading { fn inner(&self) -> Item<'_> { - let leaf = match self { + let info = match self { Reading::Temperature(val) => Info { val: *val, device: Device::Bme280.rooted(), @@ -85,7 +86,16 @@ impl Tree for Reading { }, Reading::Button(val) => return Item::Node(val as &dyn Tree), }; - Item::Leaf(leaf) + + Item::Leaf(info) + } + + fn inner_mut(&mut self) -> crate::reading::tree::ItemMut<'_> { + use crate::reading::tree::field_as_any; + + let value = + field_as_any!(self, Temperature, Humidity, Pressure, Button); + crate::reading::tree::ItemMut::Leaf(value) } fn branch_id(&self) -> crate::reading::tree::Id { @@ -216,7 +226,18 @@ impl Device { max_sample_interval: Duration::from_secs(5), temporal_resolution: Duration::from_secs(1), }, - Device::Gpio => todo!(), + Device::Gpio => crate::DeviceInfo { + affects_readings: &rtree![ + Reading::Button(Button::OneOfFour(Press(0))), + Reading::Button(Button::TwoOfFour(Press(0))), + Reading::Button(Button::ThreeOfFour(Press(0))), + Reading::Button(Button::FourOfFour(Press(0))), + Reading::Button(Button::OneOfThree(Press(0))), + Reading::Button(Button::TwoOfThree(Press(0))), + Reading::Button(Button::ThreeOfThree(Press(0))) + ], + ..DeviceInfo::button_defaults() + }, } } } diff --git a/crates/protocol/src/large_bedroom/desk_right.rs b/crates/protocol/src/large_bedroom/desk_right.rs index 3c1a39e4..8c6f53ab 100644 --- a/crates/protocol/src/large_bedroom/desk_right.rs +++ b/crates/protocol/src/large_bedroom/desk_right.rs @@ -1,10 +1,8 @@ -use core::time::Duration; - use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; #[cfg(feature = "alloc")] -use crate::reading::tree::Tree; +use crate::reading::tree::{self, Tree}; use crate::{pir, IsSameAs}; crate::button_enum! { @@ -51,31 +49,37 @@ pub enum Reading { #[cfg(feature = "alloc")] impl Tree for Reading { - fn inner(&self) -> crate::reading::tree::Item<'_> { + fn inner(&self) -> tree::Item<'_> { match self { Reading::Button(button_panel) => button_panel.inner(), Reading::Pir(status) => { - use crate::reading::tree::Item; use crate::reading::Info; - Item::Leaf(Info { + let info = Info { val: *status as u8 as f32, device: Device.rooted(), - description: "pir", + description: "Pir motion detector", range: 0.0..=2.0, resolution: 1.0, unit: crate::Unit::None, branch_id: self.branch_id(), - label_formatter: Box::new( - crate::pir::PirLabelFormatter, - ), - }) + label_formatter: Box::new(crate::pir::PirLabelFormatter), + }; + + tree::Item::Leaf(info) } } } - fn branch_id(&self) -> crate::reading::tree::Id { - todo!() + fn inner_mut(&mut self) -> tree::ItemMut<'_> { + use crate::reading::tree::field_as_any; + + let value = field_as_any!(self, Button, Pir); + tree::ItemMut::Leaf(value) + } + + fn branch_id(&self) -> tree::Id { + ReadingDiscriminants::from(self) as tree::Id } } @@ -126,10 +130,7 @@ impl Device { Reading::Button(Button::LeftLeft(crate::button::Press(0))), Reading::Pir(crate::pir::Status::Unknown) ], - affectors: &[], - min_sample_interval: Duration::from_secs(1), - max_sample_interval: Duration::MAX, - temporal_resolution: Duration::from_secs(1), + ..crate::DeviceInfo::button_defaults() } } } diff --git a/crates/protocol/src/large_bedroom/radiator.rs b/crates/protocol/src/large_bedroom/radiator.rs index d54c871a..8ed9a81c 100644 --- a/crates/protocol/src/large_bedroom/radiator.rs +++ b/crates/protocol/src/large_bedroom/radiator.rs @@ -4,7 +4,7 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; #[cfg(feature = "alloc")] -use crate::reading::tree::{Item, Tree}; +use crate::reading::tree::{Item, ItemMut, Tree}; #[cfg(feature = "alloc")] use crate::reading::FloatLabelFormatter; #[cfg(feature = "alloc")] @@ -38,7 +38,7 @@ impl_is_same_as!{Reading; Temperature, Heating, SetBy, Setpoint} #[cfg(feature = "alloc")] impl Tree for Reading { fn inner(&self) -> Item<'_> { - let leaf = match self { + let info = match self { Reading::Temperature(val) => Info { val: *val, device: crate::Device::LargeBedroom(super::Device::Radiator( @@ -90,7 +90,14 @@ impl Tree for Reading { label_formatter: Box::new(FloatLabelFormatter), }, }; - Item::Leaf(leaf) + + Item::Leaf(info) + } + fn inner_mut(&mut self) -> ItemMut<'_> { + use crate::reading::tree::field_as_any; + + let value = field_as_any!(self, Temperature, Heating, SetBy, Setpoint); + ItemMut::Leaf(value) } fn branch_id(&self) -> crate::reading::tree::Id { diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 06cfa4b6..82956533 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -33,7 +33,7 @@ pub enum Unit { Lux, MicrogramPerM3, NanoMeter, - None, // for buttons + None, // for buttons & pir NumberPerCm3, Ohm, Pa, diff --git a/crates/protocol/src/msg.rs b/crates/protocol/src/msg.rs index 9ef31481..d9a361c1 100644 --- a/crates/protocol/src/msg.rs +++ b/crates/protocol/src/msg.rs @@ -77,19 +77,17 @@ impl Msg { #[must_use] pub fn encode_slice<'a>(&self, buf: &'a mut [u8]) -> &'a mut [u8] { + buf[0] = self.header(); match self { Msg::Readings(msg) => { - buf[0] = Self::READINGS; let len = msg.encode_slice(&mut buf[1..]).len(); &mut buf[..1 + len] } Msg::ErrorReport(report) => { - buf[0] = Self::ERROR_REPORT; let len = report.encode_slice(&mut buf[1..]).len(); &mut buf[..1 + len] } Msg::AffectorList(list) => { - buf[0] = Self::AFFECTOR_LIST; let len = list.encode_slice(&mut buf[1..]).len(); &mut buf[..1 + len] } diff --git a/crates/protocol/src/pir.rs b/crates/protocol/src/pir.rs index 7aa3d469..a0bf6476 100644 --- a/crates/protocol/src/pir.rs +++ b/crates/protocol/src/pir.rs @@ -1,6 +1,6 @@ -use postcard::experimental::max_size::MaxSize; #[cfg(feature = "alloc")] use crate::reading::LabelFormatter; +use postcard::experimental::max_size::MaxSize; #[derive( strum::EnumDiscriminants, @@ -15,13 +15,12 @@ use crate::reading::LabelFormatter; )] #[repr(u8)] pub enum Status { - Started = 2, - End = 0, + OngoingActivity = 2, + NoActivity = 0, /// because the node went offline Unknown = 1, } - #[cfg(feature = "alloc")] #[derive(Debug)] pub struct PirLabelFormatter; diff --git a/crates/protocol/src/reading.rs b/crates/protocol/src/reading.rs index 764cfb17..0198263e 100644 --- a/crates/protocol/src/reading.rs +++ b/crates/protocol/src/reading.rs @@ -29,28 +29,57 @@ pub enum Reading { // Test, } +#[cfg(feature = "alloc")] +/// Unique Id for a specific reading (not the value) +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct ReadingId([tree::Id; 8]); + #[cfg(feature = "alloc")] impl Reading { #[must_use] pub fn from_same_device(&self) -> &'static [Reading] { use tree::Tree; - self.leaf().from_same_device() + self.info().from_same_device() } #[must_use] pub fn range(&self) -> core::ops::RangeInclusive { use tree::Tree; - self.leaf().range + self.info().range } #[must_use] /// the step between the two closest data-points that are not the same pub fn resolution(&self) -> f32 { use tree::Tree; - self.leaf().resolution + self.info().resolution } #[must_use] pub fn device(&self) -> Device { use tree::Tree; - self.leaf().device + self.info().device + } + // This means the enum can not go deeper then 8 + // but that seems reasonable + pub fn id(&self) -> ReadingId { + use crate::reading::tree::Tree; + + let mut current = self as &dyn Tree; + let mut res = [0; 8]; + for i in 0.. { + *res.get_mut(i) + .expect("Reading tree should not go deeper then 8") = + current.branch_id(); + match current.inner() { + tree::Item::Node(node) => current = node, + tree::Item::Leaf(info) => { + *res.get_mut(i + 1) + .expect("Reading tree should not go deeper then 8") = + info.branch_id; + break; + } + } + } + + ReadingId(res) } } impl Reading { @@ -128,7 +157,7 @@ impl Info { /// let reading = /// Reading::LargeBedroom(large_bedroom::Reading::Desk(desk::Reading::Temperature(22.428124))); /// - /// let info = reading.leaf(); + /// let info = reading.info(); /// let printed = format!("{0:.1$}", info.val, info.precision()); /// assert_eq!(printed, "22.43"); /// ``` diff --git a/crates/protocol/src/reading/tree.rs b/crates/protocol/src/reading/tree.rs index 8d7489a5..038365b8 100644 --- a/crates/protocol/src/reading/tree.rs +++ b/crates/protocol/src/reading/tree.rs @@ -1,3 +1,5 @@ +use core::any::Any; + use super::Info; pub type Id = u8; @@ -7,10 +9,17 @@ pub enum Item<'a> { Node(&'a dyn Tree), } +pub enum ItemMut<'a> { + Leaf(&'a mut dyn Any), + Node(&'a mut dyn Tree), +} + pub trait Tree: core::fmt::Debug { #[must_use] fn inner(&self) -> Item<'_>; - fn leaf(&self) -> Info + fn inner_mut(&mut self) -> ItemMut<'_>; + + fn info(&self) -> Info where Self: Sized, { @@ -18,7 +27,19 @@ pub trait Tree: core::fmt::Debug { loop { match current.inner() { Item::Node(node) => current = node, - Item::Leaf(leaf) => return leaf, + Item::Leaf(info) => return info, + } + } + } + fn value_mut(&mut self) -> &mut (dyn Any + 'static) + where + Self: Sized, + { + let mut current = self as &mut dyn Tree; + loop { + match current.inner_mut() { + ItemMut::Node(node) => current = node, + ItemMut::Leaf(value) => return value, } } } @@ -33,6 +54,17 @@ pub trait Tree: core::fmt::Debug { fn branch_id(&self) -> Id; } +macro_rules! field_as_any { + ($self:ident, $($field_name:ident),+) => { + match $self { + $( + Reading::$field_name(inner) => inner as &mut dyn core::any::Any, + )+ + } + }; +} +pub(crate) use field_as_any; + macro_rules! impl_zero { ($name:ident; $($var:ident),*) => { impl $crate::IsSameAs for $name { @@ -60,6 +92,14 @@ macro_rules! all_nodes { ),* } } + fn inner_mut(&mut self) -> crate::reading::tree::ItemMut<'_> { + match self { + $( + $name::$var(inner) => crate::reading::tree::ItemMut::Node(inner as &mut dyn crate::reading::tree::Tree) + ),* + } + + } fn branch_id(&self) -> crate::reading::tree::Id { $variant::from(self) as crate::reading::tree::Id diff --git a/crates/protocol/src/shared.rs b/crates/protocol/src/shared.rs index 40926b65..8ebda5af 100644 --- a/crates/protocol/src/shared.rs +++ b/crates/protocol/src/shared.rs @@ -1,8 +1,9 @@ pub mod radiator; +// doc test is no compile as macro is pub(crate) /// implements the `IsSameAs` trait for enum `thing` with variants `variant` /// example usage: -/// ```rust +/// ```no_compile /// impl_is_same_as!(Reading; Temperature, Heating, SetBy, Setpoint); /// ``` macro_rules! impl_is_same_as { diff --git a/crates/protocol/src/small_bedroom/bed.rs b/crates/protocol/src/small_bedroom/bed.rs index bca1d64b..53b6e107 100644 --- a/crates/protocol/src/small_bedroom/bed.rs +++ b/crates/protocol/src/small_bedroom/bed.rs @@ -4,7 +4,7 @@ use core::time::Duration; use crate::affector::{Control, ControlValue}; use crate::button::Press; #[cfg(feature = "alloc")] -use crate::reading::tree::{Id, Item, Tree}; +use crate::reading::tree::{Id, Item, ItemMut, Tree}; #[cfg(feature = "alloc")] use crate::reading::FloatLabelFormatter; #[cfg(feature = "alloc")] @@ -228,7 +228,7 @@ impl Tree for Reading { ), }; - Item::Leaf(Info { + let info = Info { val, device, resolution, @@ -237,7 +237,37 @@ impl Tree for Reading { description, branch_id: self.branch_id(), label_formatter: Box::new(FloatLabelFormatter), - }) + }; + + Item::Leaf(info) + } + + fn inner_mut(&mut self) -> ItemMut<'_> { + use crate::reading::tree::field_as_any; + + let value = field_as_any!( + self, + Button, + Brightness, + Temperature, + Humidity, + GassResistance, + Pressure, + Co2, + Weight, + MassPm1_0, + MassPm2_5, + MassPm4_0, + MassPm10, + NumberPm0_5, + NumberPm1_0, + NumberPm2_5, + NumberPm4_0, + NumberPm10, + TypicalParticleSize + ); + + ItemMut::Leaf(value) } fn branch_id(&self) -> Id { @@ -447,10 +477,7 @@ impl Device { Reading::Button(Button::RightMiddle(Press(0))), Reading::Button(Button::Right(Press(0))) ], - temporal_resolution: Duration::from_millis(1), - min_sample_interval: Duration::from_millis(2), - max_sample_interval: Duration::MAX, - affectors: &[], + ..crate::DeviceInfo::button_defaults() }, } } diff --git a/crates/protocol/src/small_bedroom/desk.rs b/crates/protocol/src/small_bedroom/desk.rs index 04cdffda..7d834d7d 100644 --- a/crates/protocol/src/small_bedroom/desk.rs +++ b/crates/protocol/src/small_bedroom/desk.rs @@ -4,7 +4,7 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; #[cfg(feature = "alloc")] -use crate::reading::tree::{Item, Tree}; +use crate::reading::tree::{Item, ItemMut, Tree}; #[cfg(feature = "alloc")] use crate::reading::FloatLabelFormatter; #[cfg(feature = "alloc")] @@ -35,7 +35,7 @@ pub enum Reading { #[cfg(feature = "alloc")] impl Tree for Reading { fn inner(&self) -> Item<'_> { - let leaf = match self { + let info = match self { Reading::Temperature(val) => Info { val: *val, device: Device::Bme280.rooted(), @@ -67,7 +67,15 @@ impl Tree for Reading { label_formatter: Box::new(FloatLabelFormatter), }, }; - Item::Leaf(leaf) + + Item::Leaf(info) + } + + fn inner_mut(&mut self) -> ItemMut<'_> { + use crate::reading::tree::field_as_any; + + let value = field_as_any!(self, Temperature, Humidity, Pressure); + ItemMut::Leaf(value) } fn branch_id(&self) -> crate::reading::tree::Id { diff --git a/crates/protocol/src/small_bedroom/portable_button_panel.rs b/crates/protocol/src/small_bedroom/portable_button_panel.rs index 98ed5ab9..f6d3196b 100644 --- a/crates/protocol/src/small_bedroom/portable_button_panel.rs +++ b/crates/protocol/src/small_bedroom/portable_button_panel.rs @@ -44,8 +44,8 @@ pub enum Reading { #[cfg(feature = "alloc")] impl Tree for Reading { fn inner(&self) -> Item<'_> { - Item::Leaf(crate::reading::Info { - val: 1.0, + let info = crate::reading::Info { + val: 1.0, // This is wrong and should be treated like button device: crate::Device::SmallBedroom( super::Device::PortableButtonPanel(Device), ), @@ -55,7 +55,13 @@ impl Tree for Reading { unit: crate::Unit::None, branch_id: self.branch_id(), label_formatter: Box::new(FloatLabelFormatter), - }) + }; + + Item::Leaf(info) + } + + fn inner_mut(&mut self) -> crate::reading::tree::ItemMut<'_> { + crate::reading::tree::ItemMut::Leaf(self) } fn name(&self) -> String { diff --git a/crates/protocol/src/small_bedroom/radiator.rs b/crates/protocol/src/small_bedroom/radiator.rs index 121767b2..80f48fb4 100644 --- a/crates/protocol/src/small_bedroom/radiator.rs +++ b/crates/protocol/src/small_bedroom/radiator.rs @@ -38,7 +38,7 @@ impl_is_same_as!(Reading; Temperature, Heating, SetBy, Setpoint); #[cfg(feature = "alloc")] impl Tree for Reading { fn inner(&self) -> Item<'_> { - let leaf = match self { + let info = match self { Reading::Temperature(val) => Info { val: *val, device: crate::Device::SmallBedroom(super::Device::Radiator( @@ -90,7 +90,16 @@ impl Tree for Reading { label_formatter: Box::new(FloatLabelFormatter), }, }; - Item::Leaf(leaf) + + Item::Leaf(info) + } + + fn inner_mut(&mut self) -> crate::reading::tree::ItemMut<'_> { + use crate::reading::tree::{field_as_any, ItemMut}; + + let value = field_as_any!(self, Temperature, Heating, SetBy, Setpoint); + ItemMut::Leaf(value) + } fn branch_id(&self) -> crate::reading::tree::Id { diff --git a/crates/text-widget/src/main.rs b/crates/text-widget/src/main.rs index ad824016..5cd50089 100644 --- a/crates/text-widget/src/main.rs +++ b/crates/text-widget/src/main.rs @@ -170,14 +170,14 @@ impl Entry { Self { curr_value: None, last_updated_at: Instant::now(), - timeout_interval: reading.leaf().device.info().max_sample_interval + timeout_interval: reading.info().device.info().max_sample_interval + Duration::from_secs(1), } } fn format(&self) -> String { if let Some(reading) = &self.curr_value { - let info = reading.leaf(); + let info = reading.info(); format!("{0:.1$} {2}", info.val, info.precision(), info.unit) } else { "X".to_string() @@ -192,12 +192,12 @@ fn update_stdout_json(entries: &[Entry], used_queries: &[String]) { .map(|(query, Entry { curr_value, .. })| { let value = curr_value .as_ref() - .map(|r| r.leaf()) + .map(|r| r.info()) .map(|info| format!("{0:.1$}", info.val, info.precision())) .unwrap_or("X".to_string()); let unit = curr_value .as_ref() - .map(|r| r.leaf().unit) + .map(|r| r.info().unit) .unwrap_or(protocol::Unit::None); format!("\"{query}\": {}, \"{query}-unit\": \"{}\"", value, unit) diff --git a/crates/ui/src/tui/readings/render/chart.rs b/crates/ui/src/tui/readings/render/chart.rs index cd3d55f7..a3131852 100644 --- a/crates/ui/src/tui/readings/render/chart.rs +++ b/crates/ui/src/tui/readings/render/chart.rs @@ -242,7 +242,7 @@ fn fmt_reading( text.push_str(&node.name()); } match cursor_value { - Some(Ok(v)) => text.push_str(&format!(": {0:.1$}", v, reading.leaf().precision())), + Some(Ok(v)) => text.push_str(&format!(": {0:.1$}", v, reading.info().precision())), Some(Err(TooInaccurate)) => text.push_str(" x"), None => (), } diff --git a/crates/ui/src/tui/readings/sensor_info.rs b/crates/ui/src/tui/readings/sensor_info.rs index 464e6c72..7969472e 100644 --- a/crates/ui/src/tui/readings/sensor_info.rs +++ b/crates/ui/src/tui/readings/sensor_info.rs @@ -77,11 +77,11 @@ impl SensorInfo { let recent_history = if is_placeholder { Vec::new() } else { - vec![(time, reading.leaf().val)] + vec![(time, reading.info().val)] }; Self { - info: reading.leaf(), + info: reading.info(), reading: reading.clone(), timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), percentiles_from_store: Vec::new(), @@ -100,7 +100,7 @@ impl SensorInfo { fn new_err(error: &Error, broken: &Reading, ui_id: u16) -> Self { let logs = logs::Logs::new_from(error); SensorInfo { - info: broken.leaf(), + info: broken.info(), reading: broken.clone(), timing: Histogram::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap(), percentiles_from_store: Vec::new(), @@ -118,13 +118,13 @@ impl SensorInfo { fn update(&mut self, reading: &Reading) { let time = jiff::Timestamp::now(); - self.info = reading.leaf(); + self.info = reading.info(); if let Some(last_reading) = self.last_at() { self.timing += (time - last_reading) .total(Unit::Millisecond) .expect("no calander units involved") as u64 } - self.recent_history.push((time, reading.leaf().val)); + self.recent_history.push((time, reading.info().val)); self.is_placeholder = false; self.condition = Ok(()); } From 7a8b77cb57659c8aef2d0cac3a329249b7ce53ca Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 25 Oct 2025 15:10:30 +0200 Subject: [PATCH 676/687] Tweak heating and wakeup --- crates/brain/src/controller/rooms/kitchen.rs | 6 +----- crates/brain/src/controller/rooms/small_bedroom.rs | 13 +++++-------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index 7ac480a4..1e61505e 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -107,16 +107,12 @@ pub async fn run( } async fn wakeup_some_lamps(system: &mut RestrictedSystem) { - const BRI: f64 = 10. / 254.; + const BRI: f64 = 2. / 254.; const CT: usize = 2000; system.one_lamp_ct("kitchen:hood_left", CT, BRI).await; - system.one_lamp_ct("kitchen:hood_right", CT, BRI).await; - system.one_lamp_ct("kitchen:fridge", CT, BRI).await; system.one_lamp_on("kitchen:hood_left").await; - system.one_lamp_on("kitchen:hood_right").await; - system.one_lamp_on("kitchen:fridge").await; } async fn update(system: &mut RestrictedSystem) { diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 168b4712..1a5824b1 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -240,15 +240,12 @@ pub(super) fn is_nap_time() -> bool { pub(crate) fn goal_temp_now() -> f64 { let goals = BTreeMap::from([ ((0, 00), 18.0), - ((8, 30), 19.0), - ((10, 00), 20.0), - ((11, 00), 20.5), - ((12, 00), 21.0), + ((10, 00), 19.0), + ((11, 00), 21.0), + ((12, 00), 22.0), ((18, 00), 20.5), - ((19, 00), 20.0), - ((21, 00), 19.5), - ((21, 30), 19.0), - ((22, 00), 18.0), + ((19, 00), 10.0), + ((21, 00), 18.0), ]); goal_now(goals, 18.0) From 3bb402c196243abf26e2c1e905e88695e2275d98 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 8 Nov 2025 17:18:51 +0100 Subject: [PATCH 677/687] remove unused web_api --- Cargo.lock | 4 - crates/brain/Cargo.toml | 5 - crates/brain/src/input/web_api/commands.rs | 94 ----------- crates/brain/src/input/web_api/mod.rs | 36 ----- crates/brain/src/input/web_api/music.rs | 30 ---- .../src/input/web_api/server/database.rs | 111 ------------- .../brain/src/input/web_api/server/login.rs | 82 ---------- .../input/web_api/server/login_redirect.rs | 98 ------------ crates/brain/src/input/web_api/server/mod.rs | 149 ------------------ .../web_api/server/static_webpages/login.css | 57 ------- .../web_api/server/static_webpages/login.html | 12 -- crates/brain/src/input/web_api/wakeup.rs | 68 -------- 12 files changed, 746 deletions(-) delete mode 100644 crates/brain/src/input/web_api/commands.rs delete mode 100644 crates/brain/src/input/web_api/mod.rs delete mode 100644 crates/brain/src/input/web_api/music.rs delete mode 100644 crates/brain/src/input/web_api/server/database.rs delete mode 100644 crates/brain/src/input/web_api/server/login.rs delete mode 100644 crates/brain/src/input/web_api/server/login_redirect.rs delete mode 100644 crates/brain/src/input/web_api/server/mod.rs delete mode 100755 crates/brain/src/input/web_api/server/static_webpages/login.css delete mode 100755 crates/brain/src/input/web_api/server/static_webpages/login.html delete mode 100644 crates/brain/src/input/web_api/wakeup.rs diff --git a/Cargo.lock b/Cargo.lock index 51cbf53c..c5adb0cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -244,9 +244,6 @@ dependencies = [ name = "brain" version = "0.1.0" dependencies = [ - "bincode 2.0.1", - "byteorder", - "bytes", "clap", "color-eyre", "data-server", @@ -263,7 +260,6 @@ dependencies = [ "serde", "serde_yaml", "sled", - "strum 0.27.1", "thiserror 2.0.12", "tokio", "tracing", diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 26f3a671..4e148408 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -16,15 +16,11 @@ tokio = { workspace = true, features = ["full"] } serde.workspace = true serde_yaml = "0.9" -bincode.workspace = true thiserror.workspace = true jiff = { workspace = true, features = ["serde"] } -bytes = "1.5" -byteorder = "1.4" - sled = "0.34" mpd = "0.1" @@ -35,7 +31,6 @@ tracing = {workspace = true} logger.workspace = true clap = { workspace = true } futures-concurrency = { workspace = true } -strum.workspace = true dbstruct = { git = "https://github.com/dvdsk/dbstruct" } color-eyre.workspace = true mpdrs = "0.1.0" diff --git a/crates/brain/src/input/web_api/commands.rs b/crates/brain/src/input/web_api/commands.rs deleted file mode 100644 index ecad490e..00000000 --- a/crates/brain/src/input/web_api/commands.rs +++ /dev/null @@ -1,94 +0,0 @@ -use actix_web::web::Data; -use actix_web::HttpResponse; -use actix_web_httpauth::extractors::basic::BasicAuth; - -use super::*; -use crate::controller::State as TargetState; -use crate::controller::{Command, Event}; - -///////////////////// lamp commands /////////////////////////////// -pub fn toggle(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth, &state.passw_db) { - state - .controller_addr - .send(Event::Command(Command::LampsToggle)) - .unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } -} - -pub fn dim(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth, &state.passw_db) { - state - .controller_addr - .send(Event::Command(Command::LampsDim)) - .unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } -} - -pub fn dimmest(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth, &state.passw_db) { - state - .controller_addr - .send(Event::Command(Command::LampsDimmest)) - .unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } -} - -pub fn normal(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth, &state.passw_db) { - state - .controller_addr - .send(Event::Command(Command::LampsDay)) - .unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } -} - -pub fn evening(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth, &state.passw_db) { - state - .controller_addr - .send(Event::Command(Command::LampsEvening)) - .unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } -} - -pub fn night(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth, &state.passw_db) { - state - .controller_addr - .send(Event::Command(Command::LampsNight)) - .unwrap(); - HttpResponse::Ok().finish() - } else { - make_auth_error() - } -} - -//////////////////////// go to state commands ///////////////////////////////// - -pub fn lightloop(state: Data, auth: BasicAuth) -> HttpResponse { - if authenticated(auth, &state.passw_db) { - state - .controller_addr - .send(Event::Command(Command::ChangeState(TargetState::LightLoop))) - .unwrap(); //TODO FIXME - HttpResponse::Ok().finish() - } else { - make_auth_error() - } -} diff --git a/crates/brain/src/input/web_api/mod.rs b/crates/brain/src/input/web_api/mod.rs deleted file mode 100644 index d8542340..00000000 --- a/crates/brain/src/input/web_api/mod.rs +++ /dev/null @@ -1,36 +0,0 @@ -use actix_web_httpauth::extractors::basic::BasicAuth; -use actix_web_httpauth::headers::www_authenticate::basic::Basic; -use actix_web_httpauth::headers::www_authenticate::WwwAuthenticate; - -use actix_web::http::StatusCode; -use actix_web::{HttpRequest, HttpResponse}; - -use crate::PasswordDatabase; - -mod commands; -mod music; -mod wakeup; - -pub mod server; -use server::State; - -fn authenticated(auth: BasicAuth, pass_db: &PasswordDatabase) -> bool { - let username = auth.user_id(); - let Some(password) = auth.password() else { - return false; - }; - pass_db - .verify_password(username.as_bytes(), password.as_bytes()) - .is_ok() -} - -fn make_auth_error() -> HttpResponse { - let challenge = Basic::with_realm("Restricted area"); - HttpResponse::Unauthorized() - .set(WwwAuthenticate(challenge)) - .finish() -} - -fn make_error(statuscode: StatusCode) -> HttpResponse { - HttpResponse::build(statuscode).finish() -} diff --git a/crates/brain/src/input/web_api/music.rs b/crates/brain/src/input/web_api/music.rs deleted file mode 100644 index 6021d351..00000000 --- a/crates/brain/src/input/web_api/music.rs +++ /dev/null @@ -1,30 +0,0 @@ -use actix_web::http::StatusCode; -use actix_web::web::{Data, Form}; - -use serde::Deserialize; - -use actix_web::HttpResponse; - -use super::*; -use crate::input::youtube_downloader::FeedbackChannel; - -#[derive(Deserialize, Debug)] -pub struct SongUrl { - url: String, -} - -pub async fn add_song_from_url(params: Form, state: Data) -> HttpResponse { - let url = params.into_inner().url; - - if state - .youtube_dl - .add_song_to_queue(url, FeedbackChannel::None) - .await - .is_ok() - { - - HttpResponse::Ok().finish() - } else { - make_error(StatusCode::INTERNAL_SERVER_ERROR) - } -} diff --git a/crates/brain/src/input/web_api/server/database.rs b/crates/brain/src/input/web_api/server/database.rs deleted file mode 100644 index c2a2be55..00000000 --- a/crates/brain/src/input/web_api/server/database.rs +++ /dev/null @@ -1,111 +0,0 @@ -use sled::{Db, Tree}; - -use ring::{digest, pbkdf2}; -use std::num::NonZeroU32; - -static PBKDF2_ALG: pbkdf2::Algorithm = pbkdf2::PBKDF2_HMAC_SHA256; -const CREDENTIAL_LEN: usize = digest::SHA256_OUTPUT_LEN; - -pub enum PasswDbError { - WrongUsername, - WrongPassword, - Internal, -} - -#[derive(Debug, Clone)] -pub struct PasswordDatabase { - pbkdf2_iterations: NonZeroU32, - db_salt_component: [u8; 16], - pub storage: Tree, -} - -impl PasswordDatabase { - pub fn from_db(db: &Db) -> Result { - Ok(Self { - pbkdf2_iterations: NonZeroU32::new(100_000).unwrap(), - db_salt_component: [ - // This value was generated from a secure PRNG. - 0xd6, 0x26, 0x98, 0xda, 0xf4, 0xdc, 0x50, 0x52, 0x24, 0xf2, 0x27, 0xd1, 0xfe, 0x39, - 0x01, 0x8a, - ], - storage: db.open_tree("passw_database")?, //created it not exist - }) - } - - pub fn set_password(&mut self, username: &[u8], password: &[u8]) -> Result<(), sled::Error> { - let salt = self.salt(username); - let mut credential = [0u8; CREDENTIAL_LEN]; - pbkdf2::derive( - PBKDF2_ALG, - self.pbkdf2_iterations, - &salt, - password, - &mut credential, - ); - - self.storage.insert(username, &credential)?; - self.storage.flush()?; - Ok(()) - } - - pub fn add_admin(&mut self, password: &str) -> Result<(), sled::Error> { - self.set_password("admin".as_bytes(), password.as_bytes()) - } - - pub async fn remove_user(&self, username: &[u8]) -> Result<(), sled::Error> { - self.storage.remove(username)?; - self.storage.flush_async().await?; - Ok(()) - } - - pub fn update(&self, old_name: &str, new_name: &str) { - if old_name == new_name { - return; - } - let credential = self.storage.get(old_name.as_bytes()).unwrap().unwrap(); - self.storage - .insert(new_name.as_bytes(), credential) - .unwrap(); - } - - pub fn verify_password( - &self, - username: &[u8], - attempted_password: &[u8], - ) -> Result<(), PasswDbError> { - if let Ok(db_entry) = self.storage.get(username) { - if let Some(credential) = db_entry { - let salted_attempt = self.salt(username); - pbkdf2::verify( - PBKDF2_ALG, - self.pbkdf2_iterations, - &salted_attempt, - attempted_password, - &credential, - ) - .map_err(|_| PasswDbError::WrongPassword) - } else { - Err(PasswDbError::WrongUsername) - } - } else { - Err(PasswDbError::Internal) - } - } - - //pub fn is_user_in_database(&self, username: &[u8]) -> Result { - // self.storage.contains_key(username) - //} - - // The salt should have a user-specific component so that an attacker - // cannot crack one password for multiple users in the database. It - // should have a database-unique component so that an attacker cannot - // crack the same user's password across databases in the unfortunate - // but common case that the user has used the same password for - // multiple systems. - pub fn salt(&self, username: &[u8]) -> Vec { - let mut salt = Vec::with_capacity(self.db_salt_component.len() + username.len()); - salt.extend(self.db_salt_component.as_ref()); - salt.extend(username); - salt - } -} diff --git a/crates/brain/src/input/web_api/server/login.rs b/crates/brain/src/input/web_api/server/login.rs deleted file mode 100644 index b1f8ea59..00000000 --- a/crates/brain/src/input/web_api/server/login.rs +++ /dev/null @@ -1,82 +0,0 @@ -use actix_identity::Identity; -use actix_web::web::{Data, Form}; -use actix_web::Result as wResult; -use actix_web::{http, HttpRequest, HttpResponse}; -use rand::{FromEntropy, Rng}; -use serde::Deserialize; - -use std::sync::{atomic::Ordering, Arc, Mutex}; - -use super::{Session, State}; - -pub fn logout(id: Identity) -> HttpResponse { - id.forget(); - HttpResponse::Found().finish() -} - -pub fn login_page() -> HttpResponse { - let page = include_str!("static_webpages/login.html"); - HttpResponse::Ok() - .header(http::header::CONTENT_TYPE, "text/html; charset=utf-8") - .body(page) -} - -#[derive(Deserialize)] -pub struct Logindata { - u: String, - p: String, -} - -/// State and POST Params -pub async fn login_get_and_check( - id: Identity, - state: Data, - req: HttpRequest, - params: Form, -) -> wResult { - trace!("checking login"); - - //time function duration - let now = std::time::Instant::now(); - - //if login valid (check passwdb) load userinfo - if state - .passw_db - .verify_password(params.u.as_str().as_bytes(), params.p.as_str().as_bytes()) - .is_err() - { - warn!("incorrect password"); - return Ok(HttpResponse::build(http::StatusCode::UNAUTHORIZED) - .content_type("text/plain") - .body("incorrect password or username")); - } else { - info!("user logged in"); - } - - let session = Session {}; //kept in case we want it back in the future - //find free session_numb, set new session number and store new session - let session_id = state.free_session_ids.fetch_add(1, Ordering::Acquire); - let mut sessions = state.sessions.write().unwrap(); - sessions.insert(session_id as u16, Arc::new(Mutex::new(session))); - - //sign and send session id cookie to user - id.remember(session_id.to_string()); - info!("remembering session"); - - let end = std::time::Instant::now(); - println!("{:?}", end - now); - - Ok(HttpResponse::Found() - .header( - http::header::LOCATION, - req.path()["/login".len()..].to_owned(), - ) - .finish()) -} - -pub fn make_random_cookie_key() -> [u8; 32] { - let mut cookie_private_key = [0u8; 32]; - let mut rng = rand::rngs::StdRng::from_entropy(); - rng.fill(&mut cookie_private_key[..]); - cookie_private_key -} diff --git a/crates/brain/src/input/web_api/server/login_redirect.rs b/crates/brain/src/input/web_api/server/login_redirect.rs deleted file mode 100644 index 5424a111..00000000 --- a/crates/brain/src/input/web_api/server/login_redirect.rs +++ /dev/null @@ -1,98 +0,0 @@ -use std::task::{Context, Poll}; - -use actix_service::{Service, Transform}; -use actix_web::dev::{ServiceRequest, ServiceResponse}; -use actix_web::{http, web, Error, HttpResponse}; - -use futures::future::{ok, Either, Ready}; - -use log::info; - -use actix_identity::RequestIdentity; -//example to mimic: https://github.com/actix/examples/blob/master/middleware/src/redirect.rs - -use super::State; - -#[derive(Default)] -pub struct CheckLogin {} - -impl Transform for CheckLogin -where - S: Service, Error = Error>, - S::Future: 'static, -{ - type Request = ServiceRequest; - type Response = ServiceResponse; - type Error = Error; - type InitError = (); - type Transform = CheckLoginMiddleware; - type Future = Ready>; - - fn new_transform(&self, service: S) -> Self::Future { - ok(CheckLoginMiddleware { service }) - } -} - -pub struct CheckLoginMiddleware { - service: S, -} - -//TODO can we get data into the middleware? look at existing identityservice -fn is_logged_in(state: &web::Data, id: String) -> Result<(), ()> { - if let Ok(id) = id.parse::() { - //check if valid session (identity key contained in sessions) - if state.sessions.read().unwrap().contains_key(&id) { - Ok(()) - } else { - Err(()) - } - } else { - Err(()) - } -} - -impl Service for CheckLoginMiddleware -where - S: Service, Error = Error>, - S::Future: 'static, -{ - type Request = ServiceRequest; - type Response = ServiceResponse; - type Error = Error; - type Future = Either>>; - //type Future = Pin>>>; - - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - self.service.poll_ready(cx) - } - - fn call(&mut self, req: ServiceRequest) -> Self::Future { - // We only need to hook into the `start` for this middleware. - - if let Some(id) = req.get_identity() { - //let id = req.get_identity().unwrap(); - let data: web::Data = req.app_data().unwrap(); - if is_logged_in(&data, id).is_ok() { - //let fut = - Either::Left(self.service.call(req)) - } else { - let redirect = "/login".to_owned() + req.path(); - Either::Right(ok(req.into_response( - HttpResponse::Found() - .header(http::header::LOCATION, redirect) - .finish() - .into_body(), //TODO why comma? is needed? - ))) - } - } else { - info!("could not get identity thus redirecting"); - let redirect = "/login".to_owned() + req.path(); - Either::Right(ok(req.into_response( - HttpResponse::Found() - .header(http::header::LOCATION, redirect) - .finish() - .into_body(), //TODO why comma? is needed? - ))) - } - } -} diff --git a/crates/brain/src/input/web_api/server/mod.rs b/crates/brain/src/input/web_api/server/mod.rs deleted file mode 100644 index c31c7012..00000000 --- a/crates/brain/src/input/web_api/server/mod.rs +++ /dev/null @@ -1,149 +0,0 @@ -use sensor_value::SensorValue; -use telegram_bot::types::refs::UserId; - -use actix_files as axtix_fs; -use actix_identity::{CookieIdentityPolicy, IdentityService}; -use actix_rt::System; -use actix_web::web::{Bytes, Data}; -use actix_web::HttpRequest; -use actix_web::HttpResponse; -use actix_web::{web, App, HttpServer, Responder}; - -use std::collections::HashMap; -use std::sync::{atomic::AtomicUsize, Arc, Mutex, RwLock}; -use std::thread; - -use crate::controller::Event; -use crate::input; -use crate::input::bot; - -pub mod database; -pub mod login; -pub mod login_redirect; - -use super::{commands, music, wakeup}; -pub use database::PasswordDatabase; -pub use login::{login_get_and_check, login_page, logout, make_random_cookie_key}; -pub use login_redirect::CheckLogin; - -pub struct Session {} //TODO deprecate - -#[derive(Clone)] -pub struct State { - pub controller_addr: crossbeam_channel::Sender, - pub jobs: input::jobs::Jobs, - pub wakeup: input::jobs::WakeUp, - pub passw_db: PasswordDatabase, - pub sessions: Arc>>>>, - pub free_session_ids: Arc, - pub youtube_dl: input::YoutubeDownloader, - pub bot_token: String, - pub valid_ids: Vec, -} - -impl State { - pub fn new( - passw_db: PasswordDatabase, - controller_tx: crossbeam_channel::Sender, - jobs: input::jobs::Jobs, - wakeup: input::jobs::WakeUp, - bot_token: String, - valid_ids: Vec, - ) -> Self { - let free_session_ids = Arc::new(AtomicUsize::new(0)); - let sessions = Arc::new(RwLock::new(HashMap::new())); - let valid_ids = valid_ids.into_iter().map(|id| UserId::from(id)).collect(); - - State { - controller_addr: controller_tx, - jobs, - wakeup, - passw_db, - youtube_dl, - sessions, - free_session_ids, - bot_token, - valid_ids, - } - } -} - -pub async fn index(_req: HttpRequest) -> impl Responder { - "Hello world!" -} - -pub fn start_webserver( - state: State, - port: u16, - domain: String, - ha_key: String, -) -> actix_web::dev::Server { - let cookie_key = make_random_cookie_key(); - let (tx, rx) = crossbeam_channel::unbounded(); - - thread::spawn(move || { - let sys = System::new("HttpServer"); - let web_server = HttpServer::new(move || { - // data the webservers functions have access to - let data = actix_web::web::Data::new(state.clone()); - - App::new() - .app_data(data) - .wrap(IdentityService::new( - CookieIdentityPolicy::new(&cookie_key[..]) - .domain(&domain) - .name("auth-cookie") - .path("/") - .secure(true), - )) - .service( - web::scope("/login").service( - web::resource(r"/{path}") - .route(web::post().to(login_get_and_check)) - .route(web::get().to(login_page)), - ), - ) - .service(web::resource("/commands/lamps/toggle").to(commands::toggle)) - .service(web::resource("/commands/lamps/evening").to(commands::evening)) - .service(web::resource("/commands/lamps/night").to(commands::night)) - .service(web::resource("/commands/lamps/day").to(commands::normal)) - .service(web::resource("/commands/lamps/dimmest").to(commands::dimmest)) - .service(web::resource("/commands/lamps/dim").to(commands::dim)) - .service(web::resource("/commands/lightloop").to(commands::lightloop)) - .service(web::resource("/alarm/tomorrow").to(wakeup::tomorrow)) - .service(web::resource("/alarm/usually").to(wakeup::usually)) - .service(web::resource(&format!("/{}", &state.bot_token)).to(bot::handle_webhook)) - .service( - web::resource(&format!("/{}", ha_key)).route(web::post().to(handle_sensor)), - ) - .service( - web::scope("/") - .wrap(CheckLogin {}) - .service(web::resource("").to(index)) - .service(web::resource("logout/").to(logout)) - .service(web::resource("add_song").to(music::add_song_from_url)) - //for all other urls we try to resolve to static files in the "web" dir - .service(axtix_fs::Files::new("", "./web/")), - ) - }) - .bind(&format!("127.0.0.1:{}", port)) // SEC: disallow connections from the outside - .unwrap() - .shutdown_timeout(5) // shut down 5 seconds after getting the signal to shut down - .run(); - - let _ = tx.send(web_server.clone()); - sys.run() - }); - - let web_handle = rx.recv().unwrap(); - web_handle -} - -pub fn handle_sensor(body: Bytes, state: Data) -> HttpResponse { - let res = bincode::deserialize::(&body[..]); - match res { - Err(err) => error!("deserialize sensorval failed: {:?}", err), - Ok(event) => state.controller_addr.send(Event::Sensor(event)).unwrap(), - } - HttpResponse::Ok().finish() -} diff --git a/crates/brain/src/input/web_api/server/static_webpages/login.css b/crates/brain/src/input/web_api/server/static_webpages/login.css deleted file mode 100755 index be527f76..00000000 --- a/crates/brain/src/input/web_api/server/static_webpages/login.css +++ /dev/null @@ -1,57 +0,0 @@ -@import url(https://fonts.googleapis.com/css?family=Open+Sans); -.btn { display: inline-block; *display: inline; *zoom: 1; padding: 4px 10px 4px; margin-bottom: 0; font-size: 13px; line-height: 18px; color: #333333; text-align: center;text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); vertical-align: middle; background-color: #f5f5f5; background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); background-image: linear-gradient(top, #ffffff, #e6e6e6); background-repeat: repeat-x; filter: progid:dximagetransform.microsoft.gradient(startColorstr=#ffffff, endColorstr=#e6e6e6, GradientType=0); border-color: #e6e6e6 #e6e6e6 #e6e6e6; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border: 1px solid #e6e6e6; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); cursor: pointer; *margin-left: .3em; } -.btn:hover, .btn:active, .btn.active, .btn.disabled, .btn[disabled] { background-color: #e6e6e6; } -.btn-large { padding: 9px 14px; font-size: 15px; line-height: normal; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } -.btn:hover { color: #333333; text-decoration: none; background-color: #e6e6e6; background-position: 0 -15px; -webkit-transition: background-position 0.1s linear; -moz-transition: background-position 0.1s linear; -ms-transition: background-position 0.1s linear; -o-transition: background-position 0.1s linear; transition: background-position 0.1s linear; } -.btn-primary, .btn-primary:hover { text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); color: #ffffff; } -.btn-primary.active { color: rgba(255, 255, 255, 0.75); } -.btn-primary { background-color: #4a77d4; background-image: -moz-linear-gradient(top, #6eb6de, #4a77d4); background-image: -ms-linear-gradient(top, #6eb6de, #4a77d4); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#6eb6de), to(#4a77d4)); background-image: -webkit-linear-gradient(top, #6eb6de, #4a77d4); background-image: -o-linear-gradient(top, #6eb6de, #4a77d4); background-image: linear-gradient(top, #6eb6de, #4a77d4); background-repeat: repeat-x; filter: progid:dximagetransform.microsoft.gradient(startColorstr=#6eb6de, endColorstr=#4a77d4, GradientType=0); border: 1px solid #3762bc; text-shadow: 1px 1px 1px rgba(0,0,0,0.4); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.5); } -.btn-primary:hover, .btn-primary:active, .btn-primary.active, .btn-primary.disabled, .btn-primary[disabled] { filter: none; background-color: #4a77d4; } -.btn-block { width: 100%; display:block; } - -* { -webkit-box-sizing:border-box; -moz-box-sizing:border-box; -ms-box-sizing:border-box; -o-box-sizing:border-box; box-sizing:border-box; } - -html { width: 100%; height:100%; overflow:hidden; } - -body { - width: 100%; - height:100%; - font-family: 'Open Sans', sans-serif; - background: #092756; - background: -moz-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%),-moz-linear-gradient(top, rgba(57,173,219,.25) 0%, rgba(42,60,87,.4) 100%), -moz-linear-gradient(-45deg, #670d10 0%, #092756 100%); - background: -webkit-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%), -webkit-linear-gradient(top, rgba(57,173,219,.25) 0%,rgba(42,60,87,.4) 100%), -webkit-linear-gradient(-45deg, #670d10 0%,#092756 100%); - background: -o-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%), -o-linear-gradient(top, rgba(57,173,219,.25) 0%,rgba(42,60,87,.4) 100%), -o-linear-gradient(-45deg, #670d10 0%,#092756 100%); - background: -ms-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%), -ms-linear-gradient(top, rgba(57,173,219,.25) 0%,rgba(42,60,87,.4) 100%), -ms-linear-gradient(-45deg, #670d10 0%,#092756 100%); - background: -webkit-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%), linear-gradient(to bottom, rgba(57,173,219,.25) 0%,rgba(42,60,87,.4) 100%), linear-gradient(135deg, #670d10 0%,#092756 100%); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3E1D6D', endColorstr='#092756',GradientType=1 ); -} -.login { - position: absolute; - top: 50%; - left: 50%; - margin: -150px 0 0 -150px; - width:300px; - height:300px; -} -.login h1 { color: #fff; text-shadow: 0 0 10px rgba(0,0,0,0.3); letter-spacing:1px; text-align:center; } - -input { - width: 100%; - margin-bottom: 10px; - background: rgba(0,0,0,0.3); - border: none; - outline: none; - padding: 10px; - font-size: 13px; - color: #fff; - text-shadow: 1px 1px 1px rgba(0,0,0,0.3); - border: 1px solid rgba(0,0,0,0.3); - border-radius: 4px; - box-shadow: inset 0 -5px 45px rgba(100,100,100,0.2), 0 1px 1px rgba(255,255,255,0.2); - -webkit-transition: box-shadow .5s ease; - -moz-transition: box-shadow .5s ease; - -o-transition: box-shadow .5s ease; - -ms-transition: box-shadow .5s ease; - transition: box-shadow .5s ease; -} -input:focus { box-shadow: inset 0 -5px 45px rgba(100,100,100,0.4), 0 1px 1px rgba(255,255,255,0.2); } diff --git a/crates/brain/src/input/web_api/server/static_webpages/login.html b/crates/brain/src/input/web_api/server/static_webpages/login.html deleted file mode 100755 index 00f96978..00000000 --- a/crates/brain/src/input/web_api/server/static_webpages/login.html +++ /dev/null @@ -1,12 +0,0 @@ - - -WebSocket Test - -

diff --git a/crates/brain/src/input/web_api/wakeup.rs b/crates/brain/src/input/web_api/wakeup.rs deleted file mode 100644 index d6b2730b..00000000 --- a/crates/brain/src/input/web_api/wakeup.rs +++ /dev/null @@ -1,68 +0,0 @@ -use actix_web::http::Method; -use actix_web::web::Bytes; -use actix_web::web::Data; -use actix_web::HttpResponse; -use actix_web_httpauth::extractors::basic::BasicAuth; - -use super::*; -use crate::input::jobs::WakeUp; - -async fn set_tomorrow(wakeup: &WakeUp, body: Bytes) -> Result { - let time = bincode::deserialize(&body).map_err(|_| ())?; - wakeup.set_tomorrow(time).await.map_err(|_| ())?; - Ok(HttpResponse::Ok().finish()) -} - -pub async fn tomorrow( - state: Data, - auth: BasicAuth, - req: HttpRequest, - body: Bytes, -) -> HttpResponse { - if !authenticated(auth, &state.passw_db) { - return make_auth_error(); - } - - match *req.method() { - Method::GET => { - let tomorrow = state.wakeup.tomorrow(); - let bytes = bincode::serialize(&tomorrow).unwrap(); - HttpResponse::Ok().body(bytes) - } - Method::POST => match set_tomorrow(&state.wakeup, body).await { - Ok(resp) => resp, - Err(_) => HttpResponse::BadRequest().finish(), - }, - _ => HttpResponse::BadRequest().finish(), - } -} - -async fn set_usually(wakeup: &WakeUp, body: Bytes) -> Result { - let time = bincode::deserialize(&body).map_err(|_| ())?; - wakeup.set_usually(time).await.map_err(|_| ())?; - Ok(HttpResponse::Ok().finish()) -} - -pub async fn usually( - state: Data, - auth: BasicAuth, - req: HttpRequest, - body: Bytes, -) -> HttpResponse { - if !authenticated(auth, &state.passw_db) { - return make_auth_error(); - } - - match *req.method() { - Method::GET => { - let usually = state.wakeup.usually(); - let bytes = bincode::serialize(&usually).unwrap(); - HttpResponse::Ok().body(bytes) - } - Method::POST => match set_usually(&state.wakeup, body).await { - Ok(resp) => resp, - Err(_) => HttpResponse::BadRequest().finish(), - }, - _ => HttpResponse::BadRequest().finish(), - } -} From de2bd2f4a8dc68f7b93ec93d0f89439bf2a68e6a Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 8 Nov 2025 23:55:28 +0100 Subject: [PATCH 678/687] adds persistance to all rooms but small bedroom --- Cargo.lock | 9 ++--- crates/brain/Cargo.toml | 3 +- crates/brain/src/controller/mod.rs | 31 +++++++++++++---- crates/brain/src/controller/rooms.rs | 26 +++++++++++++++ crates/brain/src/controller/rooms/entrance.rs | 24 ++++++++++---- crates/brain/src/controller/rooms/kitchen.rs | 27 ++++++++++----- .../src/controller/rooms/large_bedroom.rs | 33 ++++++++++++------- .../src/controller/rooms/small_bedroom.rs | 11 ++++++- .../controller/rooms/small_bedroom/state.rs | 3 +- crates/brain/src/errors.rs | 11 ------- crates/brain/src/input/jobs.rs | 10 +++--- crates/brain/src/main.rs | 33 ++++++++++++++----- 12 files changed, 157 insertions(+), 64 deletions(-) delete mode 100644 crates/brain/src/errors.rs diff --git a/Cargo.lock b/Cargo.lock index c5adb0cb..f80bb1d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -751,10 +751,9 @@ dependencies = [ [[package]] name = "dbstruct" -version = "0.5.0" -source = "git+https://github.com/dvdsk/dbstruct#54862aec8c225d34925b5ec943e0d49fd9efab22" +version = "0.6.0" dependencies = [ - "bincode 1.3.3", + "bincode 2.0.1", "dbstruct-derive", "serde", "sled", @@ -764,9 +763,7 @@ dependencies = [ [[package]] name = "dbstruct-derive" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bf0e86bb052514efb4038337e3be7444b941d874e6a406795cdf4fbfbc55fc" +version = "0.4.0" dependencies = [ "itertools 0.14.0", "proc-macro-error", diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 4e148408..1dba679d 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -31,6 +31,7 @@ tracing = {workspace = true} logger.workspace = true clap = { workspace = true } futures-concurrency = { workspace = true } -dbstruct = { git = "https://github.com/dvdsk/dbstruct" } +# dbstruct = { git = "https://github.com/dvdsk/dbstruct" } +dbstruct = { path = "/home/david/Documents/dbstruct" } color-eyre.workspace = true mpdrs = "0.1.0" diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 5eb05593..19c2b3ff 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -1,6 +1,7 @@ mod rooms; use crate::system::System; +use color_eyre::eyre::Context; pub use protocol::Reading; use serde::{Deserialize, Serialize}; use tokio::sync::broadcast; @@ -95,7 +96,8 @@ pub fn start( subscribed: [broadcast::Receiver; 4], sender: broadcast::Sender, system: System, -) -> JoinSet<()> { + db: sled::Db, +) -> Result>, color_eyre::Report> { tracing::info!("starting"); let mut tasks = JoinSet::new(); let [rx1, rx2, rx3, rx4] = subscribed; @@ -111,7 +113,15 @@ pub fn start( ], allowed_radiators: vec!["large_bedroom:radiator"], }; - tasks.spawn(rooms::large_bedroom::run(rx1, sender.clone(), restricted)); + let ds = db + .open_tree("large_bedroom") + .wrap_err("Opening db subtree for large_bedroom")?; + tasks.spawn(rooms::large_bedroom::run( + rx1, + sender.clone(), + restricted, + ds, + )); let restricted = RestrictedSystem { system: system.clone(), @@ -122,7 +132,10 @@ pub fn start( ], allowed_radiators: vec!["small_bedroom:radiator"], }; - tasks.spawn(rooms::small_bedroom::run(rx2, sender.clone(), restricted)); + let ds = db + .open_tree("small_bedroom") + .wrap_err("Opening db subtree for small_bedroom")?; + tasks.spawn(rooms::small_bedroom::run(rx2, sender.clone(), restricted, ds)); let restricted = RestrictedSystem { system: system.clone(), @@ -135,7 +148,10 @@ pub fn start( ], allowed_radiators: vec![], }; - tasks.spawn(rooms::kitchen::run(rx3, sender.clone(), restricted)); + let ds = db + .open_tree("kitchen") + .wrap_err("Opening db subtree for kitchen")?; + tasks.spawn(rooms::kitchen::run(rx3, sender.clone(), restricted, ds)); let restricted = RestrictedSystem { system: system.clone(), @@ -146,7 +162,10 @@ pub fn start( ], allowed_radiators: vec![], }; - tasks.spawn(rooms::entrance::run(rx4, sender, restricted)); + let ds = db + .open_tree("entrance") + .wrap_err("Opening db subtree for entrance")?; + tasks.spawn(rooms::entrance::run(rx4, sender, restricted, ds)); - tasks + Ok(tasks) } diff --git a/crates/brain/src/controller/rooms.rs b/crates/brain/src/controller/rooms.rs index 3fae8bf8..82b1a1fe 100644 --- a/crates/brain/src/controller/rooms.rs +++ b/crates/brain/src/controller/rooms.rs @@ -3,3 +3,29 @@ pub mod entrance; pub mod kitchen; pub mod large_bedroom; pub mod small_bedroom; + +macro_rules! impl_open_or_wipe { + ($store:ty) => { + /// Maybe the struct has changed so this can no longer be opened. + /// Just wipe it in that case, too lazy to do migrations. + fn open_or_wipe( + tree: sled::Tree, + ) -> Result<$store, color_eyre::Report> { + use ::color_eyre::eyre::WrapErr; + + if let Ok(store) = <$store>::open_tree(tree.clone()) { + Ok(store) + } else { + tracing::error!( + "Could not open {}, wiping it and opening new one", + ::std::stringify!($store) + ); + tree.clear().wrap_err("Error wiping tree")?; + <$store>::open_tree(tree) + .wrap_err("Failed to open tree after wiping") + } + } + }; +} + +use impl_open_or_wipe; diff --git a/crates/brain/src/controller/rooms/entrance.rs b/crates/brain/src/controller/rooms/entrance.rs index 026ca895..b4044f7b 100644 --- a/crates/brain/src/controller/rooms/entrance.rs +++ b/crates/brain/src/controller/rooms/entrance.rs @@ -2,6 +2,7 @@ use std::time::Duration; use futures::FutureExt; use futures_concurrency::future::Race; +use serde::{Deserialize, Serialize}; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; @@ -11,9 +12,10 @@ use crate::controller::{Event, RestrictedSystem}; const INTERVAL: Duration = Duration::from_secs(5); -#[derive(PartialEq, Eq)] +#[derive(PartialEq, Eq, Serialize, Deserialize, Default)] enum State { Sleep, + #[default] Daylight, } @@ -35,18 +37,28 @@ fn filter(event: Event) -> Option { } } +#[dbstruct::dbstruct(db=sled)] +struct Store { + #[dbstruct(Default)] + state: State, +} + +super::impl_open_or_wipe!(Store); + pub async fn run( mut event_rx: broadcast::Receiver, // todo if state change message everyone using this _event_tx: broadcast::Sender, mut system: RestrictedSystem, -) { + db: sled::Tree, +) -> color_eyre::Result<()> { enum Res { Event(RelevantEvent), ShouldUpdate, } - let mut state = State::Daylight; + let db = open_or_wipe(db)?; + let mut next_update = Instant::now() + INTERVAL; loop { let get_event = event_rx.recv_filter_mapped(filter).map(Res::Event); @@ -55,17 +67,17 @@ pub async fn run( let res = (get_event, tick).race().await; match res { Res::Event(RelevantEvent::Sleep) => { - state = State::Sleep; + db.state().set(&State::Sleep)?; system.one_lamp_off("hallway:ceiling").await; } Res::Event(RelevantEvent::Daylight) => { - state = State::Daylight; + db.state().set(&State::Daylight)?; update(&mut system).await; system.all_lamps_on().await; } Res::ShouldUpdate => { - if state == State::Daylight { + if db.state().get()? == State::Daylight { update(&mut system).await; system.all_lamps_on().await; } diff --git a/crates/brain/src/controller/rooms/kitchen.rs b/crates/brain/src/controller/rooms/kitchen.rs index 1e61505e..39c46dcd 100644 --- a/crates/brain/src/controller/rooms/kitchen.rs +++ b/crates/brain/src/controller/rooms/kitchen.rs @@ -2,6 +2,7 @@ use std::time::Duration; use futures_concurrency::future::Race; use futures_util::FutureExt; +use serde::{Deserialize, Serialize}; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; use tracing::{trace, warn}; @@ -13,9 +14,10 @@ use crate::input::jobs::Job; const INTERVAL: Duration = Duration::from_secs(5); -#[derive(PartialEq, Eq)] +#[derive(PartialEq, Eq, Serialize, Deserialize, Default)] enum State { Sleep, + #[default] Daylight, Override, Wakeup, @@ -45,19 +47,28 @@ fn filter(event: Event) -> Option { } } +#[dbstruct::dbstruct(db=sled)] +struct Store { + #[dbstruct(Default)] + state: State, +} + +super::impl_open_or_wipe!(Store); + pub async fn run( mut event_rx: broadcast::Receiver, // todo if state change message everyone using this _event_tx: broadcast::Sender, mut system: RestrictedSystem, -) { + tree: sled::Tree, +) -> color_eyre::Result<()> { #[derive(Debug)] enum Res { Event(RelevantEvent), ShouldUpdate, } - let mut state = State::Daylight; + let db = open_or_wipe(tree)?; let mut next_update = Instant::now() + INTERVAL; let wakeup_job = Job::every_day_at(10, 0, Event::WakeupKitchen, None); @@ -77,26 +88,26 @@ pub async fn run( let res = (get_event, tick).race().await; match res { Res::Event(RelevantEvent::Sleep) => { - state = State::Sleep; + db.state().set(&State::Sleep)?; system.all_lamps_off().await; } Res::Event(RelevantEvent::Wakeup) => { - state = State::Wakeup; + db.state().set(&State::Wakeup)?; trace!("Starting kitchen wakeup"); wakeup_some_lamps(&mut system).await; } Res::Event(RelevantEvent::Daylight) => { - state = State::Daylight; + db.state().set(&State::Daylight)?; update(&mut system).await; system.all_lamps_on().await; } Res::Event(RelevantEvent::Override) => { - state = State::Override; + db.state().set(&State::Override)?; system.all_lamps_ct(2000, 1.0).await; system.all_lamps_on().await; } Res::ShouldUpdate => { - if state == State::Daylight { + if db.state().get()? == State::Daylight { update(&mut system).await; system.all_lamps_on().await; } diff --git a/crates/brain/src/controller/rooms/large_bedroom.rs b/crates/brain/src/controller/rooms/large_bedroom.rs index de8f30f7..63774d93 100644 --- a/crates/brain/src/controller/rooms/large_bedroom.rs +++ b/crates/brain/src/controller/rooms/large_bedroom.rs @@ -1,7 +1,8 @@ -use std::time::Duration; +use std::time::{Duration, SystemTime}; use futures_concurrency::future::Race; use futures_util::FutureExt; +use serde::{Deserialize, Serialize}; use tokio::sync::broadcast; use tokio::time::{sleep_until, Instant}; use tracing::{info, warn}; @@ -9,11 +10,12 @@ use tracing::{info, warn}; use crate::controller::rooms::common::RecvFiltered; use crate::controller::{Event, RestrictedSystem}; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)] enum State { // Sleep, // Wakeup, - FadeOut(Instant), + FadeOut(SystemTime), + #[default] Normal, Bright, Off, @@ -51,18 +53,27 @@ fn filter(event: Event) -> Option { }) } +#[dbstruct::dbstruct(db=sled)] +struct Store { + #[dbstruct(Default)] + state: State, +} + +super::impl_open_or_wipe!(Store); + pub(crate) async fn run( mut event_rx: broadcast::Receiver, // todo if state change message everyone using this _event_tx: broadcast::Sender, mut system: RestrictedSystem, -) { + tree: sled::Tree, +) -> Result<(), color_eyre::Report> { enum Res { Event(RelevantEvent), ShouldUpdate, } - let mut state = State::Normal; + let db = open_or_wipe(tree)?; let mut next_update = Instant::now() + INTERVAL; loop { let get_event = event_rx.recv_filter_mapped(filter).map(Res::Event); @@ -73,15 +84,15 @@ pub(crate) async fn run( Res::Event(e) => handle_event(e), Res::ShouldUpdate => { next_update = Instant::now() + INTERVAL; - update(&mut system, &state).await + update(&mut system, &db.state().get()?).await } }; if let Some(new) = new_state { info!("transitioning to new state: {new:?}"); - state = new; + db.state().set(&new)?; next_update = Instant::now() + INTERVAL; - if update(&mut system, &state).await.is_some() { + if update(&mut system, &db.state().get()?).await.is_some() { warn!("Transiting to a new state while in the first update is not allowed") } } @@ -109,7 +120,7 @@ async fn update(system: &mut RestrictedSystem, state: &State) -> Option { // TODO: this was set to 1 mired (= 1M(!!) Kelvin) and 100% brightness // not sure that is the intended behaviour system.all_lamps_ct(3900, 1.0).await; - if started.elapsed() > Duration::from_secs(40) { + if !started.elapsed().is_ok_and(|t| t < Duration::from_secs(40)) { return Some(State::Off); } } @@ -151,7 +162,7 @@ fn handle_desk_button( println!("button pressed: {b:?}"); match b { Button::OneOfFour(press) if press.is_long() => Some(State::Off), - Button::OneOfFour(_) => Some(State::FadeOut(Instant::now())), + Button::OneOfFour(_) => Some(State::FadeOut(SystemTime::now())), Button::TwoOfFour(press) if press.is_long() => Some(State::Bright), Button::FourOfFour(press) if !press.is_long() => Some(State::Normal), // Button::TwoOfFour(_) => todo!(), @@ -170,7 +181,7 @@ fn handle_bed_button(b: protocol::large_bedroom::bed::Button) -> Option { match b { B::MiddleOuter(_) => Some(State::Bright), B::MiddleInner(_) => Some(State::Normal), - B::MiddleCenter(_) => Some(State::FadeOut(Instant::now())), + B::MiddleCenter(_) => Some(State::FadeOut(SystemTime::now())), _ => None, } } diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 1a5824b1..fa628062 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -36,11 +36,20 @@ const T0_00: f64 = time(0, 0); const T10_00: f64 = time(10, 0); const T21_00: f64 = time(21, 0); +#[dbstruct::dbstruct(db=sled)] +struct Store { + #[dbstruct(Default)] + state: State, +} + +super::impl_open_or_wipe!(Store); + pub async fn run( mut event_rx: broadcast::Receiver, event_tx: broadcast::Sender, system: RestrictedSystem, -) { + db: sled::Tree, +) -> color_eyre::Result<()> { let mut room = Room::new(event_tx, system.clone()); let mut next_update = Instant::now() + UPDATE_INTERVAL; let mut update_task: Option> = None; diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index a25b36da..e6988be8 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -20,11 +20,12 @@ use crate::controller::{Event, RestrictedSystem}; const MPD_IP: &str = "192.168.1.101"; const MPD_PORT: &str = "6600"; -#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)] +#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize, Default)] pub(crate) enum State { Sleep, SleepNoWakeup, Wakeup, + #[default] Daylight, Override, DelayedOff, diff --git a/crates/brain/src/errors.rs b/crates/brain/src/errors.rs deleted file mode 100644 index 5537f6a5..00000000 --- a/crates/brain/src/errors.rs +++ /dev/null @@ -1,11 +0,0 @@ -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error("Io error")] - IO(#[from] std::io::Error), - #[error("Could not parse yaml")] - YamlParsing(#[from] serde_yaml::Error), - #[error("Database error")] - DataBase(#[from] sled::Error), - #[error("Error contacting mpd")] - Mpd(#[from] mpd::error::Error), -} diff --git a/crates/brain/src/input/jobs.rs b/crates/brain/src/input/jobs.rs index 391e594a..790f9fb9 100644 --- a/crates/brain/src/input/jobs.rs +++ b/crates/brain/src/input/jobs.rs @@ -86,9 +86,10 @@ struct JobList { impl Jobs { pub(crate) fn setup( event_tx: broadcast::Sender, - db_path: &str, + db: sled::Db, ) -> Result { - let job_list = Arc::new(Mutex::new(JobList::new(db_path)?)); + let db = db.open_tree("JobList")?; + let job_list = Arc::new(Mutex::new(JobList::open_tree(db)?)); let (job_change_tx, job_change_rx) = mpsc::channel(250); let job_list_clone = job_list.clone(); @@ -106,7 +107,7 @@ impl Jobs { pub(crate) async fn add(&self, to_add: Job) -> Result { let id = { let list = self.list.lock().await; - list.add_job(to_add).await? + list.add_job(to_add)? }; //signal event timer to update its next job self.job_change_tx.send(()).await?; @@ -164,7 +165,7 @@ impl JobList { // we decrease the id for the job until there is a place in the database // after a job gets an id it is never changed /// return the id for the job - async fn add_job(&self, new_job: Job) -> Result { + fn add_job(&self, new_job: Job) -> Result { let mut new_id = new_job.time.timestamp().as_millisecond(); // create job entry if there is no job at this timestamp yet @@ -240,7 +241,6 @@ async fn event_timer( .lock() .await .add_job(new_job.clone()) - .await .unwrap(); trace!( "Added repeat job {new_job:#?} with id {new_id}" diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index d1f79696..f596401a 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -2,19 +2,18 @@ use std::array; use std::net::{IpAddr, SocketAddr}; use clap::Parser; +use color_eyre::eyre::eyre; use tokio::sync::broadcast; +use tokio::task::JoinSet; use self::input::jobs::Jobs; use self::system::System; mod controller; -mod errors; mod input; mod system; mod time; -const JOBS_DB_PATH: &str = "database/jobs"; - #[derive(Parser)] #[command(version, about, long_about=None)] struct Opt { @@ -37,7 +36,7 @@ struct Opt { } #[tokio::main] -async fn main() -> Result<(), Box> { +async fn main() -> Result<(), color_eyre::Report> { color_eyre::install().unwrap(); logger::tracing::setup(); let opt = Opt::parse(); @@ -47,13 +46,31 @@ async fn main() -> Result<(), Box> { let (event_tx, _event_rx) = broadcast::channel(250); let subscribed_rxs = array::from_fn(|_| event_tx.subscribe()); - let jobs = Jobs::setup(event_tx.clone(), JOBS_DB_PATH)?; + let db = sled::Config::default().path("database").open()?; + let jobs = Jobs::setup(event_tx.clone(), db.clone())?; let system = System::init(opt.mqtt_ip, jobs); - let _tasks = controller::start(subscribed_rxs, event_tx.clone(), system); + let tasks = + controller::start(subscribed_rxs, event_tx.clone(), system, db)?; // This never returns, should be replaced by an endless loop if (re)moved - input::sensors::subscribe(event_tx, opt.data_server).await; + let _subscribe = tokio::task::spawn(input::sensors::subscribe( + event_tx, + opt.data_server, + )); + + report_controller(tasks).await; + Err(eyre!("All tasks have failed! shutting down")) +} - unreachable!(); +async fn report_controller(mut tasks: JoinSet>) { + while let Some(failure) = tasks.join_next().await { + match failure { + Ok(Ok(())) => { + tracing::error!("Task returned, tasks should never return!") + } + Ok(Err(e)) => tracing::error!("Task returned an error: {e}"), + Err(e) => tracing::error!("Task could not join: {e}"), + } + } } From 5b81154294b04101ad15982e2912b5773b14f665 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sun, 9 Nov 2025 15:31:34 +0100 Subject: [PATCH 679/687] adds persistance to small bedroom --- Cargo.toml | 2 +- crates/brain/src/controller/mod.rs | 42 ++++- .../src/controller/rooms/small_bedroom.rs | 58 +++---- .../controller/rooms/small_bedroom/state.rs | 152 +++++++++++------- crates/brain/src/input/sensors.rs | 2 +- crates/brain/src/main.rs | 22 +-- crates/zigbee-bridge/src/device.rs | 2 +- 7 files changed, 166 insertions(+), 114 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 947da175..bab28ae9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ thiserror = "2" reserve-port = "2.2.0" [workspace.package] -rust-version = "1.82" +rust-version = "1.91" edition = "2021" license = "GPLv3" authors = ["David Kleingeld & Eva van Houten"] diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 19c2b3ff..cb583f35 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -1,11 +1,13 @@ mod rooms; +use std::future::Future; + use crate::system::System; use color_eyre::eyre::Context; pub use protocol::Reading; use serde::{Deserialize, Serialize}; use tokio::sync::broadcast; -use tokio::task::JoinSet; +use tokio::task::{JoinSet, LocalSet}; #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum Event { @@ -92,14 +94,41 @@ impl RestrictedSystem { } } +#[derive(Default)] +pub struct ControllerTasks { + tasks: JoinSet>, + local_set: LocalSet, +} + +impl ControllerTasks { + fn spawn(&mut self, future: F) + where + F: Future> + 'static, + { + self.tasks.spawn_local_on(future, &self.local_set); + } + + pub async fn report_failed(&mut self) { + while let Some(failure) = self.tasks.join_next().await { + match failure { + Ok(Ok(())) => { + tracing::error!("Task returned, tasks should never return!") + } + Ok(Err(e)) => tracing::error!("Task returned an error: {e}"), + Err(e) => tracing::error!("Task could not join: {e}"), + } + } + } +} + pub fn start( subscribed: [broadcast::Receiver; 4], sender: broadcast::Sender, system: System, db: sled::Db, -) -> Result>, color_eyre::Report> { +) -> Result { tracing::info!("starting"); - let mut tasks = JoinSet::new(); + let mut tasks = ControllerTasks::default(); let [rx1, rx2, rx3, rx4] = subscribed; let restricted = RestrictedSystem { @@ -135,7 +164,12 @@ pub fn start( let ds = db .open_tree("small_bedroom") .wrap_err("Opening db subtree for small_bedroom")?; - tasks.spawn(rooms::small_bedroom::run(rx2, sender.clone(), restricted, ds)); + tasks.spawn(rooms::small_bedroom::run( + rx2, + sender.clone(), + restricted, + ds, + )); let restricted = RestrictedSystem { system: system.clone(), diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index fa628062..6cd2fa83 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -26,7 +26,7 @@ mod state; const UPDATE_INTERVAL: Duration = Duration::from_secs(5); const OFF_DELAY: Duration = Duration::from_secs(60); -const WAKEUP_EXPIRATION: Duration = Duration::from_secs(1800); + const NAP_TIME: Duration = Duration::from_secs(30 * 60); const fn time(hour: i8, minute: i8) -> f64 { @@ -36,23 +36,15 @@ const T0_00: f64 = time(0, 0); const T10_00: f64 = time(10, 0); const T21_00: f64 = time(21, 0); -#[dbstruct::dbstruct(db=sled)] -struct Store { - #[dbstruct(Default)] - state: State, -} - -super::impl_open_or_wipe!(Store); - pub async fn run( mut event_rx: broadcast::Receiver, event_tx: broadcast::Sender, system: RestrictedSystem, db: sled::Tree, ) -> color_eyre::Result<()> { - let mut room = Room::new(event_tx, system.clone()); + let mut room = Room::new(event_tx, system.clone(), db)?; let mut next_update = Instant::now() + UPDATE_INTERVAL; - let mut update_task: Option> = None; + let mut update_task: Option>> = None; let res = system .system @@ -73,35 +65,36 @@ pub async fn run( event @ RelevantEvent::Button(_) | event @ RelevantEvent::PortableButton(_), ) => { - handle_button(&mut room, event).await; + handle_button(&mut room, event).await?; } Trigger::Event(RelevantEvent::RadiatorOverride) => { // trace!("Starting radiator override"); // room.start_radiator_override(); } - Trigger::Event(RelevantEvent::Wakeup) => room.set_wakeup().await, + Trigger::Event(RelevantEvent::Wakeup) => room.set_wakeup().await?, Trigger::Event(RelevantEvent::Pm2_5(val)) => { - room.pm2_5 = Some((val, crate::time::now())) + room.store.pm2_5().set(Some(&(val, crate::time::now())))?; } Trigger::ShouldUpdate => { // We don't want this to block if it takes a while, so // we spawn a separate task for it that we need to abort // in case it hangs update_task.map(|task| task.abort()); - update_task = Some(task::spawn(update(room.clone()))); + update_task = Some(task::spawn_local(update(room.clone()))); next_update = Instant::now() + UPDATE_INTERVAL; } } } } -async fn update(mut room: Room) { - room.update_airbox().await; - room.update_radiator().await; - room.all_lights_daylight().await; +async fn update(mut room: Room) -> color_eyre::Result<()> { + room.update_airbox().await?; + room.update_radiator().await?; + room.all_lights_daylight().await?; + Ok(()) } -async fn handle_button(room: &mut Room, event: RelevantEvent) { +async fn handle_button(room: &mut Room, event: RelevantEvent) -> color_eyre::Result<()> { use portable_button_panel::Reading as P; use ButtonPanel as B; @@ -111,7 +104,7 @@ async fn handle_button(room: &mut Room, event: RelevantEvent) { handle_audio_button(room, event).await; } B::BottomLeft(_) | B::BottomMiddle(_) | B::BottomRight(_) => { - handle_light_button(room, event).await; + handle_light_button(room, event).await?; } }, event @ RelevantEvent::PortableButton(button) => match button { @@ -127,12 +120,13 @@ async fn handle_button(room: &mut Room, event: RelevantEvent) { handle_audio_button(room, event).await; } P::Dots1ShortRelease | P::Dots2ShortRelease => { - handle_light_button(room, event).await; + handle_light_button(room, event).await?; } b => info!("Pressed unimplemented button: {b:?}"), }, _ => unreachable!(), } + Ok(()) } async fn handle_audio_button(room: &mut Room, button_event: RelevantEvent) { @@ -209,7 +203,10 @@ async fn handle_audio_button(room: &mut Room, button_event: RelevantEvent) { } } -async fn handle_light_button(room: &mut Room, event: RelevantEvent) { +async fn handle_light_button( + room: &mut Room, + event: RelevantEvent, +) -> color_eyre::Result<()> { use portable_button_panel::Reading as P; use ButtonPanel as B; use RelevantEvent as E; @@ -219,24 +216,27 @@ async fn handle_light_button(room: &mut Room, event: RelevantEvent) { // Dots2 short: wakeup match event { // Light buttons - E::Button(B::BottomLeft(_)) => room.set_sleep_delayed().await, + E::Button(B::BottomLeft(_)) => room.set_sleep_delayed().await?, E::PortableButton(P::Dots1ShortRelease) => { let now = crate::time::now(); match time(now.hour(), now.minute()) { // rust analyzer seems to think this illegal, its not T21_00.. | T0_00..T10_00 => { - room.toggle_sleep_nightlight().await + + room.toggle_sleep_nightlight().await? } - _ => room.toggle_sleep_daylight().await, + _ => room.toggle_sleep_daylight().await?, } } - E::Button(B::BottomMiddle(_)) => room.set_daylight().await, + E::Button(B::BottomMiddle(_)) => room.set_daylight().await?, E::PortableButton(P::Dots2ShortRelease) => { - room.set_wakeup().await; + room.set_wakeup().await?; } - E::Button(B::BottomRight(_)) => room.set_override().await, + E::Button(B::BottomRight(_)) => room.set_override().await?, _ => (), } + + Ok(()) } pub(super) fn is_nap_time() -> bool { diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index e6988be8..7c5be239 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -1,11 +1,12 @@ use std::sync::Arc; use std::time::Duration; +use color_eyre::Result; use jiff::Zoned; use serde::{Deserialize, Serialize}; use tokio::io::AsyncWriteExt; use tokio::net::TcpStream; -use tokio::sync::{broadcast, Mutex, RwLock}; +use tokio::sync::{broadcast, Mutex}; use tokio::task::{self, JoinHandle}; use tokio::time::sleep; use tracing::{trace, warn}; @@ -32,36 +33,44 @@ pub(crate) enum State { Nightlight, } -#[derive(Clone)] -pub(super) struct Room { - state: Arc>, +#[dbstruct::dbstruct(db=sled)] +pub(super) struct Store { + #[dbstruct(Default)] + state: State, radiator_override: Option, pub(super) pm2_5: Option<(f32, Zoned)>, +} + +#[derive(Clone)] +pub(super) struct Room { + pub(super) store: Arc, system: RestrictedSystem, event_tx: broadcast::Sender, - task_handle: Arc>>>, + task_handle: Arc>>>>, pub(super) audio_controller: Arc>, } +super::super::impl_open_or_wipe!(Store); + impl Room { pub(super) fn new( event_tx: broadcast::Sender, system: RestrictedSystem, - ) -> Self { - Self { - state: Arc::new(RwLock::new(State::Daylight)), - radiator_override: None, - pm2_5: None, + db: sled::Tree, + ) -> Result { + let store = Arc::new(open_or_wipe(db)?); + Ok(Self { + store, system, event_tx, task_handle: Arc::new(Mutex::new(None)), audio_controller: Arc::new(Mutex::new(AudioController::new( MPD_IP, MPD_PORT, ))), - } + }) } - pub(super) async fn update_radiator(&mut self) { + pub(super) async fn update_radiator(&mut self) -> Result<()> { trace!("Updating radiator"); // trace!( // "Room radiator override state: {:?}", @@ -82,113 +91,124 @@ impl Room { let goal_temp = goal_temp_now(); // trace!("Override is either not set or expired, set to goal temp: {goal_temp}"); self.system.set_radiators_setpoint(goal_temp).await; - self.radiator_override = None; + self.store.radiator_override().set(None)?; + + Ok(()) } #[allow(unused)] //TODO: fix radiator override - pub(crate) fn start_radiator_override(&mut self) { + pub(crate) fn start_radiator_override(&mut self) -> Result<()> { // Don't set if the radiator resends the manual state - if self.radiator_override.is_none() { + if self.store.radiator_override().is_none()? { warn!("Setting radiator override to now"); let now = crate::time::now(); - self.radiator_override = Some(now); + self.store.radiator_override().set(Some(&now)); } + + Ok(()) } - pub(super) async fn toggle_sleep_daylight(&mut self) { - let state = { self.state.read().await.clone() }; + pub(super) async fn toggle_sleep_daylight(&mut self) -> Result<()> { + let state = self.store.state().get()?; match state { State::Sleep | State::SleepNoWakeup => { - self.set_daylight().await; + self.set_daylight().await?; } State::Daylight | State::Wakeup | State::Override | State::DelayedOff | State::Nightlight => { - self.set_sleep_immediate().await; + self.set_sleep_immediate().await?; } } + Ok(()) } - pub(super) async fn toggle_sleep_nightlight(&mut self) { - let state = { self.state.read().await.clone() }; + pub(super) async fn toggle_sleep_nightlight(&mut self) -> Result<()> { + let state = self.store.state().get()?; match state { State::Sleep | State::SleepNoWakeup => { - self.set_nightlight().await; + self.set_nightlight().await?; } State::Daylight | State::Wakeup | State::Override | State::DelayedOff | State::Nightlight => { - self.set_sleep_immediate().await; + self.set_sleep_immediate().await?; } } + Ok(()) } - pub(super) async fn set_sleep_immediate(&mut self) { + pub(super) async fn set_sleep_immediate(&mut self) -> Result<()> { self.system.all_lamps_off().await; - self.set_state_cancel_prev(State::Sleep).await; + self.set_state_cancel_prev(State::Sleep).await?; + Ok(()) } - pub(super) async fn set_sleep_no_wakeup(&mut self) { - self.system.all_lamps_off().await; - self.set_state_cancel_prev(State::SleepNoWakeup).await; - } - - pub(super) async fn set_sleep_delayed(&mut self) { - self.set_state_cancel_prev(State::DelayedOff).await; + pub(super) async fn set_sleep_delayed(&mut self) -> Result<()> { + self.set_state_cancel_prev(State::DelayedOff).await?; self.system.one_lamp_off("small_bedroom:bureau").await; self.system.one_lamp_off("small_bedroom:piano").await; - let task_handle = task::spawn(self.clone().delayed_off_then_sleep()); + let task_handle = + task::spawn_local(self.clone().delayed_off_then_sleep()); *self.task_handle.lock().await = Some(task_handle); + Ok(()) } - pub(super) async fn set_wakeup(&mut self) { - if *self.state.read().await == State::SleepNoWakeup { + pub(super) async fn set_wakeup(&mut self) -> Result<()> { + if self.store.state().get()? == State::SleepNoWakeup { warn!("Ignoring wakeup because of override"); - return; + return Ok(()); } warn!("Starting wakeup"); - self.set_state_cancel_prev(State::Wakeup).await; + self.set_state_cancel_prev(State::Wakeup).await?; - let task_handle = task::spawn(self.clone().run_wakeup_then_daylight()); + let task_handle = + task::spawn_local(self.clone().run_wakeup_then_daylight()); *self.task_handle.lock().await = Some(task_handle); + Ok(()) } - pub(super) async fn set_daylight(&mut self) { - self.set_state_cancel_prev(State::Daylight).await; - self.all_lights_daylight().await; + pub(super) async fn set_daylight(&mut self) -> Result<()> { + self.set_state_cancel_prev(State::Daylight).await?; + self.all_lights_daylight().await?; self.system.all_lamps_on().await; + Ok(()) } - pub(super) async fn set_nightlight(&mut self) { - self.set_state_cancel_prev(State::Nightlight).await; + pub(super) async fn set_nightlight(&mut self) -> Result<()> { + self.set_state_cancel_prev(State::Nightlight).await?; self.system .one_lamp_ct("small_bedroom:ceiling", 1800, 0.1) .await; self.system.one_lamp_on("small_bedroom:ceiling").await; + Ok(()) } - pub(super) async fn set_override(&mut self) { - self.set_state_cancel_prev(State::Override).await; + pub(super) async fn set_override(&mut self) -> Result<()> { + self.set_state_cancel_prev(State::Override).await?; self.system.all_lamps_ct(2000, 1.0).await; self.system.all_lamps_on().await; + Ok(()) } - async fn set_state_cancel_prev(&mut self, state: State) { + async fn set_state_cancel_prev(&mut self, state: State) -> Result<()> { self.cancel_task().await; - *self.state.write().await = state.clone(); + self.store.state().set(&state)?; let _ = self.event_tx.send(Event::StateChangeSB(state)); + Ok(()) } - async fn set_state(&mut self, state: State) { - *self.state.write().await = state.clone(); + async fn set_state(&mut self, state: State) -> Result<()> { + self.store.state().set(&state)?; let _ = self.event_tx.send(Event::StateChangeSB(state)); + Ok(()) } async fn cancel_task(&mut self) { @@ -197,20 +217,23 @@ impl Room { } } - async fn delayed_off_then_sleep(mut self) { + async fn delayed_off_then_sleep(mut self) -> Result<()> { sleep(OFF_DELAY).await; self.system.all_lamps_off().await; - self.set_state(State::Sleep).await; + self.set_state(State::Sleep).await?; if is_nap_time() { sleep(NAP_TIME).await; - self.set_state(State::Daylight).await; - self.all_lights_daylight().await; + self.set_state(State::Daylight).await?; + self.all_lights_daylight().await?; self.system.all_lamps_on().await; } + Ok(()) } - async fn run_wakeup_then_daylight(mut self) { + // Returns result simply so the task handle when this is spawned as a task + // is the same as for the other function + async fn run_wakeup_then_daylight(mut self) -> Result<()> { const LIGHT_NAME: &str = "small_bedroom:ceiling"; const RUNTIME_MINS: i32 = 5; const MUSIC_ON_AFTER_MINS: i32 = 5; @@ -252,28 +275,33 @@ impl Room { } } - self.set_state(State::Daylight).await; - self.all_lights_daylight().await; + self.set_state(State::Daylight).await?; + self.all_lights_daylight().await?; self.system.all_lamps_on().await; warn!("Wakeup done"); + + Ok(()) } // TODO: make private once updates are in job system - pub(super) async fn all_lights_daylight(&mut self) { - if *self.state.read().await == State::Daylight { + pub(super) async fn all_lights_daylight(&mut self) -> Result<()> { + if self.store.state().get()? == State::Daylight { let (new_ct, new_bri) = daylight_now(); self.system.all_lamps_ct(new_ct, new_bri).await; } + Ok(()) } - pub(crate) async fn update_airbox(&self) { - let Some(setting) = air_filtration_now(&self.pm2_5) else { - return; + pub(crate) async fn update_airbox(&self) -> Result<()> { + let Some(setting) = air_filtration_now(&self.store.pm2_5().get()?) + else { + return Ok(()); }; if let Ok(mut stream) = TcpStream::connect("192.168.1.103:4444").await { let message: u16 = 0xDD00 + setting; let _ = stream.write(&message.to_le_bytes()).await; } + Ok(()) } } diff --git a/crates/brain/src/input/sensors.rs b/crates/brain/src/input/sensors.rs index bcc84637..71199913 100644 --- a/crates/brain/src/input/sensors.rs +++ b/crates/brain/src/input/sensors.rs @@ -14,7 +14,7 @@ pub async fn subscribe( loop { match sub.next().await { SubMessage::Reading(reading) => { - event_tx.send(Event::Sensor(reading)).unwrap(); + event_tx.send(Event::Sensor(dbg!(reading))).unwrap(); } SubMessage::ErrorReport(_) | SubMessage::AffectorControlled { .. } => continue, diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index f596401a..a8a83eb1 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -4,7 +4,6 @@ use std::net::{IpAddr, SocketAddr}; use clap::Parser; use color_eyre::eyre::eyre; use tokio::sync::broadcast; -use tokio::task::JoinSet; use self::input::jobs::Jobs; use self::system::System; @@ -46,11 +45,14 @@ async fn main() -> Result<(), color_eyre::Report> { let (event_tx, _event_rx) = broadcast::channel(250); let subscribed_rxs = array::from_fn(|_| event_tx.subscribe()); - let db = sled::Config::default().path("database").open()?; + let db = sled::Config::default() + .cache_capacity(4_000_000) + .path("database") + .open()?; let jobs = Jobs::setup(event_tx.clone(), db.clone())?; let system = System::init(opt.mqtt_ip, jobs); - let tasks = + let mut tasks = controller::start(subscribed_rxs, event_tx.clone(), system, db)?; // This never returns, should be replaced by an endless loop if (re)moved @@ -59,18 +61,6 @@ async fn main() -> Result<(), color_eyre::Report> { opt.data_server, )); - report_controller(tasks).await; + tasks.report_failed().await; Err(eyre!("All tasks have failed! shutting down")) } - -async fn report_controller(mut tasks: JoinSet>) { - while let Some(failure) = tasks.join_next().await { - match failure { - Ok(Ok(())) => { - tracing::error!("Task returned, tasks should never return!") - } - Ok(Err(e)) => tracing::error!("Task returned an error: {e}"), - Err(e) => tracing::error!("Task could not join: {e}"), - } - } -} diff --git a/crates/zigbee-bridge/src/device.rs b/crates/zigbee-bridge/src/device.rs index d60c1fea..47a85d1a 100644 --- a/crates/zigbee-bridge/src/device.rs +++ b/crates/zigbee-bridge/src/device.rs @@ -62,7 +62,7 @@ impl Clone for Box { } } -pub(crate) fn init_states() -> HashMap> { +pub(crate) fn init_states() -> HashMap> { let mut states = HashMap::new(); for (light_name, _) in LIGHT_MODELS { let device: Box = Box::new(Lamp::new(light_name)); From d5cdf1d80f968f04b1c59c1b3938b7c76056d091 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 9 Nov 2025 15:48:24 +0100 Subject: [PATCH 680/687] Fix tasks not running Disabled reporting of tasks failure --- Cargo.lock | 2 ++ crates/brain/Cargo.toml | 3 +-- crates/brain/src/controller/mod.rs | 4 ++++ crates/brain/src/controller/rooms/small_bedroom.rs | 1 + crates/brain/src/input/sensors.rs | 2 +- crates/brain/src/main.rs | 7 +++++-- 6 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f80bb1d6..3fc2b3fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -752,6 +752,7 @@ dependencies = [ [[package]] name = "dbstruct" version = "0.6.0" +source = "git+https://github.com/dvdsk/dbstruct#5ecca3460f19f34e816ae50f7b199c15f1b21b02" dependencies = [ "bincode 2.0.1", "dbstruct-derive", @@ -764,6 +765,7 @@ dependencies = [ [[package]] name = "dbstruct-derive" version = "0.4.0" +source = "git+https://github.com/dvdsk/dbstruct#5ecca3460f19f34e816ae50f7b199c15f1b21b02" dependencies = [ "itertools 0.14.0", "proc-macro-error", diff --git a/crates/brain/Cargo.toml b/crates/brain/Cargo.toml index 1dba679d..4e148408 100644 --- a/crates/brain/Cargo.toml +++ b/crates/brain/Cargo.toml @@ -31,7 +31,6 @@ tracing = {workspace = true} logger.workspace = true clap = { workspace = true } futures-concurrency = { workspace = true } -# dbstruct = { git = "https://github.com/dvdsk/dbstruct" } -dbstruct = { path = "/home/david/Documents/dbstruct" } +dbstruct = { git = "https://github.com/dvdsk/dbstruct" } color-eyre.workspace = true mpdrs = "0.1.0" diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index cb583f35..7ba204b7 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -108,6 +108,10 @@ impl ControllerTasks { self.tasks.spawn_local_on(future, &self.local_set); } + pub async fn await_tasks(self) { + self.local_set.await; + } + pub async fn report_failed(&mut self) { while let Some(failure) = self.tasks.join_next().await { match failure { diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 6cd2fa83..738dd454 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -42,6 +42,7 @@ pub async fn run( system: RestrictedSystem, db: sled::Tree, ) -> color_eyre::Result<()> { + trace!("Running small bedroom task"); let mut room = Room::new(event_tx, system.clone(), db)?; let mut next_update = Instant::now() + UPDATE_INTERVAL; let mut update_task: Option>> = None; diff --git a/crates/brain/src/input/sensors.rs b/crates/brain/src/input/sensors.rs index 71199913..bcc84637 100644 --- a/crates/brain/src/input/sensors.rs +++ b/crates/brain/src/input/sensors.rs @@ -14,7 +14,7 @@ pub async fn subscribe( loop { match sub.next().await { SubMessage::Reading(reading) => { - event_tx.send(Event::Sensor(dbg!(reading))).unwrap(); + event_tx.send(Event::Sensor(reading)).unwrap(); } SubMessage::ErrorReport(_) | SubMessage::AffectorControlled { .. } => continue, diff --git a/crates/brain/src/main.rs b/crates/brain/src/main.rs index a8a83eb1..03d8ef7b 100644 --- a/crates/brain/src/main.rs +++ b/crates/brain/src/main.rs @@ -52,7 +52,7 @@ async fn main() -> Result<(), color_eyre::Report> { let jobs = Jobs::setup(event_tx.clone(), db.clone())?; let system = System::init(opt.mqtt_ip, jobs); - let mut tasks = + let tasks = controller::start(subscribed_rxs, event_tx.clone(), system, db)?; // This never returns, should be replaced by an endless loop if (re)moved @@ -61,6 +61,9 @@ async fn main() -> Result<(), color_eyre::Report> { opt.data_server, )); - tasks.report_failed().await; + tasks.await_tasks().await; + + // TODO: re-enable this by joining? with await_tasks + // tasks.report_failed().await; Err(eyre!("All tasks have failed! shutting down")) } From e30d89f63762bfe97efa0a51bcc0f4ca051429ff Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sun, 23 Nov 2025 18:55:39 +0100 Subject: [PATCH 681/687] Tweak temperatures --- crates/brain/src/controller/rooms/small_bedroom.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 738dd454..8b7eda55 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -249,16 +249,15 @@ pub(super) fn is_nap_time() -> bool { pub(crate) fn goal_temp_now() -> f64 { let goals = BTreeMap::from([ - ((0, 00), 18.0), - ((10, 00), 19.0), + ((0, 00), 19.0), + ((10, 00), 19.5), ((11, 00), 21.0), ((12, 00), 22.0), - ((18, 00), 20.5), ((19, 00), 10.0), - ((21, 00), 18.0), + ((21, 00), 19.0), ]); - goal_now(goals, 18.0) + goal_now(goals, 19.0) } fn air_filtration_now(pm2_5_measurement: &Option<(f32, Zoned)>) -> Option { From 2f15bbb386e98999d826568ec87794020ca8b6b7 Mon Sep 17 00:00:00 2001 From: Yara Date: Tue, 9 Dec 2025 21:57:40 +0100 Subject: [PATCH 682/687] adds nix flake --- Cargo.toml | 1 + crates/data-server/tests/subscriber_api.rs | 2 +- crates/text-widget/Cargo.toml | 1 + crates/ui/Cargo.toml | 2 + flake.lock | 82 +++++++++++++++++ flake.nix | 102 +++++++++++++++++++++ rust-toolchain.toml | 10 ++ 7 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 rust-toolchain.toml diff --git a/Cargo.toml b/Cargo.toml index bab28ae9..5a84949b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ resolver = "2" members = ["crates/*"] exclude = ["nodes/embassy/bed-lb", "nodes/embassy/bed-sb", "nodes/esp32/airbox"] +description = "services and ui/interfaces to home automation system" [workspace.dependencies] data-server = { path = "crates/data-server" } diff --git a/crates/data-server/tests/subscriber_api.rs b/crates/data-server/tests/subscriber_api.rs index d5708b46..be166ee4 100644 --- a/crates/data-server/tests/subscriber_api.rs +++ b/crates/data-server/tests/subscriber_api.rs @@ -80,7 +80,7 @@ async fn subscribe_and_receive_inner(sub_port: u16) -> Result { } async fn list_affectors_inner(sub_port: u16) -> Result { - tokio::time::sleep(Duration::from_millis(500)).await; + tokio::time::sleep(Duration::from_millis(1000)).await; let list = Client::connect( (Ipv4Addr::LOCALHOST, sub_port), "api_integration_tests".to_owned(), diff --git a/crates/text-widget/Cargo.toml b/crates/text-widget/Cargo.toml index 681a6d74..48793364 100644 --- a/crates/text-widget/Cargo.toml +++ b/crates/text-widget/Cargo.toml @@ -5,6 +5,7 @@ rust-version.workspace = true edition.workspace = true license.workspace = true authors.workspace = true +description = "Widget for a desktop environment bar which displays sensor readings" [dependencies] clap.workspace = true diff --git a/crates/ui/Cargo.toml b/crates/ui/Cargo.toml index c35eddf5..8efa5bb2 100644 --- a/crates/ui/Cargo.toml +++ b/crates/ui/Cargo.toml @@ -1,8 +1,10 @@ [package] name = "ui" +version = "0.1.0" edition.workspace = true license.workspace = true authors.workspace = true +description = "A tui app for viewing data from and controlling the home automation system" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..bf0440ad --- /dev/null +++ b/flake.lock @@ -0,0 +1,82 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1765186076, + "narHash": "sha256-hM20uyap1a0M9d344I692r+ik4gTMyj60cQWO+hAYP8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "addf7cf5f383a3101ecfba091b98d0a1263dc9b8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1765248027, + "narHash": "sha256-ngar+yP06x3+2k2Iey29uU0DWx5ur06h3iPBQXlU+yI=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "7b50ad68415ae5be7ee4cc68fa570c420741b644", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..860e5c30 --- /dev/null +++ b/flake.nix @@ -0,0 +1,102 @@ +{ + description = "Home automation system, services and ui/interfaces"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs = { + nixpkgs.follows = "nixpkgs"; + }; + }; + }; + + outputs = { self, nixpkgs, flake-utils, rust-overlay }: + flake-utils.lib.eachDefaultSystem + (system: + let + overlays = [ (import rust-overlay) ]; + pkgs = import nixpkgs { inherit system overlays; }; + rustToolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; + rust = pkgs.makeRustPlatform { + cargo = rustToolchain; + rustc = rustToolchain; + }; + + src = ./.; + cargoLock = { + lockFile = "${src}/Cargo.lock"; + outputHashes = { + "bme280-0.5.1" = "sha256-EV1V6XeYxjoIwI/mzTJp1CZriYKucCr14SkRWC8DaLE="; + "byteseries-0.7.1" = "sha256-Gz+uj56L5iCL6gHSEq9uFYLKYUaMXKkhWx8RhNKH77c="; + "colorimetry-0.0.2" = "sha256-Olxp0GMmUDDfeUiTusScwAidY5POOoe45K8ezAojN4Q="; + "dbstruct-0.6.0" = "sha256-3ACZN0+MJe3r9l/0/Lif3004D8NlBYs56gH3UQWqotY="; + "tui-tree-widget-0.23.0" = "sha256-rVHmuBg6x592pNBTzjVbzQ87J8HlbTAY9vz8ZPJwmYc="; + }; + }; + + #################################################################### + #### text widget package #### + #################################################################### + text-widget = with pkgs; let + cargoTOML = lib.importTOML "${src}/crates/text-widget/Cargo.toml"; + inherit rustToolchain rust; + in + rust.buildRustPackage + { + pname = cargoTOML.package.name; + version = cargoTOML.package.version; + + inherit src cargoLock; + + meta = { + inherit (cargoTOML.package) description homepage; + maintainers = cargoTOML.package.authors; + }; + }; + + + #################################################################### + #### text widget package #### + #################################################################### + ui = with pkgs; let + cargoTOML = lib.importTOML "${src}/crates/ui/Cargo.toml"; + inherit rustToolchain rust; + in + rust.buildRustPackage + { + pname = cargoTOML.package.name; + version = cargoTOML.package.version; + + inherit src cargoLock; + + meta = { + inherit (cargoTOML.package) description homepage; + maintainers = cargoTOML.package.authors; + }; + }; + + #################################################################### + #### dev shell #### + #################################################################### + devShell = with pkgs; + mkShell { + name = "ha"; + inputsFrom = [ text-widget ]; + RUST_SRC_PATH = "${rustPlatform.rustLibSrc}"; + CARGO_TERM_COLOR = "always"; + }; + in + { + ui = ui; + devShells.default = devShell; + defaultPackage = text-widget; + }) // { + overlays.default = _: prev: { + text-widget = self.defaultPackage.${prev.system}; + ui = self.${prev.system}.ui; + }; + # nixosModules.break-enforcer = ./nix_module.nix; + }; +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 00000000..b3d725d7 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,10 @@ +[toolchain] +channel = "1.91" +components = [ + "rustc", + "cargo", + "clippy", + "rustfmt", + "rust-analyzer", + "rust-src", +] From 8e776fc313d26d80258584889babb4bfadceb9c4 Mon Sep 17 00:00:00 2001 From: Yara Date: Tue, 9 Dec 2025 22:09:38 +0100 Subject: [PATCH 683/687] fix flake --- flake.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index 860e5c30..8186c7b7 100644 --- a/flake.nix +++ b/flake.nix @@ -95,8 +95,7 @@ }) // { overlays.default = _: prev: { text-widget = self.defaultPackage.${prev.system}; - ui = self.${prev.system}.ui; + ui = self.${prev.system}; }; - # nixosModules.break-enforcer = ./nix_module.nix; }; } From 946224a8a6ac9eb10d6941536c5a5206e671ab8d Mon Sep 17 00:00:00 2001 From: Yara Date: Tue, 9 Dec 2025 22:20:28 +0100 Subject: [PATCH 684/687] fixy --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 8186c7b7..ce5c564e 100644 --- a/flake.nix +++ b/flake.nix @@ -95,7 +95,7 @@ }) // { overlays.default = _: prev: { text-widget = self.defaultPackage.${prev.system}; - ui = self.${prev.system}; + ui = self.ui.${prev.system}; }; }; } From 07f41347d1bd064ddc7c006a190ee0c5d500e6bb Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 12 Dec 2025 14:29:57 +0100 Subject: [PATCH 685/687] Update lamp models for new lamps --- Cargo.lock | 2 +- crates/brain/src/controller/mod.rs | 2 +- .../src/controller/rooms/small_bedroom/state.rs | 6 +++--- crates/zigbee-bridge/src/lamp/color_correction.rs | 14 ++++++++++---- crates/zigbee-bridge/src/lamp/model.rs | 12 ++++++++++-- crates/zigbee-bridge/src/lib.rs | 4 ++-- 6 files changed, 27 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3fc2b3fd..9b9bc349 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3665,7 +3665,7 @@ checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "ui" -version = "0.0.0" +version = "0.1.0" dependencies = [ "clap", "color-eyre", diff --git a/crates/brain/src/controller/mod.rs b/crates/brain/src/controller/mod.rs index 7ba204b7..c17ffb4d 100644 --- a/crates/brain/src/controller/mod.rs +++ b/crates/brain/src/controller/mod.rs @@ -159,7 +159,7 @@ pub fn start( let restricted = RestrictedSystem { system: system.clone(), allowed_lights: vec![ - "small_bedroom:ceiling", + "small_bedroom:table", "small_bedroom:bureau", "small_bedroom:piano", ], diff --git a/crates/brain/src/controller/rooms/small_bedroom/state.rs b/crates/brain/src/controller/rooms/small_bedroom/state.rs index 7c5be239..12a19290 100644 --- a/crates/brain/src/controller/rooms/small_bedroom/state.rs +++ b/crates/brain/src/controller/rooms/small_bedroom/state.rs @@ -185,9 +185,9 @@ impl Room { pub(super) async fn set_nightlight(&mut self) -> Result<()> { self.set_state_cancel_prev(State::Nightlight).await?; self.system - .one_lamp_ct("small_bedroom:ceiling", 1800, 0.1) + .one_lamp_ct("small_bedroom:table", 1800, 0.1) .await; - self.system.one_lamp_on("small_bedroom:ceiling").await; + self.system.one_lamp_on("small_bedroom:table").await; Ok(()) } @@ -234,7 +234,7 @@ impl Room { // Returns result simply so the task handle when this is spawned as a task // is the same as for the other function async fn run_wakeup_then_daylight(mut self) -> Result<()> { - const LIGHT_NAME: &str = "small_bedroom:ceiling"; + const LIGHT_NAME: &str = "small_bedroom:table"; const RUNTIME_MINS: i32 = 5; const MUSIC_ON_AFTER_MINS: i32 = 5; diff --git a/crates/zigbee-bridge/src/lamp/color_correction.rs b/crates/zigbee-bridge/src/lamp/color_correction.rs index 95c7528c..e1524a38 100644 --- a/crates/zigbee-bridge/src/lamp/color_correction.rs +++ b/crates/zigbee-bridge/src/lamp/color_correction.rs @@ -40,7 +40,10 @@ fn blackbody_table(model: &Model) -> BTreeMap { (4113, 0.0037), ], // LCA005 data - Model::HueGen1 | Model::HueGen2 | Model::HueOther(_) => vec![ + Model::HueGen1 + | Model::HueGen2 + | Model::Hue1600Lm + | Model::HueOther(_) => vec![ (1998, 0.0005), (2197, 0.00000), (2519, -0.0004), @@ -87,7 +90,10 @@ fn temp_table(model: &Model) -> BTreeMap { vec![(2200, 70.), (2700, -40.), (4000, 20.)] } // A19 Color 9.5W data - Model::HueGen1 | Model::HueGen2 | Model::HueOther(_) => { + Model::HueGen1 + | Model::HueGen2 + | Model::Hue1600Lm + | Model::HueOther(_) => { vec![ (2200, 2.), (2700, 5.), @@ -124,8 +130,8 @@ fn interpolate(temp: usize, table: BTreeMap) -> f64 { if let (Some(smaller), Some(larger)) = (smaller, larger) { // Linear interpolation return smaller.1 - + (temp - smaller.0) as f64 * (larger.1 - smaller.1) - / (*larger.0 as f64 - *smaller.0 as f64); + + (temp - smaller.0) as f64 * (larger.1 - smaller.1) + / (*larger.0 as f64 - *smaller.0 as f64); } match smaller.or(larger) { diff --git a/crates/zigbee-bridge/src/lamp/model.rs b/crates/zigbee-bridge/src/lamp/model.rs index f3eb7fef..7354dc4f 100644 --- a/crates/zigbee-bridge/src/lamp/model.rs +++ b/crates/zigbee-bridge/src/lamp/model.rs @@ -26,6 +26,10 @@ pub(crate) enum Model { /// 800 lm /// LCT007 HueGen2, + /// 9290038536H Hue white ambiance and color + /// 1600 lm + /// LCA012 + Hue1600Lm, #[allow(unused)] TradfriOther(String), #[allow(unused)] @@ -52,6 +56,7 @@ impl Model { | Model::TradfriE14Color | Model::HueGen1 | Model::HueGen2 + | Model::Hue1600Lm | Model::TradfriGU10 => true, Model::TradfriCandle | Model::TradfriE14White => false, // We assume no so that things at least don't break @@ -66,7 +71,7 @@ impl Model { Model::TradfriCandle | Model::TradfriGU10 => 2200..4000, Model::TradfriE27 | Model::TradfriE14Color => 1780..4000, Model::TradfriE14White => 2000..4000, - Model::HueGen1 | Model::HueGen2 => 2000..6500, + Model::HueGen1 | Model::HueGen2 | Model::Hue1600Lm => 2000..6500, Model::TradfriOther(_) => 2200..4000, Model::HueOther(_) => 2200..6500, Model::Other(_) => 2200..4000, @@ -88,7 +93,10 @@ impl Model { | Model::TradfriE14Color | Model::TradfriE14White | Model::TradfriOther(_) => false, - Model::HueGen1 | Model::HueGen2 | Model::HueOther(_) => true, + Model::HueGen1 + | Model::HueGen2 + | Model::Hue1600Lm + | Model::HueOther(_) => true, // I guess we default to sending payloads separately Model::Other(_) => false, } diff --git a/crates/zigbee-bridge/src/lib.rs b/crates/zigbee-bridge/src/lib.rs index b68dc33b..22188bdd 100644 --- a/crates/zigbee-bridge/src/lib.rs +++ b/crates/zigbee-bridge/src/lib.rs @@ -21,13 +21,13 @@ const LIGHT_MODELS: [(&str, Model); 16] = [ ("kitchen:hallway", Model::TradfriE27), ("kitchen:hood_left", Model::TradfriCandle), ("kitchen:hood_right", Model::TradfriCandle), - ("kitchen:ceiling", Model::TradfriE27), + ("kitchen:ceiling", Model::Hue1600Lm), ("large_bedroom:cabinet", Model::TradfriGU10), ("large_bedroom:ceiling", Model::TradfriE27), ("large_bedroom:desk", Model::TradfriE27), ("large_bedroom:wardrobe", Model::TradfriE27), ("large_bedroom:bed", Model::TradfriE14White), - ("small_bedroom:ceiling", Model::HueGen1), + ("small_bedroom:table", Model::Hue1600Lm), ("small_bedroom:bureau", Model::HueGen1), ("small_bedroom:piano", Model::TradfriE27), ("bathroom:ceiling", Model::HueGen1), From 88e06792595cd989fad016812004692e5743f95d Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 3 Jan 2026 16:17:27 +0100 Subject: [PATCH 686/687] Adjust temp and air filtration --- crates/brain/src/controller/rooms/small_bedroom.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/brain/src/controller/rooms/small_bedroom.rs b/crates/brain/src/controller/rooms/small_bedroom.rs index 8b7eda55..379d370f 100644 --- a/crates/brain/src/controller/rooms/small_bedroom.rs +++ b/crates/brain/src/controller/rooms/small_bedroom.rs @@ -253,19 +253,19 @@ pub(crate) fn goal_temp_now() -> f64 { ((10, 00), 19.5), ((11, 00), 21.0), ((12, 00), 22.0), - ((19, 00), 10.0), - ((21, 00), 19.0), + ((19, 00), 19.0), ]); goal_now(goals, 19.0) } fn air_filtration_now(pm2_5_measurement: &Option<(f32, Zoned)>) -> Option { + const LOW: u16 = 85; let pm2_5_expiration = 10.minutes(); let goals = - BTreeMap::from([((00, 00), 80), ((18, 00), 80), ((22, 30), 80)]); + BTreeMap::from([((00, 00), LOW), ((18, 00), 100), ((21, 30), LOW)]); - let default = goal_now(goals, 80); + let default = goal_now(goals, LOW); let Some((pm2_5, measured_time)) = pm2_5_measurement else { return Some(default); From 959bf04944c7daa950bdfa8c16b7124335747da3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Feb 2026 19:23:31 +0000 Subject: [PATCH 687/687] Bump bytes from 1.10.1 to 1.11.1 Bumps [bytes](https://github.com/tokio-rs/bytes) from 1.10.1 to 1.11.1. - [Release notes](https://github.com/tokio-rs/bytes/releases) - [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md) - [Commits](https://github.com/tokio-rs/bytes/compare/v1.10.1...v1.11.1) --- updated-dependencies: - dependency-name: bytes dependency-version: 1.11.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9b9bc349..193761f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -292,9 +292,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "byteseries"